X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FCellSPU%2FSPURegisterInfo.cpp;h=405994a8f082fbcbbeee6bee397f07ee7dcd7fa1;hb=7de81016684979490229ed59c81ff9a94a75d4c2;hp=7822d1e3b8950a4664515abac0665223cb7705b4;hpb=504c369213efb263136bb048e79af3516511c040;p=oota-llvm.git diff --git a/lib/Target/CellSPU/SPURegisterInfo.cpp b/lib/Target/CellSPU/SPURegisterInfo.cpp index 7822d1e3b89..405994a8f08 100644 --- a/lib/Target/CellSPU/SPURegisterInfo.cpp +++ b/lib/Target/CellSPU/SPURegisterInfo.cpp @@ -1,14 +1,13 @@ -//===- SPURegisterInfo.cpp - Cell SPU Register Information ------*- C++ -*-===// +//===- SPURegisterInfo.cpp - Cell SPU Register Information ----------------===// // // The LLVM Compiler Infrastructure // -// This file was developed by a team from the Computer Systems Research -// Department at The Aerospace Corporation and is distributed under the -// University of Illinois Open Source License. See LICENSE.TXT for details. +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // -// This file contains the PowerPC implementation of the MRegisterInfo class. +// This file contains the Cell implementation of the TargetRegisterInfo class. // //===----------------------------------------------------------------------===// @@ -28,7 +27,8 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineLocation.h" -#include "llvm/CodeGen/SelectionDAGNodes.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/RegisterScavenging.h" #include "llvm/CodeGen/ValueTypes.h" #include "llvm/Target/TargetFrameInfo.h" #include "llvm/Target/TargetInstrInfo.h" @@ -36,11 +36,12 @@ #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 using namespace llvm; @@ -178,8 +179,7 @@ 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"); } } @@ -191,244 +191,11 @@ SPURegisterInfo::SPURegisterInfo(const SPUSubtarget &subtarget, { } -void -SPURegisterInfo::storeRegToStackSlot(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - unsigned SrcReg, bool isKill, int FrameIdx, - const TargetRegisterClass *RC) const -{ - MachineOpCode opc; - if (RC == SPU::GPRCRegisterClass) { - opc = (FrameIdx < SPUFrameInfo::maxFrameOffset()) - ? SPU::STQDr128 - : SPU::STQXr128; - } else if (RC == SPU::R64CRegisterClass) { - opc = (FrameIdx < SPUFrameInfo::maxFrameOffset()) - ? SPU::STQDr64 - : SPU::STQXr64; - } else if (RC == SPU::R64FPRegisterClass) { - opc = (FrameIdx < SPUFrameInfo::maxFrameOffset()) - ? SPU::STQDr64 - : SPU::STQXr64; - } else if (RC == SPU::R32CRegisterClass) { - opc = (FrameIdx < SPUFrameInfo::maxFrameOffset()) - ? SPU::STQDr32 - : SPU::STQXr32; - } else if (RC == SPU::R32FPRegisterClass) { - opc = (FrameIdx < SPUFrameInfo::maxFrameOffset()) - ? SPU::STQDr32 - : SPU::STQXr32; - } else if (RC == SPU::R16CRegisterClass) { - opc = (FrameIdx < SPUFrameInfo::maxFrameOffset()) ? - SPU::STQDr16 - : SPU::STQXr16; - } else { - assert(0 && "Unknown regclass!"); - abort(); - } - - addFrameReference(BuildMI(MBB, MI, TII.get(opc)) - .addReg(SrcReg, false, false, isKill), FrameIdx); -} - -void SPURegisterInfo::storeRegToAddr(MachineFunction &MF, unsigned SrcReg, - bool isKill, - SmallVectorImpl &Addr, - const TargetRegisterClass *RC, - SmallVectorImpl &NewMIs) const { - cerr << "storeRegToAddr() invoked!\n"; - abort(); - - if (Addr[0].isFrameIndex()) { - /* do what storeRegToStackSlot does here */ - } else { - unsigned Opc = 0; - if (RC == SPU::GPRCRegisterClass) { - /* Opc = PPC::STW; */ - } else if (RC == SPU::R16CRegisterClass) { - /* Opc = PPC::STD; */ - } else if (RC == SPU::R32CRegisterClass) { - /* Opc = PPC::STFD; */ - } else if (RC == SPU::R32FPRegisterClass) { - /* Opc = PPC::STFD; */ - } else if (RC == SPU::R64FPRegisterClass) { - /* Opc = PPC::STFS; */ - } else if (RC == SPU::VECREGRegisterClass) { - /* Opc = PPC::STVX; */ - } else { - assert(0 && "Unknown regclass!"); - abort(); - } - MachineInstrBuilder MIB = BuildMI(TII.get(Opc)) - .addReg(SrcReg, false, false, isKill); - for (unsigned i = 0, e = Addr.size(); i != e; ++i) { - MachineOperand &MO = Addr[i]; - if (MO.isRegister()) - MIB.addReg(MO.getReg()); - else if (MO.isImmediate()) - MIB.addImm(MO.getImmedValue()); - else - MIB.addFrameIndex(MO.getFrameIndex()); - } - NewMIs.push_back(MIB); - } -} - -void -SPURegisterInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - unsigned DestReg, int FrameIdx, - const TargetRegisterClass *RC) const -{ - MachineOpCode opc; - if (RC == SPU::GPRCRegisterClass) { - opc = (FrameIdx < SPUFrameInfo::maxFrameOffset()) - ? SPU::LQDr128 - : SPU::LQXr128; - } else if (RC == SPU::R64CRegisterClass) { - opc = (FrameIdx < SPUFrameInfo::maxFrameOffset()) - ? SPU::LQDr64 - : SPU::LQXr64; - } else if (RC == SPU::R64FPRegisterClass) { - opc = (FrameIdx < SPUFrameInfo::maxFrameOffset()) - ? SPU::LQDr64 - : SPU::LQXr64; - } else if (RC == SPU::R32CRegisterClass) { - opc = (FrameIdx < SPUFrameInfo::maxFrameOffset()) - ? SPU::LQDr32 - : SPU::LQXr32; - } else if (RC == SPU::R32FPRegisterClass) { - opc = (FrameIdx < SPUFrameInfo::maxFrameOffset()) - ? SPU::LQDr32 - : SPU::LQXr32; - } else if (RC == SPU::R16CRegisterClass) { - opc = (FrameIdx < SPUFrameInfo::maxFrameOffset()) - ? SPU::LQDr16 - : SPU::LQXr16; - } else { - assert(0 && "Unknown regclass in loadRegFromStackSlot!"); - abort(); - } - - addFrameReference(BuildMI(MBB, MI, TII.get(opc)).addReg(DestReg), FrameIdx); -} - -/*! - \note We are really pessimistic here about what kind of a load we're doing. - */ -void SPURegisterInfo::loadRegFromAddr(MachineFunction &MF, unsigned DestReg, - SmallVectorImpl &Addr, - const TargetRegisterClass *RC, - SmallVectorImpl &NewMIs) - const { - cerr << "loadRegToAddr() invoked!\n"; - abort(); - - if (Addr[0].isFrameIndex()) { - /* do what loadRegFromStackSlot does here... */ - } else { - unsigned Opc = 0; - if (RC == SPU::R8CRegisterClass) { - /* do brilliance here */ - } else if (RC == SPU::R16CRegisterClass) { - /* Opc = PPC::LWZ; */ - } else if (RC == SPU::R32CRegisterClass) { - /* Opc = PPC::LD; */ - } else if (RC == SPU::R32FPRegisterClass) { - /* Opc = PPC::LFD; */ - } else if (RC == SPU::R64FPRegisterClass) { - /* Opc = PPC::LFS; */ - } else if (RC == SPU::VECREGRegisterClass) { - /* Opc = PPC::LVX; */ - } else if (RC == SPU::GPRCRegisterClass) { - /* Opc = something else! */ - } else { - assert(0 && "Unknown regclass!"); - abort(); - } - MachineInstrBuilder MIB = BuildMI(TII.get(Opc), DestReg); - for (unsigned i = 0, e = Addr.size(); i != e; ++i) { - MachineOperand &MO = Addr[i]; - if (MO.isRegister()) - MIB.addReg(MO.getReg()); - else if (MO.isImmediate()) - MIB.addImm(MO.getImmedValue()); - else - MIB.addFrameIndex(MO.getFrameIndex()); - } - NewMIs.push_back(MIB); - } -} - -void SPURegisterInfo::copyRegToReg(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - unsigned DestReg, unsigned SrcReg, - const TargetRegisterClass *DestRC, - const TargetRegisterClass *SrcRC) const -{ - if (DestRC != SrcRC) { - cerr << "SPURegisterInfo::copyRegToReg(): DestRC != SrcRC not supported!\n"; - abort(); - } - - if (DestRC == SPU::R8CRegisterClass) { - BuildMI(MBB, MI, TII.get(SPU::ORBIr8), DestReg).addReg(SrcReg).addImm(0); - } else if (DestRC == SPU::R16CRegisterClass) { - BuildMI(MBB, MI, TII.get(SPU::ORHIr16), DestReg).addReg(SrcReg).addImm(0); - } else if (DestRC == SPU::R32CRegisterClass) { - BuildMI(MBB, MI, TII.get(SPU::ORIr32), DestReg).addReg(SrcReg).addImm(0); - } else if (DestRC == SPU::R32FPRegisterClass) { - BuildMI(MBB, MI, TII.get(SPU::ORIf32), DestReg).addReg(SrcReg).addImm(0); - } else if (DestRC == SPU::R64CRegisterClass) { - BuildMI(MBB, MI, TII.get(SPU::ORIr64), DestReg).addReg(SrcReg).addImm(0); - } else if (DestRC == SPU::R64FPRegisterClass) { - BuildMI(MBB, MI, TII.get(SPU::ORIf64), DestReg).addReg(SrcReg).addImm(0); - } else if (DestRC == SPU::GPRCRegisterClass) { - BuildMI(MBB, MI, TII.get(SPU::ORgprc), DestReg).addReg(SrcReg) - .addReg(SrcReg); - } else if (DestRC == SPU::VECREGRegisterClass) { - BuildMI(MBB, MI, TII.get(SPU::ORv4i32), DestReg).addReg(SrcReg) - .addReg(SrcReg); - } else { - std::cerr << "Attempt to copy unknown/unsupported register class!\n"; - abort(); - } -} - -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); -} - -// 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]); +/// 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; } const unsigned * @@ -453,38 +220,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; } /*! @@ -493,83 +230,16 @@ SPURegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const */ BitVector SPURegisterInfo::getReservedRegs(const MachineFunction &MF) const { BitVector Reserved(getNumRegs()); - Reserved.set(SPU::R0); // LR - Reserved.set(SPU::R1); // SP - Reserved.set(SPU::R2); // environment pointer + Reserved.set(SPU::R0); // LR + Reserved.set(SPU::R1); // SP + Reserved.set(SPU::R2); // environment pointer return Reserved; } -/// foldMemoryOperand - SPU, like PPC, can only fold spills into -/// copy instructions, turning them into load/store instructions. -MachineInstr * -SPURegisterInfo::foldMemoryOperand(MachineInstr *MI, - SmallVectorImpl &Ops, - int FrameIndex) const -{ -#if SOMEDAY_SCOTT_LOOKS_AT_ME_AGAIN - if (Ops.size() != 1) return NULL; - - unsigned OpNum = Ops[0]; - unsigned Opc = MI->getOpcode(); - MachineInstr *NewMI = 0; - - if ((Opc == SPU::ORr32 - || Opc == SPU::ORv4i32) - && MI->getOperand(1).getReg() == MI->getOperand(2).getReg()) { - if (OpNum == 0) { // move -> store - unsigned InReg = MI->getOperand(1).getReg(); - if (FrameIndex < SPUFrameInfo::maxFrameOffset()) { - NewMI = addFrameReference(BuildMI(TII.get(SPU::STQDr32)).addReg(InReg), - FrameIndex); - } - } else { // move -> load - unsigned OutReg = MI->getOperand(0).getReg(); - Opc = (FrameIndex < SPUFrameInfo::maxFrameOffset()) ? SPU::STQDr32 : SPU::STQXr32; - NewMI = addFrameReference(BuildMI(TII.get(Opc), OutReg), FrameIndex); - } - } - - if (NewMI) - NewMI->copyKillDeadInfo(MI); - - return NewMI; -#else - return 0; -#endif -} - -/// General-purpose load/store fold to operand code -MachineInstr * -SPURegisterInfo::foldMemoryOperand(MachineInstr *MI, - SmallVectorImpl &Ops, - MachineInstr *LoadMI) const -{ - return 0; -} - //===----------------------------------------------------------------------===// // 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, @@ -583,260 +253,79 @@ SPURegisterInfo::eliminateCallFramePseudoInstr(MachineFunction &MF, void SPURegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, - RegScavenger *RS) const + RegScavenger *RS) const { - assert(SPAdj == 0 && "Unexpected SP adjacency == 0"); - unsigned i = 0; MachineInstr &MI = *II; 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!"); } MachineOperand &SPOp = MI.getOperand(i); - int FrameIndex = SPOp.getFrameIndex(); + int FrameIndex = SPOp.getIndex(); // 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.getImmedValue() + MFI->getStackSize() - + SPUFrameInfo::minStackSize(); + Offset += MO.getImm() + MFI->getStackSize() + SPUFrameInfo::minStackSize(); assert((Offset & 0xf) == 0 - && "16-byte alignment violated in SPURegisterInfo::eliminateFrameIndex"); + && "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."; + + // 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); + // remove the replaced D-form instruction + MBB.erase(II); } 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.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.setPhysRegUnused(SPU::R0); - MF.setPhysRegUnused(SPU::R1); - MF.setPhysRegUnused(SPU::R2); -} + 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); - } - - // 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) - .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); - - MachineLocation FPDst(SPU::R1); - MachineLocation FPSrc(MachineLocation::VirtualFP); - Moves.push_back(MachineMove(ReadyLabelId, FPDst, FPSrc)); - } - } 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); - } - } -} - -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(); - } - } + const TargetRegisterClass *RC = &SPU::R32CRegClass; + RS->setScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(), + RC->getAlignment(), + false)); } unsigned @@ -846,25 +335,55 @@ SPURegisterInfo::getRARegister() const } unsigned -SPURegisterInfo::getFrameRegister(MachineFunction &MF) const +SPURegisterInfo::getFrameRegister(const MachineFunction &MF) const { return SPU::R1; } -void -SPURegisterInfo::getInitialFrameState(std::vector &Moves) 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)); -} - - int SPURegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const { // FIXME: Most probably dwarf numbers differs for Linux and Darwin return SPUGenRegisterInfo::getDwarfRegNumFull(RegNum, 0); } +int +SPURegisterInfo::convertDFormToXForm(int dFormOpcode) const +{ + 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; +} + +// 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"