Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ConstraintElimination: use DynamicAPInt #99019

Closed
wants to merge 1 commit into from

Conversation

artagnon
Copy link
Contributor

To automatically handle overflows correctly and make the transform more powerful, replace uses of int64_t with DynamicAPInt in ConstraintElimination and ConstraintSystem.

To automatically handle overflows correctly and make the transform more
powerful, replace uses of int64_t with DynamicAPInt in
ConstraintElimination and ConstraintSystem.
@llvmbot
Copy link
Collaborator

llvmbot commented Jul 16, 2024

@llvm/pr-subscribers-llvm-analysis

@llvm/pr-subscribers-llvm-transforms

Author: Ramkumar Ramachandra (artagnon)

Changes

To automatically handle overflows correctly and make the transform more powerful, replace uses of int64_t with DynamicAPInt in ConstraintElimination and ConstraintSystem.


Patch is 23.52 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/99019.diff

6 Files Affected:

  • (modified) llvm/include/llvm/Analysis/ConstraintSystem.h (+24-26)
  • (modified) llvm/lib/Analysis/ConstraintSystem.cpp (+16-19)
  • (modified) llvm/lib/Transforms/Scalar/ConstraintElimination.cpp (+26-23)
  • (modified) llvm/test/Transforms/ConstraintElimination/constraint-overflow.ll (+1-2)
  • (modified) llvm/test/Transforms/ConstraintElimination/overflows.ll (+1-2)
  • (modified) llvm/unittests/Analysis/ConstraintSystemTest.cpp (+55-44)
diff --git a/llvm/include/llvm/Analysis/ConstraintSystem.h b/llvm/include/llvm/Analysis/ConstraintSystem.h
index 7b02b618f7cb4..7711336b1d635 100644
--- a/llvm/include/llvm/Analysis/ConstraintSystem.h
+++ b/llvm/include/llvm/Analysis/ConstraintSystem.h
@@ -9,38 +9,35 @@
 #ifndef LLVM_ANALYSIS_CONSTRAINTSYSTEM_H
 #define LLVM_ANALYSIS_CONSTRAINTSYSTEM_H
 
-#include "llvm/ADT/APInt.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DynamicAPInt.h"
 #include "llvm/ADT/SmallVector.h"
-#include "llvm/Support/MathExtras.h"
-
-#include <string>
 
 namespace llvm {
 
 class Value;
 class ConstraintSystem {
   struct Entry {
-    int64_t Coefficient;
+    DynamicAPInt Coefficient;
     uint16_t Id;
 
-    Entry(int64_t Coefficient, uint16_t Id)
+    Entry(const DynamicAPInt &Coefficient, uint16_t Id)
         : Coefficient(Coefficient), Id(Id) {}
   };
 
-  static int64_t getConstPart(const Entry &E) {
+  static DynamicAPInt getConstPart(const Entry &E) {
     if (E.Id == 0)
       return E.Coefficient;
-    return 0;
+    return DynamicAPInt{0};
   }
 
-  static int64_t getLastCoefficient(ArrayRef<Entry> Row, uint16_t Id) {
+  static DynamicAPInt getLastCoefficient(ArrayRef<Entry> Row, uint16_t Id) {
     if (Row.empty())
-      return 0;
+      return DynamicAPInt{0};
     if (Row.back().Id == Id)
       return Row.back().Coefficient;
-    return 0;
+    return DynamicAPInt{0};
   }
 
   size_t NumVariables = 0;
@@ -74,11 +71,12 @@ class ConstraintSystem {
   ConstraintSystem(const DenseMap<Value *, unsigned> &Value2Index)
       : NumVariables(Value2Index.size()), Value2Index(Value2Index) {}
 
-  bool addVariableRow(ArrayRef<int64_t> R) {
+  bool addVariableRow(ArrayRef<DynamicAPInt> R) {
     assert(Constraints.empty() || R.size() == NumVariables);
     // If all variable coefficients are 0, the constraint does not provide any
     // usable information.
-    if (all_of(ArrayRef(R).drop_front(1), [](int64_t C) { return C == 0; }))
+    if (all_of(ArrayRef(R).drop_front(1),
+               [](const DynamicAPInt &C) { return C == 0; }))
       return false;
 
     SmallVector<Entry, 4> NewRow;
@@ -98,10 +96,11 @@ class ConstraintSystem {
     return Value2Index;
   }
 
-  bool addVariableRowFill(ArrayRef<int64_t> R) {
+  bool addVariableRowFill(ArrayRef<DynamicAPInt> R) {
     // If all variable coefficients are 0, the constraint does not provide any
     // usable information.
-    if (all_of(ArrayRef(R).drop_front(1), [](int64_t C) { return C == 0; }))
+    if (all_of(ArrayRef(R).drop_front(1),
+               [](const DynamicAPInt &C) { return C == 0; }))
       return false;
 
     NumVariables = std::max(R.size(), NumVariables);
@@ -111,7 +110,7 @@ class ConstraintSystem {
   /// Returns true if there may be a solution for the constraints in the system.
   bool mayHaveSolution();
 
-  static SmallVector<int64_t, 8> negate(SmallVector<int64_t, 8> R) {
+  static SmallVector<DynamicAPInt, 8> negate(SmallVector<DynamicAPInt, 8> R) {
     // The negated constraint R is obtained by multiplying by -1 and adding 1 to
     // the constant.
     R[0] += 1;
@@ -122,11 +121,11 @@ class ConstraintSystem {
   /// original vector.
   ///
   /// \param R The vector of coefficients to be negated.
-  static SmallVector<int64_t, 8> negateOrEqual(SmallVector<int64_t, 8> R) {
+  static SmallVector<DynamicAPInt, 8>
+  negateOrEqual(SmallVector<DynamicAPInt, 8> R) {
     // The negated constraint R is obtained by multiplying by -1.
     for (auto &C : R)
-      if (MulOverflow(C, int64_t(-1), C))
-        return {};
+      C *= -1;
     return R;
   }
 
@@ -134,19 +133,18 @@ class ConstraintSystem {
   /// modify the original vector.
   ///
   /// \param R The vector of coefficients to be converted.
-  static SmallVector<int64_t, 8> toStrictLessThan(SmallVector<int64_t, 8> R) {
+  static SmallVector<DynamicAPInt, 8>
+  toStrictLessThan(SmallVector<DynamicAPInt, 8> R) {
     // The strict less than is obtained by subtracting 1 from the constant.
-    if (SubOverflow(R[0], int64_t(1), R[0])) {
-      return {};
-    }
+    R[0] -= 1;
     return R;
   }
 
-  bool isConditionImplied(SmallVector<int64_t, 8> R) const;
+  bool isConditionImplied(SmallVector<DynamicAPInt, 8> R) const;
 
-  SmallVector<int64_t> getLastConstraint() const {
+  SmallVector<DynamicAPInt> getLastConstraint() const {
     assert(!Constraints.empty() && "Constraint system is empty");
-    SmallVector<int64_t> Result(NumVariables, 0);
+    SmallVector<DynamicAPInt> Result(NumVariables, DynamicAPInt{0});
     for (auto &Entry : Constraints.back())
       Result[Entry.Id] = Entry.Coefficient;
     return Result;
diff --git a/llvm/lib/Analysis/ConstraintSystem.cpp b/llvm/lib/Analysis/ConstraintSystem.cpp
index e4c9dcc7544e9..bb21936c4218e 100644
--- a/llvm/lib/Analysis/ConstraintSystem.cpp
+++ b/llvm/lib/Analysis/ConstraintSystem.cpp
@@ -7,8 +7,8 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/Analysis/ConstraintSystem.h"
+#include "llvm/ADT/DynamicAPInt.h"
 #include "llvm/ADT/SmallVector.h"
-#include "llvm/Support/MathExtras.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/IR/Value.h"
 #include "llvm/Support/Debug.h"
@@ -55,8 +55,8 @@ bool ConstraintSystem::eliminateUsingFM() {
       if (R1 == R2)
         continue;
 
-      int64_t UpperLast = getLastCoefficient(RemainingRows[R2], LastIdx);
-      int64_t LowerLast = getLastCoefficient(RemainingRows[R1], LastIdx);
+      DynamicAPInt UpperLast = getLastCoefficient(RemainingRows[R2], LastIdx);
+      DynamicAPInt LowerLast = getLastCoefficient(RemainingRows[R1], LastIdx);
       assert(
           UpperLast != 0 && LowerLast != 0 &&
           "RemainingRows should only contain rows where the variable is != 0");
@@ -79,9 +79,9 @@ bool ConstraintSystem::eliminateUsingFM() {
       while (true) {
         if (IdxUpper >= UpperRow.size() || IdxLower >= LowerRow.size())
           break;
-        int64_t M1, M2, N;
-        int64_t UpperV = 0;
-        int64_t LowerV = 0;
+        DynamicAPInt M1, M2, N;
+        DynamicAPInt UpperV{0};
+        DynamicAPInt LowerV{0};
         uint16_t CurrentId = std::numeric_limits<uint16_t>::max();
         if (IdxUpper < UpperRow.size()) {
           CurrentId = std::min(UpperRow[IdxUpper].Id, CurrentId);
@@ -94,18 +94,13 @@ bool ConstraintSystem::eliminateUsingFM() {
           UpperV = UpperRow[IdxUpper].Coefficient;
           IdxUpper++;
         }
-
-        if (MulOverflow(UpperV, -1 * LowerLast, M1))
-          return false;
+        M1 = UpperV * (-LowerLast);
         if (IdxLower < LowerRow.size() && LowerRow[IdxLower].Id == CurrentId) {
           LowerV = LowerRow[IdxLower].Coefficient;
           IdxLower++;
         }
-
-        if (MulOverflow(LowerV, UpperLast, M2))
-          return false;
-        if (AddOverflow(M1, M2, N))
-          return false;
+        M2 = LowerV * UpperLast;
+        N = M1 + M2;
         if (N == 0)
           continue;
         NR.emplace_back(N, CurrentId);
@@ -170,15 +165,15 @@ void ConstraintSystem::dump() const {
         continue;
       std::string Coefficient;
       if (E.Coefficient != 1)
-        Coefficient = std::to_string(E.Coefficient) + " * ";
+        Coefficient = std::to_string(int64_t{E.Coefficient}) + " * ";
       Parts.push_back(Coefficient + Names[E.Id - 1]);
     }
     // assert(!Parts.empty() && "need to have at least some parts");
-    int64_t ConstPart = 0;
+    DynamicAPInt ConstPart{0};
     if (Row[0].Id == 0)
       ConstPart = Row[0].Coefficient;
     LLVM_DEBUG(dbgs() << join(Parts, std::string(" + "))
-                      << " <= " << std::to_string(ConstPart) << "\n");
+                      << " <= " << std::to_string(int64_t{ConstPart}) << "\n");
   }
 #endif
 }
@@ -191,10 +186,12 @@ bool ConstraintSystem::mayHaveSolution() {
   return HasSolution;
 }
 
-bool ConstraintSystem::isConditionImplied(SmallVector<int64_t, 8> R) const {
+bool ConstraintSystem::isConditionImplied(
+    SmallVector<DynamicAPInt, 8> R) const {
   // If all variable coefficients are 0, we have 'C >= 0'. If the constant is >=
   // 0, R is always true, regardless of the system.
-  if (all_of(ArrayRef(R).drop_front(1), [](int64_t C) { return C == 0; }))
+  if (all_of(ArrayRef(R).drop_front(1),
+             [](const DynamicAPInt &C) { return C == 0; }))
     return R[0] >= 0;
 
   // If there is no solution with the negation of R added to the system, the
diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
index c31173879af1e..0a5b6548b3629 100644
--- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/Transforms/Scalar/ConstraintElimination.h"
+#include "llvm/ADT/DynamicAPInt.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/ScopeExit.h"
 #include "llvm/ADT/SmallVector.h"
@@ -221,17 +222,17 @@ struct StackEntry {
 };
 
 struct ConstraintTy {
-  SmallVector<int64_t, 8> Coefficients;
+  SmallVector<DynamicAPInt, 8> Coefficients;
   SmallVector<ConditionTy, 2> Preconditions;
 
-  SmallVector<SmallVector<int64_t, 8>> ExtraInfo;
+  SmallVector<SmallVector<DynamicAPInt, 8>> ExtraInfo;
 
   bool IsSigned = false;
 
   ConstraintTy() = default;
 
-  ConstraintTy(SmallVector<int64_t, 8> Coefficients, bool IsSigned, bool IsEq,
-               bool IsNe)
+  ConstraintTy(SmallVector<DynamicAPInt, 8> Coefficients, bool IsSigned,
+               bool IsEq, bool IsNe)
       : Coefficients(std::move(Coefficients)), IsSigned(IsSigned), IsEq(IsEq),
         IsNe(IsNe) {}
 
@@ -278,8 +279,9 @@ class ConstraintInfo {
     auto &Value2Index = getValue2Index(false);
     // Add Arg > -1 constraints to unsigned system for all function arguments.
     for (Value *Arg : FunctionArgs) {
-      ConstraintTy VarPos(SmallVector<int64_t, 8>(Value2Index.size() + 1, 0),
-                          false, false, false);
+      ConstraintTy VarPos(
+          SmallVector<DynamicAPInt, 8>(Value2Index.size() + 1, DynamicAPInt{0}),
+          false, false, false);
       VarPos.Coefficients[Value2Index[Arg]] = -1;
       UnsignedCS.addVariableRow(VarPos.Coefficients);
     }
@@ -663,8 +665,8 @@ ConstraintInfo::getConstraint(CmpInst::Predicate Pred, Value *Op0, Value *Op1,
                         Preconditions, IsSigned, DL);
   auto BDec = decompose(Op1->stripPointerCastsSameRepresentation(),
                         Preconditions, IsSigned, DL);
-  int64_t Offset1 = ADec.Offset;
-  int64_t Offset2 = BDec.Offset;
+  DynamicAPInt Offset1{ADec.Offset};
+  DynamicAPInt Offset2{BDec.Offset};
   Offset1 *= -1;
 
   auto &VariablesA = ADec.Vars;
@@ -692,7 +694,8 @@ ConstraintInfo::getConstraint(CmpInst::Predicate Pred, Value *Op0, Value *Op1,
   // Build result constraint, by first adding all coefficients from A and then
   // subtracting all coefficients from B.
   ConstraintTy Res(
-      SmallVector<int64_t, 8>(Value2Index.size() + NewVariables.size() + 1, 0),
+      SmallVector<DynamicAPInt, 8>(Value2Index.size() + NewVariables.size() + 1,
+                                   DynamicAPInt{0}),
       IsSigned, IsEq, IsNe);
   // Collect variables that are known to be positive in all uses in the
   // constraint.
@@ -706,27 +709,24 @@ ConstraintInfo::getConstraint(CmpInst::Predicate Pred, Value *Op0, Value *Op1,
   }
 
   for (const auto &KV : VariablesB) {
-    if (SubOverflow(R[GetOrAddIndex(KV.Variable)], KV.Coefficient,
-                    R[GetOrAddIndex(KV.Variable)]))
-      return {};
+    R[GetOrAddIndex(KV.Variable)] =
+        R[GetOrAddIndex(KV.Variable)] - KV.Coefficient;
     auto I =
         KnownNonNegativeVariables.insert({KV.Variable, KV.IsKnownNonNegative});
     I.first->second &= KV.IsKnownNonNegative;
   }
 
-  int64_t OffsetSum;
-  if (AddOverflow(Offset1, Offset2, OffsetSum))
-    return {};
+  DynamicAPInt OffsetSum;
+  OffsetSum = Offset1 + Offset2;
   if (Pred == (IsSigned ? CmpInst::ICMP_SLT : CmpInst::ICMP_ULT))
-    if (AddOverflow(OffsetSum, int64_t(-1), OffsetSum))
-      return {};
+    OffsetSum += -1;
   R[0] = OffsetSum;
   Res.Preconditions = std::move(Preconditions);
 
   // Remove any (Coefficient, Variable) entry where the Coefficient is 0 for new
   // variables.
   while (!NewVariables.empty()) {
-    int64_t Last = R.back();
+    DynamicAPInt Last = R.back();
     if (Last != 0)
       break;
     R.pop_back();
@@ -739,7 +739,8 @@ ConstraintInfo::getConstraint(CmpInst::Predicate Pred, Value *Op0, Value *Op1,
     if (!KV.second ||
         (!Value2Index.contains(KV.first) && !NewIndexMap.contains(KV.first)))
       continue;
-    SmallVector<int64_t, 8> C(Value2Index.size() + NewVariables.size() + 1, 0);
+    SmallVector<DynamicAPInt, 8> C(Value2Index.size() + NewVariables.size() + 1,
+                                   DynamicAPInt{0});
     C[GetOrAddIndex(KV.first)] = -1;
     Res.ExtraInfo.push_back(C);
   }
@@ -756,8 +757,9 @@ ConstraintTy ConstraintInfo::getConstraintForSolving(CmpInst::Predicate Pred,
       (Pred == CmpInst::ICMP_UGE && Op1 == NullC)) {
     auto &Value2Index = getValue2Index(false);
     // Return constraint that's trivially true.
-    return ConstraintTy(SmallVector<int64_t, 8>(Value2Index.size(), 0), false,
-                        false, false);
+    return ConstraintTy(
+        SmallVector<DynamicAPInt, 8>(Value2Index.size(), DynamicAPInt{0}),
+        false, false, false);
   }
 
   // If both operands are known to be non-negative, change signed predicates to
@@ -892,7 +894,7 @@ void ConstraintInfo::transferToOtherSystem(
 
 #ifndef NDEBUG
 
-static void dumpConstraint(ArrayRef<int64_t> C,
+static void dumpConstraint(ArrayRef<DynamicAPInt> C,
                            const DenseMap<Value *, unsigned> &Value2Index) {
   ConstraintSystem CS(Value2Index);
   CS.addVariableRowFill(C);
@@ -1590,7 +1592,8 @@ void ConstraintInfo::addFact(CmpInst::Predicate Pred, Value *A, Value *B,
 
     if (!R.IsSigned) {
       for (Value *V : NewVariables) {
-        ConstraintTy VarPos(SmallVector<int64_t, 8>(Value2Index.size() + 1, 0),
+        ConstraintTy VarPos(SmallVector<DynamicAPInt, 8>(Value2Index.size() + 1,
+                                                         DynamicAPInt{0}),
                             false, false, false);
         VarPos.Coefficients[Value2Index[V]] = -1;
         CSToUse.addVariableRow(VarPos.Coefficients);
diff --git a/llvm/test/Transforms/ConstraintElimination/constraint-overflow.ll b/llvm/test/Transforms/ConstraintElimination/constraint-overflow.ll
index 88f87f4afab28..efb89fd0512d9 100644
--- a/llvm/test/Transforms/ConstraintElimination/constraint-overflow.ll
+++ b/llvm/test/Transforms/ConstraintElimination/constraint-overflow.ll
@@ -13,8 +13,7 @@ define i32 @f(i64 %a3, i64 %numElements) {
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i64 [[A1]], [[A3]]
 ; CHECK-NEXT:    br i1 [[CMP]], label [[IF_END_I:%.*]], label [[ABORT:%.*]]
 ; CHECK:       if.end.i:
-; CHECK-NEXT:    [[CMP2_NOT_I:%.*]] = icmp ult i64 [[A1]], [[A3]]
-; CHECK-NEXT:    br i1 [[CMP2_NOT_I]], label [[ABORT]], label [[EXIT:%.*]]
+; CHECK-NEXT:    br i1 false, label [[ABORT]], label [[EXIT:%.*]]
 ; CHECK:       abort:
 ; CHECK-NEXT:    ret i32 -1
 ; CHECK:       exit:
diff --git a/llvm/test/Transforms/ConstraintElimination/overflows.ll b/llvm/test/Transforms/ConstraintElimination/overflows.ll
index 556ae0c56f9aa..f60291cc846ce 100644
--- a/llvm/test/Transforms/ConstraintElimination/overflows.ll
+++ b/llvm/test/Transforms/ConstraintElimination/overflows.ll
@@ -23,8 +23,7 @@ define i1 @test_overflow_in_negate_constraint(i8 %x, i64 %y) {
 ; CHECK-NEXT:  bb:
 ; CHECK-NEXT:    [[ZEXT:%.*]] = zext i8 [[X]] to i64
 ; CHECK-NEXT:    [[SHL:%.*]] = shl nuw nsw i64 [[ZEXT]], 63
-; CHECK-NEXT:    [[ICMP:%.*]] = icmp uge i64 [[Y]], [[SHL]]
-; CHECK-NEXT:    ret i1 [[ICMP]]
+; CHECK-NEXT:    ret i1 true
 ;
 bb:
   %zext = zext i8 %x to i64
diff --git a/llvm/unittests/Analysis/ConstraintSystemTest.cpp b/llvm/unittests/Analysis/ConstraintSystemTest.cpp
index febeb982c87af..567d5cf9494e5 100644
--- a/llvm/unittests/Analysis/ConstraintSystemTest.cpp
+++ b/llvm/unittests/Analysis/ConstraintSystemTest.cpp
@@ -7,21 +7,31 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/Analysis/ConstraintSystem.h"
+#include "llvm/ADT/DynamicAPInt.h"
+#include "llvm/ADT/SmallVector.h"
 #include "gtest/gtest.h"
+#include <initializer_list>
 
 using namespace llvm;
 
 namespace {
+SmallVector<DynamicAPInt> toDynamicAPIntVec(std::initializer_list<int64_t> IL) {
+  SmallVector<DynamicAPInt> Ret;
+  Ret.reserve(IL.size());
+  for (auto El : IL)
+    Ret.emplace_back(El);
+  return Ret;
+}
 
 TEST(ConstraintSolverTest, TestSolutionChecks) {
   {
     ConstraintSystem CS;
     // x + y <= 10, x >= 5, y >= 6, x <= 10, y <= 10
-    CS.addVariableRow({10, 1, 1});
-    CS.addVariableRow({-5, -1, 0});
-    CS.addVariableRow({-6, 0, -1});
-    CS.addVariableRow({10, 1, 0});
-    CS.addVariableRow({10, 0, 1});
+    CS.addVariableRow(toDynamicAPIntVec({10, 1, 1}));
+    CS.addVariableRow(toDynamicAPIntVec({-5, -1, 0}));
+    CS.addVariableRow(toDynamicAPIntVec({-6, 0, -1}));
+    CS.addVariableRow(toDynamicAPIntVec({10, 1, 0}));
+    CS.addVariableRow(toDynamicAPIntVec({10, 0, 1}));
 
     EXPECT_FALSE(CS.mayHaveSolution());
   }
@@ -29,11 +39,11 @@ TEST(ConstraintSolverTest, TestSolutionChecks) {
   {
     ConstraintSystem CS;
     // x + y <= 10, x >= 2, y >= 3, x <= 10, y <= 10
-    CS.addVariableRow({10, 1, 1});
-    CS.addVariableRow({-2, -1, 0});
-    CS.addVariableRow({-3, 0, -1});
-    CS.addVariableRow({10, 1, 0});
-    CS.addVariableRow({10, 0, 1});
+    CS.addVariableRow(toDynamicAPIntVec({10, 1, 1}));
+    CS.addVariableRow(toDynamicAPIntVec({-2, -1, 0}));
+    CS.addVariableRow(toDynamicAPIntVec({-3, 0, -1}));
+    CS.addVariableRow(toDynamicAPIntVec({10, 1, 0}));
+    CS.addVariableRow(toDynamicAPIntVec({10, 0, 1}));
 
     EXPECT_TRUE(CS.mayHaveSolution());
   }
@@ -41,9 +51,9 @@ TEST(ConstraintSolverTest, TestSolutionChecks) {
   {
     ConstraintSystem CS;
     // x + y <= 10, x >= 10, y >= 10; does not have a solution.
-    CS.addVariableRow({10, 1, 1});
-    CS.addVariableRow({-10, -1, 0});
-    CS.addVariableRow({-10, 0, -1});
+    CS.addVariableRow(toDynamicAPIntVec({10, 1, 1}));
+    CS.addVariableRow(toDynamicAPIntVec({-10, -1, 0}));
+    CS.addVariableRow(toDynamicAPIntVec({-10, 0, -1}));
 
     EXPECT_FALSE(CS.mayHaveSolution());
   }
@@ -51,9 +61,9 @@ TEST(ConstraintSolverTest, TestSolutionChecks) {
   {
     ConstraintSystem CS;
     // x + y >= 20, 10 >= x, 10 >= y; does HAVE a solution.
-    CS.addVariableRow({-20, -1, -1});
-    CS.addVariableRow({-10, -1, 0});
-    CS.addVariableRow({-10, 0, -1});
+    CS.addVariableRow(toDynamicAPIntVec({-20, -1, -1}));
+    CS.addVariableRow(toDynamicAPIntVec({-10, -1, 0}));
+    CS.addVariableRow(toDynamicAPIntVec({-10, 0, -1}));
 
     EXPECT_TRUE(CS.mayHaveSolution());
   }
@@ -62,9 +72,9 @@ TEST(ConstraintSolverTest, TestSolutionChecks) {
     ConstraintSystem CS;
 
     // 2x + y + 3z <= 10,  2x + y >= 10, y >= 1
-    CS.addVariableRow({10, 2, 1, 3});
-    CS.addVariableRow({-10, -2, -1, 0});
-    CS.addVariableRow({-1, 0, 0, -1});
+    CS.addVariableRow(toDynamicAPIntVec({10, 2, 1, 3}));
+    CS.addVariableRow(toDynamicAPIntVec({-10, -2, -1, 0}));
+    CS.addVariableRow(toDynamicAPIntVec({-1, 0, 0, -1}));
 
     EXPECT_FALSE(CS.mayHaveSolution());
   }
@@ -73,8 +83,8 @@ TEST(ConstraintSolverTest, TestSolutionChecks) {
     ConstraintSystem CS;
 
     // 2x + y + 3z <= 10,  2x + y >= 10
-    CS.addVariableRow({10, 2, 1, 3});
-    CS.addVariableRow({-10, -2, -1, 0});
+    CS.addVariableRow(toDynamicAPIntVec({10, 2, 1, 3}));
+    CS.addVariableRow(toDynamicAPIntVec({-10, -2, -1, 0}));
 
     EXPECT_TRUE(CS.mayHaveSolution());
   }
@@ -85,47 +95,47 @@ TEST(ConstraintSolverTest, IsConditionImplied) {
     // For the test below, we assume we know
     // x <= 5 && y <= 3
     ConstraintSystem CS;
-    CS.addVariableRow({5, 1, 0});
-    CS.addVariableRow({3, 0, 1});
+    CS.addVariableRow(toDynamicAPIntVec({5, 1, 0}));
+    CS.addVariableRow(toDynamicAPIntVec({3, 0, 1}));
 
     // x + y <= 6 does not hold.
-    EXPECT_FALSE(CS.isConditionImplied({6, 1, 1}));
+    EXPECT_...
[truncated]

dtcxzyw added a commit to dtcxzyw/llvm-opt-benchmark that referenced this pull request Jul 16, 2024
@fhahn
Copy link
Contributor

fhahn commented Jul 16, 2024

To automatically handle overflows correctly

IIUC this should be fine, as we only allow expressions that won't wrap in IR semantics, so the only source of wrapping should be multiplications during solving. Unfortunately it comes at a cost of compile-time, presumably not due to overflows happening frequently but extra overhead from DynamicAPInt?

@artagnon
Copy link
Contributor Author

IIUC this should be fine, as we only allow expressions that won't wrap in IR semantics, so the only source of wrapping should be multiplications during solving. Unfortunately it comes at a cost of compile-time, presumably not due to overflows happening frequently but extra overhead from DynamicAPInt?

Yes, I realized that the source of wrapping is the solving. The compile-time regression seems unbelievably large: if my reading of DynamicAPInt is correct, it shouldn't have such a high overhead. Could we kindly verify that there are, in fact, very few or no binary changes?

@fhahn
Copy link
Contributor

fhahn commented Jul 16, 2024

IIUC this should be fine, as we only allow expressions that won't wrap in IR semantics, so the only source of wrapping should be multiplications during solving. Unfortunately it comes at a cost of compile-time, presumably not due to overflows happening frequently but extra overhead from DynamicAPInt?

Yes, I realized that the source of wrapping is the solving. The compile-time regression seems unbelievably large: if my reading of DynamicAPInt is correct, it shouldn't have such a high overhead. Could we kindly verify that there are, in fact, very few or no binary changes?

For CTMark, it looks like there are no binary changes (see size-text metric) for the link @dtcxzyw shared: https://llvm-compile-time-tracker.com/compare.php?from=c5ee3c05ca61f3fae11337c5853aee7b450a9dc6&to=dcd0c32ad587fbb884ceb76e043e1c2714f556ca&stat=size-text

@artagnon
Copy link
Contributor Author

Thanks, I didn't realize that DynamicAPInt would have such a high overhead.

@artagnon artagnon closed this Jul 16, 2024
@artagnon artagnon deleted the perf/constraintelim-int branch July 16, 2024 13:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants