xref: /llvm-project/llvm/include/llvm/Analysis/ConstraintSystem.h (revision 45ff28746f5f6350a95d8d9a3e3b3a62b932bce9)
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