| //===-- HexagonRegisterInfo.cpp - Hexagon 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 Hexagon implementation of the TargetRegisterInfo |
| // class. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "HexagonRegisterInfo.h" |
| #include "Hexagon.h" |
| #include "HexagonMachineFunctionInfo.h" |
| #include "HexagonSubtarget.h" |
| #include "HexagonTargetMachine.h" |
| #include "llvm/ADT/BitVector.h" |
| #include "llvm/ADT/STLExtras.h" |
| #include "llvm/CodeGen/MachineFrameInfo.h" |
| #include "llvm/CodeGen/MachineFunction.h" |
| #include "llvm/CodeGen/MachineFunctionPass.h" |
| #include "llvm/CodeGen/MachineInstrBuilder.h" |
| #include "llvm/CodeGen/MachineRegisterInfo.h" |
| #include "llvm/CodeGen/RegisterScavenging.h" |
| #include "llvm/IR/Function.h" |
| #include "llvm/IR/Type.h" |
| #include "llvm/MC/MachineLocation.h" |
| #include "llvm/Support/CommandLine.h" |
| #include "llvm/Support/ErrorHandling.h" |
| #include "llvm/Target/TargetInstrInfo.h" |
| #include "llvm/Target/TargetMachine.h" |
| #include "llvm/Target/TargetOptions.h" |
| |
| using namespace llvm; |
| |
| |
| HexagonRegisterInfo::HexagonRegisterInfo(HexagonSubtarget &st, |
| const HexagonInstrInfo &tii) |
| : HexagonGenRegisterInfo(Hexagon::R31), |
| Subtarget(st), |
| TII(tii) { |
| } |
| |
| const uint16_t* HexagonRegisterInfo::getCalleeSavedRegs(const MachineFunction |
| *MF) |
| const { |
| static const uint16_t CalleeSavedRegsV2[] = { |
| Hexagon::R24, Hexagon::R25, Hexagon::R26, Hexagon::R27, 0 |
| }; |
| static const uint16_t 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::V1: |
| break; |
| case HexagonSubtarget::V2: |
| return CalleeSavedRegsV2; |
| case HexagonSubtarget::V3: |
| case HexagonSubtarget::V4: |
| case HexagonSubtarget::V5: |
| return CalleeSavedRegsV3; |
| } |
| llvm_unreachable("Callee saved registers requested for unknown architecture " |
| "version"); |
| } |
| |
| 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::V1: |
| break; |
| case HexagonSubtarget::V2: |
| return CalleeSavedRegClassesV2; |
| case HexagonSubtarget::V3: |
| case HexagonSubtarget::V4: |
| case HexagonSubtarget::V5: |
| return CalleeSavedRegClassesV3; |
| } |
| llvm_unreachable("Callee saved register classes requested for unknown " |
| "architecture version"); |
| } |
| |
| void HexagonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, |
| int SPAdj, unsigned FIOperandNum, |
| RegScavenger *RS) const { |
| // |
| // Hexagon_TODO: Do we need to enforce this for Hexagon? |
| assert(SPAdj == 0 && "Unexpected"); |
| |
| MachineInstr &MI = *II; |
| int FrameIndex = MI.getOperand(FIOperandNum).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(FIOperandNum).ChangeToRegister(getStackRegister(), false, |
| false, true); |
| MI.getOperand(FIOperandNum + 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) || |
| (MI.getOpcode() == Hexagon::LDriw_f) || |
| (MI.getOpcode() == Hexagon::LDrid_f)) { |
| unsigned dstReg = (MI.getOpcode() == Hexagon::LDrid) ? |
| getSubReg(MI.getOperand(0).getReg(), Hexagon::subreg_loreg) : |
| 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(FIOperandNum).ChangeToRegister(dstReg, false, false,true); |
| MI.getOperand(FIOperandNum+1).ChangeToImmediate(0); |
| } else if ((MI.getOpcode() == Hexagon::STriw_indexed) || |
| (MI.getOpcode() == Hexagon::STriw) || |
| (MI.getOpcode() == Hexagon::STrid) || |
| (MI.getOpcode() == Hexagon::STrih) || |
| (MI.getOpcode() == Hexagon::STrib) || |
| (MI.getOpcode() == Hexagon::STrid_f) || |
| (MI.getOpcode() == Hexagon::STriw_f)) { |
| // 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(FIOperandNum).ChangeToRegister(resReg, false, false,true); |
| MI.getOperand(FIOperandNum+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(FIOperandNum).ChangeToRegister(getStackRegister(), |
| false, false, true); |
| MI.getOperand(FIOperandNum+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(FIOperandNum).ChangeToRegister(resReg, false, false, |
| true); |
| MI.getOperand(FIOperandNum+1).ChangeToImmediate(0); |
| } else { |
| BuildMI(*MI.getParent(), II, MI.getDebugLoc(), |
| TII.get(Hexagon::ADD_ri), |
| resReg).addReg(FrameReg).addImm(Offset); |
| MI.getOperand(FIOperandNum).ChangeToRegister(resReg, false, false, |
| true); |
| MI.getOperand(FIOperandNum+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(FIOperandNum).ChangeToRegister(dstReg, false, false,true); |
| MI.getOperand(FIOperandNum+1).ChangeToImmediate(0); |
| } |
| } else { |
| // If the offset is small enough to fit in the immediate field, directly |
| // encode it. |
| MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false); |
| MI.getOperand(FIOperandNum+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 { |
| llvm_unreachable("What is the exception register"); |
| } |
| |
| unsigned HexagonRegisterInfo::getEHHandlerRegister() const { |
| llvm_unreachable("What is the exception handler register"); |
| } |
| |
| #define GET_REGINFO_TARGET_DESC |
| #include "HexagonGenRegisterInfo.inc" |