Index: lib/IR/ConstantFold.cpp =================================================================== --- lib/IR/ConstantFold.cpp +++ lib/IR/ConstantFold.cpp @@ -1334,6 +1334,15 @@ 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 @@ // 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 @@ } 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 @@ "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,13 @@ // 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. + 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 +1586,7 @@ } } } + } default: break; } Index: test/Other/constant-fold-gep.ll =================================================================== --- test/Other/constant-fold-gep.ll +++ test/Other/constant-fold-gep.ll @@ -467,4 +467,21 @@ ; 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 } Index: test/Transforms/InstCombine/2010-03-03-ExtElim.ll =================================================================== --- test/Transforms/InstCombine/2010-03-03-ExtElim.ll +++ test/Transforms/InstCombine/2010-03-03-ExtElim.ll @@ -22,11 +22,11 @@ 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 } Index: test/Transforms/InstCombine/pr20079.ll =================================================================== --- test/Transforms/InstCombine/pr20079.ll +++ 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 } Index: test/Transforms/LoopVectorize/if-conversion.ll =================================================================== --- test/Transforms/LoopVectorize/if-conversion.ll +++ test/Transforms/LoopVectorize/if-conversion.ll @@ -156,7 +156,7 @@ 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: