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 @@ -2461,45 +2461,89 @@ } } + // Clang will correctly decode the usage of register name aliases into their + // official names. However, other frontends like `rustc` do not. This allows + // users of these frontends to use the ABI names for registers in LLVM-style + // register constraints. + unsigned XRegFromAlias = StringSwitch(Constraint.lower()) + .Case("{zero}", RISCV::X0) + .Case("{ra}", RISCV::X1) + .Case("{sp}", RISCV::X2) + .Case("{gp}", RISCV::X3) + .Case("{tp}", RISCV::X4) + .Case("{t0}", RISCV::X5) + .Case("{t1}", RISCV::X6) + .Case("{t2}", RISCV::X7) + .Cases("{s0}", "{fp}", RISCV::X8) + .Case("{s1}", RISCV::X9) + .Case("{a0}", RISCV::X10) + .Case("{a1}", RISCV::X11) + .Case("{a2}", RISCV::X12) + .Case("{a3}", RISCV::X13) + .Case("{a4}", RISCV::X14) + .Case("{a5}", RISCV::X15) + .Case("{a6}", RISCV::X16) + .Case("{a7}", RISCV::X17) + .Case("{s2}", RISCV::X18) + .Case("{s3}", RISCV::X19) + .Case("{s4}", RISCV::X20) + .Case("{s5}", RISCV::X21) + .Case("{s6}", RISCV::X22) + .Case("{s7}", RISCV::X23) + .Case("{s8}", RISCV::X24) + .Case("{s9}", RISCV::X25) + .Case("{s10}", RISCV::X26) + .Case("{s11}", RISCV::X27) + .Case("{t3}", RISCV::X28) + .Case("{t4}", RISCV::X29) + .Case("{t5}", RISCV::X30) + .Case("{t6}", RISCV::X31) + .Default(RISCV::NoRegister); + if (XRegFromAlias != RISCV::NoRegister) + return std::make_pair(XRegFromAlias, &RISCV::GPRRegClass); + // Since TargetLowering::getRegForInlineAsmConstraint uses the name of the // TableGen record rather than the AsmName to choose registers for InlineAsm // constraints, plus we want to match those names to the widest floating point // register type available, manually select floating point registers here. + // + // The second case is the ABI name of the register, so that frontends can also + // use the ABI names in register constraint lists. if (Subtarget.hasStdExtF() || Subtarget.hasStdExtD()) { std::pair FReg = StringSwitch>(Constraint.lower()) - .Case("{f0}", {RISCV::F0_32, RISCV::F0_64}) - .Case("{f1}", {RISCV::F1_32, RISCV::F1_64}) - .Case("{f2}", {RISCV::F2_32, RISCV::F2_64}) - .Case("{f3}", {RISCV::F3_32, RISCV::F3_64}) - .Case("{f4}", {RISCV::F4_32, RISCV::F4_64}) - .Case("{f5}", {RISCV::F5_32, RISCV::F5_64}) - .Case("{f6}", {RISCV::F6_32, RISCV::F6_64}) - .Case("{f7}", {RISCV::F7_32, RISCV::F7_64}) - .Case("{f8}", {RISCV::F8_32, RISCV::F8_64}) - .Case("{f9}", {RISCV::F9_32, RISCV::F9_64}) - .Case("{f10}", {RISCV::F10_32, RISCV::F10_64}) - .Case("{f11}", {RISCV::F11_32, RISCV::F11_64}) - .Case("{f12}", {RISCV::F12_32, RISCV::F12_64}) - .Case("{f13}", {RISCV::F13_32, RISCV::F13_64}) - .Case("{f14}", {RISCV::F14_32, RISCV::F14_64}) - .Case("{f15}", {RISCV::F15_32, RISCV::F15_64}) - .Case("{f16}", {RISCV::F16_32, RISCV::F16_64}) - .Case("{f17}", {RISCV::F17_32, RISCV::F17_64}) - .Case("{f18}", {RISCV::F18_32, RISCV::F18_64}) - .Case("{f19}", {RISCV::F19_32, RISCV::F19_64}) - .Case("{f20}", {RISCV::F20_32, RISCV::F20_64}) - .Case("{f21}", {RISCV::F21_32, RISCV::F21_64}) - .Case("{f22}", {RISCV::F22_32, RISCV::F22_64}) - .Case("{f23}", {RISCV::F23_32, RISCV::F23_64}) - .Case("{f24}", {RISCV::F24_32, RISCV::F24_64}) - .Case("{f25}", {RISCV::F25_32, RISCV::F25_64}) - .Case("{f26}", {RISCV::F26_32, RISCV::F26_64}) - .Case("{f27}", {RISCV::F27_32, RISCV::F27_64}) - .Case("{f28}", {RISCV::F28_32, RISCV::F28_64}) - .Case("{f29}", {RISCV::F29_32, RISCV::F29_64}) - .Case("{f30}", {RISCV::F30_32, RISCV::F30_64}) - .Case("{f31}", {RISCV::F31_32, RISCV::F31_64}) + .Cases("{f0}", "{ft0}", {RISCV::F0_32, RISCV::F0_64}) + .Cases("{f1}", "{ft1}", {RISCV::F1_32, RISCV::F1_64}) + .Cases("{f2}", "{ft2}", {RISCV::F2_32, RISCV::F2_64}) + .Cases("{f3}", "{ft3}", {RISCV::F3_32, RISCV::F3_64}) + .Cases("{f4}", "{ft4}", {RISCV::F4_32, RISCV::F4_64}) + .Cases("{f5}", "{ft5}", {RISCV::F5_32, RISCV::F5_64}) + .Cases("{f6}", "{ft6}", {RISCV::F6_32, RISCV::F6_64}) + .Cases("{f7}", "{ft7}", {RISCV::F7_32, RISCV::F7_64}) + .Cases("{f8}", "{fs0}", {RISCV::F8_32, RISCV::F8_64}) + .Cases("{f9}", "{fs1}", {RISCV::F9_32, RISCV::F9_64}) + .Cases("{f10}", "{fa0}", {RISCV::F10_32, RISCV::F10_64}) + .Cases("{f11}", "{fa1}", {RISCV::F11_32, RISCV::F11_64}) + .Cases("{f12}", "{fa2}", {RISCV::F12_32, RISCV::F12_64}) + .Cases("{f13}", "{fa3}", {RISCV::F13_32, RISCV::F13_64}) + .Cases("{f14}", "{fa4}", {RISCV::F14_32, RISCV::F14_64}) + .Cases("{f15}", "{fa5}", {RISCV::F15_32, RISCV::F15_64}) + .Cases("{f16}", "{fa6}", {RISCV::F16_32, RISCV::F16_64}) + .Cases("{f17}", "{fa7}", {RISCV::F17_32, RISCV::F17_64}) + .Cases("{f18}", "{fs2}", {RISCV::F18_32, RISCV::F18_64}) + .Cases("{f19}", "{fs3}", {RISCV::F19_32, RISCV::F19_64}) + .Cases("{f20}", "{fs4}", {RISCV::F20_32, RISCV::F20_64}) + .Cases("{f21}", "{fs5}", {RISCV::F21_32, RISCV::F21_64}) + .Cases("{f22}", "{fs6}", {RISCV::F22_32, RISCV::F22_64}) + .Cases("{f23}", "{fs7}", {RISCV::F23_32, RISCV::F23_64}) + .Cases("{f24}", "{fs8}", {RISCV::F24_32, RISCV::F24_64}) + .Cases("{f25}", "{fs9}", {RISCV::F25_32, RISCV::F25_64}) + .Cases("{f26}", "{fs10}", {RISCV::F26_32, RISCV::F26_64}) + .Cases("{f27}", "{fs11}", {RISCV::F27_32, RISCV::F27_64}) + .Cases("{f28}", "{ft8}", {RISCV::F28_32, RISCV::F28_64}) + .Cases("{f29}", "{ft9}", {RISCV::F29_32, RISCV::F29_64}) + .Cases("{f30}", "{ft10}", {RISCV::F30_32, RISCV::F30_64}) + .Cases("{f31}", "{ft11}", {RISCV::F31_32, RISCV::F31_64}) .Default({-1U, -1U}); if (FReg.first != -1U) return Subtarget.hasStdExtD() diff --git a/llvm/test/CodeGen/RISCV/inline-asm-abi-names.ll b/llvm/test/CodeGen/RISCV/inline-asm-abi-names.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/inline-asm-abi-names.ll @@ -0,0 +1,1591 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=RV32I %s +; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=RV64I %s + +; These test that we can use both the architectural names (x*) and the ABI names +; (a*, s*, t* etc) to refer to registers in inline asm constraint lists. In each +; case, the named register should be used for the source register of the `addi`. +; It is very likely that `a0` will be chosen as the designation register, but +; this is left to the compiler to choose. +; +; The inline assembly will, by default, contain the ABI names for the registers. +; +; Parenthesised registers in comments are the other aliases for this register. + +; NOTE: This test has to pass in 0 to the inline asm, because that's the only +; value `x0` (`zero`) can take. +define i32 @explicit_register_x0() nounwind { +; RV32I-LABEL: explicit_register_x0: +; RV32I: # %bb.0: +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, zero, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_x0: +; RV64I: # %bb.0: +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, zero, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{x0}"(i32 0) + ret i32 %1 +} + +; NOTE: This test has to pass in 0 to the inline asm, because that's the only +; value that `zero` (`x0`) can take. +define i32 @explicit_register_zero() nounwind { +; RV32I-LABEL: explicit_register_zero: +; RV32I: # %bb.0: +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, zero, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_zero: +; RV64I: # %bb.0: +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, zero, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{zero}"(i32 0) + ret i32 %1 +} + +; NOTE: This test uses `x1` (`ra`) as an input, so it should be saved. +define i32 @explicit_register_x1(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_x1: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv ra, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, ra, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_x1: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd ra, 8(sp) +; RV64I-NEXT: mv ra, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, ra, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ld ra, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{x1}"(i32 %a) + ret i32 %1 +} + +; NOTE: This test uses `ra` (`x1`) as an input, so it should be saved. +define i32 @explicit_register_ra(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_ra: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv ra, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, ra, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_ra: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd ra, 8(sp) +; RV64I-NEXT: mv ra, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, ra, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ld ra, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{ra}"(i32 %a) + ret i32 %1 +} + +define i32 @explicit_register_x2(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_x2: +; RV32I: # %bb.0: +; RV32I-NEXT: mv sp, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, sp, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_x2: +; RV64I: # %bb.0: +; RV64I-NEXT: mv sp, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, sp, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{x2}"(i32 %a) + ret i32 %1 +} + +define i32 @explicit_register_sp(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_sp: +; RV32I: # %bb.0: +; RV32I-NEXT: mv sp, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, sp, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_sp: +; RV64I: # %bb.0: +; RV64I-NEXT: mv sp, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, sp, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{sp}"(i32 %a) + ret i32 %1 +} + +; NOTE: This test uses `x3` (`gp`) as an input, so it should be saved. +define i32 @explicit_register_x3(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_x3: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw gp, 12(sp) +; RV32I-NEXT: mv gp, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, gp, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: lw gp, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_x3: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd gp, 8(sp) +; RV64I-NEXT: mv gp, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, gp, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ld gp, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{x3}"(i32 %a) + ret i32 %1 +} + +; NOTE: This test uses `gp` (`x3`) as an input, so it should be saved. +define i32 @explicit_register_gp(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_gp: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw gp, 12(sp) +; RV32I-NEXT: mv gp, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, gp, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: lw gp, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_gp: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd gp, 8(sp) +; RV64I-NEXT: mv gp, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, gp, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ld gp, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{gp}"(i32 %a) + ret i32 %1 +} + +; NOTE: This test uses `x4` (`tp`) as an input, so it should be saved. +define i32 @explicit_register_x4(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_x4: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw tp, 12(sp) +; RV32I-NEXT: mv tp, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, tp, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: lw tp, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_x4: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd tp, 8(sp) +; RV64I-NEXT: mv tp, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, tp, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ld tp, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{x4}"(i32 %a) + ret i32 %1 +} + +; NOTE: This test uses `tp` (`x4`) as an input, so it should be saved. +define i32 @explicit_register_tp(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_tp: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw tp, 12(sp) +; RV32I-NEXT: mv tp, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, tp, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: lw tp, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_tp: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd tp, 8(sp) +; RV64I-NEXT: mv tp, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, tp, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ld tp, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{tp}"(i32 %a) + ret i32 %1 +} + +define i32 @explicit_register_x5(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_x5: +; RV32I: # %bb.0: +; RV32I-NEXT: mv t0, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, t0, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_x5: +; RV64I: # %bb.0: +; RV64I-NEXT: mv t0, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, t0, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{x5}"(i32 %a) + ret i32 %1 +} + +define i32 @explicit_register_t0(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_t0: +; RV32I: # %bb.0: +; RV32I-NEXT: mv t0, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, t0, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_t0: +; RV64I: # %bb.0: +; RV64I-NEXT: mv t0, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, t0, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{t0}"(i32 %a) + ret i32 %1 +} + +define i32 @explicit_register_x6(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_x6: +; RV32I: # %bb.0: +; RV32I-NEXT: mv t1, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, t1, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_x6: +; RV64I: # %bb.0: +; RV64I-NEXT: mv t1, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, t1, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{x6}"(i32 %a) + ret i32 %1 +} + +define i32 @explicit_register_t1(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_t1: +; RV32I: # %bb.0: +; RV32I-NEXT: mv t1, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, t1, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_t1: +; RV64I: # %bb.0: +; RV64I-NEXT: mv t1, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, t1, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{t1}"(i32 %a) + ret i32 %1 +} + +define i32 @explicit_register_x7(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_x7: +; RV32I: # %bb.0: +; RV32I-NEXT: mv t2, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, t2, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_x7: +; RV64I: # %bb.0: +; RV64I-NEXT: mv t2, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, t2, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{x7}"(i32 %a) + ret i32 %1 +} + +define i32 @explicit_register_t2(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_t2: +; RV32I: # %bb.0: +; RV32I-NEXT: mv t2, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, t2, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_t2: +; RV64I: # %bb.0: +; RV64I-NEXT: mv t2, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, t2, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{t2}"(i32 %a) + ret i32 %1 +} + +; NOTE: This test uses `x8` (`s0`, `fp`) as an input, so it should be saved. +define i32 @explicit_register_x8(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_x8: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw s0, 12(sp) +; RV32I-NEXT: mv s0, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, s0, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: lw s0, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_x8: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd s0, 8(sp) +; RV64I-NEXT: mv s0, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, s0, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ld s0, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{x8}"(i32 %a) + ret i32 %1 +} + +; NOTE: This test uses `s0` (`x8`, `fp`) as an input, so it should be saved. +define i32 @explicit_register_s0(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_s0: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw s0, 12(sp) +; RV32I-NEXT: mv s0, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, s0, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: lw s0, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_s0: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd s0, 8(sp) +; RV64I-NEXT: mv s0, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, s0, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ld s0, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{s0}"(i32 %a) + ret i32 %1 +} + +; NOTE: This test uses `fp` (`x8`, `s0`) as an input, so it should be saved. +define i32 @explicit_register_fp(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_fp: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw s0, 12(sp) +; RV32I-NEXT: mv s0, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, s0, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: lw s0, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_fp: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd s0, 8(sp) +; RV64I-NEXT: mv s0, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, s0, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ld s0, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{fp}"(i32 %a) + ret i32 %1 +} + +; NOTE: This test uses `x9` (`s1`) as an input, so it should be saved. +define i32 @explicit_register_x9(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_x9: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw s1, 12(sp) +; RV32I-NEXT: mv s1, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, s1, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: lw s1, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_x9: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd s1, 8(sp) +; RV64I-NEXT: mv s1, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, s1, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ld s1, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{x9}"(i32 %a) + ret i32 %1 +} + +; NOTE: This test uses `s1` (`x9`) as an input, so it should be saved. +define i32 @explicit_register_s1(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_s1: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw s1, 12(sp) +; RV32I-NEXT: mv s1, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, s1, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: lw s1, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_s1: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd s1, 8(sp) +; RV64I-NEXT: mv s1, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, s1, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ld s1, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{s1}"(i32 %a) + ret i32 %1 +} + +define i32 @explicit_register_x10(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_x10: +; RV32I: # %bb.0: +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, a0, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_x10: +; RV64I: # %bb.0: +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, a0, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{x10}"(i32 %a) + ret i32 %1 +} + +define i32 @explicit_register_a0(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_a0: +; RV32I: # %bb.0: +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, a0, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_a0: +; RV64I: # %bb.0: +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, a0, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{a0}"(i32 %a) + ret i32 %1 +} + +define i32 @explicit_register_x11(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_x11: +; RV32I: # %bb.0: +; RV32I-NEXT: mv a1, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, a1, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_x11: +; RV64I: # %bb.0: +; RV64I-NEXT: mv a1, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, a1, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{x11}"(i32 %a) + ret i32 %1 +} + +define i32 @explicit_register_a1(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_a1: +; RV32I: # %bb.0: +; RV32I-NEXT: mv a1, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, a1, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_a1: +; RV64I: # %bb.0: +; RV64I-NEXT: mv a1, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, a1, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{a1}"(i32 %a) + ret i32 %1 +} + +define i32 @explicit_register_x12(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_x12: +; RV32I: # %bb.0: +; RV32I-NEXT: mv a2, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, a2, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_x12: +; RV64I: # %bb.0: +; RV64I-NEXT: mv a2, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, a2, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{x12}"(i32 %a) + ret i32 %1 +} + +define i32 @explicit_register_a2(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_a2: +; RV32I: # %bb.0: +; RV32I-NEXT: mv a2, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, a2, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_a2: +; RV64I: # %bb.0: +; RV64I-NEXT: mv a2, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, a2, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{a2}"(i32 %a) + ret i32 %1 +} + +define i32 @explicit_register_x13(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_x13: +; RV32I: # %bb.0: +; RV32I-NEXT: mv a3, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, a3, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_x13: +; RV64I: # %bb.0: +; RV64I-NEXT: mv a3, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, a3, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{x13}"(i32 %a) + ret i32 %1 +} + +define i32 @explicit_register_a3(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_a3: +; RV32I: # %bb.0: +; RV32I-NEXT: mv a3, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, a3, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_a3: +; RV64I: # %bb.0: +; RV64I-NEXT: mv a3, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, a3, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{a3}"(i32 %a) + ret i32 %1 +} + +define i32 @explicit_register_x14(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_x14: +; RV32I: # %bb.0: +; RV32I-NEXT: mv a4, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, a4, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_x14: +; RV64I: # %bb.0: +; RV64I-NEXT: mv a4, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, a4, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{x14}"(i32 %a) + ret i32 %1 +} + +define i32 @explicit_register_a4(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_a4: +; RV32I: # %bb.0: +; RV32I-NEXT: mv a4, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, a4, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_a4: +; RV64I: # %bb.0: +; RV64I-NEXT: mv a4, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, a4, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{a4}"(i32 %a) + ret i32 %1 +} + +define i32 @explicit_register_x15(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_x15: +; RV32I: # %bb.0: +; RV32I-NEXT: mv a5, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, a5, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_x15: +; RV64I: # %bb.0: +; RV64I-NEXT: mv a5, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, a5, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{x15}"(i32 %a) + ret i32 %1 +} + +define i32 @explicit_register_a5(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_a5: +; RV32I: # %bb.0: +; RV32I-NEXT: mv a5, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, a5, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_a5: +; RV64I: # %bb.0: +; RV64I-NEXT: mv a5, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, a5, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{a5}"(i32 %a) + ret i32 %1 +} + +define i32 @explicit_register_x16(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_x16: +; RV32I: # %bb.0: +; RV32I-NEXT: mv a6, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, a6, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_x16: +; RV64I: # %bb.0: +; RV64I-NEXT: mv a6, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, a6, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{x16}"(i32 %a) + ret i32 %1 +} + +define i32 @explicit_register_a6(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_a6: +; RV32I: # %bb.0: +; RV32I-NEXT: mv a6, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, a6, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_a6: +; RV64I: # %bb.0: +; RV64I-NEXT: mv a6, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, a6, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{a6}"(i32 %a) + ret i32 %1 +} + +define i32 @explicit_register_x17(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_x17: +; RV32I: # %bb.0: +; RV32I-NEXT: mv a7, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, a7, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_x17: +; RV64I: # %bb.0: +; RV64I-NEXT: mv a7, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, a7, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{x17}"(i32 %a) + ret i32 %1 +} + +define i32 @explicit_register_a7(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_a7: +; RV32I: # %bb.0: +; RV32I-NEXT: mv a7, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, a7, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_a7: +; RV64I: # %bb.0: +; RV64I-NEXT: mv a7, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, a7, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{a7}"(i32 %a) + ret i32 %1 +} + +; NOTE: This test uses `x18` (`s2`) as an input, so it should be saved. +define i32 @explicit_register_x18(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_x18: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw s2, 12(sp) +; RV32I-NEXT: mv s2, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, s2, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: lw s2, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_x18: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd s2, 8(sp) +; RV64I-NEXT: mv s2, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, s2, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ld s2, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{x18}"(i32 %a) + ret i32 %1 +} + +; NOTE: This test uses `s2` (`x18`) as an input, so it should be saved. +define i32 @explicit_register_s2(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_s2: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw s2, 12(sp) +; RV32I-NEXT: mv s2, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, s2, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: lw s2, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_s2: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd s2, 8(sp) +; RV64I-NEXT: mv s2, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, s2, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ld s2, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{s2}"(i32 %a) + ret i32 %1 +} + +; NOTE: This test uses `x19` (`s3`) as an input, so it should be saved. +define i32 @explicit_register_x19(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_x19: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw s3, 12(sp) +; RV32I-NEXT: mv s3, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, s3, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: lw s3, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_x19: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd s3, 8(sp) +; RV64I-NEXT: mv s3, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, s3, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ld s3, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{x19}"(i32 %a) + ret i32 %1 +} + +; NOTE: This test uses `s3` (`x19`) as an input, so it should be saved. +define i32 @explicit_register_s3(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_s3: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw s3, 12(sp) +; RV32I-NEXT: mv s3, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, s3, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: lw s3, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_s3: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd s3, 8(sp) +; RV64I-NEXT: mv s3, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, s3, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ld s3, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{s3}"(i32 %a) + ret i32 %1 +} + +; NOTE: This test uses `x20` (`s4`) as an input, so it should be saved. +define i32 @explicit_register_x20(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_x20: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw s4, 12(sp) +; RV32I-NEXT: mv s4, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, s4, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: lw s4, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_x20: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd s4, 8(sp) +; RV64I-NEXT: mv s4, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, s4, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ld s4, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{x20}"(i32 %a) + ret i32 %1 +} + +; NOTE: This test uses `s4` (`x20`) as an input, so it should be saved. +define i32 @explicit_register_s4(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_s4: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw s4, 12(sp) +; RV32I-NEXT: mv s4, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, s4, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: lw s4, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_s4: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd s4, 8(sp) +; RV64I-NEXT: mv s4, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, s4, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ld s4, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{s4}"(i32 %a) + ret i32 %1 +} + +; NOTE: This test uses `x21` (`s5`) as an input, so it should be saved. +define i32 @explicit_register_x21(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_x21: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw s5, 12(sp) +; RV32I-NEXT: mv s5, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, s5, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: lw s5, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_x21: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd s5, 8(sp) +; RV64I-NEXT: mv s5, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, s5, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ld s5, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{x21}"(i32 %a) + ret i32 %1 +} + +; NOTE: This test uses `s5` (`x21`) as an input, so it should be saved. +define i32 @explicit_register_s5(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_s5: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw s5, 12(sp) +; RV32I-NEXT: mv s5, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, s5, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: lw s5, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_s5: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd s5, 8(sp) +; RV64I-NEXT: mv s5, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, s5, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ld s5, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{s5}"(i32 %a) + ret i32 %1 +} + +; NOTE: This test uses `x22` (`s6`) as an input, so it should be saved. +define i32 @explicit_register_x22(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_x22: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw s6, 12(sp) +; RV32I-NEXT: mv s6, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, s6, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: lw s6, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_x22: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd s6, 8(sp) +; RV64I-NEXT: mv s6, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, s6, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ld s6, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{x22}"(i32 %a) + ret i32 %1 +} + +; NOTE: This test uses `s6` (`x22`) as an input, so it should be saved. +define i32 @explicit_register_s6(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_s6: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw s6, 12(sp) +; RV32I-NEXT: mv s6, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, s6, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: lw s6, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_s6: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd s6, 8(sp) +; RV64I-NEXT: mv s6, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, s6, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ld s6, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{s6}"(i32 %a) + ret i32 %1 +} + +; NOTE: This test uses `x23` (`s7`) as an input, so it should be saved. +define i32 @explicit_register_x23(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_x23: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw s7, 12(sp) +; RV32I-NEXT: mv s7, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, s7, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: lw s7, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_x23: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd s7, 8(sp) +; RV64I-NEXT: mv s7, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, s7, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ld s7, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{x23}"(i32 %a) + ret i32 %1 +} + +; NOTE: This test uses `s7` (`x23`) as an input, so it should be saved. +define i32 @explicit_register_s7(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_s7: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw s7, 12(sp) +; RV32I-NEXT: mv s7, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, s7, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: lw s7, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_s7: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd s7, 8(sp) +; RV64I-NEXT: mv s7, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, s7, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ld s7, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{s7}"(i32 %a) + ret i32 %1 +} + +; NOTE: This test uses `x24` (`s8`) as an input, so it should be saved. +define i32 @explicit_register_x24(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_x24: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw s8, 12(sp) +; RV32I-NEXT: mv s8, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, s8, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: lw s8, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_x24: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd s8, 8(sp) +; RV64I-NEXT: mv s8, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, s8, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ld s8, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{x24}"(i32 %a) + ret i32 %1 +} + +; NOTE: This test uses `s8` (`x24`) as an input, so it should be saved. +define i32 @explicit_register_s8(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_s8: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw s8, 12(sp) +; RV32I-NEXT: mv s8, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, s8, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: lw s8, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_s8: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd s8, 8(sp) +; RV64I-NEXT: mv s8, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, s8, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ld s8, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{s8}"(i32 %a) + ret i32 %1 +} + +; NOTE: This test uses `x25` (`s9`) as an input, so it should be saved. +define i32 @explicit_register_x25(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_x25: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw s9, 12(sp) +; RV32I-NEXT: mv s9, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, s9, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: lw s9, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_x25: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd s9, 8(sp) +; RV64I-NEXT: mv s9, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, s9, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ld s9, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{x25}"(i32 %a) + ret i32 %1 +} + +; NOTE: This test uses `s9` (`x25`) as an input, so it should be saved. +define i32 @explicit_register_s9(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_s9: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw s9, 12(sp) +; RV32I-NEXT: mv s9, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, s9, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: lw s9, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_s9: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd s9, 8(sp) +; RV64I-NEXT: mv s9, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, s9, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ld s9, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{s9}"(i32 %a) + ret i32 %1 +} + +; NOTE: This test uses `x26` (`s10`) as an input, so it should be saved. +define i32 @explicit_register_x26(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_x26: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw s10, 12(sp) +; RV32I-NEXT: mv s10, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, s10, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: lw s10, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_x26: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd s10, 8(sp) +; RV64I-NEXT: mv s10, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, s10, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ld s10, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{x26}"(i32 %a) + ret i32 %1 +} + +; NOTE: This test uses `s10` (`x28`) as an input, so it should be saved. +define i32 @explicit_register_s10(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_s10: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw s10, 12(sp) +; RV32I-NEXT: mv s10, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, s10, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: lw s10, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_s10: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd s10, 8(sp) +; RV64I-NEXT: mv s10, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, s10, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ld s10, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{s10}"(i32 %a) + ret i32 %1 +} + +; NOTE: This test uses `x27` (`s11`) as an input, so it should be saved. +define i32 @explicit_register_x27(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_x27: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw s11, 12(sp) +; RV32I-NEXT: mv s11, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, s11, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: lw s11, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_x27: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd s11, 8(sp) +; RV64I-NEXT: mv s11, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, s11, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ld s11, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{x27}"(i32 %a) + ret i32 %1 +} + +; NOTE: This test uses `s11` (`x27`) as an input, so it should be saved. +define i32 @explicit_register_s11(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_s11: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw s11, 12(sp) +; RV32I-NEXT: mv s11, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, s11, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: lw s11, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_s11: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd s11, 8(sp) +; RV64I-NEXT: mv s11, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, s11, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ld s11, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{s11}"(i32 %a) + ret i32 %1 +} + +define i32 @explicit_register_x28(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_x28: +; RV32I: # %bb.0: +; RV32I-NEXT: mv t3, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, t3, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_x28: +; RV64I: # %bb.0: +; RV64I-NEXT: mv t3, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, t3, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{x28}"(i32 %a) + ret i32 %1 +} + +define i32 @explicit_register_t3(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_t3: +; RV32I: # %bb.0: +; RV32I-NEXT: mv t3, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, t3, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_t3: +; RV64I: # %bb.0: +; RV64I-NEXT: mv t3, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, t3, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{t3}"(i32 %a) + ret i32 %1 +} + +define i32 @explicit_register_x29(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_x29: +; RV32I: # %bb.0: +; RV32I-NEXT: mv t4, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, t4, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_x29: +; RV64I: # %bb.0: +; RV64I-NEXT: mv t4, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, t4, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{x29}"(i32 %a) + ret i32 %1 +} + +define i32 @explicit_register_t4(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_t4: +; RV32I: # %bb.0: +; RV32I-NEXT: mv t4, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, t4, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_t4: +; RV64I: # %bb.0: +; RV64I-NEXT: mv t4, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, t4, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{t4}"(i32 %a) + ret i32 %1 +} + +define i32 @explicit_register_x30(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_x30: +; RV32I: # %bb.0: +; RV32I-NEXT: mv t5, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, t5, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_x30: +; RV64I: # %bb.0: +; RV64I-NEXT: mv t5, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, t5, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{x30}"(i32 %a) + ret i32 %1 +} + +define i32 @explicit_register_t5(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_t5: +; RV32I: # %bb.0: +; RV32I-NEXT: mv t5, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, t5, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_t5: +; RV64I: # %bb.0: +; RV64I-NEXT: mv t5, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, t5, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{t5}"(i32 %a) + ret i32 %1 +} + +define i32 @explicit_register_x31(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_x31: +; RV32I: # %bb.0: +; RV32I-NEXT: mv t6, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, t6, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_x31: +; RV64I: # %bb.0: +; RV64I-NEXT: mv t6, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, t6, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{x31}"(i32 %a) + ret i32 %1 +} + +define i32 @explicit_register_t6(i32 %a) nounwind { +; RV32I-LABEL: explicit_register_t6: +; RV32I: # %bb.0: +; RV32I-NEXT: mv t6, a0 +; RV32I-NEXT: #APP +; RV32I-NEXT: addi a0, t6, 0 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: explicit_register_t6: +; RV64I: # %bb.0: +; RV64I-NEXT: mv t6, a0 +; RV64I-NEXT: #APP +; RV64I-NEXT: addi a0, t6, 0 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret + %1 = tail call i32 asm "addi $0, $1, 0", "=r,{t6}"(i32 %a) + ret i32 %1 +} + diff --git a/llvm/test/CodeGen/RISCV/inline-asm-d-abi-names.ll b/llvm/test/CodeGen/RISCV/inline-asm-d-abi-names.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/inline-asm-d-abi-names.ll @@ -0,0 +1,1509 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 -mattr=+f,+d -target-abi ilp32d -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=RV32IFD %s +; RUN: llc -mtriple=riscv64 -mattr=+f,+d -target-abi lp64d -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=RV64IFD %s + +; These test that we can use both the architectural names (x*) and the ABI names +; (a*, s*, t* etc) to refer to registers in inline asm constraint lists. In each +; case, the named register should be used for the source register of the `addi`. +; It is very likely that `a0` will be chosen as the designation register, but +; this is left to the compiler to choose. +; +; The inline assembly will, by default, contain the ABI names for the registers. +; +; Parenthesised registers in comments are the other aliases for this register. + + +define i32 @explicit_register_f0(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_f0: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.d ft0, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, ft0 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_f0: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.d ft0, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, ft0 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{f0}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_ft0(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_ft0: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.d ft0, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, ft0 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_ft0: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.d ft0, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, ft0 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{ft0}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_f1(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_f1: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.d ft1, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, ft1 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_f1: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.d ft1, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, ft1 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{f1}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_ft1(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_ft1: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.d ft1, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, ft1 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_ft1: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.d ft1, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, ft1 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{ft1}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_f2(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_f2: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.d ft2, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, ft2 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_f2: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.d ft2, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, ft2 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{f2}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_ft2(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_ft2: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.d ft2, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, ft2 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_ft2: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.d ft2, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, ft2 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{ft2}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_f3(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_f3: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.d ft3, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, ft3 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_f3: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.d ft3, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, ft3 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{f3}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_ft3(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_ft3: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.d ft3, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, ft3 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_ft3: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.d ft3, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, ft3 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{ft3}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_f4(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_f4: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.d ft4, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, ft4 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_f4: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.d ft4, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, ft4 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{f4}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_ft4(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_ft4: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.d ft4, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, ft4 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_ft4: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.d ft4, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, ft4 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{ft4}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_f5(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_f5: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.d ft5, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, ft5 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_f5: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.d ft5, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, ft5 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{f5}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_ft5(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_ft5: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.d ft5, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, ft5 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_ft5: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.d ft5, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, ft5 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{ft5}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_f6(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_f6: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.d ft6, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, ft6 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_f6: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.d ft6, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, ft6 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{f6}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_ft6(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_ft6: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.d ft6, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, ft6 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_ft6: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.d ft6, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, ft6 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{ft6}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_f7(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_f7: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.d ft7, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, ft7 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_f7: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.d ft7, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, ft7 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{f7}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_ft7(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_ft7: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.d ft7, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, ft7 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_ft7: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.d ft7, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, ft7 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{ft7}"(double %a) + ret i32 %1 +} + + +; NOTE: This test uses `f8` (`fs0`) as an input, so it should be saved. +define i32 @explicit_register_f8(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_f8: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: fsd fs0, 8(sp) +; RV32IFD-NEXT: fmv.d fs0, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fs0 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: fld fs0, 8(sp) +; RV32IFD-NEXT: addi sp, sp, 16 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_f8: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: addi sp, sp, -16 +; RV64IFD-NEXT: fsd fs0, 8(sp) +; RV64IFD-NEXT: fmv.d fs0, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fs0 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: fld fs0, 8(sp) +; RV64IFD-NEXT: addi sp, sp, 16 +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{f8}"(double %a) + ret i32 %1 +} + +; NOTE: This test uses `fs0` (`f8`) as an input, so it should be saved. +define i32 @explicit_register_fs0(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_fs0: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: fsd fs0, 8(sp) +; RV32IFD-NEXT: fmv.d fs0, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fs0 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: fld fs0, 8(sp) +; RV32IFD-NEXT: addi sp, sp, 16 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_fs0: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: addi sp, sp, -16 +; RV64IFD-NEXT: fsd fs0, 8(sp) +; RV64IFD-NEXT: fmv.d fs0, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fs0 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: fld fs0, 8(sp) +; RV64IFD-NEXT: addi sp, sp, 16 +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{fs0}"(double %a) + ret i32 %1 +} + +; NOTE: This test uses `f9` (`fs1`) as an input, so it should be saved. +define i32 @explicit_register_f9(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_f9: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: fsd fs1, 8(sp) +; RV32IFD-NEXT: fmv.d fs1, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fs1 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: fld fs1, 8(sp) +; RV32IFD-NEXT: addi sp, sp, 16 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_f9: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: addi sp, sp, -16 +; RV64IFD-NEXT: fsd fs1, 8(sp) +; RV64IFD-NEXT: fmv.d fs1, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fs1 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: fld fs1, 8(sp) +; RV64IFD-NEXT: addi sp, sp, 16 +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{f9}"(double %a) + ret i32 %1 +} + +; NOTE: This test uses `fs1` (`f9`) as an input, so it should be saved. +define i32 @explicit_register_fs1(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_fs1: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: fsd fs1, 8(sp) +; RV32IFD-NEXT: fmv.d fs1, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fs1 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: fld fs1, 8(sp) +; RV32IFD-NEXT: addi sp, sp, 16 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_fs1: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: addi sp, sp, -16 +; RV64IFD-NEXT: fsd fs1, 8(sp) +; RV64IFD-NEXT: fmv.d fs1, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fs1 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: fld fs1, 8(sp) +; RV64IFD-NEXT: addi sp, sp, 16 +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{fs1}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_f10(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_f10: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fa0 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_f10: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fa0 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{f10}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_fa0(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_fa0: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fa0 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_fa0: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fa0 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{fa0}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_f11(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_f11: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.d fa1, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fa1 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_f11: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.d fa1, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fa1 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{f11}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_fa1(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_fa1: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.d fa1, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fa1 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_fa1: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.d fa1, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fa1 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{fa1}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_f12(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_f12: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.d fa2, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fa2 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_f12: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.d fa2, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fa2 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{f12}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_fa2(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_fa2: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.d fa2, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fa2 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_fa2: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.d fa2, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fa2 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{fa2}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_f13(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_f13: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.d fa3, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fa3 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_f13: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.d fa3, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fa3 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{f13}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_fa3(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_fa3: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.d fa3, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fa3 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_fa3: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.d fa3, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fa3 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{fa3}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_f14(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_f14: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.d fa4, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fa4 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_f14: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.d fa4, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fa4 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{f14}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_fa4(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_fa4: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.d fa4, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fa4 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_fa4: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.d fa4, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fa4 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{fa4}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_f15(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_f15: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.d fa5, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fa5 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_f15: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.d fa5, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fa5 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{f15}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_fa5(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_fa5: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.d fa5, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fa5 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_fa5: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.d fa5, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fa5 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{fa5}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_f16(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_f16: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.d fa6, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fa6 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_f16: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.d fa6, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fa6 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{f16}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_fa6(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_fa6: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.d fa6, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fa6 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_fa6: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.d fa6, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fa6 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{fa6}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_f17(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_f17: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.d fa7, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fa7 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_f17: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.d fa7, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fa7 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{f17}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_fa7(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_fa7: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.d fa7, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fa7 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_fa7: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.d fa7, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fa7 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{fa7}"(double %a) + ret i32 %1 +} + +; NOTE: This test uses `f18` (`fs2`) as an input, so it should be saved. +define i32 @explicit_register_f18(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_f18: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: fsd fs2, 8(sp) +; RV32IFD-NEXT: fmv.d fs2, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fs2 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: fld fs2, 8(sp) +; RV32IFD-NEXT: addi sp, sp, 16 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_f18: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: addi sp, sp, -16 +; RV64IFD-NEXT: fsd fs2, 8(sp) +; RV64IFD-NEXT: fmv.d fs2, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fs2 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: fld fs2, 8(sp) +; RV64IFD-NEXT: addi sp, sp, 16 +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{f18}"(double %a) + ret i32 %1 +} + +; NOTE: This test uses `fs2` (`f18`) as an input, so it should be saved. +define i32 @explicit_register_fs2(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_fs2: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: fsd fs2, 8(sp) +; RV32IFD-NEXT: fmv.d fs2, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fs2 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: fld fs2, 8(sp) +; RV32IFD-NEXT: addi sp, sp, 16 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_fs2: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: addi sp, sp, -16 +; RV64IFD-NEXT: fsd fs2, 8(sp) +; RV64IFD-NEXT: fmv.d fs2, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fs2 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: fld fs2, 8(sp) +; RV64IFD-NEXT: addi sp, sp, 16 +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{fs2}"(double %a) + ret i32 %1 +} + +; NOTE: This test uses `f19` (`fs3`) as an input, so it should be saved. +define i32 @explicit_register_f19(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_f19: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: fsd fs3, 8(sp) +; RV32IFD-NEXT: fmv.d fs3, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fs3 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: fld fs3, 8(sp) +; RV32IFD-NEXT: addi sp, sp, 16 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_f19: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: addi sp, sp, -16 +; RV64IFD-NEXT: fsd fs3, 8(sp) +; RV64IFD-NEXT: fmv.d fs3, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fs3 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: fld fs3, 8(sp) +; RV64IFD-NEXT: addi sp, sp, 16 +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{f19}"(double %a) + ret i32 %1 +} + +; NOTE: This test uses `fs3` (`f19`) as an input, so it should be saved. +define i32 @explicit_register_fs3(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_fs3: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: fsd fs3, 8(sp) +; RV32IFD-NEXT: fmv.d fs3, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fs3 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: fld fs3, 8(sp) +; RV32IFD-NEXT: addi sp, sp, 16 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_fs3: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: addi sp, sp, -16 +; RV64IFD-NEXT: fsd fs3, 8(sp) +; RV64IFD-NEXT: fmv.d fs3, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fs3 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: fld fs3, 8(sp) +; RV64IFD-NEXT: addi sp, sp, 16 +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{fs3}"(double %a) + ret i32 %1 +} + +; NOTE: This test uses `f20` (`fs4`) as an input, so it should be saved. +define i32 @explicit_register_f20(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_f20: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: fsd fs4, 8(sp) +; RV32IFD-NEXT: fmv.d fs4, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fs4 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: fld fs4, 8(sp) +; RV32IFD-NEXT: addi sp, sp, 16 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_f20: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: addi sp, sp, -16 +; RV64IFD-NEXT: fsd fs4, 8(sp) +; RV64IFD-NEXT: fmv.d fs4, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fs4 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: fld fs4, 8(sp) +; RV64IFD-NEXT: addi sp, sp, 16 +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{f20}"(double %a) + ret i32 %1 +} + +; NOTE: This test uses `fs4` (`f20`) as an input, so it should be saved. +define i32 @explicit_register_fs4(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_fs4: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: fsd fs4, 8(sp) +; RV32IFD-NEXT: fmv.d fs4, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fs4 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: fld fs4, 8(sp) +; RV32IFD-NEXT: addi sp, sp, 16 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_fs4: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: addi sp, sp, -16 +; RV64IFD-NEXT: fsd fs4, 8(sp) +; RV64IFD-NEXT: fmv.d fs4, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fs4 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: fld fs4, 8(sp) +; RV64IFD-NEXT: addi sp, sp, 16 +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{fs4}"(double %a) + ret i32 %1 +} + +; NOTE: This test uses `f21` (`fs5`) as an input, so it should be saved. +define i32 @explicit_register_f21(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_f21: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: fsd fs5, 8(sp) +; RV32IFD-NEXT: fmv.d fs5, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fs5 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: fld fs5, 8(sp) +; RV32IFD-NEXT: addi sp, sp, 16 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_f21: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: addi sp, sp, -16 +; RV64IFD-NEXT: fsd fs5, 8(sp) +; RV64IFD-NEXT: fmv.d fs5, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fs5 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: fld fs5, 8(sp) +; RV64IFD-NEXT: addi sp, sp, 16 +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{f21}"(double %a) + ret i32 %1 +} + +; NOTE: This test uses `fs5` (`f21`) as an input, so it should be saved. +define i32 @explicit_register_fs5(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_fs5: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: fsd fs5, 8(sp) +; RV32IFD-NEXT: fmv.d fs5, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fs5 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: fld fs5, 8(sp) +; RV32IFD-NEXT: addi sp, sp, 16 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_fs5: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: addi sp, sp, -16 +; RV64IFD-NEXT: fsd fs5, 8(sp) +; RV64IFD-NEXT: fmv.d fs5, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fs5 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: fld fs5, 8(sp) +; RV64IFD-NEXT: addi sp, sp, 16 +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{fs5}"(double %a) + ret i32 %1 +} + +; NOTE: This test uses `f22` (`fs6`) as an input, so it should be saved. +define i32 @explicit_register_f22(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_f22: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: fsd fs6, 8(sp) +; RV32IFD-NEXT: fmv.d fs6, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fs6 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: fld fs6, 8(sp) +; RV32IFD-NEXT: addi sp, sp, 16 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_f22: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: addi sp, sp, -16 +; RV64IFD-NEXT: fsd fs6, 8(sp) +; RV64IFD-NEXT: fmv.d fs6, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fs6 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: fld fs6, 8(sp) +; RV64IFD-NEXT: addi sp, sp, 16 +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{f22}"(double %a) + ret i32 %1 +} + +; NOTE: This test uses `fs6` (`f22`) as an input, so it should be saved. +define i32 @explicit_register_fs6(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_fs6: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: fsd fs6, 8(sp) +; RV32IFD-NEXT: fmv.d fs6, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fs6 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: fld fs6, 8(sp) +; RV32IFD-NEXT: addi sp, sp, 16 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_fs6: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: addi sp, sp, -16 +; RV64IFD-NEXT: fsd fs6, 8(sp) +; RV64IFD-NEXT: fmv.d fs6, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fs6 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: fld fs6, 8(sp) +; RV64IFD-NEXT: addi sp, sp, 16 +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{fs6}"(double %a) + ret i32 %1 +} + +; NOTE: This test uses `f23` (`fs7`) as an input, so it should be saved. +define i32 @explicit_register_f23(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_f23: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: fsd fs7, 8(sp) +; RV32IFD-NEXT: fmv.d fs7, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fs7 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: fld fs7, 8(sp) +; RV32IFD-NEXT: addi sp, sp, 16 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_f23: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: addi sp, sp, -16 +; RV64IFD-NEXT: fsd fs7, 8(sp) +; RV64IFD-NEXT: fmv.d fs7, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fs7 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: fld fs7, 8(sp) +; RV64IFD-NEXT: addi sp, sp, 16 +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{f23}"(double %a) + ret i32 %1 +} + +; NOTE: This test uses `fs7` (`f23`) as an input, so it should be saved. +define i32 @explicit_register_fs7(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_fs7: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: fsd fs7, 8(sp) +; RV32IFD-NEXT: fmv.d fs7, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fs7 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: fld fs7, 8(sp) +; RV32IFD-NEXT: addi sp, sp, 16 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_fs7: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: addi sp, sp, -16 +; RV64IFD-NEXT: fsd fs7, 8(sp) +; RV64IFD-NEXT: fmv.d fs7, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fs7 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: fld fs7, 8(sp) +; RV64IFD-NEXT: addi sp, sp, 16 +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{fs7}"(double %a) + ret i32 %1 +} + +; NOTE: This test uses `f24` (`fs8`) as an input, so it should be saved. +define i32 @explicit_register_f24(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_f24: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: fsd fs8, 8(sp) +; RV32IFD-NEXT: fmv.d fs8, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fs8 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: fld fs8, 8(sp) +; RV32IFD-NEXT: addi sp, sp, 16 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_f24: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: addi sp, sp, -16 +; RV64IFD-NEXT: fsd fs8, 8(sp) +; RV64IFD-NEXT: fmv.d fs8, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fs8 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: fld fs8, 8(sp) +; RV64IFD-NEXT: addi sp, sp, 16 +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{f24}"(double %a) + ret i32 %1 +} + +; NOTE: This test uses `fs8` (`f24`) as an input, so it should be saved. +define i32 @explicit_register_fs8(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_fs8: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: fsd fs8, 8(sp) +; RV32IFD-NEXT: fmv.d fs8, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fs8 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: fld fs8, 8(sp) +; RV32IFD-NEXT: addi sp, sp, 16 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_fs8: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: addi sp, sp, -16 +; RV64IFD-NEXT: fsd fs8, 8(sp) +; RV64IFD-NEXT: fmv.d fs8, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fs8 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: fld fs8, 8(sp) +; RV64IFD-NEXT: addi sp, sp, 16 +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{fs8}"(double %a) + ret i32 %1 +} + +; NOTE: This test uses `f25` (`fs9`) as an input, so it should be saved. +define i32 @explicit_register_f25(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_f25: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: fsd fs9, 8(sp) +; RV32IFD-NEXT: fmv.d fs9, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fs9 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: fld fs9, 8(sp) +; RV32IFD-NEXT: addi sp, sp, 16 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_f25: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: addi sp, sp, -16 +; RV64IFD-NEXT: fsd fs9, 8(sp) +; RV64IFD-NEXT: fmv.d fs9, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fs9 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: fld fs9, 8(sp) +; RV64IFD-NEXT: addi sp, sp, 16 +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{f25}"(double %a) + ret i32 %1 +} + +; NOTE: This test uses `fs9` (`f25`) as an input, so it should be saved. +define i32 @explicit_register_fs9(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_fs9: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: fsd fs9, 8(sp) +; RV32IFD-NEXT: fmv.d fs9, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fs9 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: fld fs9, 8(sp) +; RV32IFD-NEXT: addi sp, sp, 16 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_fs9: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: addi sp, sp, -16 +; RV64IFD-NEXT: fsd fs9, 8(sp) +; RV64IFD-NEXT: fmv.d fs9, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fs9 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: fld fs9, 8(sp) +; RV64IFD-NEXT: addi sp, sp, 16 +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{fs9}"(double %a) + ret i32 %1 +} + +; NOTE: This test uses `f26` (`fs10`) as an input, so it should be saved. +define i32 @explicit_register_f26(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_f26: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: fsd fs10, 8(sp) +; RV32IFD-NEXT: fmv.d fs10, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fs10 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: fld fs10, 8(sp) +; RV32IFD-NEXT: addi sp, sp, 16 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_f26: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: addi sp, sp, -16 +; RV64IFD-NEXT: fsd fs10, 8(sp) +; RV64IFD-NEXT: fmv.d fs10, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fs10 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: fld fs10, 8(sp) +; RV64IFD-NEXT: addi sp, sp, 16 +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{f26}"(double %a) + ret i32 %1 +} + +; NOTE: This test uses `fs10` (`f26`) as an input, so it should be saved. +define i32 @explicit_register_fs10(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_fs10: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: fsd fs10, 8(sp) +; RV32IFD-NEXT: fmv.d fs10, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fs10 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: fld fs10, 8(sp) +; RV32IFD-NEXT: addi sp, sp, 16 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_fs10: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: addi sp, sp, -16 +; RV64IFD-NEXT: fsd fs10, 8(sp) +; RV64IFD-NEXT: fmv.d fs10, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fs10 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: fld fs10, 8(sp) +; RV64IFD-NEXT: addi sp, sp, 16 +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{fs10}"(double %a) + ret i32 %1 +} + +; NOTE: This test uses `f27` (`fs11`) as an input, so it should be saved. +define i32 @explicit_register_f27(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_f27: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: fsd fs11, 8(sp) +; RV32IFD-NEXT: fmv.d fs11, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fs11 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: fld fs11, 8(sp) +; RV32IFD-NEXT: addi sp, sp, 16 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_f27: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: addi sp, sp, -16 +; RV64IFD-NEXT: fsd fs11, 8(sp) +; RV64IFD-NEXT: fmv.d fs11, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fs11 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: fld fs11, 8(sp) +; RV64IFD-NEXT: addi sp, sp, 16 +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{f27}"(double %a) + ret i32 %1 +} + +; NOTE: This test uses `fs11` (`f27`) as an input, so it should be saved. +define i32 @explicit_register_fs11(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_fs11: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: fsd fs11, 8(sp) +; RV32IFD-NEXT: fmv.d fs11, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, fs11 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: fld fs11, 8(sp) +; RV32IFD-NEXT: addi sp, sp, 16 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_fs11: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: addi sp, sp, -16 +; RV64IFD-NEXT: fsd fs11, 8(sp) +; RV64IFD-NEXT: fmv.d fs11, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, fs11 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: fld fs11, 8(sp) +; RV64IFD-NEXT: addi sp, sp, 16 +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{fs11}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_f28(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_f28: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.d ft8, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, ft8 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_f28: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.d ft8, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, ft8 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{f28}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_ft8(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_ft8: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.d ft8, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, ft8 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_ft8: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.d ft8, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, ft8 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{ft8}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_f29(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_f29: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.d ft9, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, ft9 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_f29: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.d ft9, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, ft9 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{f29}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_ft9(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_ft9: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.d ft9, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, ft9 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_ft9: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.d ft9, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, ft9 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{ft9}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_f30(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_f30: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.d ft10, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, ft10 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_f30: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.d ft10, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, ft10 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{f30}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_ft10(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_ft10: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.d ft10, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, ft10 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_ft10: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.d ft10, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, ft10 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{ft10}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_f31(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_f31: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.d ft11, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, ft11 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_f31: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.d ft11, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, ft11 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{f31}"(double %a) + ret i32 %1 +} + +define i32 @explicit_register_ft11(double %a) nounwind { +; RV32IFD-LABEL: explicit_register_ft11: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: fmv.d ft11, fa0 +; RV32IFD-NEXT: #APP +; RV32IFD-NEXT: fcvt.w.d a0, ft11 +; RV32IFD-NEXT: #NO_APP +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: explicit_register_ft11: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: fmv.d ft11, fa0 +; RV64IFD-NEXT: #APP +; RV64IFD-NEXT: fcvt.w.d a0, ft11 +; RV64IFD-NEXT: #NO_APP +; RV64IFD-NEXT: ret + %1 = tail call i32 asm "fcvt.w.d $0, $1", "=r,{ft11}"(double %a) + ret i32 %1 +} diff --git a/llvm/test/CodeGen/RISCV/inline-asm-d-constraint-f.ll b/llvm/test/CodeGen/RISCV/inline-asm-d-constraint-f.ll --- a/llvm/test/CodeGen/RISCV/inline-asm-d-constraint-f.ll +++ b/llvm/test/CodeGen/RISCV/inline-asm-d-constraint-f.ll @@ -38,3 +38,36 @@ %2 = tail call double asm "fadd.d $0, $1, $2", "=f,f,f"(double %a, double %1) ret double %2 } + +define double @constraint_f_double_abi_name(double %a) nounwind { +; RV32F-LABEL: constraint_f_double_abi_name: +; RV32F: # %bb.0: +; RV32F-NEXT: addi sp, sp, -16 +; RV32F-NEXT: sw a0, 8(sp) +; RV32F-NEXT: sw a1, 12(sp) +; RV32F-NEXT: fld fa1, 8(sp) +; RV32F-NEXT: lui a0, %hi(gd) +; RV32F-NEXT: fld fs0, %lo(gd)(a0) +; RV32F-NEXT: #APP +; RV32F-NEXT: fadd.d ft0, fa1, fs0 +; RV32F-NEXT: #NO_APP +; RV32F-NEXT: fsd ft0, 8(sp) +; RV32F-NEXT: lw a0, 8(sp) +; RV32F-NEXT: lw a1, 12(sp) +; RV32F-NEXT: addi sp, sp, 16 +; RV32F-NEXT: ret +; +; RV64F-LABEL: constraint_f_double_abi_name: +; RV64F: # %bb.0: +; RV64F-NEXT: fmv.d.x fa1, a0 +; RV64F-NEXT: lui a0, %hi(gd) +; RV64F-NEXT: fld fs0, %lo(gd)(a0) +; RV64F-NEXT: #APP +; RV64F-NEXT: fadd.d ft0, fa1, fs0 +; RV64F-NEXT: #NO_APP +; RV64F-NEXT: fmv.x.d a0, ft0 +; RV64F-NEXT: ret + %1 = load double, double* @gd + %2 = tail call double asm "fadd.d $0, $1, $2", "={ft0},{fa1},{fs0}"(double %a, double %1) + ret double %2 +} diff --git a/llvm/test/CodeGen/RISCV/inline-asm-f-abi-names.ll b/llvm/test/CodeGen/RISCV/inline-asm-f-abi-names.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/inline-asm-f-abi-names.ll @@ -0,0 +1,1509 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 -mattr=+f -target-abi ilp32f -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=RV32IF %s +; RUN: llc -mtriple=riscv64 -mattr=+f -target-abi lp64f -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=RV64IF %s + +; These test that we can use both the architectural names (x*) and the ABI names +; (a*, s*, t* etc) to refer to registers in inline asm constraint lists. In each +; case, the named register should be used for the source register of the `addi`. +; It is very likely that `a0` will be chosen as the designation register, but +; this is left to the compiler to choose. +; +; The inline assembly will, by default, contain the ABI names for the registers. +; +; Parenthesised registers in comments are the other aliases for this register. + + +define i32 @explicit_register_f0(float %a) nounwind { +; RV32IF-LABEL: explicit_register_f0: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.s ft0, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, ft0 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_f0: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.s ft0, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, ft0 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{f0}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_ft0(float %a) nounwind { +; RV32IF-LABEL: explicit_register_ft0: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.s ft0, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, ft0 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_ft0: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.s ft0, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, ft0 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{ft0}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_f1(float %a) nounwind { +; RV32IF-LABEL: explicit_register_f1: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.s ft1, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, ft1 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_f1: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.s ft1, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, ft1 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{f1}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_ft1(float %a) nounwind { +; RV32IF-LABEL: explicit_register_ft1: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.s ft1, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, ft1 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_ft1: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.s ft1, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, ft1 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{ft1}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_f2(float %a) nounwind { +; RV32IF-LABEL: explicit_register_f2: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.s ft2, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, ft2 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_f2: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.s ft2, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, ft2 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{f2}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_ft2(float %a) nounwind { +; RV32IF-LABEL: explicit_register_ft2: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.s ft2, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, ft2 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_ft2: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.s ft2, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, ft2 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{ft2}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_f3(float %a) nounwind { +; RV32IF-LABEL: explicit_register_f3: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.s ft3, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, ft3 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_f3: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.s ft3, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, ft3 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{f3}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_ft3(float %a) nounwind { +; RV32IF-LABEL: explicit_register_ft3: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.s ft3, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, ft3 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_ft3: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.s ft3, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, ft3 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{ft3}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_f4(float %a) nounwind { +; RV32IF-LABEL: explicit_register_f4: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.s ft4, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, ft4 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_f4: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.s ft4, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, ft4 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{f4}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_ft4(float %a) nounwind { +; RV32IF-LABEL: explicit_register_ft4: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.s ft4, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, ft4 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_ft4: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.s ft4, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, ft4 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{ft4}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_f5(float %a) nounwind { +; RV32IF-LABEL: explicit_register_f5: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.s ft5, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, ft5 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_f5: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.s ft5, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, ft5 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{f5}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_ft5(float %a) nounwind { +; RV32IF-LABEL: explicit_register_ft5: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.s ft5, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, ft5 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_ft5: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.s ft5, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, ft5 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{ft5}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_f6(float %a) nounwind { +; RV32IF-LABEL: explicit_register_f6: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.s ft6, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, ft6 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_f6: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.s ft6, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, ft6 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{f6}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_ft6(float %a) nounwind { +; RV32IF-LABEL: explicit_register_ft6: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.s ft6, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, ft6 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_ft6: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.s ft6, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, ft6 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{ft6}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_f7(float %a) nounwind { +; RV32IF-LABEL: explicit_register_f7: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.s ft7, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, ft7 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_f7: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.s ft7, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, ft7 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{f7}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_ft7(float %a) nounwind { +; RV32IF-LABEL: explicit_register_ft7: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.s ft7, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, ft7 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_ft7: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.s ft7, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, ft7 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{ft7}"(float %a) + ret i32 %1 +} + + +; NOTE: This test uses `f8` (`fs0`) as an input, so it should be saved. +define i32 @explicit_register_f8(float %a) nounwind { +; RV32IF-LABEL: explicit_register_f8: +; RV32IF: # %bb.0: +; RV32IF-NEXT: addi sp, sp, -16 +; RV32IF-NEXT: fsw fs0, 12(sp) +; RV32IF-NEXT: fmv.s fs0, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fs0 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: flw fs0, 12(sp) +; RV32IF-NEXT: addi sp, sp, 16 +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_f8: +; RV64IF: # %bb.0: +; RV64IF-NEXT: addi sp, sp, -16 +; RV64IF-NEXT: fsw fs0, 12(sp) +; RV64IF-NEXT: fmv.s fs0, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fs0 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: flw fs0, 12(sp) +; RV64IF-NEXT: addi sp, sp, 16 +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{f8}"(float %a) + ret i32 %1 +} + +; NOTE: This test uses `fs0` (`f8`) as an input, so it should be saved. +define i32 @explicit_register_fs0(float %a) nounwind { +; RV32IF-LABEL: explicit_register_fs0: +; RV32IF: # %bb.0: +; RV32IF-NEXT: addi sp, sp, -16 +; RV32IF-NEXT: fsw fs0, 12(sp) +; RV32IF-NEXT: fmv.s fs0, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fs0 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: flw fs0, 12(sp) +; RV32IF-NEXT: addi sp, sp, 16 +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_fs0: +; RV64IF: # %bb.0: +; RV64IF-NEXT: addi sp, sp, -16 +; RV64IF-NEXT: fsw fs0, 12(sp) +; RV64IF-NEXT: fmv.s fs0, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fs0 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: flw fs0, 12(sp) +; RV64IF-NEXT: addi sp, sp, 16 +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{fs0}"(float %a) + ret i32 %1 +} + +; NOTE: This test uses `f9` (`fs1`) as an input, so it should be saved. +define i32 @explicit_register_f9(float %a) nounwind { +; RV32IF-LABEL: explicit_register_f9: +; RV32IF: # %bb.0: +; RV32IF-NEXT: addi sp, sp, -16 +; RV32IF-NEXT: fsw fs1, 12(sp) +; RV32IF-NEXT: fmv.s fs1, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fs1 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: flw fs1, 12(sp) +; RV32IF-NEXT: addi sp, sp, 16 +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_f9: +; RV64IF: # %bb.0: +; RV64IF-NEXT: addi sp, sp, -16 +; RV64IF-NEXT: fsw fs1, 12(sp) +; RV64IF-NEXT: fmv.s fs1, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fs1 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: flw fs1, 12(sp) +; RV64IF-NEXT: addi sp, sp, 16 +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{f9}"(float %a) + ret i32 %1 +} + +; NOTE: This test uses `fs1` (`f9`) as an input, so it should be saved. +define i32 @explicit_register_fs1(float %a) nounwind { +; RV32IF-LABEL: explicit_register_fs1: +; RV32IF: # %bb.0: +; RV32IF-NEXT: addi sp, sp, -16 +; RV32IF-NEXT: fsw fs1, 12(sp) +; RV32IF-NEXT: fmv.s fs1, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fs1 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: flw fs1, 12(sp) +; RV32IF-NEXT: addi sp, sp, 16 +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_fs1: +; RV64IF: # %bb.0: +; RV64IF-NEXT: addi sp, sp, -16 +; RV64IF-NEXT: fsw fs1, 12(sp) +; RV64IF-NEXT: fmv.s fs1, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fs1 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: flw fs1, 12(sp) +; RV64IF-NEXT: addi sp, sp, 16 +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{fs1}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_f10(float %a) nounwind { +; RV32IF-LABEL: explicit_register_f10: +; RV32IF: # %bb.0: +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fa0 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_f10: +; RV64IF: # %bb.0: +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fa0 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{f10}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_fa0(float %a) nounwind { +; RV32IF-LABEL: explicit_register_fa0: +; RV32IF: # %bb.0: +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fa0 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_fa0: +; RV64IF: # %bb.0: +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fa0 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{fa0}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_f11(float %a) nounwind { +; RV32IF-LABEL: explicit_register_f11: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.s fa1, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fa1 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_f11: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.s fa1, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fa1 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{f11}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_fa1(float %a) nounwind { +; RV32IF-LABEL: explicit_register_fa1: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.s fa1, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fa1 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_fa1: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.s fa1, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fa1 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{fa1}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_f12(float %a) nounwind { +; RV32IF-LABEL: explicit_register_f12: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.s fa2, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fa2 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_f12: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.s fa2, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fa2 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{f12}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_fa2(float %a) nounwind { +; RV32IF-LABEL: explicit_register_fa2: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.s fa2, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fa2 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_fa2: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.s fa2, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fa2 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{fa2}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_f13(float %a) nounwind { +; RV32IF-LABEL: explicit_register_f13: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.s fa3, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fa3 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_f13: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.s fa3, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fa3 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{f13}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_fa3(float %a) nounwind { +; RV32IF-LABEL: explicit_register_fa3: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.s fa3, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fa3 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_fa3: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.s fa3, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fa3 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{fa3}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_f14(float %a) nounwind { +; RV32IF-LABEL: explicit_register_f14: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.s fa4, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fa4 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_f14: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.s fa4, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fa4 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{f14}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_fa4(float %a) nounwind { +; RV32IF-LABEL: explicit_register_fa4: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.s fa4, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fa4 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_fa4: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.s fa4, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fa4 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{fa4}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_f15(float %a) nounwind { +; RV32IF-LABEL: explicit_register_f15: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.s fa5, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fa5 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_f15: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.s fa5, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fa5 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{f15}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_fa5(float %a) nounwind { +; RV32IF-LABEL: explicit_register_fa5: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.s fa5, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fa5 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_fa5: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.s fa5, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fa5 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{fa5}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_f16(float %a) nounwind { +; RV32IF-LABEL: explicit_register_f16: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.s fa6, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fa6 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_f16: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.s fa6, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fa6 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{f16}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_fa6(float %a) nounwind { +; RV32IF-LABEL: explicit_register_fa6: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.s fa6, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fa6 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_fa6: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.s fa6, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fa6 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{fa6}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_f17(float %a) nounwind { +; RV32IF-LABEL: explicit_register_f17: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.s fa7, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fa7 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_f17: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.s fa7, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fa7 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{f17}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_fa7(float %a) nounwind { +; RV32IF-LABEL: explicit_register_fa7: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.s fa7, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fa7 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_fa7: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.s fa7, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fa7 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{fa7}"(float %a) + ret i32 %1 +} + +; NOTE: This test uses `f18` (`fs2`) as an input, so it should be saved. +define i32 @explicit_register_f18(float %a) nounwind { +; RV32IF-LABEL: explicit_register_f18: +; RV32IF: # %bb.0: +; RV32IF-NEXT: addi sp, sp, -16 +; RV32IF-NEXT: fsw fs2, 12(sp) +; RV32IF-NEXT: fmv.s fs2, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fs2 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: flw fs2, 12(sp) +; RV32IF-NEXT: addi sp, sp, 16 +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_f18: +; RV64IF: # %bb.0: +; RV64IF-NEXT: addi sp, sp, -16 +; RV64IF-NEXT: fsw fs2, 12(sp) +; RV64IF-NEXT: fmv.s fs2, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fs2 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: flw fs2, 12(sp) +; RV64IF-NEXT: addi sp, sp, 16 +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{f18}"(float %a) + ret i32 %1 +} + +; NOTE: This test uses `fs2` (`f18`) as an input, so it should be saved. +define i32 @explicit_register_fs2(float %a) nounwind { +; RV32IF-LABEL: explicit_register_fs2: +; RV32IF: # %bb.0: +; RV32IF-NEXT: addi sp, sp, -16 +; RV32IF-NEXT: fsw fs2, 12(sp) +; RV32IF-NEXT: fmv.s fs2, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fs2 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: flw fs2, 12(sp) +; RV32IF-NEXT: addi sp, sp, 16 +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_fs2: +; RV64IF: # %bb.0: +; RV64IF-NEXT: addi sp, sp, -16 +; RV64IF-NEXT: fsw fs2, 12(sp) +; RV64IF-NEXT: fmv.s fs2, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fs2 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: flw fs2, 12(sp) +; RV64IF-NEXT: addi sp, sp, 16 +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{fs2}"(float %a) + ret i32 %1 +} + +; NOTE: This test uses `f19` (`fs3`) as an input, so it should be saved. +define i32 @explicit_register_f19(float %a) nounwind { +; RV32IF-LABEL: explicit_register_f19: +; RV32IF: # %bb.0: +; RV32IF-NEXT: addi sp, sp, -16 +; RV32IF-NEXT: fsw fs3, 12(sp) +; RV32IF-NEXT: fmv.s fs3, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fs3 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: flw fs3, 12(sp) +; RV32IF-NEXT: addi sp, sp, 16 +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_f19: +; RV64IF: # %bb.0: +; RV64IF-NEXT: addi sp, sp, -16 +; RV64IF-NEXT: fsw fs3, 12(sp) +; RV64IF-NEXT: fmv.s fs3, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fs3 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: flw fs3, 12(sp) +; RV64IF-NEXT: addi sp, sp, 16 +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{f19}"(float %a) + ret i32 %1 +} + +; NOTE: This test uses `fs3` (`f19`) as an input, so it should be saved. +define i32 @explicit_register_fs3(float %a) nounwind { +; RV32IF-LABEL: explicit_register_fs3: +; RV32IF: # %bb.0: +; RV32IF-NEXT: addi sp, sp, -16 +; RV32IF-NEXT: fsw fs3, 12(sp) +; RV32IF-NEXT: fmv.s fs3, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fs3 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: flw fs3, 12(sp) +; RV32IF-NEXT: addi sp, sp, 16 +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_fs3: +; RV64IF: # %bb.0: +; RV64IF-NEXT: addi sp, sp, -16 +; RV64IF-NEXT: fsw fs3, 12(sp) +; RV64IF-NEXT: fmv.s fs3, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fs3 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: flw fs3, 12(sp) +; RV64IF-NEXT: addi sp, sp, 16 +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{fs3}"(float %a) + ret i32 %1 +} + +; NOTE: This test uses `f20` (`fs4`) as an input, so it should be saved. +define i32 @explicit_register_f20(float %a) nounwind { +; RV32IF-LABEL: explicit_register_f20: +; RV32IF: # %bb.0: +; RV32IF-NEXT: addi sp, sp, -16 +; RV32IF-NEXT: fsw fs4, 12(sp) +; RV32IF-NEXT: fmv.s fs4, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fs4 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: flw fs4, 12(sp) +; RV32IF-NEXT: addi sp, sp, 16 +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_f20: +; RV64IF: # %bb.0: +; RV64IF-NEXT: addi sp, sp, -16 +; RV64IF-NEXT: fsw fs4, 12(sp) +; RV64IF-NEXT: fmv.s fs4, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fs4 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: flw fs4, 12(sp) +; RV64IF-NEXT: addi sp, sp, 16 +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{f20}"(float %a) + ret i32 %1 +} + +; NOTE: This test uses `fs4` (`f20`) as an input, so it should be saved. +define i32 @explicit_register_fs4(float %a) nounwind { +; RV32IF-LABEL: explicit_register_fs4: +; RV32IF: # %bb.0: +; RV32IF-NEXT: addi sp, sp, -16 +; RV32IF-NEXT: fsw fs4, 12(sp) +; RV32IF-NEXT: fmv.s fs4, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fs4 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: flw fs4, 12(sp) +; RV32IF-NEXT: addi sp, sp, 16 +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_fs4: +; RV64IF: # %bb.0: +; RV64IF-NEXT: addi sp, sp, -16 +; RV64IF-NEXT: fsw fs4, 12(sp) +; RV64IF-NEXT: fmv.s fs4, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fs4 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: flw fs4, 12(sp) +; RV64IF-NEXT: addi sp, sp, 16 +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{fs4}"(float %a) + ret i32 %1 +} + +; NOTE: This test uses `f21` (`fs5`) as an input, so it should be saved. +define i32 @explicit_register_f21(float %a) nounwind { +; RV32IF-LABEL: explicit_register_f21: +; RV32IF: # %bb.0: +; RV32IF-NEXT: addi sp, sp, -16 +; RV32IF-NEXT: fsw fs5, 12(sp) +; RV32IF-NEXT: fmv.s fs5, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fs5 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: flw fs5, 12(sp) +; RV32IF-NEXT: addi sp, sp, 16 +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_f21: +; RV64IF: # %bb.0: +; RV64IF-NEXT: addi sp, sp, -16 +; RV64IF-NEXT: fsw fs5, 12(sp) +; RV64IF-NEXT: fmv.s fs5, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fs5 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: flw fs5, 12(sp) +; RV64IF-NEXT: addi sp, sp, 16 +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{f21}"(float %a) + ret i32 %1 +} + +; NOTE: This test uses `fs5` (`f21`) as an input, so it should be saved. +define i32 @explicit_register_fs5(float %a) nounwind { +; RV32IF-LABEL: explicit_register_fs5: +; RV32IF: # %bb.0: +; RV32IF-NEXT: addi sp, sp, -16 +; RV32IF-NEXT: fsw fs5, 12(sp) +; RV32IF-NEXT: fmv.s fs5, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fs5 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: flw fs5, 12(sp) +; RV32IF-NEXT: addi sp, sp, 16 +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_fs5: +; RV64IF: # %bb.0: +; RV64IF-NEXT: addi sp, sp, -16 +; RV64IF-NEXT: fsw fs5, 12(sp) +; RV64IF-NEXT: fmv.s fs5, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fs5 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: flw fs5, 12(sp) +; RV64IF-NEXT: addi sp, sp, 16 +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{fs5}"(float %a) + ret i32 %1 +} + +; NOTE: This test uses `f22` (`fs6`) as an input, so it should be saved. +define i32 @explicit_register_f22(float %a) nounwind { +; RV32IF-LABEL: explicit_register_f22: +; RV32IF: # %bb.0: +; RV32IF-NEXT: addi sp, sp, -16 +; RV32IF-NEXT: fsw fs6, 12(sp) +; RV32IF-NEXT: fmv.s fs6, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fs6 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: flw fs6, 12(sp) +; RV32IF-NEXT: addi sp, sp, 16 +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_f22: +; RV64IF: # %bb.0: +; RV64IF-NEXT: addi sp, sp, -16 +; RV64IF-NEXT: fsw fs6, 12(sp) +; RV64IF-NEXT: fmv.s fs6, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fs6 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: flw fs6, 12(sp) +; RV64IF-NEXT: addi sp, sp, 16 +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{f22}"(float %a) + ret i32 %1 +} + +; NOTE: This test uses `fs6` (`f22`) as an input, so it should be saved. +define i32 @explicit_register_fs6(float %a) nounwind { +; RV32IF-LABEL: explicit_register_fs6: +; RV32IF: # %bb.0: +; RV32IF-NEXT: addi sp, sp, -16 +; RV32IF-NEXT: fsw fs6, 12(sp) +; RV32IF-NEXT: fmv.s fs6, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fs6 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: flw fs6, 12(sp) +; RV32IF-NEXT: addi sp, sp, 16 +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_fs6: +; RV64IF: # %bb.0: +; RV64IF-NEXT: addi sp, sp, -16 +; RV64IF-NEXT: fsw fs6, 12(sp) +; RV64IF-NEXT: fmv.s fs6, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fs6 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: flw fs6, 12(sp) +; RV64IF-NEXT: addi sp, sp, 16 +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{fs6}"(float %a) + ret i32 %1 +} + +; NOTE: This test uses `f23` (`fs7`) as an input, so it should be saved. +define i32 @explicit_register_f23(float %a) nounwind { +; RV32IF-LABEL: explicit_register_f23: +; RV32IF: # %bb.0: +; RV32IF-NEXT: addi sp, sp, -16 +; RV32IF-NEXT: fsw fs7, 12(sp) +; RV32IF-NEXT: fmv.s fs7, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fs7 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: flw fs7, 12(sp) +; RV32IF-NEXT: addi sp, sp, 16 +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_f23: +; RV64IF: # %bb.0: +; RV64IF-NEXT: addi sp, sp, -16 +; RV64IF-NEXT: fsw fs7, 12(sp) +; RV64IF-NEXT: fmv.s fs7, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fs7 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: flw fs7, 12(sp) +; RV64IF-NEXT: addi sp, sp, 16 +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{f23}"(float %a) + ret i32 %1 +} + +; NOTE: This test uses `fs7` (`f23`) as an input, so it should be saved. +define i32 @explicit_register_fs7(float %a) nounwind { +; RV32IF-LABEL: explicit_register_fs7: +; RV32IF: # %bb.0: +; RV32IF-NEXT: addi sp, sp, -16 +; RV32IF-NEXT: fsw fs7, 12(sp) +; RV32IF-NEXT: fmv.s fs7, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fs7 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: flw fs7, 12(sp) +; RV32IF-NEXT: addi sp, sp, 16 +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_fs7: +; RV64IF: # %bb.0: +; RV64IF-NEXT: addi sp, sp, -16 +; RV64IF-NEXT: fsw fs7, 12(sp) +; RV64IF-NEXT: fmv.s fs7, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fs7 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: flw fs7, 12(sp) +; RV64IF-NEXT: addi sp, sp, 16 +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{fs7}"(float %a) + ret i32 %1 +} + +; NOTE: This test uses `f24` (`fs8`) as an input, so it should be saved. +define i32 @explicit_register_f24(float %a) nounwind { +; RV32IF-LABEL: explicit_register_f24: +; RV32IF: # %bb.0: +; RV32IF-NEXT: addi sp, sp, -16 +; RV32IF-NEXT: fsw fs8, 12(sp) +; RV32IF-NEXT: fmv.s fs8, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fs8 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: flw fs8, 12(sp) +; RV32IF-NEXT: addi sp, sp, 16 +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_f24: +; RV64IF: # %bb.0: +; RV64IF-NEXT: addi sp, sp, -16 +; RV64IF-NEXT: fsw fs8, 12(sp) +; RV64IF-NEXT: fmv.s fs8, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fs8 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: flw fs8, 12(sp) +; RV64IF-NEXT: addi sp, sp, 16 +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{f24}"(float %a) + ret i32 %1 +} + +; NOTE: This test uses `fs8` (`f24`) as an input, so it should be saved. +define i32 @explicit_register_fs8(float %a) nounwind { +; RV32IF-LABEL: explicit_register_fs8: +; RV32IF: # %bb.0: +; RV32IF-NEXT: addi sp, sp, -16 +; RV32IF-NEXT: fsw fs8, 12(sp) +; RV32IF-NEXT: fmv.s fs8, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fs8 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: flw fs8, 12(sp) +; RV32IF-NEXT: addi sp, sp, 16 +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_fs8: +; RV64IF: # %bb.0: +; RV64IF-NEXT: addi sp, sp, -16 +; RV64IF-NEXT: fsw fs8, 12(sp) +; RV64IF-NEXT: fmv.s fs8, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fs8 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: flw fs8, 12(sp) +; RV64IF-NEXT: addi sp, sp, 16 +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{fs8}"(float %a) + ret i32 %1 +} + +; NOTE: This test uses `f25` (`fs9`) as an input, so it should be saved. +define i32 @explicit_register_f25(float %a) nounwind { +; RV32IF-LABEL: explicit_register_f25: +; RV32IF: # %bb.0: +; RV32IF-NEXT: addi sp, sp, -16 +; RV32IF-NEXT: fsw fs9, 12(sp) +; RV32IF-NEXT: fmv.s fs9, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fs9 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: flw fs9, 12(sp) +; RV32IF-NEXT: addi sp, sp, 16 +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_f25: +; RV64IF: # %bb.0: +; RV64IF-NEXT: addi sp, sp, -16 +; RV64IF-NEXT: fsw fs9, 12(sp) +; RV64IF-NEXT: fmv.s fs9, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fs9 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: flw fs9, 12(sp) +; RV64IF-NEXT: addi sp, sp, 16 +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{f25}"(float %a) + ret i32 %1 +} + +; NOTE: This test uses `fs9` (`f25`) as an input, so it should be saved. +define i32 @explicit_register_fs9(float %a) nounwind { +; RV32IF-LABEL: explicit_register_fs9: +; RV32IF: # %bb.0: +; RV32IF-NEXT: addi sp, sp, -16 +; RV32IF-NEXT: fsw fs9, 12(sp) +; RV32IF-NEXT: fmv.s fs9, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fs9 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: flw fs9, 12(sp) +; RV32IF-NEXT: addi sp, sp, 16 +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_fs9: +; RV64IF: # %bb.0: +; RV64IF-NEXT: addi sp, sp, -16 +; RV64IF-NEXT: fsw fs9, 12(sp) +; RV64IF-NEXT: fmv.s fs9, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fs9 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: flw fs9, 12(sp) +; RV64IF-NEXT: addi sp, sp, 16 +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{fs9}"(float %a) + ret i32 %1 +} + +; NOTE: This test uses `f26` (`fs10`) as an input, so it should be saved. +define i32 @explicit_register_f26(float %a) nounwind { +; RV32IF-LABEL: explicit_register_f26: +; RV32IF: # %bb.0: +; RV32IF-NEXT: addi sp, sp, -16 +; RV32IF-NEXT: fsw fs10, 12(sp) +; RV32IF-NEXT: fmv.s fs10, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fs10 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: flw fs10, 12(sp) +; RV32IF-NEXT: addi sp, sp, 16 +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_f26: +; RV64IF: # %bb.0: +; RV64IF-NEXT: addi sp, sp, -16 +; RV64IF-NEXT: fsw fs10, 12(sp) +; RV64IF-NEXT: fmv.s fs10, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fs10 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: flw fs10, 12(sp) +; RV64IF-NEXT: addi sp, sp, 16 +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{f26}"(float %a) + ret i32 %1 +} + +; NOTE: This test uses `fs10` (`f26`) as an input, so it should be saved. +define i32 @explicit_register_fs10(float %a) nounwind { +; RV32IF-LABEL: explicit_register_fs10: +; RV32IF: # %bb.0: +; RV32IF-NEXT: addi sp, sp, -16 +; RV32IF-NEXT: fsw fs10, 12(sp) +; RV32IF-NEXT: fmv.s fs10, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fs10 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: flw fs10, 12(sp) +; RV32IF-NEXT: addi sp, sp, 16 +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_fs10: +; RV64IF: # %bb.0: +; RV64IF-NEXT: addi sp, sp, -16 +; RV64IF-NEXT: fsw fs10, 12(sp) +; RV64IF-NEXT: fmv.s fs10, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fs10 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: flw fs10, 12(sp) +; RV64IF-NEXT: addi sp, sp, 16 +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{fs10}"(float %a) + ret i32 %1 +} + +; NOTE: This test uses `f27` (`fs11`) as an input, so it should be saved. +define i32 @explicit_register_f27(float %a) nounwind { +; RV32IF-LABEL: explicit_register_f27: +; RV32IF: # %bb.0: +; RV32IF-NEXT: addi sp, sp, -16 +; RV32IF-NEXT: fsw fs11, 12(sp) +; RV32IF-NEXT: fmv.s fs11, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fs11 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: flw fs11, 12(sp) +; RV32IF-NEXT: addi sp, sp, 16 +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_f27: +; RV64IF: # %bb.0: +; RV64IF-NEXT: addi sp, sp, -16 +; RV64IF-NEXT: fsw fs11, 12(sp) +; RV64IF-NEXT: fmv.s fs11, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fs11 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: flw fs11, 12(sp) +; RV64IF-NEXT: addi sp, sp, 16 +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{f27}"(float %a) + ret i32 %1 +} + +; NOTE: This test uses `fs11` (`f27`) as an input, so it should be saved. +define i32 @explicit_register_fs11(float %a) nounwind { +; RV32IF-LABEL: explicit_register_fs11: +; RV32IF: # %bb.0: +; RV32IF-NEXT: addi sp, sp, -16 +; RV32IF-NEXT: fsw fs11, 12(sp) +; RV32IF-NEXT: fmv.s fs11, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, fs11 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: flw fs11, 12(sp) +; RV32IF-NEXT: addi sp, sp, 16 +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_fs11: +; RV64IF: # %bb.0: +; RV64IF-NEXT: addi sp, sp, -16 +; RV64IF-NEXT: fsw fs11, 12(sp) +; RV64IF-NEXT: fmv.s fs11, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, fs11 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: flw fs11, 12(sp) +; RV64IF-NEXT: addi sp, sp, 16 +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{fs11}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_f28(float %a) nounwind { +; RV32IF-LABEL: explicit_register_f28: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.s ft8, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, ft8 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_f28: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.s ft8, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, ft8 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{f28}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_ft8(float %a) nounwind { +; RV32IF-LABEL: explicit_register_ft8: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.s ft8, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, ft8 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_ft8: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.s ft8, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, ft8 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{ft8}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_f29(float %a) nounwind { +; RV32IF-LABEL: explicit_register_f29: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.s ft9, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, ft9 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_f29: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.s ft9, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, ft9 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{f29}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_ft9(float %a) nounwind { +; RV32IF-LABEL: explicit_register_ft9: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.s ft9, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, ft9 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_ft9: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.s ft9, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, ft9 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{ft9}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_f30(float %a) nounwind { +; RV32IF-LABEL: explicit_register_f30: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.s ft10, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, ft10 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_f30: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.s ft10, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, ft10 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{f30}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_ft10(float %a) nounwind { +; RV32IF-LABEL: explicit_register_ft10: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.s ft10, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, ft10 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_ft10: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.s ft10, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, ft10 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{ft10}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_f31(float %a) nounwind { +; RV32IF-LABEL: explicit_register_f31: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.s ft11, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, ft11 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_f31: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.s ft11, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, ft11 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{f31}"(float %a) + ret i32 %1 +} + +define i32 @explicit_register_ft11(float %a) nounwind { +; RV32IF-LABEL: explicit_register_ft11: +; RV32IF: # %bb.0: +; RV32IF-NEXT: fmv.s ft11, fa0 +; RV32IF-NEXT: #APP +; RV32IF-NEXT: fcvt.w.s a0, ft11 +; RV32IF-NEXT: #NO_APP +; RV32IF-NEXT: ret +; +; RV64IF-LABEL: explicit_register_ft11: +; RV64IF: # %bb.0: +; RV64IF-NEXT: fmv.s ft11, fa0 +; RV64IF-NEXT: #APP +; RV64IF-NEXT: fcvt.w.s a0, ft11 +; RV64IF-NEXT: #NO_APP +; RV64IF-NEXT: ret + %1 = tail call i32 asm "fcvt.w.s $0, $1", "=r,{ft11}"(float %a) + ret i32 %1 +} diff --git a/llvm/test/CodeGen/RISCV/inline-asm-f-constraint-f.ll b/llvm/test/CodeGen/RISCV/inline-asm-f-constraint-f.ll --- a/llvm/test/CodeGen/RISCV/inline-asm-f-constraint-f.ll +++ b/llvm/test/CodeGen/RISCV/inline-asm-f-constraint-f.ll @@ -32,3 +32,30 @@ %2 = tail call float asm "fadd.s $0, $1, $2", "=f,f,f"(float %a, float %1) ret float %2 } + +define float @constraint_f_float_abi_name(float %a) nounwind { +; RV32F-LABEL: constraint_f_float_abi_name: +; RV32F: # %bb.0: +; RV32F-NEXT: fmv.w.x fa0, a0 +; RV32F-NEXT: lui a0, %hi(gf) +; RV32F-NEXT: flw fs0, %lo(gf)(a0) +; RV32F-NEXT: #APP +; RV32F-NEXT: fadd.s ft0, fa0, fs0 +; RV32F-NEXT: #NO_APP +; RV32F-NEXT: fmv.x.w a0, ft0 +; RV32F-NEXT: ret +; +; RV64F-LABEL: constraint_f_float_abi_name: +; RV64F: # %bb.0: +; RV64F-NEXT: fmv.w.x fa0, a0 +; RV64F-NEXT: lui a0, %hi(gf) +; RV64F-NEXT: flw fs0, %lo(gf)(a0) +; RV64F-NEXT: #APP +; RV64F-NEXT: fadd.s ft0, fa0, fs0 +; RV64F-NEXT: #NO_APP +; RV64F-NEXT: fmv.x.w a0, ft0 +; RV64F-NEXT: ret + %1 = load float, float* @gf + %2 = tail call float asm "fadd.s $0, $1, $2", "={ft0},{fa0},{fs0}"(float %a, float %1) + ret float %2 +}