llvm/llvm/test/CodeGen/RISCV/GlobalISel/float-intrinsics.ll

; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: sed 's/iXLen/i32/g' %s | llc -mtriple=riscv32 -global-isel -mattr=+f \
; RUN:   -verify-machineinstrs -target-abi=ilp32f \
; RUN:   | FileCheck -check-prefix=RV32IF %s
; RUN: sed 's/iXLen/i32/g' %s | llc -mtriple=riscv32 -global-isel -mattr=+d \
; RUN:   -verify-machineinstrs -target-abi=ilp32f \
; RUN:   | FileCheck -check-prefix=RV32IF %s
; RUN: sed 's/iXLen/i64/g' %s | llc -mtriple=riscv64 -global-isel -mattr=+f \
; RUN:   -verify-machineinstrs -target-abi=lp64f \
; RUN:   | FileCheck -check-prefix=RV64IF %s
; RUN: sed 's/iXLen/i64/g' %s | llc -mtriple=riscv64 -global-isel  -mattr=+d \
; RUN:   -verify-machineinstrs -target-abi=lp64d \
; RUN:   | FileCheck -check-prefix=RV64IF %s

define float @sqrt_f32(float %a) nounwind {
; RV32IF-LABEL: sqrt_f32:
; RV32IF:       # %bb.0:
; RV32IF-NEXT:    fsqrt.s fa0, fa0
; RV32IF-NEXT:    ret
;
; RV64IF-LABEL: sqrt_f32:
; RV64IF:       # %bb.0:
; RV64IF-NEXT:    fsqrt.s fa0, fa0
; RV64IF-NEXT:    ret
  %1 = call float @llvm.sqrt.f32(float %a)
  ret float %1
}

define float @fma_f32(float %a, float %b, float %c) nounwind {
; RV32IF-LABEL: fma_f32:
; RV32IF:       # %bb.0:
; RV32IF-NEXT:    fmadd.s fa0, fa0, fa1, fa2
; RV32IF-NEXT:    ret
;
; RV64IF-LABEL: fma_f32:
; RV64IF:       # %bb.0:
; RV64IF-NEXT:    fmadd.s fa0, fa0, fa1, fa2
; RV64IF-NEXT:    ret
  %1 = call float @llvm.fma.f32(float %a, float %b, float %c)
  ret float %1
}

define float @fmuladd_f32(float %a, float %b, float %c) nounwind {
; RV32IF-LABEL: fmuladd_f32:
; RV32IF:       # %bb.0:
; RV32IF-NEXT:    fmadd.s fa0, fa0, fa1, fa2
; RV32IF-NEXT:    ret
;
; RV64IF-LABEL: fmuladd_f32:
; RV64IF:       # %bb.0:
; RV64IF-NEXT:    fmadd.s fa0, fa0, fa1, fa2
; RV64IF-NEXT:    ret
  %1 = call float @llvm.fmuladd.f32(float %a, float %b, float %c)
  ret float %1
}

define float @fabs_f32(float %a) nounwind {
; RV32IF-LABEL: fabs_f32:
; RV32IF:       # %bb.0:
; RV32IF-NEXT:    fabs.s fa0, fa0
; RV32IF-NEXT:    ret
;
; RV64IF-LABEL: fabs_f32:
; RV64IF:       # %bb.0:
; RV64IF-NEXT:    fabs.s fa0, fa0
; RV64IF-NEXT:    ret
  %1 = call float @llvm.fabs.f32(float %a)
  ret float %1
}

define float @minnum_f32(float %a, float %b) nounwind {
; RV32IF-LABEL: minnum_f32:
; RV32IF:       # %bb.0:
; RV32IF-NEXT:    fmin.s fa0, fa0, fa1
; RV32IF-NEXT:    ret
;
; RV64IF-LABEL: minnum_f32:
; RV64IF:       # %bb.0:
; RV64IF-NEXT:    fmin.s fa0, fa0, fa1
; RV64IF-NEXT:    ret
  %1 = call float @llvm.minnum.f32(float %a, float %b)
  ret float %1
}

define float @maxnum_f32(float %a, float %b) nounwind {
; RV32IF-LABEL: maxnum_f32:
; RV32IF:       # %bb.0:
; RV32IF-NEXT:    fmax.s fa0, fa0, fa1
; RV32IF-NEXT:    ret
;
; RV64IF-LABEL: maxnum_f32:
; RV64IF:       # %bb.0:
; RV64IF-NEXT:    fmax.s fa0, fa0, fa1
; RV64IF-NEXT:    ret
  %1 = call float @llvm.maxnum.f32(float %a, float %b)
  ret float %1
}

define float @copysign_f32(float %a, float %b) nounwind {
; RV32IF-LABEL: copysign_f32:
; RV32IF:       # %bb.0:
; RV32IF-NEXT:    fsgnj.s fa0, fa0, fa1
; RV32IF-NEXT:    ret
;
; RV64IF-LABEL: copysign_f32:
; RV64IF:       # %bb.0:
; RV64IF-NEXT:    fsgnj.s fa0, fa0, fa1
; RV64IF-NEXT:    ret
  %1 = call float @llvm.copysign.f32(float %a, float %b)
  ret float %1
}

define float @ceil_f32(float %a) nounwind {
; RV32IF-LABEL: ceil_f32:
; RV32IF:       # %bb.0:
; RV32IF-NEXT:    addi sp, sp, -16
; RV32IF-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
; RV32IF-NEXT:    call ceilf
; RV32IF-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
; RV32IF-NEXT:    addi sp, sp, 16
; RV32IF-NEXT:    ret
;
; RV64IF-LABEL: ceil_f32:
; RV64IF:       # %bb.0:
; RV64IF-NEXT:    addi sp, sp, -16
; RV64IF-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
; RV64IF-NEXT:    call ceilf
; RV64IF-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
; RV64IF-NEXT:    addi sp, sp, 16
; RV64IF-NEXT:    ret
  %1 = call float @llvm.ceil.f32(float %a)
  ret float %1
}

define float @trunc_f32(float %a) nounwind {
; RV32IF-LABEL: trunc_f32:
; RV32IF:       # %bb.0:
; RV32IF-NEXT:    addi sp, sp, -16
; RV32IF-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
; RV32IF-NEXT:    call truncf
; RV32IF-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
; RV32IF-NEXT:    addi sp, sp, 16
; RV32IF-NEXT:    ret
;
; RV64IF-LABEL: trunc_f32:
; RV64IF:       # %bb.0:
; RV64IF-NEXT:    addi sp, sp, -16
; RV64IF-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
; RV64IF-NEXT:    call truncf
; RV64IF-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
; RV64IF-NEXT:    addi sp, sp, 16
; RV64IF-NEXT:    ret
  %1 = call float @llvm.trunc.f32(float %a)
  ret float %1
}

define float @rint_f32(float %a) nounwind {
; RV32IF-LABEL: rint_f32:
; RV32IF:       # %bb.0:
; RV32IF-NEXT:    addi sp, sp, -16
; RV32IF-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
; RV32IF-NEXT:    call rintf
; RV32IF-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
; RV32IF-NEXT:    addi sp, sp, 16
; RV32IF-NEXT:    ret
;
; RV64IF-LABEL: rint_f32:
; RV64IF:       # %bb.0:
; RV64IF-NEXT:    addi sp, sp, -16
; RV64IF-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
; RV64IF-NEXT:    call rintf
; RV64IF-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
; RV64IF-NEXT:    addi sp, sp, 16
; RV64IF-NEXT:    ret
  %1 = call float @llvm.rint.f32(float %a)
  ret float %1
}

define float @nearbyint_f32(float %a) nounwind {
; RV32IF-LABEL: nearbyint_f32:
; RV32IF:       # %bb.0:
; RV32IF-NEXT:    addi sp, sp, -16
; RV32IF-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
; RV32IF-NEXT:    call nearbyintf
; RV32IF-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
; RV32IF-NEXT:    addi sp, sp, 16
; RV32IF-NEXT:    ret
;
; RV64IF-LABEL: nearbyint_f32:
; RV64IF:       # %bb.0:
; RV64IF-NEXT:    addi sp, sp, -16
; RV64IF-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
; RV64IF-NEXT:    call nearbyintf
; RV64IF-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
; RV64IF-NEXT:    addi sp, sp, 16
; RV64IF-NEXT:    ret
  %1 = call float @llvm.nearbyint.f32(float %a)
  ret float %1
}

define float @round_f32(float %a) nounwind {
; RV32IF-LABEL: round_f32:
; RV32IF:       # %bb.0:
; RV32IF-NEXT:    addi sp, sp, -16
; RV32IF-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
; RV32IF-NEXT:    call roundf
; RV32IF-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
; RV32IF-NEXT:    addi sp, sp, 16
; RV32IF-NEXT:    ret
;
; RV64IF-LABEL: round_f32:
; RV64IF:       # %bb.0:
; RV64IF-NEXT:    addi sp, sp, -16
; RV64IF-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
; RV64IF-NEXT:    call roundf
; RV64IF-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
; RV64IF-NEXT:    addi sp, sp, 16
; RV64IF-NEXT:    ret
  %1 = call float @llvm.round.f32(float %a)
  ret float %1
}

define float @roundeven_f32(float %a) nounwind {
; RV32IF-LABEL: roundeven_f32:
; RV32IF:       # %bb.0:
; RV32IF-NEXT:    addi sp, sp, -16
; RV32IF-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
; RV32IF-NEXT:    call roundevenf
; RV32IF-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
; RV32IF-NEXT:    addi sp, sp, 16
; RV32IF-NEXT:    ret
;
; RV64IF-LABEL: roundeven_f32:
; RV64IF:       # %bb.0:
; RV64IF-NEXT:    addi sp, sp, -16
; RV64IF-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
; RV64IF-NEXT:    call roundevenf
; RV64IF-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
; RV64IF-NEXT:    addi sp, sp, 16
; RV64IF-NEXT:    ret
  %1 = call float @llvm.roundeven.f32(float %a)
  ret float %1
}

define i1 @fpclass(float %x) {
; RV32IF-LABEL: fpclass:
; RV32IF:       # %bb.0:
; RV32IF-NEXT:    fclass.s a0, fa0
; RV32IF-NEXT:    andi a0, a0, 927
; RV32IF-NEXT:    snez a0, a0
; RV32IF-NEXT:    ret
;
; RV64IF-LABEL: fpclass:
; RV64IF:       # %bb.0:
; RV64IF-NEXT:    fclass.s a0, fa0
; RV64IF-NEXT:    andi a0, a0, 927
; RV64IF-NEXT:    snez a0, a0
; RV64IF-NEXT:    ret
  %cmp = call i1 @llvm.is.fpclass.f32(float %x, i32 639)
  ret i1 %cmp
}

define i1 @isnan_fpclass(float %x) {
; RV32IF-LABEL: isnan_fpclass:
; RV32IF:       # %bb.0:
; RV32IF-NEXT:    fclass.s a0, fa0
; RV32IF-NEXT:    andi a0, a0, 768
; RV32IF-NEXT:    snez a0, a0
; RV32IF-NEXT:    ret
;
; RV64IF-LABEL: isnan_fpclass:
; RV64IF:       # %bb.0:
; RV64IF-NEXT:    fclass.s a0, fa0
; RV64IF-NEXT:    andi a0, a0, 768
; RV64IF-NEXT:    snez a0, a0
; RV64IF-NEXT:    ret
  %1 = call i1 @llvm.is.fpclass.f32(float %x, i32 3)  ; nan
  ret i1 %1
}

define i1 @isqnan_fpclass(float %x) {
; RV32IF-LABEL: isqnan_fpclass:
; RV32IF:       # %bb.0:
; RV32IF-NEXT:    fclass.s a0, fa0
; RV32IF-NEXT:    andi a0, a0, 512
; RV32IF-NEXT:    snez a0, a0
; RV32IF-NEXT:    ret
;
; RV64IF-LABEL: isqnan_fpclass:
; RV64IF:       # %bb.0:
; RV64IF-NEXT:    fclass.s a0, fa0
; RV64IF-NEXT:    andi a0, a0, 512
; RV64IF-NEXT:    snez a0, a0
; RV64IF-NEXT:    ret
  %1 = call i1 @llvm.is.fpclass.f32(float %x, i32 2)  ; qnan
  ret i1 %1
}

define i1 @issnan_fpclass(float %x) {
; RV32IF-LABEL: issnan_fpclass:
; RV32IF:       # %bb.0:
; RV32IF-NEXT:    fclass.s a0, fa0
; RV32IF-NEXT:    andi a0, a0, 256
; RV32IF-NEXT:    snez a0, a0
; RV32IF-NEXT:    ret
;
; RV64IF-LABEL: issnan_fpclass:
; RV64IF:       # %bb.0:
; RV64IF-NEXT:    fclass.s a0, fa0
; RV64IF-NEXT:    andi a0, a0, 256
; RV64IF-NEXT:    snez a0, a0
; RV64IF-NEXT:    ret
  %1 = call i1 @llvm.is.fpclass.f32(float %x, i32 1)  ; snan
  ret i1 %1
}

define i1 @isinf_fpclass(float %x) {
; RV32IF-LABEL: isinf_fpclass:
; RV32IF:       # %bb.0:
; RV32IF-NEXT:    fclass.s a0, fa0
; RV32IF-NEXT:    andi a0, a0, 129
; RV32IF-NEXT:    snez a0, a0
; RV32IF-NEXT:    ret
;
; RV64IF-LABEL: isinf_fpclass:
; RV64IF:       # %bb.0:
; RV64IF-NEXT:    fclass.s a0, fa0
; RV64IF-NEXT:    andi a0, a0, 129
; RV64IF-NEXT:    snez a0, a0
; RV64IF-NEXT:    ret
  %1 = call i1 @llvm.is.fpclass.f32(float %x, i32 516)  ; 0x204 = "inf"
  ret i1 %1
}

define i1 @isposinf_fpclass(float %x) {
; RV32IF-LABEL: isposinf_fpclass:
; RV32IF:       # %bb.0:
; RV32IF-NEXT:    fclass.s a0, fa0
; RV32IF-NEXT:    andi a0, a0, 128
; RV32IF-NEXT:    snez a0, a0
; RV32IF-NEXT:    ret
;
; RV64IF-LABEL: isposinf_fpclass:
; RV64IF:       # %bb.0:
; RV64IF-NEXT:    fclass.s a0, fa0
; RV64IF-NEXT:    andi a0, a0, 128
; RV64IF-NEXT:    snez a0, a0
; RV64IF-NEXT:    ret
  %1 = call i1 @llvm.is.fpclass.f32(float %x, i32 512)  ; 0x200 = "+inf"
  ret i1 %1
}

define i1 @isneginf_fpclass(float %x) {
; RV32IF-LABEL: isneginf_fpclass:
; RV32IF:       # %bb.0:
; RV32IF-NEXT:    fclass.s a0, fa0
; RV32IF-NEXT:    andi a0, a0, 1
; RV32IF-NEXT:    snez a0, a0
; RV32IF-NEXT:    ret
;
; RV64IF-LABEL: isneginf_fpclass:
; RV64IF:       # %bb.0:
; RV64IF-NEXT:    fclass.s a0, fa0
; RV64IF-NEXT:    andi a0, a0, 1
; RV64IF-NEXT:    snez a0, a0
; RV64IF-NEXT:    ret
  %1 = call i1 @llvm.is.fpclass.f32(float %x, i32 4)  ; "-inf"
  ret i1 %1
}

define i1 @isfinite_fpclass(float %x) {
; RV32IF-LABEL: isfinite_fpclass:
; RV32IF:       # %bb.0:
; RV32IF-NEXT:    fclass.s a0, fa0
; RV32IF-NEXT:    andi a0, a0, 126
; RV32IF-NEXT:    snez a0, a0
; RV32IF-NEXT:    ret
;
; RV64IF-LABEL: isfinite_fpclass:
; RV64IF:       # %bb.0:
; RV64IF-NEXT:    fclass.s a0, fa0
; RV64IF-NEXT:    andi a0, a0, 126
; RV64IF-NEXT:    snez a0, a0
; RV64IF-NEXT:    ret
  %1 = call i1 @llvm.is.fpclass.f32(float %x, i32 504)  ; 0x1f8 = "finite"
  ret i1 %1
}

define i1 @isposfinite_fpclass(float %x) {
; RV32IF-LABEL: isposfinite_fpclass:
; RV32IF:       # %bb.0:
; RV32IF-NEXT:    fclass.s a0, fa0
; RV32IF-NEXT:    andi a0, a0, 112
; RV32IF-NEXT:    snez a0, a0
; RV32IF-NEXT:    ret
;
; RV64IF-LABEL: isposfinite_fpclass:
; RV64IF:       # %bb.0:
; RV64IF-NEXT:    fclass.s a0, fa0
; RV64IF-NEXT:    andi a0, a0, 112
; RV64IF-NEXT:    snez a0, a0
; RV64IF-NEXT:    ret
  %1 = call i1 @llvm.is.fpclass.f32(float %x, i32 448)  ; 0x1c0 = "+finite"
  ret i1 %1
}

define i1 @isnegfinite_fpclass(float %x) {
; RV32IF-LABEL: isnegfinite_fpclass:
; RV32IF:       # %bb.0:
; RV32IF-NEXT:    fclass.s a0, fa0
; RV32IF-NEXT:    andi a0, a0, 14
; RV32IF-NEXT:    snez a0, a0
; RV32IF-NEXT:    ret
;
; RV64IF-LABEL: isnegfinite_fpclass:
; RV64IF:       # %bb.0:
; RV64IF-NEXT:    fclass.s a0, fa0
; RV64IF-NEXT:    andi a0, a0, 14
; RV64IF-NEXT:    snez a0, a0
; RV64IF-NEXT:    ret
  %1 = call i1 @llvm.is.fpclass.f32(float %x, i32 56)  ; 0x38 = "-finite"
  ret i1 %1
}

define i1 @isnotfinite_fpclass(float %x) {
; RV32IF-LABEL: isnotfinite_fpclass:
; RV32IF:       # %bb.0:
; RV32IF-NEXT:    fclass.s a0, fa0
; RV32IF-NEXT:    andi a0, a0, 897
; RV32IF-NEXT:    snez a0, a0
; RV32IF-NEXT:    ret
;
; RV64IF-LABEL: isnotfinite_fpclass:
; RV64IF:       # %bb.0:
; RV64IF-NEXT:    fclass.s a0, fa0
; RV64IF-NEXT:    andi a0, a0, 897
; RV64IF-NEXT:    snez a0, a0
; RV64IF-NEXT:    ret
  %1 = call i1 @llvm.is.fpclass.f32(float %x, i32 519)  ; ox207 = "inf|nan"
  ret i1 %1
}