diff options
author | Tony Linthicum <tlinth@codeaurora.org> | 2011-12-12 21:14:40 +0000 |
---|---|---|
committer | Tony Linthicum <tlinth@codeaurora.org> | 2011-12-12 21:14:40 +0000 |
commit | 1213a7a57fdcb6c875b3f79103fc96d3e9d30b40 (patch) | |
tree | 531d34e916e847cebbd717082d4f696a51610812 /llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp | |
parent | 45c41641664d8ff44c03f6205312d347081882b0 (diff) | |
download | bcm5719-llvm-1213a7a57fdcb6c875b3f79103fc96d3e9d30b40.tar.gz bcm5719-llvm-1213a7a57fdcb6c875b3f79103fc96d3e9d30b40.zip |
Hexagon backend support
llvm-svn: 146412
Diffstat (limited to 'llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp')
-rw-r--r-- | llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp | 322 |
1 files changed, 322 insertions, 0 deletions
diff --git a/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp b/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp new file mode 100644 index 00000000000..9fd9fd34243 --- /dev/null +++ b/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp @@ -0,0 +1,322 @@ +//==- HexagonRegisterInfo.cpp - Hexagon 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 Hexagon implementation of the TargetRegisterInfo +// class. +// +//===----------------------------------------------------------------------===// + +#include "Hexagon.h" +#include "HexagonRegisterInfo.h" +#include "HexagonSubtarget.h" +#include "HexagonTargetMachine.h" +#include "HexagonMachineFunctionInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/MC/MachineLocation.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Type.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include <iostream> + +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/Function.h" +using namespace llvm; + + +HexagonRegisterInfo::HexagonRegisterInfo(HexagonSubtarget &st, + const HexagonInstrInfo &tii) + : HexagonGenRegisterInfo(Hexagon::R31), + Subtarget(st), + TII(tii) { +} + +const unsigned* HexagonRegisterInfo::getCalleeSavedRegs(const MachineFunction + *MF) + const { + static const unsigned CalleeSavedRegsV2[] = { + Hexagon::R24, Hexagon::R25, Hexagon::R26, Hexagon::R27, 0 + }; + static const unsigned CalleeSavedRegsV3[] = { + Hexagon::R16, Hexagon::R17, Hexagon::R18, Hexagon::R19, + Hexagon::R20, Hexagon::R21, Hexagon::R22, Hexagon::R23, + Hexagon::R24, Hexagon::R25, Hexagon::R26, Hexagon::R27, 0 + }; + + switch(Subtarget.getHexagonArchVersion()) { + case HexagonSubtarget::V2: + return CalleeSavedRegsV2; + break; + case HexagonSubtarget::V3: + case HexagonSubtarget::V4: + return CalleeSavedRegsV3; + break; + default: + const char *ErrorString = + "Callee saved registers requested for unknown archtecture version"; + llvm_unreachable(ErrorString); + } +} + +BitVector HexagonRegisterInfo::getReservedRegs(const MachineFunction &MF) + const { + BitVector Reserved(getNumRegs()); + Reserved.set(HEXAGON_RESERVED_REG_1); + Reserved.set(HEXAGON_RESERVED_REG_2); + Reserved.set(Hexagon::R29); + Reserved.set(Hexagon::R30); + Reserved.set(Hexagon::R31); + Reserved.set(Hexagon::D14); + Reserved.set(Hexagon::D15); + Reserved.set(Hexagon::LC0); + Reserved.set(Hexagon::LC1); + Reserved.set(Hexagon::SA0); + Reserved.set(Hexagon::SA1); + return Reserved; +} + + +const TargetRegisterClass* const* +HexagonRegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const { + static const TargetRegisterClass * const CalleeSavedRegClassesV2[] = { + &Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass, + &Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass, + }; + static const TargetRegisterClass * const CalleeSavedRegClassesV3[] = { + &Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass, + &Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass, + &Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass, + &Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass, + &Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass, + &Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass, + }; + + switch(Subtarget.getHexagonArchVersion()) { + case HexagonSubtarget::V2: + return CalleeSavedRegClassesV2; + break; + case HexagonSubtarget::V3: + case HexagonSubtarget::V4: + return CalleeSavedRegClassesV3; + break; + default: + const char *ErrorString = + "Callee saved register classes requested for unknown archtecture version"; + llvm_unreachable(ErrorString); + } +} + +void HexagonRegisterInfo:: +eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const { + MachineInstr &MI = *I; + + if (MI.getOpcode() == Hexagon::ADJCALLSTACKDOWN) { + // Hexagon_TODO: add code + } else if (MI.getOpcode() == Hexagon::ADJCALLSTACKUP) { + // Hexagon_TODO: add code + } else { + assert(0 && "Cannot handle this call frame pseudo instruction"); + } + MBB.erase(I); +} + +void HexagonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, + int SPAdj, RegScavenger *RS) const { + + // + // Hexagon_TODO: Do we need to enforce this for Hexagon? + assert(SPAdj == 0 && "Unexpected"); + + + unsigned i = 0; + MachineInstr &MI = *II; + while (!MI.getOperand(i).isFI()) { + ++i; + assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!"); + } + + int FrameIndex = MI.getOperand(i).getIndex(); + + // Addressable stack objects are accessed using neg. offsets from %fp. + MachineFunction &MF = *MI.getParent()->getParent(); + int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex); + MachineFrameInfo &MFI = *MF.getFrameInfo(); + + unsigned FrameReg = getFrameRegister(MF); + const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); + if (!TFI->hasFP(MF)) { + // We will not reserve space on the stack for the lr and fp registers. + Offset -= 2 * Hexagon_WordSize; + } + + const unsigned FrameSize = MFI.getStackSize(); + + if (!MFI.hasVarSizedObjects() && + TII.isValidOffset(MI.getOpcode(), (FrameSize+Offset)) && + !TII.isSpillPredRegOp(&MI)) { + // Replace frame index with a stack pointer reference. + MI.getOperand(i).ChangeToRegister(getStackRegister(), false, false, true); + MI.getOperand(i+1).ChangeToImmediate(FrameSize+Offset); + } else { + // Replace frame index with a frame pointer reference. + if (!TII.isValidOffset(MI.getOpcode(), Offset)) { + + // If the offset overflows, then correct it. + // + // For loads, we do not need a reserved register + // r0 = memw(r30 + #10000) to: + // + // r0 = add(r30, #10000) + // r0 = memw(r0) + if ( (MI.getOpcode() == Hexagon::LDriw) || + (MI.getOpcode() == Hexagon::LDrid) || + (MI.getOpcode() == Hexagon::LDrih) || + (MI.getOpcode() == Hexagon::LDriuh) || + (MI.getOpcode() == Hexagon::LDrib) || + (MI.getOpcode() == Hexagon::LDriub) ) { + unsigned dstReg = (MI.getOpcode() == Hexagon::LDrid) ? + *getSubRegisters(MI.getOperand(0).getReg()) : + MI.getOperand(0).getReg(); + + // Check if offset can fit in addi. + if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) { + BuildMI(*MI.getParent(), II, MI.getDebugLoc(), + TII.get(Hexagon::CONST32_Int_Real), dstReg).addImm(Offset); + BuildMI(*MI.getParent(), II, MI.getDebugLoc(), + TII.get(Hexagon::ADD_rr), + dstReg).addReg(FrameReg).addReg(dstReg); + } else { + BuildMI(*MI.getParent(), II, MI.getDebugLoc(), + TII.get(Hexagon::ADD_ri), + dstReg).addReg(FrameReg).addImm(Offset); + } + + MI.getOperand(i).ChangeToRegister(dstReg, false, false, true); + MI.getOperand(i+1).ChangeToImmediate(0); + } else if ((MI.getOpcode() == Hexagon::STriw) || + (MI.getOpcode() == Hexagon::STrid) || + (MI.getOpcode() == Hexagon::STrih) || + (MI.getOpcode() == Hexagon::STrib) || + (MI.getOpcode() == Hexagon::STriwt)) { + // For stores, we need a reserved register. Change + // memw(r30 + #10000) = r0 to: + // + // rs = add(r30, #10000); + // memw(rs) = r0 + unsigned resReg = HEXAGON_RESERVED_REG_1; + + // Check if offset can fit in addi. + if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) { + BuildMI(*MI.getParent(), II, MI.getDebugLoc(), + TII.get(Hexagon::CONST32_Int_Real), resReg).addImm(Offset); + BuildMI(*MI.getParent(), II, MI.getDebugLoc(), + TII.get(Hexagon::ADD_rr), + resReg).addReg(FrameReg).addReg(resReg); + } else { + BuildMI(*MI.getParent(), II, MI.getDebugLoc(), + TII.get(Hexagon::ADD_ri), + resReg).addReg(FrameReg).addImm(Offset); + } + MI.getOperand(i).ChangeToRegister(resReg, false, false, true); + MI.getOperand(i+1).ChangeToImmediate(0); + } else if (TII.isMemOp(&MI)) { + unsigned resReg = HEXAGON_RESERVED_REG_1; + if (!MFI.hasVarSizedObjects() && + TII.isValidOffset(MI.getOpcode(), (FrameSize+Offset))) { + MI.getOperand(i).ChangeToRegister(getStackRegister(), false, false, + true); + MI.getOperand(i+1).ChangeToImmediate(FrameSize+Offset); + } else if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) { + BuildMI(*MI.getParent(), II, MI.getDebugLoc(), + TII.get(Hexagon::CONST32_Int_Real), resReg).addImm(Offset); + BuildMI(*MI.getParent(), II, MI.getDebugLoc(), + TII.get(Hexagon::ADD_rr), + resReg).addReg(FrameReg).addReg(resReg); + MI.getOperand(i).ChangeToRegister(resReg, false, false, true); + MI.getOperand(i+1).ChangeToImmediate(0); + } else { + BuildMI(*MI.getParent(), II, MI.getDebugLoc(), + TII.get(Hexagon::ADD_ri), + resReg).addReg(FrameReg).addImm(Offset); + MI.getOperand(i).ChangeToRegister(resReg, false, false, true); + MI.getOperand(i+1).ChangeToImmediate(0); + } + } else { + unsigned dstReg = MI.getOperand(0).getReg(); + BuildMI(*MI.getParent(), II, MI.getDebugLoc(), + TII.get(Hexagon::CONST32_Int_Real), dstReg).addImm(Offset); + BuildMI(*MI.getParent(), II, MI.getDebugLoc(), + TII.get(Hexagon::ADD_rr), + dstReg).addReg(FrameReg).addReg(dstReg); + // Can we delete MI??? r2 = add (r2, #0). + MI.getOperand(i).ChangeToRegister(dstReg, false, false, true); + MI.getOperand(i+1).ChangeToImmediate(0); + } + } else { + // If the offset is small enough to fit in the immediate field, directly + // encode it. + MI.getOperand(i).ChangeToRegister(FrameReg, false); + MI.getOperand(i+1).ChangeToImmediate(Offset); + } + } + +} + +unsigned HexagonRegisterInfo::getRARegister() const { + return Hexagon::R31; +} + +unsigned HexagonRegisterInfo::getFrameRegister(const MachineFunction + &MF) const { + const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); + if (TFI->hasFP(MF)) { + return Hexagon::R30; + } + + return Hexagon::R29; +} + +unsigned HexagonRegisterInfo::getFrameRegister() const { + return Hexagon::R30; +} + +unsigned HexagonRegisterInfo::getStackRegister() const { + return Hexagon::R29; +} + +void HexagonRegisterInfo::getInitialFrameState(std::vector<MachineMove> + &Moves) const +{ + // VirtualFP = (R30 + #0). + unsigned FPReg = getFrameRegister(); + MachineLocation Dst(MachineLocation::VirtualFP); + MachineLocation Src(FPReg, 0); + Moves.push_back(MachineMove(0, Dst, Src)); +} + +unsigned HexagonRegisterInfo::getEHExceptionRegister() const { + assert(0 && "What is the exception register"); + return 0; +} + +unsigned HexagonRegisterInfo::getEHHandlerRegister() const { + assert(0 && "What is the exception handler register"); + return 0; +} + +#include "HexagonGenRegisterInfo.inc" |