[WebAssembly] Make CFG stackification independent of basic-block labels.
authorDan Gohman <dan433584@gmail.com>
Tue, 12 Jan 2016 19:14:46 +0000 (19:14 +0000)
committerDan Gohman <dan433584@gmail.com>
Tue, 12 Jan 2016 19:14:46 +0000 (19:14 +0000)
This patch changes the way labels are referenced. Instead of referencing the
basic-block label name (eg. .LBB0_0), instructions now just have an immediate
which indicates the depth in the control-flow stack to find a label to jump to.
This makes them much closer to what we expect to have in the binary encoding,
and avoids the problem of basic-block label names not being explicit in the
binary encoding.

Also, it terminates blocks and loops with end_block and end_loop instructions,
rather than basic-block label names, for similar reasons.

This will also fix problems where two constructs appear to have the same label,
because we no longer explicitly use labels, so consumers that need labels will
presumably create their own labels, and presumably they won't reuse labels
when they do.

This patch does make the code a little more awkward to read; as a partial
mitigation, this patch also introduces comments showing where the labels are,
and comments on each branch showing where it's branching to.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@257505 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp
lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.h
lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h
lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
lib/Target/WebAssembly/WebAssemblyInstrControl.td
lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp
lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
test/CodeGen/WebAssembly/cfg-stackify.ll
test/CodeGen/WebAssembly/reg-stackify.ll
test/CodeGen/WebAssembly/switch.ll

index f92a9d0c6615f2e99bfec7f408ebde2a8463d556..60e52015242336a936ba51fd8516b2a015951f18 100644 (file)
@@ -16,6 +16,8 @@
 #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
 #include "WebAssembly.h"
 #include "WebAssemblyMachineFunctionInfo.h"
 #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
 #include "WebAssembly.h"
 #include "WebAssemblyMachineFunctionInfo.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/StringExtras.h"
 #include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCInst.h"
 #include "llvm/MC/MCInstrInfo.h"
 #include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCInst.h"
 #include "llvm/MC/MCInstrInfo.h"
@@ -33,7 +35,7 @@ using namespace llvm;
 WebAssemblyInstPrinter::WebAssemblyInstPrinter(const MCAsmInfo &MAI,
                                                const MCInstrInfo &MII,
                                                const MCRegisterInfo &MRI)
 WebAssemblyInstPrinter::WebAssemblyInstPrinter(const MCAsmInfo &MAI,
                                                const MCInstrInfo &MII,
                                                const MCRegisterInfo &MRI)
-    : MCInstPrinter(MAI, MII, MRI) {}
+    : MCInstPrinter(MAI, MII, MRI), ControlFlowCounter(0) {}
 
 void WebAssemblyInstPrinter::printRegName(raw_ostream &OS,
                                           unsigned RegNo) const {
 
 void WebAssemblyInstPrinter::printRegName(raw_ostream &OS,
                                           unsigned RegNo) const {
@@ -59,6 +61,52 @@ void WebAssemblyInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
 
   // Print any added annotation.
   printAnnotation(OS, Annot);
 
   // Print any added annotation.
   printAnnotation(OS, Annot);
+
+  if (CommentStream) {
+    // Observe any effects on the control flow stack, for use in annotating
+    // control flow label references.
+    switch (MI->getOpcode()) {
+    default:
+      break;
+    case WebAssembly::LOOP: {
+      // Grab the TopLabel value first so that labels print in numeric order.
+      uint64_t TopLabel = ControlFlowCounter++;
+      ControlFlowStack.push_back(std::make_pair(ControlFlowCounter++, false));
+      printAnnotation(OS, "label" + utostr(TopLabel) + ':');
+      ControlFlowStack.push_back(std::make_pair(TopLabel, true));
+      break;
+    }
+    case WebAssembly::BLOCK:
+      ControlFlowStack.push_back(std::make_pair(ControlFlowCounter++, false));
+      break;
+    case WebAssembly::END_LOOP:
+      ControlFlowStack.pop_back();
+      printAnnotation(
+          OS, "label" + utostr(ControlFlowStack.pop_back_val().first) + ':');
+      break;
+    case WebAssembly::END_BLOCK:
+      printAnnotation(
+          OS, "label" + utostr(ControlFlowStack.pop_back_val().first) + ':');
+      break;
+    }
+
+    // Annotate any control flow label references.
+    unsigned NumFixedOperands = Desc.NumOperands;
+    SmallSet<uint64_t, 8> Printed;
+    for (unsigned i = 0, e = MI->getNumOperands(); i < e; ++i) {
+      const MCOperandInfo &Info = Desc.OpInfo[i];
+      if (!(i < NumFixedOperands
+                ? (Info.OperandType == WebAssembly::OPERAND_BASIC_BLOCK)
+                : (Desc.TSFlags & WebAssemblyII::VariableOpImmediateIsLabel)))
+        continue;
+      uint64_t Depth = MI->getOperand(i).getImm();
+      if (!Printed.insert(Depth).second)
+        continue;
+      const auto &Pair = ControlFlowStack.rbegin()[Depth];
+      printAnnotation(OS, utostr(Depth) + ": " + (Pair.second ? "up" : "down") +
+                              " to label" + utostr(Pair.first));
+    }
+  }
 }
 
 static std::string toString(const APFloat &FP) {
 }
 
 static std::string toString(const APFloat &FP) {
@@ -100,7 +148,7 @@ void WebAssemblyInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
   } else if (Op.isImm()) {
     assert((OpNo < MII.get(MI->getOpcode()).getNumOperands() ||
             (MII.get(MI->getOpcode()).TSFlags &
   } else if (Op.isImm()) {
     assert((OpNo < MII.get(MI->getOpcode()).getNumOperands() ||
             (MII.get(MI->getOpcode()).TSFlags &
-                     WebAssemblyII::VariableOpIsImmediate)) &&
+             WebAssemblyII::VariableOpIsImmediate)) &&
            "WebAssemblyII::VariableOpIsImmediate should be set for "
            "variable_ops immediate ops");
     if (MII.get(MI->getOpcode()).TSFlags &
            "WebAssemblyII::VariableOpIsImmediate should be set for "
            "variable_ops immediate ops");
     if (MII.get(MI->getOpcode()).TSFlags &
@@ -117,7 +165,7 @@ void WebAssemblyInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
   } else {
     assert((OpNo < MII.get(MI->getOpcode()).getNumOperands() ||
             (MII.get(MI->getOpcode()).TSFlags &
   } else {
     assert((OpNo < MII.get(MI->getOpcode()).getNumOperands() ||
             (MII.get(MI->getOpcode()).TSFlags &
-                     WebAssemblyII::VariableOpIsImmediate)) &&
+             WebAssemblyII::VariableOpIsImmediate)) &&
            "WebAssemblyII::VariableOpIsImmediate should be set for "
            "variable_ops expr ops");
     assert(Op.isExpr() && "unknown operand kind in printOperand");
            "WebAssemblyII::VariableOpIsImmediate should be set for "
            "variable_ops expr ops");
     assert(Op.isExpr() && "unknown operand kind in printOperand");
index 39a16f59fd7849d85043426217291ac72d9256d0..cd6c59a41c3322ce1869363c2ffe2b1eb65de1a3 100644 (file)
@@ -23,6 +23,9 @@ namespace llvm {
 class MCSubtargetInfo;
 
 class WebAssemblyInstPrinter final : public MCInstPrinter {
 class MCSubtargetInfo;
 
 class WebAssemblyInstPrinter final : public MCInstPrinter {
+  uint64_t ControlFlowCounter;
+  SmallVector<std::pair<uint64_t, bool>, 0> ControlFlowStack;
+
 public:
   WebAssemblyInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
                          const MCRegisterInfo &MRI);
 public:
   WebAssemblyInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
                          const MCRegisterInfo &MRI);
index 753b78fde67cab3e81b0ad3d2c3c2ddad2508844..7c4fb6c3c59cbcf7b132216841ef1b79824cdb1f 100644 (file)
@@ -58,6 +58,9 @@ enum {
   // For immediate values in the variable_ops range, this flag indicates
   // whether the value represents a type.
   VariableOpImmediateIsType   = (1 << 1),
   // For immediate values in the variable_ops range, this flag indicates
   // whether the value represents a type.
   VariableOpImmediateIsType   = (1 << 1),
+  // For immediate values in the variable_ops range, this flag indicates
+  // whether the value represents a control-flow label.
+  VariableOpImmediateIsLabel  = (1 << 2),
 };
 } // end namespace WebAssemblyII
 
 };
 } // end namespace WebAssemblyII
 
index 8d84901b3a2f524c6ab094d8c0817e5094afb75a..6a25c043c07ddd81296ce54f0b49dc07a439ec41 100644 (file)
@@ -208,10 +208,6 @@ 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 0080dc09e8ac4e5a6bebf4e8e9680d2a08062395..7876a1e18325c734647423a264f7e5df398ba852 100644 (file)
@@ -326,13 +326,21 @@ static void PlaceBlockMarker(MachineBasicBlock &MBB, MachineFunction &MF,
     InsertPos = Header->getFirstTerminator();
     while (InsertPos != Header->begin() &&
            prev(InsertPos)->definesRegister(WebAssembly::EXPR_STACK) &&
     InsertPos = Header->getFirstTerminator();
     while (InsertPos != Header->begin() &&
            prev(InsertPos)->definesRegister(WebAssembly::EXPR_STACK) &&
-           prev(InsertPos)->getOpcode() != WebAssembly::LOOP)
+           prev(InsertPos)->getOpcode() != WebAssembly::LOOP &&
+           prev(InsertPos)->getOpcode() != WebAssembly::END_BLOCK &&
+           prev(InsertPos)->getOpcode() != WebAssembly::END_LOOP)
       --InsertPos;
   }
 
   // Add the BLOCK.
       --InsertPos;
   }
 
   // Add the BLOCK.
-  BuildMI(*Header, InsertPos, DebugLoc(), TII.get(WebAssembly::BLOCK))
-      .addMBB(&MBB);
+  BuildMI(*Header, InsertPos, DebugLoc(), TII.get(WebAssembly::BLOCK));
+
+  // Mark the end of the block.
+  InsertPos = MBB.begin();
+  while (InsertPos != MBB.end() &&
+         InsertPos->getOpcode() == WebAssembly::END_LOOP)
+    ++InsertPos;
+  BuildMI(MBB, InsertPos, DebugLoc(), TII.get(WebAssembly::END_BLOCK));
 
   // Track the farthest-spanning scope that ends at this point.
   int Number = MBB.getNumber();
 
   // Track the farthest-spanning scope that ends at this point.
   int Number = MBB.getNumber();
@@ -342,10 +350,11 @@ static void PlaceBlockMarker(MachineBasicBlock &MBB, MachineFunction &MF,
 }
 
 /// Insert a LOOP marker for a loop starting at MBB (if it's a loop header).
 }
 
 /// Insert a LOOP marker for a loop starting at MBB (if it's a loop header).
-static void PlaceLoopMarker(MachineBasicBlock &MBB, MachineFunction &MF,
-                            SmallVectorImpl<MachineBasicBlock *> &ScopeTops,
-                            const WebAssemblyInstrInfo &TII,
-                            const MachineLoopInfo &MLI) {
+static void PlaceLoopMarker(
+    MachineBasicBlock &MBB, MachineFunction &MF,
+    SmallVectorImpl<MachineBasicBlock *> &ScopeTops,
+    DenseMap<const MachineInstr *, const MachineBasicBlock *> &LoopTops,
+    const WebAssemblyInstrInfo &TII, const MachineLoopInfo &MLI) {
   MachineLoop *Loop = MLI.getLoopFor(&MBB);
   if (!Loop || Loop->getHeader() != &MBB)
     return;
   MachineLoop *Loop = MLI.getLoopFor(&MBB);
   if (!Loop || Loop->getHeader() != &MBB)
     return;
@@ -362,14 +371,19 @@ static void PlaceLoopMarker(MachineBasicBlock &MBB, MachineFunction &MF,
     Iter = next(MachineFunction::iterator(Bottom));
   }
   MachineBasicBlock *AfterLoop = &*Iter;
     Iter = next(MachineFunction::iterator(Bottom));
   }
   MachineBasicBlock *AfterLoop = &*Iter;
-  BuildMI(MBB, MBB.begin(), DebugLoc(), TII.get(WebAssembly::LOOP))
-      .addMBB(AfterLoop);
 
 
-  // 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));
+  // Mark the beginning of the loop (after the end of any existing loop that
+  // ends here).
+  auto InsertPos = MBB.begin();
+  while (InsertPos != MBB.end() &&
+         InsertPos->getOpcode() == WebAssembly::END_LOOP)
+    ++InsertPos;
+  BuildMI(MBB, InsertPos, DebugLoc(), TII.get(WebAssembly::LOOP));
+
+  // Mark the end of the loop.
+  MachineInstr *End = BuildMI(*AfterLoop, AfterLoop->begin(), DebugLoc(),
+                              TII.get(WebAssembly::END_LOOP));
+  LoopTops[End] = &MBB;
 
   assert((!ScopeTops[AfterLoop->getNumber()] ||
           ScopeTops[AfterLoop->getNumber()]->getNumber() < MBB.getNumber()) &&
 
   assert((!ScopeTops[AfterLoop->getNumber()] ||
           ScopeTops[AfterLoop->getNumber()]->getNumber() < MBB.getNumber()) &&
@@ -378,6 +392,19 @@ static void PlaceLoopMarker(MachineBasicBlock &MBB, MachineFunction &MF,
     ScopeTops[AfterLoop->getNumber()] = &MBB;
 }
 
     ScopeTops[AfterLoop->getNumber()] = &MBB;
 }
 
+static unsigned
+GetDepth(const SmallVectorImpl<const MachineBasicBlock *> &Stack,
+         const MachineBasicBlock *MBB) {
+  unsigned Depth = 0;
+  for (auto X : reverse(Stack)) {
+    if (X == MBB)
+      break;
+    ++Depth;
+  }
+  assert(Depth < Stack.size() && "Branch destination should be in scope");
+  return Depth;
+}
+
 /// Insert LOOP and BLOCK markers at appropriate places.
 static void PlaceMarkers(MachineFunction &MF, const MachineLoopInfo &MLI,
                          const WebAssemblyInstrInfo &TII,
 /// Insert LOOP and BLOCK markers at appropriate places.
 static void PlaceMarkers(MachineFunction &MF, const MachineLoopInfo &MLI,
                          const WebAssemblyInstrInfo &TII,
@@ -389,25 +416,57 @@ static void PlaceMarkers(MachineFunction &MF, const MachineLoopInfo &MLI,
   // we may insert at the end.
   SmallVector<MachineBasicBlock *, 8> ScopeTops(MF.getNumBlockIDs() + 1);
 
   // we may insert at the end.
   SmallVector<MachineBasicBlock *, 8> ScopeTops(MF.getNumBlockIDs() + 1);
 
+  // For eacn LOOP_END, the corresponding LOOP.
+  DenseMap<const MachineInstr *, const MachineBasicBlock *> LoopTops;
+
   for (auto &MBB : MF) {
     // Place the LOOP for MBB if MBB is the header of a loop.
   for (auto &MBB : MF) {
     // Place the LOOP for MBB if MBB is the header of a loop.
-    PlaceLoopMarker(MBB, MF, ScopeTops, TII, MLI);
+    PlaceLoopMarker(MBB, MF, ScopeTops, LoopTops, TII, MLI);
 
     // Place the BLOCK for MBB if MBB is branched to from above.
     PlaceBlockMarker(MBB, MF, ScopeTops, TII, MLI, MDT);
   }
 
     // Place the BLOCK for MBB if MBB is branched to from above.
     PlaceBlockMarker(MBB, MF, ScopeTops, TII, MLI, MDT);
   }
-}
 
 
-#ifndef NDEBUG
-static bool
-IsOnStack(const SmallVectorImpl<std::pair<MachineBasicBlock *, bool>> &Stack,
-          const MachineBasicBlock *MBB) {
-  for (const auto &Pair : Stack)
-    if (Pair.first == MBB)
-      return true;
-  return false;
+  // Now rewrite references to basic blocks to be depth immediates.
+  SmallVector<const MachineBasicBlock *, 8> Stack;
+  for (auto &MBB : reverse(MF)) {
+    for (auto &MI : reverse(MBB)) {
+      switch (MI.getOpcode()) {
+      case WebAssembly::BLOCK:
+        assert(ScopeTops[Stack.back()->getNumber()] == &MBB &&
+               "Block should be balanced");
+        Stack.pop_back();
+        break;
+      case WebAssembly::LOOP:
+        assert(Stack.back() == &MBB && "Loop top should be balanced");
+        Stack.pop_back();
+        Stack.pop_back();
+        break;
+      case WebAssembly::END_BLOCK:
+        Stack.push_back(&MBB);
+        break;
+      case WebAssembly::END_LOOP:
+        Stack.push_back(&MBB);
+        Stack.push_back(LoopTops[&MI]);
+        break;
+      default:
+        if (MI.isTerminator()) {
+          // Rewrite MBB operands to be depth immediates.
+          SmallVector<MachineOperand, 4> Ops(MI.operands());
+          while (MI.getNumOperands() > 0)
+            MI.RemoveOperand(MI.getNumOperands() - 1);
+          for (auto MO : Ops) {
+            if (MO.isMBB())
+              MO = MachineOperand::CreateImm(GetDepth(Stack, MO.getMBB()));
+            MI.addOperand(MF, MO);
+          }
+        }
+        break;
+      }
+    }
+  }
+  assert(Stack.empty() && "Control flow should be balanced");
 }
 }
-#endif
 
 bool WebAssemblyCFGStackify::runOnMachineFunction(MachineFunction &MF) {
   DEBUG(dbgs() << "********** CFG Stackifying **********\n"
 
 bool WebAssemblyCFGStackify::runOnMachineFunction(MachineFunction &MF) {
   DEBUG(dbgs() << "********** CFG Stackifying **********\n"
@@ -427,43 +486,5 @@ bool WebAssemblyCFGStackify::runOnMachineFunction(MachineFunction &MF) {
   // Place the BLOCK and LOOP markers to indicate the beginnings of scopes.
   PlaceMarkers(MF, MLI, TII, MDT);
 
   // Place the BLOCK and LOOP markers to indicate the beginnings of scopes.
   PlaceMarkers(MF, MLI, TII, MDT);
 
-#ifndef NDEBUG
-  // Verify that block and loop beginnings and endings are in LIFO order, and
-  // that all references to blocks are to blocks on the stack at the point of
-  // the reference.
-  SmallVector<std::pair<MachineBasicBlock *, bool>, 0> Stack;
-  for (auto &MBB : MF) {
-    while (!Stack.empty() && Stack.back().first == &MBB)
-      if (Stack.back().second) {
-        assert(Stack.size() >= 2);
-        Stack.pop_back();
-        Stack.pop_back();
-      } else {
-        assert(Stack.size() >= 1);
-        Stack.pop_back();
-      }
-    for (auto &MI : MBB)
-      switch (MI.getOpcode()) {
-      case WebAssembly::LOOP:
-        Stack.push_back(std::make_pair(&MBB, false));
-        Stack.push_back(std::make_pair(MI.getOperand(0).getMBB(), true));
-        break;
-      case WebAssembly::BLOCK:
-        Stack.push_back(std::make_pair(MI.getOperand(0).getMBB(), false));
-        break;
-      default:
-        // Verify that all referenced blocks are in scope. A reference to a
-        // block with a negative number is invalid, but can happen with inline
-        // asm, so we shouldn't assert on it, but instead let CodeGen properly
-        // fail on it.
-        for (const MachineOperand &MO : MI.explicit_operands())
-          if (MO.isMBB() && MO.getMBB()->getNumber() >= 0)
-            assert(IsOnStack(Stack, MO.getMBB()));
-        break;
-      }
-  }
-  assert(Stack.empty());
-#endif
-
   return true;
 }
   return true;
 }
index 1c06b08597a014adea9f531dffa7dd1deb66acf5..d2852012be1d5b0d3496667b4572dd1d80e1b54b 100644 (file)
@@ -42,32 +42,32 @@ let Defs = [ARGUMENTS] in {
 // jump tables, so in practice we don't ever use TABLESWITCH_I64 in wasm32 mode
 // currently.
 // Set TSFlags{0} to 1 to indicate that the variable_ops are immediates.
 // jump tables, so in practice we don't ever use TABLESWITCH_I64 in wasm32 mode
 // currently.
 // Set TSFlags{0} to 1 to indicate that the variable_ops are immediates.
+// Set TSFlags{2} to 1 to indicate that the immediates represent labels.
 let isTerminator = 1, hasCtrlDep = 1, isBarrier = 1 in {
 def TABLESWITCH_I32 : I<(outs), (ins I32:$index, bb_op:$default, variable_ops),
                         [(WebAssemblytableswitch I32:$index, bb:$default)],
                         "tableswitch\t$index, $default"> {
   let TSFlags{0} = 1;
 let isTerminator = 1, hasCtrlDep = 1, isBarrier = 1 in {
 def TABLESWITCH_I32 : I<(outs), (ins I32:$index, bb_op:$default, variable_ops),
                         [(WebAssemblytableswitch I32:$index, bb:$default)],
                         "tableswitch\t$index, $default"> {
   let TSFlags{0} = 1;
+  let TSFlags{2} = 1;
 }
 def TABLESWITCH_I64 : I<(outs), (ins I64:$index, bb_op:$default, variable_ops),
                         [(WebAssemblytableswitch I64:$index, bb:$default)],
                         "tableswitch\t$index, $default"> {
   let TSFlags{0} = 1;
 }
 def TABLESWITCH_I64 : I<(outs), (ins I64:$index, bb_op:$default, variable_ops),
                         [(WebAssemblytableswitch I64:$index, bb:$default)],
                         "tableswitch\t$index, $default"> {
   let TSFlags{0} = 1;
+  let TSFlags{2} = 1;
 }
 } // isTerminator = 1, hasCtrlDep = 1, isBarrier = 1
 
 }
 } // isTerminator = 1, hasCtrlDep = 1, isBarrier = 1
 
-// Placemarkers to indicate the start of a block or loop scope. These
+// Placemarkers to indicate the start or end of a block or loop scope. These
 // use/clobber EXPR_STACK to prevent them from being moved into the middle of
 // an expression tree.
 let Uses = [EXPR_STACK], Defs = [EXPR_STACK] in {
 // use/clobber EXPR_STACK to prevent them from being moved into the middle of
 // an expression tree.
 let Uses = [EXPR_STACK], Defs = [EXPR_STACK] in {
-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), [], "block">;
+def LOOP      : I<(outs), (ins), [], "loop">;
+def END_BLOCK : I<(outs), (ins), [], "end_block">;
+def END_LOOP  : I<(outs), (ins), [], "end_loop">;
 } // Uses = [EXPR_STACK], Defs = [EXPR_STACK]
 
 } // Uses = [EXPR_STACK], Defs = [EXPR_STACK]
 
-// 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 5e7663cdb5063f7190a4e966e71bfce47b04da38..028e9af0834fe72f895a5ebd509faf66332708ca 100644 (file)
@@ -74,6 +74,9 @@ bool WebAssemblyInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
     case WebAssembly::BR_IF:
       if (HaveCond)
         return true;
     case WebAssembly::BR_IF:
       if (HaveCond)
         return true;
+      // If we're running after CFGStackify, we can't optimize further.
+      if (!MI.getOperand(1).isMBB())
+        return true;
       Cond.push_back(MachineOperand::CreateImm(true));
       Cond.push_back(MI.getOperand(0));
       TBB = MI.getOperand(1).getMBB();
       Cond.push_back(MachineOperand::CreateImm(true));
       Cond.push_back(MI.getOperand(0));
       TBB = MI.getOperand(1).getMBB();
@@ -82,12 +85,18 @@ bool WebAssemblyInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
     case WebAssembly::BR_UNLESS:
       if (HaveCond)
         return true;
     case WebAssembly::BR_UNLESS:
       if (HaveCond)
         return true;
+      // If we're running after CFGStackify, we can't optimize further.
+      if (!MI.getOperand(1).isMBB())
+        return true;
       Cond.push_back(MachineOperand::CreateImm(false));
       Cond.push_back(MI.getOperand(0));
       TBB = MI.getOperand(1).getMBB();
       HaveCond = true;
       break;
     case WebAssembly::BR:
       Cond.push_back(MachineOperand::CreateImm(false));
       Cond.push_back(MI.getOperand(0));
       TBB = MI.getOperand(1).getMBB();
       HaveCond = true;
       break;
     case WebAssembly::BR:
+      // If we're running after CFGStackify, we can't optimize further.
+      if (!MI.getOperand(0).isMBB())
+        return true;
       if (!HaveCond)
         TBB = MI.getOperand(0).getMBB();
       else
       if (!HaveCond)
         TBB = MI.getOperand(0).getMBB();
       else
index eaba53e46ed32d0cd868a194e80372064a009f0f..022a448590ecea893f770e775297f8519358567f 100644 (file)
@@ -66,6 +66,9 @@ void WebAssemblyMCInstLower::Lower(const MachineInstr *MI,
     default:
       MI->dump();
       llvm_unreachable("unknown operand type");
     default:
       MI->dump();
       llvm_unreachable("unknown operand type");
+    case MachineOperand::MO_MachineBasicBlock:
+      MI->dump();
+      llvm_unreachable("MachineBasicBlock operand should have been rewritten");
     case MachineOperand::MO_Register: {
       // Ignore all implicit register operands.
       if (MO.isImplicit())
     case MachineOperand::MO_Register: {
       // Ignore all implicit register operands.
       if (MO.isImplicit())
@@ -91,10 +94,6 @@ void WebAssemblyMCInstLower::Lower(const MachineInstr *MI,
         llvm_unreachable("unknown floating point immediate type");
       break;
     }
         llvm_unreachable("unknown floating point immediate type");
       break;
     }
-    case MachineOperand::MO_MachineBasicBlock:
-      MCOp = MCOperand::createExpr(
-          MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), Ctx));
-      break;
     case MachineOperand::MO_GlobalAddress:
       assert(MO.getTargetFlags() == 0 &&
              "WebAssembly does not use target flags on GlobalAddresses");
     case MachineOperand::MO_GlobalAddress:
       assert(MO.getTargetFlags() == 0 &&
              "WebAssembly does not use target flags on GlobalAddresses");
index 77984fa9dd444d0ab4a721ea3932e131769b47e9..f0e5f4471678577f4efc8fc3422cf9f51e9a62da 100644 (file)
@@ -18,7 +18,7 @@ declare void @something()
 ; CHECK-NEXT: br_if
 ; CHECK-NOT: br
 ; CHECK: call
 ; CHECK-NEXT: br_if
 ; CHECK-NOT: br
 ; CHECK: call
-; CHECK: br .LBB0_1{{$}}
+; CHECK: br 0{{$}}
 ; CHECK: return{{$}}
 ; OPT-LABEL: test0:
 ; OPT: loop
 ; CHECK: return{{$}}
 ; OPT-LABEL: test0:
 ; OPT: loop
@@ -28,7 +28,7 @@ declare void @something()
 ; OPT-NEXT: br_if
 ; OPT-NOT: br
 ; OPT: call
 ; OPT-NEXT: br_if
 ; OPT-NOT: br
 ; OPT: call
-; OPT: br .LBB0_1{{$}}
+; OPT: br 0{{$}}
 ; OPT: return{{$}}
 define void @test0(i32 %n) {
 entry:
 ; OPT: return{{$}}
 define void @test0(i32 %n) {
 entry:
@@ -59,7 +59,7 @@ back:
 ; CHECK-NEXT: br_if
 ; CHECK-NOT: br
 ; CHECK: call
 ; CHECK-NEXT: br_if
 ; CHECK-NOT: br
 ; CHECK: call
-; CHECK: br .LBB1_1{{$}}
+; CHECK: br 0{{$}}
 ; CHECK: return{{$}}
 ; OPT-LABEL: test1:
 ; OPT: loop
 ; CHECK: return{{$}}
 ; OPT-LABEL: test1:
 ; OPT: loop
@@ -69,7 +69,7 @@ back:
 ; OPT-NEXT: br_if
 ; OPT-NOT: br
 ; OPT: call
 ; OPT-NEXT: br_if
 ; OPT-NOT: br
 ; OPT: call
-; OPT: br .LBB1_1{{$}}
+; OPT: br 0{{$}}
 ; OPT: return{{$}}
 define void @test1(i32 %n) {
 entry:
 ; OPT: return{{$}}
 define void @test1(i32 %n) {
 entry:
@@ -94,17 +94,18 @@ back:
 
 ; CHECK-LABEL: test2:
 ; CHECK-NOT: local
 
 ; CHECK-LABEL: test2:
 ; CHECK-NOT: local
-; CHECK: block .LBB2_2{{$}}
-; CHECK: br_if {{[^,]*}}, .LBB2_2{{$}}
+; CHECK: block{{$}}
+; CHECK: br_if {{[^,]*}}, 0{{$}}
 ; CHECK: .LBB2_1:
 ; CHECK: .LBB2_1:
-; CHECK: br_if ${{[0-9]+}}, .LBB2_1{{$}}
+; CHECK: br_if ${{[0-9]+}}, 0{{$}}
 ; CHECK: .LBB2_2:
 ; CHECK: return{{$}}
 ; OPT-LABEL: test2:
 ; CHECK: .LBB2_2:
 ; CHECK: return{{$}}
 ; OPT-LABEL: test2:
-; OPT: block .LBB2_2{{$}}
-; OPT: br_if {{[^,]*}}, .LBB2_2{{$}}
+; OPT-NOT: local
+; OPT: block{{$}}
+; OPT: br_if {{[^,]*}}, 0{{$}}
 ; OPT: .LBB2_1:
 ; OPT: .LBB2_1:
-; OPT: br_if ${{[0-9]+}}, .LBB2_1{{$}}
+; OPT: br_if ${{[0-9]+}}, 0{{$}}
 ; OPT: .LBB2_2:
 ; OPT: return{{$}}
 define void @test2(double* nocapture %p, i32 %n) {
 ; OPT: .LBB2_2:
 ; OPT: return{{$}}
 define void @test2(double* nocapture %p, i32 %n) {
@@ -133,22 +134,27 @@ for.end:
 }
 
 ; CHECK-LABEL: doublediamond:
 }
 
 ; CHECK-LABEL: doublediamond:
-; CHECK: block .LBB3_5{{$}}
-; CHECK: block .LBB3_2{{$}}
-; CHECK: br_if $0, .LBB3_2{{$}}
-; CHECK: block .LBB3_4{{$}}
-; CHECK: br_if $1, .LBB3_4{{$}}
-; CHECK: br .LBB3_5{{$}}
+; CHECK: block{{$}}
+; CHECK-NEXT: block{{$}}
+; CHECK: br_if ${{[^,]*}}, 0{{$}}
+; CHECK: br 1{{$}}
+; CHECK: .LBB3_2:
+; CHECK-NEXT: end_block{{$}}
+; CHECK: block{{$}}
+; CHECK: br_if ${{[^,]*}}, 0{{$}}
+; CHECK: br 1{{$}}
 ; CHECK: .LBB3_4:
 ; CHECK: .LBB3_4:
+; CHECK-NEXT: end_block{{$}}
 ; CHECK: .LBB3_5:
 ; CHECK: .LBB3_5:
+; CHECK-NEXT: end_block{{$}}
 ; CHECK: return ${{[0-9]+}}{{$}}
 ; OPT-LABEL: doublediamond:
 ; CHECK: return ${{[0-9]+}}{{$}}
 ; OPT-LABEL: doublediamond:
-; OPT: block .LBB3_5{{$}}
-; OPT: block .LBB3_4{{$}}
-; OPT: br_if {{[^,]*}}, .LBB3_4{{$}}
-; OPT: block .LBB3_3{{$}}
-; OPT: br_if {{[^,]*}}, .LBB3_3{{$}}
-; OPT: br .LBB3_5{{$}}
+; OPT: block{{$}}
+; OPT-NEXT: block{{$}}
+; OPT: br_if ${{[^,]*}}, 0{{$}}
+; OPT: block{{$}}
+; OPT: br_if ${{[^,]*}}, 0{{$}}
+; OPT: br 1{{$}}
 ; OPT: .LBB3_4:
 ; OPT: .LBB3_5:
 ; OPT: return ${{[0-9]+}}{{$}}
 ; OPT: .LBB3_4:
 ; OPT: .LBB3_5:
 ; OPT: return ${{[0-9]+}}{{$}}
@@ -176,13 +182,13 @@ exit:
 }
 
 ; CHECK-LABEL: triangle:
 }
 
 ; CHECK-LABEL: triangle:
-; CHECK: block .LBB4_2{{$}}
-; CHECK: br_if $1, .LBB4_2{{$}}
+; CHECK: block{{$}}
+; CHECK: br_if $1, 0{{$}}
 ; CHECK: .LBB4_2:
 ; CHECK: return ${{[0-9]+}}{{$}}
 ; OPT-LABEL: triangle:
 ; CHECK: .LBB4_2:
 ; CHECK: return ${{[0-9]+}}{{$}}
 ; OPT-LABEL: triangle:
-; OPT: block .LBB4_2{{$}}
-; OPT: br_if $1, .LBB4_2{{$}}
+; OPT: block{{$}}
+; OPT: br_if $1, 0{{$}}
 ; OPT: .LBB4_2:
 ; OPT: return ${{[0-9]+}}{{$}}
 define i32 @triangle(i32* %p, i32 %a) {
 ; OPT: .LBB4_2:
 ; OPT: return ${{[0-9]+}}{{$}}
 define i32 @triangle(i32* %p, i32 %a) {
@@ -199,18 +205,18 @@ exit:
 }
 
 ; CHECK-LABEL: diamond:
 }
 
 ; CHECK-LABEL: diamond:
-; CHECK: block .LBB5_3{{$}}
-; CHECK: block .LBB5_2{{$}}
-; CHECK: br_if $1, .LBB5_2{{$}}
-; CHECK: br .LBB5_3{{$}}
+; CHECK: block{{$}}
+; CHECK: block{{$}}
+; CHECK: br_if $1, 0{{$}}
+; CHECK: br 1{{$}}
 ; CHECK: .LBB5_2:
 ; CHECK: .LBB5_3:
 ; CHECK: return ${{[0-9]+}}{{$}}
 ; OPT-LABEL: diamond:
 ; CHECK: .LBB5_2:
 ; CHECK: .LBB5_3:
 ; CHECK: return ${{[0-9]+}}{{$}}
 ; OPT-LABEL: diamond:
-; OPT: block .LBB5_3{{$}}
-; OPT: block .LBB5_2{{$}}
-; OPT: br_if {{[^,]*}}, .LBB5_2{{$}}
-; OPT: br .LBB5_3{{$}}
+; OPT: block{{$}}
+; OPT: block{{$}}
+; OPT: br_if {{[^,]*}}, 0{{$}}
+; OPT: br 1{{$}}
 ; OPT: .LBB5_2:
 ; OPT: .LBB5_3:
 ; OPT: return ${{[0-9]+}}{{$}}
 ; OPT: .LBB5_2:
 ; OPT: .LBB5_3:
 ; OPT: return ${{[0-9]+}}{{$}}
@@ -246,13 +252,13 @@ entry:
 ; CHECK-NOT: br
 ; CHECK: .LBB7_1:
 ; CHECK: i32.store $discard=, 0($0), $pop{{[0-9]+}}{{$}}
 ; CHECK-NOT: br
 ; CHECK: .LBB7_1:
 ; CHECK: i32.store $discard=, 0($0), $pop{{[0-9]+}}{{$}}
-; CHECK: br .LBB7_1{{$}}
+; CHECK: br 0{{$}}
 ; CHECK: .LBB7_2:
 ; OPT-LABEL: minimal_loop:
 ; OPT-NOT: br
 ; OPT: .LBB7_1:
 ; OPT: i32.store $discard=, 0($0), $pop{{[0-9]+}}{{$}}
 ; CHECK: .LBB7_2:
 ; OPT-LABEL: minimal_loop:
 ; OPT-NOT: br
 ; OPT: .LBB7_1:
 ; OPT: i32.store $discard=, 0($0), $pop{{[0-9]+}}{{$}}
-; OPT: br .LBB7_1{{$}}
+; OPT: br 0{{$}}
 ; OPT: .LBB7_2:
 define i32 @minimal_loop(i32* %p) {
 entry:
 ; OPT: .LBB7_2:
 define i32 @minimal_loop(i32* %p) {
 entry:
@@ -266,16 +272,16 @@ loop:
 ; CHECK-LABEL: simple_loop:
 ; CHECK-NOT: br
 ; CHECK: .LBB8_1:
 ; CHECK-LABEL: simple_loop:
 ; CHECK-NOT: br
 ; CHECK: .LBB8_1:
-; CHECK: loop .LBB8_2{{$}}
-; CHECK: br_if $pop{{[0-9]+}}, .LBB8_1{{$}}
-; CHECK: .LBB8_2:
+; CHECK: loop{{$}}
+; CHECK: br_if $pop{{[0-9]+}}, 0{{$}}
+; CHECK-NEXT: end_loop{{$}}
 ; CHECK: return ${{[0-9]+}}{{$}}
 ; OPT-LABEL: simple_loop:
 ; OPT-NOT: br
 ; OPT: .LBB8_1:
 ; CHECK: return ${{[0-9]+}}{{$}}
 ; OPT-LABEL: simple_loop:
 ; OPT-NOT: br
 ; OPT: .LBB8_1:
-; OPT: loop .LBB8_2{{$}}
-; OPT: br_if {{[^,]*}}, .LBB8_1{{$}}
-; OPT: .LBB8_2:
+; OPT: loop{{$}}
+; OPT: br_if {{[^,]*}}, 0{{$}}
+; OPT-NEXT: end_loop{{$}}
 ; OPT: return ${{[0-9]+}}{{$}}
 define i32 @simple_loop(i32* %p, i32 %a) {
 entry:
 ; OPT: return ${{[0-9]+}}{{$}}
 define i32 @simple_loop(i32* %p, i32 %a) {
 entry:
@@ -291,18 +297,18 @@ exit:
 }
 
 ; CHECK-LABEL: doubletriangle:
 }
 
 ; CHECK-LABEL: doubletriangle:
-; CHECK: block .LBB9_4{{$}}
-; CHECK: br_if $0, .LBB9_4{{$}}
-; CHECK: block .LBB9_3{{$}}
-; CHECK: br_if $1, .LBB9_3{{$}}
+; CHECK: block{{$}}
+; CHECK: br_if $0, 0{{$}}
+; CHECK: block{{$}}
+; CHECK: br_if $1, 0{{$}}
 ; CHECK: .LBB9_3:
 ; CHECK: .LBB9_4:
 ; CHECK: return ${{[0-9]+}}{{$}}
 ; OPT-LABEL: doubletriangle:
 ; CHECK: .LBB9_3:
 ; CHECK: .LBB9_4:
 ; CHECK: return ${{[0-9]+}}{{$}}
 ; OPT-LABEL: doubletriangle:
-; OPT: block .LBB9_4{{$}}
-; OPT: br_if $0, .LBB9_4{{$}}
-; OPT: block .LBB9_3{{$}}
-; OPT: br_if $1, .LBB9_3{{$}}
+; OPT: block{{$}}
+; OPT: br_if $0, 0{{$}}
+; OPT: block{{$}}
+; OPT: br_if $1, 0{{$}}
 ; OPT: .LBB9_3:
 ; OPT: .LBB9_4:
 ; OPT: return ${{[0-9]+}}{{$}}
 ; OPT: .LBB9_3:
 ; OPT: .LBB9_4:
 ; OPT: return ${{[0-9]+}}{{$}}
@@ -327,20 +333,20 @@ exit:
 }
 
 ; CHECK-LABEL: ifelse_earlyexits:
 }
 
 ; CHECK-LABEL: ifelse_earlyexits:
-; CHECK: block .LBB10_4{{$}}
-; CHECK: block .LBB10_2{{$}}
-; CHECK: br_if $0, .LBB10_2{{$}}
-; CHECK: br .LBB10_4{{$}}
+; CHECK: block{{$}}
+; CHECK: block{{$}}
+; CHECK: br_if $0, 0{{$}}
+; CHECK: br 1{{$}}
 ; CHECK: .LBB10_2:
 ; CHECK: .LBB10_2:
-; CHECK: br_if $1, .LBB10_4{{$}}
+; CHECK: br_if $1, 0{{$}}
 ; CHECK: .LBB10_4:
 ; CHECK: return ${{[0-9]+}}{{$}}
 ; OPT-LABEL: ifelse_earlyexits:
 ; CHECK: .LBB10_4:
 ; CHECK: return ${{[0-9]+}}{{$}}
 ; OPT-LABEL: ifelse_earlyexits:
-; OPT: block .LBB10_4{{$}}
-; OPT: block .LBB10_3{{$}}
-; OPT: br_if {{[^,]*}}, .LBB10_3{{$}}
-; OPT: br_if $1, .LBB10_4{{$}}
-; OPT: br .LBB10_4{{$}}
+; OPT: block{{$}}
+; OPT: block{{$}}
+; OPT: br_if {{[^,]*}}, 0{{$}}
+; OPT: br_if $1, 1{{$}}
+; OPT: br 1{{$}}
 ; OPT: .LBB10_3:
 ; OPT: .LBB10_4:
 ; OPT: return ${{[0-9]+}}{{$}}
 ; OPT: .LBB10_3:
 ; OPT: .LBB10_4:
 ; OPT: return ${{[0-9]+}}{{$}}
@@ -366,34 +372,39 @@ exit:
 
 ; CHECK-LABEL: doublediamond_in_a_loop:
 ; CHECK: .LBB11_1:
 
 ; CHECK-LABEL: doublediamond_in_a_loop:
 ; CHECK: .LBB11_1:
-; CHECK: loop            .LBB11_7{{$}}
-; CHECK: block           .LBB11_6{{$}}
-; CHECK: block           .LBB11_3{{$}}
-; CHECK: br_if           $0, .LBB11_3{{$}}
-; CHECK: br              .LBB11_6{{$}}
+; CHECK: loop{{$}}
+; CHECK: block{{$}}
+; CHECK: block{{$}}
+; CHECK: br_if           $0, 0{{$}}
+; CHECK: br              1{{$}}
 ; CHECK: .LBB11_3:
 ; CHECK: .LBB11_3:
-; CHECK: block           .LBB11_5{{$}}
-; CHECK: br_if           $1, .LBB11_5{{$}}
-; CHECK: br              .LBB11_6{{$}}
+; CHECK: block{{$}}
+; CHECK: br_if           $1, 0{{$}}
+; CHECK: br              1{{$}}
 ; CHECK: .LBB11_5:
 ; CHECK: .LBB11_6:
 ; CHECK: .LBB11_5:
 ; CHECK: .LBB11_6:
-; CHECK: br              .LBB11_1{{$}}
+; CHECK: br              0{{$}}
 ; CHECK: .LBB11_7:
 ; CHECK: .LBB11_7:
+; CHECK-NEXT: end_loop{{$}}
 ; OPT-LABEL: doublediamond_in_a_loop:
 ; OPT: .LBB11_1:
 ; OPT-LABEL: doublediamond_in_a_loop:
 ; OPT: .LBB11_1:
-; OPT: loop            .LBB11_7{{$}}
-; OPT: block           .LBB11_6{{$}}
-; OPT: block           .LBB11_5{{$}}
-; OPT: br_if           {{[^,]*}}, .LBB11_5{{$}}
-; OPT: block           .LBB11_4{{$}}
-; OPT: br_if           {{[^,]*}}, .LBB11_4{{$}}
-; OPT: br              .LBB11_6{{$}}
+; OPT: loop{{$}}
+; OPT: block{{$}}
+; OPT: block{{$}}
+; OPT: br_if           {{[^,]*}}, 0{{$}}
+; OPT: block{{$}}
+; OPT: br_if           {{[^,]*}}, 0{{$}}
+; OPT: br              2{{$}}
 ; OPT: .LBB11_4:
 ; OPT: .LBB11_4:
-; OPT: br              .LBB11_6{{$}}
+; OPT-NEXT: end_block{{$}}
+; OPT: br              1{{$}}
 ; OPT: .LBB11_5:
 ; OPT: .LBB11_5:
+; OPT-NEXT: end_block{{$}}
 ; OPT: .LBB11_6:
 ; OPT: .LBB11_6:
-; OPT: br              .LBB11_1{{$}}
+; OPT-NEXT: end_block{{$}}
+; OPT: br              0{{$}}
 ; OPT: .LBB11_7:
 ; OPT: .LBB11_7:
+; OPT-NEXT: end_loop{{$}}
 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
@@ -461,42 +472,48 @@ if.end:
 ; Test switch lowering and block placement.
 
 ; CHECK-LABEL: test4:
 ; Test switch lowering and block placement.
 
 ; CHECK-LABEL: test4:
-; CHECK-NEXT: .param      i32{{$}}
-; CHECK:      block       .LBB13_8{{$}}
-; CHECK-NEXT: block       .LBB13_7{{$}}
-; CHECK-NEXT: block       .LBB13_4{{$}}
-; CHECK:      br_if       $pop{{[0-9]*}}, .LBB13_4{{$}}
-; CHECK-NEXT: block       .LBB13_3{{$}}
-; CHECK:      br_if       $pop{{[0-9]*}}, .LBB13_3{{$}}
-; CHECK:      br_if       $pop{{[0-9]*}}, .LBB13_7{{$}}
+; CHECK-NEXT: .param       i32{{$}}
+; CHECK:      block{{$}}
+; CHECK-NEXT: block{{$}}
+; CHECK-NEXT: block{{$}}
+; CHECK:      br_if       $pop{{[0-9]*}}, 0{{$}}
+; CHECK-NEXT: block{{$}}
+; CHECK:      br_if       $pop{{[0-9]*}}, 0{{$}}
+; CHECK:      br_if       $pop{{[0-9]*}}, 2{{$}}
 ; CHECK-NEXT: .LBB13_3:
 ; CHECK-NEXT: .LBB13_3:
+; CHECK-NEXT: end_block{{$}}
 ; CHECK-NEXT: return{{$}}
 ; CHECK-NEXT: .LBB13_4:
 ; CHECK-NEXT: return{{$}}
 ; CHECK-NEXT: .LBB13_4:
-; CHECK:      br_if       $pop{{[0-9]*}}, .LBB13_8{{$}}
-; CHECK:      br_if       $pop{{[0-9]*}}, .LBB13_7{{$}}
+; CHECK:      br_if       $pop{{[0-9]*}}, 1{{$}}
+; CHECK:      br_if       $pop{{[0-9]*}}, 0{{$}}
 ; CHECK-NEXT: return{{$}}
 ; CHECK-NEXT: .LBB13_7:
 ; CHECK-NEXT: return{{$}}
 ; CHECK-NEXT: .LBB13_7:
+; CHECK-NEXT: end_block{{$}}
 ; CHECK-NEXT: return{{$}}
 ; CHECK-NEXT: .LBB13_8:
 ; CHECK-NEXT: return{{$}}
 ; CHECK-NEXT: .LBB13_8:
+; CHECK-NEXT: end_block{{$}}
 ; CHECK-NEXT: return{{$}}
 ; OPT-LABEL: test4:
 ; CHECK-NEXT: return{{$}}
 ; OPT-LABEL: test4:
-; OPT-NEXT: .param      i32{{$}}
-; OPT:      block       .LBB13_8{{$}}
-; OPT-NEXT: block       .LBB13_7{{$}}
-; OPT-NEXT: block       .LBB13_4{{$}}
-; OPT:      br_if       $pop{{[0-9]*}}, .LBB13_4{{$}}
-; OPT-NEXT: block       .LBB13_3{{$}}
-; OPT:      br_if       $pop{{[0-9]*}}, .LBB13_3{{$}}
-; OPT:      br_if       $pop{{[0-9]*}}, .LBB13_7{{$}}
+; OPT-NEXT: .param       i32{{$}}
+; OPT:      block{{$}}
+; OPT-NEXT: block{{$}}
+; OPT-NEXT: block{{$}}
+; OPT:      br_if       $pop{{[0-9]*}}, 0{{$}}
+; OPT-NEXT: block{{$}}
+; OPT:      br_if       $pop{{[0-9]*}}, 0{{$}}
+; OPT:      br_if       $pop{{[0-9]*}}, 2{{$}}
 ; OPT-NEXT: .LBB13_3:
 ; OPT-NEXT: .LBB13_3:
+; OPT-NEXT: end_block{{$}}
 ; OPT-NEXT: return{{$}}
 ; OPT-NEXT: .LBB13_4:
 ; OPT-NEXT: return{{$}}
 ; OPT-NEXT: .LBB13_4:
-; OPT:      br_if       $pop{{[0-9]*}}, .LBB13_8{{$}}
-; OPT:      br_if       $pop{{[0-9]*}}, .LBB13_7{{$}}
+; OPT:      br_if       $pop{{[0-9]*}}, 1{{$}}
+; OPT:      br_if       $pop{{[0-9]*}}, 0{{$}}
 ; OPT-NEXT: return{{$}}
 ; OPT-NEXT: .LBB13_7:
 ; OPT-NEXT: return{{$}}
 ; OPT-NEXT: .LBB13_7:
+; OPT-NEXT: end_block{{$}}
 ; OPT-NEXT: return{{$}}
 ; OPT-NEXT: .LBB13_8:
 ; OPT-NEXT: return{{$}}
 ; OPT-NEXT: .LBB13_8:
+; OPT-NEXT: end_block{{$}}
 ; OPT-NEXT: return{{$}}
 define void @test4(i32 %t) {
 entry:
 ; OPT-NEXT: return{{$}}
 define void @test4(i32 %t) {
 entry:
@@ -525,21 +542,21 @@ default:
 
 ; CHECK-LABEL: test5:
 ; CHECK:       .LBB14_1:
 
 ; CHECK-LABEL: test5:
 ; CHECK:       .LBB14_1:
-; CHECK-NEXT:  block .LBB14_4{{$}}
-; CHECK-NEXT:  loop .LBB14_3{{$}}
-; CHECK:       br_if {{[^,]*}}, .LBB14_4{{$}}
-; CHECK:       br_if {{[^,]*}}, .LBB14_1{{$}}
-; CHECK-NEXT:  .LBB14_3:
+; CHECK-NEXT:  block{{$}}
+; CHECK-NEXT:  loop{{$}}
+; CHECK:       br_if {{[^,]*}}, 2{{$}}
+; CHECK:       br_if {{[^,]*}}, 0{{$}}
+; CHECK-NEXT:  end_loop{{$}}
 ; CHECK:       return{{$}}
 ; CHECK-NEXT:  .LBB14_4:
 ; CHECK:       return{{$}}
 ; OPT-LABEL: test5:
 ; OPT:       .LBB14_1:
 ; CHECK:       return{{$}}
 ; CHECK-NEXT:  .LBB14_4:
 ; CHECK:       return{{$}}
 ; OPT-LABEL: test5:
 ; OPT:       .LBB14_1:
-; OPT-NEXT:  block .LBB14_4{{$}}
-; OPT-NEXT:  loop .LBB14_3{{$}}
-; OPT:       br_if {{[^,]*}}, .LBB14_4{{$}}
-; OPT:       br_if {{[^,]*}}, .LBB14_1{{$}}
-; OPT-NEXT:  .LBB14_3:
+; OPT-NEXT:  block{{$}}
+; OPT-NEXT:  loop{{$}}
+; OPT:       br_if {{[^,]*}}, 2{{$}}
+; OPT:       br_if {{[^,]*}}, 0{{$}}
+; OPT-NEXT:  end_loop{{$}}
 ; OPT:       return{{$}}
 ; OPT-NEXT:  .LBB14_4:
 ; OPT:       return{{$}}
 ; OPT:       return{{$}}
 ; OPT-NEXT:  .LBB14_4:
 ; OPT:       return{{$}}
@@ -570,40 +587,44 @@ return:
 
 ; CHECK-LABEL: test6:
 ; CHECK:       .LBB15_1:
 
 ; CHECK-LABEL: test6:
 ; CHECK:       .LBB15_1:
-; CHECK-NEXT:  block .LBB15_6{{$}}
-; CHECK-NEXT:  block .LBB15_5{{$}}
-; CHECK-NEXT:  loop  .LBB15_4{{$}}
+; CHECK-NEXT:  block{{$}}
+; CHECK-NEXT:  block{{$}}
+; CHECK-NEXT:  loop{{$}}
 ; CHECK-NOT:   block
 ; CHECK-NOT:   block
-; CHECK:       br_if {{[^,]*}}, .LBB15_6{{$}}
+; CHECK:       br_if {{[^,]*}}, 3{{$}}
 ; CHECK-NOT:   block
 ; CHECK-NOT:   block
-; CHECK:       br_if {{[^,]*}}, .LBB15_5{{$}}
+; CHECK:       br_if {{[^,]*}}, 2{{$}}
 ; CHECK-NOT:   block
 ; CHECK-NOT:   block
-; CHECK:       br_if {{[^,]*}}, .LBB15_1{{$}}
-; CHECK-NEXT:  .LBB15_4:
+; CHECK:       br_if {{[^,]*}}, 0{{$}}
+; CHECK-NEXT:  end_loop{{$}}
 ; CHECK-NOT:   block
 ; CHECK:       return{{$}}
 ; CHECK-NEXT:  .LBB15_5:
 ; CHECK-NOT:   block
 ; CHECK:       return{{$}}
 ; CHECK-NEXT:  .LBB15_5:
+; CHECK-NEXT:  end_block{{$}}
 ; CHECK-NOT:   block
 ; CHECK:       .LBB15_6:
 ; CHECK-NOT:   block
 ; CHECK:       .LBB15_6:
+; CHECK-NEXT:  end_block{{$}}
 ; CHECK-NOT:   block
 ; CHECK:       return{{$}}
 ; OPT-LABEL: test6:
 ; OPT:       .LBB15_1:
 ; CHECK-NOT:   block
 ; CHECK:       return{{$}}
 ; OPT-LABEL: test6:
 ; OPT:       .LBB15_1:
-; OPT-NEXT:  block .LBB15_6{{$}}
-; OPT-NEXT:  block .LBB15_5{{$}}
-; OPT-NEXT:  loop  .LBB15_4{{$}}
+; OPT-NEXT:  block{{$}}
+; OPT-NEXT:  block{{$}}
+; OPT-NEXT:  loop{{$}}
 ; OPT-NOT:   block
 ; OPT-NOT:   block
-; OPT:       br_if {{[^,]*}}, .LBB15_6{{$}}
+; OPT:       br_if {{[^,]*}}, 3{{$}}
 ; OPT-NOT:   block
 ; OPT-NOT:   block
-; OPT:       br_if {{[^,]*}}, .LBB15_5{{$}}
+; OPT:       br_if {{[^,]*}}, 2{{$}}
 ; OPT-NOT:   block
 ; OPT-NOT:   block
-; OPT:       br_if {{[^,]*}}, .LBB15_1{{$}}
-; OPT-NEXT:  .LBB15_4:
+; OPT:       br_if {{[^,]*}}, 0{{$}}
+; OPT-NEXT:  end_loop{{$}}
 ; OPT-NOT:   block
 ; OPT:       return{{$}}
 ; OPT-NEXT:  .LBB15_5:
 ; OPT-NOT:   block
 ; OPT:       return{{$}}
 ; OPT-NEXT:  .LBB15_5:
+; OPT-NEXT:  end_block{{$}}
 ; OPT-NOT:   block
 ; OPT:       .LBB15_6:
 ; OPT-NOT:   block
 ; OPT:       .LBB15_6:
+; OPT-NEXT:  end_block{{$}}
 ; OPT-NOT:   block
 ; OPT:       return{{$}}
 define void @test6(i1 %p, i1 %q) {
 ; OPT-NOT:   block
 ; OPT:       return{{$}}
 define void @test6(i1 %p, i1 %q) {
@@ -640,35 +661,37 @@ second:
 
 ; CHECK-LABEL: test7:
 ; CHECK:       .LBB16_1:
 
 ; CHECK-LABEL: test7:
 ; CHECK:       .LBB16_1:
-; CHECK-NEXT:  loop .LBB16_5{{$}}
+; CHECK-NEXT:  loop{{$}}
 ; CHECK-NOT:   block
 ; CHECK-NOT:   block
-; CHECK:       block .LBB16_4{{$}}
-; CHECK:       br_if {{[^,]*}}, .LBB16_4{{$}}
+; CHECK:       block{{$}}
+; CHECK:       br_if {{[^,]*}}, 0{{$}}
 ; CHECK-NOT:   block
 ; CHECK-NOT:   block
-; CHECK:       br_if {{[^,]*}}, .LBB16_1{{$}}
+; CHECK:       br_if {{[^,]*}}, 1{{$}}
 ; CHECK-NOT:   block
 ; CHECK:       unreachable
 ; CHECK-NOT:   block
 ; CHECK:       unreachable
-; CHECK_NEXT:  .LBB16_4:
+; CHECK-NEXT:  .LBB16_4:
+; CHECK-NEXT:  end_block{{$}}
 ; CHECK-NOT:   block
 ; CHECK-NOT:   block
-; CHECK:       br_if {{[^,]*}}, .LBB16_1{{$}}
-; CHECK-NEXT:  .LBB16_5:
+; CHECK:       br_if {{[^,]*}}, 0{{$}}
+; CHECK-NEXT:  end_loop{{$}}
 ; CHECK-NOT:   block
 ; CHECK:       unreachable
 ; OPT-LABEL: test7:
 ; OPT:       .LBB16_1:
 ; CHECK-NOT:   block
 ; CHECK:       unreachable
 ; OPT-LABEL: test7:
 ; OPT:       .LBB16_1:
-; OPT-NEXT:  loop .LBB16_5{{$}}
+; OPT-NEXT:  loop{{$}}
 ; OPT-NOT:   block
 ; OPT-NOT:   block
-; OPT:       block .LBB16_4{{$}}
+; OPT:       block{{$}}
 ; OPT-NOT:   block
 ; OPT-NOT:   block
-; OPT:       br_if {{[^,]*}}, .LBB16_4{{$}}
+; OPT:       br_if {{[^,]*}}, 0{{$}}
 ; OPT-NOT:   block
 ; OPT-NOT:   block
-; OPT:       br_if {{[^,]*}}, .LBB16_1{{$}}
+; OPT:       br_if {{[^,]*}}, 1{{$}}
 ; OPT-NOT:   block
 ; OPT:       unreachable
 ; OPT-NOT:   block
 ; OPT:       unreachable
-; OPT_NEXT:  .LBB16_4:
+; OPT-NEXT:  .LBB16_4:
+; OPT-NEXT:  end_block{{$}}
 ; OPT-NOT:   block
 ; OPT-NOT:   block
-; OPT:       br_if {{[^,]*}}, .LBB16_1{{$}}
-; OPT-NEXT:  .LBB16_5:
+; OPT:       br_if {{[^,]*}}, 0{{$}}
+; OPT-NEXT:  end_loop{{$}}
 ; OPT-NOT:   block
 ; OPT:       unreachable
 define void @test7(i1 %tobool2, i1 %tobool9) {
 ; OPT-NOT:   block
 ; OPT:       unreachable
 define void @test7(i1 %tobool2, i1 %tobool9) {
@@ -701,29 +724,31 @@ u1:
 
 ; CHECK-LABEL: test8:
 ; CHECK:       .LBB17_1:
 
 ; CHECK-LABEL: test8:
 ; CHECK:       .LBB17_1:
-; CHECK-NEXT:  loop     .LBB17_4{{$}}
-; CHECK-NEXT:  block    .LBB17_3{{$}}
+; CHECK-NEXT:  loop{{$}}
+; CHECK-NEXT:  block{{$}}
 ; CHECK-NOT:   block
 ; CHECK-NOT:   block
-; CHECK:       br_if    {{[^,]*}}, .LBB17_3{{$}}
+; CHECK:       br_if    {{[^,]*}}, 0{{$}}
 ; CHECK-NOT:   block
 ; CHECK-NOT:   block
-; CHECK:       br_if    {{[^,]*}}, .LBB17_1{{$}}
+; CHECK:       br_if    {{[^,]*}}, 1{{$}}
 ; CHECK-NEXT:  .LBB17_3:
 ; CHECK-NEXT:  .LBB17_3:
-; CHECK-NEXT:  loop     .LBB17_4{{$}}
-; CHECK-NEXT:  br_if    {{[^,]*}}, .LBB17_3{{$}}
-; CHECK-NEXT:  br       .LBB17_1{{$}}
+; CHECK-NEXT:  end_block{{$}}
+; CHECK-NEXT:  loop{{$}}
+; CHECK-NEXT:  br_if    {{[^,]*}}, 0{{$}}
+; CHECK-NEXT:  br       2{{$}}
 ; CHECK-NEXT:  .LBB17_4:
 ; OPT-LABEL: test8:
 ; OPT:       .LBB17_1:
 ; CHECK-NEXT:  .LBB17_4:
 ; OPT-LABEL: test8:
 ; OPT:       .LBB17_1:
-; OPT-NEXT:  loop     .LBB17_4{{$}}
-; OPT-NEXT:  block    .LBB17_3{{$}}
+; OPT-NEXT:  loop{{$}}
+; OPT-NEXT:  block{{$}}
 ; OPT-NOT:   block
 ; OPT-NOT:   block
-; OPT:       br_if    {{[^,]*}}, .LBB17_3{{$}}
+; OPT:       br_if    {{[^,]*}}, 0{{$}}
 ; OPT-NOT:   block
 ; OPT-NOT:   block
-; OPT:       br_if    {{[^,]*}}, .LBB17_1{{$}}
+; OPT:       br_if    {{[^,]*}}, 1{{$}}
 ; OPT-NEXT:  .LBB17_3:
 ; OPT-NEXT:  .LBB17_3:
-; OPT-NEXT:  loop     .LBB17_4{{$}}
-; OPT-NEXT:  br_if    {{[^,]*}}, .LBB17_3{{$}}
-; OPT-NEXT:  br       .LBB17_1{{$}}
+; OPT-NEXT:  end_block{{$}}
+; OPT-NEXT:  loop{{$}}
+; OPT-NEXT:  br_if    {{[^,]*}}, 0{{$}}
+; OPT-NEXT:  br       2{{$}}
 ; OPT-NEXT:  .LBB17_4:
 define i32 @test8() {
 bb:
 ; OPT-NEXT:  .LBB17_4:
 define i32 @test8() {
 bb:
@@ -747,43 +772,45 @@ bb3:
 
 ; CHECK-LABEL: test9:
 ; CHECK:       .LBB18_1:
 
 ; CHECK-LABEL: test9:
 ; CHECK:       .LBB18_1:
-; CHECK-NEXT:  loop      .LBB18_5{{$}}
+; CHECK-NEXT:  loop{{$}}
 ; CHECK-NOT:   block
 ; CHECK-NOT:   block
-; CHECK:       br_if     {{[^,]*}}, .LBB18_5{{$}}
+; CHECK:       br_if     {{[^,]*}}, 1{{$}}
 ; CHECK-NEXT:  .LBB18_2:
 ; CHECK-NEXT:  .LBB18_2:
-; CHECK-NEXT:  loop      .LBB18_5{{$}}
+; CHECK-NEXT:  loop{{$}}
 ; CHECK-NOT:   block
 ; CHECK-NOT:   block
-; CHECK:       block     .LBB18_4{{$}}
+; CHECK:       block{{$}}
 ; CHECK-NOT:   block
 ; CHECK-NOT:   block
-; CHECK:       br_if     {{[^,]*}}, .LBB18_4{{$}}
+; CHECK:       br_if     {{[^,]*}}, 0{{$}}
 ; CHECK-NOT:   block
 ; CHECK-NOT:   block
-; CHECK:       br_if     {{[^,]*}}, .LBB18_2{{$}}
-; CHECK-NEXT:  br        .LBB18_1{{$}}
+; CHECK:       br_if     {{[^,]*}}, 1{{$}}
+; CHECK-NEXT:  br        3{{$}}
 ; CHECK-NEXT:  .LBB18_4:
 ; CHECK-NEXT:  .LBB18_4:
+; CHECK-NEXT:  end_block{{$}}
 ; CHECK-NOT:   block
 ; CHECK-NOT:   block
-; CHECK:       br_if     {{[^,]*}}, .LBB18_2{{$}}
-; CHECK-NEXT:  br        .LBB18_1{{$}}
+; CHECK:       br_if     {{[^,]*}}, 0{{$}}
+; CHECK-NEXT:  br        2{{$}}
 ; CHECK-NEXT:  .LBB18_5:
 ; CHECK-NOT:   block
 ; CHECK:       return{{$}}
 ; OPT-LABEL: test9:
 ; OPT:       .LBB18_1:
 ; CHECK-NEXT:  .LBB18_5:
 ; CHECK-NOT:   block
 ; CHECK:       return{{$}}
 ; OPT-LABEL: test9:
 ; OPT:       .LBB18_1:
-; OPT-NEXT:  loop      .LBB18_5{{$}}
+; OPT-NEXT:  loop{{$}}
 ; OPT-NOT:   block
 ; OPT-NOT:   block
-; OPT:       br_if     {{[^,]*}}, .LBB18_5{{$}}
+; OPT:       br_if     {{[^,]*}}, 1{{$}}
 ; OPT-NEXT:  .LBB18_2:
 ; OPT-NEXT:  .LBB18_2:
-; OPT-NEXT:  loop      .LBB18_5{{$}}
+; OPT-NEXT:  loop{{$}}
 ; OPT-NOT:   block
 ; OPT-NOT:   block
-; OPT:       block     .LBB18_4{{$}}
+; OPT:       block{{$}}
 ; OPT-NOT:   block
 ; OPT-NOT:   block
-; OPT:       br_if     {{[^,]*}}, .LBB18_4{{$}}
+; OPT:       br_if     {{[^,]*}}, 0{{$}}
 ; OPT-NOT:   block
 ; OPT-NOT:   block
-; OPT:       br_if     {{[^,]*}}, .LBB18_2{{$}}
-; OPT-NEXT:  br        .LBB18_1{{$}}
+; OPT:       br_if     {{[^,]*}}, 1{{$}}
+; OPT-NEXT:  br        3{{$}}
 ; OPT-NEXT:  .LBB18_4:
 ; OPT-NEXT:  .LBB18_4:
+; OPT-NEXT:  end_block{{$}}
 ; OPT-NOT:   block
 ; OPT-NOT:   block
-; OPT:       br_if     {{[^,]*}}, .LBB18_2{{$}}
-; OPT-NEXT:  br        .LBB18_1{{$}}
+; OPT:       br_if     {{[^,]*}}, 0{{$}}
+; OPT-NEXT:  br        2{{$}}
 ; OPT-NEXT:  .LBB18_5:
 ; OPT-NOT:   block
 ; OPT:       return{{$}}
 ; OPT-NEXT:  .LBB18_5:
 ; OPT-NOT:   block
 ; OPT:       return{{$}}
@@ -823,45 +850,51 @@ end:
 
 ; CHECK-LABEL: test10:
 ; CHECK:       .LBB19_1:
 
 ; CHECK-LABEL: test10:
 ; CHECK:       .LBB19_1:
-; CHECK-NEXT:  loop     .LBB19_7{{$}}
+; CHECK-NEXT:  loop{{$}}
 ; CHECK-NOT:   block
 ; CHECK-NOT:   block
-; CHECK:       br_if    {{[^,]*}}, .LBB19_1{{$}}
+; CHECK:       br_if    {{[^,]*}}, 0{{$}}
 ; CHECK-NEXT:  .LBB19_2:
 ; CHECK-NEXT:  .LBB19_2:
-; CHECK-NEXT:  block    .LBB19_6{{$}}
-; CHECK-NEXT:  loop     .LBB19_5{{$}}
+; CHECK-NEXT:  block{{$}}
+; CHECK-NEXT:  loop{{$}}
 ; CHECK-NOT:   block
 ; CHECK:       .LBB19_3:
 ; CHECK-NOT:   block
 ; CHECK:       .LBB19_3:
-; CHECK-NEXT:  loop     .LBB19_5{{$}}
+; CHECK-NEXT:  loop{{$}}
 ; CHECK-NOT:   block
 ; CHECK-NOT:   block
-; CHECK:       br_if    {{[^,]*}}, .LBB19_1{{$}}
+; CHECK:       br_if    {{[^,]*}}, 5{{$}}
 ; CHECK-NOT:   block
 ; CHECK-NOT:   block
-; CHECK:       tableswitch  {{[^,]*}}, .LBB19_3, .LBB19_3, .LBB19_5, .LBB19_1, .LBB19_2, .LBB19_6{{$}}
+; CHECK:       tableswitch  {{[^,]*}}, 0, 0, 1, 5, 2, 4{{$}}
 ; CHECK-NEXT:  .LBB19_5:
 ; CHECK-NEXT:  .LBB19_5:
+; CHECK-NEXT:  end_loop{{$}}
+; CHECK-NEXT:  end_loop{{$}}
 ; CHECK-NEXT:  return{{$}}
 ; CHECK-NEXT:  .LBB19_6:
 ; CHECK-NEXT:  return{{$}}
 ; CHECK-NEXT:  .LBB19_6:
+; CHECK-NEXT:  end_block{{$}}
 ; CHECK-NOT:   block
 ; CHECK-NOT:   block
-; CHECK:       br       .LBB19_1{{$}}
+; CHECK:       br       0{{$}}
 ; CHECK-NEXT:  .LBB19_7:
 ; OPT-LABEL: test10:
 ; OPT:       .LBB19_1:
 ; CHECK-NEXT:  .LBB19_7:
 ; OPT-LABEL: test10:
 ; OPT:       .LBB19_1:
-; OPT-NEXT:  loop     .LBB19_7{{$}}
+; OPT-NEXT:  loop{{$}}
 ; OPT-NOT:   block
 ; OPT-NOT:   block
-; OPT:       br_if    {{[^,]*}}, .LBB19_1{{$}}
+; OPT:       br_if    {{[^,]*}}, 0{{$}}
 ; OPT-NEXT:  .LBB19_2:
 ; OPT-NEXT:  .LBB19_2:
-; OPT-NEXT:  block    .LBB19_6{{$}}
-; OPT-NEXT:  loop     .LBB19_5{{$}}
+; OPT-NEXT:  block{{$}}
+; OPT-NEXT:  loop{{$}}
 ; OPT-NOT:   block
 ; OPT:       .LBB19_3:
 ; OPT-NOT:   block
 ; OPT:       .LBB19_3:
-; OPT-NEXT:  loop     .LBB19_5{{$}}
+; OPT-NEXT:  loop{{$}}
 ; OPT-NOT:   block
 ; OPT-NOT:   block
-; OPT:       br_if    {{[^,]*}}, .LBB19_1{{$}}
+; OPT:       br_if    {{[^,]*}}, 5{{$}}
 ; OPT-NOT:   block
 ; OPT-NOT:   block
-; OPT:       tableswitch  {{[^,]*}}, .LBB19_3, .LBB19_3, .LBB19_5, .LBB19_1, .LBB19_2, .LBB19_6{{$}}
+; OPT:       tableswitch  {{[^,]*}}, 0, 0, 1, 5, 2, 4{{$}}
 ; OPT-NEXT:  .LBB19_5:
 ; OPT-NEXT:  .LBB19_5:
+; OPT-NEXT:  end_loop{{$}}
+; OPT-NEXT:  end_loop{{$}}
 ; OPT-NEXT:  return{{$}}
 ; OPT-NEXT:  .LBB19_6:
 ; OPT-NEXT:  return{{$}}
 ; OPT-NEXT:  .LBB19_6:
+; OPT-NEXT:  end_block{{$}}
 ; OPT-NOT:   block
 ; OPT-NOT:   block
-; OPT:       br       .LBB19_1{{$}}
+; OPT:       br       0{{$}}
 ; OPT-NEXT:  .LBB19_7:
 define void @test10() {
 bb0:
 ; OPT-NEXT:  .LBB19_7:
 define void @test10() {
 bb0:
@@ -901,58 +934,67 @@ bb6:
 ; Test a CFG DAG with interesting merging.
 
 ; CHECK-LABEL: test11:
 ; Test a CFG DAG with interesting merging.
 
 ; CHECK-LABEL: test11:
-; CHECK:       block        .LBB20_8{{$}}
-; CHECK-NEXT:  block        .LBB20_7{{$}}
-; CHECK-NEXT:  block        .LBB20_6{{$}}
-; CHECK-NEXT:  block        .LBB20_4{{$}}
-; CHECK-NEXT:  br_if        {{[^,]*}}, .LBB20_4{{$}}
+; CHECK:       block{{$}}
+; CHECK-NEXT:  block{{$}}
+; CHECK-NEXT:  block{{$}}
+; CHECK-NEXT:  block{{$}}
+; CHECK-NEXT:  br_if        {{[^,]*}}, 0{{$}}
+; CHECK-NEXT:  block{{$}}
 ; CHECK-NOT:   block
 ; CHECK-NOT:   block
-; CHECK:       block        .LBB20_3{{$}}
-; CHECK:       br_if        {{[^,]*}}, .LBB20_3{{$}}
+; CHECK:       br_if        {{[^,]*}}, 0{{$}}
 ; CHECK-NOT:   block
 ; CHECK-NOT:   block
-; CHECK:       br_if        {{[^,]*}}, .LBB20_6{{$}}
+; CHECK:       br_if        {{[^,]*}}, 2{{$}}
 ; CHECK-NEXT:  .LBB20_3:
 ; CHECK-NEXT:  .LBB20_3:
+; CHECK-NEXT:  end_block{{$}}
 ; CHECK-NOT:   block
 ; CHECK:       return{{$}}
 ; CHECK-NEXT:  .LBB20_4:
 ; CHECK-NOT:   block
 ; CHECK:       return{{$}}
 ; CHECK-NEXT:  .LBB20_4:
+; CHECK-NEXT:  end_block{{$}}
 ; CHECK-NOT:   block
 ; CHECK-NOT:   block
-; CHECK:       br_if        {{[^,]*}}, .LBB20_8{{$}}
+; CHECK:       br_if        {{[^,]*}}, 2{{$}}
 ; CHECK-NOT:   block
 ; CHECK-NOT:   block
-; CHECK:       br_if        {{[^,]*}}, .LBB20_7{{$}}
+; CHECK:       br_if        {{[^,]*}}, 1{{$}}
 ; CHECK-NEXT:  .LBB20_6:
 ; CHECK-NEXT:  .LBB20_6:
+; CHECK-NEXT:  end_block{{$}}
 ; CHECK-NOT:   block
 ; CHECK:       return{{$}}
 ; CHECK-NEXT:  .LBB20_7:
 ; CHECK-NOT:   block
 ; CHECK:       return{{$}}
 ; CHECK-NEXT:  .LBB20_7:
+; CHECK-NEXT:  end_block{{$}}
 ; CHECK-NOT:   block
 ; CHECK:       return{{$}}
 ; CHECK-NEXT:  .LBB20_8:
 ; CHECK-NOT:   block
 ; CHECK:       return{{$}}
 ; CHECK-NEXT:  .LBB20_8:
+; CHECK-NEXT:  end_block{{$}}
 ; CHECK-NOT:   block
 ; CHECK:       return{{$}}
 ; OPT-LABEL: test11:
 ; CHECK-NOT:   block
 ; CHECK:       return{{$}}
 ; OPT-LABEL: test11:
-; OPT:       block        .LBB20_8{{$}}
-; OPT-NEXT:  block        .LBB20_4{{$}}
-; OPT-NEXT:  br_if        $0, .LBB20_4{{$}}
+; OPT:       block{{$}}
+; OPT-NEXT:  block{{$}}
+; OPT-NEXT:  br_if        $0, 0{{$}}
+; OPT-NEXT:  block{{$}}
 ; OPT-NOT:   block
 ; OPT-NOT:   block
-; OPT:       block        .LBB20_3{{$}}
-; OPT:       br_if        $0, .LBB20_3{{$}}
+; OPT:       br_if        $0, 0{{$}}
 ; OPT-NOT:   block
 ; OPT-NOT:   block
-; OPT:       br_if        $0, .LBB20_8{{$}}
+; OPT:       br_if        $0, 2{{$}}
 ; OPT-NEXT:  .LBB20_3:
 ; OPT-NEXT:  .LBB20_3:
+; OPT-NEXT:  end_block{{$}}
 ; OPT-NOT:   block
 ; OPT:       return{{$}}
 ; OPT-NEXT:  .LBB20_4:
 ; OPT-NOT:   block
 ; OPT:       return{{$}}
 ; OPT-NEXT:  .LBB20_4:
+; OPT-NEXT:  end_block{{$}}
 ; OPT-NOT:   block
 ; OPT-NOT:   block
-; OPT:       block        .LBB20_6{{$}}
+; OPT:       block{{$}}
 ; OPT-NOT:   block
 ; OPT-NOT:   block
-; OPT:       br_if        $pop9, .LBB20_6{{$}}
+; OPT:       br_if        $pop9, 0{{$}}
 ; OPT-NOT:   block
 ; OPT:       return{{$}}
 ; OPT-NEXT:  .LBB20_6:
 ; OPT-NOT:   block
 ; OPT:       return{{$}}
 ; OPT-NEXT:  .LBB20_6:
+; OPT-NEXT:  end_block{{$}}
 ; OPT-NOT:   block
 ; OPT-NOT:   block
-; OPT:       br_if        $0, .LBB20_8{{$}}
+; OPT:       br_if        $0, 0{{$}}
 ; OPT-NOT:   block
 ; OPT:       return{{$}}
 ; OPT-NEXT:  .LBB20_8:
 ; OPT-NOT:   block
 ; OPT:       return{{$}}
 ; OPT-NEXT:  .LBB20_8:
+; OPT-NEXT:  end_block{{$}}
 ; OPT-NOT:   block
 ; OPT:       return{{$}}
 define void @test11() {
 ; OPT-NOT:   block
 ; OPT:       return{{$}}
 define void @test11() {
@@ -987,51 +1029,57 @@ bb8:
 
 ; CHECK-LABEL: test12:
 ; CHECK:       .LBB21_1:
 
 ; CHECK-LABEL: test12:
 ; CHECK:       .LBB21_1:
-; CHECK-NEXT:  loop        .LBB21_8{{$}}
+; CHECK-NEXT:  loop{{$}}
 ; CHECK-NOT:   block
 ; CHECK-NOT:   block
-; CHECK:       block       .LBB21_7{{$}}
-; CHECK-NEXT:  block       .LBB21_6{{$}}
-; CHECK-NEXT:  block       .LBB21_4{{$}}
-; CHECK:       br_if       {{[^,]*}}, .LBB21_4{{$}}
+; CHECK:       block{{$}}
+; CHECK-NEXT:  block{{$}}
+; CHECK-NEXT:  block{{$}}
+; CHECK:       br_if       {{[^,]*}}, 0{{$}}
 ; CHECK-NOT:   block
 ; CHECK-NOT:   block
-; CHECK:       br_if       {{[^,]*}}, .LBB21_7{{$}}
+; CHECK:       br_if       {{[^,]*}}, 2{{$}}
 ; CHECK-NOT:   block
 ; CHECK-NOT:   block
-; CHECK:       br_if       {{[^,]*}}, .LBB21_7{{$}}
-; CHECK-NEXT:  br          .LBB21_6{{$}}
+; CHECK:       br_if       {{[^,]*}}, 2{{$}}
+; CHECK-NEXT:  br          1{{$}}
 ; CHECK-NEXT:  .LBB21_4:
 ; CHECK-NEXT:  .LBB21_4:
+; CHECK-NEXT:  end_block{{$}}
 ; CHECK-NOT:   block
 ; CHECK-NOT:   block
-; CHECK:       br_if       {{[^,]*}}, .LBB21_7{{$}}
+; CHECK:       br_if       {{[^,]*}}, 1{{$}}
 ; CHECK-NOT:   block
 ; CHECK-NOT:   block
-; CHECK:       br_if       {{[^,]*}}, .LBB21_7{{$}}
+; CHECK:       br_if       {{[^,]*}}, 1{{$}}
 ; CHECK-NEXT:  .LBB21_6:
 ; CHECK-NEXT:  .LBB21_6:
+; CHECK-NEXT:  end_block{{$}}
 ; CHECK-NEXT:  return{{$}}
 ; CHECK-NEXT:  .LBB21_7:
 ; CHECK-NEXT:  return{{$}}
 ; CHECK-NEXT:  .LBB21_7:
+; CHECK-NEXT:  end_block{{$}}
 ; CHECK-NOT:   block
 ; CHECK-NOT:   block
-; CHECK:       br          .LBB21_1{{$}}
+; CHECK:       br          0{{$}}
 ; CHECK-NEXT:  .LBB21_8:
 ; OPT-LABEL: test12:
 ; OPT:       .LBB21_1:
 ; CHECK-NEXT:  .LBB21_8:
 ; OPT-LABEL: test12:
 ; OPT:       .LBB21_1:
-; OPT-NEXT:  loop        .LBB21_8{{$}}
+; OPT-NEXT:  loop{{$}}
 ; OPT-NOT:   block
 ; OPT-NOT:   block
-; OPT:       block       .LBB21_7{{$}}
-; OPT-NEXT:  block       .LBB21_6{{$}}
-; OPT-NEXT:  block       .LBB21_4{{$}}
-; OPT:       br_if       {{[^,]*}}, .LBB21_4{{$}}
+; OPT:       block{{$}}
+; OPT-NEXT:  block{{$}}
+; OPT-NEXT:  block{{$}}
+; OPT:       br_if       {{[^,]*}}, 0{{$}}
 ; OPT-NOT:   block
 ; OPT-NOT:   block
-; OPT:       br_if       {{[^,]*}}, .LBB21_7{{$}}
+; OPT:       br_if       {{[^,]*}}, 2{{$}}
 ; OPT-NOT:   block
 ; OPT-NOT:   block
-; OPT:       br_if       {{[^,]*}}, .LBB21_7{{$}}
-; OPT-NEXT:  br          .LBB21_6{{$}}
+; OPT:       br_if       {{[^,]*}}, 2{{$}}
+; OPT-NEXT:  br          1{{$}}
 ; OPT-NEXT:  .LBB21_4:
 ; OPT-NEXT:  .LBB21_4:
+; OPT-NEXT:  end_block{{$}}
 ; OPT-NOT:   block
 ; OPT-NOT:   block
-; OPT:       br_if       {{[^,]*}}, .LBB21_7{{$}}
+; OPT:       br_if       {{[^,]*}}, 1{{$}}
 ; OPT-NOT:   block
 ; OPT-NOT:   block
-; OPT:       br_if       {{[^,]*}}, .LBB21_7{{$}}
+; OPT:       br_if       {{[^,]*}}, 1{{$}}
 ; OPT-NEXT:  .LBB21_6:
 ; OPT-NEXT:  .LBB21_6:
+; OPT-NEXT:  end_block{{$}}
 ; OPT-NEXT:  return{{$}}
 ; OPT-NEXT:  .LBB21_7:
 ; OPT-NEXT:  return{{$}}
 ; OPT-NEXT:  .LBB21_7:
+; OPT-NEXT:  end_block{{$}}
 ; OPT-NOT:   block
 ; OPT-NOT:   block
-; OPT:       br          .LBB21_1{{$}}
+; OPT:       br          0{{$}}
 ; OPT-NEXT:  .LBB21_8:
 define void @test12(i8* %arg) {
 bb:
 ; OPT-NEXT:  .LBB21_8:
 define void @test12(i8* %arg) {
 bb:
@@ -1061,30 +1109,34 @@ bb7:
 ; optnone to disable optimizations to test this case.
 
 ; CHECK-LABEL: test13:
 ; optnone to disable optimizations to test this case.
 
 ; CHECK-LABEL: test13:
-; CHECK-NEXT:  .local i32{{$}}
-; CHECK:       block .LBB22_2{{$}}
-; CHECK:       br_if $pop4, .LBB22_2{{$}}
+; CHECK-NEXT:  local i32{{$}}
+; CHECK:       block{{$}}
+; CHECK:       br_if $pop4, 0{{$}}
 ; CHECK-NEXT:  return{{$}}
 ; CHECK-NEXT:  .LBB22_2:
 ; CHECK-NEXT:  return{{$}}
 ; CHECK-NEXT:  .LBB22_2:
-; CHECK:       block .LBB22_4{{$}}
-; CHECK-NEXT:  br_if $0, .LBB22_4{{$}}
+; CHECK-NEXT:  end_block{{$}}
+; CHECK:       block{{$}}
+; CHECK-NEXT:  br_if $0, 0{{$}}
 ; CHECK:       .LBB22_4:
 ; CHECK:       .LBB22_4:
-; CHECK:       block .LBB22_5{{$}}
-; CHECK:       br_if $pop6, .LBB22_5{{$}}
-; CHECK-NEXT:  .LBB22_5:
+; CHECK-NEXT:  end_block{{$}}
+; CHECK:       block{{$}}
+; CHECK:       br_if $pop6, 0{{$}}
+; CHECK-NEXT:  end_block{{$}}
 ; CHECK-NEXT:  unreachable{{$}}
 ; OPT-LABEL: test13:
 ; CHECK-NEXT:  unreachable{{$}}
 ; OPT-LABEL: test13:
-; OPT-NEXT:  .local i32{{$}}
-; OPT:       block .LBB22_2{{$}}
-; OPT:       br_if $pop4, .LBB22_2{{$}}
+; OPT-NEXT:  local i32{{$}}
+; OPT:       block{{$}}
+; OPT:       br_if $pop4, 0{{$}}
 ; OPT-NEXT:  return{{$}}
 ; OPT-NEXT:  .LBB22_2:
 ; OPT-NEXT:  return{{$}}
 ; OPT-NEXT:  .LBB22_2:
-; OPT:       block .LBB22_4{{$}}
-; OPT-NEXT:  br_if $0, .LBB22_4{{$}}
+; OPT-NEXT:  end_block{{$}}
+; OPT:       block{{$}}
+; OPT-NEXT:  br_if $0, 0{{$}}
 ; OPT:       .LBB22_4:
 ; OPT:       .LBB22_4:
-; OPT:       block .LBB22_5{{$}}
-; OPT:       br_if $pop6, .LBB22_5{{$}}
-; OPT-NEXT:  .LBB22_5:
+; OPT-NEXT:  end_block{{$}}
+; OPT:       block{{$}}
+; OPT:       br_if $pop6, 0{{$}}
+; OPT-NEXT:  end_block{{$}}
 ; OPT-NEXT:  unreachable{{$}}
 define void @test13() noinline optnone {
 bb:
 ; OPT-NEXT:  unreachable{{$}}
 define void @test13() noinline optnone {
 bb:
@@ -1101,3 +1153,65 @@ bb4:
 bb5:
   ret void
 }
 bb5:
   ret void
 }
+
+; Test a case with a single-block loop that has another loop
+; as a successor. The end_loop for the first loop should go
+; before the loop for the second.
+
+; CHECK-LABEL: test14:
+; CHECK-NEXT:     local       i32{{$}}
+; CHECK-NEXT:     i32.const   $0=, 0{{$}}
+; CHECK-NEXT: .LBB23_1:{{$}}
+; CHECK-NEXT:     loop{{$}}
+; CHECK-NEXT:     br_if       $0, 0{{$}}
+; CHECK-NEXT: .LBB23_2:{{$}}
+; CHECK-NEXT:     end_loop{{$}}
+; CHECK-NEXT:     loop{{$}}
+; CHECK-NEXT:     br_if       $0, 0{{$}}
+; CHECK-NEXT:     end_loop{{$}}
+; CHECK-NEXT:     return{{$}}
+define void @test14() {
+bb:
+  br label %bb1
+
+bb1:
+  %tmp = bitcast i1 undef to i1
+  br i1 %tmp, label %bb3, label %bb1
+
+bb3:
+  br label %bb4
+
+bb4:
+  br i1 undef, label %bb7, label %bb48
+
+bb7:
+  br i1 undef, label %bb12, label %bb12
+
+bb12:
+  br i1 undef, label %bb17, label %bb17
+
+bb17:
+  br i1 undef, label %bb22, label %bb22
+
+bb22:
+  br i1 undef, label %bb27, label %bb27
+
+bb27:
+  br i1 undef, label %bb30, label %bb30
+
+bb30:
+  br i1 undef, label %bb35, label %bb35
+
+bb35:
+  br i1 undef, label %bb38, label %bb38
+
+bb38:
+  br i1 undef, label %bb48, label %bb48
+
+bb48:
+  %tmp49 = bitcast i1 undef to i1
+  br i1 %tmp49, label %bb3, label %bb50
+
+bb50:
+  ret void
+}
index 768d5746c98068f46e29a6c02d4e23e935544e5b..f8cae7f924046f9781dfc46ce6bdf9e504b077bb 100644 (file)
@@ -55,7 +55,7 @@ define i32 @yes1(i32* %q) {
 ; CHECK-NEXT: .local i32, i32{{$}}
 ; CHECK-NEXT: i32.const   $5=, 2{{$}}
 ; CHECK-NEXT: i32.const   $4=, 1{{$}}
 ; CHECK-NEXT: .local i32, i32{{$}}
 ; CHECK-NEXT: i32.const   $5=, 2{{$}}
 ; CHECK-NEXT: i32.const   $4=, 1{{$}}
-; CHECK-NEXT: block       .LBB4_2{{$}}
+; CHECK-NEXT: block{{$}}
 ; CHECK-NEXT: i32.lt_s    $push0=, $0, $4{{$}}
 ; CHECK-NEXT: i32.lt_s    $push1=, $1, $5{{$}}
 ; CHECK-NEXT: i32.xor     $push4=, $pop0, $pop1{{$}}
 ; CHECK-NEXT: i32.lt_s    $push0=, $0, $4{{$}}
 ; CHECK-NEXT: i32.lt_s    $push1=, $1, $5{{$}}
 ; CHECK-NEXT: i32.xor     $push4=, $pop0, $pop1{{$}}
@@ -64,10 +64,11 @@ define i32 @yes1(i32* %q) {
 ; CHECK-NEXT: i32.xor     $push5=, $pop2, $pop3{{$}}
 ; CHECK-NEXT: i32.xor     $push6=, $pop4, $pop5{{$}}
 ; CHECK-NEXT: i32.ne      $push7=, $pop6, $4{{$}}
 ; CHECK-NEXT: i32.xor     $push5=, $pop2, $pop3{{$}}
 ; CHECK-NEXT: i32.xor     $push6=, $pop4, $pop5{{$}}
 ; CHECK-NEXT: i32.ne      $push7=, $pop6, $4{{$}}
-; CHECK-NEXT: br_if       $pop7, .LBB4_2{{$}}
+; CHECK-NEXT: br_if       $pop7, 0{{$}}
 ; CHECK-NEXT: i32.const   $push8=, 0{{$}}
 ; CHECK-NEXT: return      $pop8{{$}}
 ; CHECK-NEXT: .LBB4_2:
 ; CHECK-NEXT: i32.const   $push8=, 0{{$}}
 ; CHECK-NEXT: return      $pop8{{$}}
 ; CHECK-NEXT: .LBB4_2:
+; CHECK-NEXT: end_block{{$}}
 ; CHECK-NEXT: return      $4{{$}}
 define i32 @stack_uses(i32 %x, i32 %y, i32 %z, i32 %w) {
 entry:
 ; CHECK-NEXT: return      $4{{$}}
 define i32 @stack_uses(i32 %x, i32 %y, i32 %z, i32 %w) {
 entry:
@@ -89,16 +90,17 @@ false:
 ; be trivially stackified.
 
 ; CHECK-LABEL: multiple_uses:
 ; be trivially stackified.
 
 ; CHECK-LABEL: multiple_uses:
-; CHECK-NEXT: .param      i32, i32, i32{{$}}
-; CHECK-NEXT: .local      i32{{$}}
+; CHECK-NEXT: .param       i32, i32, i32{{$}}
+; CHECK-NEXT: .local       i32{{$}}
 ; CHECK-NEXT: i32.load    $3=, 0($2){{$}}
 ; CHECK-NEXT: i32.load    $3=, 0($2){{$}}
-; CHECK-NEXT: block       .LBB5_3{{$}}
+; CHECK-NEXT: block{{$}}
 ; CHECK-NEXT: i32.ge_u    $push0=, $3, $1{{$}}
 ; CHECK-NEXT: i32.ge_u    $push0=, $3, $1{{$}}
-; CHECK-NEXT: br_if       $pop0, .LBB5_3{{$}}
+; CHECK-NEXT: br_if       $pop0, 0{{$}}
 ; CHECK-NEXT: i32.lt_u    $push1=, $3, $0{{$}}
 ; CHECK-NEXT: i32.lt_u    $push1=, $3, $0{{$}}
-; CHECK-NEXT: br_if       $pop1, .LBB5_3{{$}}
+; CHECK-NEXT: br_if       $pop1, 0{{$}}
 ; CHECK-NEXT: i32.store   $discard=, 0($2), $3{{$}}
 ; CHECK-NEXT: .LBB5_3:
 ; CHECK-NEXT: i32.store   $discard=, 0($2), $3{{$}}
 ; CHECK-NEXT: .LBB5_3:
+; CHECK-NEXT: end_block{{$}}
 ; CHECK-NEXT: return{{$}}
 define void @multiple_uses(i32* %arg0, i32* %arg1, i32* %arg2) nounwind {
 bb:
 ; CHECK-NEXT: return{{$}}
 define void @multiple_uses(i32* %arg0, i32* %arg1, i32* %arg2) nounwind {
 bb:
index ef35ba11a0d8132b60ec709cbe381edf73e107e6..3df5e7f9cf6fe5327e5f562c8cda6ff5b60288a2 100644 (file)
@@ -14,14 +14,14 @@ declare void @foo4()
 declare void @foo5()
 
 ; CHECK-LABEL: bar32:
 declare void @foo5()
 
 ; CHECK-LABEL: bar32:
-; CHECK: block .LBB0_8{{$}}
-; CHECK: block .LBB0_7{{$}}
-; CHECK: block .LBB0_6{{$}}
-; CHECK: block .LBB0_5{{$}}
-; CHECK: block .LBB0_4{{$}}
-; CHECK: block .LBB0_3{{$}}
-; CHECK: block .LBB0_2{{$}}
-; CHECK: tableswitch {{[^,]*}}, .LBB0_2, .LBB0_2, .LBB0_2, .LBB0_2, .LBB0_2, .LBB0_2, .LBB0_2, .LBB0_2, .LBB0_3, .LBB0_3, .LBB0_3, .LBB0_3, .LBB0_3, .LBB0_3, .LBB0_3, .LBB0_3, .LBB0_4, .LBB0_4, .LBB0_4, .LBB0_4, .LBB0_4, .LBB0_4, .LBB0_5, .LBB0_6, .LBB0_7{{$}}
+; CHECK: block{{$}}
+; CHECK: block{{$}}
+; CHECK: block{{$}}
+; CHECK: block{{$}}
+; CHECK: block{{$}}
+; CHECK: block{{$}}
+; CHECK: block{{$}}
+; CHECK: tableswitch {{[^,]*}}, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 4, 5{{$}}
 ; CHECK: .LBB0_2:
 ; CHECK:   call foo0@FUNCTION{{$}}
 ; CHECK: .LBB0_3:
 ; CHECK: .LBB0_2:
 ; CHECK:   call foo0@FUNCTION{{$}}
 ; CHECK: .LBB0_3:
@@ -94,14 +94,14 @@ sw.epilog:                                        ; preds = %entry, %sw.bb.5, %s
 }
 
 ; CHECK-LABEL: bar64:
 }
 
 ; CHECK-LABEL: bar64:
-; CHECK: block .LBB1_8{{$}}
-; CHECK: block .LBB1_7{{$}}
-; CHECK: block .LBB1_6{{$}}
-; CHECK: block .LBB1_5{{$}}
-; CHECK: block .LBB1_4{{$}}
-; CHECK: block .LBB1_3{{$}}
-; CHECK: block .LBB1_2{{$}}
-; CHECK: tableswitch {{[^,]*}}, .LBB1_2, .LBB1_2, .LBB1_2, .LBB1_2, .LBB1_2, .LBB1_2, .LBB1_2, .LBB1_2, .LBB1_3, .LBB1_3, .LBB1_3, .LBB1_3, .LBB1_3, .LBB1_3, .LBB1_3, .LBB1_3, .LBB1_4, .LBB1_4, .LBB1_4, .LBB1_4, .LBB1_4, .LBB1_4, .LBB1_5, .LBB1_6, .LBB1_7{{$}}
+; CHECK: block{{$}}
+; CHECK: block{{$}}
+; CHECK: block{{$}}
+; CHECK: block{{$}}
+; CHECK: block{{$}}
+; CHECK: block{{$}}
+; CHECK: block{{$}}
+; CHECK: tableswitch {{[^,]*}}, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 4, 5{{$}}
 ; CHECK: .LBB1_2:
 ; CHECK:   call foo0@FUNCTION{{$}}
 ; CHECK: .LBB1_3:
 ; CHECK: .LBB1_2:
 ; CHECK:   call foo0@FUNCTION{{$}}
 ; CHECK: .LBB1_3: