From 03dcd88c781d06f917750f3a7f6df9ac7f7f67d9 Mon Sep 17 00:00:00 2001 From: Sam Elliott Date: Fri, 18 Oct 2024 22:33:35 +0100 Subject: [PATCH] [RISCV][ISel] Ensure 'in X' Constraints prevent X0 (#112563) I'm not sure if this fix is required, but I've written the patch anyway. This does not cause test changes, but we haven't got tests that try to use all 32 registers in inline assembly. Broadly, for GPRs, we made the explicit choice that `r` constraints would never attempt to use `x0`, because `x0` isn't really usable like the other GPRs. I believe the same thing applies to `Zhinx`, `Zfinx` and `Zdinx` because they should not be allocating operands to `x0` either, so this patch introduces new `NoX0` classes for `GPRF16` and `GPRF32` registers, and uses them with inline assembly. There is also a `GPRPairNoX0` for the `Zdinx` case on rv32, avoiding use of the `x0` pair which has different behaviour to the other GPR pairs. --- llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 6 +++--- llvm/lib/Target/RISCV/RISCVRegisterInfo.td | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 60ac58f824ede4..fbd2f47d276903 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -20385,11 +20385,11 @@ RISCVTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, if (VT.isVector()) break; if (VT == MVT::f16 && Subtarget.hasStdExtZhinxmin()) - return std::make_pair(0U, &RISCV::GPRF16RegClass); + return std::make_pair(0U, &RISCV::GPRF16NoX0RegClass); if (VT == MVT::f32 && Subtarget.hasStdExtZfinx()) - return std::make_pair(0U, &RISCV::GPRF32RegClass); + return std::make_pair(0U, &RISCV::GPRF32NoX0RegClass); if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit()) - return std::make_pair(0U, &RISCV::GPRPairRegClass); + return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass); return std::make_pair(0U, &RISCV::GPRNoX0RegClass); case 'f': if (Subtarget.hasStdExtZfhmin() && VT == MVT::f16) diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td index 250f3c10f309bf..685f04213afa86 100644 --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td @@ -661,6 +661,7 @@ def GPRF16 : RISCVRegisterClass<[f16], 16, (add (sequence "X%u_H", 10, 17), (sequence "X%u_H", 0, 4))>; def GPRF16C : RISCVRegisterClass<[f16], 16, (add (sequence "X%u_H", 10, 15), (sequence "X%u_H", 8, 9))>; +def GPRF16NoX0 : RISCVRegisterClass<[f16], 16, (sub GPRF16, X0_H)>; def GPRF32 : RISCVRegisterClass<[f32], 32, (add (sequence "X%u_W", 10, 17), (sequence "X%u_W", 5, 7), @@ -721,6 +722,8 @@ def GPRPair : RISCVRegisterClass<[XLenPairFVT], 64, (add def GPRPairC : RISCVRegisterClass<[XLenPairFVT], 64, (add X10_X11, X12_X13, X14_X15, X8_X9 )>; + +def GPRPairNoX0 : RISCVRegisterClass<[XLenPairFVT], 64, (sub GPRPair, X0_Pair)>; } // let RegInfos = XLenPairRI, DecoderMethod = "DecodeGPRPairRegisterClass" // The register class is added for inline assembly for vector mask types.