10b57cec5SDimitry Andric //===-- ARMBaseRegisterInfo.h - ARM Register Information Impl ---*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file contains the base ARM implementation of TargetRegisterInfo class. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_ARM_ARMBASEREGISTERINFO_H 140b57cec5SDimitry Andric #define LLVM_LIB_TARGET_ARM_ARMBASEREGISTERINFO_H 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #include "MCTargetDesc/ARMBaseInfo.h" 170b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 180b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 190b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h" 200b57cec5SDimitry Andric #include "llvm/IR/CallingConv.h" 210b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 220b57cec5SDimitry Andric #include <cstdint> 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric #define GET_REGINFO_HEADER 250b57cec5SDimitry Andric #include "ARMGenRegisterInfo.inc" 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric namespace llvm { 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric class LiveIntervals; 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric /// Register allocation hints. 320b57cec5SDimitry Andric namespace ARMRI { 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric enum { 35e8d8bef9SDimitry Andric // Used for LDRD register pairs 360b57cec5SDimitry Andric RegPairOdd = 1, 37e8d8bef9SDimitry Andric RegPairEven = 2, 38e8d8bef9SDimitry Andric // Used to hint for lr in t2DoLoopStart 39e8d8bef9SDimitry Andric RegLR = 3 400b57cec5SDimitry Andric }; 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric } // end namespace ARMRI 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric /// isARMArea1Register - Returns true if the register is a low register (r0-r7) 450b57cec5SDimitry Andric /// or a stack/pc register that we should push/pop. 4681ad6265SDimitry Andric static inline bool isARMArea1Register(unsigned Reg, bool SplitFramePushPop) { 470b57cec5SDimitry Andric using namespace ARM; 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric switch (Reg) { 500b57cec5SDimitry Andric case R0: case R1: case R2: case R3: 510b57cec5SDimitry Andric case R4: case R5: case R6: case R7: 520b57cec5SDimitry Andric case LR: case SP: case PC: 530b57cec5SDimitry Andric return true; 540b57cec5SDimitry Andric case R8: case R9: case R10: case R11: case R12: 550b57cec5SDimitry Andric // For iOS we want r7 and lr to be next to each other. 5681ad6265SDimitry Andric return !SplitFramePushPop; 570b57cec5SDimitry Andric default: 580b57cec5SDimitry Andric return false; 590b57cec5SDimitry Andric } 600b57cec5SDimitry Andric } 610b57cec5SDimitry Andric 6281ad6265SDimitry Andric static inline bool isARMArea2Register(unsigned Reg, bool SplitFramePushPop) { 630b57cec5SDimitry Andric using namespace ARM; 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric switch (Reg) { 660b57cec5SDimitry Andric case R8: case R9: case R10: case R11: case R12: 670b57cec5SDimitry Andric // iOS has this second area. 6881ad6265SDimitry Andric return SplitFramePushPop; 690b57cec5SDimitry Andric default: 700b57cec5SDimitry Andric return false; 710b57cec5SDimitry Andric } 720b57cec5SDimitry Andric } 730b57cec5SDimitry Andric 7481ad6265SDimitry Andric static inline bool isSplitFPArea1Register(unsigned Reg, 7581ad6265SDimitry Andric bool SplitFramePushPop) { 7681ad6265SDimitry Andric using namespace ARM; 7781ad6265SDimitry Andric 7881ad6265SDimitry Andric switch (Reg) { 7981ad6265SDimitry Andric case R0: case R1: case R2: case R3: 8081ad6265SDimitry Andric case R4: case R5: case R6: case R7: 8181ad6265SDimitry Andric case R8: case R9: case R10: case R12: 8281ad6265SDimitry Andric case SP: case PC: 8381ad6265SDimitry Andric return true; 8481ad6265SDimitry Andric default: 8581ad6265SDimitry Andric return false; 8681ad6265SDimitry Andric } 8781ad6265SDimitry Andric } 8881ad6265SDimitry Andric 8981ad6265SDimitry Andric static inline bool isSplitFPArea2Register(unsigned Reg, 9081ad6265SDimitry Andric bool SplitFramePushPop) { 9181ad6265SDimitry Andric using namespace ARM; 9281ad6265SDimitry Andric 9381ad6265SDimitry Andric switch (Reg) { 9481ad6265SDimitry Andric case R11: case LR: 9581ad6265SDimitry Andric return true; 9681ad6265SDimitry Andric default: 9781ad6265SDimitry Andric return false; 9881ad6265SDimitry Andric } 9981ad6265SDimitry Andric } 10081ad6265SDimitry Andric 10181ad6265SDimitry Andric static inline bool isARMArea3Register(unsigned Reg, bool SplitFramePushPop) { 1020b57cec5SDimitry Andric using namespace ARM; 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric switch (Reg) { 1050b57cec5SDimitry Andric case D15: case D14: case D13: case D12: 1060b57cec5SDimitry Andric case D11: case D10: case D9: case D8: 1070b57cec5SDimitry Andric case D7: case D6: case D5: case D4: 1080b57cec5SDimitry Andric case D3: case D2: case D1: case D0: 1090b57cec5SDimitry Andric case D31: case D30: case D29: case D28: 1100b57cec5SDimitry Andric case D27: case D26: case D25: case D24: 1110b57cec5SDimitry Andric case D23: case D22: case D21: case D20: 1120b57cec5SDimitry Andric case D19: case D18: case D17: case D16: 1130b57cec5SDimitry Andric return true; 1140b57cec5SDimitry Andric default: 1150b57cec5SDimitry Andric return false; 1160b57cec5SDimitry Andric } 1170b57cec5SDimitry Andric } 1180b57cec5SDimitry Andric 1190b57cec5SDimitry Andric static inline bool isCalleeSavedRegister(unsigned Reg, 1200b57cec5SDimitry Andric const MCPhysReg *CSRegs) { 1210b57cec5SDimitry Andric for (unsigned i = 0; CSRegs[i]; ++i) 1220b57cec5SDimitry Andric if (Reg == CSRegs[i]) 1230b57cec5SDimitry Andric return true; 1240b57cec5SDimitry Andric return false; 1250b57cec5SDimitry Andric } 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric class ARMBaseRegisterInfo : public ARMGenRegisterInfo { 1280b57cec5SDimitry Andric protected: 1290b57cec5SDimitry Andric /// BasePtr - ARM physical register used as a base ptr in complex stack 1300b57cec5SDimitry Andric /// frames. I.e., when we need a 3rd base, not just SP and FP, due to 1310b57cec5SDimitry Andric /// variable size stack objects. 1320b57cec5SDimitry Andric unsigned BasePtr = ARM::R6; 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric // Can be only subclassed. 1350b57cec5SDimitry Andric explicit ARMBaseRegisterInfo(); 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric public: 1380b57cec5SDimitry Andric /// Code Generation virtual methods... 1390b57cec5SDimitry Andric const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override; 1400b57cec5SDimitry Andric const MCPhysReg * 1410b57cec5SDimitry Andric getCalleeSavedRegsViaCopy(const MachineFunction *MF) const; 1420b57cec5SDimitry Andric const uint32_t *getCallPreservedMask(const MachineFunction &MF, 1430b57cec5SDimitry Andric CallingConv::ID) const override; 1440b57cec5SDimitry Andric const uint32_t *getNoPreservedMask() const override; 1450b57cec5SDimitry Andric const uint32_t *getTLSCallPreservedMask(const MachineFunction &MF) const; 1460b57cec5SDimitry Andric const uint32_t *getSjLjDispatchPreservedMask(const MachineFunction &MF) const; 1470b57cec5SDimitry Andric 1480b57cec5SDimitry Andric /// getThisReturnPreservedMask - Returns a call preserved mask specific to the 1490b57cec5SDimitry Andric /// case that 'returned' is on an i32 first argument if the calling convention 1500b57cec5SDimitry Andric /// is one that can (partially) model this attribute with a preserved mask 1510b57cec5SDimitry Andric /// (i.e. it is a calling convention that uses the same register for the first 1520b57cec5SDimitry Andric /// i32 argument and an i32 return value) 1530b57cec5SDimitry Andric /// 1540b57cec5SDimitry Andric /// Should return NULL in the case that the calling convention does not have 1550b57cec5SDimitry Andric /// this property 1560b57cec5SDimitry Andric const uint32_t *getThisReturnPreservedMask(const MachineFunction &MF, 1570b57cec5SDimitry Andric CallingConv::ID) const; 1580b57cec5SDimitry Andric 1598bcb0991SDimitry Andric ArrayRef<MCPhysReg> 1608bcb0991SDimitry Andric getIntraCallClobberedRegs(const MachineFunction *MF) const override; 1618bcb0991SDimitry Andric 1620b57cec5SDimitry Andric BitVector getReservedRegs(const MachineFunction &MF) const override; 1630b57cec5SDimitry Andric bool isAsmClobberable(const MachineFunction &MF, 1645ffd83dbSDimitry Andric MCRegister PhysReg) const override; 1655ffd83dbSDimitry Andric bool isInlineAsmReadOnlyReg(const MachineFunction &MF, 1660b57cec5SDimitry Andric unsigned PhysReg) const override; 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric const TargetRegisterClass * 1690b57cec5SDimitry Andric getPointerRegClass(const MachineFunction &MF, 1700b57cec5SDimitry Andric unsigned Kind = 0) const override; 1710b57cec5SDimitry Andric const TargetRegisterClass * 1720b57cec5SDimitry Andric getCrossCopyRegClass(const TargetRegisterClass *RC) const override; 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric const TargetRegisterClass * 1750b57cec5SDimitry Andric getLargestLegalSuperClass(const TargetRegisterClass *RC, 1760b57cec5SDimitry Andric const MachineFunction &MF) const override; 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric unsigned getRegPressureLimit(const TargetRegisterClass *RC, 1790b57cec5SDimitry Andric MachineFunction &MF) const override; 1800b57cec5SDimitry Andric 1815ffd83dbSDimitry Andric bool getRegAllocationHints(Register VirtReg, ArrayRef<MCPhysReg> Order, 1820b57cec5SDimitry Andric SmallVectorImpl<MCPhysReg> &Hints, 1835ffd83dbSDimitry Andric const MachineFunction &MF, const VirtRegMap *VRM, 1840b57cec5SDimitry Andric const LiveRegMatrix *Matrix) const override; 1850b57cec5SDimitry Andric 1865ffd83dbSDimitry Andric void updateRegAllocHint(Register Reg, Register NewReg, 1870b57cec5SDimitry Andric MachineFunction &MF) const override; 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andric bool hasBasePointer(const MachineFunction &MF) const; 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric bool canRealignStack(const MachineFunction &MF) const override; 1920b57cec5SDimitry Andric int64_t getFrameIndexInstrOffset(const MachineInstr *MI, 1930b57cec5SDimitry Andric int Idx) const override; 1940b57cec5SDimitry Andric bool needsFrameBaseReg(MachineInstr *MI, int64_t Offset) const override; 195e8d8bef9SDimitry Andric Register materializeFrameBaseRegister(MachineBasicBlock *MBB, int FrameIdx, 1960b57cec5SDimitry Andric int64_t Offset) const override; 1975ffd83dbSDimitry Andric void resolveFrameIndex(MachineInstr &MI, Register BaseReg, 1980b57cec5SDimitry Andric int64_t Offset) const override; 1995ffd83dbSDimitry Andric bool isFrameOffsetLegal(const MachineInstr *MI, Register BaseReg, 2000b57cec5SDimitry Andric int64_t Offset) const override; 2010b57cec5SDimitry Andric 2020b57cec5SDimitry Andric bool cannotEliminateFrame(const MachineFunction &MF) const; 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric // Debug information queries. 2050b57cec5SDimitry Andric Register getFrameRegister(const MachineFunction &MF) const override; 2065ffd83dbSDimitry Andric Register getBaseRegister() const { return BasePtr; } 2070b57cec5SDimitry Andric 2080b57cec5SDimitry Andric /// emitLoadConstPool - Emits a load from constpool to materialize the 2090b57cec5SDimitry Andric /// specified immediate. 2100b57cec5SDimitry Andric virtual void 2110b57cec5SDimitry Andric emitLoadConstPool(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, 2125ffd83dbSDimitry Andric const DebugLoc &dl, Register DestReg, unsigned SubIdx, 2130b57cec5SDimitry Andric int Val, ARMCC::CondCodes Pred = ARMCC::AL, 2145ffd83dbSDimitry Andric Register PredReg = Register(), 2150b57cec5SDimitry Andric unsigned MIFlags = MachineInstr::NoFlags) const; 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric /// Code Generation virtual methods... 2180b57cec5SDimitry Andric bool requiresRegisterScavenging(const MachineFunction &MF) const override; 2190b57cec5SDimitry Andric 2200b57cec5SDimitry Andric bool requiresFrameIndexScavenging(const MachineFunction &MF) const override; 2210b57cec5SDimitry Andric 2220b57cec5SDimitry Andric bool requiresVirtualBaseRegisters(const MachineFunction &MF) const override; 2230b57cec5SDimitry Andric 224bdd1243dSDimitry Andric bool eliminateFrameIndex(MachineBasicBlock::iterator II, 2250b57cec5SDimitry Andric int SPAdj, unsigned FIOperandNum, 2260b57cec5SDimitry Andric RegScavenger *RS = nullptr) const override; 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric /// SrcRC and DstRC will be morphed into NewRC if this returns true 2290b57cec5SDimitry Andric bool shouldCoalesce(MachineInstr *MI, 2300b57cec5SDimitry Andric const TargetRegisterClass *SrcRC, 2310b57cec5SDimitry Andric unsigned SubReg, 2320b57cec5SDimitry Andric const TargetRegisterClass *DstRC, 2330b57cec5SDimitry Andric unsigned DstSubReg, 2340b57cec5SDimitry Andric const TargetRegisterClass *NewRC, 2350b57cec5SDimitry Andric LiveIntervals &LIS) const override; 236fe6060f1SDimitry Andric 237fe6060f1SDimitry Andric bool shouldRewriteCopySrc(const TargetRegisterClass *DefRC, 238fe6060f1SDimitry Andric unsigned DefSubReg, 239fe6060f1SDimitry Andric const TargetRegisterClass *SrcRC, 240fe6060f1SDimitry Andric unsigned SrcSubReg) const override; 24181ad6265SDimitry Andric 24281ad6265SDimitry Andric int getSEHRegNum(unsigned i) const { return getEncodingValue(i); } 243*0fca6ea1SDimitry Andric 244*0fca6ea1SDimitry Andric const TargetRegisterClass * 245*0fca6ea1SDimitry Andric getLargestSuperClass(const TargetRegisterClass *RC) const override { 246*0fca6ea1SDimitry Andric if (ARM::MQPRRegClass.hasSubClassEq(RC)) 247*0fca6ea1SDimitry Andric return &ARM::MQPRRegClass; 248*0fca6ea1SDimitry Andric if (ARM::SPRRegClass.hasSubClassEq(RC)) 249*0fca6ea1SDimitry Andric return &ARM::SPRRegClass; 250*0fca6ea1SDimitry Andric if (ARM::DPR_VFP2RegClass.hasSubClassEq(RC)) 251*0fca6ea1SDimitry Andric return &ARM::DPR_VFP2RegClass; 252*0fca6ea1SDimitry Andric if (ARM::GPRRegClass.hasSubClassEq(RC)) 253*0fca6ea1SDimitry Andric return &ARM::GPRRegClass; 254*0fca6ea1SDimitry Andric return RC; 255*0fca6ea1SDimitry Andric } 256*0fca6ea1SDimitry Andric 257*0fca6ea1SDimitry Andric bool doesRegClassHavePseudoInitUndef( 258*0fca6ea1SDimitry Andric const TargetRegisterClass *RC) const override { 259*0fca6ea1SDimitry Andric (void)RC; 260*0fca6ea1SDimitry Andric // For the ARM Architecture we want to always return true because all 261*0fca6ea1SDimitry Andric // required PseudoInitUndef types have been added. If compilation fails due 262*0fca6ea1SDimitry Andric // to `Unexpected register class`, this is likely to be because the specific 263*0fca6ea1SDimitry Andric // register being used is not support by Init Undef and needs the Pseudo 264*0fca6ea1SDimitry Andric // Instruction adding to ARMInstrInfo.td. If this is implemented as a 265*0fca6ea1SDimitry Andric // conditional check, this could create a false positive where Init Undef is 266*0fca6ea1SDimitry Andric // not running, skipping the instruction and moving to the next. This could 267*0fca6ea1SDimitry Andric // lead to illegal instructions being generated by the register allocator. 268*0fca6ea1SDimitry Andric return true; 269*0fca6ea1SDimitry Andric } 2700b57cec5SDimitry Andric }; 2710b57cec5SDimitry Andric 2720b57cec5SDimitry Andric } // end namespace llvm 2730b57cec5SDimitry Andric 2740b57cec5SDimitry Andric #endif // LLVM_LIB_TARGET_ARM_ARMBASEREGISTERINFO_H 275