aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp')
-rw-r--r--contrib/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp290
1 files changed, 290 insertions, 0 deletions
diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp
new file mode 100644
index 000000000000..1fc157900ed5
--- /dev/null
+++ b/contrib/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp
@@ -0,0 +1,290 @@
+//===-- 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"
+
+#define GET_REGINFO_TARGET_DESC
+#include "HexagonGenRegisterInfo.inc"
+
+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;
+}
+
+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:
+ case HexagonSubtarget::V62:
+ return HasEHReturn ? CalleeSavedRegsV3EHReturn : CalleeSavedRegsV3;
+ }
+
+ llvm_unreachable("Callee saved registers requested for unknown architecture "
+ "version");
+}
+
+
+const uint32_t *HexagonRegisterInfo::getCallPreservedMask(
+ const MachineFunction &MF, CallingConv::ID) const {
+ return HexagonCSR_RegMask;
+}
+
+
+BitVector HexagonRegisterInfo::getReservedRegs(const MachineFunction &MF)
+ const {
+ BitVector Reserved(getNumRegs());
+ Reserved.set(Hexagon::R29);
+ Reserved.set(Hexagon::R30);
+ Reserved.set(Hexagon::R31);
+ // Control registers.
+ Reserved.set(Hexagon::SA0); // C0
+ Reserved.set(Hexagon::LC0); // C1
+ Reserved.set(Hexagon::SA1); // C2
+ Reserved.set(Hexagon::LC1); // C3
+ Reserved.set(Hexagon::P3_0); // C4
+ Reserved.set(Hexagon::USR); // C8
+ Reserved.set(Hexagon::PC); // C9
+ Reserved.set(Hexagon::UGP); // C10
+ Reserved.set(Hexagon::GP); // C11
+ Reserved.set(Hexagon::CS0); // C12
+ Reserved.set(Hexagon::CS1); // C13
+ Reserved.set(Hexagon::UPCYCLELO); // C14
+ Reserved.set(Hexagon::UPCYCLEHI); // C15
+ Reserved.set(Hexagon::FRAMELIMIT); // C16
+ Reserved.set(Hexagon::FRAMEKEY); // C17
+ Reserved.set(Hexagon::PKTCOUNTLO); // C18
+ Reserved.set(Hexagon::PKTCOUNTHI); // C19
+ Reserved.set(Hexagon::UTIMERLO); // C30
+ Reserved.set(Hexagon::UTIMERHI); // C31
+ // Out of the control registers, only C8 is explicitly defined in
+ // HexagonRegisterInfo.td. If others are defined, make sure to add
+ // them here as well.
+ Reserved.set(Hexagon::C8);
+ Reserved.set(Hexagon::USR_OVF);
+
+ for (int x = Reserved.find_first(); x >= 0; x = Reserved.find_next(x))
+ markSuperRegs(Reserved, x);
+
+ 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::PS_fia:
+ MI.setDesc(HII.get(Hexagon::A2_addi));
+ MI.getOperand(FIOp).ChangeToImmediate(RealOffset);
+ MI.RemoveOperand(FIOp+1);
+ return;
+ case Hexagon::PS_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;
+}
+
+
+unsigned HexagonRegisterInfo::getHexagonSubRegIndex(
+ const TargetRegisterClass *RC, unsigned GenIdx) const {
+ assert(GenIdx == Hexagon::ps_sub_lo || GenIdx == Hexagon::ps_sub_hi);
+
+ static const unsigned ISub[] = { Hexagon::isub_lo, Hexagon::isub_hi };
+ static const unsigned VSub[] = { Hexagon::vsub_lo, Hexagon::vsub_hi };
+
+ switch (RC->getID()) {
+ case Hexagon::CtrRegs64RegClassID:
+ case Hexagon::DoubleRegsRegClassID:
+ return ISub[GenIdx];
+ case Hexagon::VecDblRegsRegClassID:
+ case Hexagon::VecDblRegs128BRegClassID:
+ return VSub[GenIdx];
+ }
+
+ if (const TargetRegisterClass *SuperRC = *RC->getSuperClasses())
+ return getHexagonSubRegIndex(SuperRC, GenIdx);
+
+ llvm_unreachable("Invalid register class");
+}
+
+bool HexagonRegisterInfo::useFPForScavengingIndex(const MachineFunction &MF)
+ const {
+ return MF.getSubtarget<HexagonSubtarget>().getFrameLowering()->hasFP(MF);
+}
+
+
+unsigned HexagonRegisterInfo::getFirstCallerSavedNonParamReg() const {
+ return Hexagon::R6;
+}
+