[llvm] 48a749e - [RISCV] Don't include X1 in the X0_PD register pair

Alex Bradbury via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 20 05:49:20 PDT 2023


Author: Alex Bradbury
Date: 2023-07-20T13:48:15+01:00
New Revision: 48a749e26e6fc8596b31602b2696b91547246dcb

URL: https://github.com/llvm/llvm-project/commit/48a749e26e6fc8596b31602b2696b91547246dcb
DIFF: https://github.com/llvm/llvm-project/commit/48a749e26e6fc8596b31602b2696b91547246dcb.diff

LOG: [RISCV] Don't include X1 in the X0_PD register pair

Zdinx on RV32 defines the D instructions as taking even register pairs,
and specifies that if using X0 when as a destination then X1 won't be
written, and if using X0 as a source then the value is still all 0s
(i.e. X1 isn't read). Therefore, it's incorrect to model X0_PD as having
X1 as a subregister. This will also be the case for register pairs in
Zacas and the P extension (and this patch takes the same approach as
D95588 does).

This patch introduces a dummy register that is solely used as a subreg
alongside X0 in X0_PD. An earlier version of the patch had a minor
effect on register allocation in some tests, which is now avoided by:
1) Adding RISCV::DUMMY_REG_PAIR_WITH_X0 to RISCVRegisterInfo::getReservedRegs
2) Defining a new register class that includes DUMMY_REG_PAIR_WITH_X0

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

Added: 
    

Modified: 
    llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
    llvm/lib/Target/RISCV/RISCVRegisterInfo.td

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
index 8c7c5a2382de45..c3ba4c1e7fdb73 100644
--- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
@@ -103,6 +103,10 @@ BitVector RISCVRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
   if (TFI->hasBP(MF))
     markSuperRegs(Reserved, RISCVABI::getBPReg()); // bp
 
+  // Additionally reserve dummy register used to form the register pair
+  // beginning with 'x0' for instructions that take register pairs.
+  markSuperRegs(Reserved, RISCV::DUMMY_REG_PAIR_WITH_X0);
+
   // V registers for code generation. We handle them manually.
   markSuperRegs(Reserved, RISCV::VL);
   markSuperRegs(Reserved, RISCV::VTYPE);

diff  --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td
index 81212487e700bd..0b17f54431efad 100644
--- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td
@@ -535,8 +535,23 @@ def GPRF16  : RegisterClass<"RISCV", [f16], 16, (add GPR)>;
 def GPRF32  : RegisterClass<"RISCV", [f32], 32, (add GPR)>;
 } // RegInfos = XLenRI
 
+// Dummy zero register for use in the register pair containing X0 (as X1 is
+// not read to or written when the X0 register pair is used).
+def DUMMY_REG_PAIR_WITH_X0 : RISCVReg<0, "0">;
+
+// Must add DUMMY_REG_PAIR_WITH_X0 to a separate register class to prevent the
+// register's existence from changing codegen (due to the regPressureSetLimit
+// for the GPR register class being altered).
+def GPRAll : GPRRegisterClass<(add GPR, DUMMY_REG_PAIR_WITH_X0)>;
+
 let RegAltNameIndices = [ABIRegAltName] in {
-  foreach I = 0-15 in {
+  def X0_PD : RISCVRegWithSubRegs<0, X0.AsmName,
+                                     [X0, DUMMY_REG_PAIR_WITH_X0],
+                                     X0.AltNames> {
+    let SubRegIndices = [sub_32, sub_32_hi];
+    let CoveredBySubRegs = 1;
+  }
+  foreach I = 1-15 in {
     defvar Index = !shl(I, 1);
     defvar Reg = !cast<Register>("X"#Index);
     defvar RegP1 = !cast<Register>("X"#!add(Index,1));


        


More information about the llvm-commits mailing list