added register allocation code
authorRuchira Sasanka <sasanka@students.uiuc.edu>
Sat, 15 Sep 2001 00:30:44 +0000 (00:30 +0000)
committerRuchira Sasanka <sasanka@students.uiuc.edu>
Sat, 15 Sep 2001 00:30:44 +0000 (00:30 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@585 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/SparcV9/Makefile
lib/Target/SparcV9/SparcV9Internals.h
lib/Target/SparcV9/SparcV9RegInfo.cpp
lib/Target/SparcV9/SparcV9RegInfo.h
lib/Target/SparcV9/SparcV9TargetMachine.cpp

index 515d931f26dbf4672ffc253f150dce5e2b95158c..a2b8c2abd78c33b99158a6b593d1c727948b12c1 100644 (file)
@@ -5,7 +5,8 @@ LIBRARYNAME = sparc
 Source  = \
          Sparc.o \
          Sparc.burm.o \
-         SparcInstrSelection.o
+         SparcInstrSelection.o \
+         SparcRegInfo.o
 
 include $(LEVEL)/Makefile.common
 
index e4f0a8bd10a48105a6d5141bc66cc0e31a8862f5..43f67d3008a6df5f73f1e64c7841559e08253dbb 100644 (file)
@@ -853,20 +853,34 @@ public:
 
 };
 
+
 //---------------------------------------------------------------------------
-// class UltraSparcInstrInfo 
+// class UltraSparcRegInfo 
 // 
 // Purpose:
 //   This class provides info about sparc register classes.
 //---------------------------------------------------------------------------
 
 class LiveRange;
+class UltraSparc;
+
 
 class UltraSparcRegInfo : public MachineRegInfo
 {
 
  private:
-  enum RegClassIDs { IntRegClassID, FloatRegClassID, FloatCCREgClassID };
+
+  enum RegClassIDs { 
+    IntRegClassID, 
+    FloatRegClassID, 
+    IntCCRegClassID,
+    FloatCCRegClassID 
+  };
+
+  // WARNING: If the above enum order must be changed, also modify 
+  // getRegisterClassOfValue method below since it assumes this particular 
+  // order for efficiency.
+
 
   // reverse pointer to get info about the ultra sparc machine
   const UltraSparc *const UltraSparcInfo;
@@ -883,37 +897,70 @@ class UltraSparcRegInfo : public MachineRegInfo
 
  public:
 
-  UltraSparcRegInfo(const UltraSparc *USI ) : UltraSparcInfo(USI), 
-                                             NumOfIntArgRegs(6), 
-                                             NumOfFloatArgRegs(6) 
-  {    
 
+  UltraSparcRegInfo(const UltraSparc *const USI ) : UltraSparcInfo(USI), 
+                                                   NumOfIntArgRegs(6), 
+                                                   NumOfFloatArgRegs(6) 
+  {    
     MachineRegClassArr.push_back( new SparcIntRegClass(IntRegClassID) );
     MachineRegClassArr.push_back( new SparcFloatRegClass(FloatRegClassID) );
+    MachineRegClassArr.push_back( new SparcIntCCRegClass(IntCCRegClassID) );
+    MachineRegClassArr.push_back( new SparcFloatCCRegClass(FloatCCRegClassID));
 
     assert( SparcFloatRegOrder::StartOfNonVolatileRegs == 6 && 
            "6 Float regs are used for float arg passing");
-
   }
 
+  // ***** TODO  Delete
+  ~UltraSparcRegInfo(void) { }              // empty destructor 
+
+
   inline const UltraSparc & getUltraSparcInfo() const { 
     return *UltraSparcInfo;
   }
 
-  inline unsigned getRegClassIDOfValue (const Value *const Val) const {
+
+
+  inline unsigned getRegClassIDOfValue (const Value *const Val,
+                                       bool isCCReg = false) const {
+
     Type::PrimitiveID ty = (Val->getType())->getPrimitiveID();
+
+    unsigned res;
     
     if( ty && ty <= Type::LongTyID || (ty == Type::PointerTyID) )  
-      return IntRegClassID;             // sparc int reg (ty=0: void)
+      res =  IntRegClassID;             // sparc int reg (ty=0: void)
     else if( ty <= Type::DoubleTyID)
-      return FloatRegClassID;           // sparc float reg class
+      res = FloatRegClassID;           // sparc float reg class
     else { 
       cout << "TypeID: " << ty << endl;
       assert(0 && "Cannot resolve register class for type");
 
     }
+
+    if(isCCReg)
+      return res + 2;      // corresponidng condition code regiser 
+
+    else 
+      return res;
+
   }
+                   
+
+#if 0
+  unsigned getRCIDOfMachineOp (const MachineOperand & Op) const {
+
+    unsigned Type = getRegClassIDOfValue( Op.getVRegValue() );
+
+    if( Op.getOperandType() == MachineOperand::MO_CCRegister ) 
+      return Type + 2;               // because of the order of CC classes
+    else return Type;
+  }
+
+#endif
+
+
+
   void colorArgs(const Method *const Meth, LiveRangeInfo& LRI) const;
 
   static void printReg(const LiveRange *const LR)  ;
@@ -929,9 +976,11 @@ class UltraSparcRegInfo : public MachineRegInfo
       return reg;
     else if ( RegClassID == FloatRegClassID && reg < 64)
       return reg + 32;                  // we have 32 int regs
-    else if( RegClassID == FloatCCREgClassID && reg < 4)
+    else if( RegClassID == FloatCCRegClassID && reg < 4)
       return reg + 32 + 64;             // 32 int, 64 float
-    else 
+    else if( RegClassID == IntCCRegClassID ) 
+      return 4+ 32 + 64;                // only int cc reg
+    else  
       assert(0 && "Invalid register class or reg number");
 
   }
@@ -944,8 +993,9 @@ class UltraSparcRegInfo : public MachineRegInfo
     else if ( reg < (64 + 32) )
       return SparcFloatRegOrder::getRegName( reg  - 32);                  
     else if( reg < (64+32+4) )
-      assert( 0 && "no float condition reg class yet");
-      // return reg + 32 + 64;             
+      return SparcFloatCCRegOrder::getRegName( reg -32 - 64);
+    else if ( reg == 64+32+4)
+      return "xcc";                     // only integer cc reg
     else 
       assert(0 && "Invalid register number");
   }
@@ -956,9 +1006,6 @@ class UltraSparcRegInfo : public MachineRegInfo
 
 
 
-
-
-
 /*---------------------------------------------------------------------------
 Scheduling guidelines for SPARC IIi:
 
@@ -1667,12 +1714,15 @@ protected:
 class UltraSparc : public TargetMachine {
   UltraSparcInstrInfo InstInfo;
   UltraSparcSchedInfo InstSchedulingInfo;
+  UltraSparcRegInfo RegInfo;
 public:
   UltraSparc();
   virtual ~UltraSparc() {}
 
   virtual const MachineInstrInfo& getInstrInfo() const { return InstInfo; }
 
+  virtual const MachineRegInfo& getRegInfo() const { return RegInfo; }
+
   // compileMethod - For the sparc, we do instruction selection, followed by
   // delay slot scheduling, then register allocation.
   //
index 3d43fa3d2a164e92d561fe608c13f965690349c1..fe6ec235fa426c1c2f6f2e0cbcc11d3b22553862 100644 (file)
@@ -1,5 +1,6 @@
 #include "llvm/CodeGen/IGNode.h"
 #include "SparcRegInfo.h"
+#include "SparcInternals.h"
 
 #include "llvm/Target/Sparc.h"
 
index 67aa3a62ea3391cfabdfd705ccf247d2c440d5bd..d6ec90eaa2e23d929b2271c0a49cd9eca5a913b1 100644 (file)
@@ -4,17 +4,20 @@
    Purpose: Contains the description of integer register class of Sparc
 */
 
-#ifndef SPARC_INT_REG_CLASS_H
-#define SPARC_INT_REG_CLASS_H
+
+#ifndef SPARC_REG_INFO_CLASS_H
+#define SPARC_REG_INFO_CLASS_H
 
 #include "llvm/Target/RegInfo.h"
+#include "llvm/CodeGen/IGNode.h"
 
 //-----------------------------------------------------------------------------
 // Integer Register Class
 //-----------------------------------------------------------------------------
 
+
 // Int register names in same order as enum in class SparcIntRegOrder
-//
+
 static string const IntRegNames[] = 
   {       "g1", "g2", "g3", "g4", "g5", "g6", "g7",
     "o0", "o1", "o2", "o3", "o4", "o5",       "o7",
@@ -80,7 +83,7 @@ class SparcIntRegClass : public MachineRegClassInfo
  public:
 
   SparcIntRegClass(unsigned ID) 
-    : MachineRegClassInfo(0
+    : MachineRegClassInfo(ID
                          SparcIntRegOrder::NumOfAvailRegs,
                          SparcIntRegOrder::NumOfAllRegs)
     {  }
@@ -141,6 +144,7 @@ class SparcFloatRegOrder{
 };
 
 
+
 class SparcFloatRegClass : public MachineRegClassInfo
 {
  private:
@@ -151,7 +155,7 @@ class SparcFloatRegClass : public MachineRegClassInfo
  public:
 
   SparcFloatRegClass(unsigned ID) 
-    : MachineRegClassInfo(1
+    : MachineRegClassInfo(ID
                          SparcFloatRegOrder::NumOfAvailRegs,
                          SparcFloatRegOrder::NumOfAllRegs)
     {  }
@@ -162,4 +166,75 @@ class SparcFloatRegClass : public MachineRegClassInfo
 
 
 
+
+//-----------------------------------------------------------------------------
+// Int CC Register Class
+// Only one integer cc register is available
+//-----------------------------------------------------------------------------
+
+
+class SparcIntCCRegClass : public MachineRegClassInfo
+{
+public:
+
+  SparcIntCCRegClass(unsigned ID) 
+    : MachineRegClassInfo(ID,1, 1) {  }
+
+  inline void colorIGNode(IGNode * Node, bool IsColorUsedArr[] ) const {
+    Node->setColor(0);    // only one int cc reg is available
+  }
+
+};
+
+
+
+//-----------------------------------------------------------------------------
+// Float CC Register Class
+// Only 4 Float CC registers are available
+//-----------------------------------------------------------------------------
+
+
+static string const FloatCCRegNames[] = 
+  {    
+    "fcc0",  "fcc1",  "fcc2",  "fcc3"
+  };
+
+
+class SparcFloatCCRegOrder{ 
+
+ public:
+
+  enum RegsInPrefOrder {
+
+    fcc0, fcc1, fcc2, fcc3
+  };
+
+  static const string  getRegName(const unsigned reg) {
+    assert( reg < 4 );
+    return FloatCCRegNames[reg];
+  }
+
+};
+
+
+
+class SparcFloatCCRegClass : public MachineRegClassInfo
+{
+public:
+
+  SparcFloatCCRegClass(unsigned ID) 
+    : MachineRegClassInfo(ID, 4, 4) {  }
+
+  void colorIGNode(IGNode * Node, bool IsColorUsedArr[] ) const {
+    int c;
+    for(c=0; c < 4  && IsColorUsedArr[c] ; ++c) ; // find color
+    assert( (c < 4)  && "Can allocate only 4 float cc registers");
+    Node->setColor(c);   
+  }
+
+};
+
+
+
+
 #endif
index f1be4060be1be4c51d67523080faff42e7b961b8..2070af7a7aaf9f37ef174162daea772ec4f42bea 100644 (file)
 #include "llvm/CodeGen/InstrScheduling.h"
 #include "llvm/CodeGen/InstrSelection.h"
 
+#include "llvm/Analysis/LiveVar/MethodLiveVarInfo.h"
+#include "llvm/CodeGen/PhyRegAlloc.h"
+
+
 // allocateSparcTargetMachine - Allocate and return a subclass of TargetMachine
 // that implements the Sparc backend. (the llvm/CodeGen/Sparc.h interface)
 //
@@ -85,6 +89,327 @@ UltraSparcSchedInfo::initializeResources()
 }
 
 
+
+//---------------------------------------------------------------------------
+// class UltraSparcRegInfo 
+//
+// Purpose:
+//   This class provides info about sparc register classes.
+//--------------------------------------------------------------------------
+
+#if 0
+UltraSparcRegInfo::UltraSparcRegInfo(const UltraSparc *const USI ) : 
+                                                      UltraSparcInfo(USI), 
+                                                      NumOfIntArgRegs(6), 
+                                                      NumOfFloatArgRegs(6) 
+  {    
+    MachineRegClassArr.push_back( new SparcIntRegClass(IntRegClassID) );
+    MachineRegClassArr.push_back( new SparcFloatRegClass(FloatRegClassID) );
+    MachineRegClassArr.push_back( new SparcIntCCRegClass(IntCCRegClassID) );
+    MachineRegClassArr.push_back( new SparcFloatCCRegClass(FloatCCRegClassID));
+
+    assert( SparcFloatRegOrder::StartOfNonVolatileRegs == 6 && 
+           "6 Float regs are used for float arg passing");
+  }
+
+  // ***** TODO  insert deletes for reg classes 
+UltraSparcRegInfo::~UltraSparcRegInfo(void) { }    // empty destructor 
+
+#endif
+
+//---------------------------------------------------------------------------
+// UltraSparcRegInfo
+// Purpose:
+//   This method will color incoming args to a method. If there are more
+//   args than that can fit in regs, code will be inserted to pop them from
+//   stack
+//---------------------------------------------------------------------------
+
+
+void UltraSparcRegInfo::colorArgs(const Method *const Meth, 
+                                 LiveRangeInfo& LRI) const 
+{
+
+                                                 // get the argument list
+  const Method::ArgumentListType& ArgList = Meth->getArgumentList();           
+                                                 // get an iterator to arg list
+  Method::ArgumentListType::const_iterator ArgIt = ArgList.begin(); 
+  unsigned intArgNo=0;
+
+  // to keep track of which float regs are allocated for argument passing
+  bool FloatArgUsedArr[NumOfFloatArgRegs];
+
+  // init float arg used array
+  for(unsigned i=0; i < NumOfFloatArgRegs; ++i) 
+    FloatArgUsedArr[i] = false;
+
+  // for each argument
+  for( ; ArgIt != ArgList.end() ; ++ArgIt) {    
+
+    // get the LR of arg
+    LiveRange *const LR = LRI.getLiveRangeForValue((const Value *) *ArgIt); 
+    unsigned RegClassID = (LR->getRegClass())->getID();
+
+    // if the arg is in int class - allocate a reg for an int arg
+    if( RegClassID == IntRegClassID ) {
+
+      if( intArgNo < NumOfIntArgRegs) {
+       LR->setColor( SparcIntRegOrder::i0 + intArgNo );
+
+       if( DEBUG_RA) printReg( LR );
+      }
+  
+      else {
+       // TODO: Insert push code here
+       assert( 0 && "Insert push code here!");
+      }
+      ++intArgNo;
+    }
+
+    // if the arg is float/double 
+    else if ( RegClassID == FloatRegClassID) {
+
+      if( LR->getTypeID() == Type::DoubleTyID ) {
+
+       // find the first reg # we can pass a double arg
+       for(unsigned i=0; i < NumOfFloatArgRegs; i+= 2) {
+         if ( !FloatArgUsedArr[i] && !FloatArgUsedArr[i+1] ) {
+           LR->setColor( SparcFloatRegOrder::f0 + i );
+           FloatArgUsedArr[i] = true;
+           FloatArgUsedArr[i+1] = true;
+           if( DEBUG_RA) printReg( LR );
+           break;
+         }
+       }
+       if( ! LR->hasColor() ) { // if LR was not colored above
+
+         assert(0 && "insert push code here for a double");
+
+       }
+
+      }
+      else if( LR->getTypeID() == Type::FloatTyID ) { 
+
+       // find the first reg # we can pass a float arg
+       for(unsigned i=0; i < NumOfFloatArgRegs; ++i) {
+         if ( !FloatArgUsedArr[i] ) {
+           LR->setColor( SparcFloatRegOrder::f0 + i );
+           FloatArgUsedArr[i] = true;
+           if( DEBUG_RA) printReg( LR );
+           break;
+         }
+       }
+       if( ! LR->hasColor() ) { // if LR was not colored above
+         assert(0 && "insert push code here for a float");
+       }
+
+      }
+      else 
+       assert(0 && "unknown float type in method arg");
+
+    } // float register class
+
+    else 
+      assert(0 && "Unknown RegClassID");
+  }
+  
+}
+
+
+
+
+
+
+void UltraSparcRegInfo::printReg(const LiveRange *const LR) {
+
+  unsigned RegClassID = (LR->getRegClass())->getID();
+
+  cout << " *Node " << (LR->getUserIGNode())->getIndex();
+
+  if( ! LR->hasColor() ) {
+    cout << " - could not find a color" << endl;
+    return;
+  }
+  
+  // if a color is found
+
+  cout << " colored with color "<< LR->getColor();
+
+  if( RegClassID == IntRegClassID ) {
+
+    cout<< " [" << SparcIntRegOrder::getRegName(LR->getColor()) ;
+    cout << "]" << endl;
+  }
+  else if ( RegClassID == FloatRegClassID) {
+    cout << "[" << SparcFloatRegOrder::getRegName(LR->getColor());
+    if( LR->getTypeID() == Type::DoubleTyID )
+      cout << "+" << SparcFloatRegOrder::getRegName(LR->getColor()+1);
+    cout << "]" << endl;
+  }
+
+
+}
+
+
+void UltraSparcRegInfo::colorCallArgs(vector<const Instruction *> & 
+                                     CallInstrList, LiveRangeInfo& LRI,
+                                     AddedInstrMapType &AddedInstrMap) const
+{
+
+  vector<const Instruction *>::const_iterator InstIt = CallInstrList.begin();
+
+  for( ; InstIt != CallInstrList.end(); ++InstIt) {
+
+    // Inst = LLVM call instruction
+    const Instruction *const CallI = *InstIt;
+
+    MachineCodeForVMInstr &  MInstVec = CallI->getMachineInstrVec();
+    MachineCodeForVMInstr::const_iterator MIIt = MInstVec.begin();
+
+    // find the CALL/JMMPL machine instruction
+    for( ; MIIt != MInstVec.end() && 
+          ! getUltraSparcInfo().getInstrInfo().isCall((*MIIt)->getOpCode()); 
+        ++MIIt );
+
+    assert( (MIIt != MInstVec.end())  && "CALL/JMPL not found");
+
+    // CallMI = CALL/JMPL machine isntruction
+    const MachineInstr *const CallMI = *MIIt;
+
+    Instruction::op_const_iterator OpIt = CallI->op_begin();
+
+    unsigned intArgNo=0;
+    //unsigned NumOfCallInterfs = LR->getNumOfCallInterferences();
+
+    // to keep track of which float regs are allocated for argument passing
+    bool FloatArgUsedArr[NumOfFloatArgRegs];
+
+    // init float arg used array
+    for(unsigned i=0; i < NumOfFloatArgRegs; ++i) 
+      FloatArgUsedArr[i] = false;
+
+    // go thru all the operands of LLVM instruction
+    for( ; OpIt != CallI->op_end(); ++OpIt ) {
+
+      // get the LR of call operand (parameter)
+      LiveRange *const LR = LRI.getLiveRangeForValue((const Value *) *OpIt); 
+
+      if ( !LR ) {
+       cout << " Warning: In call instr, no LR for arg: " ;
+       printValue(*OpIt);
+       cout << endl;
+       continue;
+      }
+
+      unsigned RegClassID = (LR->getRegClass())->getID();
+      
+      // if the arg is in int class - allocate a reg for an int arg
+      if( RegClassID == IntRegClassID ) {
+       
+       if( intArgNo < NumOfIntArgRegs) {
+         setCallArgColor( LR, SparcIntRegOrder::o0 + intArgNo );
+       }
+       
+       else {
+         // TODO: Insert push code here
+         assert( 0 && "Insert push code here!");
+
+         AddedInstrns * AI = AddedInstrMap[ CallMI ];
+         if( ! AI ) AI = new AddedInstrns();
+
+         // AI->InstrnsBefore.push_back( getStackPushInstr(LR) );
+         AddedInstrMap[ CallMI ] = AI;
+         
+       }
+       ++intArgNo;
+      }
+      
+      // if the arg is float/double 
+      else if ( RegClassID == FloatRegClassID) {
+       
+       if( LR->getTypeID() == Type::DoubleTyID ) {
+         
+         // find the first reg # we can pass a double arg
+         for(unsigned i=0; i < NumOfFloatArgRegs; i+= 2) {
+           if ( !FloatArgUsedArr[i] && !FloatArgUsedArr[i+1] ) {
+             setCallArgColor(LR, SparcFloatRegOrder::f0 + i );             
+             FloatArgUsedArr[i] = true;
+             FloatArgUsedArr[i+1] = true;
+             //if( DEBUG_RA) printReg( LR );
+             break;
+           }
+         }
+         if( ! LR->hasColor() ) { // if LR was not colored above
+           
+           assert(0 && "insert push code here for a double");
+           
+         }
+         
+       }
+       else if( LR->getTypeID() == Type::FloatTyID ) { 
+         
+         // find the first reg # we can pass a float arg
+         for(unsigned i=0; i < NumOfFloatArgRegs; ++i) {
+           if ( !FloatArgUsedArr[i] ) {
+             setCallArgColor(LR, SparcFloatRegOrder::f0 + i );
+             FloatArgUsedArr[i] = true;
+             // LR->setColor( SparcFloatRegOrder::f0 + i );
+             // if( DEBUG_RA) printReg( LR );
+             break;
+           }
+         }
+         if( ! LR->hasColor() ) { // if LR was not colored above
+           assert(0 && "insert push code here for a float");
+         }
+         
+       }
+       else 
+         assert(0 && "unknown float type in method arg");
+       
+      } // float register class
+      
+      else 
+       assert(0 && "Unknown RegClassID");
+
+
+    } // for each operand in a call instruction
+
+    
+
+
+  } // for all call instrctions in CallInstrList
+
+}
+
+
+void UltraSparcRegInfo::setCallArgColor(LiveRange *const LR, 
+                                       const unsigned RegNo) const {
+
+  // if no call interference and LR is NOT previously colored (e.g., as an 
+  // incoming arg)
+  if( ! LR->getNumOfCallInterferences() && ! LR->hasColor() ) { 
+    // we can directly allocate a %o register
+    LR->setColor( RegNo);
+    if( DEBUG_RA) printReg( LR );
+  }
+  else {                        // there are call interferences
+    
+    /* 
+    // insert a copy machine instr to copy from LR to %o(reg)
+    PreMInstrMap[ CallMI ] = 
+    getNewCopyMInstr( LR->,  SparcIntRegOrder::o0 + intArgNo );
+    */
+    cout << " $$$ TODO: Insert a copy for call argument!: " << endl;
+
+    // We don't color LR here. It's colored as any other normal LR
+  }
+
+}
+
+
+
+
+
 //---------------------------------------------------------------------------
 // class UltraSparcMachine 
 // 
@@ -97,13 +422,47 @@ UltraSparcSchedInfo::initializeResources()
 //---------------------------------------------------------------------------
 
 UltraSparc::UltraSparc() : TargetMachine("UltraSparc-Native"),
-                          InstSchedulingInfo(&InstInfo) {
+                          InstSchedulingInfo(&InstInfo),
+                          RegInfo( this )  {
   optSizeForSubWordData = 4;
   minMemOpWordSize = 8; 
   maxAtomicMemOpWordSize = 8;
   zeroRegNum = 0;                      // %g0 always gives 0 on Sparc
 }
 
+
+
+//----------------------------------------------------------------------------
+// Entry point for register allocation for a module
+//----------------------------------------------------------------------------
+
+void AllocateRegisters(Method *M, TargetMachine &TM)
+{
+  if ( (M)->isExternal() )     // don't process prototypes
+    return;
+    
+  if( DEBUG_RA ) {
+    cout << endl << "******************** Method "<< (M)->getName();
+    cout <<        " ********************" <<endl;
+  }
+    
+  MethodLiveVarInfo LVI(M );   // Analyze live varaibles
+  LVI.analyze();
+  
+    
+  PhyRegAlloc PRA(M, TM , &LVI); // allocate registers
+  PRA.allocateRegisters();
+    
+
+  if( DEBUG_RA )  cout << endl << "Register allocation complete!" << endl;
+
+}
+
+
+
+
+
 bool UltraSparc::compileMethod(Method *M) {
   if (SelectInstructionsForMethod(M, *this)) {
     cerr << "Instruction selection failed for method " << M->getName()
@@ -116,6 +475,10 @@ bool UltraSparc::compileMethod(Method *M) {
        << M->getName() << "\n\n";
     return true;
   }
+
+  AllocateRegisters(M, *this);    // allocate registers
+
+
   return false;
 }