diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2009-10-14 17:57:32 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2009-10-14 17:57:32 +0000 |
commit | cd749a9c07f1de2fb8affde90537efa4bc3e7c54 (patch) | |
tree | b21f6de4e08b89bb7931806bab798fc2a5e3a686 /lib/Target/Blackfin/BlackfinRegisterInfo.cpp | |
parent | 72621d11de5b873f1695f391eb95f0b336c3d2d4 (diff) | |
download | FreeBSD-src-cd749a9c07f1de2fb8affde90537efa4bc3e7c54.zip FreeBSD-src-cd749a9c07f1de2fb8affde90537efa4bc3e7c54.tar.gz |
Update llvm to r84119.
Diffstat (limited to 'lib/Target/Blackfin/BlackfinRegisterInfo.cpp')
-rw-r--r-- | lib/Target/Blackfin/BlackfinRegisterInfo.cpp | 472 |
1 files changed, 472 insertions, 0 deletions
diff --git a/lib/Target/Blackfin/BlackfinRegisterInfo.cpp b/lib/Target/Blackfin/BlackfinRegisterInfo.cpp new file mode 100644 index 0000000..8c0a58a --- /dev/null +++ b/lib/Target/Blackfin/BlackfinRegisterInfo.cpp @@ -0,0 +1,472 @@ +//===- 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/MachineLocation.h" +#include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/Target/TargetFrameInfo.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" +using namespace llvm; + +BlackfinRegisterInfo::BlackfinRegisterInfo(BlackfinSubtarget &st, + const TargetInstrInfo &tii) + : BlackfinGenRegisterInfo(BF::ADJCALLSTACKDOWN, BF::ADJCALLSTACKUP), + 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; +} + +const TargetRegisterClass* const *BlackfinRegisterInfo:: +getCalleeSavedRegClasses(const MachineFunction *MF) const { + using namespace BF; + static const TargetRegisterClass * const CalleeSavedRegClasses[] = { + &PRegClass, + &DRegClass, &DRegClass, &DRegClass, &DRegClass, + &PRegClass, &PRegClass, &PRegClass, + 0 }; + return CalleeSavedRegClasses; +} + +BitVector +BlackfinRegisterInfo::getReservedRegs(const MachineFunction &MF) const { + 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 (hasFP(MF)) + Reserved.set(FP); + return Reserved; +} + +const TargetRegisterClass* +BlackfinRegisterInfo::getPhysicalRegisterRegClass(unsigned reg, EVT VT) const { + assert(isPhysicalRegister(reg) && "reg must be a physical register"); + + // Pick the smallest register class of the right type that contains + // this physreg. + const TargetRegisterClass* BestRC = 0; + for (regclass_iterator I = regclass_begin(), E = regclass_end(); + I != E; ++I) { + const TargetRegisterClass* RC = *I; + if ((VT == MVT::Other || RC->hasType(VT)) && RC->contains(reg) && + (!BestRC || RC->getNumRegs() < BestRC->getNumRegs())) + BestRC = RC; + } + + assert(BestRC && "Couldn't find the register class"); + return BestRC; +} + +// hasFP - 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. +bool BlackfinRegisterInfo::hasFP(const MachineFunction &MF) const { + const MachineFrameInfo *MFI = MF.getFrameInfo(); + return NoFramePointerElim || MFI->hasCalls() || MFI->hasVarSizedObjects(); +} + +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, bfin_subreg_hi16)) + .addImm((value >> 16) & 0xffff) + .addReg(Reg, RegState::ImplicitDefine); + BuildMI(MBB, I, DL, + TII.get(BF::LOAD16i), getSubReg(Reg, bfin_subreg_lo16)) + .addImm(value & 0xffff) + .addReg(Reg, RegState::ImplicitKill) + .addReg(Reg, RegState::ImplicitDefine); +} + +void BlackfinRegisterInfo:: +eliminateCallFramePseudoInstr(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const { + if (!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; +} + +unsigned +BlackfinRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, + int SPAdj, int *Value, + RegScavenger *RS) const { + MachineInstr &MI = *II; + MachineBasicBlock &MBB = *MI.getParent(); + MachineFunction &MF = *MBB.getParent(); + 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 (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 0; + } + 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 0; + } + if (isInt<18>(Offset)) { + MI.setDesc(TII.get(isStore + ? BF::STORE32p_imm18m4 + : BF::LOAD32p_imm18m4)); + return 0; + } + // 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; + } + return 0; +} + +void BlackfinRegisterInfo:: +processFunctionBeforeCalleeSavedScan(MachineFunction &MF, + RegScavenger *RS) const { + MachineFrameInfo *MFI = MF.getFrameInfo(); + const TargetRegisterClass *RC = BF::DPRegisterClass; + if (requiresRegisterScavenging(MF)) { + // Reserve a slot close to SP or frame pointer. + RS->setScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(), + RC->getAlignment())); + } +} + +void BlackfinRegisterInfo:: +processFunctionBeforeFrameFinalized(MachineFunction &MF) const { +} + +// Emit a prologue that sets up a stack frame. +// On function entry, R0-R2 and P0 may hold arguments. +// R3, P1, and P2 may be used as scratch registers +void BlackfinRegisterInfo::emitPrologue(MachineFunction &MF) const { + MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB + MachineBasicBlock::iterator MBBI = MBB.begin(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + DebugLoc dl = (MBBI != MBB.end() + ? MBBI->getDebugLoc() + : DebugLoc::getUnknownLoc()); + + int FrameSize = MFI->getStackSize(); + if (FrameSize%4) { + FrameSize = (FrameSize+3) & ~3; + MFI->setStackSize(FrameSize); + } + + if (!hasFP(MF)) { + assert(!MFI->hasCalls() && + "FP elimination on a non-leaf function is not supported"); + adjustRegister(MBB, MBBI, dl, BF::SP, BF::P1, -FrameSize); + return; + } + + // emit a LINK instruction + if (FrameSize <= 0x3ffff) { + BuildMI(MBB, MBBI, dl, TII.get(BF::LINK)).addImm(FrameSize); + return; + } + + // Frame is too big, do a manual LINK: + // [--SP] = RETS; + // [--SP] = FP; + // FP = SP; + // P1 = -FrameSize; + // SP = SP + P1; + BuildMI(MBB, MBBI, dl, TII.get(BF::PUSH)) + .addReg(BF::RETS, RegState::Kill); + BuildMI(MBB, MBBI, dl, TII.get(BF::PUSH)) + .addReg(BF::FP, RegState::Kill); + BuildMI(MBB, MBBI, dl, TII.get(BF::MOVE), BF::FP) + .addReg(BF::SP); + loadConstant(MBB, MBBI, dl, BF::P1, -FrameSize); + BuildMI(MBB, MBBI, dl, TII.get(BF::ADDpp), BF::SP) + .addReg(BF::SP, RegState::Kill) + .addReg(BF::P1, RegState::Kill); + +} + +void BlackfinRegisterInfo::emitEpilogue(MachineFunction &MF, + MachineBasicBlock &MBB) const { + MachineFrameInfo *MFI = MF.getFrameInfo(); + MachineBasicBlock::iterator MBBI = prior(MBB.end()); + DebugLoc dl = MBBI->getDebugLoc(); + + int FrameSize = MFI->getStackSize(); + assert(FrameSize%4 == 0 && "Misaligned frame size"); + + if (!hasFP(MF)) { + assert(!MFI->hasCalls() && + "FP elimination on a non-leaf function is not supported"); + adjustRegister(MBB, MBBI, dl, BF::SP, BF::P1, FrameSize); + return; + } + + // emit an UNLINK instruction + BuildMI(MBB, MBBI, dl, TII.get(BF::UNLINK)); +} + +unsigned BlackfinRegisterInfo::getRARegister() const { + return BF::RETS; +} + +unsigned BlackfinRegisterInfo::getFrameRegister(MachineFunction &MF) const { + return 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; +} + +int BlackfinRegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const { + llvm_unreachable("What is the dwarf register number"); + return -1; +} + +#include "BlackfinGenRegisterInfo.inc" + |