diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index fbd2f47d27690..3588ef46cadce 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -20392,12 +20392,24 @@ RISCVTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass); return std::make_pair(0U, &RISCV::GPRNoX0RegClass); case 'f': - if (Subtarget.hasStdExtZfhmin() && VT == MVT::f16) - return std::make_pair(0U, &RISCV::FPR16RegClass); - if (Subtarget.hasStdExtF() && VT == MVT::f32) - return std::make_pair(0U, &RISCV::FPR32RegClass); - if (Subtarget.hasStdExtD() && VT == MVT::f64) - return std::make_pair(0U, &RISCV::FPR64RegClass); + if (VT == MVT::f16) { + if (Subtarget.hasStdExtZfhmin()) + return std::make_pair(0U, &RISCV::FPR16RegClass); + if (Subtarget.hasStdExtZhinxmin()) + return std::make_pair(0U, &RISCV::GPRF16NoX0RegClass); + } else if (VT == MVT::f32) { + if (Subtarget.hasStdExtF()) + return std::make_pair(0U, &RISCV::FPR32RegClass); + if (Subtarget.hasStdExtZfinx()) + return std::make_pair(0U, &RISCV::GPRF32NoX0RegClass); + } else if (VT == MVT::f64) { + if (Subtarget.hasStdExtD()) + return std::make_pair(0U, &RISCV::FPR64RegClass); + if (Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit()) + return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass); + if (Subtarget.hasStdExtZdinx() && Subtarget.is64Bit()) + return std::make_pair(0U, &RISCV::GPRNoX0RegClass); + } break; default: break; @@ -20440,12 +20452,24 @@ RISCVTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, if (!VT.isVector()) return std::make_pair(0U, &RISCV::GPRCRegClass); } else if (Constraint == "cf") { - if (Subtarget.hasStdExtZfhmin() && VT == MVT::f16) - return std::make_pair(0U, &RISCV::FPR16CRegClass); - if (Subtarget.hasStdExtF() && VT == MVT::f32) - return std::make_pair(0U, &RISCV::FPR32CRegClass); - if (Subtarget.hasStdExtD() && VT == MVT::f64) - return std::make_pair(0U, &RISCV::FPR64CRegClass); + if (VT == MVT::f16) { + if (Subtarget.hasStdExtZfhmin()) + return std::make_pair(0U, &RISCV::FPR16CRegClass); + if (Subtarget.hasStdExtZhinxmin()) + return std::make_pair(0U, &RISCV::GPRF16CRegClass); + } else if (VT == MVT::f32) { + if (Subtarget.hasStdExtF()) + return std::make_pair(0U, &RISCV::FPR32CRegClass); + if (Subtarget.hasStdExtZfinx()) + return std::make_pair(0U, &RISCV::GPRF32CRegClass); + } else if (VT == MVT::f64) { + if (Subtarget.hasStdExtD()) + return std::make_pair(0U, &RISCV::FPR64CRegClass); + if (Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit()) + return std::make_pair(0U, &RISCV::GPRPairCRegClass); + if (Subtarget.hasStdExtZdinx() && Subtarget.is64Bit()) + return std::make_pair(0U, &RISCV::GPRCRegClass); + } } // Clang will correctly decode the usage of register name aliases into their diff --git a/llvm/test/CodeGen/RISCV/inline-asm-zdinx-constraint-r.ll b/llvm/test/CodeGen/RISCV/inline-asm-zdinx-constraint-r.ll index 15729ee2bc61e..57be0e5e4199a 100644 --- a/llvm/test/CodeGen/RISCV/inline-asm-zdinx-constraint-r.ll +++ b/llvm/test/CodeGen/RISCV/inline-asm-zdinx-constraint-r.ll @@ -90,3 +90,51 @@ define double @constraint_double_abi_name(double %a) nounwind { %2 = tail call double asm "fadd.d $0, $1, $2", "={t1},{a0},{s0}"(double %a, double %1) ret double %2 } + +define double @constraint_f_double(double %a) nounwind { +; RV32FINX-LABEL: constraint_f_double: +; RV32FINX: # %bb.0: +; RV32FINX-NEXT: lui a2, %hi(gd) +; RV32FINX-NEXT: lw a3, %lo(gd+4)(a2) +; RV32FINX-NEXT: lw a2, %lo(gd)(a2) +; RV32FINX-NEXT: #APP +; RV32FINX-NEXT: fadd.d a0, a0, a2 +; RV32FINX-NEXT: #NO_APP +; RV32FINX-NEXT: ret +; +; RV64FINX-LABEL: constraint_f_double: +; RV64FINX: # %bb.0: +; RV64FINX-NEXT: lui a1, %hi(gd) +; RV64FINX-NEXT: ld a1, %lo(gd)(a1) +; RV64FINX-NEXT: #APP +; RV64FINX-NEXT: fadd.d a0, a0, a1 +; RV64FINX-NEXT: #NO_APP +; RV64FINX-NEXT: ret + %1 = load double, ptr @gd + %2 = tail call double asm "fadd.d $0, $1, $2", "=f,f,f"(double %a, double %1) + ret double %2 +} + +define double @constraint_cf_double(double %a) nounwind { +; RV32FINX-LABEL: constraint_cf_double: +; RV32FINX: # %bb.0: +; RV32FINX-NEXT: lui a2, %hi(gd) +; RV32FINX-NEXT: lw a3, %lo(gd+4)(a2) +; RV32FINX-NEXT: lw a2, %lo(gd)(a2) +; RV32FINX-NEXT: #APP +; RV32FINX-NEXT: fadd.d a0, a0, a2 +; RV32FINX-NEXT: #NO_APP +; RV32FINX-NEXT: ret +; +; RV64FINX-LABEL: constraint_cf_double: +; RV64FINX: # %bb.0: +; RV64FINX-NEXT: lui a1, %hi(gd) +; RV64FINX-NEXT: ld a1, %lo(gd)(a1) +; RV64FINX-NEXT: #APP +; RV64FINX-NEXT: fadd.d a0, a0, a1 +; RV64FINX-NEXT: #NO_APP +; RV64FINX-NEXT: ret + %1 = load double, ptr @gd + %2 = tail call double asm "fadd.d $0, $1, $2", "=^cf,^cf,^cf"(double %a, double %1) + ret double %2 +} diff --git a/llvm/test/CodeGen/RISCV/inline-asm-zfinx-constraint-r.ll b/llvm/test/CodeGen/RISCV/inline-asm-zfinx-constraint-r.ll index a8d3515fe1890..1c0de6c3f1612 100644 --- a/llvm/test/CodeGen/RISCV/inline-asm-zfinx-constraint-r.ll +++ b/llvm/test/CodeGen/RISCV/inline-asm-zfinx-constraint-r.ll @@ -87,3 +87,48 @@ define float @constraint_float_abi_name(float %a) nounwind { ret float %2 } +define float @constraint_f_float(float %a) nounwind { +; RV32FINX-LABEL: constraint_f_float: +; RV32FINX: # %bb.0: +; RV32FINX-NEXT: lui a1, %hi(gf) +; RV32FINX-NEXT: lw a1, %lo(gf)(a1) +; RV32FINX-NEXT: #APP +; RV32FINX-NEXT: fadd.s a0, a0, a1 +; RV32FINX-NEXT: #NO_APP +; RV32FINX-NEXT: ret +; +; RV64FINX-LABEL: constraint_f_float: +; RV64FINX: # %bb.0: +; RV64FINX-NEXT: lui a1, %hi(gf) +; RV64FINX-NEXT: lw a1, %lo(gf)(a1) +; RV64FINX-NEXT: #APP +; RV64FINX-NEXT: fadd.s a0, a0, a1 +; RV64FINX-NEXT: #NO_APP +; RV64FINX-NEXT: ret + %1 = load float, ptr @gf + %2 = tail call float asm "fadd.s $0, $1, $2", "=f,f,f"(float %a, float %1) + ret float %2 +} + +define float @constraint_cf_float(float %a) nounwind { +; RV32FINX-LABEL: constraint_cf_float: +; RV32FINX: # %bb.0: +; RV32FINX-NEXT: lui a1, %hi(gf) +; RV32FINX-NEXT: lw a1, %lo(gf)(a1) +; RV32FINX-NEXT: #APP +; RV32FINX-NEXT: fadd.s a0, a0, a1 +; RV32FINX-NEXT: #NO_APP +; RV32FINX-NEXT: ret +; +; RV64FINX-LABEL: constraint_cf_float: +; RV64FINX: # %bb.0: +; RV64FINX-NEXT: lui a1, %hi(gf) +; RV64FINX-NEXT: lw a1, %lo(gf)(a1) +; RV64FINX-NEXT: #APP +; RV64FINX-NEXT: fadd.s a0, a0, a1 +; RV64FINX-NEXT: #NO_APP +; RV64FINX-NEXT: ret + %1 = load float, ptr @gf + %2 = tail call float asm "fadd.s $0, $1, $2", "=^cf,cf,cf"(float %a, float %1) + ret float %2 +} diff --git a/llvm/test/CodeGen/RISCV/inline-asm-zhinx-constraint-r.ll b/llvm/test/CodeGen/RISCV/inline-asm-zhinx-constraint-r.ll index f9707c6c8995d..086d2a1d6f3b2 100644 --- a/llvm/test/CodeGen/RISCV/inline-asm-zhinx-constraint-r.ll +++ b/llvm/test/CodeGen/RISCV/inline-asm-zhinx-constraint-r.ll @@ -156,3 +156,85 @@ define half @constraint_half_abi_name(half %a) nounwind { %2 = tail call half asm "fadd.s $0, $1, $2", "={t0},{a0},{s0}"(half %a, half %1) ret half %2 } + +define half @constraint_f_half(half %a) nounwind { +; RV32ZHINX-LABEL: constraint_f_half: +; RV32ZHINX: # %bb.0: +; RV32ZHINX-NEXT: lui a1, %hi(gh) +; RV32ZHINX-NEXT: lh a1, %lo(gh)(a1) +; RV32ZHINX-NEXT: #APP +; RV32ZHINX-NEXT: fadd.h a0, a0, a1 +; RV32ZHINX-NEXT: #NO_APP +; RV32ZHINX-NEXT: ret +; +; RV64ZHINX-LABEL: constraint_f_half: +; RV64ZHINX: # %bb.0: +; RV64ZHINX-NEXT: lui a1, %hi(gh) +; RV64ZHINX-NEXT: lh a1, %lo(gh)(a1) +; RV64ZHINX-NEXT: #APP +; RV64ZHINX-NEXT: fadd.h a0, a0, a1 +; RV64ZHINX-NEXT: #NO_APP +; RV64ZHINX-NEXT: ret +; +; RV32DINXZHINX-LABEL: constraint_f_half: +; RV32DINXZHINX: # %bb.0: +; RV32DINXZHINX-NEXT: lui a1, %hi(gh) +; RV32DINXZHINX-NEXT: lh a1, %lo(gh)(a1) +; RV32DINXZHINX-NEXT: #APP +; RV32DINXZHINX-NEXT: fadd.h a0, a0, a1 +; RV32DINXZHINX-NEXT: #NO_APP +; RV32DINXZHINX-NEXT: ret +; +; RV64DINXZHINX-LABEL: constraint_f_half: +; RV64DINXZHINX: # %bb.0: +; RV64DINXZHINX-NEXT: lui a1, %hi(gh) +; RV64DINXZHINX-NEXT: lh a1, %lo(gh)(a1) +; RV64DINXZHINX-NEXT: #APP +; RV64DINXZHINX-NEXT: fadd.h a0, a0, a1 +; RV64DINXZHINX-NEXT: #NO_APP +; RV64DINXZHINX-NEXT: ret + %1 = load half, ptr @gh + %2 = tail call half asm "fadd.h $0, $1, $2", "=f,f,f"(half %a, half %1) + ret half %2 +} + +define half @constraint_cf_half(half %a) nounwind { +; RV32ZHINX-LABEL: constraint_cf_half: +; RV32ZHINX: # %bb.0: +; RV32ZHINX-NEXT: lui a1, %hi(gh) +; RV32ZHINX-NEXT: lh a1, %lo(gh)(a1) +; RV32ZHINX-NEXT: #APP +; RV32ZHINX-NEXT: fadd.h a0, a0, a1 +; RV32ZHINX-NEXT: #NO_APP +; RV32ZHINX-NEXT: ret +; +; RV64ZHINX-LABEL: constraint_cf_half: +; RV64ZHINX: # %bb.0: +; RV64ZHINX-NEXT: lui a1, %hi(gh) +; RV64ZHINX-NEXT: lh a1, %lo(gh)(a1) +; RV64ZHINX-NEXT: #APP +; RV64ZHINX-NEXT: fadd.h a0, a0, a1 +; RV64ZHINX-NEXT: #NO_APP +; RV64ZHINX-NEXT: ret +; +; RV32DINXZHINX-LABEL: constraint_cf_half: +; RV32DINXZHINX: # %bb.0: +; RV32DINXZHINX-NEXT: lui a1, %hi(gh) +; RV32DINXZHINX-NEXT: lh a1, %lo(gh)(a1) +; RV32DINXZHINX-NEXT: #APP +; RV32DINXZHINX-NEXT: fadd.h a0, a0, a1 +; RV32DINXZHINX-NEXT: #NO_APP +; RV32DINXZHINX-NEXT: ret +; +; RV64DINXZHINX-LABEL: constraint_cf_half: +; RV64DINXZHINX: # %bb.0: +; RV64DINXZHINX-NEXT: lui a1, %hi(gh) +; RV64DINXZHINX-NEXT: lh a1, %lo(gh)(a1) +; RV64DINXZHINX-NEXT: #APP +; RV64DINXZHINX-NEXT: fadd.h a0, a0, a1 +; RV64DINXZHINX-NEXT: #NO_APP +; RV64DINXZHINX-NEXT: ret + %1 = load half, ptr @gh + %2 = tail call half asm "fadd.h $0, $1, $2", "=^cf,^cf,^cf"(half %a, half %1) + ret half %2 +}