Added code to support correct saving of %ccr across calls

llvm-svn: 1111
diff --git a/llvm/lib/Target/Sparc/SparcInstr.def b/llvm/lib/Target/Sparc/SparcInstr.def
index 368cc5a..cf70b31 100644
--- a/llvm/lib/Target/Sparc/SparcInstr.def
+++ b/llvm/lib/Target/Sparc/SparcInstr.def
@@ -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(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)
diff --git a/llvm/lib/Target/Sparc/SparcInternals.h b/llvm/lib/Target/Sparc/SparcInternals.h
index 72b234f..2f151b7 100644
--- a/llvm/lib/Target/Sparc/SparcInternals.h
+++ b/llvm/lib/Target/Sparc/SparcInternals.h
@@ -254,6 +254,9 @@
   const unsigned getCallInstNumArgs(const MachineInstr *CallMI) const;
 
 
+  MachineInstr * cpCCR2IntMI(const unsigned IntReg) const;
+  MachineInstr * cpInt2CCRMI(const unsigned IntReg) const;
+
  public:
 
 
@@ -371,9 +374,8 @@
       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 
diff --git a/llvm/lib/Target/Sparc/SparcRegClassInfo.h b/llvm/lib/Target/Sparc/SparcRegClassInfo.h
index 4f91268..fd76815 100644
--- a/llvm/lib/Target/Sparc/SparcRegClassInfo.h
+++ b/llvm/lib/Target/Sparc/SparcRegClassInfo.h
@@ -191,22 +191,54 @@
 
 //-----------------------------------------------------------------------------
 // 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; }
 
 };
diff --git a/llvm/lib/Target/Sparc/SparcRegInfo.cpp b/llvm/lib/Target/Sparc/SparcRegInfo.cpp
index a34a530..9c57892 100644
--- a/llvm/lib/Target/Sparc/SparcRegInfo.cpp
+++ b/llvm/lib/Target/Sparc/SparcRegInfo.cpp
@@ -896,7 +896,6 @@
   switch( RegType ) {
     
   case IntRegType:
-  case IntCCRegType:
   case FloatCCRegType: 
     MI = new MachineInstr(STX, 3);
     MI->SetMachineOperand(0, SrcReg, false);
@@ -921,8 +920,11 @@
 			  (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 @@
   switch( RegType ) {
     
   case IntRegType:
-  case IntCCRegType:
   case FloatCCRegType: 
     MI = new MachineInstr(LDX, 3);
     MI->SetMachineOperand(0, SrcPtrReg, false);
@@ -971,14 +972,21 @@
     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 @@
 
 	    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);
+	    
+	      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 ); 
+
+	      ((PRA.AddedInstrMap[MInst])->InstrnsAfter).push_back(AdIAft);
 
 	    }
-	    */
-	    
-	    MachineInstr *AdIBef = 
-	      cpReg2MemMI(Reg, getStackPointer(), StackOff, RegType ); 
-
-	    MachineInstr *AdIAft = 
-	      cpMem2RegMI(getStackPointer(), StackOff, Reg, RegType ); 
-
-	    ((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 @@
   
 }
 
+//---------------------------------------------------------------------------
+// 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;
+}