[llvm-commits] CVS: llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp PPCInstrInfo.td PPCRegisterInfo.cpp PPCRegisterInfo.td

Chris Lattner lattner at cs.uiuc.edu
Mon Mar 13 13:52:22 PST 2006



Changes in directory llvm/lib/Target/PowerPC:

PPCISelDAGToDAG.cpp updated: 1.164 -> 1.165
PPCInstrInfo.td updated: 1.181 -> 1.182
PPCRegisterInfo.cpp updated: 1.43 -> 1.44
PPCRegisterInfo.td updated: 1.29 -> 1.30
---
Log message:

For functions that use vector registers, save VRSAVE, mark used
registers, and update it on entry to each function, then restore it on exit.

This compiles:

void func(vfloat *a, vfloat *b, vfloat *c) {
        *a = *b * *c + *c;
}

to this:

_func:
        mfspr r2, 256
        oris r6, r2, 49152
        mtspr 256: http://llvm.cs.uiuc.edu/PR256 , r6
        lvx v0, 0, r5
        lvx v1, 0, r4
        vmaddfp v0, v1, v0, v0
        stvx v0, 0, r3
        mtspr 256: http://llvm.cs.uiuc.edu/PR256 , r2
        blr

GCC produces this (which has additional stack accesses):

_func:
        mfspr r0,256
        stw r0,-4(r1)
        oris r0,r0,0xc000
        mtspr 256: http://llvm.cs.uiuc.edu/PR256 ,r0
        lvx v0,0,r5
        lvx v1,0,r4
        lwz r12,-4(r1)
        vmaddfp v0,v0,v1,v0
        stvx v0,0,r3
        mtspr 256: http://llvm.cs.uiuc.edu/PR256 ,r12
        blr



---
Diffs of the changes:  (+130 -10)

 PPCISelDAGToDAG.cpp |   59 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 PPCInstrInfo.td     |   26 ++++++++++++++++------
 PPCRegisterInfo.cpp |   51 ++++++++++++++++++++++++++++++++++++++++++++
 PPCRegisterInfo.td  |    4 +--
 4 files changed, 130 insertions(+), 10 deletions(-)


Index: llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
diff -u llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp:1.164 llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp:1.165
--- llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp:1.164	Sun Mar 12 03:13:49 2006
+++ llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp	Mon Mar 13 15:52:10 2006
@@ -196,8 +196,65 @@
   CodeGenMap.clear();
   DAG.RemoveDeadNodes();
   
-  // Emit machine code to BB. 
+  // Emit machine code to BB.
   ScheduleAndEmitDAG(DAG);
+  
+  // Check to see if this function uses vector registers, which means we have to
+  // save and restore the VRSAVE register and update it with the regs we use.  
+  //
+  // In this case, there will be virtual registers of vector type type created
+  // by the scheduler.  Detect them now.
+  SSARegMap *RegMap = DAG.getMachineFunction().getSSARegMap();
+  bool HasVectorVReg = false;
+  for (unsigned i = MRegisterInfo::FirstVirtualRegister, 
+       e = RegMap->getLastVirtReg(); i != e; ++i)
+    if (RegMap->getRegClass(i) == &PPC::VRRCRegClass) {
+      HasVectorVReg = true;
+      break;
+    }
+  
+  // If we have a vector register, we want to emit code into the entry and exit
+  // blocks to save and restore the VRSAVE register.  We do this here (instead
+  // of marking all vector instructions as clobbering VRSAVE) for two reasons:
+  //
+  // 1. This (trivially) reduces the load on the register allocator, by not
+  //    having to represent the live range of the VRSAVE register.
+  // 2. This (more significantly) allows us to create a temporary virtual
+  //    register to hold the saved VRSAVE value, allowing this temporary to be
+  //    register allocated, instead of forcing it to be spilled to the stack.
+  if (HasVectorVReg) {
+    // Create two vregs - one to hold the VRSAVE register that is live-in to the
+    // function and one for the value after having bits or'd into it.
+    unsigned InVRSAVE = RegMap->createVirtualRegister(&PPC::GPRCRegClass);
+    unsigned UpdatedVRSAVE = RegMap->createVirtualRegister(&PPC::GPRCRegClass);
+    
+    MachineFunction &MF = DAG.getMachineFunction();
+    MachineBasicBlock &EntryBB = *MF.begin();
+    // Emit the following code into the entry block:
+    // InVRSAVE = MFVRSAVE
+    // UpdatedVRSAVE = UPDATE_VRSAVE InVRSAVE
+    // MTVRSAVE UpdatedVRSAVE
+    MachineBasicBlock::iterator IP = EntryBB.begin();  // Insert Point
+    BuildMI(EntryBB, IP, PPC::MFVRSAVE, 0, InVRSAVE);
+    BuildMI(EntryBB, IP, PPC::UPDATE_VRSAVE, 1, UpdatedVRSAVE).addReg(InVRSAVE);
+    BuildMI(EntryBB, IP, PPC::MTVRSAVE, 1).addReg(UpdatedVRSAVE);
+    
+    // Find all return blocks, outputting a restore in each epilog.
+    const TargetInstrInfo &TII = *DAG.getTarget().getInstrInfo();
+    for (MachineFunction::iterator BB = MF.begin(), E = MF.end(); BB != E; ++BB)
+      if (!BB->empty() && TII.isReturn(BB->back().getOpcode())) {
+        IP = BB->end(); --IP;
+        
+        // Skip over all terminator instructions, which are part of the return
+        // sequence.
+        MachineBasicBlock::iterator I2 = IP;
+        while (I2 != BB->begin() && TII.isTerminatorInstr((--I2)->getOpcode()))
+          IP = I2;
+        
+        // Emit: MTVRSAVE InVRSave
+        BuildMI(*BB, IP, PPC::MTVRSAVE, 1).addReg(InVRSAVE);
+      }        
+  }
 }
 
 /// getGlobalBaseReg - Output the instructions required to put the


Index: llvm/lib/Target/PowerPC/PPCInstrInfo.td
diff -u llvm/lib/Target/PowerPC/PPCInstrInfo.td:1.181 llvm/lib/Target/PowerPC/PPCInstrInfo.td:1.182
--- llvm/lib/Target/PowerPC/PPCInstrInfo.td:1.181	Sun Mar 12 23:15:10 2006
+++ llvm/lib/Target/PowerPC/PPCInstrInfo.td	Mon Mar 13 15:52:10 2006
@@ -210,6 +210,9 @@
 def ADJCALLSTACKUP   : Pseudo<(ops u16imm:$amt),
                               "; ADJCALLSTACKUP",
                               [(callseq_end imm:$amt)]>;
+
+def UPDATE_VRSAVE    : Pseudo<(ops GPRC:$rD, GPRC:$rS),
+                              "UPDATE_VRSAVE $rD, $rS", []>;
 }
 def IMPLICIT_DEF_GPR : Pseudo<(ops GPRC:$rD), "; $rD = IMPLICIT_DEF_GPRC",
                               [(set GPRC:$rD, (undef))]>;
@@ -694,8 +697,24 @@
 //
 def MFCTR : XFXForm_1_ext<31, 339, 9, (ops GPRC:$rT), "mfctr $rT", SprMFSPR>,
             PPC970_DGroup_First, PPC970_Unit_FXU;
+def MTCTR : XFXForm_7_ext<31, 467, 9, (ops GPRC:$rS), "mtctr $rS", SprMTSPR>,
+            PPC970_DGroup_First, PPC970_Unit_FXU;
+
+def MTLR  : XFXForm_7_ext<31, 467, 8, (ops GPRC:$rS), "mtlr $rS", SprMTSPR>,
+            PPC970_DGroup_First, PPC970_Unit_FXU;
 def MFLR  : XFXForm_1_ext<31, 339, 8, (ops GPRC:$rT), "mflr $rT",  SprMFSPR>,
             PPC970_DGroup_First, PPC970_Unit_FXU;
+
+// Move to/from VRSAVE: despite being a SPR, the VRSAVE register is renamed like
+// a GPR on the PPC970.  As such, copies in and out have the same performance
+// characteristics as an OR instruction.
+def MTVRSAVE : XFXForm_7_ext<31, 467, 256, (ops GPRC:$rS),
+                             "mtspr 256, $rS", IntGeneral>,
+               PPC970_Unit_FXU;
+def MFVRSAVE : XFXForm_1_ext<31, 339, 256, (ops GPRC:$rT),
+                             "mfspr $rT, 256", IntGeneral>,
+               PPC970_Unit_FXU;
+
 def MFCR  : XFXForm_3<31, 19, (ops GPRC:$rT), "mfcr $rT", SprMFCR>,
             PPC970_MicroCode, PPC970_Unit_CRU;
 def MTCRF : XFXForm_5<31, 144, (ops crbitm:$FXM, GPRC:$rS),
@@ -704,13 +723,6 @@
 def MFOCRF: XFXForm_5a<31, 19, (ops GPRC:$rT, crbitm:$FXM),
                        "mfcr $rT, $FXM", SprMFCR>,
             PPC970_DGroup_First, PPC970_Unit_CRU;
-def MTCTR : XFXForm_7_ext<31, 467, 9, (ops GPRC:$rS), "mtctr $rS", SprMTSPR>,
-            PPC970_DGroup_First, PPC970_Unit_FXU;
-def MTLR  : XFXForm_7_ext<31, 467, 8, (ops GPRC:$rS), "mtlr $rS", SprMTSPR>,
-            PPC970_DGroup_First, PPC970_Unit_FXU;
-def MTSPR : XFXForm_7<31, 467, (ops GPRC:$rS, u16imm:$UIMM), "mtspr $UIMM, $rS",
-                      SprMTSPR>,
-            PPC970_DGroup_Single, PPC970_Unit_FXU;
 
 // XS-Form instructions.  Just 'sradi'
 //


Index: llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
diff -u llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp:1.43 llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp:1.44
--- llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp:1.43	Thu Feb  2 14:12:32 2006
+++ llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp	Mon Mar 13 15:52:10 2006
@@ -266,12 +266,63 @@
   }
 }
 
+// HandleVRSaveUpdate - MI is the UPDATE_VRSAVE instruction introduced by the
+// instruction selector.  Based on the vector registers that have been used,
+// transform this into the appropriate ORI instruction.
+static void HandleVRSaveUpdate(MachineInstr *MI, const bool *UsedRegs) {
+  unsigned UsedRegMask = 0;
+#define HANDLEREG(N) if (UsedRegs[PPC::V##N]) UsedRegMask |= 1 << (31-N)
+  HANDLEREG( 0); HANDLEREG( 1); HANDLEREG( 2); HANDLEREG( 3);
+  HANDLEREG( 4); HANDLEREG( 5); HANDLEREG( 6); HANDLEREG( 7);
+  HANDLEREG( 8); HANDLEREG( 9); HANDLEREG(10); HANDLEREG(11);
+  HANDLEREG(12); HANDLEREG(13); HANDLEREG(14); HANDLEREG(15);
+  HANDLEREG(16); HANDLEREG(17); HANDLEREG(18); HANDLEREG(19);
+  HANDLEREG(20); HANDLEREG(21); HANDLEREG(22); HANDLEREG(23);
+  HANDLEREG(24); HANDLEREG(25); HANDLEREG(26); HANDLEREG(27);
+  HANDLEREG(28); HANDLEREG(29); HANDLEREG(30); HANDLEREG(31);
+#undef HANDLEREG
+  unsigned SrcReg = MI->getOperand(1).getReg();
+  unsigned DstReg = MI->getOperand(0).getReg();
+  // If no registers are used, turn this into a copy.
+  if (UsedRegMask == 0) {
+    if (SrcReg != DstReg)
+      BuildMI(*MI->getParent(), MI, PPC::OR4, 2, DstReg)
+        .addReg(SrcReg).addReg(SrcReg);
+  } else if ((UsedRegMask & 0xFFFF) == UsedRegMask) {
+    BuildMI(*MI->getParent(), MI, PPC::ORI, 2, DstReg)
+        .addReg(SrcReg).addImm(UsedRegMask);
+  } else if ((UsedRegMask & 0xFFFF0000) == UsedRegMask) {
+    BuildMI(*MI->getParent(), MI, PPC::ORIS, 2, DstReg)
+        .addReg(SrcReg).addImm(UsedRegMask >> 16);
+  } else {
+    BuildMI(*MI->getParent(), MI, PPC::ORIS, 2, DstReg)
+       .addReg(SrcReg).addImm(UsedRegMask >> 16);
+    BuildMI(*MI->getParent(), MI, PPC::ORI, 2, DstReg)
+      .addReg(DstReg).addImm(UsedRegMask & 0xFFFF);
+  }
+  
+  // Remove the old UPDATE_VRSAVE instruction.
+  MI->getParent()->erase(MI);
+}
+
 
 void PPCRegisterInfo::emitPrologue(MachineFunction &MF) const {
   MachineBasicBlock &MBB = MF.front();   // Prolog goes in entry BB
   MachineBasicBlock::iterator MBBI = MBB.begin();
   MachineFrameInfo *MFI = MF.getFrameInfo();
 
+  // Scan the first few instructions of the prolog, looking for an UPDATE_VRSAVE
+  // instruction.  If we find it, process it.
+  for (unsigned i = 0; MBBI != MBB.end() && i < 5; ++i, ++MBBI) {
+    if (MBBI->getOpcode() == PPC::UPDATE_VRSAVE) {
+      HandleVRSaveUpdate(MBBI, MF.getUsedPhysregs());
+      break;
+    }
+  }
+  
+  // Move MBBI back to the beginning of the function.
+  MBBI = MBB.begin();
+  
   // Get the number of bytes to allocate from the FrameInfo
   unsigned NumBytes = MFI->getStackSize();
   


Index: llvm/lib/Target/PowerPC/PPCRegisterInfo.td
diff -u llvm/lib/Target/PowerPC/PPCRegisterInfo.td:1.29 llvm/lib/Target/PowerPC/PPCRegisterInfo.td:1.30
--- llvm/lib/Target/PowerPC/PPCRegisterInfo.td:1.29	Wed Dec 21 20:26:21 2005
+++ llvm/lib/Target/PowerPC/PPCRegisterInfo.td	Mon Mar 13 15:52:10 2006
@@ -152,9 +152,9 @@
     GPRCClass::iterator
     GPRCClass::allocation_order_end(MachineFunction &MF) const {
       if (hasFP(MF))
-        return end()-4;
+        return end()-4;  // don't allocate R31, R0, R1, LR
       else
-        return end()-3;
+        return end()-3;  // don't allocate R0, R1, LR
     }
   }];
 }






More information about the llvm-commits mailing list