diff --git a/llvm/lib/Transforms/Scalar/GVN.cpp b/llvm/lib/Transforms/Scalar/GVN.cpp --- a/llvm/lib/Transforms/Scalar/GVN.cpp +++ b/llvm/lib/Transforms/Scalar/GVN.cpp @@ -1494,14 +1494,6 @@ return false; } - // FIXME: Can we support the fallthrough edge? - if (isa(Pred->getTerminator())) { - LLVM_DEBUG( - dbgs() << "COULD NOT PRE LOAD BECAUSE OF CALLBR CRITICAL EDGE '" - << Pred->getName() << "': " << *Load << '\n'); - return false; - } - if (LoadBB->isEHPad()) { LLVM_DEBUG( dbgs() << "COULD NOT PRE LOAD BECAUSE OF AN EH PAD CRITICAL EDGE '" @@ -2875,11 +2867,6 @@ if (isa(PREPred->getTerminator())) return false; - // Don't do PRE across callbr. - // FIXME: Can we do this across the fallthrough edge? - if (isa(PREPred->getTerminator())) - return false; - // We can't do PRE safely on a critical edge, so instead we schedule // the edge to be split and perform the PRE the next time we iterate // on the function. diff --git a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp --- a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp +++ b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp @@ -769,8 +769,7 @@ unsigned NumBroken = 0; for (BasicBlock &BB : F) { Instruction *TI = BB.getTerminator(); - if (TI->getNumSuccessors() > 1 && !isa(TI) && - !isa(TI)) + if (TI->getNumSuccessors() > 1 && !isa(TI)) for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i) if (SplitCriticalEdge(TI, i, Options)) ++NumBroken; diff --git a/llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp b/llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp --- a/llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp +++ b/llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp @@ -129,8 +129,7 @@ SmallVector LoopPreds; // Check if extra modifications will be required to preserve loop-simplify // form after splitting. If it would require splitting blocks with IndirectBr - // or CallBr terminators, bail out if preserving loop-simplify form is - // requested. + // terminators, bail out if preserving loop-simplify form is requested. if (LI) { if (Loop *TIL = LI->getLoopFor(TIBB)) { @@ -156,10 +155,7 @@ // Loop-simplify form can be preserved, if we can split all in-loop // predecessors. if (any_of(LoopPreds, [](BasicBlock *Pred) { - const Instruction *T = Pred->getTerminator(); - if (const auto *CBR = dyn_cast(T)) - return CBR->getDefaultDest() != Pred; - return isa(T); + return isa(Pred->getTerminator()); })) { if (Options.PreserveLoopSimplify) return nullptr; diff --git a/llvm/test/Transforms/GVN/callbr-loadpre-critedge.ll b/llvm/test/Transforms/GVN/callbr-loadpre-critedge.ll --- a/llvm/test/Transforms/GVN/callbr-loadpre-critedge.ll +++ b/llvm/test/Transforms/GVN/callbr-loadpre-critedge.ll @@ -9,19 +9,22 @@ define void @widget(%struct.pluto** %tmp1) { ; CHECK-LABEL: @widget( ; CHECK-NEXT: bb: -; CHECK-NEXT: callbr void asm sideeffect "", "i,i"(i8* blockaddress(@widget, [[BB5:%.*]]), i8* blockaddress(@widget, [[BB8:%.*]])) -; CHECK-NEXT: to label [[BB4:%.*]] [label [[BB5]], label %bb8] +; CHECK-NEXT: callbr void asm sideeffect "", "i,i"(i8* blockaddress(@widget, [[BB5:%.*]]), i8* blockaddress(@widget, [[BB_BB8_CRIT_EDGE:%.*]])) +; CHECK-NEXT: to label [[BB4:%.*]] [label [[BB5]], label %bb.bb8_crit_edge] +; CHECK: bb.bb8_crit_edge: +; CHECK-NEXT: [[TMP10_PRE:%.*]] = load %struct.pluto*, %struct.pluto** [[TMP1:%.*]], align 8 +; CHECK-NEXT: br label [[BB8:%.*]] ; CHECK: bb4: ; CHECK-NEXT: br label [[BB5]] ; CHECK: bb5: -; CHECK-NEXT: [[TMP6:%.*]] = load %struct.pluto*, %struct.pluto** [[TMP1:%.*]] +; CHECK-NEXT: [[TMP6:%.*]] = load %struct.pluto*, %struct.pluto** [[TMP1]], align 8 ; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT_PLUTO:%.*]], %struct.pluto* [[TMP6]], i64 0, i32 1 ; CHECK-NEXT: br label [[BB8]] ; CHECK: bb8: -; CHECK-NEXT: [[TMP9:%.*]] = phi i8* [ [[TMP7]], [[BB5]] ], [ null, [[BB:%.*]] ] -; CHECK-NEXT: [[TMP10:%.*]] = load %struct.pluto*, %struct.pluto** [[TMP1]] +; CHECK-NEXT: [[TMP10:%.*]] = phi %struct.pluto* [ [[TMP6]], [[BB5]] ], [ [[TMP10_PRE]], [[BB_BB8_CRIT_EDGE]] ] +; CHECK-NEXT: [[TMP9:%.*]] = phi i8* [ [[TMP7]], [[BB5]] ], [ null, [[BB_BB8_CRIT_EDGE]] ] ; CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT_PLUTO]], %struct.pluto* [[TMP10]], i64 0, i32 0 -; CHECK-NEXT: [[TMP12:%.*]] = load i8, i8* [[TMP11]] +; CHECK-NEXT: [[TMP12:%.*]] = load i8, i8* [[TMP11]], align 1 ; CHECK-NEXT: tail call void @spam(i8* [[TMP9]], i8 [[TMP12]]) ; CHECK-NEXT: ret void ; diff --git a/llvm/test/Transforms/GVN/callbr-scalarpre-critedge.ll b/llvm/test/Transforms/GVN/callbr-scalarpre-critedge.ll --- a/llvm/test/Transforms/GVN/callbr-scalarpre-critedge.ll +++ b/llvm/test/Transforms/GVN/callbr-scalarpre-critedge.ll @@ -8,8 +8,11 @@ ; CHECK-LABEL: @wombat( ; CHECK-NEXT: bb: ; CHECK-NEXT: [[TMP5:%.*]] = or i64 [[ARG2:%.*]], [[ARG:%.*]] -; CHECK-NEXT: callbr void asm sideeffect "", "i,i"(i8* blockaddress(@wombat, [[BB7:%.*]]), i8* blockaddress(@wombat, [[BB9:%.*]])) -; CHECK-NEXT: to label [[BB6:%.*]] [label [[BB7]], label %bb9] +; CHECK-NEXT: callbr void asm sideeffect "", "i,i"(i8* blockaddress(@wombat, [[BB7:%.*]]), i8* blockaddress(@wombat, [[BB_BB9_CRIT_EDGE:%.*]])) +; CHECK-NEXT: to label [[BB6:%.*]] [label [[BB7]], label %bb.bb9_crit_edge] +; CHECK: bb.bb9_crit_edge: +; CHECK-NEXT: [[DOTPRE:%.*]] = trunc i64 [[TMP5]] to i32 +; CHECK-NEXT: br label [[BB9:%.*]] ; CHECK: bb6: ; CHECK-NEXT: br label [[BB7]] ; CHECK: bb7: @@ -17,14 +20,14 @@ ; CHECK-NEXT: tail call void @barney(i32 [[TMP8]]) ; CHECK-NEXT: br label [[BB9]] ; CHECK: bb9: -; CHECK-NEXT: [[TMP10:%.*]] = trunc i64 [[TMP5]] to i32 -; CHECK-NEXT: store i32 [[TMP10]], i32* [[ARG3:%.*]] +; CHECK-NEXT: [[TMP10_PRE_PHI:%.*]] = phi i32 [ [[DOTPRE]], [[BB_BB9_CRIT_EDGE]] ], [ [[TMP8]], [[BB7]] ] +; CHECK-NEXT: store i32 [[TMP10_PRE_PHI]], i32* [[ARG3:%.*]], align 4 ; CHECK-NEXT: ret void ; bb: %tmp5 = or i64 %arg2, %arg callbr void asm sideeffect "", "i,i"(i8* blockaddress(@wombat, %bb7), i8* blockaddress(@wombat, %bb9)) - to label %bb6 [label %bb7, label %bb9] + to label %bb6 [label %bb7, label %bb9] bb6: ; preds = %bb br label %bb7 diff --git a/llvm/test/Transforms/LoopStrengthReduce/callbr-critical-edge-splitting.ll b/llvm/test/Transforms/LoopStrengthReduce/callbr-critical-edge-splitting.ll --- a/llvm/test/Transforms/LoopStrengthReduce/callbr-critical-edge-splitting.ll +++ b/llvm/test/Transforms/LoopStrengthReduce/callbr-critical-edge-splitting.ll @@ -9,8 +9,8 @@ ; LEGACYPM-NEXT: entry: ; LEGACYPM-NEXT: br label [[FOR_COND:%.*]] ; LEGACYPM: for.cond: -; LEGACYPM-NEXT: callbr void asm sideeffect "", "i,i,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@test1, [[COND_TRUE_I:%.*]]), i8* blockaddress(@test1, [[FOR_END:%.*]])) -; LEGACYPM-NEXT: to label [[ASM_FALLTHROUGH_I_I:%.*]] [label [[COND_TRUE_I]], label %for.end] +; LEGACYPM-NEXT: callbr void asm sideeffect "", "i,i,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@test1, [[COND_TRUE_I:%.*]]), i8* blockaddress(@test1, [[FOR_ENDSPLIT:%.*]])) +; LEGACYPM-NEXT: to label [[ASM_FALLTHROUGH_I_I:%.*]] [label [[COND_TRUE_I]], label %for.endsplit] ; LEGACYPM: asm.fallthrough.i.i: ; LEGACYPM-NEXT: unreachable ; LEGACYPM: cond.true.i: @@ -20,11 +20,15 @@ ; LEGACYPM-NEXT: [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], 1 ; LEGACYPM-NEXT: br i1 true, label [[DO_BODY_I_I_RDRAND_INT_EXIT_I_CRIT_EDGE:%.*]], label [[DO_BODY_I_I_DO_BODY_I_I_CRIT_EDGE]] ; LEGACYPM: do.body.i.i.rdrand_int.exit.i_crit_edge: -; LEGACYPM-NEXT: br i1 true, label [[FOR_END]], label [[FOR_INC:%.*]] +; LEGACYPM-NEXT: br i1 true, label [[DO_BODY_I_I_RDRAND_INT_EXIT_I_CRIT_EDGE_FOR_END_CRIT_EDGE:%.*]], label [[FOR_INC:%.*]] +; LEGACYPM: do.body.i.i.rdrand_int.exit.i_crit_edge.for.end_crit_edge: +; LEGACYPM-NEXT: br label [[FOR_END:%.*]] ; LEGACYPM: for.inc: ; LEGACYPM-NEXT: br label [[FOR_COND]] +; LEGACYPM: for.endsplit: +; LEGACYPM-NEXT: br label [[FOR_END]] ; LEGACYPM: for.end: -; LEGACYPM-NEXT: [[PGOCOUNT_PROMOTED24:%.*]] = phi i64 [ undef, [[FOR_COND]] ], [ [[LSR_IV_NEXT]], [[DO_BODY_I_I_RDRAND_INT_EXIT_I_CRIT_EDGE]] ] +; LEGACYPM-NEXT: [[PGOCOUNT_PROMOTED24:%.*]] = phi i64 [ [[LSR_IV_NEXT]], [[DO_BODY_I_I_RDRAND_INT_EXIT_I_CRIT_EDGE_FOR_END_CRIT_EDGE]] ], [ undef, [[FOR_ENDSPLIT]] ] ; LEGACYPM-NEXT: ret i32 undef ; ; NEWPM-LABEL: @test1(