[mips][microMIPS] Delay slot filler: Replace the microMIPS JR with the JRC
authorJozef Kolek <jozef.kolek@imgtec.com>
Fri, 13 Feb 2015 17:51:27 +0000 (17:51 +0000)
committerJozef Kolek <jozef.kolek@imgtec.com>
Fri, 13 Feb 2015 17:51:27 +0000 (17:51 +0000)
This patch adds functionality in MIPS delay slot filler such as if delay slot
filler have to put NOP instruction into the delay slot of microMIPS JR
instruction, then instead of emitting NOP this instruction is replaced by
compact jump instruction JRC.

Differential Revision: http://reviews.llvm.org/D7522

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

lib/Target/Mips/MipsDelaySlotFiller.cpp
test/CodeGen/Mips/longbranch.ll
test/CodeGen/Mips/micromips-compact-jump.ll [new file with mode: 0644]
test/CodeGen/Mips/micromips-delay-slot-jr.ll

index 8c2040d5c16fbf5b2ab0bd920f1539d608e78ac8..ac03c0bd3dde4b5c560d21736813cae1149033bd 100644 (file)
@@ -199,6 +199,9 @@ namespace {
     Iter replaceWithCompactBranch(MachineBasicBlock &MBB,
                                   Iter Branch, DebugLoc DL);
 
+    Iter replaceWithCompactJump(MachineBasicBlock &MBB,
+                                Iter Jump, DebugLoc DL);
+
     /// This function checks if it is valid to move Candidate to the delay slot
     /// and returns true if it isn't. It also updates memory and register
     /// dependence information.
@@ -515,6 +518,24 @@ Iter Filler::replaceWithCompactBranch(MachineBasicBlock &MBB,
   return Branch;
 }
 
+// Replace Jumps with the compact jump instruction.
+Iter Filler::replaceWithCompactJump(MachineBasicBlock &MBB,
+                                    Iter Jump, DebugLoc DL) {
+  const MipsInstrInfo *TII =
+      MBB.getParent()->getSubtarget<MipsSubtarget>().getInstrInfo();
+
+  const MCInstrDesc &NewDesc = TII->get(Mips::JRC16_MM);
+  MachineInstrBuilder MIB = BuildMI(MBB, Jump, DL, NewDesc);
+
+  MIB.addReg(Jump->getOperand(0).getReg());
+
+  Iter tmpIter = Jump;
+  Jump = std::prev(Jump);
+  MBB.erase(tmpIter);
+
+  return Jump;
+}
+
 // For given opcode returns opcode of corresponding instruction with short
 // delay slot.
 static int getEquivalentCallShort(int Opcode) {
@@ -582,17 +603,29 @@ bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
     // adding NOP replace this instruction with the corresponding compact
     // branch instruction, i.e. BEQZC or BNEZC.
     unsigned Opcode = I->getOpcode();
-    if (InMicroMipsMode &&
-        (Opcode == Mips::BEQ || Opcode == Mips::BNE) &&
-        ((unsigned) I->getOperand(1).getReg()) == Mips::ZERO) {
-
-      I = replaceWithCompactBranch(MBB, I, I->getDebugLoc());
-
-    } else {
-      // Bundle the NOP to the instruction with the delay slot.
-      BuildMI(MBB, std::next(I), I->getDebugLoc(), TII->get(Mips::NOP));
-      MIBundleBuilder(MBB, I, std::next(I, 2));
+    if (InMicroMipsMode) {
+      switch (Opcode) {
+        case Mips::BEQ:
+        case Mips::BNE:
+          if (((unsigned) I->getOperand(1).getReg()) == Mips::ZERO) {
+            I = replaceWithCompactBranch(MBB, I, I->getDebugLoc());
+            continue;
+          }
+          break;
+        case Mips::JR:
+        case Mips::PseudoReturn:
+        case Mips::PseudoIndirectBranch:
+          // For microMIPS the PseudoReturn and PseudoIndirectBranch are allways
+          // expanded to JR_MM, so they can be replaced with JRC16_MM.
+          I = replaceWithCompactJump(MBB, I, I->getDebugLoc());
+          continue;
+        default:
+          break;
+      }
     }
+    // Bundle the NOP to the instruction with the delay slot.
+    BuildMI(MBB, std::next(I), I->getDebugLoc(), TII->get(Mips::NOP));
+    MIBundleBuilder(MBB, I, std::next(I, 2));
   }
 
   return Changed;
index 821ced8e7b83391fd04ba43af4184c6e6650c694..f61b250491e94a9211f2469d33db3a40e8936352 100644 (file)
@@ -126,8 +126,7 @@ end:
 ; MICROMIPS:        li16    $[[R2:[0-9]+]], 1
 ; MICROMIPS:        sw16    $[[R2]], 0($[[R1]])
 ; MICROMIPS:   $[[BB2]]:
-; MICROMIPS:        jr      $ra
-; MICROMIPS:        nop
+; MICROMIPS:        jrc      $ra
 
 
 ; Check the NaCl version.  Check that sp change is not in the branch delay slot
diff --git a/test/CodeGen/Mips/micromips-compact-jump.ll b/test/CodeGen/Mips/micromips-compact-jump.ll
new file mode 100644 (file)
index 0000000..70cff84
--- /dev/null
@@ -0,0 +1,11 @@
+; RUN: llc -march=mipsel -mcpu=mips32r2 -mattr=+micromips \
+; RUN:   -disable-mips-delay-filler -O3 < %s | FileCheck %s
+
+define i32 @foo(i32 signext %a) #0 {
+entry:
+  ret i32 0
+}
+
+declare i32 @bar(i32 signext) #1
+
+; CHECK:      jrc
index df593b35e2a6303eae1387b32b5958bf7c0d1d33..09a98c2a7d10cbd761b224ee3406443aa71bba9a 100644 (file)
@@ -29,8 +29,7 @@ declare i32 @puts(i8* nocapture readonly) #1
 !3 = !{!"omnipotent char", !4, i64 0}
 !4 = !{!"Simple C/C++ TBAA"}
 
-; CHECK:      jr
-; CHECK-NEXT: nop
+; CHECK:      jrc
 
 %struct.foostruct = type { [3 x float] }
 %struct.barstruct = type { %struct.foostruct, float }
@@ -43,6 +42,5 @@ define float* @spooky(i32 signext %i) #0 {
 }
 
 ; CHECK:      spooky:
-; CHECK:      jr $ra
-; CHECK-NEXT: nop
+; CHECK:      jrc $ra