1 //===- SDBM.h - MLIR SDBM declaration ---------------------------*- C++ -*-===// 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 // A striped difference-bound matrix (SDBM) is a set in Z^N (or R^N) defined 10 // as {(x_1, ... x_n) | f(x_1, ... x_n) >= 0} where f is an SDBM expression. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef MLIR_DIALECT_SDBM_SDBM_H 15 #define MLIR_DIALECT_SDBM_SDBM_H 16 17 #include "mlir/Support/LLVM.h" 18 #include "llvm/ADT/DenseMap.h" 19 20 namespace mlir { 21 22 class MLIRContext; 23 class SDBMDialect; 24 class SDBMExpr; 25 class SDBMTermExpr; 26 27 /// A utility class for SDBM to represent an integer with potentially infinite 28 /// positive value. This uses the largest value of int64_t to represent infinity 29 /// and redefines the arithmetic operators so that the infinity "saturates": 30 /// inf + x = inf, 31 /// inf - x = inf. 32 /// If a sum of two finite values reaches the largest value of int64_t, the 33 /// behavior of IntInfty is undefined (in practice, it asserts), similarly to 34 /// regular signed integer overflow. 35 class IntInfty { 36 public: 37 constexpr static int64_t infty = std::numeric_limits<int64_t>::max(); 38 IntInfty(int64_t v)39 /*implicit*/ IntInfty(int64_t v) : value(v) {} 40 41 IntInfty &operator=(int64_t v) { 42 value = v; 43 return *this; 44 } 45 infinity()46 static IntInfty infinity() { return IntInfty(infty); } 47 getValue()48 int64_t getValue() const { return value; } int64_t()49 explicit operator int64_t() const { return value; } 50 isFinite()51 bool isFinite() { return value != infty; } 52 53 private: 54 int64_t value; 55 }; 56 57 inline IntInfty operator+(IntInfty lhs, IntInfty rhs) { 58 if (!lhs.isFinite() || !rhs.isFinite()) 59 return IntInfty::infty; 60 61 // Check for overflows, treating the sum of two values adding up to INT_MAX as 62 // overflow. Convert values to unsigned to get an extra bit and avoid the 63 // undefined behavior of signed integer overflows. 64 assert((lhs.getValue() <= 0 || rhs.getValue() <= 0 || 65 static_cast<uint64_t>(lhs.getValue()) + 66 static_cast<uint64_t>(rhs.getValue()) < 67 static_cast<uint64_t>(std::numeric_limits<int64_t>::max())) && 68 "IntInfty overflow"); 69 // Check for underflows by converting values to unsigned to avoid undefined 70 // behavior of signed integers perform the addition (bitwise result is same 71 // because numbers are required to be two's complement in C++) and check if 72 // the sign bit remains negative. 73 assert((lhs.getValue() >= 0 || rhs.getValue() >= 0 || 74 ((static_cast<uint64_t>(lhs.getValue()) + 75 static_cast<uint64_t>(rhs.getValue())) >> 76 63) == 1) && 77 "IntInfty underflow"); 78 79 return lhs.getValue() + rhs.getValue(); 80 } 81 82 inline bool operator<(IntInfty lhs, IntInfty rhs) { 83 return lhs.getValue() < rhs.getValue(); 84 } 85 86 inline bool operator<=(IntInfty lhs, IntInfty rhs) { 87 return lhs.getValue() <= rhs.getValue(); 88 } 89 90 inline bool operator==(IntInfty lhs, IntInfty rhs) { 91 return lhs.getValue() == rhs.getValue(); 92 } 93 94 inline bool operator!=(IntInfty lhs, IntInfty rhs) { return !(lhs == rhs); } 95 96 /// Striped difference-bound matrix is a representation of an integer set bound 97 /// by a system of SDBMExprs interpreted as inequalities "expr <= 0". 98 class SDBM { 99 public: 100 /// Obtain an SDBM from a list of SDBM expressions treated as inequalities and 101 /// equalities with zero. 102 static SDBM get(ArrayRef<SDBMExpr> inequalities, 103 ArrayRef<SDBMExpr> equalities); 104 105 void getSDBMExpressions(SDBMDialect *dialect, 106 SmallVectorImpl<SDBMExpr> &inequalities, 107 SmallVectorImpl<SDBMExpr> &equalities); 108 109 void print(raw_ostream &os); 110 void dump(); 111 operator()112 IntInfty operator()(int i, int j) { return at(i, j); } 113 114 private: 115 /// Get the given element of the difference bounds matrix. First index 116 /// corresponds to the negative term of the difference, second index 117 /// corresponds to the positive term of the difference. at(int i,int j)118 IntInfty &at(int i, int j) { return matrix[i * getNumVariables() + j]; } 119 120 /// Populate `inequalities` and `equalities` based on the values at(row,col) 121 /// and at(col,row) of the DBM. Depending on the values being finite and 122 /// being subsumed by stripe expressions, this may or may not add elements to 123 /// the lists of equalities and inequalities. 124 void convertDBMElement(unsigned row, unsigned col, SDBMTermExpr rowExpr, 125 SDBMTermExpr colExpr, 126 SmallVectorImpl<SDBMExpr> &inequalities, 127 SmallVectorImpl<SDBMExpr> &equalities); 128 129 /// Populate `inequalities` based on the value at(pos,pos) of the DBM. Only 130 /// adds new inequalities if the inequality is not trivially true. 131 void convertDBMDiagonalElement(unsigned pos, SDBMTermExpr expr, 132 SmallVectorImpl<SDBMExpr> &inequalities); 133 134 /// Get the total number of elements in the matrix. getNumVariables()135 unsigned getNumVariables() const { 136 return 1 + numDims + numSymbols + numTemporaries; 137 } 138 139 /// Get the position in the matrix that corresponds to the given dimension. getDimPosition(unsigned position)140 unsigned getDimPosition(unsigned position) const { return 1 + position; } 141 142 /// Get the position in the matrix that corresponds to the given symbol. getSymbolPosition(unsigned position)143 unsigned getSymbolPosition(unsigned position) const { 144 return 1 + numDims + position; 145 } 146 147 /// Get the position in the matrix that corresponds to the given temporary. getTemporaryPosition(unsigned position)148 unsigned getTemporaryPosition(unsigned position) const { 149 return 1 + numDims + numSymbols + position; 150 } 151 152 /// Number of dimensions in the system, 153 unsigned numDims; 154 /// Number of symbols in the system. 155 unsigned numSymbols; 156 /// Number of temporary variables in the system. 157 unsigned numTemporaries; 158 159 /// Difference bounds matrix, stored as a linearized row-major vector. 160 /// Each value in this matrix corresponds to an inequality 161 /// 162 /// v@col - v@row <= at(row, col) 163 /// 164 /// where v@col and v@row are the variables that correspond to the linearized 165 /// position in the matrix. The positions correspond to 166 /// 167 /// - constant 0 (producing constraints v@col <= X and -v@row <= Y); 168 /// - SDBM expression dimensions (d0, d1, ...); 169 /// - SDBM expression symbols (s0, s1, ...); 170 /// - temporary variables (t0, t1, ...). 171 /// 172 /// Temporary variables are introduced to represent expressions that are not 173 /// trivially a difference between two variables. For example, if one side of 174 /// a difference expression is itself a stripe expression, it will be replaced 175 /// with a temporary variable assigned equal to this expression. 176 /// 177 /// Infinite entries in the matrix correspond correspond to an absence of a 178 /// constraint: 179 /// 180 /// v@col - v@row <= infinity 181 /// 182 /// is trivially true. Negated values at symmetric positions in the matrix 183 /// allow one to couple two inequalities into a single equality. 184 std::vector<IntInfty> matrix; 185 186 /// The mapping between the indices of variables in the DBM and the stripe 187 /// expressions they are equal to. These expressions are stored as they 188 /// appeared when constructing an SDBM from a SDBMExprs, in particular no 189 /// temporaries can appear in these expressions. This removes the need to 190 /// iteratively substitute definitions of the temporaries in the reverse 191 /// conversion. 192 DenseMap<unsigned, SDBMExpr> stripeToPoint; 193 }; 194 195 } // namespace mlir 196 197 #endif // MLIR_DIALECT_SDBM_SDBM_H 198