//===- BlackfinRegisterInfo.cpp - Blackfin Register Information -*- C++ -*-===// // // 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 Blackfin implementation of the TargetRegisterInfo // class. // //===----------------------------------------------------------------------===// #include "Blackfin.h" #include "BlackfinRegisterInfo.h" #include "BlackfinSubtarget.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/RegisterScavenging.h" #include "llvm/Target/TargetFrameLowering.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Type.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" #define GET_REGINFO_TARGET_DESC #include "BlackfinGenRegisterInfo.inc" using namespace llvm; BlackfinRegisterInfo::BlackfinRegisterInfo(BlackfinSubtarget &st, const TargetInstrInfo &tii) : BlackfinGenRegisterInfo(BF::RETS), Subtarget(st), TII(tii) {} const unsigned* BlackfinRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { using namespace BF; static const unsigned CalleeSavedRegs[] = { FP, R4, R5, R6, R7, P3, P4, P5, 0 }; return CalleeSavedRegs; } BitVector BlackfinRegisterInfo::getReservedRegs(const MachineFunction &MF) const { const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); using namespace BF; BitVector Reserved(getNumRegs()); Reserved.set(AZ); Reserved.set(AN); Reserved.set(AQ); Reserved.set(AC0); Reserved.set(AC1); Reserved.set(AV0); Reserved.set(AV0S); Reserved.set(AV1); Reserved.set(AV1S); Reserved.set(V); Reserved.set(VS); Reserved.set(CYCLES).set(CYCLES2); Reserved.set(L0); Reserved.set(L1); Reserved.set(L2); Reserved.set(L3); Reserved.set(SP); Reserved.set(RETS); if (TFI->hasFP(MF)) Reserved.set(FP); return Reserved; } bool BlackfinRegisterInfo:: requiresRegisterScavenging(const MachineFunction &MF) const { return true; } // Emit instructions to add delta to D/P register. ScratchReg must be of the // same class as Reg (P). void BlackfinRegisterInfo::adjustRegister(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, DebugLoc DL, unsigned Reg, unsigned ScratchReg, int delta) const { if (!delta) return; if (isInt<7>(delta)) { BuildMI(MBB, I, DL, TII.get(BF::ADDpp_imm7), Reg) .addReg(Reg) // No kill on two-addr operand .addImm(delta); return; } // We must load delta into ScratchReg and add that. loadConstant(MBB, I, DL, ScratchReg, delta); if (BF::PRegClass.contains(Reg)) { assert(BF::PRegClass.contains(ScratchReg) && "ScratchReg must be a P register"); BuildMI(MBB, I, DL, TII.get(BF::ADDpp), Reg) .addReg(Reg, RegState::Kill) .addReg(ScratchReg, RegState::Kill); } else { assert(BF::DRegClass.contains(Reg) && "Reg must be a D or P register"); assert(BF::DRegClass.contains(ScratchReg) && "ScratchReg must be a D register"); BuildMI(MBB, I, DL, TII.get(BF::ADD), Reg) .addReg(Reg, RegState::Kill) .addReg(ScratchReg, RegState::Kill); } } // Emit instructions to load a constant into D/P register void BlackfinRegisterInfo::loadConstant(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, DebugLoc DL, unsigned Reg, int value) const { if (isInt<7>(value)) { BuildMI(MBB, I, DL, TII.get(BF::LOADimm7), Reg).addImm(value); return; } if (isUInt<16>(value)) { BuildMI(MBB, I, DL, TII.get(BF::LOADuimm16), Reg).addImm(value); return; } if (isInt<16>(value)) { BuildMI(MBB, I, DL, TII.get(BF::LOADimm16), Reg).addImm(value); return; } // We must split into halves BuildMI(MBB, I, DL, TII.get(BF::LOAD16i), getSubReg(Reg, BF::hi16)) .addImm((value >> 16) & 0xffff) .addReg(Reg, RegState::ImplicitDefine); BuildMI(MBB, I, DL, TII.get(BF::LOAD16i), getSubReg(Reg, BF::lo16)) .addImm(value & 0xffff) .addReg(Reg, RegState::ImplicitKill) .addReg(Reg, RegState::ImplicitDefine); } void BlackfinRegisterInfo:: eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const { const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); if (!TFI->hasReservedCallFrame(MF)) { int64_t Amount = I->getOperand(0).getImm(); if (Amount != 0) { assert(Amount%4 == 0 && "Unaligned call frame size"); if (I->getOpcode() == BF::ADJCALLSTACKDOWN) { adjustRegister(MBB, I, I->getDebugLoc(), BF::SP, BF::P1, -Amount); } else { assert(I->getOpcode() == BF::ADJCALLSTACKUP && "Unknown call frame pseudo instruction"); adjustRegister(MBB, I, I->getDebugLoc(), BF::SP, BF::P1, Amount); } } } MBB.erase(I); } /// findScratchRegister - Find a 'free' register. Try for a call-clobbered /// register first and then a spilled callee-saved register if that fails. static unsigned findScratchRegister(MachineBasicBlock::iterator II, RegScavenger *RS, const TargetRegisterClass *RC, int SPAdj) { assert(RS && "Register scavenging must be on"); unsigned Reg = RS->FindUnusedReg(RC); if (Reg == 0) Reg = RS->scavengeRegister(RC, II, SPAdj); return Reg; } void BlackfinRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, RegScavenger *RS) const { MachineInstr &MI = *II; MachineBasicBlock &MBB = *MI.getParent(); MachineFunction &MF = *MBB.getParent(); const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); DebugLoc DL = MI.getDebugLoc(); unsigned FIPos; for (FIPos=0; !MI.getOperand(FIPos).isFI(); ++FIPos) { assert(FIPos < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!"); } int FrameIndex = MI.getOperand(FIPos).getIndex(); assert(FIPos+1 < MI.getNumOperands() && MI.getOperand(FIPos+1).isImm()); int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex) + MI.getOperand(FIPos+1).getImm(); unsigned BaseReg = BF::FP; if (TFI->hasFP(MF)) { assert(SPAdj==0 && "Unexpected SP adjust in function with frame pointer"); } else { BaseReg = BF::SP; Offset += MF.getFrameInfo()->getStackSize() + SPAdj; } bool isStore = false; switch (MI.getOpcode()) { case BF::STORE32fi: isStore = true; case BF::LOAD32fi: { assert(Offset%4 == 0 && "Unaligned i32 stack access"); assert(FIPos==1 && "Bad frame index operand"); MI.getOperand(FIPos).ChangeToRegister(BaseReg, false); MI.getOperand(FIPos+1).setImm(Offset); if (isUInt<6>(Offset)) { MI.setDesc(TII.get(isStore ? BF::STORE32p_uimm6m4 : BF::LOAD32p_uimm6m4)); return; } if (BaseReg == BF::FP && isUInt<7>(-Offset)) { MI.setDesc(TII.get(isStore ? BF::STORE32fp_nimm7m4 : BF::LOAD32fp_nimm7m4)); MI.getOperand(FIPos+1).setImm(-Offset); return; } if (isInt<18>(Offset)) { MI.setDesc(TII.get(isStore ? BF::STORE32p_imm18m4 : BF::LOAD32p_imm18m4)); return; } // Use RegScavenger to calculate proper offset... MI.dump(); llvm_unreachable("Stack frame offset too big"); break; } case BF::ADDpp: { assert(MI.getOperand(0).isReg() && "ADD instruction needs a register"); unsigned DestReg = MI.getOperand(0).getReg(); // We need to produce a stack offset in a P register. We emit: // P0 = offset; // P0 = BR + P0; assert(FIPos==1 && "Bad frame index operand"); loadConstant(MBB, II, DL, DestReg, Offset); MI.getOperand(1).ChangeToRegister(DestReg, false, false, true); MI.getOperand(2).ChangeToRegister(BaseReg, false); break; } case BF::STORE16fi: isStore = true; case BF::LOAD16fi: { assert(Offset%2 == 0 && "Unaligned i16 stack access"); assert(FIPos==1 && "Bad frame index operand"); // We need a P register to use as an address unsigned ScratchReg = findScratchRegister(II, RS, &BF::PRegClass, SPAdj); assert(ScratchReg && "Could not scavenge register"); loadConstant(MBB, II, DL, ScratchReg, Offset); BuildMI(MBB, II, DL, TII.get(BF::ADDpp), ScratchReg) .addReg(ScratchReg, RegState::Kill) .addReg(BaseReg); MI.setDesc(TII.get(isStore ? BF::STORE16pi : BF::LOAD16pi)); MI.getOperand(1).ChangeToRegister(ScratchReg, false, false, true); MI.RemoveOperand(2); break; } case BF::STORE8fi: { // This is an AnyCC spill, we need a scratch register. assert(FIPos==1 && "Bad frame index operand"); MachineOperand SpillReg = MI.getOperand(0); unsigned ScratchReg = findScratchRegister(II, RS, &BF::DRegClass, SPAdj); assert(ScratchReg && "Could not scavenge register"); if (SpillReg.getReg()==BF::NCC) { BuildMI(MBB, II, DL, TII.get(BF::MOVENCC_z), ScratchReg) .addOperand(SpillReg); BuildMI(MBB, II, DL, TII.get(BF::BITTGL), ScratchReg) .addReg(ScratchReg).addImm(0); } else { BuildMI(MBB, II, DL, TII.get(BF::MOVECC_zext), ScratchReg) .addOperand(SpillReg); } // STORE D MI.setDesc(TII.get(BF::STORE8p_imm16)); MI.getOperand(0).ChangeToRegister(ScratchReg, false, false, true); MI.getOperand(FIPos).ChangeToRegister(BaseReg, false); MI.getOperand(FIPos+1).setImm(Offset); break; } case BF::LOAD8fi: { // This is an restore, we need a scratch register. assert(FIPos==1 && "Bad frame index operand"); MachineOperand SpillReg = MI.getOperand(0); unsigned ScratchReg = findScratchRegister(II, RS, &BF::DRegClass, SPAdj); assert(ScratchReg && "Could not scavenge register"); MI.setDesc(TII.get(BF::LOAD32p_imm16_8z)); MI.getOperand(0).ChangeToRegister(ScratchReg, true); MI.getOperand(FIPos).ChangeToRegister(BaseReg, false); MI.getOperand(FIPos+1).setImm(Offset); ++II; if (SpillReg.getReg()==BF::CC) { // CC = D BuildMI(MBB, II, DL, TII.get(BF::MOVECC_nz), BF::CC) .addReg(ScratchReg, RegState::Kill); } else { // Restore NCC (CC = D==0) BuildMI(MBB, II, DL, TII.get(BF::SETEQri_not), BF::NCC) .addReg(ScratchReg, RegState::Kill) .addImm(0); } break; } default: llvm_unreachable("Cannot eliminate frame index"); break; } } unsigned BlackfinRegisterInfo::getFrameRegister(const MachineFunction &MF) const { const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); return TFI->hasFP(MF) ? BF::FP : BF::SP; } unsigned BlackfinRegisterInfo::getEHExceptionRegister() const { llvm_unreachable("What is the exception register"); return 0; } unsigned BlackfinRegisterInfo::getEHHandlerRegister() const { llvm_unreachable("What is the exception handler register"); return 0; }