Added code to support correct saving of %ccr across calls
authorRuchira Sasanka <sasanka@students.uiuc.edu>
Sat, 3 Nov 2001 19:59:59 +0000 (19:59 +0000)
committerRuchira Sasanka <sasanka@students.uiuc.edu>
Sat, 3 Nov 2001 19:59:59 +0000 (19:59 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@1111 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/SparcV9/SparcV9Instr.def
lib/Target/SparcV9/SparcV9Internals.h
lib/Target/SparcV9/SparcV9RegClassInfo.h
lib/Target/SparcV9/SparcV9RegInfo.cpp

index 368cc5ad76f67e93c7412158b4bd89f62d6aa77d..cf70b31b12eebc1dd647d7f2a6594e64be0ab5b0 100644 (file)
@@ -38,6 +38,7 @@
 //                                             instr class flags (defined in MachineInstrInfo.h)
 
 
+
 I(NOP, "nop",          0,  -1,  0, false, 0,  1,  SPARC_NONE,  M_NOP_FLAG)
   
 // Synthetic SPARC assembly opcodes for setting a register to a constant.
@@ -430,6 +431,11 @@ I(RETURN, "return",        2, -1,   0, false, 1, 2,  SPARC_CTI,  M_BRANCH_FLAG | M_RET_
 I(SAVE  , "save",      3,  2, B12, true , 0, 1,  SPARC_SINGLE, M_INT_FLAG | M_ARITH_FLAG)
 I(RESTORE, "restore",  3,  2, B12, true , 0, 1,  SPARC_SINGLE, M_INT_FLAG | M_ARITH_FLAG)
 
+// Read and Write CCR register from/to an int reg
+I(RDCCR,  "rd",         2,   1, 0, false,  0,  1,  SPARC_IEUN,  M_INT_FLAG)
+I(WRCCR,  "wr",         3,   2, 0, false,  0,  1,  SPARC_IEUN,  M_INT_FLAG)
+
+
 // Synthetic phi operation for near-SSA form of machine code
 // Number of operands is variable, indicated by -1.  Result is the first op.
 I(PHI, "<phi>",        -1, 0,   0, false, 0, 0,  SPARC_INV,  M_DUMMY_PHI_FLAG)
index 72b234f72cb5365b419e4613c9667070040193f2..2f151b788789fec89fe60db6c61704a215f00927 100644 (file)
@@ -254,6 +254,9 @@ class UltraSparcRegInfo : public MachineRegInfo
   const unsigned getCallInstNumArgs(const MachineInstr *CallMI) const;
 
 
+  MachineInstr * cpCCR2IntMI(const unsigned IntReg) const;
+  MachineInstr * cpInt2CCRMI(const unsigned IntReg) const;
+
  public:
 
 
@@ -371,9 +374,8 @@ class UltraSparcRegInfo : public MachineRegInfo
       return SparcFloatRegOrder::getRegName( reg  - 32);                  
     else if( reg < (64+32+4) )
       return SparcFloatCCRegOrder::getRegName( reg -32 - 64);
-    else if ( reg == 64+32+4)
-      return "xcc";                     // only integer cc reg
-
+    else if( reg < (64+32+4+2) )    // two names: %xcc and %ccr
+      return SparcIntCCRegOrder::getRegName( reg -32 - 64 - 4);             
     else if (reg== InvalidRegNum)       //****** TODO: Remove */
       return "<*NoReg*>";
     else 
index 4f91268c37440b2149a664e94ac228c5e8c61181..fd7681575002add9152c34e9f2a7c7e82ef14d74 100644 (file)
@@ -191,22 +191,54 @@ class SparcFloatRegClass : public MachineRegClassInfo
 
 //-----------------------------------------------------------------------------
 // Int CC Register Class
-// Only one integer cc register is available
+// Only one integer cc register is available. However, this register is
+// referred to as %xcc when instructions like subcc are executed but 
+// referred to as %ccr (i.e., %xcc + %icc") when this register is moved
+// into an integer register using RD or WR instrcutions. So, two ids are
+// allocated for two names.
 //-----------------------------------------------------------------------------
 
 
+static string const IntCCRegNames[] = 
+  {    
+    "xcc",  "ccr"
+  };
+
+
+class SparcIntCCRegOrder{ 
+
+ public:
+
+  enum RegsInPrefOrder {
+
+    xcc, ccr   // only one is available - see the note above
+  };
+
+  static const string  getRegName(const unsigned reg) {
+    assert( reg < 2 );
+    return IntCCRegNames[reg];
+  }
+
+  // according to  Sparc 64 ABI,  %ccr is volatile
+  inline bool isRegVolatile(const int Reg) const { return true; }
+
+
+};
+
+
+
 class SparcIntCCRegClass : public MachineRegClassInfo
 {
 public:
 
   SparcIntCCRegClass(unsigned ID) 
-    : MachineRegClassInfo(ID,1, 1) {  }
+    : MachineRegClassInfo(ID, 1, 2) {  }
 
   inline void colorIGNode(IGNode * Node, bool IsColorUsedArr[] ) const {
     Node->setColor(0);    // only one int cc reg is available
   }
 
-  // *** TODO: Check this
+
   inline bool isRegVolatile(const int Reg) const { return true; }
 
 };
index a34a5305ae73a5974c89ed49f88518171f807ad6..9c57892392e6df1b15d27d4fb0d1096216921d5d 100644 (file)
@@ -896,7 +896,6 @@ MachineInstr * UltraSparcRegInfo::cpReg2MemMI(const unsigned SrcReg,
   switch( RegType ) {
     
   case IntRegType:
-  case IntCCRegType:
   case FloatCCRegType: 
     MI = new MachineInstr(STX, 3);
     MI->SetMachineOperand(0, SrcReg, false);
@@ -921,8 +920,11 @@ MachineInstr * UltraSparcRegInfo::cpReg2MemMI(const unsigned SrcReg,
                          (int64_t) Offset, false);
     break;
 
+  case IntCCRegType:
+    assert( 0 && "Cannot directly store %ccr to memory");
+    
   default:
-    assert(0 && "Unknow RegType");
+    assert(0 && "Unknow RegType in cpReg2MemMI");
   }
 
   return MI;
@@ -945,7 +947,6 @@ MachineInstr * UltraSparcRegInfo::cpMem2RegMI(const unsigned SrcPtrReg,
   switch( RegType ) {
     
   case IntRegType:
-  case IntCCRegType:
   case FloatCCRegType: 
     MI = new MachineInstr(LDX, 3);
     MI->SetMachineOperand(0, SrcPtrReg, false);
@@ -971,14 +972,21 @@ MachineInstr * UltraSparcRegInfo::cpMem2RegMI(const unsigned SrcPtrReg,
     MI->SetMachineOperand(2, DestReg, false);
     break;
 
+  case IntCCRegType:
+    assert( 0 && "Cannot directly load into %ccr from memory");
+
   default:
-    assert(0 && "Unknow RegType");
+    assert(0 && "Unknow RegType in cpMem2RegMI");
   }
 
   return MI;
 }
 
 
+
+
+// Following method is Not needed now
+
 MachineInstr* UltraSparcRegInfo::cpValue2Value(Value *Src, Value *Dest) const {
 
   MachineInstr * MI = NULL;
@@ -1071,28 +1079,91 @@ void UltraSparcRegInfo::insertCallerSavingCode(const MachineInstr *MInst,
 
            int StackOff =  PRA.StackOffsets. getNewTmpPosOffFromFP();
 
-           /**** TODO  - Handle IntCCRegType
+
+           MachineInstr *AdIBefCC, *AdIAftCC, *AdICpCC;
+
+
+           //---- Insert code for pushing the reg on stack ----------
                  
+           if( RegType == IntCCRegType ) {
+
+             // Handle IntCCRegType specially since we cannot directly 
+             // push %ccr on to the stack
+
+             const LiveVarSet *LVSetBef = 
+               PRA.LVI->getLiveVarSetBeforeMInst(MInst, BB);
+
+             // get a free INTEGER register
+             int FreeIntReg = 
+               PRA.getUsableRegAtMI(LR->getRegClass(), IntRegType, MInst, 
+                                    LVSetBef, AdIBefCC, AdIAftCC);
 
+             // insert the instructions in reverse order since we are
+             // adding them to the front of InstrnsBefore
 
+             if(AdIAftCC)
+               (PRA.AddedInstrMap[MInst]->InstrnsBefore).push_front(AdIAftCC);
+
+             AdICpCC = cpCCR2IntMI(FreeIntReg);
+             (PRA.AddedInstrMap[MInst]->InstrnsBefore).push_front(AdICpCC);
+
+             if(AdIBefCC)
+               (PRA.AddedInstrMap[MInst]->InstrnsBefore).push_front(AdIBefCC);
+
+             cerr << "\n!! Inserted caller saving (push) inst for %ccr:";
+             if(AdIBefCC) cerr << "\t" <<  *(AdIBefCC);
+             cerr  << "\t" << *AdICpCC;
+             if(AdIAftCC) cerr  << "\t" << *(AdIAftCC);
+
+           } else  {  
+             // for any other register type, just add the push inst
+             MachineInstr *AdIBef = 
+               cpReg2MemMI(Reg, getStackPointer(), StackOff, RegType ); 
+             ((PRA.AddedInstrMap[MInst])->InstrnsBefore).push_front(AdIBef);
            }
-           */
+
+
+           //---- Insert code for popping the reg from the stack ----------
+
+           if( RegType == IntCCRegType ) {
+
+             // Handle IntCCRegType specially since we cannot directly 
+             // pop %ccr on from the stack
+             
+             // get a free INT register
+             int FreeIntReg = 
+               PRA.getUsableRegAtMI(LR->getRegClass(), IntRegType, MInst, 
+                                    LVSetAft, AdIBefCC, AdIAftCC);
+             
+             if(AdIBefCC)
+               (PRA.AddedInstrMap[MInst]->InstrnsAfter).push_back(AdIBefCC);
+
+             AdICpCC = cpInt2CCRMI(FreeIntReg);
+             (PRA.AddedInstrMap[MInst]->InstrnsAfter).push_back(AdICpCC);
            
-           MachineInstr *AdIBef = 
-             cpReg2MemMI(Reg, getStackPointer(), StackOff, RegType ); 
+             if(AdIAftCC)
+               (PRA.AddedInstrMap[MInst]->InstrnsAfter).push_back(AdIAftCC);
+
+             cerr << "\n!! Inserted caller saving (pop) inst for %ccr:";
+             if(AdIBefCC) cerr << "\t" <<  *(AdIBefCC);
+             cerr  << "\t" << *AdICpCC;
+             if(AdIAftCC) cerr  << "\t" << *(AdIAftCC);
+
+           } else {
+             // for any other register type, just add the pop inst
+             MachineInstr *AdIAft = 
+               cpMem2RegMI(getStackPointer(), StackOff, Reg, RegType ); 
 
-           MachineInstr *AdIAft = 
-             cpMem2RegMI(getStackPointer(), StackOff, Reg, RegType ); 
+             ((PRA.AddedInstrMap[MInst])->InstrnsAfter).push_back(AdIAft);
 
-           ((PRA.AddedInstrMap[MInst])->InstrnsBefore).push_front(AdIBef);
-           ((PRA.AddedInstrMap[MInst])->InstrnsAfter).push_back(AdIAft);
+           }
            
            PushedRegSet.insert( Reg );
 
-           if(DEBUG_RA) {
-             cerr << "\nFor callee save call inst:" << *MInst;
+           if(1) {
+             cerr << "\nFor call inst:" << *MInst;
              cerr << "\n  -inserted caller saving instrs:\n\t ";
-             cerr << *AdIBef << "\n\t" << *AdIAft  ;
+             cerr << *AdIBefCC << "\n\t" << *AdIAftCC  ;
            }       
          } // if not already pushed
 
@@ -1106,10 +1177,36 @@ void UltraSparcRegInfo::insertCallerSavingCode(const MachineInstr *MInst,
   
 }
 
+//---------------------------------------------------------------------------
+// Copies %ccr into an integer register. IntReg is the UNIFIED register
+// number.
+//---------------------------------------------------------------------------
 
+MachineInstr * UltraSparcRegInfo::cpCCR2IntMI(const unsigned IntReg) const {
+  MachineInstr * MI = NULL;
 
+  MI = new MachineInstr(RDCCR, 2);
+  MI->SetMachineOperand(0, SparcIntCCRegOrder::ccr, false);
+  MI->SetMachineOperand(1, IntReg, true);
 
+  return MI;
+}
+
+//---------------------------------------------------------------------------
+// Copies an integer register into  %ccr. IntReg is the UNIFIED register
+// number.
+//---------------------------------------------------------------------------
+
+MachineInstr * UltraSparcRegInfo::cpInt2CCRMI(const unsigned IntReg) const {
+  MachineInstr * MI = NULL;
+
+  MI = new MachineInstr(WRCCR, 3);
+  MI->SetMachineOperand(0, IntReg, false);
+  MI->SetMachineOperand(1, SparcIntRegOrder::g0, false);
+  MI->SetMachineOperand(2, SparcIntCCRegOrder::ccr, true);
 
+  return MI;
+}