[AArch64] Add an option to reserve physical registers from RA
authorGuozhi Wei <carrot@google.com>
Tue, 6 Sep 2022 17:18:01 +0000 (17:18 +0000)
committerGuozhi Wei <carrot@google.com>
Tue, 6 Sep 2022 17:18:01 +0000 (17:18 +0000)
This patch adds an option --reserve-regs-for-regalloc, so we can reserve a list
of physical registers. These registers will not be used by register allocator,
but can still be used as ABI requests such as passing arguments to function
call.

Its main purpose is simulating high register pressure by reserving many physical
registers. So it will be much easier to test and debug register allocation
changes.

Differential Revision: https://reviews.llvm.org/D132717

llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
llvm/lib/Target/AArch64/AArch64RegisterInfo.h
llvm/lib/Target/AArch64/AArch64Subtarget.cpp
llvm/lib/Target/AArch64/AArch64Subtarget.h
llvm/test/CodeGen/AArch64/arm64-platform-reg.ll

index 7a0c7d0..c50471b 100644 (file)
@@ -309,7 +309,7 @@ const uint32_t *AArch64RegisterInfo::getWindowsStackProbePreservedMask() const {
 }
 
 BitVector
-AArch64RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
+AArch64RegisterInfo::getStrictlyReservedRegs(const MachineFunction &MF) const {
   const AArch64FrameLowering *TFI = getFrameLowering(MF);
 
   // FIXME: avoid re-calculating this every time.
@@ -355,14 +355,32 @@ AArch64RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
   return Reserved;
 }
 
+BitVector
+AArch64RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
+  BitVector Reserved = getStrictlyReservedRegs(MF);
+
+  for (size_t i = 0; i < AArch64::GPR32commonRegClass.getNumRegs(); ++i) {
+    if (MF.getSubtarget<AArch64Subtarget>().isXRegisterReservedForRA(i))
+      markSuperRegs(Reserved, AArch64::GPR32commonRegClass.getRegister(i));
+  }
+
+  assert(checkAllSuperRegsMarked(Reserved));
+  return Reserved;
+}
+
 bool AArch64RegisterInfo::isReservedReg(const MachineFunction &MF,
                                         MCRegister Reg) const {
   return getReservedRegs(MF)[Reg];
 }
 
+bool AArch64RegisterInfo::isStrictlyReservedReg(const MachineFunction &MF,
+                                                MCRegister Reg) const {
+  return getStrictlyReservedRegs(MF)[Reg];
+}
+
 bool AArch64RegisterInfo::isAnyArgRegReserved(const MachineFunction &MF) const {
   return llvm::any_of(*AArch64::GPR64argRegClass.MC, [this, &MF](MCPhysReg r) {
-    return isReservedReg(MF, r);
+    return isStrictlyReservedReg(MF, r);
   });
 }
 
index 91a5af1..9c27c34 100644 (file)
@@ -35,6 +35,7 @@ public:
   }
 
   bool isReservedReg(const MachineFunction &MF, MCRegister Reg) const;
+  bool isStrictlyReservedReg(const MachineFunction &MF, MCRegister Reg) const;
   bool isAnyArgRegReserved(const MachineFunction &MF) const;
   void emitReservedArgRegCallError(const MachineFunction &MF) const;
 
@@ -88,6 +89,7 @@ public:
   /// Stack probing calls preserve different CSRs to the normal CC.
   const uint32_t *getWindowsStackProbePreservedMask() const;
 
+  BitVector getStrictlyReservedRegs(const MachineFunction &MF) const;
   BitVector getReservedRegs(const MachineFunction &MF) const override;
   bool isAsmClobberable(const MachineFunction &MF,
                        MCRegister PhysReg) const override;
index 1500530..af7fb7a 100644 (file)
@@ -56,6 +56,15 @@ static cl::opt<unsigned> OverrideVectorInsertExtractBaseCost(
     "aarch64-insert-extract-base-cost",
     cl::desc("Base cost of vector insert/extract element"), cl::Hidden);
 
+// Reserve a list of X# registers, so they are unavailable for register
+// allocator, but can still be used as ABI requests, such as passing arguments
+// to function call.
+static cl::list<std::string>
+ReservedRegsForRA("reserve-regs-for-regalloc", cl::desc("Reserve physical "
+                  "registers, so they can't be used by register allocator. "
+                  "Should only be used for testing register allocator."),
+                  cl::CommaSeparated, cl::Hidden);
+
 unsigned AArch64Subtarget::getVectorInsertExtractBaseCost() const {
   if (OverrideVectorInsertExtractBaseCost.getNumOccurrences() > 0)
     return OverrideVectorInsertExtractBaseCost;
@@ -265,6 +274,7 @@ AArch64Subtarget::AArch64Subtarget(const Triple &TT, const std::string &CPU,
                                    unsigned MaxSVEVectorSizeInBitsOverride)
     : AArch64GenSubtargetInfo(TT, CPU, TuneCPU, FS),
       ReserveXRegister(AArch64::GPR64commonRegClass.getNumRegs()),
+      ReserveXRegisterForRA(AArch64::GPR64commonRegClass.getNumRegs()),
       CustomCallSavedXRegs(AArch64::GPR64commonRegClass.getNumRegs()),
       IsLittle(LittleEndian),
       MinSVEVectorSizeInBits(MinSVEVectorSizeInBitsOverride),
@@ -287,6 +297,14 @@ AArch64Subtarget::AArch64Subtarget(const Triple &TT, const std::string &CPU,
       *static_cast<const AArch64TargetMachine *>(&TM), *this, *RBI));
 
   RegBankInfo.reset(RBI);
+
+  auto TRI = getRegisterInfo();
+  StringSet<> ReservedRegNames;
+  ReservedRegNames.insert(ReservedRegsForRA.begin(), ReservedRegsForRA.end());
+  for (unsigned i = 0; i < 31; ++i) {
+    if (ReservedRegNames.count(TRI->getName(AArch64::X0 + i)))
+      ReserveXRegisterForRA.set(i);
+  }
 }
 
 const CallLowering *AArch64Subtarget::getCallLowering() const {
index 7296e14..81dcaaf 100644 (file)
@@ -110,6 +110,9 @@ protected:
   // ReserveXRegister[i] - X#i is not available as a general purpose register.
   BitVector ReserveXRegister;
 
+  // ReserveXRegisterForRA[i] - X#i is not available for register allocator.
+  BitVector ReserveXRegisterForRA;
+
   // CustomCallUsedXRegister[i] - X#i call saved.
   BitVector CustomCallSavedXRegs;
 
@@ -196,7 +199,13 @@ public:
   }
 
   bool isXRegisterReserved(size_t i) const { return ReserveXRegister[i]; }
-  unsigned getNumXRegisterReserved() const { return ReserveXRegister.count(); }
+  bool isXRegisterReservedForRA(size_t i) const { return ReserveXRegisterForRA[i]; }
+  unsigned getNumXRegisterReserved() const {
+    BitVector AllReservedX(AArch64::GPR64commonRegClass.getNumRegs());
+    AllReservedX |= ReserveXRegister;
+    AllReservedX |= ReserveXRegisterForRA;
+    return AllReservedX.count();
+  }
   bool isXRegCustomCalleeSaved(size_t i) const {
     return CustomCallSavedXRegs[i];
   }
index 89fc645..95f46b7 100644 (file)
@@ -13,6 +13,7 @@
 ; RUN: llc -mtriple=arm64-linux-gnu -mattr=+reserve-x5 -o - %s | FileCheck %s --check-prefixes=CHECK-RESERVE,CHECK-RESERVE-X5
 ; RUN: llc -mtriple=arm64-linux-gnu -mattr=+reserve-x6 -o - %s | FileCheck %s --check-prefixes=CHECK-RESERVE,CHECK-RESERVE-X6
 ; RUN: llc -mtriple=arm64-linux-gnu -mattr=+reserve-x7 -o - %s | FileCheck %s --check-prefixes=CHECK-RESERVE,CHECK-RESERVE-X7
+; RUN: llc -mtriple=arm64-linux-gnu -reserve-regs-for-regalloc=X8 -o - %s | FileCheck %s --check-prefixes=CHECK-RESERVE,CHECK-RESERVE-X8
 ; RUN: llc -mtriple=arm64-linux-gnu -mattr=+reserve-x9 -o - %s | FileCheck %s --check-prefixes=CHECK-RESERVE,CHECK-RESERVE-X9
 ; RUN: llc -mtriple=arm64-linux-gnu -mattr=+reserve-x10 -o - %s | FileCheck %s --check-prefixes=CHECK-RESERVE,CHECK-RESERVE-X10
 ; RUN: llc -mtriple=arm64-linux-gnu -mattr=+reserve-x11 -o - %s | FileCheck %s --check-prefixes=CHECK-RESERVE,CHECK-RESERVE-X11
@@ -20,6 +21,9 @@
 ; RUN: llc -mtriple=arm64-linux-gnu -mattr=+reserve-x13 -o - %s | FileCheck %s --check-prefixes=CHECK-RESERVE,CHECK-RESERVE-X13
 ; RUN: llc -mtriple=arm64-linux-gnu -mattr=+reserve-x14 -o - %s | FileCheck %s --check-prefixes=CHECK-RESERVE,CHECK-RESERVE-X14
 ; RUN: llc -mtriple=arm64-linux-gnu -mattr=+reserve-x15 -o - %s | FileCheck %s --check-prefixes=CHECK-RESERVE,CHECK-RESERVE-X15
+; RUN: llc -mtriple=arm64-linux-gnu -reserve-regs-for-regalloc=X16 -o - %s | FileCheck %s --check-prefixes=CHECK-RESERVE,CHECK-RESERVE-X16
+; RUN: llc -mtriple=arm64-linux-gnu -reserve-regs-for-regalloc=X17 -o - %s | FileCheck %s --check-prefixes=CHECK-RESERVE,CHECK-RESERVE-X17
+; RUN: llc -mtriple=arm64-linux-gnu -reserve-regs-for-regalloc=X19 -o - %s | FileCheck %s --check-prefixes=CHECK-RESERVE,CHECK-RESERVE-X19
 ; RUN: llc -mtriple=arm64-linux-gnu -mattr=+reserve-x20 -o - %s | FileCheck %s --check-prefixes=CHECK-RESERVE,CHECK-RESERVE-X20
 ; RUN: llc -mtriple=arm64-linux-gnu -mattr=+reserve-x21 -o - %s | FileCheck %s --check-prefixes=CHECK-RESERVE,CHECK-RESERVE-X21
 ; RUN: llc -mtriple=arm64-linux-gnu -mattr=+reserve-x22 -o - %s | FileCheck %s --check-prefixes=CHECK-RESERVE,CHECK-RESERVE-X22
@@ -69,6 +73,7 @@
 ; RUN: -mattr=+reserve-x27 \
 ; RUN: -mattr=+reserve-x28 \
 ; RUN: -mattr=+reserve-x30 \
+; RUN: -reserve-regs-for-regalloc=X8,X16,X17,X19 \
 ; RUN: -o - %s | FileCheck %s \
 ; RUN: --check-prefix=CHECK-RESERVE \
 ; RUN: --check-prefix=CHECK-RESERVE-X1 \
@@ -78,6 +83,7 @@
 ; RUN: --check-prefix=CHECK-RESERVE-X5 \
 ; RUN: --check-prefix=CHECK-RESERVE-X6 \
 ; RUN: --check-prefix=CHECK-RESERVE-X7 \
+; RUN: --check-prefix=CHECK-RESERVE-X8 \
 ; RUN: --check-prefix=CHECK-RESERVE-X9 \
 ; RUN: --check-prefix=CHECK-RESERVE-X10 \
 ; RUN: --check-prefix=CHECK-RESERVE-X11 \
 ; RUN: --check-prefix=CHECK-RESERVE-X13 \
 ; RUN: --check-prefix=CHECK-RESERVE-X14 \
 ; RUN: --check-prefix=CHECK-RESERVE-X15 \
+; RUN: --check-prefix=CHECK-RESERVE-X16 \
+; RUN: --check-prefix=CHECK-RESERVE-X17 \
 ; RUN: --check-prefix=CHECK-RESERVE-X18 \
+; RUN: --check-prefix=CHECK-RESERVE-X19 \
 ; RUN: --check-prefix=CHECK-RESERVE-X20 \
 ; RUN: --check-prefix=CHECK-RESERVE-X21 \
 ; RUN: --check-prefix=CHECK-RESERVE-X22 \
@@ -113,6 +122,8 @@ define void @keep_live() {
 ; CHECK: str x18
 
 ; CHECK-RESERVE-NOT: ldr fp
+; CHECK-RESERVE-X8-NOT: adrp x8
+; CHECK-RESERVE-X8-NOT: ldr x8
 ; CHECK-RESERVE-X1-NOT: ldr x1,
 ; CHECK-RESERVE-X2-NOT: ldr x2,
 ; CHECK-RESERVE-X3-NOT: ldr x3,
@@ -127,7 +138,10 @@ define void @keep_live() {
 ; CHECK-RESERVE-X13-NOT: ldr x13,
 ; CHECK-RESERVE-X14-NOT: ldr x14,
 ; CHECK-RESERVE-X15-NOT: ldr x15,
+; CHECK-RESERVE-X16-NOT: ldr x16
+; CHECK-RESERVE-X17-NOT: ldr x17
 ; CHECK-RESERVE-X18-NOT: ldr x18
+; CHECK-RESERVE-X19-NOT: ldr x19
 ; CHECK-RESERVE-X20-NOT: ldr x20
 ; CHECK-RESERVE-X21-NOT: ldr x21
 ; CHECK-RESERVE-X22-NOT: ldr x22
@@ -154,7 +168,10 @@ define void @keep_live() {
 ; CHECK-RESERVE-X13-NOT: ldr x13,
 ; CHECK-RESERVE-X14-NOT: ldr x14,
 ; CHECK-RESERVE-X15-NOT: ldr x15,
+; CHECK-RESERVE-X16-NOT: ldr x16
+; CHECK-RESERVE-X17-NOT: ldr x17
 ; CHECK-RESERVE-X18-NOT: ldr x18
+; CHECK-RESERVE-X19-NOT: ldr x19
 ; CHECK-RESERVE-X20-NOT: ldr x20
 ; CHECK-RESERVE-X21-NOT: ldr x21
 ; CHECK-RESERVE-X22-NOT: ldr x22