diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp --- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp +++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp @@ -189,17 +189,37 @@ SmallVectorImpl &DFSInStack); }; +struct BoundInfo { + int64_t LowerBound = MinSignedConstraintValue; + int64_t UpperBound = MaxConstraintValue; + + BoundInfo(int64_t LowerBound = MinSignedConstraintValue, + int64_t UpperBound = MaxConstraintValue) + : LowerBound(LowerBound), UpperBound(UpperBound) {} + + bool isLowerBoundSet() const { + return LowerBound != MinSignedConstraintValue; + }; + bool isUpperBoundSet() const { return UpperBound != MaxConstraintValue; }; +}; /// Represents a (Coefficient * Variable) entry after IR decomposition. struct DecompEntry { int64_t Coefficient; Value *Variable; /// True if the variable is known positive in the current constraint. - bool IsKnownNonNegative; + BoundInfo Bounds; DecompEntry(int64_t Coefficient, Value *Variable, - bool IsKnownNonNegative = false) - : Coefficient(Coefficient), Variable(Variable), - IsKnownNonNegative(IsKnownNonNegative) {} + bool IsKnownNonNegative = false, + int64_t UpperBound = MaxConstraintValue) + : Coefficient(Coefficient), Variable(Variable) { + if (IsKnownNonNegative) + Bounds.LowerBound = 0; + Bounds.UpperBound = UpperBound; + } + // Set UpperBound and LowerBound + DecompEntry(int64_t Coefficient, Value *Variable, BoundInfo Bounds) + : Coefficient(Coefficient), Variable(Variable), Bounds(Bounds) {} }; /// Represents an Offset + Coefficient1 * Variable1 + ... decomposition. @@ -208,8 +228,9 @@ SmallVector Vars; Decomposition(int64_t Offset) : Offset(Offset) {} - Decomposition(Value *V, bool IsKnownNonNegative = false) { - Vars.emplace_back(1, V, IsKnownNonNegative); + Decomposition(Value *V, bool IsKnownNonNegative = false, + int64_t UpperBound = MaxConstraintValue) { + Vars.emplace_back(1, V, IsKnownNonNegative, UpperBound); } Decomposition(int64_t Offset, ArrayRef Vars) : Offset(Offset), Vars(Vars) {} @@ -475,21 +496,25 @@ IsSigned); // Collect variables that are known to be positive in all uses in the // constraint. - DenseMap KnownNonNegativeVariables; + DenseMap BoundInfoVariables; Res.IsEq = IsEq; auto &R = Res.Coefficients; for (const auto &KV : VariablesA) { R[GetOrAddIndex(KV.Variable)] += KV.Coefficient; - auto I = - KnownNonNegativeVariables.insert({KV.Variable, KV.IsKnownNonNegative}); - I.first->second &= KV.IsKnownNonNegative; + auto I = BoundInfoVariables.insert( + {KV.Variable, {KV.Bounds.LowerBound, KV.Bounds.UpperBound}}); + I.first->second = { + std::max(I.first->second.LowerBound, KV.Bounds.LowerBound), + std::min(I.first->second.UpperBound, KV.Bounds.UpperBound)}; } for (const auto &KV : VariablesB) { R[GetOrAddIndex(KV.Variable)] -= KV.Coefficient; - auto I = - KnownNonNegativeVariables.insert({KV.Variable, KV.IsKnownNonNegative}); - I.first->second &= KV.IsKnownNonNegative; + auto I = BoundInfoVariables.insert( + {KV.Variable, {KV.Bounds.LowerBound, KV.Bounds.UpperBound}}); + I.first->second = { + std::max(I.first->second.LowerBound, KV.Bounds.LowerBound), + std::min(I.first->second.UpperBound, KV.Bounds.UpperBound)}; } int64_t OffsetSum; @@ -513,12 +538,24 @@ } // Add extra constraints for variables that are known positive. - for (auto &KV : KnownNonNegativeVariables) { - if (!KV.second || + for (auto &KV : BoundInfoVariables) { + if (!KV.second.isLowerBoundSet() || (!Value2Index.contains(KV.first) && !NewIndexMap.contains(KV.first))) continue; SmallVector C(Value2Index.size() + NewVariables.size() + 1, 0); C[GetOrAddIndex(KV.first)] = -1; + C[0] = KV.second.LowerBound; + Res.ExtraInfo.push_back(C); + } + + // Add extra constraints for variables that have an upperBound. + for (auto &KV : BoundInfoVariables) { + if (!KV.second.isUpperBoundSet() || + (!Value2Index.contains(KV.first) && !NewIndexMap.contains(KV.first))) + continue; + SmallVector C(Value2Index.size() + NewVariables.size() + 1, 0); + C[GetOrAddIndex(KV.first)] = 1; + C[0] = KV.second.UpperBound; Res.ExtraInfo.push_back(C); } return Res;