//===-- 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/PseudoSourceValue.h" #include "llvm/CodeGen/RegisterScavenging.h" #include "llvm/IR/Function.h" #include "llvm/IR/Type.h" #include "llvm/MC/MachineLocation.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" using namespace llvm; HexagonRegisterInfo::HexagonRegisterInfo() : HexagonGenRegisterInfo(Hexagon::R31) {} bool HexagonRegisterInfo::isEHReturnCalleeSaveReg(unsigned R) const { return R == Hexagon::R0 || R == Hexagon::R1 || R == Hexagon::R2 || R == Hexagon::R3 || R == Hexagon::D0 || R == Hexagon::D1; } bool HexagonRegisterInfo::isCalleeSaveReg(unsigned Reg) const { return Hexagon::R16 <= Reg && Reg <= Hexagon::R27; } const MCPhysReg * HexagonRegisterInfo::getCallerSavedRegs(const MachineFunction *MF, const TargetRegisterClass *RC) const { using namespace Hexagon; static const MCPhysReg Int32[] = { R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, 0 }; static const MCPhysReg Int64[] = { D0, D1, D2, D3, D4, D5, D6, D7, 0 }; static const MCPhysReg Pred[] = { P0, P1, P2, P3, 0 }; static const MCPhysReg VecSgl[] = { V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30, V31, 0 }; static const MCPhysReg VecDbl[] = { W0, W1, W2, W3, W4, W5, W6, W7, W8, W9, W10, W11, W12, W13, W14, W15, 0 }; switch (RC->getID()) { case IntRegsRegClassID: return Int32; case DoubleRegsRegClassID: return Int64; case PredRegsRegClassID: return Pred; case VectorRegsRegClassID: case VectorRegs128BRegClassID: return VecSgl; case VecDblRegsRegClassID: case VecDblRegs128BRegClassID: return VecDbl; default: break; } static const MCPhysReg Empty[] = { 0 }; #ifndef NDEBUG dbgs() << "Register class: " << getRegClassName(RC) << "\n"; #endif llvm_unreachable("Unexpected register class"); return Empty; } const MCPhysReg * HexagonRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { static const MCPhysReg 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 }; // Functions that contain a call to __builtin_eh_return also save the first 4 // parameter registers. static const MCPhysReg CalleeSavedRegsV3EHReturn[] = { Hexagon::R0, Hexagon::R1, Hexagon::R2, Hexagon::R3, 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 }; bool HasEHReturn = MF->getInfo<HexagonMachineFunctionInfo>()->hasEHReturn(); switch (MF->getSubtarget<HexagonSubtarget>().getHexagonArchVersion()) { case HexagonSubtarget::V4: case HexagonSubtarget::V5: case HexagonSubtarget::V55: case HexagonSubtarget::V60: return HasEHReturn ? CalleeSavedRegsV3EHReturn : CalleeSavedRegsV3; } llvm_unreachable("Callee saved registers requested for unknown architecture " "version"); } BitVector HexagonRegisterInfo::getReservedRegs(const MachineFunction &MF) const { BitVector Reserved(getNumRegs()); Reserved.set(Hexagon::R29); Reserved.set(Hexagon::R30); Reserved.set(Hexagon::R31); Reserved.set(Hexagon::PC); Reserved.set(Hexagon::D14); Reserved.set(Hexagon::D15); Reserved.set(Hexagon::LC0); Reserved.set(Hexagon::LC1); Reserved.set(Hexagon::SA0); Reserved.set(Hexagon::SA1); Reserved.set(Hexagon::UGP); Reserved.set(Hexagon::GP); Reserved.set(Hexagon::CS0); Reserved.set(Hexagon::CS1); Reserved.set(Hexagon::CS); return Reserved; } void HexagonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, unsigned FIOp, RegScavenger *RS) const { // // Hexagon_TODO: Do we need to enforce this for Hexagon? assert(SPAdj == 0 && "Unexpected"); MachineInstr &MI = *II; MachineBasicBlock &MB = *MI.getParent(); MachineFunction &MF = *MB.getParent(); auto &HST = MF.getSubtarget<HexagonSubtarget>(); auto &HII = *HST.getInstrInfo(); auto &HFI = *HST.getFrameLowering(); unsigned BP = 0; int FI = MI.getOperand(FIOp).getIndex(); // Select the base pointer (BP) and calculate the actual offset from BP // to the beginning of the object at index FI. int Offset = HFI.getFrameIndexReference(MF, FI, BP); // Add the offset from the instruction. int RealOffset = Offset + MI.getOperand(FIOp+1).getImm(); bool IsKill = false; unsigned Opc = MI.getOpcode(); switch (Opc) { case Hexagon::TFR_FIA: MI.setDesc(HII.get(Hexagon::A2_addi)); MI.getOperand(FIOp).ChangeToImmediate(RealOffset); MI.RemoveOperand(FIOp+1); return; case Hexagon::TFR_FI: // Set up the instruction for updating below. MI.setDesc(HII.get(Hexagon::A2_addi)); break; } if (!HII.isValidOffset(Opc, RealOffset)) { // If the offset is not valid, calculate the address in a temporary // register and use it with offset 0. auto &MRI = MF.getRegInfo(); unsigned TmpR = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass); const DebugLoc &DL = MI.getDebugLoc(); BuildMI(MB, II, DL, HII.get(Hexagon::A2_addi), TmpR) .addReg(BP) .addImm(RealOffset); BP = TmpR; RealOffset = 0; IsKill = true; } MI.getOperand(FIOp).ChangeToRegister(BP, false, false, IsKill); MI.getOperand(FIOp+1).ChangeToImmediate(RealOffset); } unsigned HexagonRegisterInfo::getRARegister() const { return Hexagon::R31; } unsigned HexagonRegisterInfo::getFrameRegister(const MachineFunction &MF) const { const HexagonFrameLowering *TFI = getFrameLowering(MF); if (TFI->hasFP(MF)) return getFrameRegister(); return getStackRegister(); } unsigned HexagonRegisterInfo::getFrameRegister() const { return Hexagon::R30; } unsigned HexagonRegisterInfo::getStackRegister() const { return Hexagon::R29; } bool HexagonRegisterInfo::useFPForScavengingIndex(const MachineFunction &MF) const { return MF.getSubtarget<HexagonSubtarget>().getFrameLowering()->hasFP(MF); } unsigned HexagonRegisterInfo::getFirstCallerSavedNonParamReg() const { return Hexagon::R6; } #define GET_REGINFO_TARGET_DESC #include "HexagonGenRegisterInfo.inc"