Added phi elimination code
[oota-llvm.git] / lib / Target / SparcV9 / SparcV9Internals.h
index ad0f17f307d89a2667999d2fc92973494c77c1a2..9b8fe177ef2753ca32638582630994477dbb5e65 100644 (file)
@@ -1,9 +1,13 @@
-//===-- SparcInternals.h - Header file for Sparc backend ---------*- C++ -*--=//
-//
-// This file defines stuff that is to be private to the Sparc backend, but is 
-// shared among different portions of the backend.
-//
-//===----------------------------------------------------------------------===//
+// $Id$ -*- C++ -*--
+//***************************************************************************
+// File:
+//     SparcInternals.h
+// 
+// Purpose:
+//       This file defines stuff that is to be private to the Sparc
+//       backend, but is shared among different portions of the backend.
+//**************************************************************************/
+
 
 #ifndef SPARC_INTERNALS_H
 #define SPARC_INTERNALS_H
@@ -12,8 +16,9 @@
 #include "SparcRegClassInfo.h"
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/Target/MachineInstrInfo.h"
-
 #include "llvm/Target/MachineSchedInfo.h"
+#include "llvm/Target/MachineFrameInfo.h"
+#include "llvm/Target/MachineCacheInfo.h"
 #include "llvm/CodeGen/RegClass.h"
 #include "llvm/Type.h"
 
@@ -62,7 +67,7 @@ enum SparcMachineOpCode {
 
   // End-of-array marker
   INVALID_OPCODE,
-  NUM_REAL_OPCODES = RETURN+1,         // number of valid opcodes
+  NUM_REAL_OPCODES = PHI,              // number of valid opcodes
   NUM_TOTAL_OPCODES = INVALID_OPCODE
 };
 
@@ -83,9 +88,9 @@ extern const MachineInstrDescriptor SparcMachineInstrDesc[];
 
 class UltraSparcInstrInfo : public MachineInstrInfo {
 public:
-  /*ctor*/     UltraSparcInstrInfo();
+  /*ctor*/     UltraSparcInstrInfo(const TargetMachine& tgt);
   
-  virtual bool         hasResultInterlock      (MachineOpCode opCode)
+  virtual bool         hasResultInterlock      (MachineOpCode opCode) const
   {
     // All UltraSPARC instructions have interlocks (note that delay slots
     // are not considered here).
@@ -96,17 +101,65 @@ public:
     return (opCode == FCMPS || opCode == FCMPD || opCode == FCMPQ);
   }
 
+  //-------------------------------------------------------------------------
+  // Code generation support for creating individual machine instructions
+  //-------------------------------------------------------------------------
+  
+  // Create an instruction sequence to put the constant `val' into
+  // the virtual register `dest'.  The generated instructions are
+  // returned in `minstrVec'.  Any temporary registers (TmpInstruction)
+  // created are returned in `tempVec'.
+  // 
+  virtual void  CreateCodeToLoadConst(Value* val,
+                                      Instruction* dest,
+                                      vector<MachineInstr*>& minstrVec,
+                                      vector<TmpInstruction*>& tempVec) const;
 
+  
+  // Create an instruction sequence to copy an integer value `val'
+  // to a floating point value `dest' by copying to memory and back.
+  // val must be an integral type.  dest must be a Float or Double.
+  // The generated instructions are returned in `minstrVec'.
+  // Any temp. registers (TmpInstruction) created are returned in `tempVec'.
+  // 
+  virtual void  CreateCodeToCopyIntToFloat(Method* method,
+                                           Value* val,
+                                           Instruction* dest,
+                                           vector<MachineInstr*>& minstrVec,
+                                           vector<TmpInstruction*>& tempVec,
+                                           TargetMachine& target) const;
+
+  // Similarly, create an instruction sequence to copy an FP value
+  // `val' to an integer value `dest' by copying to memory and back.
+  // See the previous function for information about return values.
+  // 
+  virtual void  CreateCodeToCopyFloatToInt(Method* method,
+                                           Value* val,
+                                           Instruction* dest,
+                                           vector<MachineInstr*>& minstrVec,
+                                           vector<TmpInstruction*>& tempVec,
+                                           TargetMachine& target) const;
+
+ // create copy instruction(s)
+  virtual void
+  CreateCopyInstructionsByType(const TargetMachine& target,
+                             Value* src,
+                             Instruction* dest,
+                             vector<MachineInstr*>& minstrVec) const;
 
 
-  
 };
 
 
+//----------------------------------------------------------------------------
+// class UltraSparcRegInfo
+//
+//----------------------------------------------------------------------------
+
 
 class LiveRange;
 class UltraSparc;
-
+class PhyRegAlloc;
 
 
 class UltraSparcRegInfo : public MachineRegInfo
@@ -135,6 +188,9 @@ class UltraSparcRegInfo : public MachineRegInfo
     FloatCCRegType
   };
 
+  // the size of a value (int, float, etc..) stored in the stack frame
+  
+
 
   // WARNING: If the above enum order must be changed, also modify 
   // getRegisterClassOfValue method below since it assumes this particular 
@@ -148,7 +204,10 @@ class UltraSparcRegInfo : public MachineRegInfo
   // %o0 to %o5 (cannot be changed)
   unsigned const NumOfIntArgRegs;
   unsigned const NumOfFloatArgRegs;
-  unsigned const InvalidRegNum;
+  int const InvalidRegNum;
+  int SizeOfOperandOnStack;
+
+
 
   //void setCallArgColor(LiveRange *const LR, const unsigned RegNo) const;
 
@@ -162,7 +221,8 @@ class UltraSparcRegInfo : public MachineRegInfo
   void suggestReg4RetAddr(const MachineInstr * RetMI, 
                          LiveRangeInfo& LRI) const;
 
-  void suggestReg4CallAddr(const MachineInstr * CallMI) const;
+  void suggestReg4CallAddr(const MachineInstr * CallMI, LiveRangeInfo& LRI,
+                          vector<RegClass *> RCList) const;
 
 
   Value *getValue4ReturnAddr( const MachineInstr * MInst ) const ;
@@ -188,7 +248,7 @@ class UltraSparcRegInfo : public MachineRegInfo
     case FloatCCRegClassID: return FloatCCRegType ; 
 
     default: assert( 0 && "Unknown reg class ID");
-
+      return 0;
     }
 
   }
@@ -214,28 +274,65 @@ class UltraSparcRegInfo : public MachineRegInfo
     case FloatCCRegClassID: return FloatCCRegType ; 
 
     default: assert( 0 && "Unknown reg class ID");
-
+      return 0;
     }
 
   }
 
 
+  int getRegType(int reg) const {
+    if( reg < 32 ) 
+      return IntRegType;
+    else if ( reg < (32 + 32) )
+      return FPSingleRegType;
+    else if ( reg < (64 + 32) )
+      return FPDoubleRegType;
+    else if( reg < (64+32+4) )
+      return FloatCCRegType;
+    else if( reg < (64+32+4+2) )  
+      return IntCCRegType;             
+    else 
+      assert(0 && "Invalid register number in getRegType");
+  }
 
 
-  MachineInstr * cpReg2RegMI(const unsigned SrcReg,  const unsigned DestReg,
-                            const int RegType) const;
+
+  // ***TODO: See this method is necessary
 
   MachineInstr * cpValue2RegMI(Value * Val,  const unsigned DestReg,
                               const int RegType) const;
 
+  const Value *getCallInstRetAddr(const MachineInstr *CallMI) const;
+  const unsigned getCallInstNumArgs(const MachineInstr *CallMI) const;
+
+
+  MachineInstr * cpCCR2IntMI(const unsigned IntReg) const;
+  MachineInstr * cpInt2CCRMI(const unsigned IntReg) const;
+
+
+
+  void moveInst2OrdVec(vector<MachineInstr *> &OrdVec, MachineInstr *UnordInst,
+                      PhyRegAlloc &PRA ) const;
+
+  void OrderAddedInstrns( vector<MachineInstr *> &UnordVec, 
+                         vector<MachineInstr *> &OrdVec,
+                         PhyRegAlloc &PRA) const;
+
+
+
+
+
+
 
  public:
 
 
-  UltraSparcRegInfo(const UltraSparc *const USI ) : UltraSparcInfo(USI), 
+  UltraSparcRegInfo(const TargetMachine& tgt ) :    MachineRegInfo(tgt),
+                                                    UltraSparcInfo(& (const UltraSparc&) tgt), 
                                                    NumOfIntArgRegs(6), 
                                                    NumOfFloatArgRegs(32),
-                                                   InvalidRegNum(1000)
+                                                   InvalidRegNum(1000),
+                                                   SizeOfOperandOnStack(8)
   {    
     MachineRegClassArr.push_back( new SparcIntRegClass(IntRegClassID) );
     MachineRegClassArr.push_back( new SparcFloatRegClass(FloatRegClassID) );
@@ -244,6 +341,7 @@ class UltraSparcRegInfo : public MachineRegInfo
 
     assert( SparcFloatRegOrder::StartOfNonVolatileRegs == 32 && 
            "32 Float regs are used for float arg passing");
+
   }
 
   // ***** TODO  Delete
@@ -269,17 +367,15 @@ class UltraSparcRegInfo : public MachineRegInfo
     else if( ty <= Type::DoubleTyID)
       res = FloatRegClassID;           // sparc float reg class
     else { 
-      cout << "TypeID: " << ty << endl;
+      cerr << "TypeID: " << ty << endl;
       assert(0 && "Cannot resolve register class for type");
-
+      return 0;
     }
 
     if(isCCReg)
       return res + 2;      // corresponidng condition code regiser 
-
     else 
       return res;
-
   }
 
   // returns the register tha contains always zero
@@ -309,7 +405,7 @@ class UltraSparcRegInfo : public MachineRegInfo
                       AddedInstrns *const FirstAI) const;
 
   void colorCallArgs(const MachineInstr *const CallMI, LiveRangeInfo& LRI,
-                    AddedInstrns *const CallAI) const;
+                    AddedInstrns *const CallAI,  PhyRegAlloc &PRA) const;
 
   void colorRetValue(const MachineInstr *const RetI,   LiveRangeInfo& LRI,
                     AddedInstrns *const RetAI) const;
@@ -332,11 +428,11 @@ class UltraSparcRegInfo : public MachineRegInfo
       return reg + 32 + 64;             // 32 int, 64 float
     else if( RegClassID == IntCCRegClassID ) 
       return 4+ 32 + 64;                // only int cc reg
-    else if (reg==1000)                 //****** TODO: Remove 
-      return 1000;
+    else if (reg==InvalidRegNum)                
+      return InvalidRegNum;
     else  
       assert(0 && "Invalid register class or reg number");
-
+    return 0;
   }
 
   // given the unified register number, this gives the name
@@ -347,14 +443,59 @@ 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==1000)                 //****** TODO: Remove
+    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 
       assert(0 && "Invalid register number");
+    return "";
+  }
+
+  inline unsigned int getRegNumInCallersWindow(int reg) {
+    if (reg == InvalidRegNum || reg >= 32)
+      return reg;
+    return SparcIntRegOrder::getRegNumInCallersWindow(reg);
+  }
+  
+  inline bool mustBeRemappedInCallersWindow(int reg) {
+    return (reg != InvalidRegNum && reg < 32);
   }
+  
+  const Value * getCallInstRetVal(const MachineInstr *CallMI) const;
+
+  MachineInstr * cpReg2RegMI(const unsigned SrcReg, const unsigned DestReg,
+                            const int RegType) const;
+
+  MachineInstr * cpReg2MemMI(const unsigned SrcReg,  const unsigned DestPtrReg,
+                            const int Offset, const int RegType) const;
+
+  MachineInstr * cpMem2RegMI(const unsigned SrcPtrReg, const int Offset,
+                            const unsigned DestReg, const int RegType) const;
+
+  MachineInstr* cpValue2Value(Value *Src, Value *Dest) const;
+
+
+  inline bool isRegVolatile(const int RegClassID, const int Reg) const {
+    return  (MachineRegClassArr[RegClassID])->isRegVolatile(Reg);
+  }
+
+
+  inline unsigned getFramePointer() const {
+    return SparcIntRegOrder::i6;
+  }
+
+  inline unsigned getStackPointer() const {
+    return SparcIntRegOrder::o6;
+  }
+
+  inline int getInvalidRegNum() const {
+    return InvalidRegNum;
+  }
+
+
+  void insertCallerSavingCode(const MachineInstr *MInst, 
+                             const BasicBlock *BB, PhyRegAlloc &PRA ) const;
 
 
 };
@@ -498,7 +639,7 @@ const InstrClassRUsage NoneClassRUsage = {
   /*numEntries*/ 0,
   /* V[] */ {
     /*Cycle G */
-    /*Cycle E */
+    /*Ccle E */
     /*Cycle C */
     /*Cycle N1*/
     /*Cycle N1*/
@@ -777,8 +918,6 @@ const InstrIssueDelta  SparcInstrIssueDeltas[] = {
   { ADDCcc,    true,   true,   0 },
   { SUBC,      true,   true,   0 },
   { SUBCcc,    true,   true,   0 },
-//{ SAVE,      true,   true,   0 },
-//{ RESTORE,   true,   true,   0 },
 //{ LDSTUB,    true,   true,   0 },
 //{ SWAP,      true,   true,   0 },
 //{ SWAPA,     true,   true,   0 },
@@ -802,17 +941,14 @@ const InstrIssueDelta  SparcInstrIssueDeltas[] = {
   { RETURN,    true,   true,   0 },
 //{ DONE,      true,   true,   0 },
 //{ RETRY,     true,   true,   0 },
-//{ WR,                true,   true,   0 },
-//{ WRPR,      true,   true,   4 },
-//{ RD,                true,   true,   0 },
-//{ RDPR,      true,   true,   0 },
 //{ TCC,       true,   true,   0 },
 //{ SHUTDOWN,  true,   true,   0 },
   
                                // Special cases for breaking group *before*
                                // CURRENTLY NOT SUPPORTED!
   { CALL,      false,  false,  0 },
-  { JMPL,      false,  false,  0 },
+  { JMPLCALL,  false,  false,  0 },
+  { JMPLRET,   false,  false,  0 },
   
                                // Special cases for breaking the group *after*
   { MULX,      true,   true,   (4+34)/2 },
@@ -832,8 +968,10 @@ const InstrIssueDelta  SparcInstrIssueDeltas[] = {
   { UDIVX,     true,   true,   68 },
 //{ SDIVcc,    true,   true,   36 },
 //{ UDIVcc,    true,   true,   37 },
-//{ WR,                false,  false,  4 },
-//{ WRPR,      false,  false,  4 },
+  { WRCCR,     true,   true,   4 },
+//{ WRPR,      true,   true,   4 },
+//{ RDCCR,     true,   true,   0 }, // no bubbles after, but see below
+//{ RDPR,      true,   true,   0 },
 };
 
 
@@ -852,7 +990,8 @@ const InstrRUsageDelta SparcInstrUsageDeltas[] = {
   // 
   // JMPL counts as a load/store instruction for issue!
   //
-  { JMPL,     LSIssueSlots.rid,  0,  1 },
+  { JMPLCALL, LSIssueSlots.rid,  0,  1 },
+  { JMPLRET,  LSIssueSlots.rid,  0,  1 },
   
   // 
   // Many instructions cannot issue for the next 2 cycles after an FCMP
@@ -879,7 +1018,7 @@ const InstrRUsageDelta SparcInstrUsageDeltas[] = {
   
   // 
   // Some instructions are stalled in the GROUP stage if a CTI is in
-  // the E or C stage
+  // the E or C stage.  We model that with a fake resource CTIDelayCycle.
   // 
   { LDD,      CTIDelayCycle.rid,  1, 1 },
 //{ LDDA,     CTIDelayCycle.rid,  1, 1 },
@@ -905,6 +1044,17 @@ const InstrRUsageDelta SparcInstrUsageDeltas[] = {
   { LDSW,    LdReturn.rid,  2, -1 },
   { LDSW,    LdReturn.rid,  3,  1 },
 
+  //
+  // RDPR from certain registers and RD from any register are not dispatchable
+  // until four clocks after they reach the head of the instr. buffer.
+  // Together with their single-issue requirement, this means all four issue
+  // slots are effectively blocked for those cycles, plus the issue cycle.
+  // This does not increase the latency of the instruction itself.
+  // 
+  { RDCCR,   AllIssueSlots.rid,     0,  5 },
+  { RDCCR,   AllIssueSlots.rid,     0,  5 },
+  { RDCCR,   AllIssueSlots.rid,     0,  5 },
+  { RDCCR,   AllIssueSlots.rid,     0,  5 },
 
 #undef EXPLICIT_BUBBLES_NEEDED
 #ifdef EXPLICIT_BUBBLES_NEEDED
@@ -1049,13 +1199,117 @@ const InstrRUsageDelta SparcInstrUsageDeltas[] = {
 
 class UltraSparcSchedInfo: public MachineSchedInfo {
 public:
-  /*ctor*/        UltraSparcSchedInfo  (const MachineInstrInfo* mii);
+  /*ctor*/        UltraSparcSchedInfo  (const TargetMachine& tgt);
   /*dtor*/ virtual ~UltraSparcSchedInfo        () {}
 protected:
   virtual void initializeResources     ();
 };
 
 
+//---------------------------------------------------------------------------
+// class UltraSparcFrameInfo 
+// 
+// Purpose:
+//   Interface to stack frame layout info for the UltraSPARC.
+//---------------------------------------------------------------------------
+
+class UltraSparcFrameInfo: public MachineFrameInfo {
+public:
+  /*ctor*/ UltraSparcFrameInfo(const TargetMachine& tgt) : MachineFrameInfo(tgt) {}
+  
+public:
+  int  getStackFrameSizeAlignment   () const { return StackFrameSizeAlignment;}
+  int  getMinStackFrameSize         () const { return MinStackFrameSize; }
+  int  getNumFixedOutgoingArgs      () const { return NumFixedOutgoingArgs; }
+  int  getSizeOfEachArgOnStack      () const { return SizeOfEachArgOnStack; }
+  bool argsOnStackHaveFixedSize     () const { return true; }
+
+  //
+  // These methods compute offsets using the frame contents for a
+  // particular method.  The frame contents are obtained from the
+  // MachineCodeInfoForMethod object for the given method.
+  // 
+  int getFirstIncomingArgOffset  (MachineCodeForMethod& mcInfo,
+                                  bool& pos) const
+  {
+    pos = true;                         // arguments area grows upwards
+    return FirstIncomingArgOffsetFromFP;
+  }
+  int getFirstOutgoingArgOffset  (MachineCodeForMethod& mcInfo,
+                                  bool& pos) const
+  {
+    pos = true;                         // arguments area grows upwards
+    return FirstOutgoingArgOffsetFromSP;
+  }
+  int getFirstOptionalOutgoingArgOffset(MachineCodeForMethod& mcInfo,
+                                        bool& pos)const
+  {
+    pos = true;                         // arguments area grows upwards
+    return FirstOptionalOutgoingArgOffsetFromSP;
+  }
+  
+  int getFirstAutomaticVarOffset (MachineCodeForMethod& mcInfo,
+                                  bool& pos) const;
+  int getRegSpillAreaOffset      (MachineCodeForMethod& mcInfo,
+                                  bool& pos) const;
+  int getTmpAreaOffset           (MachineCodeForMethod& mcInfo,
+                                  bool& pos) const;
+  int getDynamicAreaOffset       (MachineCodeForMethod& mcInfo,
+                                  bool& pos) const;
+
+  //
+  // These methods specify the base register used for each stack area
+  // (generally FP or SP)
+  // 
+  virtual int getIncomingArgBaseRegNum()               const {
+    return (int) target.getRegInfo().getFramePointer();
+  }
+  virtual int getOutgoingArgBaseRegNum()               const {
+    return (int) target.getRegInfo().getStackPointer();
+  }
+  virtual int getOptionalOutgoingArgBaseRegNum()       const {
+    return (int) target.getRegInfo().getStackPointer();
+  }
+  virtual int getAutomaticVarBaseRegNum()              const {
+    return (int) target.getRegInfo().getFramePointer();
+  }
+  virtual int getRegSpillAreaBaseRegNum()              const {
+    return (int) target.getRegInfo().getFramePointer();
+  }
+  virtual int getDynamicAreaBaseRegNum()               const {
+    return (int) target.getRegInfo().getStackPointer();
+  }
+  
+private:
+  // All stack addresses must be offset by 0x7ff (2047) on Sparc V9.
+  static const int OFFSET                                  = (int) 0x7ff;
+  static const int StackFrameSizeAlignment                 =  16;
+  static const int MinStackFrameSize                       = 176;
+  static const int NumFixedOutgoingArgs                    =   6;
+  static const int SizeOfEachArgOnStack                    =   8;
+  static const int StaticAreaOffsetFromFP                  =  0 + OFFSET;
+  static const int FirstIncomingArgOffsetFromFP            = 128 + OFFSET;
+  static const int FirstOptionalIncomingArgOffsetFromFP    = 176 + OFFSET;
+  static const int FirstOutgoingArgOffsetFromSP            = 128 + OFFSET;
+  static const int FirstOptionalOutgoingArgOffsetFromSP    = 176 + OFFSET;
+};
+
+
+//---------------------------------------------------------------------------
+// class UltraSparcCacheInfo 
+// 
+// Purpose:
+//   Interface to cache parameters for the UltraSPARC.
+//   Just use defaults for now.
+//---------------------------------------------------------------------------
+
+class UltraSparcCacheInfo: public MachineCacheInfo {
+public:
+  /*ctor*/          UltraSparcCacheInfo  (const TargetMachine& target) :
+    MachineCacheInfo(target) {} 
+};
+
+
 //---------------------------------------------------------------------------
 // class UltraSparcMachine 
 // 
@@ -1071,6 +1325,8 @@ private:
   UltraSparcInstrInfo instrInfo;
   UltraSparcSchedInfo schedInfo;
   UltraSparcRegInfo   regInfo;
+  UltraSparcFrameInfo frameInfo;
+  UltraSparcCacheInfo cacheInfo;
 public:
   UltraSparc();
   virtual ~UltraSparc() {}
@@ -1078,6 +1334,8 @@ public:
   virtual const MachineInstrInfo &getInstrInfo() const { return instrInfo; }
   virtual const MachineSchedInfo &getSchedInfo() const { return schedInfo; }
   virtual const MachineRegInfo   &getRegInfo()   const { return regInfo; }
+  virtual const MachineFrameInfo &getFrameInfo() const { return frameInfo; }
+  virtual const MachineCacheInfo &getCacheInfo() const { return cacheInfo; }
   
   // compileMethod - For the sparc, we do instruction selection, followed by
   // delay slot scheduling, then register allocation.