//===- SPURegisterInfo.cpp - Cell SPU Register Information ----------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file contains the Cell implementation of the TargetRegisterInfo class. // //===----------------------------------------------------------------------===// #define DEBUG_TYPE "reginfo" #include "SPU.h" #include "SPURegisterInfo.h" #include "SPUInstrBuilder.h" #include "SPUSubtarget.h" #include "SPUMachineFunction.h" #include "SPUFrameLowering.h" #include "llvm/Constants.h" #include "llvm/Type.h" #include "llvm/CodeGen/ValueTypes.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/RegisterScavenging.h" #include "llvm/CodeGen/ValueTypes.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 #define GET_REGINFO_TARGET_DESC #include "SPUGenRegisterInfo.inc" using namespace llvm; /// getRegisterNumbering - Given the enum value for some register, e.g. /// PPC::F14, return the number that it corresponds to (e.g. 14). unsigned SPURegisterInfo::getRegisterNumbering(unsigned RegEnum) { using namespace SPU; switch (RegEnum) { case SPU::R0: return 0; case SPU::R1: return 1; case SPU::R2: return 2; case SPU::R3: return 3; case SPU::R4: return 4; case SPU::R5: return 5; case SPU::R6: return 6; case SPU::R7: return 7; case SPU::R8: return 8; case SPU::R9: return 9; case SPU::R10: return 10; case SPU::R11: return 11; case SPU::R12: return 12; case SPU::R13: return 13; case SPU::R14: return 14; case SPU::R15: return 15; case SPU::R16: return 16; case SPU::R17: return 17; case SPU::R18: return 18; case SPU::R19: return 19; case SPU::R20: return 20; case SPU::R21: return 21; case SPU::R22: return 22; case SPU::R23: return 23; case SPU::R24: return 24; case SPU::R25: return 25; case SPU::R26: return 26; case SPU::R27: return 27; case SPU::R28: return 28; case SPU::R29: return 29; case SPU::R30: return 30; case SPU::R31: return 31; case SPU::R32: return 32; case SPU::R33: return 33; case SPU::R34: return 34; case SPU::R35: return 35; case SPU::R36: return 36; case SPU::R37: return 37; case SPU::R38: return 38; case SPU::R39: return 39; case SPU::R40: return 40; case SPU::R41: return 41; case SPU::R42: return 42; case SPU::R43: return 43; case SPU::R44: return 44; case SPU::R45: return 45; case SPU::R46: return 46; case SPU::R47: return 47; case SPU::R48: return 48; case SPU::R49: return 49; case SPU::R50: return 50; case SPU::R51: return 51; case SPU::R52: return 52; case SPU::R53: return 53; case SPU::R54: return 54; case SPU::R55: return 55; case SPU::R56: return 56; case SPU::R57: return 57; case SPU::R58: return 58; case SPU::R59: return 59; case SPU::R60: return 60; case SPU::R61: return 61; case SPU::R62: return 62; case SPU::R63: return 63; case SPU::R64: return 64; case SPU::R65: return 65; case SPU::R66: return 66; case SPU::R67: return 67; case SPU::R68: return 68; case SPU::R69: return 69; case SPU::R70: return 70; case SPU::R71: return 71; case SPU::R72: return 72; case SPU::R73: return 73; case SPU::R74: return 74; case SPU::R75: return 75; case SPU::R76: return 76; case SPU::R77: return 77; case SPU::R78: return 78; case SPU::R79: return 79; case SPU::R80: return 80; case SPU::R81: return 81; case SPU::R82: return 82; case SPU::R83: return 83; case SPU::R84: return 84; case SPU::R85: return 85; case SPU::R86: return 86; case SPU::R87: return 87; case SPU::R88: return 88; case SPU::R89: return 89; case SPU::R90: return 90; case SPU::R91: return 91; case SPU::R92: return 92; case SPU::R93: return 93; case SPU::R94: return 94; case SPU::R95: return 95; case SPU::R96: return 96; case SPU::R97: return 97; case SPU::R98: return 98; case SPU::R99: return 99; case SPU::R100: return 100; case SPU::R101: return 101; case SPU::R102: return 102; case SPU::R103: return 103; case SPU::R104: return 104; case SPU::R105: return 105; case SPU::R106: return 106; case SPU::R107: return 107; case SPU::R108: return 108; case SPU::R109: return 109; case SPU::R110: return 110; case SPU::R111: return 111; case SPU::R112: return 112; case SPU::R113: return 113; case SPU::R114: return 114; case SPU::R115: return 115; case SPU::R116: return 116; case SPU::R117: return 117; case SPU::R118: return 118; case SPU::R119: return 119; case SPU::R120: return 120; case SPU::R121: return 121; case SPU::R122: return 122; case SPU::R123: return 123; case SPU::R124: return 124; case SPU::R125: return 125; case SPU::R126: return 126; case SPU::R127: return 127; default: report_fatal_error("Unhandled reg in SPURegisterInfo::getRegisterNumbering"); } } SPURegisterInfo::SPURegisterInfo(const SPUSubtarget &subtarget, const TargetInstrInfo &tii) : SPUGenRegisterInfo(SPU::R0), Subtarget(subtarget), TII(tii) { } /// 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 * SPURegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { // Cell ABI calling convention static const unsigned 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, SPU::R92, SPU::R93, SPU::R94, SPU::R95, SPU::R96, SPU::R97, SPU::R98, SPU::R99, SPU::R100, SPU::R101, SPU::R102, SPU::R103, SPU::R104, SPU::R105, SPU::R106, SPU::R107, SPU::R108, SPU::R109, SPU::R110, SPU::R111, SPU::R112, SPU::R113, SPU::R114, SPU::R115, SPU::R116, SPU::R117, SPU::R118, SPU::R119, SPU::R120, SPU::R121, SPU::R122, SPU::R123, SPU::R124, SPU::R125, SPU::R126, SPU::R127, SPU::R2, /* environment pointer */ SPU::R1, /* stack pointer */ SPU::R0, /* link register */ 0 /* end */ }; return SPU_CalleeSaveRegs; } /*! R0 (link register), R1 (stack pointer) and R2 (environment pointer -- this is generally unused) are the Cell's reserved registers */ 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 return Reserved; } //===----------------------------------------------------------------------===// // Stack Frame Processing methods //===----------------------------------------------------------------------===// //-------------------------------------------------------------------------- void SPURegisterInfo::eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const { // Simply discard ADJCALLSTACKDOWN, ADJCALLSTACKUP instructions. MBB.erase(I); } void SPURegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, RegScavenger *RS) const { 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).isFI()) { ++i; assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!"); } MachineOperand &SPOp = MI.getOperand(i); 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 // 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() + 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' 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); } } unsigned SPURegisterInfo::getFrameRegister(const MachineFunction &MF) const { return SPU::R1; } 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; }