llvm/llvm/test/CodeGen/RISCV/float-zfa.ll

; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=riscv32 -target-abi ilp32f -mattr=+zfa < %s \
; RUN:     | FileCheck %s
; RUN: llc -mtriple=riscv64 -target-abi lp64f -mattr=+zfa < %s \
; RUN:     | FileCheck %s

define float @loadfpimm1() {
; CHECK-LABEL: loadfpimm1:
; CHECK:       # %bb.0:
; CHECK-NEXT:    fli.s fa0, 0.0625
; CHECK-NEXT:    ret
  ret float 0.0625
}

define float @loadfpimm2() {
; CHECK-LABEL: loadfpimm2:
; CHECK:       # %bb.0:
; CHECK-NEXT:    fli.s fa0, 0.75
; CHECK-NEXT:    ret
  ret float 0.75
}

define float @loadfpimm3() {
; CHECK-LABEL: loadfpimm3:
; CHECK:       # %bb.0:
; CHECK-NEXT:    fli.s fa0, 1.25
; CHECK-NEXT:    ret
  ret float 1.25
}

define float @loadfpimm4() {
; CHECK-LABEL: loadfpimm4:
; CHECK:       # %bb.0:
; CHECK-NEXT:    fli.s fa0, 3.0
; CHECK-NEXT:    ret
  ret float 3.0
}

define float @loadfpimm5() {
; CHECK-LABEL: loadfpimm5:
; CHECK:       # %bb.0:
; CHECK-NEXT:    fli.s fa0, 256.0
; CHECK-NEXT:    ret
  ret float 256.0
}

define float @loadfpimm6() {
; CHECK-LABEL: loadfpimm6:
; CHECK:       # %bb.0:
; CHECK-NEXT:    fli.s fa0, inf
; CHECK-NEXT:    ret
  ret float 0x7FF0000000000000
}

define float @loadfpimm7() {
; CHECK-LABEL: loadfpimm7:
; CHECK:       # %bb.0:
; CHECK-NEXT:    fli.s fa0, nan
; CHECK-NEXT:    ret
  ret float 0x7FF8000000000000
}

define float @loadfpimm8() {
; CHECK-LABEL: loadfpimm8:
; CHECK:       # %bb.0:
; CHECK-NEXT:    fli.s fa0, min
; CHECK-NEXT:    ret
  ret float 0x3810000000000000
}

define float @loadfpimm9() {
; CHECK-LABEL: loadfpimm9:
; CHECK:       # %bb.0:
; CHECK-NEXT:    lui a0, 276464
; CHECK-NEXT:    fmv.w.x fa0, a0
; CHECK-NEXT:    ret
  ret float 255.0
}

; This is the f16 minimum value. Make sure we don't use fli.s.
define float @loadfpimm10() {
; CHECK-LABEL: loadfpimm10:
; CHECK:       # %bb.0:
; CHECK-NEXT:    lui a0, 231424
; CHECK-NEXT:    fmv.w.x fa0, a0
; CHECK-NEXT:    ret
  ret float 0.00006103515625
}

define float @loadfpimm11() {
; CHECK-LABEL: loadfpimm11:
; CHECK:       # %bb.0:
; CHECK-NEXT:    fli.s fa0, -1.0
; CHECK-NEXT:    ret
  ret float -1.0
}

; Ensure fli isn't directly used for negated versions of numbers in the fli
; table.
define float @loadfpimm12() {
; CHECK-LABEL: loadfpimm12:
; CHECK:       # %bb.0:
; CHECK-NEXT:    fli.s fa5, 2.0
; CHECK-NEXT:    fneg.s fa0, fa5
; CHECK-NEXT:    ret
  ret float -2.0
}

; Ensure fli isn't directly used for negative min normal value.
define float @loadfpimm13() {
; CHECK-LABEL: loadfpimm13:
; CHECK:       # %bb.0:
; CHECK-NEXT:    fli.s fa5, min
; CHECK-NEXT:    fneg.s fa0, fa5
; CHECK-NEXT:    ret
  ret float 0xb810000000000000
}

declare float @llvm.minimum.f32(float, float)

define float @fminm_s(float %a, float %b) nounwind {
; CHECK-LABEL: fminm_s:
; CHECK:       # %bb.0:
; CHECK-NEXT:    fminm.s fa0, fa0, fa1
; CHECK-NEXT:    ret
  %1 = call float @llvm.minimum.f32(float %a, float %b)
  ret float %1
}

declare float @llvm.maximum.f32(float, float)

define float @fmaxm_s(float %a, float %b) nounwind {
; CHECK-LABEL: fmaxm_s:
; CHECK:       # %bb.0:
; CHECK-NEXT:    fmaxm.s fa0, fa0, fa1
; CHECK-NEXT:    ret
  %1 = call float @llvm.maximum.f32(float %a, float %b)
  ret float %1
}


define float @fround_s_1(float %a) nounwind {
; CHECK-LABEL: fround_s_1:
; CHECK:       # %bb.0:
; CHECK-NEXT:    fround.s fa0, fa0, rmm
; CHECK-NEXT:    ret
  %call = tail call float @roundf(float %a) nounwind readnone
  ret float %call
}

declare float @roundf(float) nounwind readnone


define float @fround_s_2(float %a) nounwind {
; CHECK-LABEL: fround_s_2:
; CHECK:       # %bb.0:
; CHECK-NEXT:    fround.s fa0, fa0, rdn
; CHECK-NEXT:    ret
  %call = tail call float @floorf(float %a) nounwind readnone
  ret float %call
}

declare float @floorf(float) nounwind readnone


define float @fround_s_3(float %a) nounwind {
; CHECK-LABEL: fround_s_3:
; CHECK:       # %bb.0:
; CHECK-NEXT:    fround.s fa0, fa0, rup
; CHECK-NEXT:    ret
  %call = tail call float @ceilf(float %a) nounwind readnone
  ret float %call
}

declare float @ceilf(float) nounwind readnone


define float @fround_s_4(float %a) nounwind {
; CHECK-LABEL: fround_s_4:
; CHECK:       # %bb.0:
; CHECK-NEXT:    fround.s fa0, fa0, rtz
; CHECK-NEXT:    ret
  %call = tail call float @truncf(float %a) nounwind readnone
  ret float %call
}

declare float @truncf(float) nounwind readnone


define float @fround_s_5(float %a) nounwind {
; CHECK-LABEL: fround_s_5:
; CHECK:       # %bb.0:
; CHECK-NEXT:    fround.s fa0, fa0
; CHECK-NEXT:    ret
  %call = tail call float @nearbyintf(float %a) nounwind readnone
  ret float %call
}

declare float @nearbyintf(float) nounwind readnone


define float @froundnx_s(float %a) nounwind {
; CHECK-LABEL: froundnx_s:
; CHECK:       # %bb.0:
; CHECK-NEXT:    froundnx.s fa0, fa0
; CHECK-NEXT:    ret
  %call = tail call float @rintf(float %a) nounwind readnone
  ret float %call
}

declare float @rintf(float) nounwind readnone

declare i1 @llvm.experimental.constrained.fcmp.f32(float, float, metadata, metadata)

define i32 @fcmp_olt_q(float %a, float %b) nounwind strictfp {
; CHECK-LABEL: fcmp_olt_q:
; CHECK:       # %bb.0:
; CHECK-NEXT:    fltq.s a0, fa0, fa1
; CHECK-NEXT:    ret
  %1 = call i1 @llvm.experimental.constrained.fcmp.f32(float %a, float %b, metadata !"olt", metadata !"fpexcept.strict") strictfp
  %2 = zext i1 %1 to i32
  ret i32 %2
}

define i32 @fcmp_ole_q(float %a, float %b) nounwind strictfp {
; CHECK-LABEL: fcmp_ole_q:
; CHECK:       # %bb.0:
; CHECK-NEXT:    fleq.s a0, fa0, fa1
; CHECK-NEXT:    ret
  %1 = call i1 @llvm.experimental.constrained.fcmp.f32(float %a, float %b, metadata !"ole", metadata !"fpexcept.strict") strictfp
  %2 = zext i1 %1 to i32
  ret i32 %2
}

define i32 @fcmp_one_q(float %a, float %b) nounwind strictfp {
; CHECK-LABEL: fcmp_one_q:
; CHECK:       # %bb.0:
; CHECK-NEXT:    fltq.s a0, fa0, fa1
; CHECK-NEXT:    fltq.s a1, fa1, fa0
; CHECK-NEXT:    or a0, a1, a0
; CHECK-NEXT:    ret
  %1 = call i1 @llvm.experimental.constrained.fcmp.f32(float %a, float %b, metadata !"one", metadata !"fpexcept.strict") strictfp
  %2 = zext i1 %1 to i32
  ret i32 %2
}

define i32 @fcmp_ueq_q(float %a, float %b) nounwind strictfp {
; CHECK-LABEL: fcmp_ueq_q:
; CHECK:       # %bb.0:
; CHECK-NEXT:    fltq.s a0, fa0, fa1
; CHECK-NEXT:    fltq.s a1, fa1, fa0
; CHECK-NEXT:    or a0, a1, a0
; CHECK-NEXT:    xori a0, a0, 1
; CHECK-NEXT:    ret
  %1 = call i1 @llvm.experimental.constrained.fcmp.f32(float %a, float %b, metadata !"ueq", metadata !"fpexcept.strict") strictfp
  %2 = zext i1 %1 to i32
  ret i32 %2
}

declare void @foo(float, float)

; Make sure we use two fli instructions instead of copying.
define void @fli_remat() {
; CHECK-LABEL: fli_remat:
; CHECK:       # %bb.0:
; CHECK-NEXT:    fli.s fa0, 1.0
; CHECK-NEXT:    fli.s fa1, 1.0
; CHECK-NEXT:    tail foo
  tail call void @foo(float 1.000000e+00, float 1.000000e+00)
  ret void
}

define float @fadd_neg_0p5(float %x) {
; CHECK-LABEL: fadd_neg_0p5:
; CHECK:       # %bb.0:
; CHECK-NEXT:    fli.s fa5, 0.5
; CHECK-NEXT:    fsub.s fa0, fa0, fa5
; CHECK-NEXT:    ret
  %a = fadd float %x, -0.5
  ret float %a
}

define float @fma_neg_addend(float %x, float %y) nounwind {
; CHECK-LABEL: fma_neg_addend:
; CHECK:       # %bb.0:
; CHECK-NEXT:    fli.s fa5, 0.5
; CHECK-NEXT:    fmsub.s fa0, fa0, fa1, fa5
; CHECK-NEXT:    ret
  %a = call float @llvm.fma.f32(float %x, float %y, float -0.5)
  ret float %a
}

define float @fma_neg_multiplicand(float %x, float %y) nounwind {
; CHECK-LABEL: fma_neg_multiplicand:
; CHECK:       # %bb.0:
; CHECK-NEXT:    fli.s fa5, 0.125
; CHECK-NEXT:    fnmsub.s fa0, fa5, fa0, fa1
; CHECK-NEXT:    ret
  %a = call float @llvm.fma.f32(float %x, float -0.125, float %y)
  ret float %a
}

define float @fma_neg_addend_multiplicand(float %x) nounwind {
; CHECK-LABEL: fma_neg_addend_multiplicand:
; CHECK:       # %bb.0:
; CHECK-NEXT:    fli.s fa5, 0.25
; CHECK-NEXT:    fli.s fa4, 0.5
; CHECK-NEXT:    fnmadd.s fa0, fa4, fa0, fa5
; CHECK-NEXT:    ret
  %a = call float @llvm.fma.f32(float %x, float -0.5, float -0.25)
  ret float %a
}

define float @select_loadfpimm(float %x) nounwind {
; CHECK-LABEL: select_loadfpimm:
; CHECK:       # %bb.0: # %entry
; CHECK-NEXT:    fmv.w.x fa5, zero
; CHECK-NEXT:    fle.s a0, fa5, fa0
; CHECK-NEXT:    fli.s fa0, 0.5
; CHECK-NEXT:    bnez a0, .LBB30_2
; CHECK-NEXT:  # %bb.1:
; CHECK-NEXT:    fneg.s fa0, fa0
; CHECK-NEXT:  .LBB30_2: # %entry
; CHECK-NEXT:    ret
entry:
  %cmp = fcmp ult float %x, 0.000000e+00
  %sel = select i1 %cmp, float -5.000000e-01, float 5.000000e-01
  ret float %sel
}