[llvm] r183088 - Sparc: Combine add/or/sethi instruction with restore if possible.

Venkatraman Govindaraju venkatra at cs.wisc.edu
Sun Jun 2 14:48:17 PDT 2013


Author: venkatra
Date: Sun Jun  2 16:48:17 2013
New Revision: 183088

URL: http://llvm.org/viewvc/llvm-project?rev=183088&view=rev
Log:
Sparc: Combine add/or/sethi instruction with restore if possible.

Modified:
    llvm/trunk/lib/Target/Sparc/DelaySlotFiller.cpp
    llvm/trunk/test/CodeGen/SPARC/2011-01-11-FrameAddr.ll
    llvm/trunk/test/CodeGen/SPARC/2011-01-19-DelaySlot.ll
    llvm/trunk/test/CodeGen/SPARC/64bit.ll
    llvm/trunk/test/CodeGen/SPARC/64cond.ll

Modified: llvm/trunk/lib/Target/Sparc/DelaySlotFiller.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Sparc/DelaySlotFiller.cpp?rev=183088&r1=183087&r2=183088&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Sparc/DelaySlotFiller.cpp (original)
+++ llvm/trunk/lib/Target/Sparc/DelaySlotFiller.cpp Sun Jun  2 16:48:17 2013
@@ -82,6 +82,9 @@ namespace {
 
     bool needsUnimp(MachineBasicBlock::iterator I, unsigned &StructSize);
 
+    bool tryCombineRestoreWithPrevInst(MachineBasicBlock &MBB,
+                                       MachineBasicBlock::iterator MBBI);
+
   };
   char Filler::ID = 0;
 } // end of anonymous namespace
@@ -100,29 +103,44 @@ FunctionPass *llvm::createSparcDelaySlot
 bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
   bool Changed = false;
 
-  for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I)
-    if (I->hasDelaySlot()) {
-      MachineBasicBlock::iterator D = MBB.end();
-      MachineBasicBlock::iterator J = I;
-
-      if (!DisableDelaySlotFiller)
-        D = findDelayInstr(MBB, I);
-
-      ++FilledSlots;
-      Changed = true;
-
-      if (D == MBB.end())
-        BuildMI(MBB, ++J, I->getDebugLoc(), TII->get(SP::NOP));
-      else
-        MBB.splice(++J, &MBB, D);
-      unsigned structSize = 0;
-      if (needsUnimp(I, structSize)) {
-        MachineBasicBlock::iterator J = I;
-        ++J; //skip the delay filler.
-        BuildMI(MBB, ++J, I->getDebugLoc(),
-                TII->get(SP::UNIMP)).addImm(structSize);
-      }
+  for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ) {
+    MachineBasicBlock::iterator MI = I;
+    ++I;
+
+    //If MI is restore, try combining it with previous inst.
+    if (!DisableDelaySlotFiller &&
+        (MI->getOpcode() == SP::RESTORErr
+         || MI->getOpcode() == SP::RESTOREri)) {
+      Changed |= tryCombineRestoreWithPrevInst(MBB, MI);
+      continue;
+    }
+
+    //If MI has no delay slot, skip
+    if (!MI->hasDelaySlot())
+      continue;
+
+    MachineBasicBlock::iterator D = MBB.end();
+
+    if (!DisableDelaySlotFiller)
+      D = findDelayInstr(MBB, MI);
+
+    ++FilledSlots;
+    Changed = true;
+
+    if (D == MBB.end())
+      BuildMI(MBB, I, MI->getDebugLoc(), TII->get(SP::NOP));
+    else
+      MBB.splice(I, &MBB, D);
+
+    unsigned structSize = 0;
+    if (needsUnimp(MI, structSize)) {
+      MachineBasicBlock::iterator J = MI;
+      ++J; //skip the delay filler.
+      assert (J != MBB.end() && "MI needs a delay instruction.");
+      BuildMI(MBB, ++J, I->getDebugLoc(),
+              TII->get(SP::UNIMP)).addImm(structSize);
     }
+  }
   return Changed;
 }
 
@@ -332,3 +350,140 @@ bool Filler::needsUnimp(MachineBasicBloc
   StructSize = MO.getImm();
   return true;
 }
+
+static bool combineRestoreADD(MachineBasicBlock::iterator RestoreMI,
+                              MachineBasicBlock::iterator AddMI,
+                              const TargetInstrInfo *TII)
+{
+  //Before:  add  <op0>, <op1>, %i[0-7]
+  //         restore %g0, %g0, %i[0-7]
+  //
+  //After :  restore <op0>, <op1>, %o[0-7]
+
+  unsigned reg = AddMI->getOperand(0).getReg();
+  if (reg < SP::I0 || reg > SP::I7)
+    return false;
+
+  //Erase RESTORE
+  RestoreMI->eraseFromParent();
+
+  //Change ADD to RESTORE
+  AddMI->setDesc(TII->get((AddMI->getOpcode() == SP::ADDrr)
+                          ? SP::RESTORErr
+                          : SP::RESTOREri));
+
+  //map the destination register
+  AddMI->getOperand(0).setReg(reg - SP::I0 + SP::O0);
+
+  return true;
+}
+
+static bool combineRestoreOR(MachineBasicBlock::iterator RestoreMI,
+                             MachineBasicBlock::iterator OrMI,
+                             const TargetInstrInfo *TII)
+{
+  //Before:  or  <op0>, <op1>, %i[0-7]
+  //         restore %g0, %g0, %i[0-7]
+  //   and <op0> or <op1> is zero,
+  //
+  //After :  restore <op0>, <op1>, %o[0-7]
+
+  unsigned reg = OrMI->getOperand(0).getReg();
+  if (reg < SP::I0 || reg > SP::I7)
+    return false;
+
+  //check whether it is a copy
+  if (OrMI->getOpcode() == SP::ORrr
+      && OrMI->getOperand(1).getReg() != SP::G0
+      && OrMI->getOperand(2).getReg() != SP::G0)
+    return false;
+
+  if (OrMI->getOpcode() == SP::ORri
+      && OrMI->getOperand(1).getReg() != SP::G0
+      && (!OrMI->getOperand(2).isImm() || OrMI->getOperand(2).getImm() != 0))
+    return false;
+
+  //Erase RESTORE
+  RestoreMI->eraseFromParent();
+
+  //Change OR to RESTORE
+  OrMI->setDesc(TII->get((OrMI->getOpcode() == SP::ORrr)
+                         ? SP::RESTORErr
+                         : SP::RESTOREri));
+
+  //map the destination register
+  OrMI->getOperand(0).setReg(reg - SP::I0 + SP::O0);
+
+  return true;
+}
+
+static bool combineRestoreSETHIi(MachineBasicBlock::iterator RestoreMI,
+                                 MachineBasicBlock::iterator SetHiMI,
+                                 const TargetInstrInfo *TII)
+{
+  //Before:  sethi imm3, %i[0-7]
+  //         restore %g0, %g0, %g0
+  //
+  //After :  restore %g0, (imm3<<10), %o[0-7]
+
+  unsigned reg = SetHiMI->getOperand(0).getReg();
+  if (reg < SP::I0 || reg > SP::I7)
+    return false;
+
+  if (!SetHiMI->getOperand(1).isImm())
+    return false;
+
+  int64_t imm = SetHiMI->getOperand(1).getImm();
+
+  //is it a 3 bit immediate?
+  if (!isInt<3>(imm))
+    return false;
+
+  //make it a 13 bit immediate
+  imm = (imm << 10) & 0x1FFF;
+
+  assert(RestoreMI->getOpcode() == SP::RESTORErr);
+
+  RestoreMI->setDesc(TII->get(SP::RESTOREri));
+
+  RestoreMI->getOperand(0).setReg(reg - SP::I0 + SP::O0);
+  RestoreMI->getOperand(1).setReg(SP::G0);
+  RestoreMI->getOperand(2).ChangeToImmediate(imm);
+
+
+  //Erase the original SETHI
+  SetHiMI->eraseFromParent();
+
+  return true;
+}
+
+bool Filler::tryCombineRestoreWithPrevInst(MachineBasicBlock &MBB,
+                                        MachineBasicBlock::iterator MBBI)
+{
+  //No previous instruction
+  if (MBBI == MBB.begin())
+    return false;
+
+  //asssert that MBBI is "restore %g0, %g0, %g0"
+  assert(MBBI->getOpcode() == SP::RESTORErr
+         && MBBI->getOperand(0).getReg() == SP::G0
+         && MBBI->getOperand(1).getReg() == SP::G0
+         && MBBI->getOperand(2).getReg() == SP::G0);
+
+  MachineBasicBlock::iterator PrevInst = MBBI; --PrevInst;
+
+  //Cannot combine with a delay filler
+  if (isDelayFiller(MBB, PrevInst))
+    return false;
+
+  switch (PrevInst->getOpcode()) {
+  default: break;
+  case SP::ADDrr:
+  case SP::ADDri: return combineRestoreADD(MBBI, PrevInst, TII); break;
+  case SP::ORrr:
+  case SP::ORri:  return combineRestoreOR(MBBI, PrevInst, TII); break;
+  case SP::SETHIi: return combineRestoreSETHIi(MBBI, PrevInst, TII); break;
+  }
+  //Cannot combine with the previous instruction
+  return false;
+}

Modified: llvm/trunk/test/CodeGen/SPARC/2011-01-11-FrameAddr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/SPARC/2011-01-11-FrameAddr.ll?rev=183088&r1=183087&r2=183088&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/SPARC/2011-01-11-FrameAddr.ll (original)
+++ llvm/trunk/test/CodeGen/SPARC/2011-01-11-FrameAddr.ll Sun Jun  2 16:48:17 2013
@@ -7,10 +7,14 @@
 define i8* @frameaddr() nounwind readnone {
 entry:
 ;V8: frameaddr
-;V8: or %g0, %fp, {{.+}}
+;V8: save %sp, -96, %sp
+;V8: jmp %i7+8
+;V8: restore %g0, %fp, %o0
 
 ;V9: frameaddr
-;V9: or %g0, %fp, {{.+}}
+;V9: save %sp, -96, %sp
+;V9: jmp %i7+8
+;V9: restore %g0, %fp, %o0
   %0 = tail call i8* @llvm.frameaddress(i32 0)
   ret i8* %0
 }

Modified: llvm/trunk/test/CodeGen/SPARC/2011-01-19-DelaySlot.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/SPARC/2011-01-19-DelaySlot.ll?rev=183088&r1=183087&r2=183088&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/SPARC/2011-01-19-DelaySlot.ll (original)
+++ llvm/trunk/test/CodeGen/SPARC/2011-01-19-DelaySlot.ll Sun Jun  2 16:48:17 2013
@@ -105,3 +105,79 @@ entry:
 
 
 declare i32 @func(i32*)
+
+
+define i32 @restore_add(i32 %a, i32 %b) {
+entry:
+;CHECK:  restore_add:
+;CHECK:  jmp %i7+8
+;CHECK:  restore %o0, %i1, %o0
+  %0 = tail call i32 @bar(i32 %a) nounwind
+  %1 = add nsw i32 %0, %b
+  ret i32 %1
+}
+
+define i32 @restore_add_imm(i32 %a) {
+entry:
+;CHECK:  restore_add_imm:
+;CHECK:  jmp %i7+8
+;CHECK:  restore %o0, 20, %o0
+  %0 = tail call i32 @bar(i32 %a) nounwind
+  %1 = add nsw i32 %0, 20
+  ret i32 %1
+}
+
+define i32 @restore_or(i32 %a) {
+entry:
+;CHECK:  restore_or:
+;CHECK:  jmp %i7+8
+;CHECK:  restore %g0, %o0, %o0
+  %0 = tail call i32 @bar(i32 %a) nounwind
+  ret i32 %0
+}
+
+define i32 @restore_or_imm(i32 %a) {
+entry:
+;CHECK:  restore_or_imm:
+;CHECK:  or %o0, 20, %i0
+;CHECK:  jmp %i7+8
+;CHECK:  restore %g0, %g0, %g0
+  %0 = tail call i32 @bar(i32 %a) nounwind
+  %1 = or i32 %0, 20
+  ret i32 %1
+}
+
+
+define i32 @restore_sethi(i32 %a) {
+entry:
+;CHECK: restore_sethi
+;CHECK-NOT: sethi  3
+;CHECK: restore %g0, 3072, %o0
+  %0 = tail call i32 @bar(i32 %a) nounwind
+  %1 = icmp ne i32 %0, 0
+  %2 = select i1 %1, i32 3072, i32 0
+  ret i32 %2
+}
+
+define i32 @restore_sethi_3bit(i32 %a) {
+entry:
+;CHECK: restore_sethi
+;CHECK: sethi  6
+;CHECK-NOT: restore %g0, 6144, %o0
+  %0 = tail call i32 @bar(i32 %a) nounwind
+  %1 = icmp ne i32 %0, 0
+  %2 = select i1 %1, i32 6144, i32 0
+  ret i32 %2
+}
+
+define i32 @restore_sethi_large(i32 %a) {
+entry:
+;CHECK: restore_sethi
+;CHECK: sethi  4000, %i0
+;CHECK: restore %g0, %g0, %g0
+  %0 = tail call i32 @bar(i32 %a) nounwind
+  %1 = icmp ne i32 %0, 0
+  %2 = select i1 %1, i32 4096000, i32 0
+  ret i32 %2
+}
+

Modified: llvm/trunk/test/CodeGen/SPARC/64bit.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/SPARC/64bit.ll?rev=183088&r1=183087&r2=183088&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/SPARC/64bit.ll (original)
+++ llvm/trunk/test/CodeGen/SPARC/64bit.ll Sun Jun  2 16:48:17 2013
@@ -1,13 +1,22 @@
-; RUN: llc < %s -march=sparcv9 -disable-sparc-leaf-proc | FileCheck %s
+; RUN: llc < %s -march=sparcv9 -disable-sparc-delay-filler -disable-sparc-leaf-proc | FileCheck %s
+; RUN: llc < %s -march=sparcv9  | FileCheck %s -check-prefix=OPT
 
 ; CHECK: ret2:
 ; CHECK: or %g0, %i1, %i0
+
+; OPT: ret2:
+; OPT: jmp %o7+8
+; OPT: or %g0, %o1, %o0
 define i64 @ret2(i64 %a, i64 %b) {
   ret i64 %b
 }
 
 ; CHECK: shl_imm
 ; CHECK: sllx %i0, 7, %i0
+
+; OPT: shl_imm:
+; OPT: jmp %o7+8
+; OPT: sllx %o0, 7, %o0
 define i64 @shl_imm(i64 %a) {
   %x = shl i64 %a, 7
   ret i64 %x
@@ -15,6 +24,10 @@ define i64 @shl_imm(i64 %a) {
 
 ; CHECK: sra_reg
 ; CHECK: srax %i0, %i1, %i0
+
+; OPT: sra_reg:
+; OPT: jmp %o7+8
+; OPT: srax %o0, %o1, %o0
 define i64 @sra_reg(i64 %a, i64 %b) {
   %x = ashr i64 %a, %b
   ret i64 %x
@@ -27,12 +40,20 @@ define i64 @sra_reg(i64 %a, i64 %b) {
 ;
 ; CHECK: ret_imm0
 ; CHECK: or %g0, 0, %i0
+
+; OPT: ret_imm0
+; OPT: jmp %o7+8
+; OPT: or %g0, 0, %o0
 define i64 @ret_imm0() {
   ret i64 0
 }
 
 ; CHECK: ret_simm13
 ; CHECK: or %g0, -4096, %i0
+
+; OPT:   ret_simm13
+; OPT:   jmp %o7+8
+; OPT:   or %g0, -4096, %o0
 define i64 @ret_simm13() {
   ret i64 -4096
 }
@@ -41,13 +62,23 @@ define i64 @ret_simm13() {
 ; CHECK: sethi 4, %i0
 ; CHECK-NOT: or
 ; CHECK: restore
+
+; OPT:  ret_sethi
+; OPT:  jmp %o7+8
+; OPT:  sethi 4, %o0
 define i64 @ret_sethi() {
   ret i64 4096
 }
 
-; CHECK: ret_sethi
+; CHECK: ret_sethi_or
 ; CHECK: sethi 4, [[R:%[goli][0-7]]]
 ; CHECK: or [[R]], 1, %i0
+
+; OPT: ret_sethi_or
+; OPT: sethi 4, [[R:%[go][0-7]]]
+; OPT: jmp %o7+8
+; OPT: or [[R]], 1, %o0
+
 define i64 @ret_sethi_or() {
   ret i64 4097
 }
@@ -55,6 +86,12 @@ define i64 @ret_sethi_or() {
 ; CHECK: ret_nimm33
 ; CHECK: sethi 4, [[R:%[goli][0-7]]]
 ; CHECK: xor [[R]], -4, %i0
+
+; OPT: ret_nimm33
+; OPT: sethi 4, [[R:%[go][0-7]]]
+; OPT: jmp %o7+8
+; OPT: xor [[R]], -4, %o0
+
 define i64 @ret_nimm33() {
   ret i64 -4100
 }

Modified: llvm/trunk/test/CodeGen/SPARC/64cond.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/SPARC/64cond.ll?rev=183088&r1=183087&r2=183088&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/SPARC/64cond.ll (original)
+++ llvm/trunk/test/CodeGen/SPARC/64cond.ll Sun Jun  2 16:48:17 2013
@@ -36,7 +36,7 @@ if.end:
 ; CHECK: selecti32_xcc
 ; CHECK: subcc %i0, %i1
 ; CHECK: movg %xcc, %i2, %i3
-; CHECK: or %g0, %i3, %i0
+; CHECK: restore %g0, %i3, %o0
 define i32 @selecti32_xcc(i64 %x, i64 %y, i32 %a, i32 %b) {
 entry:
   %tobool = icmp sgt i64 %x, %y
@@ -47,7 +47,7 @@ entry:
 ; CHECK: selecti64_xcc
 ; CHECK: subcc %i0, %i1
 ; CHECK: movg %xcc, %i2, %i3
-; CHECK: or %g0, %i3, %i0
+; CHECK: restore %g0, %i3, %o0
 define i64 @selecti64_xcc(i64 %x, i64 %y, i64 %a, i64 %b) {
 entry:
   %tobool = icmp sgt i64 %x, %y
@@ -58,7 +58,7 @@ entry:
 ; CHECK: selecti64_icc
 ; CHECK: subcc %i0, %i1
 ; CHECK: movg %icc, %i2, %i3
-; CHECK: or %g0, %i3, %i0
+; CHECK: restore %g0, %i3, %o0
 define i64 @selecti64_icc(i32 %x, i32 %y, i64 %a, i64 %b) {
 entry:
   %tobool = icmp sgt i32 %x, %y
@@ -69,7 +69,7 @@ entry:
 ; CHECK: selecti64_fcc
 ; CHECK: fcmps %f1, %f3
 ; CHECK: movul %fcc0, %i2, %i3
-; CHECK: or %g0, %i3, %i0
+; CHECK: restore %g0, %i3, %o0
 define i64 @selecti64_fcc(float %x, float %y, i64 %a, i64 %b) {
 entry:
   %tobool = fcmp ult float %x, %y





More information about the llvm-commits mailing list