diff options
-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 9a51faa4cc..bb4bdaf8a4 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 0000000000..d283e942bb --- /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 0000000000..903859675c --- /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 11b0c7beab..af458ea039 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 0000000000..0926c072f9 --- /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 21e884be8e..c5fa145a8e 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 = |