Coverage Report

Created: 2024-01-17 10:31

/src/llvm-project/llvm/include/llvm/Analysis/ConstraintSystem.h
Line
Count
Source (jump to first uncovered line)
1
//===- ConstraintSystem.h -  A system of linear constraints. --------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#ifndef LLVM_ANALYSIS_CONSTRAINTSYSTEM_H
10
#define LLVM_ANALYSIS_CONSTRAINTSYSTEM_H
11
12
#include "llvm/ADT/APInt.h"
13
#include "llvm/ADT/ArrayRef.h"
14
#include "llvm/ADT/DenseMap.h"
15
#include "llvm/ADT/SmallVector.h"
16
#include "llvm/Support/MathExtras.h"
17
18
#include <string>
19
20
namespace llvm {
21
22
class Value;
23
class ConstraintSystem {
24
  struct Entry {
25
    int64_t Coefficient;
26
    uint16_t Id;
27
28
    Entry(int64_t Coefficient, uint16_t Id)
29
0
        : Coefficient(Coefficient), Id(Id) {}
30
  };
31
32
0
  static int64_t getConstPart(const Entry &E) {
33
0
    if (E.Id == 0)
34
0
      return E.Coefficient;
35
0
    return 0;
36
0
  }
37
38
0
  static int64_t getLastCoefficient(ArrayRef<Entry> Row, uint16_t Id) {
39
0
    if (Row.empty())
40
0
      return 0;
41
0
    if (Row.back().Id == Id)
42
0
      return Row.back().Coefficient;
43
0
    return 0;
44
0
  }
45
46
  size_t NumVariables = 0;
47
48
  /// Current linear constraints in the system.
49
  /// An entry of the form c0, c1, ... cn represents the following constraint:
50
  ///   c0 >= v0 * c1 + .... + v{n-1} * cn
51
  SmallVector<SmallVector<Entry, 8>, 4> Constraints;
52
53
  /// A map of variables (IR values) to their corresponding index in the
54
  /// constraint system.
55
  DenseMap<Value *, unsigned> Value2Index;
56
57
  // Eliminate constraints from the system using Fourier–Motzkin elimination.
58
  bool eliminateUsingFM();
59
60
  /// Returns true if there may be a solution for the constraints in the system.
61
  bool mayHaveSolutionImpl();
62
63
  /// Get list of variable names from the Value2Index map.
64
  SmallVector<std::string> getVarNamesList() const;
65
66
public:
67
0
  ConstraintSystem() {}
68
0
  ConstraintSystem(ArrayRef<Value *> FunctionArgs) {
69
0
    NumVariables += FunctionArgs.size();
70
0
    for (auto *Arg : FunctionArgs) {
71
0
      Value2Index.insert({Arg, Value2Index.size() + 1});
72
0
    }
73
0
  }
74
  ConstraintSystem(const DenseMap<Value *, unsigned> &Value2Index)
75
0
      : NumVariables(Value2Index.size()), Value2Index(Value2Index) {}
76
77
0
  bool addVariableRow(ArrayRef<int64_t> R) {
78
0
    assert(Constraints.empty() || R.size() == NumVariables);
79
    // If all variable coefficients are 0, the constraint does not provide any
80
    // usable information.
81
0
    if (all_of(ArrayRef(R).drop_front(1), [](int64_t C) { return C == 0; }))
82
0
      return false;
83
84
0
    SmallVector<Entry, 4> NewRow;
85
0
    for (const auto &[Idx, C] : enumerate(R)) {
86
0
      if (C == 0)
87
0
        continue;
88
0
      NewRow.emplace_back(C, Idx);
89
0
    }
90
0
    if (Constraints.empty())
91
0
      NumVariables = R.size();
92
0
    Constraints.push_back(std::move(NewRow));
93
0
    return true;
94
0
  }
95
96
0
  DenseMap<Value *, unsigned> &getValue2Index() { return Value2Index; }
97
0
  const DenseMap<Value *, unsigned> &getValue2Index() const {
98
0
    return Value2Index;
99
0
  }
100
101
0
  bool addVariableRowFill(ArrayRef<int64_t> R) {
102
    // If all variable coefficients are 0, the constraint does not provide any
103
    // usable information.
104
0
    if (all_of(ArrayRef(R).drop_front(1), [](int64_t C) { return C == 0; }))
105
0
      return false;
106
107
0
    NumVariables = std::max(R.size(), NumVariables);
108
0
    return addVariableRow(R);
109
0
  }
110
111
  /// Returns true if there may be a solution for the constraints in the system.
112
  bool mayHaveSolution();
113
114
0
  static SmallVector<int64_t, 8> negate(SmallVector<int64_t, 8> R) {
115
    // The negated constraint R is obtained by multiplying by -1 and adding 1 to
116
    // the constant.
117
0
    R[0] += 1;
118
0
    return negateOrEqual(R);
119
0
  }
120
121
  /// Multiplies each coefficient in the given vector by -1. Does not modify the
122
  /// original vector.
123
  ///
124
  /// \param R The vector of coefficients to be negated.
125
0
  static SmallVector<int64_t, 8> negateOrEqual(SmallVector<int64_t, 8> R) {
126
    // The negated constraint R is obtained by multiplying by -1.
127
0
    for (auto &C : R)
128
0
      if (MulOverflow(C, int64_t(-1), C))
129
0
        return {};
130
0
    return R;
131
0
  }
132
133
  /// Converts the given vector to form a strict less than inequality. Does not
134
  /// modify the original vector.
135
  ///
136
  /// \param R The vector of coefficients to be converted.
137
0
  static SmallVector<int64_t, 8> toStrictLessThan(SmallVector<int64_t, 8> R) {
138
    // The strict less than is obtained by subtracting 1 from the constant.
139
0
    if (SubOverflow(R[0], int64_t(1), R[0])) {
140
0
      return {};
141
0
    }
142
0
    return R;
143
0
  }
144
145
  bool isConditionImplied(SmallVector<int64_t, 8> R) const;
146
147
0
  SmallVector<int64_t> getLastConstraint() const {
148
0
    assert(!Constraints.empty() && "Constraint system is empty");
149
0
    SmallVector<int64_t> Result(NumVariables, 0);
150
0
    for (auto &Entry : Constraints.back())
151
0
      Result[Entry.Id] = Entry.Coefficient;
152
0
    return Result;
153
0
  }
154
155
0
  void popLastConstraint() { Constraints.pop_back(); }
156
0
  void popLastNVariables(unsigned N) {
157
0
    assert(NumVariables > N);
158
0
    NumVariables -= N;
159
0
  }
160
161
  /// Returns the number of rows in the constraint system.
162
0
  unsigned size() const { return Constraints.size(); }
163
164
  /// Print the constraints in the system.
165
  void dump() const;
166
};
167
} // namespace llvm
168
169
#endif // LLVM_ANALYSIS_CONSTRAINTSYSTEM_H