summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
authorSanjoy Das <sanjoy@playingwithpointers.com>2015-09-27 21:09:48 +0000
committerSanjoy Das <sanjoy@playingwithpointers.com>2015-09-27 21:09:48 +0000
commitf1090b6061b34177ad826a595064232a1c08fb4e (patch)
tree79d2e31753788a88bb9492ce67b5f30aa3835546 /llvm
parent9533407566c3bafa96d7000e460cf49919acbd38 (diff)
downloadbcm5719-llvm-f1090b6061b34177ad826a595064232a1c08fb4e.tar.gz
bcm5719-llvm-f1090b6061b34177ad826a595064232a1c08fb4e.zip
[SCEV] identical instructions don't compute equal values
Before this change `HasSameValue` would return true for distinct `alloca` instructions if they happened to be allocating the same type (`alloca` instructions are not specified as reading memory). This change adds an explicit whitelist of instruction types for which "identical" instructions compute the same value. Fixes PR24952. llvm-svn: 248690
Diffstat (limited to 'llvm')
-rw-r--r--llvm/lib/Analysis/ScalarEvolution.cpp9
-rw-r--r--llvm/test/Transforms/IndVarSimplify/pr24952.ll27
2 files changed, 35 insertions, 1 deletions
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 32d3d36c739..57caa9d368a 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -6412,13 +6412,20 @@ static bool HasSameValue(const SCEV *A, const SCEV *B) {
// Quick check to see if they are the same SCEV.
if (A == B) return true;
+ auto ComputesEqualValues = [](const Instruction *A, const Instruction *B) {
+ // Not all instructions that are "identical" compute the same value. For
+ // instance, two distinct alloca instructions allocating the same type are
+ // identical and do not read memory; but compute distinct values.
+ return A->isIdenticalTo(B) && (isa<BinaryOperator>(A) || isa<GetElementPtrInst>(A));
+ };
+
// Otherwise, if they're both SCEVUnknown, it's possible that they hold
// two different instructions with the same value. Check for this case.
if (const SCEVUnknown *AU = dyn_cast<SCEVUnknown>(A))
if (const SCEVUnknown *BU = dyn_cast<SCEVUnknown>(B))
if (const Instruction *AI = dyn_cast<Instruction>(AU->getValue()))
if (const Instruction *BI = dyn_cast<Instruction>(BU->getValue()))
- if (AI->isIdenticalTo(BI) && !AI->mayReadFromMemory())
+ if (ComputesEqualValues(AI, BI))
return true;
// Otherwise assume they may have a different value.
diff --git a/llvm/test/Transforms/IndVarSimplify/pr24952.ll b/llvm/test/Transforms/IndVarSimplify/pr24952.ll
new file mode 100644
index 00000000000..c430cae98f5
--- /dev/null
+++ b/llvm/test/Transforms/IndVarSimplify/pr24952.ll
@@ -0,0 +1,27 @@
+; RUN: opt -indvars -S < %s | FileCheck %s
+
+declare void @use(i1)
+
+define void @f() {
+; CHECK-LABEL: @f(
+ entry:
+ %x = alloca i32
+ %y = alloca i32
+ br label %loop
+
+ loop:
+ %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
+ %iv.inc = add i32 %iv, 1
+
+ %x.gep = getelementptr i32, i32* %x, i32 %iv
+ %eql = icmp eq i32* %x.gep, %y
+; CHECK-NOT: @use(i1 true)
+ call void @use(i1 %eql)
+
+ ; %be.cond deliberately 'false' -- we want want the trip count to be 0.
+ %be.cond = icmp ult i32 %iv, 0
+ br i1 %be.cond, label %loop, label %leave
+
+ leave:
+ ret void
+}
OpenPOWER on IntegriCloud