1cd4edf94SFlorian Hahn //===- ConstraintSystem.h - A system of linear constraints. --------------===// 2cd4edf94SFlorian Hahn // 3cd4edf94SFlorian Hahn // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4cd4edf94SFlorian Hahn // See https://llvm.org/LICENSE.txt for license information. 5cd4edf94SFlorian Hahn // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6cd4edf94SFlorian Hahn // 7cd4edf94SFlorian Hahn //===----------------------------------------------------------------------===// 8cd4edf94SFlorian Hahn 9cd4edf94SFlorian Hahn #ifndef LLVM_ANALYSIS_CONSTRAINTSYSTEM_H 10cd4edf94SFlorian Hahn #define LLVM_ANALYSIS_CONSTRAINTSYSTEM_H 11cd4edf94SFlorian Hahn 12cd4edf94SFlorian Hahn #include "llvm/ADT/ArrayRef.h" 13a9d6a86bSZain Jaffal #include "llvm/ADT/DenseMap.h" 14cd4edf94SFlorian Hahn #include "llvm/ADT/SmallVector.h" 150a0181dcSFlorian Hahn #include "llvm/Support/MathExtras.h" 16cd4edf94SFlorian Hahn 17cd4edf94SFlorian Hahn #include <string> 18cd4edf94SFlorian Hahn 19cd4edf94SFlorian Hahn namespace llvm { 20665ee0cdSZain Jaffal 21a9d6a86bSZain Jaffal class Value; 22cd4edf94SFlorian Hahn class ConstraintSystem { 23b32b7068SFlorian Hahn struct Entry { 24b32b7068SFlorian Hahn int64_t Coefficient; 25b32b7068SFlorian Hahn uint16_t Id; 26b32b7068SFlorian Hahn 27b32b7068SFlorian Hahn Entry(int64_t Coefficient, uint16_t Id) 28b32b7068SFlorian Hahn : Coefficient(Coefficient), Id(Id) {} 29b32b7068SFlorian Hahn }; 30b32b7068SFlorian Hahn 31b32b7068SFlorian Hahn static int64_t getConstPart(const Entry &E) { 32b32b7068SFlorian Hahn if (E.Id == 0) 33b32b7068SFlorian Hahn return E.Coefficient; 34b32b7068SFlorian Hahn return 0; 35b32b7068SFlorian Hahn } 36b32b7068SFlorian Hahn 37b32b7068SFlorian Hahn static int64_t getLastCoefficient(ArrayRef<Entry> Row, uint16_t Id) { 38b32b7068SFlorian Hahn if (Row.empty()) 39b32b7068SFlorian Hahn return 0; 40b32b7068SFlorian Hahn if (Row.back().Id == Id) 41b32b7068SFlorian Hahn return Row.back().Coefficient; 42b32b7068SFlorian Hahn return 0; 43b32b7068SFlorian Hahn } 44b32b7068SFlorian Hahn 45b32b7068SFlorian Hahn size_t NumVariables = 0; 46b32b7068SFlorian Hahn 47cd4edf94SFlorian Hahn /// Current linear constraints in the system. 48cd4edf94SFlorian Hahn /// An entry of the form c0, c1, ... cn represents the following constraint: 49cd4edf94SFlorian Hahn /// c0 >= v0 * c1 + .... + v{n-1} * cn 50b32b7068SFlorian Hahn SmallVector<SmallVector<Entry, 8>, 4> Constraints; 51cd4edf94SFlorian Hahn 52a9d6a86bSZain Jaffal /// A map of variables (IR values) to their corresponding index in the 53a9d6a86bSZain Jaffal /// constraint system. 54a9d6a86bSZain Jaffal DenseMap<Value *, unsigned> Value2Index; 55a9d6a86bSZain Jaffal 56cd4edf94SFlorian Hahn // Eliminate constraints from the system using Fourier–Motzkin elimination. 57cd4edf94SFlorian Hahn bool eliminateUsingFM(); 58cd4edf94SFlorian Hahn 59cd4edf94SFlorian Hahn /// Returns true if there may be a solution for the constraints in the system. 60cd4edf94SFlorian Hahn bool mayHaveSolutionImpl(); 61cd4edf94SFlorian Hahn 6207f93d8cSZain Jaffal /// Get list of variable names from the Value2Index map. 6307f93d8cSZain Jaffal SmallVector<std::string> getVarNamesList() const; 6407f93d8cSZain Jaffal 65cd4edf94SFlorian Hahn public: 6607f93d8cSZain Jaffal ConstraintSystem() {} 671d23d60cSZain Jaffal ConstraintSystem(ArrayRef<Value *> FunctionArgs) { 681d23d60cSZain Jaffal NumVariables += FunctionArgs.size(); 691d23d60cSZain Jaffal for (auto *Arg : FunctionArgs) { 701d23d60cSZain Jaffal Value2Index.insert({Arg, Value2Index.size() + 1}); 711d23d60cSZain Jaffal } 721d23d60cSZain Jaffal } 7307f93d8cSZain Jaffal ConstraintSystem(const DenseMap<Value *, unsigned> &Value2Index) 741d23d60cSZain Jaffal : NumVariables(Value2Index.size()), Value2Index(Value2Index) {} 7507f93d8cSZain Jaffal 76b4670438SFlorian Hahn bool addVariableRow(ArrayRef<int64_t> R) { 77b32b7068SFlorian Hahn assert(Constraints.empty() || R.size() == NumVariables); 784ceecc82SFlorian Hahn // If all variable coefficients are 0, the constraint does not provide any 794ceecc82SFlorian Hahn // usable information. 8038818b60Sserge-sans-paille if (all_of(ArrayRef(R).drop_front(1), [](int64_t C) { return C == 0; })) 814ceecc82SFlorian Hahn return false; 824ceecc82SFlorian Hahn 83b32b7068SFlorian Hahn SmallVector<Entry, 4> NewRow; 84b32b7068SFlorian Hahn for (const auto &[Idx, C] : enumerate(R)) { 85b32b7068SFlorian Hahn if (C == 0) 86b32b7068SFlorian Hahn continue; 87b32b7068SFlorian Hahn NewRow.emplace_back(C, Idx); 88cd4edf94SFlorian Hahn } 89b32b7068SFlorian Hahn if (Constraints.empty()) 90b32b7068SFlorian Hahn NumVariables = R.size(); 91b32b7068SFlorian Hahn Constraints.push_back(std::move(NewRow)); 924ceecc82SFlorian Hahn return true; 93cd4edf94SFlorian Hahn } 94cd4edf94SFlorian Hahn 95a9d6a86bSZain Jaffal DenseMap<Value *, unsigned> &getValue2Index() { return Value2Index; } 96a9d6a86bSZain Jaffal const DenseMap<Value *, unsigned> &getValue2Index() const { 97a9d6a86bSZain Jaffal return Value2Index; 98a9d6a86bSZain Jaffal } 99a9d6a86bSZain Jaffal 100b4670438SFlorian Hahn bool addVariableRowFill(ArrayRef<int64_t> R) { 101542c3351SFlorian Hahn // If all variable coefficients are 0, the constraint does not provide any 102542c3351SFlorian Hahn // usable information. 10338818b60Sserge-sans-paille if (all_of(ArrayRef(R).drop_front(1), [](int64_t C) { return C == 0; })) 104542c3351SFlorian Hahn return false; 105542c3351SFlorian Hahn 106b32b7068SFlorian Hahn NumVariables = std::max(R.size(), NumVariables); 1074ceecc82SFlorian Hahn return addVariableRow(R); 1083d42d549SFlorian Hahn } 1093d42d549SFlorian Hahn 110cd4edf94SFlorian Hahn /// Returns true if there may be a solution for the constraints in the system. 111cd4edf94SFlorian Hahn bool mayHaveSolution(); 112db22e70dSFlorian Hahn 113db22e70dSFlorian Hahn static SmallVector<int64_t, 8> negate(SmallVector<int64_t, 8> R) { 114db22e70dSFlorian Hahn // The negated constraint R is obtained by multiplying by -1 and adding 1 to 115db22e70dSFlorian Hahn // the constant. 116*45ff2874SFlorian Hahn if (AddOverflow(R[0], int64_t(1), R[0])) 117*45ff2874SFlorian Hahn return {}; 118*45ff2874SFlorian Hahn 1191774c148SAntonio Frighetto return negateOrEqual(R); 1201774c148SAntonio Frighetto } 1211774c148SAntonio Frighetto 1221774c148SAntonio Frighetto /// Multiplies each coefficient in the given vector by -1. Does not modify the 1231774c148SAntonio Frighetto /// original vector. 1241774c148SAntonio Frighetto /// 1251774c148SAntonio Frighetto /// \param R The vector of coefficients to be negated. 1261774c148SAntonio Frighetto static SmallVector<int64_t, 8> negateOrEqual(SmallVector<int64_t, 8> R) { 1271774c148SAntonio Frighetto // The negated constraint R is obtained by multiplying by -1. 128db22e70dSFlorian Hahn for (auto &C : R) 1290a0181dcSFlorian Hahn if (MulOverflow(C, int64_t(-1), C)) 1300a0181dcSFlorian Hahn return {}; 131db22e70dSFlorian Hahn return R; 132db22e70dSFlorian Hahn } 133db22e70dSFlorian Hahn 1341774c148SAntonio Frighetto /// Converts the given vector to form a strict less than inequality. Does not 1351774c148SAntonio Frighetto /// modify the original vector. 1361774c148SAntonio Frighetto /// 1371774c148SAntonio Frighetto /// \param R The vector of coefficients to be converted. 1381774c148SAntonio Frighetto static SmallVector<int64_t, 8> toStrictLessThan(SmallVector<int64_t, 8> R) { 1391774c148SAntonio Frighetto // The strict less than is obtained by subtracting 1 from the constant. 1401774c148SAntonio Frighetto if (SubOverflow(R[0], int64_t(1), R[0])) { 1411774c148SAntonio Frighetto return {}; 1421774c148SAntonio Frighetto } 1431774c148SAntonio Frighetto return R; 1441774c148SAntonio Frighetto } 1451774c148SAntonio Frighetto 1461ca02bddSFlorian Hahn bool isConditionImplied(SmallVector<int64_t, 8> R) const; 1473d42d549SFlorian Hahn 148b32b7068SFlorian Hahn SmallVector<int64_t> getLastConstraint() const { 149b32b7068SFlorian Hahn assert(!Constraints.empty() && "Constraint system is empty"); 150b32b7068SFlorian Hahn SmallVector<int64_t> Result(NumVariables, 0); 151b32b7068SFlorian Hahn for (auto &Entry : Constraints.back()) 152b32b7068SFlorian Hahn Result[Entry.Id] = Entry.Coefficient; 153b32b7068SFlorian Hahn return Result; 154b32b7068SFlorian Hahn } 155b32b7068SFlorian Hahn 1563d42d549SFlorian Hahn void popLastConstraint() { Constraints.pop_back(); } 157542c3351SFlorian Hahn void popLastNVariables(unsigned N) { 158b32b7068SFlorian Hahn assert(NumVariables > N); 159b32b7068SFlorian Hahn NumVariables -= N; 160542c3351SFlorian Hahn } 161f19876c5SFlorian Hahn 162f19876c5SFlorian Hahn /// Returns the number of rows in the constraint system. 163f19876c5SFlorian Hahn unsigned size() const { return Constraints.size(); } 1643e09bc25SFlorian Hahn 16507f93d8cSZain Jaffal /// Print the constraints in the system. 16607f93d8cSZain Jaffal void dump() const; 167cd4edf94SFlorian Hahn }; 168cd4edf94SFlorian Hahn } // namespace llvm 169cd4edf94SFlorian Hahn 170cd4edf94SFlorian Hahn #endif // LLVM_ANALYSIS_CONSTRAINTSYSTEM_H 171