Index: lib/Transforms/Scalar/GVN.cpp =================================================================== --- lib/Transforms/Scalar/GVN.cpp +++ lib/Transforms/Scalar/GVN.cpp @@ -2255,6 +2255,21 @@ Instruction *PREInstr = nullptr; if (NumWithout != 0) { + bool IsSafeToSpeculativelyExecute = isSafeToSpeculativelyExecute(CurInst); + if (!IsSafeToSpeculativelyExecute) { + // It is only valid to insert a new instruction if the current instruction + // is always executed. An instruction with implicit control flow could + // prevent us from doing it. If we cannot speculate the execution, then + // PRE should be prohibited. + 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; + } + } + // Don't do PRE across indirect branch. if (isa(PREPred->getTerminator())) return false; 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,121 @@ ; 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 +} + +; It is OK to PRE across implicit control flow if we don't insert new +; instructions. +define i32 @test5(i1 %cond, i32 %p, i32 %q) { + +; CHECK-LABEL: @test5 +; CHECK: block1: + +block1: + br i1 %cond, label %block2, label %block3 + +block2: + %a = sdiv i32 %p, %q + br label %block4 + +block3: + %b = sdiv i32 %p, %q + br label %block4 + +; CHECK: block4: +; CHECK-NEXT: %c.pre-phi = phi i32 [ %b, %block3 ], [ %a, %block2 ] +; CHECK-NEXT: call void @may_exit() +; CHECK-NEXT: ret i32 %c.pre-phi + +block4: + call void @may_exit() nounwind + %c = sdiv i32 %p, %q + ret i32 %c +}