-//===-- 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
#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"
// 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
};
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).
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
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
unsigned const NumOfIntArgRegs;
unsigned const NumOfFloatArgRegs;
int const InvalidRegNum;
+ int SizeOfOperandOnStack;
+
+
//void setCallArgColor(LiveRange *const LR, const unsigned RegNo) const;
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 ;
case FloatCCRegClassID: return FloatCCRegType ;
default: assert( 0 && "Unknown reg class ID");
-
+ return 0;
}
}
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");
+ }
+
+
// ***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) );
assert( SparcFloatRegOrder::StartOfNonVolatileRegs == 32 &&
"32 Float regs are used for float arg passing");
+
}
// ***** TODO Delete
else {
cerr << "TypeID: " << ty << endl;
assert(0 && "Cannot resolve register class for type");
+ return 0;
}
if(isCCReg)
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;
return InvalidRegNum;
else
assert(0 && "Invalid register class or reg number");
-
+ return 0;
}
// given the unified register number, this gives the name
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== InvalidRegNum) //****** 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 * 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);
}
return InvalidRegNum;
}
+
+ void insertCallerSavingCode(const MachineInstr *MInst,
+ const BasicBlock *BB, PhyRegAlloc &PRA ) const;
+
+
};
{ 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 },
{ 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 },
{ 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 },
};
//
// 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
//
// 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 },
{ 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
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
//
UltraSparcInstrInfo instrInfo;
UltraSparcSchedInfo schedInfo;
UltraSparcRegInfo regInfo;
+ UltraSparcFrameInfo frameInfo;
+ UltraSparcCacheInfo cacheInfo;
public:
UltraSparc();
virtual ~UltraSparc() {}
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.