Compiler projects using llvm
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=riscv32 -verify-machineinstrs -no-integrated-as < %s \
; RUN:   | FileCheck -check-prefix=RV32I %s
; RUN: llc -mtriple=riscv64 -verify-machineinstrs -no-integrated-as < %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) # 4-byte Folded Spill
; RV32I-NEXT:    mv ra, a0
; RV32I-NEXT:    #APP
; RV32I-NEXT:    addi a0, ra, 0
; RV32I-NEXT:    #NO_APP
; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
; 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) # 8-byte Folded Spill
; RV64I-NEXT:    mv ra, a0
; RV64I-NEXT:    #APP
; RV64I-NEXT:    addi a0, ra, 0
; RV64I-NEXT:    #NO_APP
; RV64I-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
; 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) # 4-byte Folded Spill
; RV32I-NEXT:    mv ra, a0
; RV32I-NEXT:    #APP
; RV32I-NEXT:    addi a0, ra, 0
; RV32I-NEXT:    #NO_APP
; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
; 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) # 8-byte Folded Spill
; RV64I-NEXT:    mv ra, a0
; RV64I-NEXT:    #APP
; RV64I-NEXT:    addi a0, ra, 0
; RV64I-NEXT:    #NO_APP
; RV64I-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
; 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) # 4-byte Folded Spill
; RV32I-NEXT:    mv gp, a0
; RV32I-NEXT:    #APP
; RV32I-NEXT:    addi a0, gp, 0
; RV32I-NEXT:    #NO_APP
; RV32I-NEXT:    lw gp, 12(sp) # 4-byte Folded Reload
; 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) # 8-byte Folded Spill
; RV64I-NEXT:    mv gp, a0
; RV64I-NEXT:    #APP
; RV64I-NEXT:    addi a0, gp, 0
; RV64I-NEXT:    #NO_APP
; RV64I-NEXT:    ld gp, 8(sp) # 8-byte Folded Reload
; 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) # 4-byte Folded Spill
; RV32I-NEXT:    mv gp, a0
; RV32I-NEXT:    #APP
; RV32I-NEXT:    addi a0, gp, 0
; RV32I-NEXT:    #NO_APP
; RV32I-NEXT:    lw gp, 12(sp) # 4-byte Folded Reload
; 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) # 8-byte Folded Spill
; RV64I-NEXT:    mv gp, a0
; RV64I-NEXT:    #APP
; RV64I-NEXT:    addi a0, gp, 0
; RV64I-NEXT:    #NO_APP
; RV64I-NEXT:    ld gp, 8(sp) # 8-byte Folded Reload
; 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) # 4-byte Folded Spill
; RV32I-NEXT:    mv tp, a0
; RV32I-NEXT:    #APP
; RV32I-NEXT:    addi a0, tp, 0
; RV32I-NEXT:    #NO_APP
; RV32I-NEXT:    lw tp, 12(sp) # 4-byte Folded Reload
; 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) # 8-byte Folded Spill
; RV64I-NEXT:    mv tp, a0
; RV64I-NEXT:    #APP
; RV64I-NEXT:    addi a0, tp, 0
; RV64I-NEXT:    #NO_APP
; RV64I-NEXT:    ld tp, 8(sp) # 8-byte Folded Reload
; 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) # 4-byte Folded Spill
; RV32I-NEXT:    mv tp, a0
; RV32I-NEXT:    #APP
; RV32I-NEXT:    addi a0, tp, 0
; RV32I-NEXT:    #NO_APP
; RV32I-NEXT:    lw tp, 12(sp) # 4-byte Folded Reload
; 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) # 8-byte Folded Spill
; RV64I-NEXT:    mv tp, a0
; RV64I-NEXT:    #APP
; RV64I-NEXT:    addi a0, tp, 0
; RV64I-NEXT:    #NO_APP
; RV64I-NEXT:    ld tp, 8(sp) # 8-byte Folded Reload
; 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) # 4-byte Folded Spill
; RV32I-NEXT:    mv s0, a0
; RV32I-NEXT:    #APP
; RV32I-NEXT:    addi a0, s0, 0
; RV32I-NEXT:    #NO_APP
; RV32I-NEXT:    lw s0, 12(sp) # 4-byte Folded Reload
; 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) # 8-byte Folded Spill
; RV64I-NEXT:    mv s0, a0
; RV64I-NEXT:    #APP
; RV64I-NEXT:    addi a0, s0, 0
; RV64I-NEXT:    #NO_APP
; RV64I-NEXT:    ld s0, 8(sp) # 8-byte Folded Reload
; 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) # 4-byte Folded Spill
; RV32I-NEXT:    mv s0, a0
; RV32I-NEXT:    #APP
; RV32I-NEXT:    addi a0, s0, 0
; RV32I-NEXT:    #NO_APP
; RV32I-NEXT:    lw s0, 12(sp) # 4-byte Folded Reload
; 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) # 8-byte Folded Spill
; RV64I-NEXT:    mv s0, a0
; RV64I-NEXT:    #APP
; RV64I-NEXT:    addi a0, s0, 0
; RV64I-NEXT:    #NO_APP
; RV64I-NEXT:    ld s0, 8(sp) # 8-byte Folded Reload
; 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) # 4-byte Folded Spill
; RV32I-NEXT:    mv s0, a0
; RV32I-NEXT:    #APP
; RV32I-NEXT:    addi a0, s0, 0
; RV32I-NEXT:    #NO_APP
; RV32I-NEXT:    lw s0, 12(sp) # 4-byte Folded Reload
; 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) # 8-byte Folded Spill
; RV64I-NEXT:    mv s0, a0
; RV64I-NEXT:    #APP
; RV64I-NEXT:    addi a0, s0, 0
; RV64I-NEXT:    #NO_APP
; RV64I-NEXT:    ld s0, 8(sp) # 8-byte Folded Reload
; 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) # 4-byte Folded Spill
; RV32I-NEXT:    mv s1, a0
; RV32I-NEXT:    #APP
; RV32I-NEXT:    addi a0, s1, 0
; RV32I-NEXT:    #NO_APP
; RV32I-NEXT:    lw s1, 12(sp) # 4-byte Folded Reload
; 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) # 8-byte Folded Spill
; RV64I-NEXT:    mv s1, a0
; RV64I-NEXT:    #APP
; RV64I-NEXT:    addi a0, s1, 0
; RV64I-NEXT:    #NO_APP
; RV64I-NEXT:    ld s1, 8(sp) # 8-byte Folded Reload
; 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) # 4-byte Folded Spill
; RV32I-NEXT:    mv s1, a0
; RV32I-NEXT:    #APP
; RV32I-NEXT:    addi a0, s1, 0
; RV32I-NEXT:    #NO_APP
; RV32I-NEXT:    lw s1, 12(sp) # 4-byte Folded Reload
; 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) # 8-byte Folded Spill
; RV64I-NEXT:    mv s1, a0
; RV64I-NEXT:    #APP
; RV64I-NEXT:    addi a0, s1, 0
; RV64I-NEXT:    #NO_APP
; RV64I-NEXT:    ld s1, 8(sp) # 8-byte Folded Reload
; 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) # 4-byte Folded Spill
; RV32I-NEXT:    mv s2, a0
; RV32I-NEXT:    #APP
; RV32I-NEXT:    addi a0, s2, 0
; RV32I-NEXT:    #NO_APP
; RV32I-NEXT:    lw s2, 12(sp) # 4-byte Folded Reload
; 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) # 8-byte Folded Spill
; RV64I-NEXT:    mv s2, a0
; RV64I-NEXT:    #APP
; RV64I-NEXT:    addi a0, s2, 0
; RV64I-NEXT:    #NO_APP
; RV64I-NEXT:    ld s2, 8(sp) # 8-byte Folded Reload
; 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) # 4-byte Folded Spill
; RV32I-NEXT:    mv s2, a0
; RV32I-NEXT:    #APP
; RV32I-NEXT:    addi a0, s2, 0
; RV32I-NEXT:    #NO_APP
; RV32I-NEXT:    lw s2, 12(sp) # 4-byte Folded Reload
; 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) # 8-byte Folded Spill
; RV64I-NEXT:    mv s2, a0
; RV64I-NEXT:    #APP
; RV64I-NEXT:    addi a0, s2, 0
; RV64I-NEXT:    #NO_APP
; RV64I-NEXT:    ld s2, 8(sp) # 8-byte Folded Reload
; 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) # 4-byte Folded Spill
; RV32I-NEXT:    mv s3, a0
; RV32I-NEXT:    #APP
; RV32I-NEXT:    addi a0, s3, 0
; RV32I-NEXT:    #NO_APP
; RV32I-NEXT:    lw s3, 12(sp) # 4-byte Folded Reload
; 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) # 8-byte Folded Spill
; RV64I-NEXT:    mv s3, a0
; RV64I-NEXT:    #APP
; RV64I-NEXT:    addi a0, s3, 0
; RV64I-NEXT:    #NO_APP
; RV64I-NEXT:    ld s3, 8(sp) # 8-byte Folded Reload
; 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) # 4-byte Folded Spill
; RV32I-NEXT:    mv s3, a0
; RV32I-NEXT:    #APP
; RV32I-NEXT:    addi a0, s3, 0
; RV32I-NEXT:    #NO_APP
; RV32I-NEXT:    lw s3, 12(sp) # 4-byte Folded Reload
; 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) # 8-byte Folded Spill
; RV64I-NEXT:    mv s3, a0
; RV64I-NEXT:    #APP
; RV64I-NEXT:    addi a0, s3, 0
; RV64I-NEXT:    #NO_APP
; RV64I-NEXT:    ld s3, 8(sp) # 8-byte Folded Reload
; 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) # 4-byte Folded Spill
; RV32I-NEXT:    mv s4, a0
; RV32I-NEXT:    #APP
; RV32I-NEXT:    addi a0, s4, 0
; RV32I-NEXT:    #NO_APP
; RV32I-NEXT:    lw s4, 12(sp) # 4-byte Folded Reload
; 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) # 8-byte Folded Spill
; RV64I-NEXT:    mv s4, a0
; RV64I-NEXT:    #APP
; RV64I-NEXT:    addi a0, s4, 0
; RV64I-NEXT:    #NO_APP
; RV64I-NEXT:    ld s4, 8(sp) # 8-byte Folded Reload
; 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) # 4-byte Folded Spill
; RV32I-NEXT:    mv s4, a0
; RV32I-NEXT:    #APP
; RV32I-NEXT:    addi a0, s4, 0
; RV32I-NEXT:    #NO_APP
; RV32I-NEXT:    lw s4, 12(sp) # 4-byte Folded Reload
; 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) # 8-byte Folded Spill
; RV64I-NEXT:    mv s4, a0
; RV64I-NEXT:    #APP
; RV64I-NEXT:    addi a0, s4, 0
; RV64I-NEXT:    #NO_APP
; RV64I-NEXT:    ld s4, 8(sp) # 8-byte Folded Reload
; 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) # 4-byte Folded Spill
; RV32I-NEXT:    mv s5, a0
; RV32I-NEXT:    #APP
; RV32I-NEXT:    addi a0, s5, 0
; RV32I-NEXT:    #NO_APP
; RV32I-NEXT:    lw s5, 12(sp) # 4-byte Folded Reload
; 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) # 8-byte Folded Spill
; RV64I-NEXT:    mv s5, a0
; RV64I-NEXT:    #APP
; RV64I-NEXT:    addi a0, s5, 0
; RV64I-NEXT:    #NO_APP
; RV64I-NEXT:    ld s5, 8(sp) # 8-byte Folded Reload
; 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) # 4-byte Folded Spill
; RV32I-NEXT:    mv s5, a0
; RV32I-NEXT:    #APP
; RV32I-NEXT:    addi a0, s5, 0
; RV32I-NEXT:    #NO_APP
; RV32I-NEXT:    lw s5, 12(sp) # 4-byte Folded Reload
; 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) # 8-byte Folded Spill
; RV64I-NEXT:    mv s5, a0
; RV64I-NEXT:    #APP
; RV64I-NEXT:    addi a0, s5, 0
; RV64I-NEXT:    #NO_APP
; RV64I-NEXT:    ld s5, 8(sp) # 8-byte Folded Reload
; 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) # 4-byte Folded Spill
; RV32I-NEXT:    mv s6, a0
; RV32I-NEXT:    #APP
; RV32I-NEXT:    addi a0, s6, 0
; RV32I-NEXT:    #NO_APP
; RV32I-NEXT:    lw s6, 12(sp) # 4-byte Folded Reload
; 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) # 8-byte Folded Spill
; RV64I-NEXT:    mv s6, a0
; RV64I-NEXT:    #APP
; RV64I-NEXT:    addi a0, s6, 0
; RV64I-NEXT:    #NO_APP
; RV64I-NEXT:    ld s6, 8(sp) # 8-byte Folded Reload
; 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) # 4-byte Folded Spill
; RV32I-NEXT:    mv s6, a0
; RV32I-NEXT:    #APP
; RV32I-NEXT:    addi a0, s6, 0
; RV32I-NEXT:    #NO_APP
; RV32I-NEXT:    lw s6, 12(sp) # 4-byte Folded Reload
; 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) # 8-byte Folded Spill
; RV64I-NEXT:    mv s6, a0
; RV64I-NEXT:    #APP
; RV64I-NEXT:    addi a0, s6, 0
; RV64I-NEXT:    #NO_APP
; RV64I-NEXT:    ld s6, 8(sp) # 8-byte Folded Reload
; 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) # 4-byte Folded Spill
; RV32I-NEXT:    mv s7, a0
; RV32I-NEXT:    #APP
; RV32I-NEXT:    addi a0, s7, 0
; RV32I-NEXT:    #NO_APP
; RV32I-NEXT:    lw s7, 12(sp) # 4-byte Folded Reload
; 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) # 8-byte Folded Spill
; RV64I-NEXT:    mv s7, a0
; RV64I-NEXT:    #APP
; RV64I-NEXT:    addi a0, s7, 0
; RV64I-NEXT:    #NO_APP
; RV64I-NEXT:    ld s7, 8(sp) # 8-byte Folded Reload
; 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) # 4-byte Folded Spill
; RV32I-NEXT:    mv s7, a0
; RV32I-NEXT:    #APP
; RV32I-NEXT:    addi a0, s7, 0
; RV32I-NEXT:    #NO_APP
; RV32I-NEXT:    lw s7, 12(sp) # 4-byte Folded Reload
; 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) # 8-byte Folded Spill
; RV64I-NEXT:    mv s7, a0
; RV64I-NEXT:    #APP
; RV64I-NEXT:    addi a0, s7, 0
; RV64I-NEXT:    #NO_APP
; RV64I-NEXT:    ld s7, 8(sp) # 8-byte Folded Reload
; 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) # 4-byte Folded Spill
; RV32I-NEXT:    mv s8, a0
; RV32I-NEXT:    #APP
; RV32I-NEXT:    addi a0, s8, 0
; RV32I-NEXT:    #NO_APP
; RV32I-NEXT:    lw s8, 12(sp) # 4-byte Folded Reload
; 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) # 8-byte Folded Spill
; RV64I-NEXT:    mv s8, a0
; RV64I-NEXT:    #APP
; RV64I-NEXT:    addi a0, s8, 0
; RV64I-NEXT:    #NO_APP
; RV64I-NEXT:    ld s8, 8(sp) # 8-byte Folded Reload
; 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) # 4-byte Folded Spill
; RV32I-NEXT:    mv s8, a0
; RV32I-NEXT:    #APP
; RV32I-NEXT:    addi a0, s8, 0
; RV32I-NEXT:    #NO_APP
; RV32I-NEXT:    lw s8, 12(sp) # 4-byte Folded Reload
; 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) # 8-byte Folded Spill
; RV64I-NEXT:    mv s8, a0
; RV64I-NEXT:    #APP
; RV64I-NEXT:    addi a0, s8, 0
; RV64I-NEXT:    #NO_APP
; RV64I-NEXT:    ld s8, 8(sp) # 8-byte Folded Reload
; 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) # 4-byte Folded Spill
; RV32I-NEXT:    mv s9, a0
; RV32I-NEXT:    #APP
; RV32I-NEXT:    addi a0, s9, 0
; RV32I-NEXT:    #NO_APP
; RV32I-NEXT:    lw s9, 12(sp) # 4-byte Folded Reload
; 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) # 8-byte Folded Spill
; RV64I-NEXT:    mv s9, a0
; RV64I-NEXT:    #APP
; RV64I-NEXT:    addi a0, s9, 0
; RV64I-NEXT:    #NO_APP
; RV64I-NEXT:    ld s9, 8(sp) # 8-byte Folded Reload
; 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) # 4-byte Folded Spill
; RV32I-NEXT:    mv s9, a0
; RV32I-NEXT:    #APP
; RV32I-NEXT:    addi a0, s9, 0
; RV32I-NEXT:    #NO_APP
; RV32I-NEXT:    lw s9, 12(sp) # 4-byte Folded Reload
; 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) # 8-byte Folded Spill
; RV64I-NEXT:    mv s9, a0
; RV64I-NEXT:    #APP
; RV64I-NEXT:    addi a0, s9, 0
; RV64I-NEXT:    #NO_APP
; RV64I-NEXT:    ld s9, 8(sp) # 8-byte Folded Reload
; 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) # 4-byte Folded Spill
; RV32I-NEXT:    mv s10, a0
; RV32I-NEXT:    #APP
; RV32I-NEXT:    addi a0, s10, 0
; RV32I-NEXT:    #NO_APP
; RV32I-NEXT:    lw s10, 12(sp) # 4-byte Folded Reload
; 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) # 8-byte Folded Spill
; RV64I-NEXT:    mv s10, a0
; RV64I-NEXT:    #APP
; RV64I-NEXT:    addi a0, s10, 0
; RV64I-NEXT:    #NO_APP
; RV64I-NEXT:    ld s10, 8(sp) # 8-byte Folded Reload
; 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) # 4-byte Folded Spill
; RV32I-NEXT:    mv s10, a0
; RV32I-NEXT:    #APP
; RV32I-NEXT:    addi a0, s10, 0
; RV32I-NEXT:    #NO_APP
; RV32I-NEXT:    lw s10, 12(sp) # 4-byte Folded Reload
; 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) # 8-byte Folded Spill
; RV64I-NEXT:    mv s10, a0
; RV64I-NEXT:    #APP
; RV64I-NEXT:    addi a0, s10, 0
; RV64I-NEXT:    #NO_APP
; RV64I-NEXT:    ld s10, 8(sp) # 8-byte Folded Reload
; 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) # 4-byte Folded Spill
; RV32I-NEXT:    mv s11, a0
; RV32I-NEXT:    #APP
; RV32I-NEXT:    addi a0, s11, 0
; RV32I-NEXT:    #NO_APP
; RV32I-NEXT:    lw s11, 12(sp) # 4-byte Folded Reload
; 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) # 8-byte Folded Spill
; RV64I-NEXT:    mv s11, a0
; RV64I-NEXT:    #APP
; RV64I-NEXT:    addi a0, s11, 0
; RV64I-NEXT:    #NO_APP
; RV64I-NEXT:    ld s11, 8(sp) # 8-byte Folded Reload
; 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) # 4-byte Folded Spill
; RV32I-NEXT:    mv s11, a0
; RV32I-NEXT:    #APP
; RV32I-NEXT:    addi a0, s11, 0
; RV32I-NEXT:    #NO_APP
; RV32I-NEXT:    lw s11, 12(sp) # 4-byte Folded Reload
; 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) # 8-byte Folded Spill
; RV64I-NEXT:    mv s11, a0
; RV64I-NEXT:    #APP
; RV64I-NEXT:    addi a0, s11, 0
; RV64I-NEXT:    #NO_APP
; RV64I-NEXT:    ld s11, 8(sp) # 8-byte Folded Reload
; 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
}