Index: include/llvm/Transforms/Utils/Local.h =================================================================== --- include/llvm/Transforms/Utils/Local.h +++ include/llvm/Transforms/Utils/Local.h @@ -316,7 +316,7 @@ unsigned replaceDominatedUsesWith(Value *From, Value *To, DominatorTree &DT, const BasicBlockEdge &Edge); /// \brief Replace each use of 'From' with 'To' if that use is dominated by -/// the given BasicBlock. Returns the number of replacements made. +/// the end of the given BasicBlock. Returns the number of replacements made. unsigned replaceDominatedUsesWith(Value *From, Value *To, DominatorTree &DT, const BasicBlock *BB); Index: lib/Transforms/Scalar/GVN.cpp =================================================================== --- lib/Transforms/Scalar/GVN.cpp +++ lib/Transforms/Scalar/GVN.cpp @@ -2133,7 +2133,10 @@ /// The given values are known to be equal in every block /// dominated by 'Root'. Exploit this, for example by replacing 'LHS' with /// 'RHS' everywhere in the scope. Returns whether a change was made. -/// If DominatesByEdge is false, then it means that it is dominated by Root.End. +/// If DominatesByEdge is false, it means that there might be multiple edges +/// from Root.Start to Root.End, in which case we need to pass Root.Start and +/// use a different implementation of replaceDominatedUsesWith to test. +// bool GVN::propagateEquality(Value *LHS, Value *RHS, const BasicBlockEdge &Root, bool DominatesByEdge) { SmallVector, 4> Worklist; @@ -2195,7 +2198,7 @@ unsigned NumReplacements = DominatesByEdge ? replaceDominatedUsesWith(LHS, RHS, *DT, Root) - : replaceDominatedUsesWith(LHS, RHS, *DT, Root.getEnd()); + : replaceDominatedUsesWith(LHS, RHS, *DT, Root.getStart()); Changed |= NumReplacements > 0; NumGVNEqProp += NumReplacements; @@ -2271,7 +2274,7 @@ DominatesByEdge ? replaceDominatedUsesWith(NotCmp, NotVal, *DT, Root) : replaceDominatedUsesWith(NotCmp, NotVal, *DT, - Root.getEnd()); + Root.getStart()); Changed |= NumReplacements > 0; NumGVNEqProp += NumReplacements; } Index: lib/Transforms/Utils/Local.cpp =================================================================== --- lib/Transforms/Utils/Local.cpp +++ lib/Transforms/Utils/Local.cpp @@ -1537,7 +1537,7 @@ UI != UE;) { Use &U = *UI++; auto *I = cast(U.getUser()); - if (DT.dominates(BB, I->getParent())) { + if (DT.properlyDominates(BB, I->getParent())) { U.set(To); DEBUG(dbgs() << "Replace dominated use of '" << From->getName() << "' as " << *To << " in " << *U << "\n"); Index: test/Transforms/GVN/assume-equal.ll =================================================================== --- test/Transforms/GVN/assume-equal.ll +++ test/Transforms/GVN/assume-equal.ll @@ -226,6 +226,46 @@ ret i32 17 } +; This test checks if GVN can do the constant propagation correctly +; when there are multiple uses of the same assume value in the +; basic block that has a loop back-edge pointing to itself. +; +; CHECK-LABEL: define i32 @_Z1il(i32 %val, i1 %k) +define i32 @_Z1il(i32 %val, i1 %k) { + br label %next + +next: +; CHECK: tail call void @llvm.assume(i1 %k) +; CHECK-NEXT: %cmp = icmp eq i32 %val, 50 + tail call void @llvm.assume(i1 %k) + tail call void @llvm.assume(i1 %k) + %cmp = icmp eq i32 %val, 50 + br i1 %cmp, label %next, label %meh + +meh: + ret i32 0 +} + +; This test checks if GVN can prevent the constant propagation correctly +; in the successor blocks that are not dominated by the basic block +; with the assume instruction. +; +; CHECK-LABEL: define i1 @_z1im(i32 %val, i1 %k, i1 %j) +define i1 @_z1im(i32 %val, i1 %k, i1 %j) { + br i1 %j, label %next, label %meh + +next: +; CHECK: tail call void @llvm.assume(i1 %k) +; CHECK-NEXT: br label %meh + tail call void @llvm.assume(i1 %k) + tail call void @llvm.assume(i1 %k) + br label %meh + +meh: +; CHECK: ret i1 %k + ret i1 %k +} + declare noalias i8* @_Znwm(i64) declare void @_ZN1AC1Ev(%struct.A*) declare void @llvm.assume(i1)