xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/ARM/ARMBaseRegisterInfo.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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