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/STLExtras.h" 15e8d8bef9SDimitry Andric #include "llvm/ADT/SmallVector.h" 16e8d8bef9SDimitry Andric 17e8d8bef9SDimitry Andric #include <string> 18e8d8bef9SDimitry Andric 19e8d8bef9SDimitry Andric namespace llvm { 20e8d8bef9SDimitry Andric 21e8d8bef9SDimitry Andric class ConstraintSystem { 22e8d8bef9SDimitry Andric /// Current linear constraints in the system. 23e8d8bef9SDimitry Andric /// An entry of the form c0, c1, ... cn represents the following constraint: 24e8d8bef9SDimitry Andric /// c0 >= v0 * c1 + .... + v{n-1} * cn 25e8d8bef9SDimitry Andric SmallVector<SmallVector<int64_t, 8>, 4> Constraints; 26e8d8bef9SDimitry Andric 27e8d8bef9SDimitry Andric /// Current greatest common divisor for all coefficients in the system. 28e8d8bef9SDimitry Andric uint32_t GCD = 1; 29e8d8bef9SDimitry Andric 30e8d8bef9SDimitry Andric // Eliminate constraints from the system using Fourier–Motzkin elimination. 31e8d8bef9SDimitry Andric bool eliminateUsingFM(); 32e8d8bef9SDimitry Andric 33e8d8bef9SDimitry Andric /// Print the constraints in the system, using x0...xn as variable names. 34e8d8bef9SDimitry Andric void dump() const; 35e8d8bef9SDimitry Andric 36e8d8bef9SDimitry Andric /// Returns true if there may be a solution for the constraints in the system. 37e8d8bef9SDimitry Andric bool mayHaveSolutionImpl(); 38e8d8bef9SDimitry Andric 39e8d8bef9SDimitry Andric public: 40e8d8bef9SDimitry Andric bool addVariableRow(const SmallVector<int64_t, 8> &R) { 41e8d8bef9SDimitry Andric assert(Constraints.empty() || R.size() == Constraints.back().size()); 42e8d8bef9SDimitry Andric // If all variable coefficients are 0, the constraint does not provide any 43e8d8bef9SDimitry Andric // usable information. 44e8d8bef9SDimitry Andric if (all_of(makeArrayRef(R).drop_front(1), [](int64_t C) { return C == 0; })) 45e8d8bef9SDimitry Andric return false; 46e8d8bef9SDimitry Andric 47e8d8bef9SDimitry Andric for (const auto &C : R) { 48e8d8bef9SDimitry Andric auto A = std::abs(C); 49e8d8bef9SDimitry Andric GCD = APIntOps::GreatestCommonDivisor({32, (uint32_t)A}, {32, GCD}) 50e8d8bef9SDimitry Andric .getZExtValue(); 51e8d8bef9SDimitry Andric } 52e8d8bef9SDimitry Andric Constraints.push_back(R); 53e8d8bef9SDimitry Andric return true; 54e8d8bef9SDimitry Andric } 55e8d8bef9SDimitry Andric 56e8d8bef9SDimitry Andric bool addVariableRowFill(const SmallVector<int64_t, 8> &R) { 57e8d8bef9SDimitry Andric for (auto &CR : Constraints) { 58e8d8bef9SDimitry Andric while (CR.size() != R.size()) 59e8d8bef9SDimitry Andric CR.push_back(0); 60e8d8bef9SDimitry Andric } 61e8d8bef9SDimitry Andric return addVariableRow(R); 62e8d8bef9SDimitry Andric } 63e8d8bef9SDimitry Andric 64e8d8bef9SDimitry Andric /// Returns true if there may be a solution for the constraints in the system. 65e8d8bef9SDimitry Andric bool mayHaveSolution(); 66e8d8bef9SDimitry Andric 67e8d8bef9SDimitry Andric static SmallVector<int64_t, 8> negate(SmallVector<int64_t, 8> R) { 68e8d8bef9SDimitry Andric // The negated constraint R is obtained by multiplying by -1 and adding 1 to 69e8d8bef9SDimitry Andric // the constant. 70e8d8bef9SDimitry Andric R[0] += 1; 71e8d8bef9SDimitry Andric for (auto &C : R) 72e8d8bef9SDimitry Andric C *= -1; 73e8d8bef9SDimitry Andric return R; 74e8d8bef9SDimitry Andric } 75e8d8bef9SDimitry Andric 76*04eeddc0SDimitry Andric bool isConditionImplied(SmallVector<int64_t, 8> R) const; 77e8d8bef9SDimitry Andric 78e8d8bef9SDimitry Andric void popLastConstraint() { Constraints.pop_back(); } 79e8d8bef9SDimitry Andric 80e8d8bef9SDimitry Andric /// Returns the number of rows in the constraint system. 81e8d8bef9SDimitry Andric unsigned size() const { return Constraints.size(); } 82fe6060f1SDimitry Andric 83fe6060f1SDimitry Andric /// Print the constraints in the system, using \p Names as variable names. 84fe6060f1SDimitry Andric void dump(ArrayRef<std::string> Names) const; 85e8d8bef9SDimitry Andric }; 86e8d8bef9SDimitry Andric } // namespace llvm 87e8d8bef9SDimitry Andric 88e8d8bef9SDimitry Andric #endif // LLVM_ANALYSIS_CONSTRAINTSYSTEM_H 89