Files
clang-p2996/llvm/test/CodeGen/RISCV/half-arith.ll
Craig Topper 7b0c41841e [RISCV] Move compressible registers to the beginning of the FP allocation order.
We don't have very many compressible FP instructions, just load and store.
These instruction require the FP register to be f8-f15.

This patch changes the FP allocation order to prioritize f10-f15 first.
These are also the FP argument registers. So I allocated them in reverse
order starting at f15 to avoid taking the first argument registers.
This appears to match gcc allocation order.

Reviewed By: asb

Differential Revision: https://reviews.llvm.org/D146488
2023-03-27 17:29:28 -07:00

2408 lines
84 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=riscv32 -mattr=+zfh -verify-machineinstrs \
; RUN: -target-abi ilp32f < %s | FileCheck -check-prefix=CHECKIZFH %s
; RUN: llc -mtriple=riscv64 -mattr=+zfh -verify-machineinstrs \
; RUN: -target-abi lp64f < %s | FileCheck -check-prefix=CHECKIZFH %s
; 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
; RUN: llc -mtriple=riscv32 -mattr=+zfhmin -verify-machineinstrs \
; RUN: -target-abi ilp32f < %s | FileCheck -check-prefixes=CHECKIZFHMIN,CHECK-RV32-FSGNJ %s
; RUN: llc -mtriple=riscv64 -mattr=+zfhmin -verify-machineinstrs \
; RUN: -target-abi lp64f < %s | FileCheck --check-prefixes=CHECKIZFHMIN,CHECK-RV64-FSGNJ %s
; These tests are each targeted at a particular RISC-V FPU instruction.
; Compares and conversions can be found in half-fcmp.ll and half-convert.ll
; respectively. Some other half-*.ll files in this folder exercise LLVM IR
; instructions that don't directly match a RISC-V instruction.
define half @fadd_s(half %a, half %b) nounwind {
; CHECKIZFH-LABEL: fadd_s:
; CHECKIZFH: # %bb.0:
; CHECKIZFH-NEXT: fadd.h fa0, fa0, fa1
; CHECKIZFH-NEXT: ret
;
; RV32I-LABEL: fadd_s:
; RV32I: # %bb.0:
; RV32I-NEXT: addi sp, sp, -16
; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s0, 8(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s1, 4(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s2, 0(sp) # 4-byte Folded Spill
; RV32I-NEXT: mv s0, a1
; RV32I-NEXT: lui a1, 16
; RV32I-NEXT: addi s2, a1, -1
; RV32I-NEXT: and a0, a0, s2
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv s1, a0
; RV32I-NEXT: and a0, s0, s2
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv a1, a0
; RV32I-NEXT: mv a0, s1
; RV32I-NEXT: call __addsf3@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s1, 4(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s2, 0(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 16
; RV32I-NEXT: ret
;
; RV64I-LABEL: fadd_s:
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -32
; RV64I-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s0, 16(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s1, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s2, 0(sp) # 8-byte Folded Spill
; RV64I-NEXT: mv s0, a1
; RV64I-NEXT: lui a1, 16
; RV64I-NEXT: addiw s2, a1, -1
; RV64I-NEXT: and a0, a0, s2
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv s1, a0
; RV64I-NEXT: and a0, s0, s2
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv a1, a0
; RV64I-NEXT: mv a0, s1
; RV64I-NEXT: call __addsf3@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s0, 16(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s1, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s2, 0(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 32
; RV64I-NEXT: ret
;
; CHECKIZFHMIN-LABEL: fadd_s:
; CHECKIZFHMIN: # %bb.0:
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa1
; CHECKIZFHMIN-NEXT: fcvt.s.h fa4, fa0
; CHECKIZFHMIN-NEXT: fadd.s fa5, fa4, fa5
; CHECKIZFHMIN-NEXT: fcvt.h.s fa0, fa5
; CHECKIZFHMIN-NEXT: ret
%1 = fadd half %a, %b
ret half %1
}
define half @fsub_s(half %a, half %b) nounwind {
; CHECKIZFH-LABEL: fsub_s:
; CHECKIZFH: # %bb.0:
; CHECKIZFH-NEXT: fsub.h fa0, fa0, fa1
; CHECKIZFH-NEXT: ret
;
; RV32I-LABEL: fsub_s:
; RV32I: # %bb.0:
; RV32I-NEXT: addi sp, sp, -16
; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s0, 8(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s1, 4(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s2, 0(sp) # 4-byte Folded Spill
; RV32I-NEXT: mv s0, a1
; RV32I-NEXT: lui a1, 16
; RV32I-NEXT: addi s2, a1, -1
; RV32I-NEXT: and a0, a0, s2
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv s1, a0
; RV32I-NEXT: and a0, s0, s2
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv a1, a0
; RV32I-NEXT: mv a0, s1
; RV32I-NEXT: call __subsf3@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s1, 4(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s2, 0(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 16
; RV32I-NEXT: ret
;
; RV64I-LABEL: fsub_s:
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -32
; RV64I-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s0, 16(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s1, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s2, 0(sp) # 8-byte Folded Spill
; RV64I-NEXT: mv s0, a1
; RV64I-NEXT: lui a1, 16
; RV64I-NEXT: addiw s2, a1, -1
; RV64I-NEXT: and a0, a0, s2
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv s1, a0
; RV64I-NEXT: and a0, s0, s2
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv a1, a0
; RV64I-NEXT: mv a0, s1
; RV64I-NEXT: call __subsf3@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s0, 16(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s1, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s2, 0(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 32
; RV64I-NEXT: ret
;
; CHECKIZFHMIN-LABEL: fsub_s:
; CHECKIZFHMIN: # %bb.0:
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa1
; CHECKIZFHMIN-NEXT: fcvt.s.h fa4, fa0
; CHECKIZFHMIN-NEXT: fsub.s fa5, fa4, fa5
; CHECKIZFHMIN-NEXT: fcvt.h.s fa0, fa5
; CHECKIZFHMIN-NEXT: ret
%1 = fsub half %a, %b
ret half %1
}
define half @fmul_s(half %a, half %b) nounwind {
; CHECKIZFH-LABEL: fmul_s:
; CHECKIZFH: # %bb.0:
; CHECKIZFH-NEXT: fmul.h fa0, fa0, fa1
; CHECKIZFH-NEXT: ret
;
; RV32I-LABEL: fmul_s:
; RV32I: # %bb.0:
; RV32I-NEXT: addi sp, sp, -16
; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s0, 8(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s1, 4(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s2, 0(sp) # 4-byte Folded Spill
; RV32I-NEXT: mv s0, a1
; RV32I-NEXT: lui a1, 16
; RV32I-NEXT: addi s2, a1, -1
; RV32I-NEXT: and a0, a0, s2
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv s1, a0
; RV32I-NEXT: and a0, s0, s2
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv a1, a0
; RV32I-NEXT: mv a0, s1
; RV32I-NEXT: call __mulsf3@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s1, 4(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s2, 0(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 16
; RV32I-NEXT: ret
;
; RV64I-LABEL: fmul_s:
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -32
; RV64I-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s0, 16(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s1, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s2, 0(sp) # 8-byte Folded Spill
; RV64I-NEXT: mv s0, a1
; RV64I-NEXT: lui a1, 16
; RV64I-NEXT: addiw s2, a1, -1
; RV64I-NEXT: and a0, a0, s2
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv s1, a0
; RV64I-NEXT: and a0, s0, s2
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv a1, a0
; RV64I-NEXT: mv a0, s1
; RV64I-NEXT: call __mulsf3@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s0, 16(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s1, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s2, 0(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 32
; RV64I-NEXT: ret
;
; CHECKIZFHMIN-LABEL: fmul_s:
; CHECKIZFHMIN: # %bb.0:
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa1
; CHECKIZFHMIN-NEXT: fcvt.s.h fa4, fa0
; CHECKIZFHMIN-NEXT: fmul.s fa5, fa4, fa5
; CHECKIZFHMIN-NEXT: fcvt.h.s fa0, fa5
; CHECKIZFHMIN-NEXT: ret
%1 = fmul half %a, %b
ret half %1
}
define half @fdiv_s(half %a, half %b) nounwind {
; CHECKIZFH-LABEL: fdiv_s:
; CHECKIZFH: # %bb.0:
; CHECKIZFH-NEXT: fdiv.h fa0, fa0, fa1
; CHECKIZFH-NEXT: ret
;
; RV32I-LABEL: fdiv_s:
; RV32I: # %bb.0:
; RV32I-NEXT: addi sp, sp, -16
; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s0, 8(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s1, 4(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s2, 0(sp) # 4-byte Folded Spill
; RV32I-NEXT: mv s0, a1
; RV32I-NEXT: lui a1, 16
; RV32I-NEXT: addi s2, a1, -1
; RV32I-NEXT: and a0, a0, s2
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv s1, a0
; RV32I-NEXT: and a0, s0, s2
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv a1, a0
; RV32I-NEXT: mv a0, s1
; RV32I-NEXT: call __divsf3@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s1, 4(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s2, 0(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 16
; RV32I-NEXT: ret
;
; RV64I-LABEL: fdiv_s:
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -32
; RV64I-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s0, 16(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s1, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s2, 0(sp) # 8-byte Folded Spill
; RV64I-NEXT: mv s0, a1
; RV64I-NEXT: lui a1, 16
; RV64I-NEXT: addiw s2, a1, -1
; RV64I-NEXT: and a0, a0, s2
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv s1, a0
; RV64I-NEXT: and a0, s0, s2
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv a1, a0
; RV64I-NEXT: mv a0, s1
; RV64I-NEXT: call __divsf3@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s0, 16(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s1, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s2, 0(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 32
; RV64I-NEXT: ret
;
; CHECKIZFHMIN-LABEL: fdiv_s:
; CHECKIZFHMIN: # %bb.0:
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa1
; CHECKIZFHMIN-NEXT: fcvt.s.h fa4, fa0
; CHECKIZFHMIN-NEXT: fdiv.s fa5, fa4, fa5
; CHECKIZFHMIN-NEXT: fcvt.h.s fa0, fa5
; CHECKIZFHMIN-NEXT: ret
%1 = fdiv half %a, %b
ret half %1
}
declare half @llvm.sqrt.f16(half)
define half @fsqrt_s(half %a) nounwind {
; CHECKIZFH-LABEL: fsqrt_s:
; CHECKIZFH: # %bb.0:
; CHECKIZFH-NEXT: fsqrt.h fa0, fa0
; CHECKIZFH-NEXT: ret
;
; RV32I-LABEL: fsqrt_s:
; RV32I: # %bb.0:
; RV32I-NEXT: addi sp, sp, -16
; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
; RV32I-NEXT: slli a0, a0, 16
; RV32I-NEXT: srli a0, a0, 16
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: call sqrtf@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 16
; RV32I-NEXT: ret
;
; RV64I-LABEL: fsqrt_s:
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -16
; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: slli a0, a0, 48
; RV64I-NEXT: srli a0, a0, 48
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: call sqrtf@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 16
; RV64I-NEXT: ret
;
; CHECKIZFHMIN-LABEL: fsqrt_s:
; CHECKIZFHMIN: # %bb.0:
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa0
; CHECKIZFHMIN-NEXT: fsqrt.s fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.h.s fa0, fa5
; CHECKIZFHMIN-NEXT: ret
%1 = call half @llvm.sqrt.f16(half %a)
ret half %1
}
declare half @llvm.copysign.f16(half, half)
define half @fsgnj_s(half %a, half %b) nounwind {
; CHECKIZFH-LABEL: fsgnj_s:
; CHECKIZFH: # %bb.0:
; CHECKIZFH-NEXT: fsgnj.h fa0, fa0, fa1
; CHECKIZFH-NEXT: ret
;
; RV32I-LABEL: fsgnj_s:
; RV32I: # %bb.0:
; RV32I-NEXT: lui a2, 1048568
; RV32I-NEXT: and a1, a1, a2
; RV32I-NEXT: slli a0, a0, 17
; RV32I-NEXT: srli a0, a0, 17
; RV32I-NEXT: or a0, a0, a1
; RV32I-NEXT: ret
;
; RV64I-LABEL: fsgnj_s:
; RV64I: # %bb.0:
; RV64I-NEXT: lui a2, 1048568
; RV64I-NEXT: and a1, a1, a2
; RV64I-NEXT: slli a0, a0, 49
; RV64I-NEXT: srli a0, a0, 49
; RV64I-NEXT: or a0, a0, a1
; RV64I-NEXT: ret
;
; CHECK-RV32-FSGNJ-LABEL: fsgnj_s:
; CHECK-RV32-FSGNJ: # %bb.0:
; CHECK-RV32-FSGNJ-NEXT: addi sp, sp, -16
; CHECK-RV32-FSGNJ-NEXT: fsh fa1, 12(sp)
; CHECK-RV32-FSGNJ-NEXT: fsh fa0, 8(sp)
; CHECK-RV32-FSGNJ-NEXT: lbu a0, 13(sp)
; CHECK-RV32-FSGNJ-NEXT: lbu a1, 9(sp)
; CHECK-RV32-FSGNJ-NEXT: andi a0, a0, 128
; CHECK-RV32-FSGNJ-NEXT: andi a1, a1, 127
; CHECK-RV32-FSGNJ-NEXT: or a0, a1, a0
; CHECK-RV32-FSGNJ-NEXT: sb a0, 9(sp)
; CHECK-RV32-FSGNJ-NEXT: flh fa0, 8(sp)
; CHECK-RV32-FSGNJ-NEXT: addi sp, sp, 16
; CHECK-RV32-FSGNJ-NEXT: ret
;
; CHECK-RV64-FSGNJ-LABEL: fsgnj_s:
; CHECK-RV64-FSGNJ: # %bb.0:
; CHECK-RV64-FSGNJ-NEXT: addi sp, sp, -16
; CHECK-RV64-FSGNJ-NEXT: fsh fa1, 8(sp)
; CHECK-RV64-FSGNJ-NEXT: fsh fa0, 0(sp)
; CHECK-RV64-FSGNJ-NEXT: lbu a0, 9(sp)
; CHECK-RV64-FSGNJ-NEXT: lbu a1, 1(sp)
; CHECK-RV64-FSGNJ-NEXT: andi a0, a0, 128
; CHECK-RV64-FSGNJ-NEXT: andi a1, a1, 127
; CHECK-RV64-FSGNJ-NEXT: or a0, a1, a0
; CHECK-RV64-FSGNJ-NEXT: sb a0, 1(sp)
; CHECK-RV64-FSGNJ-NEXT: flh fa0, 0(sp)
; CHECK-RV64-FSGNJ-NEXT: addi sp, sp, 16
; CHECK-RV64-FSGNJ-NEXT: ret
; CHECKFSGNJ-LABEL: fsgnj_s:
; CHECKFSGNJ: # %bb.0:
; CHECKFSGNJ-NEXT: addi sp, sp, -16
; CHECKFSGNJ-NEXT: fsh fa1, 12(sp)
; CHECKFSGNJ-NEXT: fsh fa0, 8(sp)
; CHECKFSGNJ-NEXT: lbu a0, 13(sp)
; CHECKFSGNJ-NEXT: lbu a1, 9(sp)
; CHECKFSGNJ-NEXT: andi a0, a0, 128
; CHECKFSGNJ-NEXT: andi a1, a1, 127
; CHECKFSGNJ-NEXT: or a0, a1, a0
; CHECKFSGNJ-NEXT: sb a0, 9(sp)
; CHECKFSGNJ-NEXT: flh fa0, 8(sp)
; CHECKFSGNJ-NEXT: addi sp, sp, 16
; CHECKFSGNJ-NEXT: ret
; CHECK64FSGNJ-LABEL: fsgnj_s:
; CHECK64FSGNJ: # %bb.0:
; CHECK64FSGNJ-NEXT: addi sp, sp, -16
; CHECK64FSGNJ-NEXT: fsh fa1, 8(sp)
; CHECK64FSGNJ-NEXT: fsh fa0, 0(sp)
; CHECK64FSGNJ-NEXT: lbu a0, 9(sp)
; CHECK64FSGNJ-NEXT: lbu a1, 1(sp)
; CHECK64FSGNJ-NEXT: andi a0, a0, 128
; CHECK64FSGNJ-NEXT: andi a1, a1, 127
; CHECK64FSGNJ-NEXT: or a0, a1, a0
; CHECK64FSGNJ-NEXT: sb a0, 1(sp)
; CHECK64FSGNJ-NEXT: flh fa0, 0(sp)
; CHECK64FSGNJ-NEXT: addi sp, sp, 16
; CHECK64FSGNJ-NEXT: ret
%1 = call half @llvm.copysign.f16(half %a, half %b)
ret half %1
}
; This function performs extra work to ensure that
; DAGCombiner::visitBITCAST doesn't replace the fneg with an xor.
define i32 @fneg_s(half %a, half %b) nounwind {
; CHECKIZFH-LABEL: fneg_s:
; CHECKIZFH: # %bb.0:
; CHECKIZFH-NEXT: fadd.h fa5, fa0, fa0
; CHECKIZFH-NEXT: fneg.h fa4, fa5
; CHECKIZFH-NEXT: feq.h a0, fa5, fa4
; CHECKIZFH-NEXT: ret
;
; RV32I-LABEL: fneg_s:
; RV32I: # %bb.0:
; RV32I-NEXT: addi sp, sp, -16
; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s0, 8(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s1, 4(sp) # 4-byte Folded Spill
; RV32I-NEXT: lui a1, 16
; RV32I-NEXT: addi s1, a1, -1
; RV32I-NEXT: and a0, a0, s1
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv a1, a0
; RV32I-NEXT: call __addsf3@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: and a0, a0, s1
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv s0, a0
; RV32I-NEXT: lui a0, 524288
; RV32I-NEXT: xor a0, s0, a0
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: and a0, a0, s1
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv a1, a0
; RV32I-NEXT: mv a0, s0
; RV32I-NEXT: call __eqsf2@plt
; RV32I-NEXT: seqz a0, a0
; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s1, 4(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 16
; RV32I-NEXT: ret
;
; RV64I-LABEL: fneg_s:
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -32
; RV64I-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s0, 16(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s1, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: lui a1, 16
; RV64I-NEXT: addiw s1, a1, -1
; RV64I-NEXT: and a0, a0, s1
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv a1, a0
; RV64I-NEXT: call __addsf3@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: and a0, a0, s1
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv s0, a0
; RV64I-NEXT: lui a0, 524288
; RV64I-NEXT: xor a0, s0, a0
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: and a0, a0, s1
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv a1, a0
; RV64I-NEXT: mv a0, s0
; RV64I-NEXT: call __eqsf2@plt
; RV64I-NEXT: seqz a0, a0
; RV64I-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s0, 16(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s1, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 32
; RV64I-NEXT: ret
;
; CHECKIZFHMIN-LABEL: fneg_s:
; CHECKIZFHMIN: # %bb.0:
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa0
; CHECKIZFHMIN-NEXT: fadd.s fa5, fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.h.s fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa5
; CHECKIZFHMIN-NEXT: fneg.s fa4, fa5
; CHECKIZFHMIN-NEXT: fcvt.h.s fa4, fa4
; CHECKIZFHMIN-NEXT: fcvt.s.h fa4, fa4
; CHECKIZFHMIN-NEXT: feq.s a0, fa5, fa4
; CHECKIZFHMIN-NEXT: ret
%1 = fadd half %a, %a
%2 = fneg half %1
%3 = fcmp oeq half %1, %2
%4 = zext i1 %3 to i32
ret i32 %4
}
; This function performs extra work to ensure that
; DAGCombiner::visitBITCAST doesn't replace the fneg with an xor.
define half @fsgnjn_s(half %a, half %b) nounwind {
; CHECKIZFH-LABEL: fsgnjn_s:
; CHECKIZFH: # %bb.0:
; CHECKIZFH-NEXT: fadd.h fa5, fa0, fa1
; CHECKIZFH-NEXT: fsgnjn.h fa0, fa0, fa5
; CHECKIZFH-NEXT: ret
;
; RV32I-LABEL: fsgnjn_s:
; RV32I: # %bb.0:
; RV32I-NEXT: addi sp, sp, -32
; RV32I-NEXT: sw ra, 28(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s0, 24(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s1, 20(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s2, 16(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s3, 12(sp) # 4-byte Folded Spill
; RV32I-NEXT: mv s0, a1
; RV32I-NEXT: mv s1, a0
; RV32I-NEXT: lui a0, 16
; RV32I-NEXT: addi s3, a0, -1
; RV32I-NEXT: and a0, s1, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv s2, a0
; RV32I-NEXT: and a0, s0, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv a1, a0
; RV32I-NEXT: mv a0, s2
; RV32I-NEXT: call __addsf3@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: and a0, a0, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: lui a1, 524288
; RV32I-NEXT: xor a0, a0, a1
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: lui a1, 1048568
; RV32I-NEXT: and a0, a0, a1
; RV32I-NEXT: slli s1, s1, 17
; RV32I-NEXT: srli s1, s1, 17
; RV32I-NEXT: or a0, s1, a0
; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s0, 24(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s1, 20(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s2, 16(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s3, 12(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 32
; RV32I-NEXT: ret
;
; RV64I-LABEL: fsgnjn_s:
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -48
; RV64I-NEXT: sd ra, 40(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s0, 32(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s1, 24(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s2, 16(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s3, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: mv s0, a1
; RV64I-NEXT: mv s1, a0
; RV64I-NEXT: lui a0, 16
; RV64I-NEXT: addiw s3, a0, -1
; RV64I-NEXT: and a0, s1, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv s2, a0
; RV64I-NEXT: and a0, s0, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv a1, a0
; RV64I-NEXT: mv a0, s2
; RV64I-NEXT: call __addsf3@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: and a0, a0, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: lui a1, 524288
; RV64I-NEXT: xor a0, a0, a1
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: lui a1, 1048568
; RV64I-NEXT: and a0, a0, a1
; RV64I-NEXT: slli s1, s1, 49
; RV64I-NEXT: srli s1, s1, 49
; RV64I-NEXT: or a0, s1, a0
; RV64I-NEXT: ld ra, 40(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s0, 32(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s1, 24(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s2, 16(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s3, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 48
; RV64I-NEXT: ret
;
; CHECK-RV32-FSGNJ-LABEL: fsgnjn_s:
; CHECK-RV32-FSGNJ: # %bb.0:
; CHECK-RV32-FSGNJ-NEXT: addi sp, sp, -16
; CHECK-RV32-FSGNJ-NEXT: fcvt.s.h fa5, fa1
; CHECK-RV32-FSGNJ-NEXT: fcvt.s.h fa4, fa0
; CHECK-RV32-FSGNJ-NEXT: fadd.s fa5, fa4, fa5
; CHECK-RV32-FSGNJ-NEXT: fcvt.h.s fa5, fa5
; CHECK-RV32-FSGNJ-NEXT: fcvt.s.h fa5, fa5
; CHECK-RV32-FSGNJ-NEXT: fneg.s fa5, fa5
; CHECK-RV32-FSGNJ-NEXT: fcvt.h.s fa5, fa5
; CHECK-RV32-FSGNJ-NEXT: fsh fa0, 8(sp)
; CHECK-RV32-FSGNJ-NEXT: fsh fa5, 12(sp)
; CHECK-RV32-FSGNJ-NEXT: lbu a0, 9(sp)
; CHECK-RV32-FSGNJ-NEXT: lbu a1, 13(sp)
; CHECK-RV32-FSGNJ-NEXT: andi a0, a0, 127
; CHECK-RV32-FSGNJ-NEXT: andi a1, a1, 128
; CHECK-RV32-FSGNJ-NEXT: or a0, a0, a1
; CHECK-RV32-FSGNJ-NEXT: sb a0, 9(sp)
; CHECK-RV32-FSGNJ-NEXT: flh fa0, 8(sp)
; CHECK-RV32-FSGNJ-NEXT: addi sp, sp, 16
; CHECK-RV32-FSGNJ-NEXT: ret
;
; CHECK-RV64-FSGNJ-LABEL: fsgnjn_s:
; CHECK-RV64-FSGNJ: # %bb.0:
; CHECK-RV64-FSGNJ-NEXT: addi sp, sp, -16
; CHECK-RV64-FSGNJ-NEXT: fcvt.s.h fa5, fa1
; CHECK-RV64-FSGNJ-NEXT: fcvt.s.h fa4, fa0
; CHECK-RV64-FSGNJ-NEXT: fadd.s fa5, fa4, fa5
; CHECK-RV64-FSGNJ-NEXT: fcvt.h.s fa5, fa5
; CHECK-RV64-FSGNJ-NEXT: fcvt.s.h fa5, fa5
; CHECK-RV64-FSGNJ-NEXT: fneg.s fa5, fa5
; CHECK-RV64-FSGNJ-NEXT: fcvt.h.s fa5, fa5
; CHECK-RV64-FSGNJ-NEXT: fsh fa0, 0(sp)
; CHECK-RV64-FSGNJ-NEXT: fsh fa5, 8(sp)
; CHECK-RV64-FSGNJ-NEXT: lbu a0, 1(sp)
; CHECK-RV64-FSGNJ-NEXT: lbu a1, 9(sp)
; CHECK-RV64-FSGNJ-NEXT: andi a0, a0, 127
; CHECK-RV64-FSGNJ-NEXT: andi a1, a1, 128
; CHECK-RV64-FSGNJ-NEXT: or a0, a0, a1
; CHECK-RV64-FSGNJ-NEXT: sb a0, 1(sp)
; CHECK-RV64-FSGNJ-NEXT: flh fa0, 0(sp)
; CHECK-RV64-FSGNJ-NEXT: addi sp, sp, 16
; CHECK-RV64-FSGNJ-NEXT: ret
; CHECKFSGNJ-LABEL: fsgnjn_s:
; CHECKFSGNJ: # %bb.0:
; CHECKFSGNJ-NEXT: addi sp, sp, -16
; CHECKFSGNJ-NEXT: fcvt.s.h ft0, fa1
; CHECKFSGNJ-NEXT: fcvt.s.h ft1, fa0
; CHECKFSGNJ-NEXT: fadd.s ft0, ft1, ft0
; CHECKFSGNJ-NEXT: fcvt.h.s ft0, ft0
; CHECKFSGNJ-NEXT: fcvt.s.h ft0, ft0
; CHECKFSGNJ-NEXT: fneg.s ft0, ft0
; CHECKFSGNJ-NEXT: fcvt.h.s ft0, ft0
; CHECKFSGNJ-NEXT: fsh fa0, 8(sp)
; CHECKFSGNJ-NEXT: fsh ft0, 12(sp)
; CHECKFSGNJ-NEXT: lbu a0, 9(sp)
; CHECKFSGNJ-NEXT: lbu a1, 13(sp)
; CHECKFSGNJ-NEXT: andi a0, a0, 127
; CHECKFSGNJ-NEXT: andi a1, a1, 128
; CHECKFSGNJ-NEXT: or a0, a0, a1
; CHECKFSGNJ-NEXT: sb a0, 9(sp)
; CHECKFSGNJ-NEXT: flh fa0, 8(sp)
; CHECKFSGNJ-NEXT: addi sp, sp, 16
; CHECKFSGNJ-NEXT: ret
; CHECK64FSGNJ-LABEL: fsgnjn_s:
; CHECK64FSGNJ: # %bb.0:
; CHECK64FSGNJ-NEXT: addi sp, sp, -16
; CHECK64FSGNJ-NEXT: fcvt.s.h ft0, fa1
; CHECK64FSGNJ-NEXT: fcvt.s.h ft1, fa0
; CHECK64FSGNJ-NEXT: fadd.s ft0, ft1, ft0
; CHECK64FSGNJ-NEXT: fcvt.h.s ft0, ft0
; CHECK64FSGNJ-NEXT: fcvt.s.h ft0, ft0
; CHECK64FSGNJ-NEXT: fneg.s ft0, ft0
; CHECK64FSGNJ-NEXT: fcvt.h.s ft0, ft0
; CHECK64FSGNJ-NEXT: fsh fa0, 0(sp)
; CHECK64FSGNJ-NEXT: fsh ft0, 8(sp)
; CHECK64FSGNJ-NEXT: lbu a0, 1(sp)
; CHECK64FSGNJ-NEXT: lbu a1, 9(sp)
; CHECK64FSGNJ-NEXT: andi a0, a0, 127
; CHECK64FSGNJ-NEXT: andi a1, a1, 128
; CHECK64FSGNJ-NEXT: or a0, a0, a1
; CHECK64FSGNJ-NEXT: sb a0, 1(sp)
; CHECK64FSGNJ-NEXT: flh fa0, 0(sp)
; CHECK64FSGNJ-NEXT: addi sp, sp, 16
; CHECK64FSGNJ-NEXT: ret
%1 = fadd half %a, %b
%2 = fneg half %1
%3 = call half @llvm.copysign.f16(half %a, half %2)
ret half %3
}
declare half @llvm.fabs.f16(half)
; This function performs extra work to ensure that
; DAGCombiner::visitBITCAST doesn't replace the fabs with an and.
define half @fabs_s(half %a, half %b) nounwind {
; CHECKIZFH-LABEL: fabs_s:
; CHECKIZFH: # %bb.0:
; CHECKIZFH-NEXT: fadd.h fa5, fa0, fa1
; CHECKIZFH-NEXT: fabs.h fa4, fa5
; CHECKIZFH-NEXT: fadd.h fa0, fa4, fa5
; CHECKIZFH-NEXT: ret
;
; RV32I-LABEL: fabs_s:
; RV32I: # %bb.0:
; RV32I-NEXT: addi sp, sp, -16
; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s0, 8(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s1, 4(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s2, 0(sp) # 4-byte Folded Spill
; RV32I-NEXT: mv s0, a1
; RV32I-NEXT: lui a1, 16
; RV32I-NEXT: addi s2, a1, -1
; RV32I-NEXT: and a0, a0, s2
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv s1, a0
; RV32I-NEXT: and a0, s0, s2
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv a1, a0
; RV32I-NEXT: mv a0, s1
; RV32I-NEXT: call __addsf3@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: and a0, a0, s2
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv s0, a0
; RV32I-NEXT: slli a0, a0, 1
; RV32I-NEXT: srli a0, a0, 1
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: and a0, a0, s2
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv a1, s0
; RV32I-NEXT: call __addsf3@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s1, 4(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s2, 0(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 16
; RV32I-NEXT: ret
;
; RV64I-LABEL: fabs_s:
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -32
; RV64I-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s0, 16(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s1, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s2, 0(sp) # 8-byte Folded Spill
; RV64I-NEXT: mv s0, a1
; RV64I-NEXT: lui a1, 16
; RV64I-NEXT: addiw s2, a1, -1
; RV64I-NEXT: and a0, a0, s2
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv s1, a0
; RV64I-NEXT: and a0, s0, s2
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv a1, a0
; RV64I-NEXT: mv a0, s1
; RV64I-NEXT: call __addsf3@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: and a0, a0, s2
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv s0, a0
; RV64I-NEXT: slli a0, a0, 33
; RV64I-NEXT: srli a0, a0, 33
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: and a0, a0, s2
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv a1, s0
; RV64I-NEXT: call __addsf3@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s0, 16(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s1, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s2, 0(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 32
; RV64I-NEXT: ret
;
; CHECKIZFHMIN-LABEL: fabs_s:
; CHECKIZFHMIN: # %bb.0:
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa1
; CHECKIZFHMIN-NEXT: fcvt.s.h fa4, fa0
; CHECKIZFHMIN-NEXT: fadd.s fa5, fa4, fa5
; CHECKIZFHMIN-NEXT: fcvt.h.s fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa5
; CHECKIZFHMIN-NEXT: fabs.s fa4, fa5
; CHECKIZFHMIN-NEXT: fcvt.h.s fa4, fa4
; CHECKIZFHMIN-NEXT: fcvt.s.h fa4, fa4
; CHECKIZFHMIN-NEXT: fadd.s fa5, fa4, fa5
; CHECKIZFHMIN-NEXT: fcvt.h.s fa0, fa5
; CHECKIZFHMIN-NEXT: ret
%1 = fadd half %a, %b
%2 = call half @llvm.fabs.f16(half %1)
%3 = fadd half %2, %1
ret half %3
}
declare half @llvm.minnum.f16(half, half)
define half @fmin_s(half %a, half %b) nounwind {
; CHECKIZFH-LABEL: fmin_s:
; CHECKIZFH: # %bb.0:
; CHECKIZFH-NEXT: fmin.h fa0, fa0, fa1
; CHECKIZFH-NEXT: ret
;
; RV32I-LABEL: fmin_s:
; RV32I: # %bb.0:
; RV32I-NEXT: addi sp, sp, -16
; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s0, 8(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s1, 4(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s2, 0(sp) # 4-byte Folded Spill
; RV32I-NEXT: mv s0, a1
; RV32I-NEXT: lui a1, 16
; RV32I-NEXT: addi s2, a1, -1
; RV32I-NEXT: and a0, a0, s2
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv s1, a0
; RV32I-NEXT: and a0, s0, s2
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv a1, a0
; RV32I-NEXT: mv a0, s1
; RV32I-NEXT: call fminf@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s1, 4(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s2, 0(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 16
; RV32I-NEXT: ret
;
; RV64I-LABEL: fmin_s:
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -32
; RV64I-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s0, 16(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s1, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s2, 0(sp) # 8-byte Folded Spill
; RV64I-NEXT: mv s0, a1
; RV64I-NEXT: lui a1, 16
; RV64I-NEXT: addiw s2, a1, -1
; RV64I-NEXT: and a0, a0, s2
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv s1, a0
; RV64I-NEXT: and a0, s0, s2
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv a1, a0
; RV64I-NEXT: mv a0, s1
; RV64I-NEXT: call fminf@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s0, 16(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s1, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s2, 0(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 32
; RV64I-NEXT: ret
;
; CHECKIZFHMIN-LABEL: fmin_s:
; CHECKIZFHMIN: # %bb.0:
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa1
; CHECKIZFHMIN-NEXT: fcvt.s.h fa4, fa0
; CHECKIZFHMIN-NEXT: fmin.s fa5, fa4, fa5
; CHECKIZFHMIN-NEXT: fcvt.h.s fa0, fa5
; CHECKIZFHMIN-NEXT: ret
%1 = call half @llvm.minnum.f16(half %a, half %b)
ret half %1
}
declare half @llvm.maxnum.f16(half, half)
define half @fmax_s(half %a, half %b) nounwind {
; CHECKIZFH-LABEL: fmax_s:
; CHECKIZFH: # %bb.0:
; CHECKIZFH-NEXT: fmax.h fa0, fa0, fa1
; CHECKIZFH-NEXT: ret
;
; RV32I-LABEL: fmax_s:
; RV32I: # %bb.0:
; RV32I-NEXT: addi sp, sp, -16
; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s0, 8(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s1, 4(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s2, 0(sp) # 4-byte Folded Spill
; RV32I-NEXT: mv s0, a1
; RV32I-NEXT: lui a1, 16
; RV32I-NEXT: addi s2, a1, -1
; RV32I-NEXT: and a0, a0, s2
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv s1, a0
; RV32I-NEXT: and a0, s0, s2
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv a1, a0
; RV32I-NEXT: mv a0, s1
; RV32I-NEXT: call fmaxf@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s1, 4(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s2, 0(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 16
; RV32I-NEXT: ret
;
; RV64I-LABEL: fmax_s:
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -32
; RV64I-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s0, 16(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s1, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s2, 0(sp) # 8-byte Folded Spill
; RV64I-NEXT: mv s0, a1
; RV64I-NEXT: lui a1, 16
; RV64I-NEXT: addiw s2, a1, -1
; RV64I-NEXT: and a0, a0, s2
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv s1, a0
; RV64I-NEXT: and a0, s0, s2
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv a1, a0
; RV64I-NEXT: mv a0, s1
; RV64I-NEXT: call fmaxf@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s0, 16(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s1, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s2, 0(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 32
; RV64I-NEXT: ret
;
; CHECKIZFHMIN-LABEL: fmax_s:
; CHECKIZFHMIN: # %bb.0:
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa1
; CHECKIZFHMIN-NEXT: fcvt.s.h fa4, fa0
; CHECKIZFHMIN-NEXT: fmax.s fa5, fa4, fa5
; CHECKIZFHMIN-NEXT: fcvt.h.s fa0, fa5
; CHECKIZFHMIN-NEXT: ret
%1 = call half @llvm.maxnum.f16(half %a, half %b)
ret half %1
}
declare half @llvm.fma.f16(half, half, half)
define half @fmadd_s(half %a, half %b, half %c) nounwind {
; CHECKIZFH-LABEL: fmadd_s:
; CHECKIZFH: # %bb.0:
; CHECKIZFH-NEXT: fmadd.h fa0, fa0, fa1, fa2
; CHECKIZFH-NEXT: ret
;
; RV32I-LABEL: fmadd_s:
; RV32I: # %bb.0:
; RV32I-NEXT: addi sp, sp, -32
; RV32I-NEXT: sw ra, 28(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s0, 24(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s1, 20(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s2, 16(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s3, 12(sp) # 4-byte Folded Spill
; RV32I-NEXT: mv s0, a2
; RV32I-NEXT: mv s1, a1
; RV32I-NEXT: lui a1, 16
; RV32I-NEXT: addi s3, a1, -1
; RV32I-NEXT: and a0, a0, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv s2, a0
; RV32I-NEXT: and a0, s1, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv s1, a0
; RV32I-NEXT: and a0, s0, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv a2, a0
; RV32I-NEXT: mv a0, s2
; RV32I-NEXT: mv a1, s1
; RV32I-NEXT: call fmaf@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s0, 24(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s1, 20(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s2, 16(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s3, 12(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 32
; RV32I-NEXT: ret
;
; RV64I-LABEL: fmadd_s:
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -48
; RV64I-NEXT: sd ra, 40(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s0, 32(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s1, 24(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s2, 16(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s3, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: mv s0, a2
; RV64I-NEXT: mv s1, a1
; RV64I-NEXT: lui a1, 16
; RV64I-NEXT: addiw s3, a1, -1
; RV64I-NEXT: and a0, a0, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv s2, a0
; RV64I-NEXT: and a0, s1, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv s1, a0
; RV64I-NEXT: and a0, s0, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv a2, a0
; RV64I-NEXT: mv a0, s2
; RV64I-NEXT: mv a1, s1
; RV64I-NEXT: call fmaf@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: ld ra, 40(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s0, 32(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s1, 24(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s2, 16(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s3, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 48
; RV64I-NEXT: ret
;
; CHECKIZFHMIN-LABEL: fmadd_s:
; CHECKIZFHMIN: # %bb.0:
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa2
; CHECKIZFHMIN-NEXT: fcvt.s.h fa4, fa1
; CHECKIZFHMIN-NEXT: fcvt.s.h fa3, fa0
; CHECKIZFHMIN-NEXT: fmadd.s fa5, fa3, fa4, fa5
; CHECKIZFHMIN-NEXT: fcvt.h.s fa0, fa5
; CHECKIZFHMIN-NEXT: ret
%1 = call half @llvm.fma.f16(half %a, half %b, half %c)
ret half %1
}
define half @fmsub_s(half %a, half %b, half %c) nounwind {
; CHECKIZFH-LABEL: fmsub_s:
; CHECKIZFH: # %bb.0:
; CHECKIZFH-NEXT: fmv.h.x fa5, zero
; CHECKIZFH-NEXT: fadd.h fa5, fa2, fa5
; CHECKIZFH-NEXT: fmsub.h fa0, fa0, fa1, fa5
; CHECKIZFH-NEXT: ret
;
; RV32I-LABEL: fmsub_s:
; RV32I: # %bb.0:
; RV32I-NEXT: addi sp, sp, -32
; RV32I-NEXT: sw ra, 28(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s0, 24(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s1, 20(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s2, 16(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s3, 12(sp) # 4-byte Folded Spill
; RV32I-NEXT: mv s0, a1
; RV32I-NEXT: mv s1, a0
; RV32I-NEXT: lui a0, 16
; RV32I-NEXT: addi s3, a0, -1
; RV32I-NEXT: and a0, a2, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: li a1, 0
; RV32I-NEXT: call __addsf3@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: and a0, a0, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: lui a1, 524288
; RV32I-NEXT: xor a0, a0, a1
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: mv s2, a0
; RV32I-NEXT: and a0, s1, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv s1, a0
; RV32I-NEXT: and a0, s0, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv s0, a0
; RV32I-NEXT: and a0, s2, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv a2, a0
; RV32I-NEXT: mv a0, s1
; RV32I-NEXT: mv a1, s0
; RV32I-NEXT: call fmaf@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s0, 24(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s1, 20(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s2, 16(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s3, 12(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 32
; RV32I-NEXT: ret
;
; RV64I-LABEL: fmsub_s:
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -48
; RV64I-NEXT: sd ra, 40(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s0, 32(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s1, 24(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s2, 16(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s3, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: mv s0, a1
; RV64I-NEXT: mv s1, a0
; RV64I-NEXT: lui a0, 16
; RV64I-NEXT: addiw s3, a0, -1
; RV64I-NEXT: and a0, a2, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: li a1, 0
; RV64I-NEXT: call __addsf3@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: and a0, a0, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: lui a1, 524288
; RV64I-NEXT: xor a0, a0, a1
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: mv s2, a0
; RV64I-NEXT: and a0, s1, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv s1, a0
; RV64I-NEXT: and a0, s0, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv s0, a0
; RV64I-NEXT: and a0, s2, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv a2, a0
; RV64I-NEXT: mv a0, s1
; RV64I-NEXT: mv a1, s0
; RV64I-NEXT: call fmaf@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: ld ra, 40(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s0, 32(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s1, 24(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s2, 16(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s3, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 48
; RV64I-NEXT: ret
;
; CHECKIZFHMIN-LABEL: fmsub_s:
; CHECKIZFHMIN: # %bb.0:
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa2
; CHECKIZFHMIN-NEXT: fmv.w.x fa4, zero
; CHECKIZFHMIN-NEXT: fadd.s fa5, fa5, fa4
; CHECKIZFHMIN-NEXT: fcvt.h.s fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa5
; CHECKIZFHMIN-NEXT: fneg.s fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.h.s fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.s.h fa4, fa1
; CHECKIZFHMIN-NEXT: fcvt.s.h fa3, fa0
; CHECKIZFHMIN-NEXT: fmadd.s fa5, fa3, fa4, fa5
; CHECKIZFHMIN-NEXT: fcvt.h.s fa0, fa5
; CHECKIZFHMIN-NEXT: ret
%c_ = fadd half 0.0, %c ; avoid negation using xor
%negc = fsub half -0.0, %c_
%1 = call half @llvm.fma.f16(half %a, half %b, half %negc)
ret half %1
}
define half @fnmadd_s(half %a, half %b, half %c) nounwind {
; CHECKIZFH-LABEL: fnmadd_s:
; CHECKIZFH: # %bb.0:
; CHECKIZFH-NEXT: fmv.h.x fa5, zero
; CHECKIZFH-NEXT: fadd.h fa4, fa0, fa5
; CHECKIZFH-NEXT: fadd.h fa5, fa2, fa5
; CHECKIZFH-NEXT: fnmadd.h fa0, fa4, fa1, fa5
; CHECKIZFH-NEXT: ret
;
; RV32I-LABEL: fnmadd_s:
; RV32I: # %bb.0:
; RV32I-NEXT: addi sp, sp, -32
; RV32I-NEXT: sw ra, 28(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s0, 24(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s1, 20(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s2, 16(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s3, 12(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s4, 8(sp) # 4-byte Folded Spill
; RV32I-NEXT: mv s1, a2
; RV32I-NEXT: mv s0, a1
; RV32I-NEXT: lui s3, 16
; RV32I-NEXT: addi s3, s3, -1
; RV32I-NEXT: and a0, a0, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: li a1, 0
; RV32I-NEXT: call __addsf3@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: mv s2, a0
; RV32I-NEXT: and a0, s1, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: li a1, 0
; RV32I-NEXT: call __addsf3@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: mv s1, a0
; RV32I-NEXT: and a0, s2, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: lui s4, 524288
; RV32I-NEXT: xor a0, a0, s4
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: mv s2, a0
; RV32I-NEXT: and a0, s1, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: xor a0, a0, s4
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: mv s1, a0
; RV32I-NEXT: and a0, s0, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv s0, a0
; RV32I-NEXT: and a0, s2, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv s2, a0
; RV32I-NEXT: and a0, s1, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv a2, a0
; RV32I-NEXT: mv a0, s2
; RV32I-NEXT: mv a1, s0
; RV32I-NEXT: call fmaf@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s0, 24(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s1, 20(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s2, 16(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s3, 12(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s4, 8(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 32
; RV32I-NEXT: ret
;
; RV64I-LABEL: fnmadd_s:
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -48
; RV64I-NEXT: sd ra, 40(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s0, 32(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s1, 24(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s2, 16(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s3, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s4, 0(sp) # 8-byte Folded Spill
; RV64I-NEXT: mv s1, a2
; RV64I-NEXT: mv s0, a1
; RV64I-NEXT: lui s3, 16
; RV64I-NEXT: addiw s3, s3, -1
; RV64I-NEXT: and a0, a0, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: li a1, 0
; RV64I-NEXT: call __addsf3@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: mv s2, a0
; RV64I-NEXT: and a0, s1, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: li a1, 0
; RV64I-NEXT: call __addsf3@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: mv s1, a0
; RV64I-NEXT: and a0, s2, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: lui s4, 524288
; RV64I-NEXT: xor a0, a0, s4
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: mv s2, a0
; RV64I-NEXT: and a0, s1, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: xor a0, a0, s4
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: mv s1, a0
; RV64I-NEXT: and a0, s0, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv s0, a0
; RV64I-NEXT: and a0, s2, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv s2, a0
; RV64I-NEXT: and a0, s1, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv a2, a0
; RV64I-NEXT: mv a0, s2
; RV64I-NEXT: mv a1, s0
; RV64I-NEXT: call fmaf@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: ld ra, 40(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s0, 32(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s1, 24(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s2, 16(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s3, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s4, 0(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 48
; RV64I-NEXT: ret
;
; CHECKIZFHMIN-LABEL: fnmadd_s:
; CHECKIZFHMIN: # %bb.0:
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa0
; CHECKIZFHMIN-NEXT: fmv.w.x fa4, zero
; CHECKIZFHMIN-NEXT: fadd.s fa5, fa5, fa4
; CHECKIZFHMIN-NEXT: fcvt.h.s fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.s.h fa3, fa2
; CHECKIZFHMIN-NEXT: fadd.s fa4, fa3, fa4
; CHECKIZFHMIN-NEXT: fcvt.h.s fa4, fa4
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa5
; CHECKIZFHMIN-NEXT: fneg.s fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.h.s fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.s.h fa4, fa4
; CHECKIZFHMIN-NEXT: fneg.s fa4, fa4
; CHECKIZFHMIN-NEXT: fcvt.h.s fa4, fa4
; CHECKIZFHMIN-NEXT: fcvt.s.h fa4, fa4
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.s.h fa3, fa1
; CHECKIZFHMIN-NEXT: fmadd.s fa5, fa5, fa3, fa4
; CHECKIZFHMIN-NEXT: fcvt.h.s fa0, fa5
; CHECKIZFHMIN-NEXT: ret
%a_ = fadd half 0.0, %a
%c_ = fadd half 0.0, %c
%nega = fsub half -0.0, %a_
%negc = fsub half -0.0, %c_
%1 = call half @llvm.fma.f16(half %nega, half %b, half %negc)
ret half %1
}
define half @fnmadd_s_2(half %a, half %b, half %c) nounwind {
; CHECKIZFH-LABEL: fnmadd_s_2:
; CHECKIZFH: # %bb.0:
; CHECKIZFH-NEXT: fmv.h.x fa5, zero
; CHECKIZFH-NEXT: fadd.h fa4, fa1, fa5
; CHECKIZFH-NEXT: fadd.h fa5, fa2, fa5
; CHECKIZFH-NEXT: fnmadd.h fa0, fa4, fa0, fa5
; CHECKIZFH-NEXT: ret
;
; RV32I-LABEL: fnmadd_s_2:
; RV32I: # %bb.0:
; RV32I-NEXT: addi sp, sp, -32
; RV32I-NEXT: sw ra, 28(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s0, 24(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s1, 20(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s2, 16(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s3, 12(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s4, 8(sp) # 4-byte Folded Spill
; RV32I-NEXT: mv s1, a2
; RV32I-NEXT: mv s0, a0
; RV32I-NEXT: lui s3, 16
; RV32I-NEXT: addi s3, s3, -1
; RV32I-NEXT: and a0, a1, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: li a1, 0
; RV32I-NEXT: call __addsf3@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: mv s2, a0
; RV32I-NEXT: and a0, s1, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: li a1, 0
; RV32I-NEXT: call __addsf3@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: mv s1, a0
; RV32I-NEXT: and a0, s2, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: lui s4, 524288
; RV32I-NEXT: xor a0, a0, s4
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: mv s2, a0
; RV32I-NEXT: and a0, s1, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: xor a0, a0, s4
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: mv s1, a0
; RV32I-NEXT: and a0, s0, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv s0, a0
; RV32I-NEXT: and a0, s2, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv s2, a0
; RV32I-NEXT: and a0, s1, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv a2, a0
; RV32I-NEXT: mv a0, s0
; RV32I-NEXT: mv a1, s2
; RV32I-NEXT: call fmaf@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s0, 24(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s1, 20(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s2, 16(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s3, 12(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s4, 8(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 32
; RV32I-NEXT: ret
;
; RV64I-LABEL: fnmadd_s_2:
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -48
; RV64I-NEXT: sd ra, 40(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s0, 32(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s1, 24(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s2, 16(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s3, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s4, 0(sp) # 8-byte Folded Spill
; RV64I-NEXT: mv s1, a2
; RV64I-NEXT: mv s0, a0
; RV64I-NEXT: lui s3, 16
; RV64I-NEXT: addiw s3, s3, -1
; RV64I-NEXT: and a0, a1, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: li a1, 0
; RV64I-NEXT: call __addsf3@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: mv s2, a0
; RV64I-NEXT: and a0, s1, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: li a1, 0
; RV64I-NEXT: call __addsf3@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: mv s1, a0
; RV64I-NEXT: and a0, s2, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: lui s4, 524288
; RV64I-NEXT: xor a0, a0, s4
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: mv s2, a0
; RV64I-NEXT: and a0, s1, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: xor a0, a0, s4
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: mv s1, a0
; RV64I-NEXT: and a0, s0, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv s0, a0
; RV64I-NEXT: and a0, s2, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv s2, a0
; RV64I-NEXT: and a0, s1, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv a2, a0
; RV64I-NEXT: mv a0, s0
; RV64I-NEXT: mv a1, s2
; RV64I-NEXT: call fmaf@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: ld ra, 40(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s0, 32(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s1, 24(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s2, 16(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s3, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s4, 0(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 48
; RV64I-NEXT: ret
;
; CHECKIZFHMIN-LABEL: fnmadd_s_2:
; CHECKIZFHMIN: # %bb.0:
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa1
; CHECKIZFHMIN-NEXT: fmv.w.x fa4, zero
; CHECKIZFHMIN-NEXT: fadd.s fa5, fa5, fa4
; CHECKIZFHMIN-NEXT: fcvt.h.s fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.s.h fa3, fa2
; CHECKIZFHMIN-NEXT: fadd.s fa4, fa3, fa4
; CHECKIZFHMIN-NEXT: fcvt.h.s fa4, fa4
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa5
; CHECKIZFHMIN-NEXT: fneg.s fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.h.s fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.s.h fa4, fa4
; CHECKIZFHMIN-NEXT: fneg.s fa4, fa4
; CHECKIZFHMIN-NEXT: fcvt.h.s fa4, fa4
; CHECKIZFHMIN-NEXT: fcvt.s.h fa4, fa4
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.s.h fa3, fa0
; CHECKIZFHMIN-NEXT: fmadd.s fa5, fa3, fa5, fa4
; CHECKIZFHMIN-NEXT: fcvt.h.s fa0, fa5
; CHECKIZFHMIN-NEXT: ret
%b_ = fadd half 0.0, %b
%c_ = fadd half 0.0, %c
%negb = fsub half -0.0, %b_
%negc = fsub half -0.0, %c_
%1 = call half @llvm.fma.f16(half %a, half %negb, half %negc)
ret half %1
}
define half @fnmadd_s_3(half %a, half %b, half %c) nounwind {
; RV32IZFH-LABEL: fnmadd_s_3:
; RV32IZFH: # %bb.0:
; RV32IZFH-NEXT: fmadd.h ft0, fa0, fa1, fa2
; RV32IZFH-NEXT: fneg.h fa0, ft0
; RV32IZFH-NEXT: ret
;
; RV64IZFH-LABEL: fnmadd_s_3:
; RV64IZFH: # %bb.0:
; RV64IZFH-NEXT: fmadd.h ft0, fa0, fa1, fa2
; RV64IZFH-NEXT: fneg.h fa0, ft0
; RV64IZFH-NEXT: ret
;
; CHECKIZFH-LABEL: fnmadd_s_3:
; CHECKIZFH: # %bb.0:
; CHECKIZFH-NEXT: fmadd.h fa5, fa0, fa1, fa2
; CHECKIZFH-NEXT: fneg.h fa0, fa5
; CHECKIZFH-NEXT: ret
;
; RV32I-LABEL: fnmadd_s_3:
; RV32I: # %bb.0:
; RV32I-NEXT: addi sp, sp, -32
; RV32I-NEXT: sw ra, 28(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s0, 24(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s1, 20(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s2, 16(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s3, 12(sp) # 4-byte Folded Spill
; RV32I-NEXT: mv s0, a2
; RV32I-NEXT: mv s1, a1
; RV32I-NEXT: lui a1, 16
; RV32I-NEXT: addi s3, a1, -1
; RV32I-NEXT: and a0, a0, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv s2, a0
; RV32I-NEXT: and a0, s1, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv s1, a0
; RV32I-NEXT: and a0, s0, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv a2, a0
; RV32I-NEXT: mv a0, s2
; RV32I-NEXT: mv a1, s1
; RV32I-NEXT: call fmaf@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: lui a1, 1048568
; RV32I-NEXT: xor a0, a0, a1
; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s0, 24(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s1, 20(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s2, 16(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s3, 12(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 32
; RV32I-NEXT: ret
;
; RV64I-LABEL: fnmadd_s_3:
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -48
; RV64I-NEXT: sd ra, 40(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s0, 32(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s1, 24(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s2, 16(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s3, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: mv s0, a2
; RV64I-NEXT: mv s1, a1
; RV64I-NEXT: lui a1, 16
; RV64I-NEXT: addiw s3, a1, -1
; RV64I-NEXT: and a0, a0, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv s2, a0
; RV64I-NEXT: and a0, s1, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv s1, a0
; RV64I-NEXT: and a0, s0, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv a2, a0
; RV64I-NEXT: mv a0, s2
; RV64I-NEXT: mv a1, s1
; RV64I-NEXT: call fmaf@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: lui a1, 1048568
; RV64I-NEXT: xor a0, a0, a1
; RV64I-NEXT: ld ra, 40(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s0, 32(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s1, 24(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s2, 16(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s3, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 48
; RV64I-NEXT: ret
;
; CHECKIZFHMIN-LABEL: fnmadd_s_3:
; CHECKIZFHMIN: # %bb.0:
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa2
; CHECKIZFHMIN-NEXT: fcvt.s.h fa4, fa1
; CHECKIZFHMIN-NEXT: fcvt.s.h fa3, fa0
; CHECKIZFHMIN-NEXT: fmadd.s fa5, fa3, fa4, fa5
; CHECKIZFHMIN-NEXT: fcvt.h.s fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa5
; CHECKIZFHMIN-NEXT: fneg.s fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.h.s fa0, fa5
; CHECKIZFHMIN-NEXT: ret
%1 = call half @llvm.fma.f16(half %a, half %b, half %c)
%neg = fneg half %1
ret half %neg
}
define half @fnmadd_nsz(half %a, half %b, half %c) nounwind {
; RV32IZFH-LABEL: fnmadd_nsz:
; RV32IZFH: # %bb.0:
; RV32IZFH-NEXT: fnmadd.h fa0, fa0, fa1, fa2
; RV32IZFH-NEXT: ret
;
; RV64IZFH-LABEL: fnmadd_nsz:
; RV64IZFH: # %bb.0:
; RV64IZFH-NEXT: fnmadd.h fa0, fa0, fa1, fa2
; RV64IZFH-NEXT: ret
;
; CHECKIZFH-LABEL: fnmadd_nsz:
; CHECKIZFH: # %bb.0:
; CHECKIZFH-NEXT: fnmadd.h fa0, fa0, fa1, fa2
; CHECKIZFH-NEXT: ret
;
; RV32I-LABEL: fnmadd_nsz:
; RV32I: # %bb.0:
; RV32I-NEXT: addi sp, sp, -32
; RV32I-NEXT: sw ra, 28(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s0, 24(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s1, 20(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s2, 16(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s3, 12(sp) # 4-byte Folded Spill
; RV32I-NEXT: mv s0, a2
; RV32I-NEXT: mv s1, a1
; RV32I-NEXT: lui a1, 16
; RV32I-NEXT: addi s3, a1, -1
; RV32I-NEXT: and a0, a0, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv s2, a0
; RV32I-NEXT: and a0, s1, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv s1, a0
; RV32I-NEXT: and a0, s0, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv a2, a0
; RV32I-NEXT: mv a0, s2
; RV32I-NEXT: mv a1, s1
; RV32I-NEXT: call fmaf@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: lui a1, 1048568
; RV32I-NEXT: xor a0, a0, a1
; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s0, 24(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s1, 20(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s2, 16(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s3, 12(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 32
; RV32I-NEXT: ret
;
; RV64I-LABEL: fnmadd_nsz:
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -48
; RV64I-NEXT: sd ra, 40(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s0, 32(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s1, 24(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s2, 16(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s3, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: mv s0, a2
; RV64I-NEXT: mv s1, a1
; RV64I-NEXT: lui a1, 16
; RV64I-NEXT: addiw s3, a1, -1
; RV64I-NEXT: and a0, a0, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv s2, a0
; RV64I-NEXT: and a0, s1, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv s1, a0
; RV64I-NEXT: and a0, s0, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv a2, a0
; RV64I-NEXT: mv a0, s2
; RV64I-NEXT: mv a1, s1
; RV64I-NEXT: call fmaf@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: lui a1, 1048568
; RV64I-NEXT: xor a0, a0, a1
; RV64I-NEXT: ld ra, 40(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s0, 32(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s1, 24(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s2, 16(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s3, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 48
; RV64I-NEXT: ret
;
; CHECKIZFHMIN-LABEL: fnmadd_nsz:
; CHECKIZFHMIN: # %bb.0:
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa2
; CHECKIZFHMIN-NEXT: fcvt.s.h fa4, fa1
; CHECKIZFHMIN-NEXT: fcvt.s.h fa3, fa0
; CHECKIZFHMIN-NEXT: fmadd.s fa5, fa3, fa4, fa5
; CHECKIZFHMIN-NEXT: fcvt.h.s fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa5
; CHECKIZFHMIN-NEXT: fneg.s fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.h.s fa0, fa5
; CHECKIZFHMIN-NEXT: ret
%1 = call nsz half @llvm.fma.f16(half %a, half %b, half %c)
%neg = fneg nsz half %1
ret half %neg
}
define half @fnmsub_s(half %a, half %b, half %c) nounwind {
; CHECKIZFH-LABEL: fnmsub_s:
; CHECKIZFH: # %bb.0:
; CHECKIZFH-NEXT: fmv.h.x fa5, zero
; CHECKIZFH-NEXT: fadd.h fa5, fa0, fa5
; CHECKIZFH-NEXT: fnmsub.h fa0, fa5, fa1, fa2
; CHECKIZFH-NEXT: ret
;
; RV32I-LABEL: fnmsub_s:
; RV32I: # %bb.0:
; RV32I-NEXT: addi sp, sp, -32
; RV32I-NEXT: sw ra, 28(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s0, 24(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s1, 20(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s2, 16(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s3, 12(sp) # 4-byte Folded Spill
; RV32I-NEXT: mv s0, a2
; RV32I-NEXT: mv s1, a1
; RV32I-NEXT: lui a1, 16
; RV32I-NEXT: addi s3, a1, -1
; RV32I-NEXT: and a0, a0, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: li a1, 0
; RV32I-NEXT: call __addsf3@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: and a0, a0, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: lui a1, 524288
; RV32I-NEXT: xor a0, a0, a1
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: mv s2, a0
; RV32I-NEXT: and a0, s1, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv s1, a0
; RV32I-NEXT: and a0, s0, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv s0, a0
; RV32I-NEXT: and a0, s2, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv a1, s1
; RV32I-NEXT: mv a2, s0
; RV32I-NEXT: call fmaf@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s0, 24(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s1, 20(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s2, 16(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s3, 12(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 32
; RV32I-NEXT: ret
;
; RV64I-LABEL: fnmsub_s:
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -48
; RV64I-NEXT: sd ra, 40(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s0, 32(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s1, 24(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s2, 16(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s3, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: mv s0, a2
; RV64I-NEXT: mv s1, a1
; RV64I-NEXT: lui a1, 16
; RV64I-NEXT: addiw s3, a1, -1
; RV64I-NEXT: and a0, a0, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: li a1, 0
; RV64I-NEXT: call __addsf3@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: and a0, a0, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: lui a1, 524288
; RV64I-NEXT: xor a0, a0, a1
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: mv s2, a0
; RV64I-NEXT: and a0, s1, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv s1, a0
; RV64I-NEXT: and a0, s0, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv s0, a0
; RV64I-NEXT: and a0, s2, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv a1, s1
; RV64I-NEXT: mv a2, s0
; RV64I-NEXT: call fmaf@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: ld ra, 40(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s0, 32(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s1, 24(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s2, 16(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s3, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 48
; RV64I-NEXT: ret
;
; CHECKIZFHMIN-LABEL: fnmsub_s:
; CHECKIZFHMIN: # %bb.0:
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa0
; CHECKIZFHMIN-NEXT: fmv.w.x fa4, zero
; CHECKIZFHMIN-NEXT: fadd.s fa5, fa5, fa4
; CHECKIZFHMIN-NEXT: fcvt.h.s fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa5
; CHECKIZFHMIN-NEXT: fneg.s fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.h.s fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.s.h fa4, fa2
; CHECKIZFHMIN-NEXT: fcvt.s.h fa3, fa1
; CHECKIZFHMIN-NEXT: fmadd.s fa5, fa5, fa3, fa4
; CHECKIZFHMIN-NEXT: fcvt.h.s fa0, fa5
; CHECKIZFHMIN-NEXT: ret
%a_ = fadd half 0.0, %a
%nega = fsub half -0.0, %a_
%1 = call half @llvm.fma.f16(half %nega, half %b, half %c)
ret half %1
}
define half @fnmsub_s_2(half %a, half %b, half %c) nounwind {
; CHECKIZFH-LABEL: fnmsub_s_2:
; CHECKIZFH: # %bb.0:
; CHECKIZFH-NEXT: fmv.h.x fa5, zero
; CHECKIZFH-NEXT: fadd.h fa5, fa1, fa5
; CHECKIZFH-NEXT: fnmsub.h fa0, fa5, fa0, fa2
; CHECKIZFH-NEXT: ret
;
; RV32I-LABEL: fnmsub_s_2:
; RV32I: # %bb.0:
; RV32I-NEXT: addi sp, sp, -32
; RV32I-NEXT: sw ra, 28(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s0, 24(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s1, 20(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s2, 16(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s3, 12(sp) # 4-byte Folded Spill
; RV32I-NEXT: mv s0, a2
; RV32I-NEXT: mv s1, a0
; RV32I-NEXT: lui a0, 16
; RV32I-NEXT: addi s3, a0, -1
; RV32I-NEXT: and a0, a1, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: li a1, 0
; RV32I-NEXT: call __addsf3@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: and a0, a0, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: lui a1, 524288
; RV32I-NEXT: xor a0, a0, a1
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: mv s2, a0
; RV32I-NEXT: and a0, s1, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv s1, a0
; RV32I-NEXT: and a0, s0, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv s0, a0
; RV32I-NEXT: and a0, s2, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv a1, a0
; RV32I-NEXT: mv a0, s1
; RV32I-NEXT: mv a2, s0
; RV32I-NEXT: call fmaf@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s0, 24(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s1, 20(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s2, 16(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s3, 12(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 32
; RV32I-NEXT: ret
;
; RV64I-LABEL: fnmsub_s_2:
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -48
; RV64I-NEXT: sd ra, 40(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s0, 32(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s1, 24(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s2, 16(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s3, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: mv s0, a2
; RV64I-NEXT: mv s1, a0
; RV64I-NEXT: lui a0, 16
; RV64I-NEXT: addiw s3, a0, -1
; RV64I-NEXT: and a0, a1, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: li a1, 0
; RV64I-NEXT: call __addsf3@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: and a0, a0, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: lui a1, 524288
; RV64I-NEXT: xor a0, a0, a1
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: mv s2, a0
; RV64I-NEXT: and a0, s1, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv s1, a0
; RV64I-NEXT: and a0, s0, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv s0, a0
; RV64I-NEXT: and a0, s2, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv a1, a0
; RV64I-NEXT: mv a0, s1
; RV64I-NEXT: mv a2, s0
; RV64I-NEXT: call fmaf@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: ld ra, 40(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s0, 32(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s1, 24(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s2, 16(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s3, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 48
; RV64I-NEXT: ret
;
; CHECKIZFHMIN-LABEL: fnmsub_s_2:
; CHECKIZFHMIN: # %bb.0:
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa1
; CHECKIZFHMIN-NEXT: fmv.w.x fa4, zero
; CHECKIZFHMIN-NEXT: fadd.s fa5, fa5, fa4
; CHECKIZFHMIN-NEXT: fcvt.h.s fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa5
; CHECKIZFHMIN-NEXT: fneg.s fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.h.s fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.s.h fa4, fa2
; CHECKIZFHMIN-NEXT: fcvt.s.h fa3, fa0
; CHECKIZFHMIN-NEXT: fmadd.s fa5, fa3, fa5, fa4
; CHECKIZFHMIN-NEXT: fcvt.h.s fa0, fa5
; CHECKIZFHMIN-NEXT: ret
%b_ = fadd half 0.0, %b
%negb = fsub half -0.0, %b_
%1 = call half @llvm.fma.f16(half %a, half %negb, half %c)
ret half %1
}
define half @fmadd_s_contract(half %a, half %b, half %c) nounwind {
; CHECKIZFH-LABEL: fmadd_s_contract:
; CHECKIZFH: # %bb.0:
; CHECKIZFH-NEXT: fmadd.h fa0, fa0, fa1, fa2
; CHECKIZFH-NEXT: ret
;
; RV32I-LABEL: fmadd_s_contract:
; RV32I: # %bb.0:
; RV32I-NEXT: addi sp, sp, -32
; RV32I-NEXT: sw ra, 28(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s0, 24(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s1, 20(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s2, 16(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s3, 12(sp) # 4-byte Folded Spill
; RV32I-NEXT: mv s0, a2
; RV32I-NEXT: mv s1, a1
; RV32I-NEXT: lui a1, 16
; RV32I-NEXT: addi s3, a1, -1
; RV32I-NEXT: and a0, a0, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv s2, a0
; RV32I-NEXT: and a0, s1, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv a1, a0
; RV32I-NEXT: mv a0, s2
; RV32I-NEXT: call __mulsf3@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: mv s1, a0
; RV32I-NEXT: and a0, s0, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv s0, a0
; RV32I-NEXT: and a0, s1, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv a1, s0
; RV32I-NEXT: call __addsf3@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s0, 24(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s1, 20(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s2, 16(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s3, 12(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 32
; RV32I-NEXT: ret
;
; RV64I-LABEL: fmadd_s_contract:
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -48
; RV64I-NEXT: sd ra, 40(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s0, 32(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s1, 24(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s2, 16(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s3, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: mv s0, a2
; RV64I-NEXT: mv s1, a1
; RV64I-NEXT: lui a1, 16
; RV64I-NEXT: addiw s3, a1, -1
; RV64I-NEXT: and a0, a0, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv s2, a0
; RV64I-NEXT: and a0, s1, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv a1, a0
; RV64I-NEXT: mv a0, s2
; RV64I-NEXT: call __mulsf3@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: mv s1, a0
; RV64I-NEXT: and a0, s0, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv s0, a0
; RV64I-NEXT: and a0, s1, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv a1, s0
; RV64I-NEXT: call __addsf3@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: ld ra, 40(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s0, 32(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s1, 24(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s2, 16(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s3, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 48
; RV64I-NEXT: ret
;
; CHECKIZFHMIN-LABEL: fmadd_s_contract:
; CHECKIZFHMIN: # %bb.0:
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa1
; CHECKIZFHMIN-NEXT: fcvt.s.h fa4, fa0
; CHECKIZFHMIN-NEXT: fmul.s fa5, fa4, fa5
; CHECKIZFHMIN-NEXT: fcvt.h.s fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.s.h fa4, fa2
; CHECKIZFHMIN-NEXT: fadd.s fa5, fa5, fa4
; CHECKIZFHMIN-NEXT: fcvt.h.s fa0, fa5
; CHECKIZFHMIN-NEXT: ret
%1 = fmul contract half %a, %b
%2 = fadd contract half %1, %c
ret half %2
}
define half @fmsub_s_contract(half %a, half %b, half %c) nounwind {
; CHECKIZFH-LABEL: fmsub_s_contract:
; CHECKIZFH: # %bb.0:
; CHECKIZFH-NEXT: fmv.h.x fa5, zero
; CHECKIZFH-NEXT: fadd.h fa5, fa2, fa5
; CHECKIZFH-NEXT: fmsub.h fa0, fa0, fa1, fa5
; CHECKIZFH-NEXT: ret
;
; RV32I-LABEL: fmsub_s_contract:
; RV32I: # %bb.0:
; RV32I-NEXT: addi sp, sp, -32
; RV32I-NEXT: sw ra, 28(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s0, 24(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s1, 20(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s2, 16(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s3, 12(sp) # 4-byte Folded Spill
; RV32I-NEXT: mv s0, a1
; RV32I-NEXT: mv s1, a0
; RV32I-NEXT: lui a0, 16
; RV32I-NEXT: addi s3, a0, -1
; RV32I-NEXT: and a0, a2, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: li a1, 0
; RV32I-NEXT: call __addsf3@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: mv s2, a0
; RV32I-NEXT: and a0, s1, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv s1, a0
; RV32I-NEXT: and a0, s0, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv a1, a0
; RV32I-NEXT: mv a0, s1
; RV32I-NEXT: call __mulsf3@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: and a0, a0, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv s0, a0
; RV32I-NEXT: and a0, s2, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv a1, a0
; RV32I-NEXT: mv a0, s0
; RV32I-NEXT: call __subsf3@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s0, 24(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s1, 20(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s2, 16(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s3, 12(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 32
; RV32I-NEXT: ret
;
; RV64I-LABEL: fmsub_s_contract:
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -48
; RV64I-NEXT: sd ra, 40(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s0, 32(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s1, 24(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s2, 16(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s3, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: mv s0, a1
; RV64I-NEXT: mv s1, a0
; RV64I-NEXT: lui a0, 16
; RV64I-NEXT: addiw s3, a0, -1
; RV64I-NEXT: and a0, a2, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: li a1, 0
; RV64I-NEXT: call __addsf3@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: mv s2, a0
; RV64I-NEXT: and a0, s1, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv s1, a0
; RV64I-NEXT: and a0, s0, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv a1, a0
; RV64I-NEXT: mv a0, s1
; RV64I-NEXT: call __mulsf3@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: and a0, a0, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv s0, a0
; RV64I-NEXT: and a0, s2, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv a1, a0
; RV64I-NEXT: mv a0, s0
; RV64I-NEXT: call __subsf3@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: ld ra, 40(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s0, 32(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s1, 24(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s2, 16(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s3, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 48
; RV64I-NEXT: ret
;
; CHECKIZFHMIN-LABEL: fmsub_s_contract:
; CHECKIZFHMIN: # %bb.0:
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa2
; CHECKIZFHMIN-NEXT: fmv.w.x fa4, zero
; CHECKIZFHMIN-NEXT: fadd.s fa5, fa5, fa4
; CHECKIZFHMIN-NEXT: fcvt.h.s fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.s.h fa4, fa1
; CHECKIZFHMIN-NEXT: fcvt.s.h fa3, fa0
; CHECKIZFHMIN-NEXT: fmul.s fa4, fa3, fa4
; CHECKIZFHMIN-NEXT: fcvt.h.s fa4, fa4
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.s.h fa4, fa4
; CHECKIZFHMIN-NEXT: fsub.s fa5, fa4, fa5
; CHECKIZFHMIN-NEXT: fcvt.h.s fa0, fa5
; CHECKIZFHMIN-NEXT: ret
%c_ = fadd half 0.0, %c ; avoid negation using xor
%1 = fmul contract half %a, %b
%2 = fsub contract half %1, %c_
ret half %2
}
define half @fnmadd_s_contract(half %a, half %b, half %c) nounwind {
; CHECKIZFH-LABEL: fnmadd_s_contract:
; CHECKIZFH: # %bb.0:
; CHECKIZFH-NEXT: fmv.h.x fa5, zero
; CHECKIZFH-NEXT: fadd.h fa4, fa0, fa5
; CHECKIZFH-NEXT: fadd.h fa3, fa1, fa5
; CHECKIZFH-NEXT: fadd.h fa5, fa2, fa5
; CHECKIZFH-NEXT: fnmadd.h fa0, fa4, fa3, fa5
; CHECKIZFH-NEXT: ret
;
; RV32I-LABEL: fnmadd_s_contract:
; RV32I: # %bb.0:
; RV32I-NEXT: addi sp, sp, -32
; RV32I-NEXT: sw ra, 28(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s0, 24(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s1, 20(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s2, 16(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s3, 12(sp) # 4-byte Folded Spill
; RV32I-NEXT: mv s0, a2
; RV32I-NEXT: mv s1, a1
; RV32I-NEXT: lui s3, 16
; RV32I-NEXT: addi s3, s3, -1
; RV32I-NEXT: and a0, a0, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: li a1, 0
; RV32I-NEXT: call __addsf3@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: mv s2, a0
; RV32I-NEXT: and a0, s1, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: li a1, 0
; RV32I-NEXT: call __addsf3@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: mv s1, a0
; RV32I-NEXT: and a0, s0, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: li a1, 0
; RV32I-NEXT: call __addsf3@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: mv s0, a0
; RV32I-NEXT: and a0, s2, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv s2, a0
; RV32I-NEXT: and a0, s1, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv a1, a0
; RV32I-NEXT: mv a0, s2
; RV32I-NEXT: call __mulsf3@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: and a0, a0, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: lui a1, 524288
; RV32I-NEXT: xor a0, a0, a1
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: mv s1, a0
; RV32I-NEXT: and a0, s0, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv s0, a0
; RV32I-NEXT: and a0, s1, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv a1, s0
; RV32I-NEXT: call __subsf3@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s0, 24(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s1, 20(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s2, 16(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s3, 12(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 32
; RV32I-NEXT: ret
;
; RV64I-LABEL: fnmadd_s_contract:
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -48
; RV64I-NEXT: sd ra, 40(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s0, 32(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s1, 24(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s2, 16(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s3, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: mv s0, a2
; RV64I-NEXT: mv s1, a1
; RV64I-NEXT: lui s3, 16
; RV64I-NEXT: addiw s3, s3, -1
; RV64I-NEXT: and a0, a0, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: li a1, 0
; RV64I-NEXT: call __addsf3@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: mv s2, a0
; RV64I-NEXT: and a0, s1, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: li a1, 0
; RV64I-NEXT: call __addsf3@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: mv s1, a0
; RV64I-NEXT: and a0, s0, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: li a1, 0
; RV64I-NEXT: call __addsf3@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: mv s0, a0
; RV64I-NEXT: and a0, s2, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv s2, a0
; RV64I-NEXT: and a0, s1, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv a1, a0
; RV64I-NEXT: mv a0, s2
; RV64I-NEXT: call __mulsf3@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: and a0, a0, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: lui a1, 524288
; RV64I-NEXT: xor a0, a0, a1
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: mv s1, a0
; RV64I-NEXT: and a0, s0, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv s0, a0
; RV64I-NEXT: and a0, s1, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv a1, s0
; RV64I-NEXT: call __subsf3@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: ld ra, 40(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s0, 32(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s1, 24(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s2, 16(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s3, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 48
; RV64I-NEXT: ret
;
; CHECKIZFHMIN-LABEL: fnmadd_s_contract:
; CHECKIZFHMIN: # %bb.0:
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa0
; CHECKIZFHMIN-NEXT: fmv.w.x fa4, zero
; CHECKIZFHMIN-NEXT: fadd.s fa5, fa5, fa4
; CHECKIZFHMIN-NEXT: fcvt.h.s fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.s.h fa3, fa1
; CHECKIZFHMIN-NEXT: fadd.s fa3, fa3, fa4
; CHECKIZFHMIN-NEXT: fcvt.h.s fa3, fa3
; CHECKIZFHMIN-NEXT: fcvt.s.h fa2, fa2
; CHECKIZFHMIN-NEXT: fadd.s fa4, fa2, fa4
; CHECKIZFHMIN-NEXT: fcvt.h.s fa4, fa4
; CHECKIZFHMIN-NEXT: fcvt.s.h fa3, fa3
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa5
; CHECKIZFHMIN-NEXT: fmul.s fa5, fa5, fa3
; CHECKIZFHMIN-NEXT: fcvt.h.s fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa5
; CHECKIZFHMIN-NEXT: fneg.s fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.h.s fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.s.h fa4, fa4
; CHECKIZFHMIN-NEXT: fsub.s fa5, fa5, fa4
; CHECKIZFHMIN-NEXT: fcvt.h.s fa0, fa5
; CHECKIZFHMIN-NEXT: ret
%a_ = fadd half 0.0, %a ; avoid negation using xor
%b_ = fadd half 0.0, %b ; avoid negation using xor
%c_ = fadd half 0.0, %c ; avoid negation using xor
%1 = fmul contract half %a_, %b_
%2 = fneg half %1
%3 = fsub contract half %2, %c_
ret half %3
}
define half @fnmsub_s_contract(half %a, half %b, half %c) nounwind {
; CHECKIZFH-LABEL: fnmsub_s_contract:
; CHECKIZFH: # %bb.0:
; CHECKIZFH-NEXT: fmv.h.x fa5, zero
; CHECKIZFH-NEXT: fadd.h fa4, fa0, fa5
; CHECKIZFH-NEXT: fadd.h fa5, fa1, fa5
; CHECKIZFH-NEXT: fnmsub.h fa0, fa4, fa5, fa2
; CHECKIZFH-NEXT: ret
;
; RV32I-LABEL: fnmsub_s_contract:
; RV32I: # %bb.0:
; RV32I-NEXT: addi sp, sp, -32
; RV32I-NEXT: sw ra, 28(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s0, 24(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s1, 20(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s2, 16(sp) # 4-byte Folded Spill
; RV32I-NEXT: sw s3, 12(sp) # 4-byte Folded Spill
; RV32I-NEXT: mv s0, a2
; RV32I-NEXT: mv s1, a1
; RV32I-NEXT: lui s3, 16
; RV32I-NEXT: addi s3, s3, -1
; RV32I-NEXT: and a0, a0, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: li a1, 0
; RV32I-NEXT: call __addsf3@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: mv s2, a0
; RV32I-NEXT: and a0, s1, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: li a1, 0
; RV32I-NEXT: call __addsf3@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: mv s1, a0
; RV32I-NEXT: and a0, s2, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv s2, a0
; RV32I-NEXT: and a0, s1, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv a1, a0
; RV32I-NEXT: mv a0, s2
; RV32I-NEXT: call __mulsf3@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: mv s1, a0
; RV32I-NEXT: and a0, s0, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv s0, a0
; RV32I-NEXT: and a0, s1, s3
; RV32I-NEXT: call __extendhfsf2@plt
; RV32I-NEXT: mv a1, a0
; RV32I-NEXT: mv a0, s0
; RV32I-NEXT: call __subsf3@plt
; RV32I-NEXT: call __truncsfhf2@plt
; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s0, 24(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s1, 20(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s2, 16(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s3, 12(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 32
; RV32I-NEXT: ret
;
; RV64I-LABEL: fnmsub_s_contract:
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -48
; RV64I-NEXT: sd ra, 40(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s0, 32(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s1, 24(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s2, 16(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s3, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: mv s0, a2
; RV64I-NEXT: mv s1, a1
; RV64I-NEXT: lui s3, 16
; RV64I-NEXT: addiw s3, s3, -1
; RV64I-NEXT: and a0, a0, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: li a1, 0
; RV64I-NEXT: call __addsf3@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: mv s2, a0
; RV64I-NEXT: and a0, s1, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: li a1, 0
; RV64I-NEXT: call __addsf3@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: mv s1, a0
; RV64I-NEXT: and a0, s2, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv s2, a0
; RV64I-NEXT: and a0, s1, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv a1, a0
; RV64I-NEXT: mv a0, s2
; RV64I-NEXT: call __mulsf3@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: mv s1, a0
; RV64I-NEXT: and a0, s0, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv s0, a0
; RV64I-NEXT: and a0, s1, s3
; RV64I-NEXT: call __extendhfsf2@plt
; RV64I-NEXT: mv a1, a0
; RV64I-NEXT: mv a0, s0
; RV64I-NEXT: call __subsf3@plt
; RV64I-NEXT: call __truncsfhf2@plt
; RV64I-NEXT: ld ra, 40(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s0, 32(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s1, 24(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s2, 16(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s3, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 48
; RV64I-NEXT: ret
;
; CHECKIZFHMIN-LABEL: fnmsub_s_contract:
; CHECKIZFHMIN: # %bb.0:
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa0
; CHECKIZFHMIN-NEXT: fmv.w.x fa4, zero
; CHECKIZFHMIN-NEXT: fadd.s fa5, fa5, fa4
; CHECKIZFHMIN-NEXT: fcvt.h.s fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.s.h fa3, fa1
; CHECKIZFHMIN-NEXT: fadd.s fa4, fa3, fa4
; CHECKIZFHMIN-NEXT: fcvt.h.s fa4, fa4
; CHECKIZFHMIN-NEXT: fcvt.s.h fa4, fa4
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa5
; CHECKIZFHMIN-NEXT: fmul.s fa5, fa5, fa4
; CHECKIZFHMIN-NEXT: fcvt.h.s fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.s.h fa5, fa5
; CHECKIZFHMIN-NEXT: fcvt.s.h fa4, fa2
; CHECKIZFHMIN-NEXT: fsub.s fa5, fa4, fa5
; CHECKIZFHMIN-NEXT: fcvt.h.s fa0, fa5
; CHECKIZFHMIN-NEXT: ret
%a_ = fadd half 0.0, %a ; avoid negation using xor
%b_ = fadd half 0.0, %b ; avoid negation using xor
%1 = fmul contract half %a_, %b_
%2 = fsub contract half %c, %1
ret half %2
}