]> granicus.if.org Git - llvm/commitdiff
[SCCP] Pick the right lattice value for constants.
authorDavide Italiano <davide@freebsd.org>
Wed, 22 Nov 2017 03:04:55 +0000 (03:04 +0000)
committerDavide Italiano <davide@freebsd.org>
Wed, 22 Nov 2017 03:04:55 +0000 (03:04 +0000)
After the dataflow algorithm proves that an argument is constant,
it replaces it value with the integer constant and drops the lattice
value associated to the DEF.

e.g. in the example we have @f() that's called twice:
call @f(undef, ...)
call @f(2, ...)

`undef` MEET 2 = 2 so we replace the argument and all its uses with
the constant 2.

Shortly after, tryToReplaceWithConstantRange() tries to get the lattice
value for the argument we just replaced, causing an assertion.
This function is a little peculiar as it runs when we're doing replacement
and not as part of the solver but still queries the solver.

The fix is that of checking whether we replaced the value already and
get a temporary lattice value for the constant.

Thanks to Zhendong Su for the report!

Fixes PR35357.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@318817 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Scalar/SCCP.cpp
test/Transforms/SCCP/pr35357.ll [new file with mode: 0644]

index 192ba13c5988c1c4708276ee69bf238380877865..e5866b4718da1e64842fc5c9a4b35dd014f5b574 100644 (file)
@@ -1615,8 +1615,15 @@ static bool tryToReplaceWithConstantRange(SCCPSolver &Solver, Value *V) {
     if (!Icmp || !Solver.isBlockExecutable(Icmp->getParent()))
       continue;
 
-    auto A = Solver.getLatticeValueFor(Icmp->getOperand(0));
-    auto B = Solver.getLatticeValueFor(Icmp->getOperand(1));
+    auto getIcmpLatticeValue = [&](Value *Op) {
+      if (auto *C = dyn_cast<Constant>(Op))
+        return ValueLatticeElement::get(C);
+      return Solver.getLatticeValueFor(Op);
+    };
+
+    ValueLatticeElement A = getIcmpLatticeValue(Icmp->getOperand(0));
+    ValueLatticeElement B = getIcmpLatticeValue(Icmp->getOperand(1));
+
     Constant *C = nullptr;
     if (A.satisfiesPredicate(Icmp->getPredicate(), B))
       C = ConstantInt::getTrue(Icmp->getType());
diff --git a/test/Transforms/SCCP/pr35357.ll b/test/Transforms/SCCP/pr35357.ll
new file mode 100644 (file)
index 0000000..fda123b
--- /dev/null
@@ -0,0 +1,24 @@
+; RUN: opt -S %s -ipsccp | FileCheck %s
+
+@a = internal global i32 2
+
+define i32 @patatino() {
+; CHECK: @patatino(
+; CHECK: call void @f(i32 undef, i32 1)
+; CHECK-NEXT: call void @f(i32 2, i32 0)
+; CHECK-NEXT: ret i32 0
+entry:
+  call void @f(i32 undef, i32 1)
+  %0 = load i32, i32* @a
+  call void @f(i32 %0, i32 0)
+  ret i32 0
+}
+
+define internal void @f(i32 %c, i32 %d) {
+; CHECK: @f(
+; CHECK:    ret void
+;
+entry:
+  %cmp = icmp ne i32 %c, %d
+  ret void
+}