diff options
author | Misha Brukman <brukman+llvm@gmail.com> | 2003-12-17 22:04:00 +0000 |
---|---|---|
committer | Misha Brukman <brukman+llvm@gmail.com> | 2003-12-17 22:04:00 +0000 |
commit | d71295a684fb351e196f4f78ea94e5d1af904eb8 (patch) | |
tree | ebc260c7a6036eb8c698cd062804a8beacbc9e31 /lib | |
parent | 3e7ada642a00c6904231f2446b33c7f15bb45151 (diff) | |
download | external_llvm-d71295a684fb351e196f4f78ea94e5d1af904eb8.zip external_llvm-d71295a684fb351e196f4f78ea94e5d1af904eb8.tar.gz external_llvm-d71295a684fb351e196f4f78ea94e5d1af904eb8.tar.bz2 |
Reorganized the Sparc backend to be more modular -- each different
implementation of a Target{RegInfo, InstrInfo, Machine, etc} now has a separate
header and a separate implementation file.
This means that instead of a massive SparcInternals.h that forces a
recompilation of the whole target whenever a minor detail is changed, you should
only recompile a few files.
Note that SparcInternals.h is still around; its contents should be minimized.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@10500 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Target/SparcV9/SparcV9CodeEmitter.cpp | 63 | ||||
-rw-r--r-- | lib/Target/SparcV9/SparcV9FrameInfo.cpp | 65 | ||||
-rw-r--r-- | lib/Target/SparcV9/SparcV9FrameInfo.h | 174 | ||||
-rw-r--r-- | lib/Target/SparcV9/SparcV9InstrInfo.cpp | 43 | ||||
-rw-r--r-- | lib/Target/SparcV9/SparcV9InstrInfo.h | 201 | ||||
-rw-r--r-- | lib/Target/SparcV9/SparcV9InstrSelection.cpp | 15 | ||||
-rw-r--r-- | lib/Target/SparcV9/SparcV9Internals.h | 583 | ||||
-rw-r--r-- | lib/Target/SparcV9/SparcV9RegClassInfo.cpp | 9 | ||||
-rw-r--r-- | lib/Target/SparcV9/SparcV9RegInfo.cpp | 88 | ||||
-rw-r--r-- | lib/Target/SparcV9/SparcV9RegInfo.h | 190 | ||||
-rw-r--r-- | lib/Target/SparcV9/SparcV9SchedInfo.cpp | 6 | ||||
-rw-r--r-- | lib/Target/SparcV9/SparcV9TargetMachine.cpp | 122 | ||||
-rw-r--r-- | lib/Target/SparcV9/SparcV9TargetMachine.h | 59 |
13 files changed, 845 insertions, 773 deletions
diff --git a/lib/Target/SparcV9/SparcV9CodeEmitter.cpp b/lib/Target/SparcV9/SparcV9CodeEmitter.cpp index 9a51faa..bb4bdaf 100644 --- a/lib/Target/SparcV9/SparcV9CodeEmitter.cpp +++ b/lib/Target/SparcV9/SparcV9CodeEmitter.cpp @@ -35,6 +35,8 @@ #include "Support/hash_set" #include "Support/Statistic.h" #include "SparcInternals.h" +#include "SparcTargetMachine.h" +#include "SparcRegInfo.h" #include "SparcV9CodeEmitter.h" #include "Config/alloca.h" @@ -46,8 +48,8 @@ namespace { Statistic<> CallbackCalls("callback", "Number CompilationCallback() calls"); } -bool UltraSparc::addPassesToEmitMachineCode(FunctionPassManager &PM, - MachineCodeEmitter &MCE) { +bool SparcTargetMachine::addPassesToEmitMachineCode(FunctionPassManager &PM, + MachineCodeEmitter &MCE) { MachineCodeEmitter *M = &MCE; DEBUG(M = MachineCodeEmitter::createFilePrinterEmitter(MCE)); PM.add(new SparcV9CodeEmitter(*this, *M)); @@ -102,10 +104,10 @@ namespace { private: uint64_t emitStubForFunction(Function *F); - static void SaveRegisters(uint64_t DoubleFP[], uint64_t &FSR, - uint64_t &FPRS, uint64_t &CCR); - static void RestoreRegisters(uint64_t DoubleFP[], uint64_t &FSR, - uint64_t &FPRS, uint64_t &CCR); + static void SaveRegisters(uint64_t DoubleFP[], uint64_t CC[], + uint64_t Globals[]); + static void RestoreRegisters(uint64_t DoubleFP[], uint64_t CC[], + uint64_t Globals[]); static void CompilationCallback(); uint64_t resolveFunctionReference(uint64_t RetAddr); @@ -209,17 +211,20 @@ void JITResolver::insertFarJumpAtAddr(int64_t Target, uint64_t Addr) { } } -void JITResolver::SaveRegisters(uint64_t DoubleFP[], uint64_t &FSR, - uint64_t &FPRS, uint64_t &CCR) { +void JITResolver::SaveRegisters(uint64_t DoubleFP[], uint64_t CC[], + uint64_t Globals[]) { #if defined(sparc) || defined(__sparc__) || defined(__sparcv9) -#if 0 __asm__ __volatile__ (// Save condition-code registers "stx %%fsr, %0;\n\t" "rd %%fprs, %1;\n\t" "rd %%ccr, %2;\n\t" - : "=m"(FSR), "=r"(FPRS), "=r"(CCR)); -#endif + : "=m"(CC[0]), "=r"(CC[1]), "=r"(CC[2])); + + __asm__ __volatile__ (// Save globals g1 and g5 + "stx %%g1, %0;\n\t" + "stx %%g5, %0;\n\t" + : "=m"(Globals[0]), "=m"(Globals[1])); // GCC says: `asm' only allows up to thirty parameters! __asm__ __volatile__ (// Save Single/Double FP registers, part 1 @@ -261,18 +266,21 @@ void JITResolver::SaveRegisters(uint64_t DoubleFP[], uint64_t &FSR, } -void JITResolver::RestoreRegisters(uint64_t DoubleFP[], uint64_t &FSR, - uint64_t &FPRS, uint64_t &CCR) +void JITResolver::RestoreRegisters(uint64_t DoubleFP[], uint64_t CC[], + uint64_t Globals[]) { #if defined(sparc) || defined(__sparc__) || defined(__sparcv9) -#if 0 __asm__ __volatile__ (// Restore condition-code registers "ldx %0, %%fsr;\n\t" "wr %1, 0, %%fprs;\n\t" "wr %2, 0, %%ccr;\n\t" - :: "m"(FSR), "r"(FPRS), "r"(CCR)); -#endif + :: "m"(CC[0]), "r"(CC[1]), "r"(CC[2])); + + __asm__ __volatile__ (// Restore globals g1 and g5 + "ldx %0, %%g1;\n\t" + "ldx %0, %%g5;\n\t" + :: "m"(Globals[0]), "m"(Globals[1])); // GCC says: `asm' only allows up to thirty parameters! __asm__ __volatile__ (// Restore Single/Double FP registers, part 1 @@ -314,11 +322,12 @@ void JITResolver::RestoreRegisters(uint64_t DoubleFP[], uint64_t &FSR, } void JITResolver::CompilationCallback() { - // Local space to save double registers + // Local space to save the registers uint64_t DoubleFP[32]; - uint64_t FSR, FPRS, CCR; + uint64_t CC[3]; + uint64_t Globals[2]; - SaveRegisters(DoubleFP, FSR, FPRS, CCR); + SaveRegisters(DoubleFP, CC, Globals); ++CallbackCalls; uint64_t CameFrom = (uint64_t)(intptr_t)__builtin_return_address(0); @@ -394,7 +403,7 @@ void JITResolver::CompilationCallback() { __asm__ __volatile__ ("sub %%i7, %0, %%i7" : : "r" (Offset+12)); #endif - RestoreRegisters(DoubleFP, FSR, FPRS, CCR); + RestoreRegisters(DoubleFP, CC, Globals); } /// emitStubForFunction - This method is used by the JIT when it needs to emit @@ -476,7 +485,7 @@ SparcV9CodeEmitter::getRealRegNum(unsigned fakeReg, fakeReg = RI.getClassRegNum(fakeReg, regClass); switch (regClass) { - case UltraSparcRegInfo::IntRegClassID: { + case SparcRegInfo::IntRegClassID: { // Sparc manual, p31 static const unsigned IntRegMap[] = { // "o0", "o1", "o2", "o3", "o4", "o5", "o7", @@ -494,12 +503,12 @@ SparcV9CodeEmitter::getRealRegNum(unsigned fakeReg, return IntRegMap[fakeReg]; break; } - case UltraSparcRegInfo::FloatRegClassID: { + case SparcRegInfo::FloatRegClassID: { DEBUG(std::cerr << "FP reg: " << fakeReg << "\n"); - if (regType == UltraSparcRegInfo::FPSingleRegType) { + if (regType == SparcRegInfo::FPSingleRegType) { // only numbered 0-31, hence can already fit into 5 bits (and 6) DEBUG(std::cerr << "FP single reg, returning: " << fakeReg << "\n"); - } else if (regType == UltraSparcRegInfo::FPDoubleRegType) { + } else if (regType == SparcRegInfo::FPDoubleRegType) { // FIXME: This assumes that we only have 5-bit register fields! // From Sparc Manual, page 40. // The bit layout becomes: b[4], b[3], b[2], b[1], b[5] @@ -509,7 +518,7 @@ SparcV9CodeEmitter::getRealRegNum(unsigned fakeReg, } return fakeReg; } - case UltraSparcRegInfo::IntCCRegClassID: { + case SparcRegInfo::IntCCRegClassID: { /* xcc, icc, ccr */ static const unsigned IntCCReg[] = { 6, 4, 2 }; @@ -518,7 +527,7 @@ SparcV9CodeEmitter::getRealRegNum(unsigned fakeReg, DEBUG(std::cerr << "IntCC reg: " << IntCCReg[fakeReg] << "\n"); return IntCCReg[fakeReg]; } - case UltraSparcRegInfo::FloatCCRegClassID: { + case SparcRegInfo::FloatCCRegClassID: { /* These are laid out %fcc0 - %fcc3 => 0 - 3, so are correct */ DEBUG(std::cerr << "FP CC reg: " << fakeReg << "\n"); return fakeReg; @@ -573,7 +582,7 @@ inline void SparcV9CodeEmitter::emitFarCall(uint64_t Target, Function *F) { } } -void UltraSparc::replaceMachineCodeForFunction (void *Old, void *New) { +void SparcTargetMachine::replaceMachineCodeForFunction (void *Old, void *New) { assert (TheJITResolver && "Can only call replaceMachineCodeForFunction from within JIT"); uint64_t Target = (uint64_t)(intptr_t)New; diff --git a/lib/Target/SparcV9/SparcV9FrameInfo.cpp b/lib/Target/SparcV9/SparcV9FrameInfo.cpp new file mode 100644 index 0000000..d283e94 --- /dev/null +++ b/lib/Target/SparcV9/SparcV9FrameInfo.cpp @@ -0,0 +1,65 @@ +//===-- Sparc.cpp - General implementation file for the Sparc Target ------===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Interface to stack frame layout info for the UltraSPARC. Starting offsets +// for each area of the stack frame are aligned at a multiple of +// getStackFrameSizeAlignment(). +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFunctionInfo.h" +#include "llvm/Target/TargetFrameInfo.h" +#include "SparcFrameInfo.h" + +using namespace llvm; + +int +SparcFrameInfo::getFirstAutomaticVarOffset(MachineFunction&, bool& pos) const { + pos = false; // static stack area grows downwards + return StaticAreaOffsetFromFP; +} + +int +SparcFrameInfo::getRegSpillAreaOffset(MachineFunction& mcInfo, bool& pos) const +{ + // ensure no more auto vars are added + mcInfo.getInfo()->freezeAutomaticVarsArea(); + + pos = false; // static stack area grows downwards + unsigned autoVarsSize = mcInfo.getInfo()->getAutomaticVarsSize(); + return StaticAreaOffsetFromFP - autoVarsSize; +} + +int SparcFrameInfo::getTmpAreaOffset(MachineFunction& mcInfo, bool& pos) const { + MachineFunctionInfo *MFI = mcInfo.getInfo(); + MFI->freezeAutomaticVarsArea(); // ensure no more auto vars are added + MFI->freezeSpillsArea(); // ensure no more spill slots are added + + pos = false; // static stack area grows downwards + unsigned autoVarsSize = MFI->getAutomaticVarsSize(); + unsigned spillAreaSize = MFI->getRegSpillsSize(); + int offset = autoVarsSize + spillAreaSize; + return StaticAreaOffsetFromFP - offset; +} + +int +SparcFrameInfo::getDynamicAreaOffset(MachineFunction& mcInfo, bool& pos) const { + // Dynamic stack area grows downwards starting at top of opt-args area. + // The opt-args, required-args, and register-save areas are empty except + // during calls and traps, so they are shifted downwards on each + // dynamic-size alloca. + pos = false; + unsigned optArgsSize = mcInfo.getInfo()->getMaxOptionalArgsSize(); + if (int extra = optArgsSize % getStackFrameSizeAlignment()) + optArgsSize += (getStackFrameSizeAlignment() - extra); + int offset = optArgsSize + FirstOptionalOutgoingArgOffsetFromSP; + assert((offset - OFFSET) % getStackFrameSizeAlignment() == 0); + return offset; +} diff --git a/lib/Target/SparcV9/SparcV9FrameInfo.h b/lib/Target/SparcV9/SparcV9FrameInfo.h new file mode 100644 index 0000000..9038596 --- /dev/null +++ b/lib/Target/SparcV9/SparcV9FrameInfo.h @@ -0,0 +1,174 @@ +//===-- SparcFrameInfo.h - Define TargetFrameInfo for Sparc -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Interface to stack frame layout info for the UltraSPARC. +// Starting offsets for each area of the stack frame are aligned at +// a multiple of getStackFrameSizeAlignment(). +// +//---------------------------------------------------------------------------- + +#ifndef SPARC_FRAMEINFO_H +#define SPARC_FRAMEINFO_H + +#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegInfo.h" + +namespace llvm { + +class SparcFrameInfo: public TargetFrameInfo { + const TargetMachine ⌖ +public: + SparcFrameInfo(const TargetMachine &TM) + : TargetFrameInfo(StackGrowsDown, StackFrameSizeAlignment, 0), target(TM) {} + +public: + // These methods provide constant parameters of the frame layout. + // + 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; } + + // This method adjusts a stack offset to meet alignment rules of target. + // The fixed OFFSET (0x7ff) must be subtracted and the result aligned. + virtual int adjustAlignment(int unalignedOffset, bool growUp, + unsigned int align) const { + return unalignedOffset + (growUp? +1:-1)*((unalignedOffset-OFFSET) % align); + } + + // These methods compute offsets using the frame contents for a + // particular function. The frame contents are obtained from the + // MachineCodeInfoForMethod object for the given function. + // + int getFirstIncomingArgOffset(MachineFunction& mcInfo, bool& growUp) const { + growUp = true; // arguments area grows upwards + return FirstIncomingArgOffsetFromFP; + } + int getFirstOutgoingArgOffset(MachineFunction& mcInfo, bool& growUp) const { + growUp = true; // arguments area grows upwards + return FirstOutgoingArgOffsetFromSP; + } + int getFirstOptionalOutgoingArgOffset(MachineFunction& mcInfo, + bool& growUp) const { + growUp = true; // arguments area grows upwards + return FirstOptionalOutgoingArgOffsetFromSP; + } + + int getFirstAutomaticVarOffset(MachineFunction& mcInfo, bool& growUp) const; + int getRegSpillAreaOffset(MachineFunction& mcInfo, bool& growUp) const; + int getTmpAreaOffset(MachineFunction& mcInfo, bool& growUp) const; + int getDynamicAreaOffset(MachineFunction& mcInfo, bool& growUp) 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(); + } + + virtual int getIncomingArgOffset(MachineFunction& mcInfo, + unsigned argNum) const { + assert(argsOnStackHaveFixedSize()); + + unsigned relativeOffset = argNum * getSizeOfEachArgOnStack(); + bool growUp; // do args grow up or down + int firstArg = getFirstIncomingArgOffset(mcInfo, growUp); + return growUp ? firstArg + relativeOffset : firstArg - relativeOffset; + } + + virtual int getOutgoingArgOffset(MachineFunction& mcInfo, + unsigned argNum) const { + assert(argsOnStackHaveFixedSize()); + //assert(((int) argNum - this->getNumFixedOutgoingArgs()) + // <= (int) mcInfo.getInfo()->getMaxOptionalNumArgs()); + + unsigned relativeOffset = argNum * getSizeOfEachArgOnStack(); + bool growUp; // do args grow up or down + int firstArg = getFirstOutgoingArgOffset(mcInfo, growUp); + return growUp ? firstArg + relativeOffset : firstArg - relativeOffset; + } + +private: + /*---------------------------------------------------------------------- + This diagram shows the stack frame layout used by llc on Sparc V9. + Note that only the location of automatic variables, spill area, + temporary storage, and dynamically allocated stack area are chosen + by us. The rest conform to the Sparc V9 ABI. + All stack addresses are offset by OFFSET = 0x7ff (2047). + + Alignment assumptions and other invariants: + (1) %sp+OFFSET and %fp+OFFSET are always aligned on 16-byte boundary + (2) Variables in automatic, spill, temporary, or dynamic regions + are aligned according to their size as in all memory accesses. + (3) Everything below the dynamically allocated stack area is only used + during a call to another function, so it is never needed when + the current function is active. This is why space can be allocated + dynamically by incrementing %sp any time within the function. + + STACK FRAME LAYOUT: + + ... + %fp+OFFSET+176 Optional extra incoming arguments# 1..N + %fp+OFFSET+168 Incoming argument #6 + ... ... + %fp+OFFSET+128 Incoming argument #1 + ... ... + ---%fp+OFFSET-0--------Bottom of caller's stack frame-------------------- + %fp+OFFSET-8 Automatic variables <-- ****TOP OF STACK FRAME**** + Spill area + Temporary storage + ... + + %sp+OFFSET+176+8N Bottom of dynamically allocated stack area + %sp+OFFSET+168+8N Optional extra outgoing argument# N + ... ... + %sp+OFFSET+176 Optional extra outgoing argument# 1 + %sp+OFFSET+168 Outgoing argument #6 + ... ... + %sp+OFFSET+128 Outgoing argument #1 + %sp+OFFSET+120 Save area for %i7 + ... ... + %sp+OFFSET+0 Save area for %l0 <-- ****BOTTOM OF STACK FRAME**** + + *----------------------------------------------------------------------*/ + + // 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 FirstIncomingArgOffsetFromFP = 128 + OFFSET; + static const int FirstOptionalIncomingArgOffsetFromFP = 176 + OFFSET; + static const int StaticAreaOffsetFromFP = 0 + OFFSET; + static const int FirstOutgoingArgOffsetFromSP = 128 + OFFSET; + static const int FirstOptionalOutgoingArgOffsetFromSP = 176 + OFFSET; +}; + +} // End llvm namespace + +#endif diff --git a/lib/Target/SparcV9/SparcV9InstrInfo.cpp b/lib/Target/SparcV9/SparcV9InstrInfo.cpp index 11b0c7b..af458ea 100644 --- a/lib/Target/SparcV9/SparcV9InstrInfo.cpp +++ b/lib/Target/SparcV9/SparcV9InstrInfo.cpp @@ -9,8 +9,6 @@ // //===----------------------------------------------------------------------===// -#include "SparcInternals.h" -#include "SparcInstrSelectionSupport.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/Function.h" @@ -22,6 +20,9 @@ #include "llvm/CodeGen/MachineFunctionInfo.h" #include "llvm/CodeGen/MachineCodeForInstruction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" +#include "SparcInternals.h" +#include "SparcInstrSelectionSupport.h" +#include "SparcInstrInfo.h" namespace llvm { @@ -41,7 +42,7 @@ static const uint32_t MAXSIMM = (1 << 12) - 1; // set bits in simm13 field of OR //--------------------------------------------------------------------------- uint64_t -UltraSparcInstrInfo::ConvertConstantToIntType(const TargetMachine &target, +SparcInstrInfo::ConvertConstantToIntType(const TargetMachine &target, const Value *V, const Type *destType, bool &isValidConstant) const @@ -406,7 +407,7 @@ InitializeMaxConstantsTable() //--------------------------------------------------------------------------- -// class UltraSparcInstrInfo +// class SparcInstrInfo // // Purpose: // Information about individual instructions. @@ -416,7 +417,7 @@ InitializeMaxConstantsTable() //--------------------------------------------------------------------------- /*ctor*/ -UltraSparcInstrInfo::UltraSparcInstrInfo() +SparcInstrInfo::SparcInstrInfo() : TargetInstrInfo(SparcMachineInstrDesc, /*descSize = */ V9::NUM_TOTAL_OPCODES, /*numRealOpCodes = */ V9::NUM_REAL_OPCODES) @@ -425,7 +426,7 @@ UltraSparcInstrInfo::UltraSparcInstrInfo() } bool -UltraSparcInstrInfo::ConstantMayNotFitInImmedField(const Constant* CV, +SparcInstrInfo::ConstantMayNotFitInImmedField(const Constant* CV, const Instruction* I) const { if (I->getOpcode() >= MaxConstantsTable.size()) // user-defined op (or bug!) @@ -455,12 +456,12 @@ UltraSparcInstrInfo::ConstantMayNotFitInImmedField(const Constant* CV, // Any stack space required is allocated via MachineFunction. // void -UltraSparcInstrInfo::CreateCodeToLoadConst(const TargetMachine& target, - Function* F, - Value* val, - Instruction* dest, - std::vector<MachineInstr*>& mvec, - MachineCodeForInstruction& mcfi) const +SparcInstrInfo::CreateCodeToLoadConst(const TargetMachine& target, + Function* F, + Value* val, + Instruction* dest, + std::vector<MachineInstr*>& mvec, + MachineCodeForInstruction& mcfi) const { assert(isa<Constant>(val) || isa<GlobalValue>(val) && "I only know about constant values and global addresses"); @@ -552,7 +553,7 @@ UltraSparcInstrInfo::CreateCodeToLoadConst(const TargetMachine& target, // Any stack space required is allocated via MachineFunction. // void -UltraSparcInstrInfo::CreateCodeToCopyIntToFloat(const TargetMachine& target, +SparcInstrInfo::CreateCodeToCopyIntToFloat(const TargetMachine& target, Function* F, Value* val, Instruction* dest, @@ -613,7 +614,7 @@ UltraSparcInstrInfo::CreateCodeToCopyIntToFloat(const TargetMachine& target, // Temporary stack space required is allocated via MachineFunction. // void -UltraSparcInstrInfo::CreateCodeToCopyFloatToInt(const TargetMachine& target, +SparcInstrInfo::CreateCodeToCopyFloatToInt(const TargetMachine& target, Function* F, Value* val, Instruction* dest, @@ -664,11 +665,11 @@ UltraSparcInstrInfo::CreateCodeToCopyFloatToInt(const TargetMachine& target, // Any stack space required is allocated via MachineFunction. // void -UltraSparcInstrInfo::CreateCopyInstructionsByType(const TargetMachine& target, - Function *F, - Value* src, - Instruction* dest, - std::vector<MachineInstr*>& mvec, +SparcInstrInfo::CreateCopyInstructionsByType(const TargetMachine& target, + Function *F, + Value* src, + Instruction* dest, + std::vector<MachineInstr*>& mvec, MachineCodeForInstruction& mcfi) const { bool loadConstantToReg = false; @@ -760,7 +761,7 @@ CreateBitExtensionInstructions(bool signExtend, // Any stack space required is allocated via MachineFunction. // void -UltraSparcInstrInfo::CreateSignExtensionInstructions( +SparcInstrInfo::CreateSignExtensionInstructions( const TargetMachine& target, Function* F, Value* srcVal, @@ -782,7 +783,7 @@ UltraSparcInstrInfo::CreateSignExtensionInstructions( // Any stack space required is allocated via MachineFunction. // void -UltraSparcInstrInfo::CreateZeroExtensionInstructions( +SparcInstrInfo::CreateZeroExtensionInstructions( const TargetMachine& target, Function* F, Value* srcVal, diff --git a/lib/Target/SparcV9/SparcV9InstrInfo.h b/lib/Target/SparcV9/SparcV9InstrInfo.h new file mode 100644 index 0000000..0926c07 --- /dev/null +++ b/lib/Target/SparcV9/SparcV9InstrInfo.h @@ -0,0 +1,201 @@ +//===-- SparcInstrInfo.h - Define TargetInstrInfo for Sparc -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class contains information about individual instructions. +// Most information is stored in the SparcMachineInstrDesc array above. +// Other information is computed on demand, and most such functions +// default to member functions in base class TargetInstrInfo. +// +//===----------------------------------------------------------------------===// + +#ifndef SPARC_INSTRINFO_H +#define SPARC_INSTRINFO_H + +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "SparcInternals.h" + +namespace llvm { + +struct SparcInstrInfo : public TargetInstrInfo { + SparcInstrInfo(); + + // All immediate constants are in position 1 except the + // store instructions and SETxx. + // + virtual int getImmedConstantPos(MachineOpCode opCode) const { + bool ignore; + if (this->maxImmedConstant(opCode, ignore) != 0) { + // 1st store opcode + assert(! this->isStore((MachineOpCode) V9::STBr - 1)); + // last store opcode + assert(! this->isStore((MachineOpCode) V9::STXFSRi + 1)); + + if (opCode == V9::SETSW || opCode == V9::SETUW || + opCode == V9::SETX || opCode == V9::SETHI) + return 0; + if (opCode >= V9::STBr && opCode <= V9::STXFSRi) + return 2; + return 1; + } + else + return -1; + } + + /// createNOPinstr - returns the target's implementation of NOP, which is + /// usually a pseudo-instruction, implemented by a degenerate version of + /// another instruction, e.g. X86: xchg ax, ax; SparcV9: sethi 0, g0 + /// + MachineInstr* createNOPinstr() const { + return BuildMI(V9::SETHI, 2).addZImm(0).addReg(SparcIntRegClass::g0); + } + + /// isNOPinstr - not having a special NOP opcode, we need to know if a given + /// instruction is interpreted as an `official' NOP instr, i.e., there may be + /// more than one way to `do nothing' but only one canonical way to slack off. + /// + bool isNOPinstr(const MachineInstr &MI) const { + // Make sure the instruction is EXACTLY `sethi g0, 0' + if (MI.getOpcode() == V9::SETHI && MI.getNumOperands() == 2) { + const MachineOperand &op0 = MI.getOperand(0), &op1 = MI.getOperand(1); + if (op0.isImmediate() && op0.getImmedValue() == 0 && + op1.isMachineRegister() && + op1.getMachineRegNum() == SparcIntRegClass::g0) + { + return true; + } + } + return false; + } + + virtual bool hasResultInterlock(MachineOpCode opCode) const + { + // All UltraSPARC instructions have interlocks (note that delay slots + // are not considered here). + // However, instructions that use the result of an FCMP produce a + // 9-cycle stall if they are issued less than 3 cycles after the FCMP. + // Force the compiler to insert a software interlock (i.e., gap of + // 2 other groups, including NOPs if necessary). + return (opCode == V9::FCMPS || opCode == V9::FCMPD || opCode == V9::FCMPQ); + } + + //------------------------------------------------------------------------- + // Queries about representation of LLVM quantities (e.g., constants) + //------------------------------------------------------------------------- + + virtual bool ConstantMayNotFitInImmedField(const Constant* CV, + const Instruction* I) const; + + //------------------------------------------------------------------------- + // Code generation support for creating individual machine instructions + //------------------------------------------------------------------------- + + // Get certain common op codes for the current target. This and all the + // Create* methods below should be moved to a machine code generation class + // + virtual MachineOpCode getNOPOpCode() const { return V9::NOP; } + + // Get the value of an integral constant in the form that must + // be put into the machine register. The specified constant is interpreted + // as (i.e., converted if necessary to) the specified destination type. The + // result is always returned as an uint64_t, since the representation of + // int64_t and uint64_t are identical. The argument can be any known const. + // + // isValidConstant is set to true if a valid constant was found. + // + virtual uint64_t ConvertConstantToIntType(const TargetMachine &target, + const Value *V, + const Type *destType, + bool &isValidConstant) const; + + // Create an instruction sequence to put the constant `val' into + // the virtual register `dest'. `val' may be a Constant or a + // GlobalValue, viz., the constant address of a global variable or function. + // The generated instructions are returned in `mvec'. + // Any temp. registers (TmpInstruction) created are recorded in mcfi. + // Any stack space required is allocated via mcff. + // + virtual void CreateCodeToLoadConst(const TargetMachine& target, + Function* F, + Value* val, + Instruction* dest, + std::vector<MachineInstr*>& mvec, + MachineCodeForInstruction& mcfi) 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 `mvec'. + // Any temp. registers (TmpInstruction) created are recorded in mcfi. + // Any stack space required is allocated via mcff. + // + virtual void CreateCodeToCopyIntToFloat(const TargetMachine& target, + Function* F, + Value* val, + Instruction* dest, + std::vector<MachineInstr*>& mvec, + MachineCodeForInstruction& mcfi) const; + + // Similarly, create an instruction sequence to copy an FP value + // `val' to an integer value `dest' by copying to memory and back. + // The generated instructions are returned in `mvec'. + // Any temp. registers (TmpInstruction) created are recorded in mcfi. + // Any stack space required is allocated via mcff. + // + virtual void CreateCodeToCopyFloatToInt(const TargetMachine& target, + Function* F, + Value* val, + Instruction* dest, + std::vector<MachineInstr*>& mvec, + MachineCodeForInstruction& mcfi) const; + + // Create instruction(s) to copy src to dest, for arbitrary types + // The generated instructions are returned in `mvec'. + // Any temp. registers (TmpInstruction) created are recorded in mcfi. + // Any stack space required is allocated via mcff. + // + virtual void CreateCopyInstructionsByType(const TargetMachine& target, + Function* F, + Value* src, + Instruction* dest, + std::vector<MachineInstr*>& mvec, + MachineCodeForInstruction& mcfi) const; + + // Create instruction sequence to produce a sign-extended register value + // from an arbitrary sized value (sized in bits, not bytes). + // The generated instructions are appended to `mvec'. + // Any temp. registers (TmpInstruction) created are recorded in mcfi. + // Any stack space required is allocated via mcff. + // + virtual void CreateSignExtensionInstructions(const TargetMachine& target, + Function* F, + Value* srcVal, + Value* destVal, + unsigned int numLowBits, + std::vector<MachineInstr*>& mvec, + MachineCodeForInstruction& mcfi) const; + + // Create instruction sequence to produce a zero-extended register value + // from an arbitrary sized value (sized in bits, not bytes). + // The generated instructions are appended to `mvec'. + // Any temp. registers (TmpInstruction) created are recorded in mcfi. + // Any stack space required is allocated via mcff. + // + virtual void CreateZeroExtensionInstructions(const TargetMachine& target, + Function* F, + Value* srcVal, + Value* destVal, + unsigned int numLowBits, + std::vector<MachineInstr*>& mvec, + MachineCodeForInstruction& mcfi) const; +}; + +} // End llvm namespace + +#endif diff --git a/lib/Target/SparcV9/SparcV9InstrSelection.cpp b/lib/Target/SparcV9/SparcV9InstrSelection.cpp index 21e884b..c5fa145 100644 --- a/lib/Target/SparcV9/SparcV9InstrSelection.cpp +++ b/lib/Target/SparcV9/SparcV9InstrSelection.cpp @@ -11,9 +11,6 @@ // //===----------------------------------------------------------------------===// -#include "SparcInstrSelectionSupport.h" -#include "SparcInternals.h" -#include "SparcRegClassInfo.h" #include "llvm/Constants.h" #include "llvm/ConstantHandling.h" #include "llvm/DerivedTypes.h" @@ -28,6 +25,10 @@ #include "llvm/CodeGen/MachineFunctionInfo.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineInstrAnnot.h" +#include "SparcInstrSelectionSupport.h" +#include "SparcInternals.h" +#include "SparcRegClassInfo.h" +#include "SparcRegInfo.h" #include "Support/MathExtras.h" #include <algorithm> #include <cmath> @@ -1583,8 +1584,8 @@ GetInstructionsByRule(InstructionNode* subtreeRoot, // -- For non-FP values, create an add-with-0 instruction // if (retVal != NULL) { - const UltraSparcRegInfo& regInfo = - (UltraSparcRegInfo&) target.getRegInfo(); + const SparcRegInfo& regInfo = + (SparcRegInfo&) target.getRegInfo(); const Type* retType = retVal->getType(); unsigned regClassID = regInfo.getRegClassIDOfType(retType); unsigned retRegNum = (retType->isFloatingPoint() @@ -2488,8 +2489,8 @@ GetInstructionsByRule(InstructionNode* subtreeRoot, MachineFunction& MF = MachineFunction::get(currentFunc); MachineCodeForInstruction& mcfi = MachineCodeForInstruction::get(callInstr); - const UltraSparcRegInfo& regInfo = - (UltraSparcRegInfo&) target.getRegInfo(); + const SparcRegInfo& regInfo = + (SparcRegInfo&) target.getRegInfo(); const TargetFrameInfo& frameInfo = target.getFrameInfo(); // Create hidden virtual register for return address with type void* diff --git a/lib/Target/SparcV9/SparcV9Internals.h b/lib/Target/SparcV9/SparcV9Internals.h index e6926bb..27dc7d0 100644 --- a/lib/Target/SparcV9/SparcV9Internals.h +++ b/lib/Target/SparcV9/SparcV9Internals.h @@ -28,7 +28,7 @@ namespace llvm { class LiveRange; -class UltraSparc; +class SparcTargetMachine; class Pass; enum SparcInstrSchedClass { @@ -71,571 +71,34 @@ namespace V9 { }; } - // Array of machine instruction descriptions... extern const TargetInstrDescriptor SparcMachineInstrDesc[]; - -//--------------------------------------------------------------------------- -// class UltraSparcInstrInfo -// -// Purpose: -// Information about individual instructions. -// Most information is stored in the SparcMachineInstrDesc array above. -// Other information is computed on demand, and most such functions -// default to member functions in base class TargetInstrInfo. -//--------------------------------------------------------------------------- - -struct UltraSparcInstrInfo : public TargetInstrInfo { - UltraSparcInstrInfo(); - - // - // All immediate constants are in position 1 except the - // store instructions and SETxx. - // - virtual int getImmedConstantPos(MachineOpCode opCode) const { - bool ignore; - if (this->maxImmedConstant(opCode, ignore) != 0) { - // 1st store opcode - assert(! this->isStore((MachineOpCode) V9::STBr - 1)); - // last store opcode - assert(! this->isStore((MachineOpCode) V9::STXFSRi + 1)); - - if (opCode == V9::SETSW || opCode == V9::SETUW || - opCode == V9::SETX || opCode == V9::SETHI) - return 0; - if (opCode >= V9::STBr && opCode <= V9::STXFSRi) - return 2; - return 1; - } - else - return -1; - } - - /// createNOPinstr - returns the target's implementation of NOP, which is - /// usually a pseudo-instruction, implemented by a degenerate version of - /// another instruction, e.g. X86: xchg ax, ax; SparcV9: sethi 0, g0 - /// - MachineInstr* createNOPinstr() const { - return BuildMI(V9::SETHI, 2).addZImm(0).addReg(SparcIntRegClass::g0); - } - - /// isNOPinstr - not having a special NOP opcode, we need to know if a given - /// instruction is interpreted as an `official' NOP instr, i.e., there may be - /// more than one way to `do nothing' but only one canonical way to slack off. - /// - bool isNOPinstr(const MachineInstr &MI) const { - // Make sure the instruction is EXACTLY `sethi g0, 0' - if (MI.getOpcode() == V9::SETHI && MI.getNumOperands() == 2) { - const MachineOperand &op0 = MI.getOperand(0), &op1 = MI.getOperand(1); - if (op0.isImmediate() && op0.getImmedValue() == 0 && - op1.isMachineRegister() && - op1.getMachineRegNum() == SparcIntRegClass::g0) - { - return true; - } - } - return false; - } - - virtual bool hasResultInterlock(MachineOpCode opCode) const - { - // All UltraSPARC instructions have interlocks (note that delay slots - // are not considered here). - // However, instructions that use the result of an FCMP produce a - // 9-cycle stall if they are issued less than 3 cycles after the FCMP. - // Force the compiler to insert a software interlock (i.e., gap of - // 2 other groups, including NOPs if necessary). - return (opCode == V9::FCMPS || opCode == V9::FCMPD || opCode == V9::FCMPQ); - } - - //------------------------------------------------------------------------- - // Queries about representation of LLVM quantities (e.g., constants) - //------------------------------------------------------------------------- - - virtual bool ConstantMayNotFitInImmedField(const Constant* CV, - const Instruction* I) const; - - //------------------------------------------------------------------------- - // Code generation support for creating individual machine instructions - //------------------------------------------------------------------------- - - // Get certain common op codes for the current target. This and all the - // Create* methods below should be moved to a machine code generation class - // - virtual MachineOpCode getNOPOpCode() const { return V9::NOP; } - - // Get the value of an integral constant in the form that must - // be put into the machine register. The specified constant is interpreted - // as (i.e., converted if necessary to) the specified destination type. The - // result is always returned as an uint64_t, since the representation of - // int64_t and uint64_t are identical. The argument can be any known const. - // - // isValidConstant is set to true if a valid constant was found. - // - virtual uint64_t ConvertConstantToIntType(const TargetMachine &target, - const Value *V, - const Type *destType, - bool &isValidConstant) const; - - // Create an instruction sequence to put the constant `val' into - // the virtual register `dest'. `val' may be a Constant or a - // GlobalValue, viz., the constant address of a global variable or function. - // The generated instructions are returned in `mvec'. - // Any temp. registers (TmpInstruction) created are recorded in mcfi. - // Any stack space required is allocated via mcff. - // - virtual void CreateCodeToLoadConst(const TargetMachine& target, - Function* F, - Value* val, - Instruction* dest, - std::vector<MachineInstr*>& mvec, - MachineCodeForInstruction& mcfi) 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 `mvec'. - // Any temp. registers (TmpInstruction) created are recorded in mcfi. - // Any stack space required is allocated via mcff. - // - virtual void CreateCodeToCopyIntToFloat(const TargetMachine& target, - Function* F, - Value* val, - Instruction* dest, - std::vector<MachineInstr*>& mvec, - MachineCodeForInstruction& mcfi) const; - - // Similarly, create an instruction sequence to copy an FP value - // `val' to an integer value `dest' by copying to memory and back. - // The generated instructions are returned in `mvec'. - // Any temp. registers (TmpInstruction) created are recorded in mcfi. - // Any stack space required is allocated via mcff. - // - virtual void CreateCodeToCopyFloatToInt(const TargetMachine& target, - Function* F, - Value* val, - Instruction* dest, - std::vector<MachineInstr*>& mvec, - MachineCodeForInstruction& mcfi) const; - - // Create instruction(s) to copy src to dest, for arbitrary types - // The generated instructions are returned in `mvec'. - // Any temp. registers (TmpInstruction) created are recorded in mcfi. - // Any stack space required is allocated via mcff. - // - virtual void CreateCopyInstructionsByType(const TargetMachine& target, - Function* F, - Value* src, - Instruction* dest, - std::vector<MachineInstr*>& mvec, - MachineCodeForInstruction& mcfi) const; - - // Create instruction sequence to produce a sign-extended register value - // from an arbitrary sized value (sized in bits, not bytes). - // The generated instructions are appended to `mvec'. - // Any temp. registers (TmpInstruction) created are recorded in mcfi. - // Any stack space required is allocated via mcff. - // - virtual void CreateSignExtensionInstructions(const TargetMachine& target, - Function* F, - Value* srcVal, - Value* destVal, - unsigned int numLowBits, - std::vector<MachineInstr*>& mvec, - MachineCodeForInstruction& mcfi) const; - - // Create instruction sequence to produce a zero-extended register value - // from an arbitrary sized value (sized in bits, not bytes). - // The generated instructions are appended to `mvec'. - // Any temp. registers (TmpInstruction) created are recorded in mcfi. - // Any stack space required is allocated via mcff. - // - virtual void CreateZeroExtensionInstructions(const TargetMachine& target, - Function* F, - Value* srcVal, - Value* destVal, - unsigned int numLowBits, - std::vector<MachineInstr*>& mvec, - MachineCodeForInstruction& mcfi) const; -}; - - -//---------------------------------------------------------------------------- -// class UltraSparcRegInfo -// -// This class implements the virtual class TargetRegInfo for Sparc. -// -//---------------------------------------------------------------------------- - -class UltraSparcRegInfo : public TargetRegInfo { - -private: - - // Number of registers used for passing int args (usually 6: %o0 - %o5) - // - unsigned const NumOfIntArgRegs; - - // Number of registers used for passing float args (usually 32: %f0 - %f31) - // - unsigned const NumOfFloatArgRegs; - - // ======================== Private Methods ============================= - - // The following methods are used to color special live ranges (e.g. - // function args and return values etc.) with specific hardware registers - // as required. See SparcRegInfo.cpp for the implementation. - // - void suggestReg4RetAddr(MachineInstr *RetMI, - LiveRangeInfo &LRI) const; - - void suggestReg4CallAddr(MachineInstr *CallMI, LiveRangeInfo &LRI) const; - - // Helper used by the all the getRegType() functions. - int getRegTypeForClassAndType(unsigned regClassID, const Type* type) const; - -public: - // Type of registers available in Sparc. There can be several reg types - // in the same class. For instace, the float reg class has Single/Double - // types - // - enum RegTypes { - IntRegType, - FPSingleRegType, - FPDoubleRegType, - IntCCRegType, - FloatCCRegType, - SpecialRegType - }; - - // The actual register classes in the Sparc - // - // **** WARNING: If this enum order is changed, also modify - // getRegisterClassOfValue method below since it assumes this particular - // order for efficiency. - // - enum RegClassIDs { - IntRegClassID, // Integer - FloatRegClassID, // Float (both single/double) - IntCCRegClassID, // Int Condition Code - FloatCCRegClassID, // Float Condition code - SpecialRegClassID // Special (unallocated) registers - }; - - UltraSparcRegInfo(const UltraSparc &tgt); - - // To find the register class used for a specified Type - // - unsigned getRegClassIDOfType(const Type *type, - bool isCCReg = false) const; - - // To find the register class to which a specified register belongs - // - unsigned getRegClassIDOfRegType(int regType) const; - - // getZeroRegNum - returns the register that contains always zero this is the - // unified register number - // - virtual int getZeroRegNum() const; - - // getCallAddressReg - returns the reg used for pushing the address when a - // function is called. This can be used for other purposes between calls - // - unsigned getCallAddressReg() const; - - // Returns the register containing the return address. - // It should be made sure that this register contains the return - // value when a return instruction is reached. - // - unsigned getReturnAddressReg() const; - - // Number of registers used for passing int args (usually 6: %o0 - %o5) - // and float args (usually 32: %f0 - %f31) - // - unsigned const getNumOfIntArgRegs() const { return NumOfIntArgRegs; } - unsigned const getNumOfFloatArgRegs() const { return NumOfFloatArgRegs; } - - // Compute which register can be used for an argument, if any - // - int regNumForIntArg(bool inCallee, bool isVarArgsCall, - unsigned argNo, unsigned& regClassId) const; - - int regNumForFPArg(unsigned RegType, bool inCallee, bool isVarArgsCall, - unsigned argNo, unsigned& regClassId) const; - - // The following methods are used to color special live ranges (e.g. - // function args and return values etc.) with specific hardware registers - // as required. See SparcRegInfo.cpp for the implementation for Sparc. - // - void suggestRegs4MethodArgs(const Function *Meth, - LiveRangeInfo& LRI) const; - - void suggestRegs4CallArgs(MachineInstr *CallMI, - LiveRangeInfo& LRI) const; - - void suggestReg4RetValue(MachineInstr *RetMI, - LiveRangeInfo& LRI) const; - - void colorMethodArgs(const Function *Meth, LiveRangeInfo& LRI, - std::vector<MachineInstr*>& InstrnsBefore, - std::vector<MachineInstr*>& InstrnsAfter) const; - - // method used for printing a register for debugging purposes - // - void printReg(const LiveRange *LR) const; - - // returns the # of bytes of stack space allocated for each register - // type. For Sparc, currently we allocate 8 bytes on stack for all - // register types. We can optimize this later if necessary to save stack - // space (However, should make sure that stack alignment is correct) - // - inline int getSpilledRegSize(int RegType) const { - return 8; - } - - - // To obtain the return value and the indirect call address (if any) - // contained in a CALL machine instruction - // - const Value * getCallInstRetVal(const MachineInstr *CallMI) const; - const Value * getCallInstIndirectAddrVal(const MachineInstr *CallMI) const; - - // The following methods are used to generate "copy" machine instructions - // for an architecture. - // - // The function regTypeNeedsScratchReg() can be used to check whether a - // scratch register is needed to copy a register of type `regType' to - // or from memory. If so, such a scratch register can be provided by - // the caller (e.g., if it knows which regsiters are free); otherwise - // an arbitrary one will be chosen and spilled by the copy instructions. - // - bool regTypeNeedsScratchReg(int RegType, - int& scratchRegClassId) const; - - void cpReg2RegMI(std::vector<MachineInstr*>& mvec, - unsigned SrcReg, unsigned DestReg, - int RegType) const; - - void cpReg2MemMI(std::vector<MachineInstr*>& mvec, - unsigned SrcReg, unsigned DestPtrReg, - int Offset, int RegType, int scratchReg = -1) const; - - void cpMem2RegMI(std::vector<MachineInstr*>& mvec, - unsigned SrcPtrReg, int Offset, unsigned DestReg, - int RegType, int scratchReg = -1) const; - - void cpValue2Value(Value *Src, Value *Dest, - std::vector<MachineInstr*>& mvec) const; - - // Get the register type for a register identified different ways. - // Note that getRegTypeForLR(LR) != getRegTypeForDataType(LR->getType())! - // The reg class of a LR depends both on the Value types in it and whether - // they are CC registers or not (for example). - int getRegTypeForDataType(const Type* type) const; - int getRegTypeForLR(const LiveRange *LR) const; - int getRegType(int unifiedRegNum) const; - - virtual unsigned getFramePointer() const; - virtual unsigned getStackPointer() const; -}; - - - - //--------------------------------------------------------------------------- -// class UltraSparcSchedInfo +// class SparcSchedInfo // // Purpose: // Interface to instruction scheduling information for UltraSPARC. // The parameter values above are based on UltraSPARC IIi. //--------------------------------------------------------------------------- - -class UltraSparcSchedInfo: public TargetSchedInfo { +class SparcSchedInfo: public TargetSchedInfo { public: - UltraSparcSchedInfo(const TargetMachine &tgt); + SparcSchedInfo(const TargetMachine &tgt); protected: virtual void initializeResources(); }; - //--------------------------------------------------------------------------- -// class UltraSparcFrameInfo -// -// Purpose: -// Interface to stack frame layout info for the UltraSPARC. -// Starting offsets for each area of the stack frame are aligned at -// a multiple of getStackFrameSizeAlignment(). -//--------------------------------------------------------------------------- - -class UltraSparcFrameInfo: public TargetFrameInfo { - const TargetMachine ⌖ -public: - UltraSparcFrameInfo(const TargetMachine &TM) - : TargetFrameInfo(StackGrowsDown, StackFrameSizeAlignment, 0), target(TM) {} - -public: - // These methods provide constant parameters of the frame layout. - // - 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; } - - // This method adjusts a stack offset to meet alignment rules of target. - // The fixed OFFSET (0x7ff) must be subtracted and the result aligned. - virtual int adjustAlignment (int unalignedOffset, - bool growUp, - unsigned int align) const { - return unalignedOffset + (growUp? +1:-1)*((unalignedOffset-OFFSET) % align); - } - - // These methods compute offsets using the frame contents for a - // particular function. The frame contents are obtained from the - // MachineCodeInfoForMethod object for the given function. - // - int getFirstIncomingArgOffset (MachineFunction& mcInfo, - bool& growUp) const - { - growUp = true; // arguments area grows upwards - return FirstIncomingArgOffsetFromFP; - } - int getFirstOutgoingArgOffset (MachineFunction& mcInfo, - bool& growUp) const - { - growUp = true; // arguments area grows upwards - return FirstOutgoingArgOffsetFromSP; - } - int getFirstOptionalOutgoingArgOffset(MachineFunction& mcInfo, - bool& growUp)const - { - growUp = true; // arguments area grows upwards - return FirstOptionalOutgoingArgOffsetFromSP; - } - - int getFirstAutomaticVarOffset (MachineFunction& mcInfo, - bool& growUp) const; - int getRegSpillAreaOffset (MachineFunction& mcInfo, - bool& growUp) const; - int getTmpAreaOffset (MachineFunction& mcInfo, - bool& growUp) const; - int getDynamicAreaOffset (MachineFunction& mcInfo, - bool& growUp) 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(); - } - - virtual int getIncomingArgOffset(MachineFunction& mcInfo, - unsigned argNum) const { - assert(argsOnStackHaveFixedSize()); - - unsigned relativeOffset = argNum * getSizeOfEachArgOnStack(); - bool growUp; // do args grow up or down - int firstArg = getFirstIncomingArgOffset(mcInfo, growUp); - return growUp ? firstArg + relativeOffset : firstArg - relativeOffset; - } - - virtual int getOutgoingArgOffset(MachineFunction& mcInfo, - unsigned argNum) const { - assert(argsOnStackHaveFixedSize()); - //assert(((int) argNum - this->getNumFixedOutgoingArgs()) - // <= (int) mcInfo.getInfo()->getMaxOptionalNumArgs()); - - unsigned relativeOffset = argNum * getSizeOfEachArgOnStack(); - bool growUp; // do args grow up or down - int firstArg = getFirstOutgoingArgOffset(mcInfo, growUp); - return growUp ? firstArg + relativeOffset : firstArg - relativeOffset; - } - -private: - /*---------------------------------------------------------------------- - This diagram shows the stack frame layout used by llc on Sparc V9. - Note that only the location of automatic variables, spill area, - temporary storage, and dynamically allocated stack area are chosen - by us. The rest conform to the Sparc V9 ABI. - All stack addresses are offset by OFFSET = 0x7ff (2047). - - Alignment assumptions and other invariants: - (1) %sp+OFFSET and %fp+OFFSET are always aligned on 16-byte boundary - (2) Variables in automatic, spill, temporary, or dynamic regions - are aligned according to their size as in all memory accesses. - (3) Everything below the dynamically allocated stack area is only used - during a call to another function, so it is never needed when - the current function is active. This is why space can be allocated - dynamically by incrementing %sp any time within the function. - - STACK FRAME LAYOUT: - - ... - %fp+OFFSET+176 Optional extra incoming arguments# 1..N - %fp+OFFSET+168 Incoming argument #6 - ... ... - %fp+OFFSET+128 Incoming argument #1 - ... ... - ---%fp+OFFSET-0--------Bottom of caller's stack frame-------------------- - %fp+OFFSET-8 Automatic variables <-- ****TOP OF STACK FRAME**** - Spill area - Temporary storage - ... - - %sp+OFFSET+176+8N Bottom of dynamically allocated stack area - %sp+OFFSET+168+8N Optional extra outgoing argument# N - ... ... - %sp+OFFSET+176 Optional extra outgoing argument# 1 - %sp+OFFSET+168 Outgoing argument #6 - ... ... - %sp+OFFSET+128 Outgoing argument #1 - %sp+OFFSET+120 Save area for %i7 - ... ... - %sp+OFFSET+0 Save area for %l0 <-- ****BOTTOM OF STACK FRAME**** - - *----------------------------------------------------------------------*/ - - // 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 FirstIncomingArgOffsetFromFP = 128 + OFFSET; - static const int FirstOptionalIncomingArgOffsetFromFP = 176 + OFFSET; - static const int StaticAreaOffsetFromFP = 0 + OFFSET; - static const int FirstOutgoingArgOffsetFromSP = 128 + OFFSET; - static const int FirstOptionalOutgoingArgOffsetFromSP = 176 + OFFSET; -}; - - -//--------------------------------------------------------------------------- -// class UltraSparcCacheInfo +// class SparcCacheInfo // // Purpose: // Interface to cache parameters for the UltraSPARC. // Just use defaults for now. //--------------------------------------------------------------------------- -struct UltraSparcCacheInfo: public TargetCacheInfo { - UltraSparcCacheInfo(const TargetMachine &T) : TargetCacheInfo(T) {} +struct SparcCacheInfo: public TargetCacheInfo { + SparcCacheInfo(const TargetMachine &T) : TargetCacheInfo(T) {} }; @@ -664,38 +127,6 @@ FunctionPass* createPrologEpilogInsertionPass(); /// Pass* createBytecodeAsmPrinterPass(std::ostream &Out); -//--------------------------------------------------------------------------- -// class UltraSparc -// -// Purpose: -// Primary interface to machine description for the UltraSPARC. -// Primarily just initializes machine-dependent parameters in -// class TargetMachine, and creates machine-dependent subclasses -// for classes such as InstrInfo, SchedInfo and RegInfo. -//--------------------------------------------------------------------------- - -class UltraSparc : public TargetMachine { - UltraSparcInstrInfo instrInfo; - UltraSparcSchedInfo schedInfo; - UltraSparcRegInfo regInfo; - UltraSparcFrameInfo frameInfo; - UltraSparcCacheInfo cacheInfo; -public: - UltraSparc(); - - virtual const TargetInstrInfo &getInstrInfo() const { return instrInfo; } - virtual const TargetSchedInfo &getSchedInfo() const { return schedInfo; } - virtual const TargetRegInfo &getRegInfo() const { return regInfo; } - virtual const TargetFrameInfo &getFrameInfo() const { return frameInfo; } - virtual const TargetCacheInfo &getCacheInfo() const { return cacheInfo; } - - virtual bool addPassesToEmitAssembly(PassManager &PM, std::ostream &Out); - virtual bool addPassesToJITCompile(FunctionPassManager &PM); - virtual bool addPassesToEmitMachineCode(FunctionPassManager &PM, - MachineCodeEmitter &MCE); - virtual void replaceMachineCodeForFunction(void *Old, void *New); -}; - } // End llvm namespace #endif diff --git a/lib/Target/SparcV9/SparcV9RegClassInfo.cpp b/lib/Target/SparcV9/SparcV9RegClassInfo.cpp index 564e59c..c6d559a 100644 --- a/lib/Target/SparcV9/SparcV9RegClassInfo.cpp +++ b/lib/Target/SparcV9/SparcV9RegClassInfo.cpp @@ -11,9 +11,10 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Type.h" #include "SparcRegClassInfo.h" #include "SparcInternals.h" -#include "llvm/Type.h" +#include "SparcRegInfo.h" #include "../../CodeGen/RegAlloc/RegAllocCommon.h" // FIXME! #include "../../CodeGen/RegAlloc/IGNode.h" // FIXME! @@ -320,8 +321,8 @@ void SparcFloatRegClass::markColorsUsed(unsigned RegInClass, int RegTypeWanted, std::vector<bool> &IsColorUsedArr) const { - if (UserRegType == UltraSparcRegInfo::FPDoubleRegType || - RegTypeWanted == UltraSparcRegInfo::FPDoubleRegType) { + if (UserRegType == SparcRegInfo::FPDoubleRegType || + RegTypeWanted == SparcRegInfo::FPDoubleRegType) { // This register is used as or is needed as a double-precision reg. // We need to mark the [even,odd] pair corresponding to this reg. // Get the even numbered register corresponding to this reg. @@ -348,7 +349,7 @@ void SparcFloatRegClass::markColorsUsed(unsigned RegInClass, int SparcFloatRegClass::findUnusedColor(int RegTypeWanted, const std::vector<bool> &IsColorUsedArr) const { - if (RegTypeWanted == UltraSparcRegInfo::FPDoubleRegType) { + if (RegTypeWanted == SparcRegInfo::FPDoubleRegType) { unsigned NC = 2 * this->getNumOfAvailRegs(); assert(IsColorUsedArr.size() == NC && "Invalid colors-used array"); for (unsigned c = 0; c < NC; c+=2) diff --git a/lib/Target/SparcV9/SparcV9RegInfo.cpp b/lib/Target/SparcV9/SparcV9RegInfo.cpp index 5edbbe0..1d742ef 100644 --- a/lib/Target/SparcV9/SparcV9RegInfo.cpp +++ b/lib/Target/SparcV9/SparcV9RegInfo.cpp @@ -12,8 +12,6 @@ // //===----------------------------------------------------------------------===// -#include "SparcInternals.h" -#include "SparcRegClassInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunctionInfo.h" #include "llvm/CodeGen/InstrSelection.h" @@ -22,10 +20,14 @@ #include "llvm/CodeGen/MachineInstrAnnot.h" #include "../../CodeGen/RegAlloc/LiveRangeInfo.h" // FIXME!! #include "../../CodeGen/RegAlloc/LiveRange.h" // FIXME!! +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" #include "llvm/iTerminators.h" #include "llvm/iOther.h" -#include "llvm/Function.h" -#include "llvm/DerivedTypes.h" +#include "SparcInternals.h" +#include "SparcRegClassInfo.h" +#include "SparcRegInfo.h" +#include "SparcTargetMachine.h" namespace llvm { @@ -33,7 +35,7 @@ enum { BadRegClass = ~0 }; -UltraSparcRegInfo::UltraSparcRegInfo(const UltraSparc &tgt) +SparcRegInfo::SparcRegInfo(const SparcTargetMachine &tgt) : TargetRegInfo(tgt), NumOfIntArgRegs(6), NumOfFloatArgRegs(32) { MachineRegClassArr.push_back(new SparcIntRegClass(IntRegClassID)); @@ -50,16 +52,16 @@ UltraSparcRegInfo::UltraSparcRegInfo(const UltraSparc &tgt) // getZeroRegNum - returns the register that contains always zero. // this is the unified register number // -int UltraSparcRegInfo::getZeroRegNum() const { - return getUnifiedRegNum(UltraSparcRegInfo::IntRegClassID, +int SparcRegInfo::getZeroRegNum() const { + return getUnifiedRegNum(SparcRegInfo::IntRegClassID, SparcIntRegClass::g0); } // getCallAddressReg - returns the reg used for pushing the address when a // method is called. This can be used for other purposes between calls // -unsigned UltraSparcRegInfo::getCallAddressReg() const { - return getUnifiedRegNum(UltraSparcRegInfo::IntRegClassID, +unsigned SparcRegInfo::getCallAddressReg() const { + return getUnifiedRegNum(SparcRegInfo::IntRegClassID, SparcIntRegClass::o7); } @@ -67,8 +69,8 @@ unsigned UltraSparcRegInfo::getCallAddressReg() const { // It should be made sure that this register contains the return // value when a return instruction is reached. // -unsigned UltraSparcRegInfo::getReturnAddressReg() const { - return getUnifiedRegNum(UltraSparcRegInfo::IntRegClassID, +unsigned SparcRegInfo::getReturnAddressReg() const { + return getUnifiedRegNum(SparcRegInfo::IntRegClassID, SparcIntRegClass::i7); } @@ -133,14 +135,14 @@ const char * const SparcSpecialRegClass::getRegName(unsigned reg) const { } // Get unified reg number for frame pointer -unsigned UltraSparcRegInfo::getFramePointer() const { - return getUnifiedRegNum(UltraSparcRegInfo::IntRegClassID, +unsigned SparcRegInfo::getFramePointer() const { + return getUnifiedRegNum(SparcRegInfo::IntRegClassID, SparcIntRegClass::i6); } // Get unified reg number for stack pointer -unsigned UltraSparcRegInfo::getStackPointer() const { - return getUnifiedRegNum(UltraSparcRegInfo::IntRegClassID, +unsigned SparcRegInfo::getStackPointer() const { + return getUnifiedRegNum(SparcRegInfo::IntRegClassID, SparcIntRegClass::o6); } @@ -173,7 +175,7 @@ isVarArgsCall(const MachineInstr *CallMI) { // regClassId is set to the register class ID. // int -UltraSparcRegInfo::regNumForIntArg(bool inCallee, bool isVarArgsCall, +SparcRegInfo::regNumForIntArg(bool inCallee, bool isVarArgsCall, unsigned argNo, unsigned& regClassId) const { regClassId = IntRegClassID; @@ -192,7 +194,7 @@ UltraSparcRegInfo::regNumForIntArg(bool inCallee, bool isVarArgsCall, // regClassId is set to the register class ID. // int -UltraSparcRegInfo::regNumForFPArg(unsigned regType, +SparcRegInfo::regNumForFPArg(unsigned regType, bool inCallee, bool isVarArgsCall, unsigned argNo, unsigned& regClassId) const { @@ -221,7 +223,7 @@ UltraSparcRegInfo::regNumForFPArg(unsigned regType, // The following 4 methods are used to find the RegType (SparcInternals.h) // of a LiveRange, a Value, and for a given register unified reg number. // -int UltraSparcRegInfo::getRegTypeForClassAndType(unsigned regClassID, +int SparcRegInfo::getRegTypeForClassAndType(unsigned regClassID, const Type* type) const { switch (regClassID) { @@ -237,17 +239,17 @@ int UltraSparcRegInfo::getRegTypeForClassAndType(unsigned regClassID, } } -int UltraSparcRegInfo::getRegTypeForDataType(const Type* type) const +int SparcRegInfo::getRegTypeForDataType(const Type* type) const { return getRegTypeForClassAndType(getRegClassIDOfType(type), type); } -int UltraSparcRegInfo::getRegTypeForLR(const LiveRange *LR) const +int SparcRegInfo::getRegTypeForLR(const LiveRange *LR) const { return getRegTypeForClassAndType(LR->getRegClassID(), LR->getType()); } -int UltraSparcRegInfo::getRegType(int unifiedRegNum) const +int SparcRegInfo::getRegType(int unifiedRegNum) const { if (unifiedRegNum < 32) return IntRegType; @@ -267,7 +269,7 @@ int UltraSparcRegInfo::getRegType(int unifiedRegNum) const // To find the register class used for a specified Type // -unsigned UltraSparcRegInfo::getRegClassIDOfType(const Type *type, +unsigned SparcRegInfo::getRegClassIDOfType(const Type *type, bool isCCReg) const { Type::PrimitiveID ty = type->getPrimitiveID(); unsigned res; @@ -290,7 +292,7 @@ unsigned UltraSparcRegInfo::getRegClassIDOfType(const Type *type, return res; } -unsigned UltraSparcRegInfo::getRegClassIDOfRegType(int regType) const { +unsigned SparcRegInfo::getRegClassIDOfRegType(int regType) const { switch(regType) { case IntRegType: return IntRegClassID; case FPSingleRegType: @@ -307,7 +309,7 @@ unsigned UltraSparcRegInfo::getRegClassIDOfRegType(int regType) const { // Suggests a register for the ret address in the RET machine instruction. // We always suggest %i7 by convention. //--------------------------------------------------------------------------- -void UltraSparcRegInfo::suggestReg4RetAddr(MachineInstr *RetMI, +void SparcRegInfo::suggestReg4RetAddr(MachineInstr *RetMI, LiveRangeInfo& LRI) const { assert(target.getInstrInfo().isReturn(RetMI->getOpCode())); @@ -336,7 +338,7 @@ void UltraSparcRegInfo::suggestReg4RetAddr(MachineInstr *RetMI, // Sparc ABI dictates that %o7 be used for this purpose. //--------------------------------------------------------------------------- void -UltraSparcRegInfo::suggestReg4CallAddr(MachineInstr * CallMI, +SparcRegInfo::suggestReg4CallAddr(MachineInstr * CallMI, LiveRangeInfo& LRI) const { CallArgsDescriptor* argDesc = CallArgsDescriptor::get(CallMI); @@ -360,7 +362,7 @@ UltraSparcRegInfo::suggestReg4CallAddr(MachineInstr * CallMI, // If the arg is passed on stack due to the lack of regs, NOTHING will be // done - it will be colored (or spilled) as a normal live range. //--------------------------------------------------------------------------- -void UltraSparcRegInfo::suggestRegs4MethodArgs(const Function *Meth, +void SparcRegInfo::suggestRegs4MethodArgs(const Function *Meth, LiveRangeInfo& LRI) const { // Check if this is a varArgs function. needed for choosing regs. @@ -393,7 +395,7 @@ void UltraSparcRegInfo::suggestRegs4MethodArgs(const Function *Meth, // the correct hardware registers if they did not receive the correct // (suggested) color through graph coloring. //--------------------------------------------------------------------------- -void UltraSparcRegInfo::colorMethodArgs(const Function *Meth, +void SparcRegInfo::colorMethodArgs(const Function *Meth, LiveRangeInfo &LRI, std::vector<MachineInstr*>& InstrnsBefore, std::vector<MachineInstr*>& InstrnsAfter) const { @@ -566,7 +568,7 @@ void UltraSparcRegInfo::colorMethodArgs(const Function *Meth, // This method is called before graph coloring to suggest colors to the // outgoing call args and the return value of the call. //--------------------------------------------------------------------------- -void UltraSparcRegInfo::suggestRegs4CallArgs(MachineInstr *CallMI, +void SparcRegInfo::suggestRegs4CallArgs(MachineInstr *CallMI, LiveRangeInfo& LRI) const { assert ( (target.getInstrInfo()).isCall(CallMI->getOpCode()) ); @@ -634,7 +636,7 @@ void UltraSparcRegInfo::suggestRegs4CallArgs(MachineInstr *CallMI, // this method is called for an LLVM return instruction to identify which // values will be returned from this method and to suggest colors. //--------------------------------------------------------------------------- -void UltraSparcRegInfo::suggestReg4RetValue(MachineInstr *RetMI, +void SparcRegInfo::suggestReg4RetValue(MachineInstr *RetMI, LiveRangeInfo& LRI) const { assert( (target.getInstrInfo()).isReturn( RetMI->getOpCode() ) ); @@ -662,7 +664,7 @@ void UltraSparcRegInfo::suggestReg4RetValue(MachineInstr *RetMI, //--------------------------------------------------------------------------- bool -UltraSparcRegInfo::regTypeNeedsScratchReg(int RegType, +SparcRegInfo::regTypeNeedsScratchReg(int RegType, int& scratchRegType) const { if (RegType == IntCCRegType) @@ -679,7 +681,7 @@ UltraSparcRegInfo::regTypeNeedsScratchReg(int RegType, //--------------------------------------------------------------------------- void -UltraSparcRegInfo::cpReg2RegMI(std::vector<MachineInstr*>& mvec, +SparcRegInfo::cpReg2RegMI(std::vector<MachineInstr*>& mvec, unsigned SrcReg, unsigned DestReg, int RegType) const { @@ -695,7 +697,7 @@ UltraSparcRegInfo::cpReg2RegMI(std::vector<MachineInstr*>& mvec, if (getRegType(DestReg) == IntRegType) { // copy intCC reg to int reg MI = (BuildMI(V9::RDCCR, 2) - .addMReg(getUnifiedRegNum(UltraSparcRegInfo::IntCCRegClassID, + .addMReg(getUnifiedRegNum(SparcRegInfo::IntCCRegClassID, SparcIntCCRegClass::ccr)) .addMReg(DestReg,MOTy::Def)); } else { @@ -705,7 +707,7 @@ UltraSparcRegInfo::cpReg2RegMI(std::vector<MachineInstr*>& mvec, MI = (BuildMI(V9::WRCCRr, 3) .addMReg(SrcReg) .addMReg(SparcIntRegClass::g0) - .addMReg(getUnifiedRegNum(UltraSparcRegInfo::IntCCRegClassID, + .addMReg(getUnifiedRegNum(SparcRegInfo::IntCCRegClassID, SparcIntCCRegClass::ccr), MOTy::Def)); } break; @@ -743,7 +745,7 @@ UltraSparcRegInfo::cpReg2RegMI(std::vector<MachineInstr*>& mvec, void -UltraSparcRegInfo::cpReg2MemMI(std::vector<MachineInstr*>& mvec, +SparcRegInfo::cpReg2MemMI(std::vector<MachineInstr*>& mvec, unsigned SrcReg, unsigned PtrReg, int Offset, int RegType, @@ -763,7 +765,7 @@ UltraSparcRegInfo::cpReg2MemMI(std::vector<MachineInstr*>& mvec, OffReg = PRA.getUnusedUniRegAtMI(RC, RegType, MInst, LVSetBef); #else // Default to using register g4 for holding large offsets - OffReg = getUnifiedRegNum(UltraSparcRegInfo::IntRegClassID, + OffReg = getUnifiedRegNum(SparcRegInfo::IntRegClassID, SparcIntRegClass::g4); #endif assert(OffReg >= 0 && "FIXME: cpReg2MemMI cannot find an unused reg."); @@ -796,7 +798,7 @@ UltraSparcRegInfo::cpReg2MemMI(std::vector<MachineInstr*>& mvec, assert(scratchReg >= 0 && "Need scratch reg to store %ccr to memory"); assert(getRegType(scratchReg) ==IntRegType && "Invalid scratch reg"); MI = (BuildMI(V9::RDCCR, 2) - .addMReg(getUnifiedRegNum(UltraSparcRegInfo::IntCCRegClassID, + .addMReg(getUnifiedRegNum(SparcRegInfo::IntCCRegClassID, SparcIntCCRegClass::ccr)) .addMReg(scratchReg, MOTy::Def)); mvec.push_back(MI); @@ -805,7 +807,7 @@ UltraSparcRegInfo::cpReg2MemMI(std::vector<MachineInstr*>& mvec, return; case FloatCCRegType: { - unsigned fsrReg = getUnifiedRegNum(UltraSparcRegInfo::SpecialRegClassID, + unsigned fsrReg = getUnifiedRegNum(SparcRegInfo::SpecialRegClassID, SparcSpecialRegClass::fsr); if (target.getInstrInfo().constantFitsInImmedField(V9::STXFSRi, Offset)) MI=BuildMI(V9::STXFSRi,3).addMReg(fsrReg).addMReg(PtrReg).addSImm(Offset); @@ -827,7 +829,7 @@ UltraSparcRegInfo::cpReg2MemMI(std::vector<MachineInstr*>& mvec, void -UltraSparcRegInfo::cpMem2RegMI(std::vector<MachineInstr*>& mvec, +SparcRegInfo::cpMem2RegMI(std::vector<MachineInstr*>& mvec, unsigned PtrReg, int Offset, unsigned DestReg, @@ -848,7 +850,7 @@ UltraSparcRegInfo::cpMem2RegMI(std::vector<MachineInstr*>& mvec, OffReg = PRA.getUnusedUniRegAtMI(RC, RegType, MInst, LVSetBef); #else // Default to using register g4 for holding large offsets - OffReg = getUnifiedRegNum(UltraSparcRegInfo::IntRegClassID, + OffReg = getUnifiedRegNum(SparcRegInfo::IntRegClassID, SparcIntRegClass::g4); #endif assert(OffReg >= 0 && "FIXME: cpReg2MemMI cannot find an unused reg."); @@ -890,12 +892,12 @@ UltraSparcRegInfo::cpMem2RegMI(std::vector<MachineInstr*>& mvec, MI = (BuildMI(V9::WRCCRr, 3) .addMReg(scratchReg) .addMReg(SparcIntRegClass::g0) - .addMReg(getUnifiedRegNum(UltraSparcRegInfo::IntCCRegClassID, + .addMReg(getUnifiedRegNum(SparcRegInfo::IntCCRegClassID, SparcIntCCRegClass::ccr), MOTy::Def)); break; case FloatCCRegType: { - unsigned fsrRegNum = getUnifiedRegNum(UltraSparcRegInfo::SpecialRegClassID, + unsigned fsrRegNum = getUnifiedRegNum(SparcRegInfo::SpecialRegClassID, SparcSpecialRegClass::fsr); if (target.getInstrInfo().constantFitsInImmedField(V9::LDXFSRi, Offset)) MI = BuildMI(V9::LDXFSRi, 3).addMReg(PtrReg).addSImm(Offset) @@ -919,7 +921,7 @@ UltraSparcRegInfo::cpMem2RegMI(std::vector<MachineInstr*>& mvec, void -UltraSparcRegInfo::cpValue2Value(Value *Src, Value *Dest, +SparcRegInfo::cpValue2Value(Value *Src, Value *Dest, std::vector<MachineInstr*>& mvec) const { int RegType = getRegTypeForDataType(Src->getType()); MachineInstr * MI = NULL; @@ -948,7 +950,7 @@ UltraSparcRegInfo::cpValue2Value(Value *Src, Value *Dest, // Print the register assigned to a LR //--------------------------------------------------------------------------- -void UltraSparcRegInfo::printReg(const LiveRange *LR) const { +void SparcRegInfo::printReg(const LiveRange *LR) const { unsigned RegClassID = LR->getRegClassID(); std::cerr << " Node "; diff --git a/lib/Target/SparcV9/SparcV9RegInfo.h b/lib/Target/SparcV9/SparcV9RegInfo.h new file mode 100644 index 0000000..68d0ad8 --- /dev/null +++ b/lib/Target/SparcV9/SparcV9RegInfo.h @@ -0,0 +1,190 @@ +//===-- SparcRegInfo.h - Define TargetRegInfo for Sparc ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class implements the virtual class TargetRegInfo for Sparc. +// +//---------------------------------------------------------------------------- + +#ifndef SPARC_REGINFO_H +#define SPARC_REGINFO_H + +namespace llvm { + +class SparcRegInfo : public TargetRegInfo { + +private: + + // Number of registers used for passing int args (usually 6: %o0 - %o5) + // + unsigned const NumOfIntArgRegs; + + // Number of registers used for passing float args (usually 32: %f0 - %f31) + // + unsigned const NumOfFloatArgRegs; + + // The following methods are used to color special live ranges (e.g. + // function args and return values etc.) with specific hardware registers + // as required. See SparcRegInfo.cpp for the implementation. + // + void suggestReg4RetAddr(MachineInstr *RetMI, + LiveRangeInfo &LRI) const; + + void suggestReg4CallAddr(MachineInstr *CallMI, LiveRangeInfo &LRI) const; + + // Helper used by the all the getRegType() functions. + int getRegTypeForClassAndType(unsigned regClassID, const Type* type) const; + +public: + // Type of registers available in Sparc. There can be several reg types + // in the same class. For instace, the float reg class has Single/Double + // types + // + enum RegTypes { + IntRegType, + FPSingleRegType, + FPDoubleRegType, + IntCCRegType, + FloatCCRegType, + SpecialRegType + }; + + // The actual register classes in the Sparc + // + // **** WARNING: If this enum order is changed, also modify + // getRegisterClassOfValue method below since it assumes this particular + // order for efficiency. + // + enum RegClassIDs { + IntRegClassID, // Integer + FloatRegClassID, // Float (both single/double) + IntCCRegClassID, // Int Condition Code + FloatCCRegClassID, // Float Condition code + SpecialRegClassID // Special (unallocated) registers + }; + + SparcRegInfo(const SparcTargetMachine &tgt); + + // To find the register class used for a specified Type + // + unsigned getRegClassIDOfType(const Type *type, + bool isCCReg = false) const; + + // To find the register class to which a specified register belongs + // + unsigned getRegClassIDOfRegType(int regType) const; + + // getZeroRegNum - returns the register that contains always zero this is the + // unified register number + // + virtual int getZeroRegNum() const; + + // getCallAddressReg - returns the reg used for pushing the address when a + // function is called. This can be used for other purposes between calls + // + unsigned getCallAddressReg() const; + + // Returns the register containing the return address. + // It should be made sure that this register contains the return + // value when a return instruction is reached. + // + unsigned getReturnAddressReg() const; + + // Number of registers used for passing int args (usually 6: %o0 - %o5) + // and float args (usually 32: %f0 - %f31) + // + unsigned const getNumOfIntArgRegs() const { return NumOfIntArgRegs; } + unsigned const getNumOfFloatArgRegs() const { return NumOfFloatArgRegs; } + + // Compute which register can be used for an argument, if any + // + int regNumForIntArg(bool inCallee, bool isVarArgsCall, + unsigned argNo, unsigned& regClassId) const; + + int regNumForFPArg(unsigned RegType, bool inCallee, bool isVarArgsCall, + unsigned argNo, unsigned& regClassId) const; + + // The following methods are used to color special live ranges (e.g. + // function args and return values etc.) with specific hardware registers + // as required. See SparcRegInfo.cpp for the implementation for Sparc. + // + void suggestRegs4MethodArgs(const Function *Meth, + LiveRangeInfo& LRI) const; + + void suggestRegs4CallArgs(MachineInstr *CallMI, + LiveRangeInfo& LRI) const; + + void suggestReg4RetValue(MachineInstr *RetMI, + LiveRangeInfo& LRI) const; + + void colorMethodArgs(const Function *Meth, LiveRangeInfo& LRI, + std::vector<MachineInstr*>& InstrnsBefore, + std::vector<MachineInstr*>& InstrnsAfter) const; + + // method used for printing a register for debugging purposes + // + void printReg(const LiveRange *LR) const; + + // returns the # of bytes of stack space allocated for each register + // type. For Sparc, currently we allocate 8 bytes on stack for all + // register types. We can optimize this later if necessary to save stack + // space (However, should make sure that stack alignment is correct) + // + inline int getSpilledRegSize(int RegType) const { + return 8; + } + + + // To obtain the return value and the indirect call address (if any) + // contained in a CALL machine instruction + // + const Value * getCallInstRetVal(const MachineInstr *CallMI) const; + const Value * getCallInstIndirectAddrVal(const MachineInstr *CallMI) const; + + // The following methods are used to generate "copy" machine instructions + // for an architecture. + // + // The function regTypeNeedsScratchReg() can be used to check whether a + // scratch register is needed to copy a register of type `regType' to + // or from memory. If so, such a scratch register can be provided by + // the caller (e.g., if it knows which regsiters are free); otherwise + // an arbitrary one will be chosen and spilled by the copy instructions. + // + bool regTypeNeedsScratchReg(int RegType, + int& scratchRegClassId) const; + + void cpReg2RegMI(std::vector<MachineInstr*>& mvec, + unsigned SrcReg, unsigned DestReg, + int RegType) const; + + void cpReg2MemMI(std::vector<MachineInstr*>& mvec, + unsigned SrcReg, unsigned DestPtrReg, + int Offset, int RegType, int scratchReg = -1) const; + + void cpMem2RegMI(std::vector<MachineInstr*>& mvec, + unsigned SrcPtrReg, int Offset, unsigned DestReg, + int RegType, int scratchReg = -1) const; + + void cpValue2Value(Value *Src, Value *Dest, + std::vector<MachineInstr*>& mvec) const; + + // Get the register type for a register identified different ways. + // Note that getRegTypeForLR(LR) != getRegTypeForDataType(LR->getType())! + // The reg class of a LR depends both on the Value types in it and whether + // they are CC registers or not (for example). + int getRegTypeForDataType(const Type* type) const; + int getRegTypeForLR(const LiveRange *LR) const; + int getRegType(int unifiedRegNum) const; + + virtual unsigned getFramePointer() const; + virtual unsigned getStackPointer() const; +}; + +} // End llvm namespace + +#endif diff --git a/lib/Target/SparcV9/SparcV9SchedInfo.cpp b/lib/Target/SparcV9/SparcV9SchedInfo.cpp index 7d8ea05..0165874 100644 --- a/lib/Target/SparcV9/SparcV9SchedInfo.cpp +++ b/lib/Target/SparcV9/SparcV9SchedInfo.cpp @@ -728,7 +728,7 @@ static const InstrRUsageDelta SparcInstrUsageDeltas[] = { //--------------------------------------------------------------------------- -// class UltraSparcSchedInfo +// class SparcSchedInfo // // Purpose: // Scheduling information for the UltraSPARC. @@ -737,7 +737,7 @@ static const InstrRUsageDelta SparcInstrUsageDeltas[] = { //--------------------------------------------------------------------------- /*ctor*/ -UltraSparcSchedInfo::UltraSparcSchedInfo(const TargetMachine& tgt) +SparcSchedInfo::SparcSchedInfo(const TargetMachine& tgt) : TargetSchedInfo(tgt, (unsigned int) SPARC_NUM_SCHED_CLASSES, SparcRUsageDesc, @@ -764,7 +764,7 @@ UltraSparcSchedInfo::UltraSparcSchedInfo(const TargetMachine& tgt) } void -UltraSparcSchedInfo::initializeResources() +SparcSchedInfo::initializeResources() { // Compute TargetSchedInfo::instrRUsages and TargetSchedInfo::issueGaps TargetSchedInfo::initializeResources(); diff --git a/lib/Target/SparcV9/SparcV9TargetMachine.cpp b/lib/Target/SparcV9/SparcV9TargetMachine.cpp index 1502dfc..5bbed40 100644 --- a/lib/Target/SparcV9/SparcV9TargetMachine.cpp +++ b/lib/Target/SparcV9/SparcV9TargetMachine.cpp @@ -6,27 +6,31 @@ // the University of Illinois Open Source License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file contains the code for the Sparc Target that does not fit in any of -// the other files in this directory. -// +// +// Primary interface to machine description for the UltraSPARC. Primarily just +// initializes machine-dependent parameters in class TargetMachine, and creates +// machine-dependent subclasses for classes such as TargetInstrInfo. +// //===----------------------------------------------------------------------===// -#include "SparcInternals.h" -#include "MappingInfo.h" #include "llvm/Function.h" #include "llvm/PassManager.h" #include "llvm/Assembly/PrintModulePass.h" -#include "llvm/Transforms/Scalar.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineFunctionInfo.h" #include "llvm/CodeGen/InstrSelection.h" #include "llvm/CodeGen/InstrScheduling.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFunctionInfo.h" #include "llvm/CodeGen/MachineCodeForInstruction.h" #include "llvm/CodeGen/Passes.h" #include "llvm/Target/TargetMachineImpls.h" +#include "llvm/Transforms/Scalar.h" +#include "MappingInfo.h" +#include "SparcInternals.h" +#include "SparcTargetMachine.h" #include "Support/CommandLine.h" +using namespace llvm; + namespace llvm { static const unsigned ImplicitRegUseList[] = { 0 }; /* not used yet */ @@ -62,87 +66,9 @@ namespace { cl::Hidden); } -//---------------------------------------------------------------------------- -// allocateSparcTargetMachine - Allocate and return a subclass of TargetMachine -// that implements the Sparc backend. (the llvm/CodeGen/Sparc.h interface) -//---------------------------------------------------------------------------- - -TargetMachine *allocateSparcTargetMachine(const Module &M) { - return new UltraSparc(); -} - -//--------------------------------------------------------------------------- -// class UltraSparcFrameInfo -// -// Interface to stack frame layout info for the UltraSPARC. -// Starting offsets for each area of the stack frame are aligned at -// a multiple of getStackFrameSizeAlignment(). -//--------------------------------------------------------------------------- - -int -UltraSparcFrameInfo::getFirstAutomaticVarOffset(MachineFunction& , - bool& pos) const -{ - pos = false; // static stack area grows downwards - return StaticAreaOffsetFromFP; -} - -int -UltraSparcFrameInfo::getRegSpillAreaOffset(MachineFunction& mcInfo, - bool& pos) const -{ - // ensure no more auto vars are added - mcInfo.getInfo()->freezeAutomaticVarsArea(); - - pos = false; // static stack area grows downwards - unsigned autoVarsSize = mcInfo.getInfo()->getAutomaticVarsSize(); - return StaticAreaOffsetFromFP - autoVarsSize; -} - -int -UltraSparcFrameInfo::getTmpAreaOffset(MachineFunction& mcInfo, - bool& pos) const -{ - MachineFunctionInfo *MFI = mcInfo.getInfo(); - MFI->freezeAutomaticVarsArea(); // ensure no more auto vars are added - MFI->freezeSpillsArea(); // ensure no more spill slots are added - - pos = false; // static stack area grows downwards - unsigned autoVarsSize = MFI->getAutomaticVarsSize(); - unsigned spillAreaSize = MFI->getRegSpillsSize(); - int offset = autoVarsSize + spillAreaSize; - return StaticAreaOffsetFromFP - offset; -} - -int -UltraSparcFrameInfo::getDynamicAreaOffset(MachineFunction& mcInfo, - bool& pos) const -{ - // Dynamic stack area grows downwards starting at top of opt-args area. - // The opt-args, required-args, and register-save areas are empty except - // during calls and traps, so they are shifted downwards on each - // dynamic-size alloca. - pos = false; - unsigned optArgsSize = mcInfo.getInfo()->getMaxOptionalArgsSize(); - if (int extra = optArgsSize % getStackFrameSizeAlignment()) - optArgsSize += (getStackFrameSizeAlignment() - extra); - int offset = optArgsSize + FirstOptionalOutgoingArgOffsetFromSP; - assert((offset - OFFSET) % getStackFrameSizeAlignment() == 0); - return offset; -} - -//--------------------------------------------------------------------------- -// class UltraSparcMachine -// -// Purpose: -// Primary interface to machine description for the UltraSPARC. -// Primarily just initializes machine-dependent parameters in -// class TargetMachine, and creates machine-dependent subclasses -// for classes such as TargetInstrInfo. -// -//--------------------------------------------------------------------------- +} // End llvm namespace -UltraSparc::UltraSparc() +SparcTargetMachine::SparcTargetMachine() : TargetMachine("UltraSparc-Native", false), schedInfo(*this), regInfo(*this), @@ -153,7 +79,8 @@ UltraSparc::UltraSparc() // addPassesToEmitAssembly - This method controls the entire code generation // process for the ultra sparc. // -bool UltraSparc::addPassesToEmitAssembly(PassManager &PM, std::ostream &Out) +bool +SparcTargetMachine::addPassesToEmitAssembly(PassManager &PM, std::ostream &Out) { // The following 3 passes used to be inserted specially by llc. // Replace malloc and free instructions with library calls. @@ -225,7 +152,7 @@ bool UltraSparc::addPassesToEmitAssembly(PassManager &PM, std::ostream &Out) // addPassesToJITCompile - This method controls the JIT method of code // generation for the UltraSparc. // -bool UltraSparc::addPassesToJITCompile(FunctionPassManager &PM) { +bool SparcTargetMachine::addPassesToJITCompile(FunctionPassManager &PM) { const TargetData &TD = getTargetData(); PM.add(new TargetData("lli", TD.isLittleEndian(), TD.getPointerSize(), @@ -269,4 +196,15 @@ bool UltraSparc::addPassesToJITCompile(FunctionPassManager &PM) { return false; // success! } -} // End llvm namespace +//---------------------------------------------------------------------------- +// allocateSparcTargetMachine - Allocate and return a subclass of TargetMachine +// that implements the Sparc backend. (the llvm/CodeGen/Sparc.h interface) +//---------------------------------------------------------------------------- + +namespace llvm { + +TargetMachine *allocateSparcTargetMachine(const Module &M) { + return new SparcTargetMachine(); +} + +} diff --git a/lib/Target/SparcV9/SparcV9TargetMachine.h b/lib/Target/SparcV9/SparcV9TargetMachine.h new file mode 100644 index 0000000..c8a6116 --- /dev/null +++ b/lib/Target/SparcV9/SparcV9TargetMachine.h @@ -0,0 +1,59 @@ +//===-- SparcTargetMachine.h - Define TargetMachine for Sparc ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the primary interface to machine description for the +// UltraSPARC. +// +//===----------------------------------------------------------------------===// + +#ifndef SPARC_TARGETMACHINE_H +#define SPARC_TARGETMACHINE_H + +#include "llvm/PassManager.h" +#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "SparcInstrInfo.h" +#include "SparcInternals.h" +#include "SparcRegInfo.h" +#include "SparcFrameInfo.h" + +namespace llvm { + +class SparcTargetMachine : public TargetMachine { + SparcInstrInfo instrInfo; + SparcSchedInfo schedInfo; + SparcRegInfo regInfo; + SparcFrameInfo frameInfo; + SparcCacheInfo cacheInfo; +public: + SparcTargetMachine(); + + virtual const TargetInstrInfo &getInstrInfo() const { return instrInfo; } + virtual const TargetSchedInfo &getSchedInfo() const { return schedInfo; } + virtual const TargetRegInfo &getRegInfo() const { return regInfo; } + virtual const TargetFrameInfo &getFrameInfo() const { return frameInfo; } + virtual const TargetCacheInfo &getCacheInfo() const { return cacheInfo; } + + virtual bool addPassesToEmitAssembly(PassManager &PM, std::ostream &Out); + virtual bool addPassesToJITCompile(FunctionPassManager &PM); + virtual bool addPassesToEmitMachineCode(FunctionPassManager &PM, + MachineCodeEmitter &MCE); + virtual void replaceMachineCodeForFunction(void *Old, void *New); + + /// getJITStubForFunction - Create or return a stub for the specified + /// function. This stub acts just like the specified function, except that it + /// allows the "address" of the function to be taken without having to + /// generate code for it. + /// + ///virtual void *getJITStubForFunction(Function *F, MachineCodeEmitter &MCE); +}; + +} // End llvm namespace + +#endif |