xref: /freebsd-src/contrib/llvm-project/llvm/include/llvm/Analysis/ConstraintSystem.h (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
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