[WebAssembly] Always print loop end labels
authorDan Gohman <dan433584@gmail.com>
Mon, 23 Nov 2015 19:12:37 +0000 (19:12 +0000)
committerDan Gohman <dan433584@gmail.com>
Mon, 23 Nov 2015 19:12:37 +0000 (19:12 +0000)
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
lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
lib/Target/WebAssembly/WebAssemblyInstrControl.td
test/CodeGen/WebAssembly/cfg-stackify.ll

index c452e1dd024422a91b9234cd109445500b5d8a37..f7f37ee8c8946e23e1d479550f6f37b847ce3c36 100644 (file)
@@ -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;
     // 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;
   default: {
     WebAssemblyMCInstLower MCInstLowering(OutContext, *this);
     MCInst TmpInst;
index 78e15f036b2e37a0f7f0004e6f4e5ff3b3563411..2ec1ea5f65aa7aab319ef67b95a07868f0d86ca0 100644 (file)
@@ -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()) {
         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);
           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.
       }
 
     // Place the BLOCK for MBB if MBB is branched to from above.
index 92393d435c251133e8bf226ce1714f17e030df1e..7fa4c5613e96f24778da191f92d347c14d8e79f9 100644 (file)
@@ -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">;
 
 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<WebAssemblyRegClass vt> {
   def RETURN_#vt : I<(outs), (ins vt:$val), [(WebAssemblyreturn vt:$val)],
                      "return  \t$val">;
 multiclass RETURN<WebAssemblyRegClass vt> {
   def RETURN_#vt : I<(outs), (ins vt:$val), [(WebAssemblyreturn vt:$val)],
                      "return  \t$val">;
index cac981992158c93e516e4794182a018d12920e0b..e62a8c88ef921295107ca349d864b7e421e1a4d0 100644 (file)
@@ -186,6 +186,7 @@ entry:
 ; CHECK: BB7_1:
 ; CHECK: i32.store $0, $pop{{[0-9]+}}{{$}}
 ; CHECK: br BB7_1{{$}}
 ; 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
 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_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:
 ; 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_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
 define i32 @doublediamond_in_a_loop(i32 %a, i32 %b, i32* %p) {
 entry:
   br label %header