}
}
+ // 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<unsigned>(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<unsigned, unsigned> FReg =
StringSwitch<std::pair<unsigned, unsigned>>(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})
- .Default({-1U, -1U});
- if (FReg.first != -1U)
+ .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({RISCV::NoRegister, RISCV::NoRegister});
+ if (FReg.first != RISCV::NoRegister)
return Subtarget.hasStdExtD()
? std::make_pair(FReg.second, &RISCV::FPR64RegClass)
: std::make_pair(FReg.first, &RISCV::FPR32RegClass);
--- /dev/null
+; 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
+}
--- /dev/null
+; 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
+}
%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
+}
--- /dev/null
+; 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
+}
%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
+}