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