diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp @@ -103,6 +103,10 @@ 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 --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td @@ -535,8 +535,23 @@ 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("X"#Index); defvar RegP1 = !cast("X"#!add(Index,1));