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