From 5aafb6def54fc6f4de28e1bccc42a036ca8e33bf Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Mon, 23 Nov 2015 19:12:37 +0000 Subject: [PATCH] [WebAssembly] Always print loop end labels WebAssembly is currently using labels to end scopes, so for example a loop scope looks like this: BB0_0: loop BB0_1 ... BB0_1: with BB0_0 being the label of the first block not in the loop. This requires that the label be printed even when it's only reachable via fallthrough. To arrange this, insert a no-op LOOP_END instruction in such cases at the end of the loop. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@253901 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp | 4 ++++ lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp | 12 +++++++++++- lib/Target/WebAssembly/WebAssemblyInstrControl.td | 5 +++++ test/CodeGen/WebAssembly/cfg-stackify.ll | 3 +++ 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp index c452e1dd024..f7f37ee8c89 100644 --- a/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp +++ b/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp @@ -221,6 +221,10 @@ void WebAssemblyAsmPrinter::EmitInstruction(const MachineInstr *MI) { // These represent values which are live into the function entry, so there's // no instruction to emit. break; + case WebAssembly::LOOP_END: + // This is a no-op which just exists to tell AsmPrinter.cpp that there's a + // fallthrough which nevertheless requires a label for the destination here. + break; default: { WebAssemblyMCInstLower MCInstLowering(OutContext, *this); MCInst TmpInst; diff --git a/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp b/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp index 78e15f036b2..2ec1ea5f65a 100644 --- a/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp +++ b/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp @@ -289,11 +289,21 @@ static void PlaceMarkers(MachineFunction &MF, const MachineLoopInfo &MLI, MachineBasicBlock *Bottom = Loop->getBottomBlock(); auto Iter = next(MachineFunction::iterator(Bottom)); if (Iter == MF.end()) { - MF.push_back(MF.CreateMachineBasicBlock()); + MachineBasicBlock *Label = MF.CreateMachineBasicBlock(); + // Give it a fake predecessor so that AsmPrinter prints its label. + Label->addSuccessor(Label); + MF.push_back(Label); Iter = next(MachineFunction::iterator(Bottom)); } BuildMI(MBB, MBB.begin(), DebugLoc(), TII.get(WebAssembly::LOOP)) .addMBB(&*Iter); + + // Emit a special no-op telling the asm printer that we need a label + // to close the loop scope, even though the destination is only + // reachable by fallthrough. + if (!Bottom->back().isBarrier()) + BuildMI(*Bottom, Bottom->end(), DebugLoc(), + TII.get(WebAssembly::LOOP_END)); } // Place the BLOCK for MBB if MBB is branched to from above. diff --git a/lib/Target/WebAssembly/WebAssemblyInstrControl.td b/lib/Target/WebAssembly/WebAssemblyInstrControl.td index 92393d435c2..7fa4c5613e9 100644 --- a/lib/Target/WebAssembly/WebAssemblyInstrControl.td +++ b/lib/Target/WebAssembly/WebAssemblyInstrControl.td @@ -39,6 +39,11 @@ def TABLESWITCH_I64 : I<(outs), (ins I64:$index, variable_ops), def BLOCK : I<(outs), (ins bb_op:$dst), [], "block \t$dst">; def LOOP : I<(outs), (ins bb_op:$dst), [], "loop \t$dst">; +// No-op to indicate to the AsmPrinter that a loop ends here, so a +// basic block label is needed even if it wouldn't otherwise appear so. +let isTerminator = 1, hasCtrlDep = 1 in +def LOOP_END : I<(outs), (ins), []>; + multiclass RETURN { def RETURN_#vt : I<(outs), (ins vt:$val), [(WebAssemblyreturn vt:$val)], "return \t$val">; diff --git a/test/CodeGen/WebAssembly/cfg-stackify.ll b/test/CodeGen/WebAssembly/cfg-stackify.ll index cac98199215..e62a8c88ef9 100644 --- a/test/CodeGen/WebAssembly/cfg-stackify.ll +++ b/test/CodeGen/WebAssembly/cfg-stackify.ll @@ -186,6 +186,7 @@ entry: ; CHECK: BB7_1: ; CHECK: i32.store $0, $pop{{[0-9]+}}{{$}} ; CHECK: br BB7_1{{$}} +; CHECK: BB7_2: define i32 @minimal_loop(i32* %p) { entry: store volatile i32 0, i32* %p @@ -200,6 +201,7 @@ loop: ; CHECK: BB8_1: ; CHECK: loop BB8_2{{$}} ; CHECK: br_if $pop{{[0-9]+}}, BB8_1{{$}} +; CHECK: BB8_2: ; CHECK: return ${{[0-9]+}}{{$}} define i32 @simple_loop(i32* %p, i32 %a) { entry: @@ -285,6 +287,7 @@ exit: ; CHECK: BB11_5: ; CHECK: BB11_6: ; CHECK: br BB11_1{{$}} +; CHECK: BB11_7: define i32 @doublediamond_in_a_loop(i32 %a, i32 %b, i32* %p) { entry: br label %header