Index: lib/Transforms/Scalar/GVN.cpp =================================================================== --- lib/Transforms/Scalar/GVN.cpp +++ lib/Transforms/Scalar/GVN.cpp @@ -2189,9 +2189,25 @@ unsigned NumWithout = 0; BasicBlock *PREPred = nullptr; BasicBlock *CurrentBlock = CurInst->getParent(); + bool IsSafeToSpeculativelyExecute = isSafeToSpeculativelyExecute(CurInst); + + // Make sure that there are no instructions with implicit control flow that + // could prevent us from reaching our instruction. + if (!IsSafeToSpeculativelyExecute) { + auto It = FirstImplicitControlFlowInsts.find(CurrentBlock); + if (It != FirstImplicitControlFlowInsts.end()) { + assert(It->second->getParent() == CurrentBlock && + "Implicit control flow map broken?"); + if (OI->dominates(It->second, CurInst)) + return false; + } + } SmallVector, 8> predMap; for (BasicBlock *P : predecessors(CurrentBlock)) { + // Don't PRE across predecessors with implicit control flow. + if (!IsSafeToSpeculativelyExecute && FirstImplicitControlFlowInsts.count(P)) + return false; // We're not interested in PRE where blocks with predecessors that are // not reachable. if (!DT->isReachableFromEntry(P)) { Index: test/Transforms/GVN/PRE/local-pre.ll =================================================================== --- test/Transforms/GVN/PRE/local-pre.ll +++ test/Transforms/GVN/PRE/local-pre.ll @@ -1,6 +1,13 @@ ; RUN: opt < %s -gvn -enable-pre -S | FileCheck %s +declare void @may_exit() nounwind + +declare void @may_exit_1(i32) nounwind + define i32 @main(i32 %p, i32 %q) { + +; CHECK-LABEL: @main( + block1: %cmp = icmp eq i32 %p, %q br i1 %cmp, label %block2, label %block3 @@ -20,3 +27,92 @@ ; CHECK: %b.pre-phi = phi i32 [ %.pre, %block3 ], [ %a, %block2 ] ; CHECK-NEXT: ret i32 %b.pre-phi } + +; Don't PRE across implicit control flow. +define i32 @test2(i32 %p, i32 %q) { + +; CHECK-LABEL: @test2 +; CHECK: block1: + +block1: + %cmp = icmp eq i32 %p, %q + br i1 %cmp, label %block2, label %block3 + +block2: + %a = sdiv i32 %p, %q + br label %block4 + +block3: + br label %block4 + +; CHECK: block4: +; CHECK-NEXT: call void @may_exit( +; CHECK-NEXT: %b = sdiv +; CHECK-NEXT: ret i32 %b + +block4: + call void @may_exit() nounwind + %b = sdiv i32 %p, %q + ret i32 %b +} + +; Don't PRE across implicit control flow. +define i32 @test3(i32 %p, i32 %q, i1 %r) { + +; CHECK-LABEL: @test3 +; CHECK: block1: + +block1: + br i1 %r, label %block2, label %block3 + +block2: + %a = sdiv i32 %p, %q + br label %block4 + +block3: + br label %block4 + +block4: + +; CHECK: block4: +; CHECK-NEXT: phi i32 +; CHECK-NEXT: call void @may_exit_1( +; CHECK-NEXT: %b = sdiv +; CHECK-NEXT: ret i32 %b + + %phi = phi i32 [ 0, %block3 ], [ %a, %block2 ] + call void @may_exit_1(i32 %phi) nounwind + %b = sdiv i32 %p, %q + ret i32 %b + +} + +; It's OK to PRE an instruction that is guaranteed to be safe to execute +; speculatively. +; TODO: Does it make any sense in this case? +define i32 @test4(i32 %p, i32 %q) { + +; CHECK-LABEL: @test4 +; CHECK: block1: + +block1: + %cmp = icmp eq i32 %p, %q + br i1 %cmp, label %block2, label %block3 + +block2: + %a = sdiv i32 %p, 6 + br label %block4 + +block3: + br label %block4 + +; CHECK: block4: +; CHECK-NEXT: %b.pre-phi = phi i32 +; CHECK-NEXT: call void @may_exit( +; CHECK-NEXT: ret i32 %b + +block4: + call void @may_exit() nounwind + %b = sdiv i32 %p, 6 + ret i32 %b +}