diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -15845,7 +15845,7 @@ // TODO: Support fixed vectors up to XLen for P extension? if (VT.isVector()) break; - return std::make_pair(0U, &RISCV::GPRRegClass); + return std::make_pair(0U, &RISCV::GPRNoX0RegClass); case 'f': if (Subtarget.hasStdExtZfhOrZfhmin() && VT == MVT::f16) return std::make_pair(0U, &RISCV::FPR16RegClass); diff --git a/llvm/test/CodeGen/RISCV/inline-asm.ll b/llvm/test/CodeGen/RISCV/inline-asm.ll --- a/llvm/test/CodeGen/RISCV/inline-asm.ll +++ b/llvm/test/CodeGen/RISCV/inline-asm.ll @@ -29,6 +29,33 @@ ret i32 %2 } +; Don't allow 'x0' for 'r'. Some instructions have a different behavior when +; x0 is encoded. +define i32 @constraint_r_zero(i32 %a) nounwind { +; RV32I-LABEL: constraint_r_zero: +; RV32I: # %bb.0: +; RV32I-NEXT: lui a0, %hi(gi) +; RV32I-NEXT: lw a0, %lo(gi)(a0) +; RV32I-NEXT: li a1, 0 +; RV32I-NEXT: #APP +; RV32I-NEXT: add a0, a1, a0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: constraint_r_zero: +; RV64I: # %bb.0: +; RV64I-NEXT: lui a0, %hi(gi) +; RV64I-NEXT: lw a0, %lo(gi)(a0) +; RV64I-NEXT: li a1, 0 +; RV64I-NEXT: #APP +; RV64I-NEXT: add a0, a1, a0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret + %1 = load i32, ptr @gi + %2 = tail call i32 asm "add $0, $1, $2", "=r,r,r"(i32 0, i32 %1) + ret i32 %2 +} + define i32 @constraint_i(i32 %a) nounwind { ; RV32I-LABEL: constraint_i: ; RV32I: # %bb.0: