summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2012-02-24 19:01:58 +0000
committerChris Lattner <sabre@nondot.org>2012-02-24 19:01:58 +0000
commit009e2650d69fe93bda1864340c5f000e56c52fb8 (patch)
tree0da13e16342e5c497332c81991972cd21517be33
parent1a2d061ec08b86ba91d7009b6ffcf08d5bac3f42 (diff)
downloadllvm-009e2650d69fe93bda1864340c5f000e56c52fb8.tar.gz
llvm-009e2650d69fe93bda1864340c5f000e56c52fb8.tar.bz2
llvm-009e2650d69fe93bda1864340c5f000e56c52fb8.tar.xz
fix PR12075, a regression in a recent transform I added. In unreachable code, gep chains can be infinite. Just like "stripPointerCasts", use a set to keep track of visited instructions so we don't recurse infinitely.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@151383 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Analysis/InstructionSimplify.cpp22
-rw-r--r--test/Transforms/InstSimplify/compare.ll10
2 files changed, 28 insertions, 4 deletions
diff --git a/lib/Analysis/InstructionSimplify.cpp b/lib/Analysis/InstructionSimplify.cpp
index 9b0ce1113a..37253f72cf 100644
--- a/lib/Analysis/InstructionSimplify.cpp
+++ b/lib/Analysis/InstructionSimplify.cpp
@@ -1522,13 +1522,27 @@ static Value *ExtractEquivalentCondition(Value *V, CmpInst::Predicate Pred,
/// stripPointerAdjustments - This is like Value::stripPointerCasts, but also
/// removes inbounds gep operations, regardless of their indices.
+static Value *stripPointerAdjustmentsImpl(Value *V,
+ SmallPtrSet<GEPOperator*, 8> &VisitedGEPs) {
+ GEPOperator *GEP = dyn_cast<GEPOperator>(V);
+ if (GEP == 0 || !GEP->isInBounds())
+ return V;
+
+ // If we've already seen this GEP, we will end up infinitely looping. This
+ // can happen in unreachable code.
+ if (!VisitedGEPs.insert(GEP))
+ return V;
+
+ return stripPointerAdjustmentsImpl(GEP->getOperand(0)->stripPointerCasts(),
+ VisitedGEPs);
+}
+
static Value *stripPointerAdjustments(Value *V) {
- if (GEPOperator *GEP = dyn_cast<GEPOperator>(V))
- if (GEP->isInBounds())
- return stripPointerAdjustments(GEP->getOperand(0)->stripPointerCasts());
- return V;
+ SmallPtrSet<GEPOperator*, 8> VisitedGEPs;
+ return stripPointerAdjustmentsImpl(V, VisitedGEPs);
}
+
/// SimplifyICmpInst - Given operands for an ICmpInst, see if we can
/// fold the result. If not, this returns null.
static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
diff --git a/test/Transforms/InstSimplify/compare.ll b/test/Transforms/InstSimplify/compare.ll
index f22ac46397..6ee6dfbdbc 100644
--- a/test/Transforms/InstSimplify/compare.ll
+++ b/test/Transforms/InstSimplify/compare.ll
@@ -463,3 +463,13 @@ define i1 @alloca_compare(i64 %idx) {
; CHECK: alloca_compare
; CHECK: ret i1 false
}
+
+; PR12075
+define i1 @infinite_gep() {
+ ret i1 1
+
+unreachableblock:
+ %X = getelementptr i32 *%X, i32 1
+ %Y = icmp eq i32* %X, null
+ ret i1 %Y
+}