Improve Thumb-2 jump table support.
authorDavid Goodwin <david_goodwin@apple.com>
Tue, 30 Jun 2009 19:50:22 +0000 (19:50 +0000)
committerDavid Goodwin <david_goodwin@apple.com>
Tue, 30 Jun 2009 19:50:22 +0000 (19:50 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@74549 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/ARMCodeEmitter.cpp
lib/Target/ARM/ARMConstantIslandPass.cpp
lib/Target/ARM/ARMInstrInfo.cpp
lib/Target/ARM/ARMInstrThumb2.td
test/CodeGen/Thumb2/thumb2-jumptbl.ll [new file with mode: 0644]

index 8424c2eaed1d78b2f8e7c38e6f84b69cd415c97b..f29576148b3280967601640ade6fba53ae5f5b07 100644 (file)
@@ -1155,16 +1155,17 @@ void Emitter<CodeEmitter>::emitMiscBranchInstruction(const MachineInstr &MI) {
   const TargetInstrDesc &TID = MI.getDesc();
 
   // Handle jump tables.
-  if (TID.Opcode == ARM::BR_JTr || TID.Opcode == ARM::BR_JTadd) {
+  if (TID.Opcode == ARM::BR_JTr || TID.Opcode == ARM::BR_JTadd ||
+      TID.Opcode == ARM::t2BR_JTr || TID.Opcode == ARM::t2BR_JTadd) {
     // First emit a ldr pc, [] instruction.
     emitDataProcessingInstruction(MI, ARM::PC);
 
     // Then emit the inline jump table.
-    unsigned JTIndex = (TID.Opcode == ARM::BR_JTr)
+    unsigned JTIndex = (TID.Opcode == ARM::BR_JTr || TID.Opcode == ARM::t2BR_JTr)
       ? MI.getOperand(1).getIndex() : MI.getOperand(2).getIndex();
     emitInlineJumpTable(JTIndex);
     return;
-  } else if (TID.Opcode == ARM::BR_JTm) {
+  } else if (TID.Opcode == ARM::BR_JTm || TID.Opcode == ARM::t2BR_JTm) {
     // First emit a ldr pc, [] instruction.
     emitLoadStoreInstruction(MI, ARM::PC);
 
index 50badfffecd69fe66cbfbfed788c8af8336f514b..19c311c4f280cd5c9fc93bcf2a3a485d101568c0 100644 (file)
@@ -379,6 +379,8 @@ void ARMConstantIslands::InitialFunctionScan(MachineFunction &Fn,
         switch (Opc) {
         case ARM::tBR_JTr:
         case ARM::t2BR_JTr:
+        case ARM::t2BR_JTm:
+        case ARM::t2BR_JTadd:
           // A Thumb table jump may involve padding; for the offsets to
           // be right, functions containing these must be 4-byte aligned.
           AFI->setAlign(2U);
@@ -766,7 +768,9 @@ void ARMConstantIslands::AdjustBBOffsetsAfter(MachineBasicBlock *BB,
         // following unconditional branches are removed by AnalyzeBranch.
         MachineInstr *ThumbJTMI = NULL;
         if ((prior(MBB->end())->getOpcode() == ARM::tBR_JTr)
-            || (prior(MBB->end())->getOpcode() == ARM::t2BR_JTr))
+            || (prior(MBB->end())->getOpcode() == ARM::t2BR_JTr)
+            || (prior(MBB->end())->getOpcode() == ARM::t2BR_JTm)
+            || (prior(MBB->end())->getOpcode() == ARM::t2BR_JTadd))
           ThumbJTMI = prior(MBB->end());
         if (ThumbJTMI) {
           unsigned newMIOffset = GetOffsetOf(ThumbJTMI);
index 5941b1eddb36fad2ab7a5fd2d479f76bc11c1204..35ebb7eec86501419087d67ceeb20fa901bc1519 100644 (file)
@@ -401,7 +401,8 @@ bool
   // correctness of Thumb constant islands.
   if ((SecondLastOpc == ARM::BR_JTr || SecondLastOpc==ARM::BR_JTm ||
        SecondLastOpc == ARM::BR_JTadd || SecondLastOpc==ARM::tBR_JTr ||
-       SecondLastOpc==ARM::t2BR_JTr) &&
+       SecondLastOpc == ARM::t2BR_JTr || SecondLastOpc==ARM::t2BR_JTm ||
+       SecondLastOpc == ARM::t2BR_JTadd) &&
       (LastOpc == ARM::B || LastOpc == ARM::tB || LastOpc == ARM::t2B)) {
     I = LastInst;
     if (AllowModify)
@@ -708,7 +709,9 @@ ARMBaseInstrInfo::BlockHasNoFallThrough(const MachineBasicBlock &MBB) const {
   case ARM::tBR_JTr:
   case ARM::t2BR_JTr:
   case ARM::BR_JTr:   // Jumptable branch.
+  case ARM::t2BR_JTm:
   case ARM::BR_JTm:   // Jumptable branch through mem.
+  case ARM::t2BR_JTadd:
   case ARM::BR_JTadd: // Jumptable branch add to pc.
     return true;
   default: return false;
@@ -846,8 +849,10 @@ unsigned ARMBaseInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const {
     case ARM::BR_JTr:
     case ARM::BR_JTm:
     case ARM::BR_JTadd:
-    case ARM::tBR_JTr:
-    case ARM::t2BR_JTr: {
+    case ARM::t2BR_JTr:
+    case ARM::t2BR_JTm:
+    case ARM::t2BR_JTadd:
+    case ARM::tBR_JTr: {
       // These are jumptable branches, i.e. a branch followed by an inlined
       // jumptable. The size is 4 + 4 * number of entries.
       unsigned NumOps = TID.getNumOperands();
@@ -865,8 +870,7 @@ unsigned ARMBaseInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const {
       // bytes, we can use 16-bit entries instead. Then there won't be an
       // alignment issue.
       return getNumJTEntries(JT, JTI) * 4 +
-        ((MI->getOpcode()==ARM::tBR_JTr || 
-          MI->getOpcode()==ARM::t2BR_JTr) ? 2 : 4);
+        ((MI->getOpcode()==ARM::tBR_JTr) ? 2 : 4);
     }
     default:
       // Otherwise, pseudo-instruction sizes are zero.
index b6d54f0023052bcf50402f6c5dfcfa93b2ee5c1a..8479154319f3a3ed791c5d233e54729e4e80f073 100644 (file)
@@ -698,11 +698,25 @@ def t2B   : T2XI<(outs), (ins brtarget:$target),
                  "b $target",
                  [(br bb:$target)]>;
 
-def t2BR_JTr : T2JTI<(outs),
-                     (ins tGPR:$target, jtblock_operand:$jt, i32imm:$id),
-                     "cpy pc, $target \n\t.align\t2\n$jt",
-                     [(ARMbrjt tGPR:$target, tjumptable:$jt, imm:$id)]>;
-}
+let isNotDuplicable = 1, isIndirectBranch = 1 in {
+def t2BR_JTr : T2JTI<(outs), (ins GPR:$target, jtblock_operand:$jt, i32imm:$id),
+                     "mov pc, $target \n$jt",
+                     [(ARMbrjt GPR:$target, tjumptable:$jt, imm:$id)]>;
+
+def t2BR_JTm : 
+    T2JTI<(outs),
+          (ins t2addrmode_so_reg:$target, jtblock_operand:$jt, i32imm:$id),
+          "ldr pc, $target \n$jt",
+          [(ARMbrjt (i32 (load t2addrmode_so_reg:$target)), tjumptable:$jt,
+             imm:$id)]>;
+
+def t2BR_JTadd : 
+    T2JTI<(outs),
+          (ins GPR:$target, GPR:$idx, jtblock_operand:$jt, i32imm:$id),
+          "add pc, $target, $idx \n$jt",
+          [(ARMbrjt (add GPR:$target, GPR:$idx), tjumptable:$jt, imm:$id)]>;
+} // isNotDuplicate, isIndirectBranch
+} // isBranch, isTerminator, isBarrier
 
 // FIXME: should be able to write a pattern for ARMBrcond, but can't use
 // a two-value operand where a dag node expects two operands. :(
diff --git a/test/CodeGen/Thumb2/thumb2-jumptbl.ll b/test/CodeGen/Thumb2/thumb2-jumptbl.ll
new file mode 100644 (file)
index 0000000..512c669
--- /dev/null
@@ -0,0 +1,26 @@
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep {ldr\\W*pc,} | count 1
+
+define i32 @foo(i32 %a) nounwind  {
+entry:
+       switch i32 %a, label %bb4 [
+                i32 1, label %bb5
+                i32 2, label %bb1
+                i32 3, label %bb2
+                i32 5, label %bb3
+       ]
+
+bb1:           ; preds = %entry
+       ret i32 1
+
+bb2:           ; preds = %entry
+       ret i32 1234
+
+bb3:           ; preds = %entry
+       ret i32 3456
+
+bb4:           ; preds = %entry
+       ret i32 0
+
+bb5:           ; preds = %entry
+       ret i32 12
+}