Index: llvm/include/llvm/Transforms/Scalar/GVN.h =================================================================== --- llvm/include/llvm/Transforms/Scalar/GVN.h +++ llvm/include/llvm/Transforms/Scalar/GVN.h @@ -360,7 +360,7 @@ BasicBlock *splitCriticalEdges(BasicBlock *Pred, BasicBlock *Succ); bool replaceOperandsForInBlockEquality(Instruction *I) const; bool propagateEquality(Value *LHS, Value *RHS, const BasicBlockEdge &Root, - bool DominatesByEdge); + bool DominatesByEdge, const DataLayout &DL); bool processFoldableCondBr(BranchInst *BI); void addDeadBlock(BasicBlock *BB); void assignValNumForDeadCode(); Index: llvm/lib/Transforms/Scalar/GVN.cpp =================================================================== --- llvm/lib/Transforms/Scalar/GVN.cpp +++ llvm/lib/Transforms/Scalar/GVN.cpp @@ -33,6 +33,7 @@ #include "llvm/Analysis/GlobalsModRef.h" #include "llvm/Analysis/InstructionPrecedenceTracking.h" #include "llvm/Analysis/InstructionSimplify.h" +#include "llvm/Analysis/Loads.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/MemoryBuiltins.h" #include "llvm/Analysis/MemoryDependenceAnalysis.h" @@ -1926,7 +1927,8 @@ // This property is only true in dominated successors, propagateEquality // will check dominance for us. - Changed |= propagateEquality(V, True, Edge, false); + Changed |= propagateEquality(V, True, Edge, false, + IntrinsicI->getModule()->getDataLayout()); } // We can replace assume value with true, which covers cases like this: @@ -2270,7 +2272,7 @@ /// value starting from the end of Root.Start. bool GVNPass::propagateEquality(Value *LHS, Value *RHS, const BasicBlockEdge &Root, - bool DominatesByEdge) { + bool DominatesByEdge, const DataLayout &DL) { SmallVector, 4> Worklist; Worklist.push_back(std::make_pair(LHS, RHS)); bool Changed = false; @@ -2311,6 +2313,11 @@ } } + // Don't try to propagate equalities between noalias pointers. + if (isa(LHS->getType()) && + !canReplacePointersIfEqual(LHS, RHS, DL, nullptr, getAliasAnalysis())) + continue; + // If value numbering later sees that an instruction in the scope is equal // to 'LHS' then ensure it will be turned into 'RHS'. In order to preserve // the invariant that instructions only occur in the leader table for their @@ -2482,11 +2489,13 @@ Value *TrueVal = ConstantInt::getTrue(TrueSucc->getContext()); BasicBlockEdge TrueE(Parent, TrueSucc); - Changed |= propagateEquality(BranchCond, TrueVal, TrueE, true); + Changed |= propagateEquality(BranchCond, TrueVal, TrueE, true, + I->getModule()->getDataLayout()); Value *FalseVal = ConstantInt::getFalse(FalseSucc->getContext()); BasicBlockEdge FalseE(Parent, FalseSucc); - Changed |= propagateEquality(BranchCond, FalseVal, FalseE, true); + Changed |= propagateEquality(BranchCond, FalseVal, FalseE, true, + I->getModule()->getDataLayout()); return Changed; } @@ -2508,7 +2517,8 @@ // If there is only a single edge, propagate the case value into it. if (SwitchEdges.lookup(Dst) == 1) { BasicBlockEdge E(Parent, Dst); - Changed |= propagateEquality(SwitchCond, i->getCaseValue(), E, true); + Changed |= propagateEquality(SwitchCond, i->getCaseValue(), E, true, + I->getModule()->getDataLayout()); } } return Changed; Index: llvm/test/Transforms/GVN/condprop.ll =================================================================== --- llvm/test/Transforms/GVN/condprop.ll +++ llvm/test/Transforms/GVN/condprop.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -passes=gvn -S | FileCheck %s -@a = external global i32 ; [#uses=7] +@a = external global i32 ; [#uses=8] define i32 @test1() nounwind { ; CHECK-LABEL: @test1( @@ -563,23 +563,20 @@ ; CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds i32, ptr [[PTR1]], i32 2 ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: br i1 undef, label [[LOOP_IF1_CRIT_EDGE:%.*]], label [[THEN:%.*]] -; CHECK: loop.if1_crit_edge: -; CHECK-NEXT: [[VAL2_PRE:%.*]] = load i32, ptr [[GEP2]], align 4 -; CHECK-NEXT: br label [[IF1:%.*]] +; CHECK-NEXT: br i1 undef, label [[IF1:%.*]], label [[THEN:%.*]] ; CHECK: if1: -; CHECK-NEXT: [[VAL2:%.*]] = phi i32 [ [[VAL2_PRE]], [[LOOP_IF1_CRIT_EDGE]] ], [ [[VAL3:%.*]], [[LOOP_END:%.*]] ] +; CHECK-NEXT: [[VAL2:%.*]] = load i32, ptr [[GEP2]], align 4 ; CHECK-NEXT: store i32 [[VAL2]], ptr [[GEP2]], align 4 ; CHECK-NEXT: store i32 0, ptr [[GEP1]], align 4 ; CHECK-NEXT: br label [[THEN]] ; CHECK: then: ; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[GEP2]], [[PTR2:%.*]] -; CHECK-NEXT: br i1 [[CMP]], label [[LOOP_END]], label [[IF2:%.*]] +; CHECK-NEXT: br i1 [[CMP]], label [[LOOP_END:%.*]], label [[IF2:%.*]] ; CHECK: if2: ; CHECK-NEXT: br label [[LOOP_END]] ; CHECK: loop.end: -; CHECK-NEXT: [[PHI3:%.*]] = phi ptr [ [[PTR2]], [[THEN]] ], [ [[PTR1]], [[IF2]] ] -; CHECK-NEXT: [[VAL3]] = load i32, ptr [[GEP2]], align 4 +; CHECK-NEXT: [[PHI3:%.*]] = phi ptr [ [[GEP2]], [[THEN]] ], [ [[PTR1]], [[IF2]] ] +; CHECK-NEXT: [[VAL3:%.*]] = load i32, ptr [[GEP2]], align 4 ; CHECK-NEXT: store i32 [[VAL3]], ptr [[PHI3]], align 4 ; CHECK-NEXT: br i1 undef, label [[LOOP]], label [[IF1]] ; @@ -613,3 +610,34 @@ %gep3 = getelementptr inbounds i32, ptr %ptr1, i32 1 br i1 undef, label %loop, label %if1 } + +; Make sure we dont return 1. +define i32 @test15(ptr noalias %p, i64 %i) { +; CHECK-LABEL: @test15( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[I:%.*]] +; CHECK-NEXT: store i32 1, ptr [[ARRAYIDX]], align 4 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[P]], @a +; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] +; CHECK: if.then: +; CHECK-NEXT: store i32 2, ptr [[P]], align 4 +; CHECK-NEXT: [[DOTPRE:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ [[DOTPRE]], [[IF_THEN]] ], [ 1, [[ENTRY:%.*]] ] +; CHECK-NEXT: ret i32 [[TMP0]] +; +entry: + %arrayidx = getelementptr inbounds i32, ptr %p, i64 %i + store i32 1, ptr %arrayidx, align 4 + %cmp = icmp eq ptr %p, @a + br i1 %cmp, label %if.then, label %if.end + +if.then: + store i32 2, ptr %p, align 4 + br label %if.end + +if.end: + %0 = load i32, ptr %arrayidx, align 4 + ret i32 %0 +}