; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
; RUN: llc -mtriple=riscv32 -mattr=+zfbfmin -verify-machineinstrs \
; RUN: -target-abi ilp32f < %s | FileCheck -check-prefixes=CHECK,RV32IZFBFMIN %s
; RUN: llc -mtriple=riscv64 -mattr=+zfbfmin -verify-machineinstrs \
; RUN: -target-abi lp64f < %s | FileCheck -check-prefixes=CHECK,RV64IZFBFMIN %s
; These tests descend from float-arith.ll, where each function was targeted at
; a particular RISC-V FPU instruction.
define bfloat @fadd_bf16(bfloat %a, bfloat %b) nounwind {
; CHECK-LABEL: fadd_bf16:
; CHECK: # %bb.0:
; CHECK-NEXT: fcvt.s.bf16 fa5, fa1
; CHECK-NEXT: fcvt.s.bf16 fa4, fa0
; CHECK-NEXT: fadd.s fa5, fa4, fa5
; CHECK-NEXT: fcvt.bf16.s fa0, fa5
; CHECK-NEXT: ret
%1 = fadd bfloat %a, %b
ret bfloat %1
}
define bfloat @fsub_bf16(bfloat %a, bfloat %b) nounwind {
; CHECK-LABEL: fsub_bf16:
; CHECK: # %bb.0:
; CHECK-NEXT: fcvt.s.bf16 fa5, fa1
; CHECK-NEXT: fcvt.s.bf16 fa4, fa0
; CHECK-NEXT: fsub.s fa5, fa4, fa5
; CHECK-NEXT: fcvt.bf16.s fa0, fa5
; CHECK-NEXT: ret
%1 = fsub bfloat %a, %b
ret bfloat %1
}
define bfloat @fmul_bf16(bfloat %a, bfloat %b) nounwind {
; CHECK-LABEL: fmul_bf16:
; CHECK: # %bb.0:
; CHECK-NEXT: fcvt.s.bf16 fa5, fa1
; CHECK-NEXT: fcvt.s.bf16 fa4, fa0
; CHECK-NEXT: fmul.s fa5, fa4, fa5
; CHECK-NEXT: fcvt.bf16.s fa0, fa5
; CHECK-NEXT: ret
%1 = fmul bfloat %a, %b
ret bfloat %1
}
define bfloat @fdiv_bf16(bfloat %a, bfloat %b) nounwind {
; CHECK-LABEL: fdiv_bf16:
; CHECK: # %bb.0:
; CHECK-NEXT: fcvt.s.bf16 fa5, fa1
; CHECK-NEXT: fcvt.s.bf16 fa4, fa0
; CHECK-NEXT: fdiv.s fa5, fa4, fa5
; CHECK-NEXT: fcvt.bf16.s fa0, fa5
; CHECK-NEXT: ret
%1 = fdiv bfloat %a, %b
ret bfloat %1
}
declare bfloat @llvm.sqrt.bf16(bfloat)
define bfloat @fsqrt_bf16(bfloat %a) nounwind {
; CHECK-LABEL: fsqrt_bf16:
; CHECK: # %bb.0:
; CHECK-NEXT: fcvt.s.bf16 fa5, fa0
; CHECK-NEXT: fsqrt.s fa5, fa5
; CHECK-NEXT: fcvt.bf16.s fa0, fa5
; CHECK-NEXT: ret
%1 = call bfloat @llvm.sqrt.bf16(bfloat %a)
ret bfloat %1
}
declare bfloat @llvm.copysign.bf16(bfloat, bfloat)
define bfloat @fsgnj_bf16(bfloat %a, bfloat %b) nounwind {
; RV32IZFBFMIN-LABEL: fsgnj_bf16:
; RV32IZFBFMIN: # %bb.0:
; RV32IZFBFMIN-NEXT: fmv.x.h a0, fa1
; RV32IZFBFMIN-NEXT: lui a1, 1048568
; RV32IZFBFMIN-NEXT: and a0, a0, a1
; RV32IZFBFMIN-NEXT: fmv.x.h a1, fa0
; RV32IZFBFMIN-NEXT: slli a1, a1, 17
; RV32IZFBFMIN-NEXT: srli a1, a1, 17
; RV32IZFBFMIN-NEXT: or a0, a1, a0
; RV32IZFBFMIN-NEXT: fmv.h.x fa0, a0
; RV32IZFBFMIN-NEXT: ret
;
; RV64IZFBFMIN-LABEL: fsgnj_bf16:
; RV64IZFBFMIN: # %bb.0:
; RV64IZFBFMIN-NEXT: fmv.x.h a0, fa1
; RV64IZFBFMIN-NEXT: lui a1, 1048568
; RV64IZFBFMIN-NEXT: and a0, a0, a1
; RV64IZFBFMIN-NEXT: fmv.x.h a1, fa0
; RV64IZFBFMIN-NEXT: slli a1, a1, 49
; RV64IZFBFMIN-NEXT: srli a1, a1, 49
; RV64IZFBFMIN-NEXT: or a0, a1, a0
; RV64IZFBFMIN-NEXT: fmv.h.x fa0, a0
; RV64IZFBFMIN-NEXT: ret
%1 = call bfloat @llvm.copysign.bf16(bfloat %a, bfloat %b)
ret bfloat %1
}
define i32 @fneg_bf16(bfloat %a, bfloat %b) nounwind {
; CHECK-LABEL: fneg_bf16:
; CHECK: # %bb.0:
; CHECK-NEXT: fcvt.s.bf16 fa5, fa0
; CHECK-NEXT: fadd.s fa5, fa5, fa5
; CHECK-NEXT: fcvt.bf16.s fa5, fa5
; CHECK-NEXT: fmv.x.h a0, fa5
; CHECK-NEXT: lui a1, 1048568
; CHECK-NEXT: xor a0, a0, a1
; CHECK-NEXT: fmv.h.x fa4, a0
; CHECK-NEXT: fcvt.s.bf16 fa4, fa4
; CHECK-NEXT: fcvt.s.bf16 fa5, fa5
; CHECK-NEXT: feq.s a0, fa5, fa4
; CHECK-NEXT: ret
%1 = fadd bfloat %a, %a
%2 = fneg bfloat %1
%3 = fcmp oeq bfloat %1, %2
%4 = zext i1 %3 to i32
ret i32 %4
}
define bfloat @fsgnjn_bf16(bfloat %a, bfloat %b) nounwind {
; RV32IZFBFMIN-LABEL: fsgnjn_bf16:
; RV32IZFBFMIN: # %bb.0:
; RV32IZFBFMIN-NEXT: fcvt.s.bf16 fa5, fa1
; RV32IZFBFMIN-NEXT: fcvt.s.bf16 fa4, fa0
; RV32IZFBFMIN-NEXT: fadd.s fa5, fa4, fa5
; RV32IZFBFMIN-NEXT: fcvt.bf16.s fa5, fa5
; RV32IZFBFMIN-NEXT: fmv.x.h a0, fa5
; RV32IZFBFMIN-NEXT: not a0, a0
; RV32IZFBFMIN-NEXT: lui a1, 1048568
; RV32IZFBFMIN-NEXT: and a0, a0, a1
; RV32IZFBFMIN-NEXT: fmv.x.h a1, fa0
; RV32IZFBFMIN-NEXT: slli a1, a1, 17
; RV32IZFBFMIN-NEXT: srli a1, a1, 17
; RV32IZFBFMIN-NEXT: or a0, a1, a0
; RV32IZFBFMIN-NEXT: fmv.h.x fa0, a0
; RV32IZFBFMIN-NEXT: ret
;
; RV64IZFBFMIN-LABEL: fsgnjn_bf16:
; RV64IZFBFMIN: # %bb.0:
; RV64IZFBFMIN-NEXT: fcvt.s.bf16 fa5, fa1
; RV64IZFBFMIN-NEXT: fcvt.s.bf16 fa4, fa0
; RV64IZFBFMIN-NEXT: fadd.s fa5, fa4, fa5
; RV64IZFBFMIN-NEXT: fcvt.bf16.s fa5, fa5
; RV64IZFBFMIN-NEXT: fmv.x.h a0, fa5
; RV64IZFBFMIN-NEXT: not a0, a0
; RV64IZFBFMIN-NEXT: lui a1, 1048568
; RV64IZFBFMIN-NEXT: and a0, a0, a1
; RV64IZFBFMIN-NEXT: fmv.x.h a1, fa0
; RV64IZFBFMIN-NEXT: slli a1, a1, 49
; RV64IZFBFMIN-NEXT: srli a1, a1, 49
; RV64IZFBFMIN-NEXT: or a0, a1, a0
; RV64IZFBFMIN-NEXT: fmv.h.x fa0, a0
; RV64IZFBFMIN-NEXT: ret
%1 = fadd bfloat %a, %b
%2 = fneg bfloat %1
%3 = call bfloat @llvm.copysign.bf16(bfloat %a, bfloat %2)
ret bfloat %3
}
declare bfloat @llvm.fabs.bf16(bfloat)
define bfloat @fabs_bf16(bfloat %a, bfloat %b) nounwind {
; RV32IZFBFMIN-LABEL: fabs_bf16:
; RV32IZFBFMIN: # %bb.0:
; RV32IZFBFMIN-NEXT: fcvt.s.bf16 fa5, fa1
; RV32IZFBFMIN-NEXT: fcvt.s.bf16 fa4, fa0
; RV32IZFBFMIN-NEXT: fadd.s fa5, fa4, fa5
; RV32IZFBFMIN-NEXT: fcvt.bf16.s fa5, fa5
; RV32IZFBFMIN-NEXT: fmv.x.h a0, fa5
; RV32IZFBFMIN-NEXT: slli a0, a0, 17
; RV32IZFBFMIN-NEXT: srli a0, a0, 17
; RV32IZFBFMIN-NEXT: fmv.h.x fa4, a0
; RV32IZFBFMIN-NEXT: fcvt.s.bf16 fa5, fa5
; RV32IZFBFMIN-NEXT: fcvt.s.bf16 fa4, fa4
; RV32IZFBFMIN-NEXT: fadd.s fa5, fa4, fa5
; RV32IZFBFMIN-NEXT: fcvt.bf16.s fa0, fa5
; RV32IZFBFMIN-NEXT: ret
;
; RV64IZFBFMIN-LABEL: fabs_bf16:
; RV64IZFBFMIN: # %bb.0:
; RV64IZFBFMIN-NEXT: fcvt.s.bf16 fa5, fa1
; RV64IZFBFMIN-NEXT: fcvt.s.bf16 fa4, fa0
; RV64IZFBFMIN-NEXT: fadd.s fa5, fa4, fa5
; RV64IZFBFMIN-NEXT: fcvt.bf16.s fa5, fa5
; RV64IZFBFMIN-NEXT: fmv.x.h a0, fa5
; RV64IZFBFMIN-NEXT: slli a0, a0, 49
; RV64IZFBFMIN-NEXT: srli a0, a0, 49
; RV64IZFBFMIN-NEXT: fmv.h.x fa4, a0
; RV64IZFBFMIN-NEXT: fcvt.s.bf16 fa5, fa5
; RV64IZFBFMIN-NEXT: fcvt.s.bf16 fa4, fa4
; RV64IZFBFMIN-NEXT: fadd.s fa5, fa4, fa5
; RV64IZFBFMIN-NEXT: fcvt.bf16.s fa0, fa5
; RV64IZFBFMIN-NEXT: ret
%1 = fadd bfloat %a, %b
%2 = call bfloat @llvm.fabs.bf16(bfloat %1)
%3 = fadd bfloat %2, %1
ret bfloat %3
}
declare bfloat @llvm.minnum.bf16(bfloat, bfloat)
define bfloat @fmin_bf16(bfloat %a, bfloat %b) nounwind {
; CHECK-LABEL: fmin_bf16:
; CHECK: # %bb.0:
; CHECK-NEXT: fcvt.s.bf16 fa5, fa1
; CHECK-NEXT: fcvt.s.bf16 fa4, fa0
; CHECK-NEXT: fmin.s fa5, fa4, fa5
; CHECK-NEXT: fcvt.bf16.s fa0, fa5
; CHECK-NEXT: ret
%1 = call bfloat @llvm.minnum.bf16(bfloat %a, bfloat %b)
ret bfloat %1
}
declare bfloat @llvm.maxnum.bf16(bfloat, bfloat)
define bfloat @fmax_bf16(bfloat %a, bfloat %b) nounwind {
; CHECK-LABEL: fmax_bf16:
; CHECK: # %bb.0:
; CHECK-NEXT: fcvt.s.bf16 fa5, fa1
; CHECK-NEXT: fcvt.s.bf16 fa4, fa0
; CHECK-NEXT: fmax.s fa5, fa4, fa5
; CHECK-NEXT: fcvt.bf16.s fa0, fa5
; CHECK-NEXT: ret
%1 = call bfloat @llvm.maxnum.bf16(bfloat %a, bfloat %b)
ret bfloat %1
}
declare bfloat @llvm.fma.bf16(bfloat, bfloat, bfloat)
define bfloat @fmadd_bf16(bfloat %a, bfloat %b, bfloat %c) nounwind {
; CHECK-LABEL: fmadd_bf16:
; CHECK: # %bb.0:
; CHECK-NEXT: fcvt.s.bf16 fa5, fa2
; CHECK-NEXT: fcvt.s.bf16 fa4, fa1
; CHECK-NEXT: fcvt.s.bf16 fa3, fa0
; CHECK-NEXT: fmadd.s fa5, fa3, fa4, fa5
; CHECK-NEXT: fcvt.bf16.s fa0, fa5
; CHECK-NEXT: ret
%1 = call bfloat @llvm.fma.bf16(bfloat %a, bfloat %b, bfloat %c)
ret bfloat %1
}
define bfloat @fmsub_bf16(bfloat %a, bfloat %b, bfloat %c) nounwind {
; CHECK-LABEL: fmsub_bf16:
; CHECK: # %bb.0:
; CHECK-NEXT: fcvt.s.bf16 fa5, fa2
; CHECK-NEXT: fmv.w.x fa4, zero
; CHECK-NEXT: fadd.s fa5, fa5, fa4
; CHECK-NEXT: fcvt.bf16.s fa5, fa5
; CHECK-NEXT: fmv.x.h a0, fa5
; CHECK-NEXT: lui a1, 1048568
; CHECK-NEXT: xor a0, a0, a1
; CHECK-NEXT: fmv.h.x fa5, a0
; CHECK-NEXT: fcvt.s.bf16 fa5, fa5
; CHECK-NEXT: fcvt.s.bf16 fa4, fa1
; CHECK-NEXT: fcvt.s.bf16 fa3, fa0
; CHECK-NEXT: fmadd.s fa5, fa3, fa4, fa5
; CHECK-NEXT: fcvt.bf16.s fa0, fa5
; CHECK-NEXT: ret
%c_ = fadd bfloat 0.0, %c ; avoid negation using xor
%negc = fsub bfloat -0.0, %c_
%1 = call bfloat @llvm.fma.bf16(bfloat %a, bfloat %b, bfloat %negc)
ret bfloat %1
}
define bfloat @fnmadd_bf16(bfloat %a, bfloat %b, bfloat %c) nounwind {
; CHECK-LABEL: fnmadd_bf16:
; CHECK: # %bb.0:
; CHECK-NEXT: fcvt.s.bf16 fa5, fa0
; CHECK-NEXT: fmv.w.x fa4, zero
; CHECK-NEXT: fadd.s fa5, fa5, fa4
; CHECK-NEXT: fcvt.bf16.s fa5, fa5
; CHECK-NEXT: fcvt.s.bf16 fa3, fa2
; CHECK-NEXT: fadd.s fa4, fa3, fa4
; CHECK-NEXT: fcvt.bf16.s fa4, fa4
; CHECK-NEXT: fmv.x.h a0, fa5
; CHECK-NEXT: lui a1, 1048568
; CHECK-NEXT: xor a0, a0, a1
; CHECK-NEXT: fmv.h.x fa5, a0
; CHECK-NEXT: fmv.x.h a0, fa4
; CHECK-NEXT: xor a0, a0, a1
; CHECK-NEXT: fmv.h.x fa4, a0
; CHECK-NEXT: fcvt.s.bf16 fa4, fa4
; CHECK-NEXT: fcvt.s.bf16 fa5, fa5
; CHECK-NEXT: fcvt.s.bf16 fa3, fa1
; CHECK-NEXT: fmadd.s fa5, fa5, fa3, fa4
; CHECK-NEXT: fcvt.bf16.s fa0, fa5
; CHECK-NEXT: ret
%a_ = fadd bfloat 0.0, %a
%c_ = fadd bfloat 0.0, %c
%nega = fsub bfloat -0.0, %a_
%negc = fsub bfloat -0.0, %c_
%1 = call bfloat @llvm.fma.bf16(bfloat %nega, bfloat %b, bfloat %negc)
ret bfloat %1
}
define bfloat @fnmadd_s_2(bfloat %a, bfloat %b, bfloat %c) nounwind {
; CHECK-LABEL: fnmadd_s_2:
; CHECK: # %bb.0:
; CHECK-NEXT: fcvt.s.bf16 fa5, fa1
; CHECK-NEXT: fmv.w.x fa4, zero
; CHECK-NEXT: fadd.s fa5, fa5, fa4
; CHECK-NEXT: fcvt.bf16.s fa5, fa5
; CHECK-NEXT: fcvt.s.bf16 fa3, fa2
; CHECK-NEXT: fadd.s fa4, fa3, fa4
; CHECK-NEXT: fcvt.bf16.s fa4, fa4
; CHECK-NEXT: fmv.x.h a0, fa5
; CHECK-NEXT: lui a1, 1048568
; CHECK-NEXT: xor a0, a0, a1
; CHECK-NEXT: fmv.h.x fa5, a0
; CHECK-NEXT: fmv.x.h a0, fa4
; CHECK-NEXT: xor a0, a0, a1
; CHECK-NEXT: fmv.h.x fa4, a0
; CHECK-NEXT: fcvt.s.bf16 fa4, fa4
; CHECK-NEXT: fcvt.s.bf16 fa5, fa5
; CHECK-NEXT: fcvt.s.bf16 fa3, fa0
; CHECK-NEXT: fmadd.s fa5, fa3, fa5, fa4
; CHECK-NEXT: fcvt.bf16.s fa0, fa5
; CHECK-NEXT: ret
%b_ = fadd bfloat 0.0, %b
%c_ = fadd bfloat 0.0, %c
%negb = fsub bfloat -0.0, %b_
%negc = fsub bfloat -0.0, %c_
%1 = call bfloat @llvm.fma.bf16(bfloat %a, bfloat %negb, bfloat %negc)
ret bfloat %1
}
define bfloat @fnmadd_s_3(bfloat %a, bfloat %b, bfloat %c) nounwind {
; CHECK-LABEL: fnmadd_s_3:
; CHECK: # %bb.0:
; CHECK-NEXT: fcvt.s.bf16 fa5, fa2
; CHECK-NEXT: fcvt.s.bf16 fa4, fa1
; CHECK-NEXT: fcvt.s.bf16 fa3, fa0
; CHECK-NEXT: fmadd.s fa5, fa3, fa4, fa5
; CHECK-NEXT: fcvt.bf16.s fa5, fa5
; CHECK-NEXT: fmv.x.h a0, fa5
; CHECK-NEXT: lui a1, 1048568
; CHECK-NEXT: xor a0, a0, a1
; CHECK-NEXT: fmv.h.x fa0, a0
; CHECK-NEXT: ret
%1 = call bfloat @llvm.fma.bf16(bfloat %a, bfloat %b, bfloat %c)
%neg = fneg bfloat %1
ret bfloat %neg
}
define bfloat @fnmadd_nsz(bfloat %a, bfloat %b, bfloat %c) nounwind {
; CHECK-LABEL: fnmadd_nsz:
; CHECK: # %bb.0:
; CHECK-NEXT: fcvt.s.bf16 fa5, fa2
; CHECK-NEXT: fcvt.s.bf16 fa4, fa1
; CHECK-NEXT: fcvt.s.bf16 fa3, fa0
; CHECK-NEXT: fmadd.s fa5, fa3, fa4, fa5
; CHECK-NEXT: fcvt.bf16.s fa5, fa5
; CHECK-NEXT: fmv.x.h a0, fa5
; CHECK-NEXT: lui a1, 1048568
; CHECK-NEXT: xor a0, a0, a1
; CHECK-NEXT: fmv.h.x fa0, a0
; CHECK-NEXT: ret
%1 = call nsz bfloat @llvm.fma.bf16(bfloat %a, bfloat %b, bfloat %c)
%neg = fneg nsz bfloat %1
ret bfloat %neg
}
define bfloat @fnmsub_bf16(bfloat %a, bfloat %b, bfloat %c) nounwind {
; CHECK-LABEL: fnmsub_bf16:
; CHECK: # %bb.0:
; CHECK-NEXT: fcvt.s.bf16 fa5, fa0
; CHECK-NEXT: fmv.w.x fa4, zero
; CHECK-NEXT: fadd.s fa5, fa5, fa4
; CHECK-NEXT: fcvt.bf16.s fa5, fa5
; CHECK-NEXT: fmv.x.h a0, fa5
; CHECK-NEXT: lui a1, 1048568
; CHECK-NEXT: xor a0, a0, a1
; CHECK-NEXT: fmv.h.x fa5, a0
; CHECK-NEXT: fcvt.s.bf16 fa5, fa5
; CHECK-NEXT: fcvt.s.bf16 fa4, fa2
; CHECK-NEXT: fcvt.s.bf16 fa3, fa1
; CHECK-NEXT: fmadd.s fa5, fa5, fa3, fa4
; CHECK-NEXT: fcvt.bf16.s fa0, fa5
; CHECK-NEXT: ret
%a_ = fadd bfloat 0.0, %a
%nega = fsub bfloat -0.0, %a_
%1 = call bfloat @llvm.fma.bf16(bfloat %nega, bfloat %b, bfloat %c)
ret bfloat %1
}
define bfloat @fnmsub_bf16_2(bfloat %a, bfloat %b, bfloat %c) nounwind {
; CHECK-LABEL: fnmsub_bf16_2:
; CHECK: # %bb.0:
; CHECK-NEXT: fcvt.s.bf16 fa5, fa1
; CHECK-NEXT: fmv.w.x fa4, zero
; CHECK-NEXT: fadd.s fa5, fa5, fa4
; CHECK-NEXT: fcvt.bf16.s fa5, fa5
; CHECK-NEXT: fmv.x.h a0, fa5
; CHECK-NEXT: lui a1, 1048568
; CHECK-NEXT: xor a0, a0, a1
; CHECK-NEXT: fmv.h.x fa5, a0
; CHECK-NEXT: fcvt.s.bf16 fa5, fa5
; CHECK-NEXT: fcvt.s.bf16 fa4, fa2
; CHECK-NEXT: fcvt.s.bf16 fa3, fa0
; CHECK-NEXT: fmadd.s fa5, fa3, fa5, fa4
; CHECK-NEXT: fcvt.bf16.s fa0, fa5
; CHECK-NEXT: ret
%b_ = fadd bfloat 0.0, %b
%negb = fsub bfloat -0.0, %b_
%1 = call bfloat @llvm.fma.bf16(bfloat %a, bfloat %negb, bfloat %c)
ret bfloat %1
}
define bfloat @fmadd_bf16_contract(bfloat %a, bfloat %b, bfloat %c) nounwind {
; CHECK-LABEL: fmadd_bf16_contract:
; CHECK: # %bb.0:
; CHECK-NEXT: fcvt.s.bf16 fa5, fa1
; CHECK-NEXT: fcvt.s.bf16 fa4, fa0
; CHECK-NEXT: fmul.s fa5, fa4, fa5
; CHECK-NEXT: fcvt.bf16.s fa5, fa5
; CHECK-NEXT: fcvt.s.bf16 fa5, fa5
; CHECK-NEXT: fcvt.s.bf16 fa4, fa2
; CHECK-NEXT: fadd.s fa5, fa5, fa4
; CHECK-NEXT: fcvt.bf16.s fa0, fa5
; CHECK-NEXT: ret
%1 = fmul contract bfloat %a, %b
%2 = fadd contract bfloat %1, %c
ret bfloat %2
}
define bfloat @fmsub_bf16_contract(bfloat %a, bfloat %b, bfloat %c) nounwind {
; CHECK-LABEL: fmsub_bf16_contract:
; CHECK: # %bb.0:
; CHECK-NEXT: fcvt.s.bf16 fa5, fa2
; CHECK-NEXT: fmv.w.x fa4, zero
; CHECK-NEXT: fadd.s fa5, fa5, fa4
; CHECK-NEXT: fcvt.bf16.s fa5, fa5
; CHECK-NEXT: fcvt.s.bf16 fa4, fa1
; CHECK-NEXT: fcvt.s.bf16 fa3, fa0
; CHECK-NEXT: fmul.s fa4, fa3, fa4
; CHECK-NEXT: fcvt.bf16.s fa4, fa4
; CHECK-NEXT: fcvt.s.bf16 fa5, fa5
; CHECK-NEXT: fcvt.s.bf16 fa4, fa4
; CHECK-NEXT: fsub.s fa5, fa4, fa5
; CHECK-NEXT: fcvt.bf16.s fa0, fa5
; CHECK-NEXT: ret
%c_ = fadd bfloat 0.0, %c ; avoid negation using xor
%1 = fmul contract bfloat %a, %b
%2 = fsub contract bfloat %1, %c_
ret bfloat %2
}
define bfloat @fnmadd_bf16_contract(bfloat %a, bfloat %b, bfloat %c) nounwind {
; CHECK-LABEL: fnmadd_bf16_contract:
; CHECK: # %bb.0:
; CHECK-NEXT: fcvt.s.bf16 fa5, fa0
; CHECK-NEXT: fmv.w.x fa4, zero
; CHECK-NEXT: fadd.s fa5, fa5, fa4
; CHECK-NEXT: fcvt.bf16.s fa5, fa5
; CHECK-NEXT: fcvt.s.bf16 fa3, fa1
; CHECK-NEXT: fadd.s fa3, fa3, fa4
; CHECK-NEXT: fcvt.bf16.s fa3, fa3
; CHECK-NEXT: fcvt.s.bf16 fa2, fa2
; CHECK-NEXT: fadd.s fa4, fa2, fa4
; CHECK-NEXT: fcvt.bf16.s fa4, fa4
; CHECK-NEXT: fcvt.s.bf16 fa3, fa3
; CHECK-NEXT: fcvt.s.bf16 fa5, fa5
; CHECK-NEXT: fmul.s fa5, fa5, fa3
; CHECK-NEXT: fcvt.bf16.s fa5, fa5
; CHECK-NEXT: fmv.x.h a0, fa5
; CHECK-NEXT: lui a1, 1048568
; CHECK-NEXT: xor a0, a0, a1
; CHECK-NEXT: fmv.h.x fa5, a0
; CHECK-NEXT: fcvt.s.bf16 fa5, fa5
; CHECK-NEXT: fcvt.s.bf16 fa4, fa4
; CHECK-NEXT: fsub.s fa5, fa5, fa4
; CHECK-NEXT: fcvt.bf16.s fa0, fa5
; CHECK-NEXT: ret
%a_ = fadd bfloat 0.0, %a ; avoid negation using xor
%b_ = fadd bfloat 0.0, %b ; avoid negation using xor
%c_ = fadd bfloat 0.0, %c ; avoid negation using xor
%1 = fmul contract bfloat %a_, %b_
%2 = fneg bfloat %1
%3 = fsub contract bfloat %2, %c_
ret bfloat %3
}
define bfloat @fnmsub_bf16_contract(bfloat %a, bfloat %b, bfloat %c) nounwind {
; CHECK-LABEL: fnmsub_bf16_contract:
; CHECK: # %bb.0:
; CHECK-NEXT: fcvt.s.bf16 fa5, fa0
; CHECK-NEXT: fmv.w.x fa4, zero
; CHECK-NEXT: fadd.s fa5, fa5, fa4
; CHECK-NEXT: fcvt.bf16.s fa5, fa5
; CHECK-NEXT: fcvt.s.bf16 fa3, fa1
; CHECK-NEXT: fadd.s fa4, fa3, fa4
; CHECK-NEXT: fcvt.bf16.s fa4, fa4
; CHECK-NEXT: fcvt.s.bf16 fa4, fa4
; CHECK-NEXT: fcvt.s.bf16 fa5, fa5
; CHECK-NEXT: fmul.s fa5, fa5, fa4
; CHECK-NEXT: fcvt.bf16.s fa5, fa5
; CHECK-NEXT: fcvt.s.bf16 fa5, fa5
; CHECK-NEXT: fcvt.s.bf16 fa4, fa2
; CHECK-NEXT: fsub.s fa5, fa4, fa5
; CHECK-NEXT: fcvt.bf16.s fa0, fa5
; CHECK-NEXT: ret
%a_ = fadd bfloat 0.0, %a ; avoid negation using xor
%b_ = fadd bfloat 0.0, %b ; avoid negation using xor
%1 = fmul contract bfloat %a_, %b_
%2 = fsub contract bfloat %c, %1
ret bfloat %2
}