From fd7b160a14d78a2fbf2ab8dbc08ceba9d4dc846d Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 16 Dec 2015 19:06:41 +0000 Subject: [PATCH] [WebAssembly] Fix the CFG Stackifier to handle unoptimized branches If a branch both branches to and falls through to the same block, treat it as an explicit branch. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@255803 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../WebAssembly/WebAssemblyCFGStackify.cpp | 16 ++++++- test/CodeGen/WebAssembly/cfg-stackify.ll | 46 +++++++++++++++++++ 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp b/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp index 6412442176d..6ac53662359 100644 --- a/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp +++ b/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp @@ -251,6 +251,19 @@ static void SortBlocks(MachineFunction &MF, const MachineLoopInfo &MLI) { #endif } +/// Test whether Pred has any terminators explicitly branching to MBB, as +/// opposed to falling through. Note that it's possible (eg. in unoptimized +/// code) for a branch instruction to both branch to a block and fallthrough +/// to it, so we check the actual branch operands to see if there are any +/// explicit mentions. +static bool ExplicitlyBranchesTo(MachineBasicBlock *Pred, MachineBasicBlock *MBB) { + for (MachineInstr &MI : Pred->terminators()) + for (MachineOperand &MO : MI.explicit_operands()) + if (MO.isMBB() && MO.getMBB() == MBB) + return true; + return false; +} + /// Insert a BLOCK marker for branches to MBB (if needed). static void PlaceBlockMarker(MachineBasicBlock &MBB, MachineFunction &MF, SmallVectorImpl &ScopeTops, @@ -266,8 +279,7 @@ static void PlaceBlockMarker(MachineBasicBlock &MBB, MachineFunction &MF, for (MachineBasicBlock *Pred : MBB.predecessors()) if (Pred->getNumber() < MBBNumber) { Header = Header ? MDT.findNearestCommonDominator(Header, Pred) : Pred; - if (!Pred->isLayoutSuccessor(&MBB) || - !(Pred->empty() || !Pred->back().isBarrier())) + if (ExplicitlyBranchesTo(Pred, &MBB)) IsBranchedTo = true; } if (!Header) diff --git a/test/CodeGen/WebAssembly/cfg-stackify.ll b/test/CodeGen/WebAssembly/cfg-stackify.ll index 7717f35fec0..a10fb614909 100644 --- a/test/CodeGen/WebAssembly/cfg-stackify.ll +++ b/test/CodeGen/WebAssembly/cfg-stackify.ll @@ -1054,3 +1054,49 @@ bb4: bb7: ret void } + +; A block can be "branched to" from another even if it is also reachable via +; fallthrough from the other. This would normally be optimized away, so use +; optnone to disable optimizations to test this case. + +; CHECK-LABEL: test13: +; CHECK-NEXT: .local i32{{$}} +; CHECK: block BB22_2{{$}} +; CHECK: br_if $pop4, BB22_2{{$}} +; CHECK-NEXT: return{{$}} +; CHECK-NEXT: BB22_2: +; CHECK: block BB22_4{{$}} +; CHECK-NEXT: br_if $0, BB22_4{{$}} +; CHECK: BB22_4: +; CHECK: block BB22_5{{$}} +; CHECK: br_if $pop6, BB22_5{{$}} +; CHECK-NEXT: BB22_5: +; CHECK-NEXT: unreachable{{$}} +; OPT-LABEL: test13: +; OPT-NEXT: .local i32{{$}} +; OPT: block BB22_2{{$}} +; OPT: br_if $pop4, BB22_2{{$}} +; OPT-NEXT: return{{$}} +; OPT-NEXT: BB22_2: +; OPT: block BB22_4{{$}} +; OPT-NEXT: br_if $0, BB22_4{{$}} +; OPT: BB22_4: +; OPT: block BB22_5{{$}} +; OPT: br_if $pop6, BB22_5{{$}} +; OPT-NEXT: BB22_5: +; OPT-NEXT: unreachable{{$}} +define void @test13() noinline optnone { +bb: + br i1 undef, label %bb5, label %bb2 +bb1: + unreachable +bb2: + br i1 undef, label %bb3, label %bb4 +bb3: + br label %bb4 +bb4: + %tmp = phi i1 [ false, %bb2 ], [ false, %bb3 ] + br i1 %tmp, label %bb1, label %bb1 +bb5: + ret void +} -- 2.34.1