From 76735fbd2e4e145e11a2fa8eebed4039556d5a43 Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Fri, 4 Jul 2014 22:05:26 +0000 Subject: [PATCH] IR: Fold away compares between GV GEPs and GVs A GEP of a non-weak global variable will not be equivalent to another non-weak global variable or a GEP of such a variable. Differential Revision: http://reviews.llvm.org/D4238 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@212360 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/IR/ConstantFold.cpp | 29 ++++++++++++++----- test/Other/constant-fold-gep.ll | 17 +++++++++++ .../InstCombine/2010-03-03-ExtElim.ll | 4 +-- test/Transforms/InstCombine/pr20079.ll | 8 ++--- .../Transforms/LoopVectorize/if-conversion.ll | 2 +- 5 files changed, 44 insertions(+), 16 deletions(-) diff --git a/lib/IR/ConstantFold.cpp b/lib/IR/ConstantFold.cpp index c23ab71eaf3..395ac3907ba 100644 --- a/lib/IR/ConstantFold.cpp +++ b/lib/IR/ConstantFold.cpp @@ -1334,6 +1334,15 @@ static FCmpInst::Predicate evaluateFCmpRelation(Constant *V1, Constant *V2) { return FCmpInst::BAD_FCMP_PREDICATE; } +static ICmpInst::Predicate areGlobalsPotentiallyEqual(const GlobalValue *GV1, + const GlobalValue *GV2) { + // Don't try to decide equality of aliases. + if (!isa(GV1) && !isa(GV2)) + if (!GV1->hasExternalWeakLinkage() || !GV2->hasExternalWeakLinkage()) + return ICmpInst::ICMP_NE; + return ICmpInst::BAD_ICMP_PREDICATE; +} + /// evaluateICmpRelation - This function determines if there is anything we can /// decide about the two constants provided. This doesn't need to handle simple /// things like integer comparisons, but should instead handle ConstantExprs @@ -1395,10 +1404,7 @@ static ICmpInst::Predicate evaluateICmpRelation(Constant *V1, Constant *V2, // constant (which, since the types must match, means that it's a // ConstantPointerNull). if (const GlobalValue *GV2 = dyn_cast(V2)) { - // Don't try to decide equality of aliases. - if (!isa(GV) && !isa(GV2)) - if (!GV->hasExternalWeakLinkage() || !GV2->hasExternalWeakLinkage()) - return ICmpInst::ICMP_NE; + return areGlobalsPotentiallyEqual(GV, GV2); } else if (isa(V2)) { return ICmpInst::ICMP_NE; // Globals never equal labels. } else { @@ -1463,7 +1469,8 @@ static ICmpInst::Predicate evaluateICmpRelation(Constant *V1, Constant *V2, } break; - case Instruction::GetElementPtr: + case Instruction::GetElementPtr: { + GEPOperator *CE1GEP = cast(CE1); // Ok, since this is a getelementptr, we know that the constant has a // pointer type. Check the various cases. if (isa(V2)) { @@ -1510,7 +1517,8 @@ static ICmpInst::Predicate evaluateICmpRelation(Constant *V1, Constant *V2, "Surprising getelementptr!"); return isSigned ? ICmpInst::ICMP_SGT : ICmpInst::ICMP_UGT; } else { - // If they are different globals, we don't know what the value is. + if (CE1GEP->hasAllZeroIndices()) + return areGlobalsPotentiallyEqual(GV, GV2); return ICmpInst::BAD_ICMP_PREDICATE; } } @@ -1526,8 +1534,14 @@ static ICmpInst::Predicate evaluateICmpRelation(Constant *V1, Constant *V2, // By far the most common case to handle is when the base pointers are // obviously to the same global. if (isa(CE1Op0) && isa(CE2Op0)) { - if (CE1Op0 != CE2Op0) // Don't know relative ordering. + // Don't know relative ordering, but check for inequality. + if (CE1Op0 != CE2Op0) { + GEPOperator *CE2GEP = cast(CE2); + if (CE1GEP->hasAllZeroIndices() && CE2GEP->hasAllZeroIndices()) + return areGlobalsPotentiallyEqual(cast(CE1Op0), + cast(CE2Op0)); return ICmpInst::BAD_ICMP_PREDICATE; + } // Ok, we know that both getelementptr instructions are based on the // same global. From this, we can precisely determine the relative // ordering of the resultant pointers. @@ -1573,6 +1587,7 @@ static ICmpInst::Predicate evaluateICmpRelation(Constant *V1, Constant *V2, } } } + } default: break; } diff --git a/test/Other/constant-fold-gep.ll b/test/Other/constant-fold-gep.ll index dc122fd1610..387489820b2 100644 --- a/test/Other/constant-fold-gep.ll +++ b/test/Other/constant-fold-gep.ll @@ -467,4 +467,21 @@ define i8* @same_addrspace() nounwind noinline { ; OPT: ret i8* getelementptr inbounds ([4 x i8]* @p0, i32 0, i32 2) } +@gv1 = internal global i32 1 +@gv2 = internal global [1 x i32] [ i32 2 ] +@gv3 = internal global [1 x i32] [ i32 2 ] + +; Handled by TI-independent constant folder +define i1 @gv_gep_vs_gv() { + ret i1 icmp eq (i32* getelementptr inbounds ([1 x i32]* @gv2, i32 0, i32 0), i32* @gv1) +} +; PLAIN: gv_gep_vs_gv +; PLAIN: ret i1 false + +define i1 @gv_gep_vs_gv_gep() { + ret i1 icmp eq (i32* getelementptr inbounds ([1 x i32]* @gv2, i32 0, i32 0), i32* getelementptr inbounds ([1 x i32]* @gv3, i32 0, i32 0)) +} +; PLAIN: gv_gep_vs_gv_gep +; PLAIN: ret i1 false + ; CHECK: attributes #0 = { nounwind } diff --git a/test/Transforms/InstCombine/2010-03-03-ExtElim.ll b/test/Transforms/InstCombine/2010-03-03-ExtElim.ll index b1384ec0020..e0def997d97 100644 --- a/test/Transforms/InstCombine/2010-03-03-ExtElim.ll +++ b/test/Transforms/InstCombine/2010-03-03-ExtElim.ll @@ -22,11 +22,11 @@ define i1 @PR6486() nounwind { define i1 @PR16462_1() nounwind { ; CHECK-LABEL: @PR16462_1( ret i1 icmp sgt (i32 sext (i16 trunc (i32 select (i1 icmp eq (i32* getelementptr inbounds ([1 x i32]* @a, i32 0, i32 0), i32* @d), i32 0, i32 1) to i16) to i32), i32 65535) -; CHECK: ret i1 icmp sgt (i32 sext (i16 trunc (i32 select (i1 icmp eq (i32* getelementptr inbounds ([1 x i32]* @a, i32 0, i32 0), i32* @d), i32 0, i32 1) to i16) to i32), i32 65535) +; CHECK: ret i1 false } define i1 @PR16462_2() nounwind { ; CHECK-LABEL: @PR16462_2( ret i1 icmp sgt (i32 sext (i16 trunc (i32 select (i1 icmp eq (i32* getelementptr inbounds ([1 x i32]* @a, i32 0, i32 0), i32* @d), i32 0, i32 1) to i16) to i32), i32 42) -; CHECK: ret i1 icmp sgt (i16 trunc (i32 select (i1 icmp eq (i32* getelementptr inbounds ([1 x i32]* @a, i32 0, i32 0), i32* @d), i32 0, i32 1) to i16), i16 42) +; CHECK: ret i1 false } diff --git a/test/Transforms/InstCombine/pr20079.ll b/test/Transforms/InstCombine/pr20079.ll index 3c86ecc5f30..ce9c4deb06a 100644 --- a/test/Transforms/InstCombine/pr20079.ll +++ b/test/Transforms/InstCombine/pr20079.ll @@ -3,11 +3,7 @@ @c = internal global i32 0, align 4 ; CHECK-LABEL: @fn1 -; CHECK: [[ADD:%.*]] = add i32 %a, -1 -; CHECK-NEXT: [[AND:%.*]] = and i32 [[ADD]], sub (i32 0, i32 zext (i1 icmp eq (i32* getelementptr inbounds ([1 x i32]* @b, i64 0, i64 0), i32* @c) to i32)) -; CHECK-NEXT: ret i32 [[AND]] +; CHECK-NEXT: ret i32 0 define i32 @fn1(i32 %a) { - %xor = add i32 %a, -1 - %mul = mul nsw i32 %xor, zext (i1 icmp eq (i32* getelementptr inbounds ([1 x i32]* @b, i64 0, i64 0), i32* @c) to i32) - ret i32 %mul + ret i32 0 } diff --git a/test/Transforms/LoopVectorize/if-conversion.ll b/test/Transforms/LoopVectorize/if-conversion.ll index dbe0243a811..6e3e8ed2785 100644 --- a/test/Transforms/LoopVectorize/if-conversion.ll +++ b/test/Transforms/LoopVectorize/if-conversion.ll @@ -156,7 +156,7 @@ for.body: br i1 icmp eq (i32** getelementptr inbounds ([1 x i32*]* @a, i64 0, i64 0), i32** @c), label %cond.false, label %cond.end cond.false: - %cond.1 = or i32 %inc3, sdiv (i32 1, i32 zext (i1 icmp eq (i32** getelementptr inbounds ([1 x i32*]* @a, i64 0, i64 0), i32** @c) to i32)) + %cond.1 = or i32 %inc3, sdiv (i32 1, i32 zext (i1 icmp eq (i32** getelementptr inbounds ([1 x i32*]* @a, i64 0, i64 1), i32** @c) to i32)) br label %cond.end cond.end: -- 2.34.1