X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FCellSPU%2FSPURegisterInfo.cpp;h=1b2da5f50c8123571b22638a9c01eed160e4a9b7;hb=4e02f23de24375294005f88b5254a3775d39fcb2;hp=4a6075581414e7e5f507703fbf79e839a2e62f0d;hpb=6f0d024a534af18d9e60b3ea757376cd8a3a980e;p=oota-llvm.git diff --git a/lib/Target/CellSPU/SPURegisterInfo.cpp b/lib/Target/CellSPU/SPURegisterInfo.cpp index 4a607558141..1b2da5f50c8 100644 --- a/lib/Target/CellSPU/SPURegisterInfo.cpp +++ b/lib/Target/CellSPU/SPURegisterInfo.cpp @@ -1,4 +1,4 @@ -//===- SPURegisterInfo.cpp - Cell SPU Register Information ----------------===// +//===-- SPURegisterInfo.cpp - Cell SPU Register Information ---------------===// // // The LLVM Compiler Infrastructure // @@ -12,13 +12,12 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "reginfo" -#include "SPU.h" #include "SPURegisterInfo.h" -#include "SPURegisterNames.h" +#include "SPU.h" #include "SPUInstrBuilder.h" #include "SPUSubtarget.h" #include "SPUMachineFunction.h" -#include "SPUFrameInfo.h" +#include "SPUFrameLowering.h" #include "llvm/Constants.h" #include "llvm/Type.h" #include "llvm/CodeGen/ValueTypes.h" @@ -26,21 +25,24 @@ #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineLocation.h" #include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/SelectionDAGNodes.h" +#include "llvm/CodeGen/RegisterScavenging.h" #include "llvm/CodeGen/ValueTypes.h" -#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetFrameLowering.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" #include -#include + +#define GET_REGINFO_TARGET_DESC +#include "SPUGenRegisterInfo.inc" using namespace llvm; @@ -178,60 +180,28 @@ unsigned SPURegisterInfo::getRegisterNumbering(unsigned RegEnum) { case SPU::R126: return 126; case SPU::R127: return 127; default: - std::cerr << "Unhandled reg in SPURegisterInfo::getRegisterNumbering!\n"; - abort(); + report_fatal_error("Unhandled reg in SPURegisterInfo::getRegisterNumbering"); } } SPURegisterInfo::SPURegisterInfo(const SPUSubtarget &subtarget, const TargetInstrInfo &tii) : - SPUGenRegisterInfo(SPU::ADJCALLSTACKDOWN, SPU::ADJCALLSTACKUP), - Subtarget(subtarget), - TII(tii) + SPUGenRegisterInfo(SPU::R0), Subtarget(subtarget), TII(tii) { } -void SPURegisterInfo::reMaterialize(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, - unsigned DestReg, - const MachineInstr *Orig) const { - MachineInstr *MI = Orig->clone(); - MI->getOperand(0).setReg(DestReg); - MBB.insert(I, MI); +/// getPointerRegClass - Return the register class to use to hold pointers. +/// This is used for addressing modes. +const TargetRegisterClass * +SPURegisterInfo::getPointerRegClass(unsigned Kind) const { + return &SPU::R32CRegClass; } -// SPU's 128-bit registers used for argument passing: -static const unsigned SPU_ArgRegs[] = { - SPU::R3, SPU::R4, SPU::R5, SPU::R6, SPU::R7, SPU::R8, SPU::R9, - SPU::R10, SPU::R11, SPU::R12, SPU::R13, SPU::R14, SPU::R15, SPU::R16, - SPU::R17, SPU::R18, SPU::R19, SPU::R20, SPU::R21, SPU::R22, SPU::R23, - SPU::R24, SPU::R25, SPU::R26, SPU::R27, SPU::R28, SPU::R29, SPU::R30, - SPU::R31, SPU::R32, SPU::R33, SPU::R34, SPU::R35, SPU::R36, SPU::R37, - SPU::R38, SPU::R39, SPU::R40, SPU::R41, SPU::R42, SPU::R43, SPU::R44, - SPU::R45, SPU::R46, SPU::R47, SPU::R48, SPU::R49, SPU::R50, SPU::R51, - SPU::R52, SPU::R53, SPU::R54, SPU::R55, SPU::R56, SPU::R57, SPU::R58, - SPU::R59, SPU::R60, SPU::R61, SPU::R62, SPU::R63, SPU::R64, SPU::R65, - SPU::R66, SPU::R67, SPU::R68, SPU::R69, SPU::R70, SPU::R71, SPU::R72, - SPU::R73, SPU::R74, SPU::R75, SPU::R76, SPU::R77, SPU::R78, SPU::R79 -}; - -const unsigned * -SPURegisterInfo::getArgRegs() -{ - return SPU_ArgRegs; -} - -const unsigned -SPURegisterInfo::getNumArgRegs() -{ - return sizeof(SPU_ArgRegs) / sizeof(SPU_ArgRegs[0]); -} - -const unsigned * +const uint16_t * SPURegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { // Cell ABI calling convention - static const unsigned SPU_CalleeSaveRegs[] = { + static const uint16_t SPU_CalleeSaveRegs[] = { SPU::R80, SPU::R81, SPU::R82, SPU::R83, SPU::R84, SPU::R85, SPU::R86, SPU::R87, SPU::R88, SPU::R89, SPU::R90, SPU::R91, @@ -249,38 +219,8 @@ SPURegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const SPU::R0, /* link register */ 0 /* end */ }; - - return SPU_CalleeSaveRegs; -} -const TargetRegisterClass* const* -SPURegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const -{ - // Cell ABI Calling Convention - static const TargetRegisterClass * const SPU_CalleeSaveRegClasses[] = { - &SPU::GPRCRegClass, &SPU::GPRCRegClass, &SPU::GPRCRegClass, - &SPU::GPRCRegClass, &SPU::GPRCRegClass, &SPU::GPRCRegClass, - &SPU::GPRCRegClass, &SPU::GPRCRegClass, &SPU::GPRCRegClass, - &SPU::GPRCRegClass, &SPU::GPRCRegClass, &SPU::GPRCRegClass, - &SPU::GPRCRegClass, &SPU::GPRCRegClass, &SPU::GPRCRegClass, - &SPU::GPRCRegClass, &SPU::GPRCRegClass, &SPU::GPRCRegClass, - &SPU::GPRCRegClass, &SPU::GPRCRegClass, &SPU::GPRCRegClass, - &SPU::GPRCRegClass, &SPU::GPRCRegClass, &SPU::GPRCRegClass, - &SPU::GPRCRegClass, &SPU::GPRCRegClass, &SPU::GPRCRegClass, - &SPU::GPRCRegClass, &SPU::GPRCRegClass, &SPU::GPRCRegClass, - &SPU::GPRCRegClass, &SPU::GPRCRegClass, &SPU::GPRCRegClass, - &SPU::GPRCRegClass, &SPU::GPRCRegClass, &SPU::GPRCRegClass, - &SPU::GPRCRegClass, &SPU::GPRCRegClass, &SPU::GPRCRegClass, - &SPU::GPRCRegClass, &SPU::GPRCRegClass, &SPU::GPRCRegClass, - &SPU::GPRCRegClass, &SPU::GPRCRegClass, &SPU::GPRCRegClass, - &SPU::GPRCRegClass, &SPU::GPRCRegClass, &SPU::GPRCRegClass, - &SPU::GPRCRegClass, /* environment pointer */ - &SPU::GPRCRegClass, /* stack pointer */ - &SPU::GPRCRegClass, /* link register */ - 0 /* end */ - }; - - return SPU_CalleeSaveRegClasses; + return SPU_CalleeSaveRegs; } /*! @@ -299,25 +239,6 @@ BitVector SPURegisterInfo::getReservedRegs(const MachineFunction &MF) const { // Stack Frame Processing methods //===----------------------------------------------------------------------===// -// needsFP - Return true if the specified function should have a dedicated frame -// pointer register. This is true if the function has variable sized allocas or -// if frame pointer elimination is disabled. -// -static bool needsFP(const MachineFunction &MF) { - const MachineFrameInfo *MFI = MF.getFrameInfo(); - return NoFramePointerElim || MFI->hasVarSizedObjects(); -} - -//-------------------------------------------------------------------------- -// hasFP - Return true if the specified function actually has a dedicated frame -// pointer register. This is true if the function needs a frame pointer and has -// a non-zero stack size. -bool -SPURegisterInfo::hasFP(const MachineFunction &MF) const { - const MachineFrameInfo *MFI = MF.getFrameInfo(); - return MFI->getStackSize() && needsFP(MF); -} - //-------------------------------------------------------------------------- void SPURegisterInfo::eliminateCallFramePseudoInstr(MachineFunction &MF, @@ -338,8 +259,9 @@ SPURegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, MachineBasicBlock &MBB = *MI.getParent(); MachineFunction &MF = *MBB.getParent(); MachineFrameInfo *MFI = MF.getFrameInfo(); + DebugLoc dl = II->getDebugLoc(); - while (!MI.getOperand(i).isFrameIndex()) { + while (!MI.getOperand(i).isFI()) { ++i; assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!"); } @@ -350,266 +272,85 @@ SPURegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, // Now add the frame object offset to the offset from r1. int Offset = MFI->getObjectOffset(FrameIndex); - // Most instructions, except for generated FrameIndex additions using AIr32, - // have the immediate in operand 1. AIr32, in this case, has the immediate - // in operand 2. - unsigned OpNo = (MI.getOpcode() != SPU::AIr32 ? 1 : 2); + // Most instructions, except for generated FrameIndex additions using AIr32 + // and ILAr32, have the immediate in operand 1. AIr32 and ILAr32 have the + // immediate in operand 2. + unsigned OpNo = 1; + if (MI.getOpcode() == SPU::AIr32 || MI.getOpcode() == SPU::ILAr32) + OpNo = 2; + MachineOperand &MO = MI.getOperand(OpNo); // Offset is biased by $lr's slot at the bottom. - Offset += MO.getImm() + MFI->getStackSize() + SPUFrameInfo::minStackSize(); + Offset += MO.getImm() + MFI->getStackSize() + SPUFrameLowering::minStackSize(); assert((Offset & 0xf) == 0 && "16-byte alignment violated in eliminateFrameIndex"); // Replace the FrameIndex with base register with $sp (aka $r1) SPOp.ChangeToRegister(SPU::R1, false); - if (Offset > SPUFrameInfo::maxFrameOffset() - || Offset < SPUFrameInfo::minFrameOffset()) { - cerr << "Large stack adjustment (" - << Offset - << ") in SPURegisterInfo::eliminateFrameIndex."; - } else { - MO.ChangeToImmediate(Offset); - } -} - -/// determineFrameLayout - Determine the size of the frame and maximum call -/// frame size. -void -SPURegisterInfo::determineFrameLayout(MachineFunction &MF) const -{ - MachineFrameInfo *MFI = MF.getFrameInfo(); - - // Get the number of bytes to allocate from the FrameInfo - unsigned FrameSize = MFI->getStackSize(); - - // Get the alignments provided by the target, and the maximum alignment - // (if any) of the fixed frame objects. - unsigned TargetAlign = MF.getTarget().getFrameInfo()->getStackAlignment(); - unsigned Align = std::max(TargetAlign, MFI->getMaxAlignment()); - assert(isPowerOf2_32(Align) && "Alignment is not power of 2"); - unsigned AlignMask = Align - 1; - - // Get the maximum call frame size of all the calls. - unsigned maxCallFrameSize = MFI->getMaxCallFrameSize(); - - // If we have dynamic alloca then maxCallFrameSize needs to be aligned so - // that allocations will be aligned. - if (MFI->hasVarSizedObjects()) - maxCallFrameSize = (maxCallFrameSize + AlignMask) & ~AlignMask; - // Update maximum call frame size. - MFI->setMaxCallFrameSize(maxCallFrameSize); - - // Include call frame size in total. - FrameSize += maxCallFrameSize; - - // Make sure the frame is aligned. - FrameSize = (FrameSize + AlignMask) & ~AlignMask; - - // Update frame info. - MFI->setStackSize(FrameSize); -} - -void SPURegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF, - RegScavenger *RS) - const { -#if 0 - // Save and clear the LR state. - SPUFunctionInfo *FI = MF.getInfo(); - FI->setUsesLR(MF.getRegInfo().isPhysRegUsed(LR)); -#endif - // Mark LR and SP unused, since the prolog spills them to stack and - // we don't want anyone else to spill them for us. - // - // Also, unless R2 is really used someday, don't spill it automatically. - MF.getRegInfo().setPhysRegUnused(SPU::R0); - MF.getRegInfo().setPhysRegUnused(SPU::R1); - MF.getRegInfo().setPhysRegUnused(SPU::R2); -} - -void SPURegisterInfo::emitPrologue(MachineFunction &MF) const -{ - MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB - MachineBasicBlock::iterator MBBI = MBB.begin(); - MachineFrameInfo *MFI = MF.getFrameInfo(); - MachineModuleInfo *MMI = MFI->getMachineModuleInfo(); - - // Prepare for debug frame info. - bool hasDebugInfo = MMI && MMI->hasDebugInfo(); - unsigned FrameLabelId = 0; - - // Move MBBI back to the beginning of the function. - MBBI = MBB.begin(); - - // Work out frame sizes. - determineFrameLayout(MF); - int FrameSize = MFI->getStackSize(); - - assert((FrameSize & 0xf) == 0 - && "SPURegisterInfo::emitPrologue: FrameSize not aligned"); - - if (FrameSize > 0) { - FrameSize = -(FrameSize + SPUFrameInfo::minStackSize()); - if (hasDebugInfo) { - // Mark effective beginning of when frame pointer becomes valid. - FrameLabelId = MMI->NextLabelID(); - BuildMI(MBB, MBBI, TII.get(ISD::LABEL)).addImm(FrameLabelId).addImm(0); - } - - // Adjust stack pointer, spilling $lr -> 16($sp) and $sp -> -FrameSize($sp) - // for the ABI - BuildMI(MBB, MBBI, TII.get(SPU::STQDr32), SPU::R0).addImm(16) - .addReg(SPU::R1); - if (isS10Constant(FrameSize)) { - // Spill $sp to adjusted $sp - BuildMI(MBB, MBBI, TII.get(SPU::STQDr32), SPU::R1).addImm(FrameSize) + // if 'Offset' doesn't fit to the D-form instruction's + // immediate, convert the instruction to X-form + // if the instruction is not an AI (which takes a s10 immediate), assume + // it is a load/store that can take a s14 immediate + if ((MI.getOpcode() == SPU::AIr32 && !isInt<10>(Offset)) + || !isInt<14>(Offset)) { + int newOpcode = convertDFormToXForm(MI.getOpcode()); + unsigned tmpReg = findScratchRegister(II, RS, &SPU::R32CRegClass, SPAdj); + BuildMI(MBB, II, dl, TII.get(SPU::ILr32), tmpReg ) + .addImm(Offset); + BuildMI(MBB, II, dl, TII.get(newOpcode), MI.getOperand(0).getReg()) + .addReg(tmpReg, RegState::Kill) .addReg(SPU::R1); - // Adjust $sp by required amout - BuildMI(MBB, MBBI, TII.get(SPU::AIr32), SPU::R1).addReg(SPU::R1) - .addImm(FrameSize); - } else if (FrameSize <= (1 << 16) - 1 && FrameSize >= -(1 << 16)) { - // Frame size can be loaded into ILr32n, so temporarily spill $r2 and use - // $r2 to adjust $sp: - BuildMI(MBB, MBBI, TII.get(SPU::STQDr128), SPU::R2) - .addImm(-16) - .addReg(SPU::R1); - BuildMI(MBB, MBBI, TII.get(SPU::ILr32), SPU::R2) - .addImm(FrameSize); - BuildMI(MBB, MBBI, TII.get(SPU::STQDr32), SPU::R1) - .addReg(SPU::R2) - .addReg(SPU::R1); - BuildMI(MBB, MBBI, TII.get(SPU::Ar32), SPU::R1) - .addReg(SPU::R1) - .addReg(SPU::R2); - BuildMI(MBB, MBBI, TII.get(SPU::SFIr32), SPU::R2) - .addReg(SPU::R2) - .addImm(16); - BuildMI(MBB, MBBI, TII.get(SPU::LQXr128), SPU::R2) - .addReg(SPU::R2) - .addReg(SPU::R1); - } else { - cerr << "Unhandled frame size: " << FrameSize << "\n"; - abort(); - } - - if (hasDebugInfo) { - std::vector &Moves = MMI->getFrameMoves(); - - // Show update of SP. - MachineLocation SPDst(MachineLocation::VirtualFP); - MachineLocation SPSrc(MachineLocation::VirtualFP, -FrameSize); - Moves.push_back(MachineMove(FrameLabelId, SPDst, SPSrc)); - - // Add callee saved registers to move list. - const std::vector &CSI = MFI->getCalleeSavedInfo(); - for (unsigned I = 0, E = CSI.size(); I != E; ++I) { - int Offset = MFI->getObjectOffset(CSI[I].getFrameIdx()); - unsigned Reg = CSI[I].getReg(); - if (Reg == SPU::R0) continue; - MachineLocation CSDst(MachineLocation::VirtualFP, Offset); - MachineLocation CSSrc(Reg); - Moves.push_back(MachineMove(FrameLabelId, CSDst, CSSrc)); - } - - // Mark effective beginning of when frame pointer is ready. - unsigned ReadyLabelId = MMI->NextLabelID(); - BuildMI(MBB, MBBI, TII.get(ISD::LABEL)).addImm(ReadyLabelId).addImm(0); - - MachineLocation FPDst(SPU::R1); - MachineLocation FPSrc(MachineLocation::VirtualFP); - Moves.push_back(MachineMove(ReadyLabelId, FPDst, FPSrc)); - } + // remove the replaced D-form instruction + MBB.erase(II); } else { - // This is a leaf function -- insert a branch hint iff there are - // sufficient number instructions in the basic block. Note that - // this is just a best guess based on the basic block's size. - if (MBB.size() >= (unsigned) SPUFrameInfo::branchHintPenalty()) { - MachineBasicBlock::iterator MBBI = prior(MBB.end()); - // Insert terminator label - unsigned BranchLabelId = MMI->NextLabelID(); - BuildMI(MBB, MBBI, TII.get(SPU::LABEL)).addImm(BranchLabelId).addImm(0); - } + MO.ChangeToImmediate(Offset); } } -void -SPURegisterInfo::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const -{ - MachineBasicBlock::iterator MBBI = prior(MBB.end()); - const MachineFrameInfo *MFI = MF.getFrameInfo(); - int FrameSize = MFI->getStackSize(); - int LinkSlotOffset = SPUFrameInfo::stackSlotSize(); - - assert(MBBI->getOpcode() == SPU::RET && - "Can only insert epilog into returning blocks"); - assert((FrameSize & 0xf) == 0 - && "SPURegisterInfo::emitEpilogue: FrameSize not aligned"); - if (FrameSize > 0) { - FrameSize = FrameSize + SPUFrameInfo::minStackSize(); - if (isS10Constant(FrameSize + LinkSlotOffset)) { - // Reload $lr, adjust $sp by required amount - // Note: We do this to slightly improve dual issue -- not by much, but it - // is an opportunity for dual issue. - BuildMI(MBB, MBBI, TII.get(SPU::LQDr128), SPU::R0) - .addImm(FrameSize + LinkSlotOffset) - .addReg(SPU::R1); - BuildMI(MBB, MBBI, TII.get(SPU::AIr32), SPU::R1) - .addReg(SPU::R1) - .addImm(FrameSize); - } else if (FrameSize <= (1 << 16) - 1 && FrameSize >= -(1 << 16)) { - // Frame size can be loaded into ILr32n, so temporarily spill $r2 and use - // $r2 to adjust $sp: - BuildMI(MBB, MBBI, TII.get(SPU::STQDr128), SPU::R2) - .addImm(16) - .addReg(SPU::R1); - BuildMI(MBB, MBBI, TII.get(SPU::ILr32), SPU::R2) - .addImm(FrameSize); - BuildMI(MBB, MBBI, TII.get(SPU::Ar32), SPU::R1) - .addReg(SPU::R1) - .addReg(SPU::R2); - BuildMI(MBB, MBBI, TII.get(SPU::LQDr128), SPU::R0) - .addImm(16) - .addReg(SPU::R2); - BuildMI(MBB, MBBI, TII.get(SPU::SFIr32), SPU::R2). - addReg(SPU::R2) - .addImm(16); - BuildMI(MBB, MBBI, TII.get(SPU::LQXr128), SPU::R2) - .addReg(SPU::R2) - .addReg(SPU::R1); - } else { - cerr << "Unhandled frame size: " << FrameSize << "\n"; - abort(); - } - } -} - unsigned -SPURegisterInfo::getRARegister() const -{ - return SPU::R0; -} - -unsigned -SPURegisterInfo::getFrameRegister(MachineFunction &MF) const +SPURegisterInfo::getFrameRegister(const MachineFunction &MF) const { return SPU::R1; } -void -SPURegisterInfo::getInitialFrameState(std::vector &Moves) const +int +SPURegisterInfo::convertDFormToXForm(int dFormOpcode) const { - // Initial state of the frame pointer is R1. - MachineLocation Dst(MachineLocation::VirtualFP); - MachineLocation Src(SPU::R1, 0); - Moves.push_back(MachineMove(0, Dst, Src)); + switch(dFormOpcode) + { + case SPU::AIr32: return SPU::Ar32; + case SPU::LQDr32: return SPU::LQXr32; + case SPU::LQDr128: return SPU::LQXr128; + case SPU::LQDv16i8: return SPU::LQXv16i8; + case SPU::LQDv4i32: return SPU::LQXv4i32; + case SPU::LQDv4f32: return SPU::LQXv4f32; + case SPU::STQDr32: return SPU::STQXr32; + case SPU::STQDr128: return SPU::STQXr128; + case SPU::STQDv16i8: return SPU::STQXv16i8; + case SPU::STQDv4i32: return SPU::STQXv4i32; + case SPU::STQDv4f32: return SPU::STQXv4f32; + + default: assert( false && "Unhandled D to X-form conversion"); + } + // default will assert, but need to return something to keep the + // compiler happy. + return dFormOpcode; } - -int -SPURegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const { - // FIXME: Most probably dwarf numbers differs for Linux and Darwin - return SPUGenRegisterInfo::getDwarfRegNumFull(RegNum, 0); +// TODO this is already copied from PPC. Could this convenience function +// be moved to the RegScavenger class? +unsigned +SPURegisterInfo::findScratchRegister(MachineBasicBlock::iterator II, + RegScavenger *RS, + const TargetRegisterClass *RC, + int SPAdj) const +{ + assert(RS && "Register scavenging must be on"); + unsigned Reg = RS->FindUnusedReg(RC); + if (Reg == 0) + Reg = RS->scavengeRegister(RC, II, SPAdj); + assert( Reg && "Register scavenger failed"); + return Reg; } - -#include "SPUGenRegisterInfo.inc"