1e8d8bef9SDimitry Andric //===- ConstraintSystem.h - A system of linear constraints. --------------===// 2e8d8bef9SDimitry Andric // 3e8d8bef9SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e8d8bef9SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5e8d8bef9SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e8d8bef9SDimitry Andric // 7e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 8e8d8bef9SDimitry Andric 9e8d8bef9SDimitry Andric #ifndef LLVM_ANALYSIS_CONSTRAINTSYSTEM_H 10e8d8bef9SDimitry Andric #define LLVM_ANALYSIS_CONSTRAINTSYSTEM_H 11e8d8bef9SDimitry Andric 12e8d8bef9SDimitry Andric #include "llvm/ADT/APInt.h" 13e8d8bef9SDimitry Andric #include "llvm/ADT/ArrayRef.h" 14e8d8bef9SDimitry Andric #include "llvm/ADT/SmallVector.h" 15e8d8bef9SDimitry Andric 16e8d8bef9SDimitry Andric #include <string> 17e8d8bef9SDimitry Andric 18e8d8bef9SDimitry Andric namespace llvm { 19e8d8bef9SDimitry Andric 20e8d8bef9SDimitry Andric class ConstraintSystem { 21e8d8bef9SDimitry Andric /// Current linear constraints in the system. 22e8d8bef9SDimitry Andric /// An entry of the form c0, c1, ... cn represents the following constraint: 23e8d8bef9SDimitry Andric /// c0 >= v0 * c1 + .... + v{n-1} * cn 24e8d8bef9SDimitry Andric SmallVector<SmallVector<int64_t, 8>, 4> Constraints; 25e8d8bef9SDimitry Andric 26e8d8bef9SDimitry Andric /// Current greatest common divisor for all coefficients in the system. 27e8d8bef9SDimitry Andric uint32_t GCD = 1; 28e8d8bef9SDimitry Andric 29e8d8bef9SDimitry Andric // Eliminate constraints from the system using Fourier–Motzkin elimination. 30e8d8bef9SDimitry Andric bool eliminateUsingFM(); 31e8d8bef9SDimitry Andric 32e8d8bef9SDimitry Andric /// Print the constraints in the system, using x0...xn as variable names. 33e8d8bef9SDimitry Andric void dump() const; 34e8d8bef9SDimitry Andric 35e8d8bef9SDimitry Andric /// Returns true if there may be a solution for the constraints in the system. 36e8d8bef9SDimitry Andric bool mayHaveSolutionImpl(); 37e8d8bef9SDimitry Andric 38e8d8bef9SDimitry Andric public: 39*81ad6265SDimitry Andric bool addVariableRow(ArrayRef<int64_t> R) { 40e8d8bef9SDimitry Andric assert(Constraints.empty() || R.size() == Constraints.back().size()); 41e8d8bef9SDimitry Andric // If all variable coefficients are 0, the constraint does not provide any 42e8d8bef9SDimitry Andric // usable information. 43e8d8bef9SDimitry Andric if (all_of(makeArrayRef(R).drop_front(1), [](int64_t C) { return C == 0; })) 44e8d8bef9SDimitry Andric return false; 45e8d8bef9SDimitry Andric 46e8d8bef9SDimitry Andric for (const auto &C : R) { 47e8d8bef9SDimitry Andric auto A = std::abs(C); 48e8d8bef9SDimitry Andric GCD = APIntOps::GreatestCommonDivisor({32, (uint32_t)A}, {32, GCD}) 49e8d8bef9SDimitry Andric .getZExtValue(); 50e8d8bef9SDimitry Andric } 51*81ad6265SDimitry Andric Constraints.emplace_back(R.begin(), R.end()); 52e8d8bef9SDimitry Andric return true; 53e8d8bef9SDimitry Andric } 54e8d8bef9SDimitry Andric 55*81ad6265SDimitry Andric bool addVariableRowFill(ArrayRef<int64_t> R) { 56*81ad6265SDimitry Andric // If all variable coefficients are 0, the constraint does not provide any 57*81ad6265SDimitry Andric // usable information. 58*81ad6265SDimitry Andric if (all_of(makeArrayRef(R).drop_front(1), [](int64_t C) { return C == 0; })) 59*81ad6265SDimitry Andric return false; 60*81ad6265SDimitry Andric 61e8d8bef9SDimitry Andric for (auto &CR : Constraints) { 62e8d8bef9SDimitry Andric while (CR.size() != R.size()) 63e8d8bef9SDimitry Andric CR.push_back(0); 64e8d8bef9SDimitry Andric } 65e8d8bef9SDimitry Andric return addVariableRow(R); 66e8d8bef9SDimitry Andric } 67e8d8bef9SDimitry Andric 68e8d8bef9SDimitry Andric /// Returns true if there may be a solution for the constraints in the system. 69e8d8bef9SDimitry Andric bool mayHaveSolution(); 70e8d8bef9SDimitry Andric 71e8d8bef9SDimitry Andric static SmallVector<int64_t, 8> negate(SmallVector<int64_t, 8> R) { 72e8d8bef9SDimitry Andric // The negated constraint R is obtained by multiplying by -1 and adding 1 to 73e8d8bef9SDimitry Andric // the constant. 74e8d8bef9SDimitry Andric R[0] += 1; 75e8d8bef9SDimitry Andric for (auto &C : R) 76e8d8bef9SDimitry Andric C *= -1; 77e8d8bef9SDimitry Andric return R; 78e8d8bef9SDimitry Andric } 79e8d8bef9SDimitry Andric 8004eeddc0SDimitry Andric bool isConditionImplied(SmallVector<int64_t, 8> R) const; 81e8d8bef9SDimitry Andric 82*81ad6265SDimitry Andric ArrayRef<int64_t> getLastConstraint() { return Constraints[0]; } 83e8d8bef9SDimitry Andric void popLastConstraint() { Constraints.pop_back(); } 84*81ad6265SDimitry Andric void popLastNVariables(unsigned N) { 85*81ad6265SDimitry Andric for (auto &C : Constraints) { 86*81ad6265SDimitry Andric for (unsigned i = 0; i < N; i++) 87*81ad6265SDimitry Andric C.pop_back(); 88*81ad6265SDimitry Andric } 89*81ad6265SDimitry Andric } 90e8d8bef9SDimitry Andric 91e8d8bef9SDimitry Andric /// Returns the number of rows in the constraint system. 92e8d8bef9SDimitry Andric unsigned size() const { return Constraints.size(); } 93fe6060f1SDimitry Andric 94fe6060f1SDimitry Andric /// Print the constraints in the system, using \p Names as variable names. 95fe6060f1SDimitry Andric void dump(ArrayRef<std::string> Names) const; 96e8d8bef9SDimitry Andric }; 97e8d8bef9SDimitry Andric } // namespace llvm 98e8d8bef9SDimitry Andric 99e8d8bef9SDimitry Andric #endif // LLVM_ANALYSIS_CONSTRAINTSYSTEM_H 100