llvm/llvm/test/CodeGen/LoongArch/float-fma.ll

; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc --mtriple=loongarch32 --mattr=+f,-d --fp-contract=fast < %s \
; RUN:   | FileCheck %s --check-prefix=LA32-CONTRACT-FAST
; RUN: llc --mtriple=loongarch32 --mattr=+f,-d --fp-contract=on < %s \
; RUN:   | FileCheck %s --check-prefix=LA32-CONTRACT-ON
; RUN: llc --mtriple=loongarch32 --mattr=+f,-d --fp-contract=off < %s \
; RUN:   | FileCheck %s --check-prefix=LA32-CONTRACT-OFF
; RUN: llc --mtriple=loongarch64 --mattr=+f,-d --fp-contract=fast < %s \
; RUN:   | FileCheck %s --check-prefix=LA64-CONTRACT-FAST
; RUN: llc --mtriple=loongarch64 --mattr=+f,-d --fp-contract=on < %s \
; RUN:   | FileCheck %s --check-prefix=LA64-CONTRACT-ON
; RUN: llc --mtriple=loongarch64 --mattr=+f,-d --fp-contract=off < %s \
; RUN:   | FileCheck %s --check-prefix=LA64-CONTRACT-OFF

define float @fmadd_s(float %a, float %b, float %c) nounwind {
; LA32-CONTRACT-FAST-LABEL: fmadd_s:
; LA32-CONTRACT-FAST:       # %bb.0:
; LA32-CONTRACT-FAST-NEXT:    fmadd.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-FAST-NEXT:    ret
;
; LA32-CONTRACT-ON-LABEL: fmadd_s:
; LA32-CONTRACT-ON:       # %bb.0:
; LA32-CONTRACT-ON-NEXT:    fmul.s $fa0, $fa0, $fa1
; LA32-CONTRACT-ON-NEXT:    fadd.s $fa0, $fa0, $fa2
; LA32-CONTRACT-ON-NEXT:    ret
;
; LA32-CONTRACT-OFF-LABEL: fmadd_s:
; LA32-CONTRACT-OFF:       # %bb.0:
; LA32-CONTRACT-OFF-NEXT:    fmul.s $fa0, $fa0, $fa1
; LA32-CONTRACT-OFF-NEXT:    fadd.s $fa0, $fa0, $fa2
; LA32-CONTRACT-OFF-NEXT:    ret
;
; LA64-CONTRACT-FAST-LABEL: fmadd_s:
; LA64-CONTRACT-FAST:       # %bb.0:
; LA64-CONTRACT-FAST-NEXT:    fmadd.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-FAST-NEXT:    ret
;
; LA64-CONTRACT-ON-LABEL: fmadd_s:
; LA64-CONTRACT-ON:       # %bb.0:
; LA64-CONTRACT-ON-NEXT:    fmul.s $fa0, $fa0, $fa1
; LA64-CONTRACT-ON-NEXT:    fadd.s $fa0, $fa0, $fa2
; LA64-CONTRACT-ON-NEXT:    ret
;
; LA64-CONTRACT-OFF-LABEL: fmadd_s:
; LA64-CONTRACT-OFF:       # %bb.0:
; LA64-CONTRACT-OFF-NEXT:    fmul.s $fa0, $fa0, $fa1
; LA64-CONTRACT-OFF-NEXT:    fadd.s $fa0, $fa0, $fa2
; LA64-CONTRACT-OFF-NEXT:    ret
  %mul = fmul float %a, %b
  %add = fadd float %mul, %c
  ret float %add
}

define float @fmsub_s(float %a, float %b, float %c) nounwind {
; LA32-CONTRACT-FAST-LABEL: fmsub_s:
; LA32-CONTRACT-FAST:       # %bb.0:
; LA32-CONTRACT-FAST-NEXT:    fmsub.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-FAST-NEXT:    ret
;
; LA32-CONTRACT-ON-LABEL: fmsub_s:
; LA32-CONTRACT-ON:       # %bb.0:
; LA32-CONTRACT-ON-NEXT:    fmul.s $fa0, $fa0, $fa1
; LA32-CONTRACT-ON-NEXT:    fsub.s $fa0, $fa0, $fa2
; LA32-CONTRACT-ON-NEXT:    ret
;
; LA32-CONTRACT-OFF-LABEL: fmsub_s:
; LA32-CONTRACT-OFF:       # %bb.0:
; LA32-CONTRACT-OFF-NEXT:    fmul.s $fa0, $fa0, $fa1
; LA32-CONTRACT-OFF-NEXT:    fsub.s $fa0, $fa0, $fa2
; LA32-CONTRACT-OFF-NEXT:    ret
;
; LA64-CONTRACT-FAST-LABEL: fmsub_s:
; LA64-CONTRACT-FAST:       # %bb.0:
; LA64-CONTRACT-FAST-NEXT:    fmsub.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-FAST-NEXT:    ret
;
; LA64-CONTRACT-ON-LABEL: fmsub_s:
; LA64-CONTRACT-ON:       # %bb.0:
; LA64-CONTRACT-ON-NEXT:    fmul.s $fa0, $fa0, $fa1
; LA64-CONTRACT-ON-NEXT:    fsub.s $fa0, $fa0, $fa2
; LA64-CONTRACT-ON-NEXT:    ret
;
; LA64-CONTRACT-OFF-LABEL: fmsub_s:
; LA64-CONTRACT-OFF:       # %bb.0:
; LA64-CONTRACT-OFF-NEXT:    fmul.s $fa0, $fa0, $fa1
; LA64-CONTRACT-OFF-NEXT:    fsub.s $fa0, $fa0, $fa2
; LA64-CONTRACT-OFF-NEXT:    ret
  %mul = fmul float %a, %b
  %sub = fsub float %mul, %c
  ret float %sub
}

define float @fnmadd_s(float %a, float %b, float %c) nounwind {
; LA32-CONTRACT-FAST-LABEL: fnmadd_s:
; LA32-CONTRACT-FAST:       # %bb.0:
; LA32-CONTRACT-FAST-NEXT:    fnmadd.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-FAST-NEXT:    ret
;
; LA32-CONTRACT-ON-LABEL: fnmadd_s:
; LA32-CONTRACT-ON:       # %bb.0:
; LA32-CONTRACT-ON-NEXT:    fmul.s $fa0, $fa0, $fa1
; LA32-CONTRACT-ON-NEXT:    fadd.s $fa0, $fa0, $fa2
; LA32-CONTRACT-ON-NEXT:    fneg.s $fa0, $fa0
; LA32-CONTRACT-ON-NEXT:    ret
;
; LA32-CONTRACT-OFF-LABEL: fnmadd_s:
; LA32-CONTRACT-OFF:       # %bb.0:
; LA32-CONTRACT-OFF-NEXT:    fmul.s $fa0, $fa0, $fa1
; LA32-CONTRACT-OFF-NEXT:    fadd.s $fa0, $fa0, $fa2
; LA32-CONTRACT-OFF-NEXT:    fneg.s $fa0, $fa0
; LA32-CONTRACT-OFF-NEXT:    ret
;
; LA64-CONTRACT-FAST-LABEL: fnmadd_s:
; LA64-CONTRACT-FAST:       # %bb.0:
; LA64-CONTRACT-FAST-NEXT:    fnmadd.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-FAST-NEXT:    ret
;
; LA64-CONTRACT-ON-LABEL: fnmadd_s:
; LA64-CONTRACT-ON:       # %bb.0:
; LA64-CONTRACT-ON-NEXT:    fmul.s $fa0, $fa0, $fa1
; LA64-CONTRACT-ON-NEXT:    fadd.s $fa0, $fa0, $fa2
; LA64-CONTRACT-ON-NEXT:    fneg.s $fa0, $fa0
; LA64-CONTRACT-ON-NEXT:    ret
;
; LA64-CONTRACT-OFF-LABEL: fnmadd_s:
; LA64-CONTRACT-OFF:       # %bb.0:
; LA64-CONTRACT-OFF-NEXT:    fmul.s $fa0, $fa0, $fa1
; LA64-CONTRACT-OFF-NEXT:    fadd.s $fa0, $fa0, $fa2
; LA64-CONTRACT-OFF-NEXT:    fneg.s $fa0, $fa0
; LA64-CONTRACT-OFF-NEXT:    ret
  %mul = fmul float %a, %b
  %add = fadd float %mul, %c
  %negadd = fneg float %add
  ret float %negadd
}

define float @fnmadd_s_nsz(float %a, float %b, float %c) nounwind {
; LA32-CONTRACT-FAST-LABEL: fnmadd_s_nsz:
; LA32-CONTRACT-FAST:       # %bb.0:
; LA32-CONTRACT-FAST-NEXT:    fnmadd.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-FAST-NEXT:    ret
;
; LA32-CONTRACT-ON-LABEL: fnmadd_s_nsz:
; LA32-CONTRACT-ON:       # %bb.0:
; LA32-CONTRACT-ON-NEXT:    fneg.s $fa0, $fa0
; LA32-CONTRACT-ON-NEXT:    fmul.s $fa0, $fa0, $fa1
; LA32-CONTRACT-ON-NEXT:    fsub.s $fa0, $fa0, $fa2
; LA32-CONTRACT-ON-NEXT:    ret
;
; LA32-CONTRACT-OFF-LABEL: fnmadd_s_nsz:
; LA32-CONTRACT-OFF:       # %bb.0:
; LA32-CONTRACT-OFF-NEXT:    fneg.s $fa0, $fa0
; LA32-CONTRACT-OFF-NEXT:    fmul.s $fa0, $fa0, $fa1
; LA32-CONTRACT-OFF-NEXT:    fsub.s $fa0, $fa0, $fa2
; LA32-CONTRACT-OFF-NEXT:    ret
;
; LA64-CONTRACT-FAST-LABEL: fnmadd_s_nsz:
; LA64-CONTRACT-FAST:       # %bb.0:
; LA64-CONTRACT-FAST-NEXT:    fnmadd.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-FAST-NEXT:    ret
;
; LA64-CONTRACT-ON-LABEL: fnmadd_s_nsz:
; LA64-CONTRACT-ON:       # %bb.0:
; LA64-CONTRACT-ON-NEXT:    fneg.s $fa0, $fa0
; LA64-CONTRACT-ON-NEXT:    fmul.s $fa0, $fa0, $fa1
; LA64-CONTRACT-ON-NEXT:    fsub.s $fa0, $fa0, $fa2
; LA64-CONTRACT-ON-NEXT:    ret
;
; LA64-CONTRACT-OFF-LABEL: fnmadd_s_nsz:
; LA64-CONTRACT-OFF:       # %bb.0:
; LA64-CONTRACT-OFF-NEXT:    fneg.s $fa0, $fa0
; LA64-CONTRACT-OFF-NEXT:    fmul.s $fa0, $fa0, $fa1
; LA64-CONTRACT-OFF-NEXT:    fsub.s $fa0, $fa0, $fa2
; LA64-CONTRACT-OFF-NEXT:    ret
  %nega = fneg nsz float %a
  %negc = fneg nsz float %c
  %mul = fmul nsz float %nega, %b
  %add = fadd nsz float %mul, %negc
  ret float %add
}

;; Check that fnmadd.s is not emitted.
define float @not_fnmadd_s(float %a, float %b, float %c) nounwind {
; LA32-CONTRACT-FAST-LABEL: not_fnmadd_s:
; LA32-CONTRACT-FAST:       # %bb.0:
; LA32-CONTRACT-FAST-NEXT:    fneg.s $fa0, $fa0
; LA32-CONTRACT-FAST-NEXT:    fmsub.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-FAST-NEXT:    ret
;
; LA32-CONTRACT-ON-LABEL: not_fnmadd_s:
; LA32-CONTRACT-ON:       # %bb.0:
; LA32-CONTRACT-ON-NEXT:    fneg.s $fa0, $fa0
; LA32-CONTRACT-ON-NEXT:    fmul.s $fa0, $fa0, $fa1
; LA32-CONTRACT-ON-NEXT:    fsub.s $fa0, $fa0, $fa2
; LA32-CONTRACT-ON-NEXT:    ret
;
; LA32-CONTRACT-OFF-LABEL: not_fnmadd_s:
; LA32-CONTRACT-OFF:       # %bb.0:
; LA32-CONTRACT-OFF-NEXT:    fneg.s $fa0, $fa0
; LA32-CONTRACT-OFF-NEXT:    fmul.s $fa0, $fa0, $fa1
; LA32-CONTRACT-OFF-NEXT:    fsub.s $fa0, $fa0, $fa2
; LA32-CONTRACT-OFF-NEXT:    ret
;
; LA64-CONTRACT-FAST-LABEL: not_fnmadd_s:
; LA64-CONTRACT-FAST:       # %bb.0:
; LA64-CONTRACT-FAST-NEXT:    fneg.s $fa0, $fa0
; LA64-CONTRACT-FAST-NEXT:    fmsub.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-FAST-NEXT:    ret
;
; LA64-CONTRACT-ON-LABEL: not_fnmadd_s:
; LA64-CONTRACT-ON:       # %bb.0:
; LA64-CONTRACT-ON-NEXT:    fneg.s $fa0, $fa0
; LA64-CONTRACT-ON-NEXT:    fmul.s $fa0, $fa0, $fa1
; LA64-CONTRACT-ON-NEXT:    fsub.s $fa0, $fa0, $fa2
; LA64-CONTRACT-ON-NEXT:    ret
;
; LA64-CONTRACT-OFF-LABEL: not_fnmadd_s:
; LA64-CONTRACT-OFF:       # %bb.0:
; LA64-CONTRACT-OFF-NEXT:    fneg.s $fa0, $fa0
; LA64-CONTRACT-OFF-NEXT:    fmul.s $fa0, $fa0, $fa1
; LA64-CONTRACT-OFF-NEXT:    fsub.s $fa0, $fa0, $fa2
; LA64-CONTRACT-OFF-NEXT:    ret
  %nega = fneg float %a
  %negc = fneg float %c
  %mul = fmul float %nega, %b
  %add = fadd float %mul, %negc
  ret float %add
}

define float @fnmsub_s(float %a, float %b, float %c) nounwind {
; LA32-CONTRACT-FAST-LABEL: fnmsub_s:
; LA32-CONTRACT-FAST:       # %bb.0:
; LA32-CONTRACT-FAST-NEXT:    fnmsub.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-FAST-NEXT:    ret
;
; LA32-CONTRACT-ON-LABEL: fnmsub_s:
; LA32-CONTRACT-ON:       # %bb.0:
; LA32-CONTRACT-ON-NEXT:    fmul.s $fa0, $fa0, $fa1
; LA32-CONTRACT-ON-NEXT:    fsub.s $fa0, $fa0, $fa2
; LA32-CONTRACT-ON-NEXT:    fneg.s $fa0, $fa0
; LA32-CONTRACT-ON-NEXT:    ret
;
; LA32-CONTRACT-OFF-LABEL: fnmsub_s:
; LA32-CONTRACT-OFF:       # %bb.0:
; LA32-CONTRACT-OFF-NEXT:    fmul.s $fa0, $fa0, $fa1
; LA32-CONTRACT-OFF-NEXT:    fsub.s $fa0, $fa0, $fa2
; LA32-CONTRACT-OFF-NEXT:    fneg.s $fa0, $fa0
; LA32-CONTRACT-OFF-NEXT:    ret
;
; LA64-CONTRACT-FAST-LABEL: fnmsub_s:
; LA64-CONTRACT-FAST:       # %bb.0:
; LA64-CONTRACT-FAST-NEXT:    fnmsub.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-FAST-NEXT:    ret
;
; LA64-CONTRACT-ON-LABEL: fnmsub_s:
; LA64-CONTRACT-ON:       # %bb.0:
; LA64-CONTRACT-ON-NEXT:    fmul.s $fa0, $fa0, $fa1
; LA64-CONTRACT-ON-NEXT:    fsub.s $fa0, $fa0, $fa2
; LA64-CONTRACT-ON-NEXT:    fneg.s $fa0, $fa0
; LA64-CONTRACT-ON-NEXT:    ret
;
; LA64-CONTRACT-OFF-LABEL: fnmsub_s:
; LA64-CONTRACT-OFF:       # %bb.0:
; LA64-CONTRACT-OFF-NEXT:    fmul.s $fa0, $fa0, $fa1
; LA64-CONTRACT-OFF-NEXT:    fsub.s $fa0, $fa0, $fa2
; LA64-CONTRACT-OFF-NEXT:    fneg.s $fa0, $fa0
; LA64-CONTRACT-OFF-NEXT:    ret
  %negc = fneg float %c
  %mul = fmul float %a, %b
  %add = fadd float %mul, %negc
  %neg = fneg float %add
  ret float %neg
}

define float @fnmsub_s_nsz(float %a, float %b, float %c) nounwind {
; LA32-CONTRACT-FAST-LABEL: fnmsub_s_nsz:
; LA32-CONTRACT-FAST:       # %bb.0:
; LA32-CONTRACT-FAST-NEXT:    fnmsub.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-FAST-NEXT:    ret
;
; LA32-CONTRACT-ON-LABEL: fnmsub_s_nsz:
; LA32-CONTRACT-ON:       # %bb.0:
; LA32-CONTRACT-ON-NEXT:    fmul.s $fa0, $fa0, $fa1
; LA32-CONTRACT-ON-NEXT:    fsub.s $fa0, $fa2, $fa0
; LA32-CONTRACT-ON-NEXT:    ret
;
; LA32-CONTRACT-OFF-LABEL: fnmsub_s_nsz:
; LA32-CONTRACT-OFF:       # %bb.0:
; LA32-CONTRACT-OFF-NEXT:    fmul.s $fa0, $fa0, $fa1
; LA32-CONTRACT-OFF-NEXT:    fsub.s $fa0, $fa2, $fa0
; LA32-CONTRACT-OFF-NEXT:    ret
;
; LA64-CONTRACT-FAST-LABEL: fnmsub_s_nsz:
; LA64-CONTRACT-FAST:       # %bb.0:
; LA64-CONTRACT-FAST-NEXT:    fnmsub.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-FAST-NEXT:    ret
;
; LA64-CONTRACT-ON-LABEL: fnmsub_s_nsz:
; LA64-CONTRACT-ON:       # %bb.0:
; LA64-CONTRACT-ON-NEXT:    fmul.s $fa0, $fa0, $fa1
; LA64-CONTRACT-ON-NEXT:    fsub.s $fa0, $fa2, $fa0
; LA64-CONTRACT-ON-NEXT:    ret
;
; LA64-CONTRACT-OFF-LABEL: fnmsub_s_nsz:
; LA64-CONTRACT-OFF:       # %bb.0:
; LA64-CONTRACT-OFF-NEXT:    fmul.s $fa0, $fa0, $fa1
; LA64-CONTRACT-OFF-NEXT:    fsub.s $fa0, $fa2, $fa0
; LA64-CONTRACT-OFF-NEXT:    ret
  %nega = fneg nsz float %a
  %mul = fmul nsz float %nega, %b
  %add = fadd nsz float %mul, %c
  ret float %add
}

;; Check that fnmsub.s is not emitted.
define float @not_fnmsub_s(float %a, float %b, float %c) nounwind {
; LA32-CONTRACT-FAST-LABEL: not_fnmsub_s:
; LA32-CONTRACT-FAST:       # %bb.0:
; LA32-CONTRACT-FAST-NEXT:    fneg.s $fa0, $fa0
; LA32-CONTRACT-FAST-NEXT:    fmadd.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-FAST-NEXT:    ret
;
; LA32-CONTRACT-ON-LABEL: not_fnmsub_s:
; LA32-CONTRACT-ON:       # %bb.0:
; LA32-CONTRACT-ON-NEXT:    fmul.s $fa0, $fa0, $fa1
; LA32-CONTRACT-ON-NEXT:    fsub.s $fa0, $fa2, $fa0
; LA32-CONTRACT-ON-NEXT:    ret
;
; LA32-CONTRACT-OFF-LABEL: not_fnmsub_s:
; LA32-CONTRACT-OFF:       # %bb.0:
; LA32-CONTRACT-OFF-NEXT:    fmul.s $fa0, $fa0, $fa1
; LA32-CONTRACT-OFF-NEXT:    fsub.s $fa0, $fa2, $fa0
; LA32-CONTRACT-OFF-NEXT:    ret
;
; LA64-CONTRACT-FAST-LABEL: not_fnmsub_s:
; LA64-CONTRACT-FAST:       # %bb.0:
; LA64-CONTRACT-FAST-NEXT:    fneg.s $fa0, $fa0
; LA64-CONTRACT-FAST-NEXT:    fmadd.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-FAST-NEXT:    ret
;
; LA64-CONTRACT-ON-LABEL: not_fnmsub_s:
; LA64-CONTRACT-ON:       # %bb.0:
; LA64-CONTRACT-ON-NEXT:    fmul.s $fa0, $fa0, $fa1
; LA64-CONTRACT-ON-NEXT:    fsub.s $fa0, $fa2, $fa0
; LA64-CONTRACT-ON-NEXT:    ret
;
; LA64-CONTRACT-OFF-LABEL: not_fnmsub_s:
; LA64-CONTRACT-OFF:       # %bb.0:
; LA64-CONTRACT-OFF-NEXT:    fmul.s $fa0, $fa0, $fa1
; LA64-CONTRACT-OFF-NEXT:    fsub.s $fa0, $fa2, $fa0
; LA64-CONTRACT-OFF-NEXT:    ret
  %nega = fneg float %a
  %mul = fmul float %nega, %b
  %add = fadd float %mul, %c
  ret float %add
}

define float @contract_fmadd_s(float %a, float %b, float %c) nounwind {
; LA32-CONTRACT-FAST-LABEL: contract_fmadd_s:
; LA32-CONTRACT-FAST:       # %bb.0:
; LA32-CONTRACT-FAST-NEXT:    fmadd.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-FAST-NEXT:    ret
;
; LA32-CONTRACT-ON-LABEL: contract_fmadd_s:
; LA32-CONTRACT-ON:       # %bb.0:
; LA32-CONTRACT-ON-NEXT:    fmadd.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-ON-NEXT:    ret
;
; LA32-CONTRACT-OFF-LABEL: contract_fmadd_s:
; LA32-CONTRACT-OFF:       # %bb.0:
; LA32-CONTRACT-OFF-NEXT:    fmadd.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-OFF-NEXT:    ret
;
; LA64-CONTRACT-FAST-LABEL: contract_fmadd_s:
; LA64-CONTRACT-FAST:       # %bb.0:
; LA64-CONTRACT-FAST-NEXT:    fmadd.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-FAST-NEXT:    ret
;
; LA64-CONTRACT-ON-LABEL: contract_fmadd_s:
; LA64-CONTRACT-ON:       # %bb.0:
; LA64-CONTRACT-ON-NEXT:    fmadd.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-ON-NEXT:    ret
;
; LA64-CONTRACT-OFF-LABEL: contract_fmadd_s:
; LA64-CONTRACT-OFF:       # %bb.0:
; LA64-CONTRACT-OFF-NEXT:    fmadd.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-OFF-NEXT:    ret
  %mul = fmul contract float %a, %b
  %add = fadd contract float %mul, %c
  ret float %add
}

define float @contract_fmsub_s(float %a, float %b, float %c) nounwind {
; LA32-CONTRACT-FAST-LABEL: contract_fmsub_s:
; LA32-CONTRACT-FAST:       # %bb.0:
; LA32-CONTRACT-FAST-NEXT:    fmsub.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-FAST-NEXT:    ret
;
; LA32-CONTRACT-ON-LABEL: contract_fmsub_s:
; LA32-CONTRACT-ON:       # %bb.0:
; LA32-CONTRACT-ON-NEXT:    fmsub.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-ON-NEXT:    ret
;
; LA32-CONTRACT-OFF-LABEL: contract_fmsub_s:
; LA32-CONTRACT-OFF:       # %bb.0:
; LA32-CONTRACT-OFF-NEXT:    fmsub.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-OFF-NEXT:    ret
;
; LA64-CONTRACT-FAST-LABEL: contract_fmsub_s:
; LA64-CONTRACT-FAST:       # %bb.0:
; LA64-CONTRACT-FAST-NEXT:    fmsub.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-FAST-NEXT:    ret
;
; LA64-CONTRACT-ON-LABEL: contract_fmsub_s:
; LA64-CONTRACT-ON:       # %bb.0:
; LA64-CONTRACT-ON-NEXT:    fmsub.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-ON-NEXT:    ret
;
; LA64-CONTRACT-OFF-LABEL: contract_fmsub_s:
; LA64-CONTRACT-OFF:       # %bb.0:
; LA64-CONTRACT-OFF-NEXT:    fmsub.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-OFF-NEXT:    ret
  %mul = fmul contract float %a, %b
  %sub = fsub contract float %mul, %c
  ret float %sub
}

define float @contract_fnmadd_s(float %a, float %b, float %c) nounwind {
; LA32-CONTRACT-FAST-LABEL: contract_fnmadd_s:
; LA32-CONTRACT-FAST:       # %bb.0:
; LA32-CONTRACT-FAST-NEXT:    fnmadd.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-FAST-NEXT:    ret
;
; LA32-CONTRACT-ON-LABEL: contract_fnmadd_s:
; LA32-CONTRACT-ON:       # %bb.0:
; LA32-CONTRACT-ON-NEXT:    fnmadd.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-ON-NEXT:    ret
;
; LA32-CONTRACT-OFF-LABEL: contract_fnmadd_s:
; LA32-CONTRACT-OFF:       # %bb.0:
; LA32-CONTRACT-OFF-NEXT:    fnmadd.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-OFF-NEXT:    ret
;
; LA64-CONTRACT-FAST-LABEL: contract_fnmadd_s:
; LA64-CONTRACT-FAST:       # %bb.0:
; LA64-CONTRACT-FAST-NEXT:    fnmadd.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-FAST-NEXT:    ret
;
; LA64-CONTRACT-ON-LABEL: contract_fnmadd_s:
; LA64-CONTRACT-ON:       # %bb.0:
; LA64-CONTRACT-ON-NEXT:    fnmadd.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-ON-NEXT:    ret
;
; LA64-CONTRACT-OFF-LABEL: contract_fnmadd_s:
; LA64-CONTRACT-OFF:       # %bb.0:
; LA64-CONTRACT-OFF-NEXT:    fnmadd.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-OFF-NEXT:    ret
  %mul = fmul contract float %a, %b
  %add = fadd contract float %mul, %c
  %negadd = fneg contract float %add
  ret float %negadd
}

define float @contract_fnmadd_s_nsz(float %a, float %b, float %c) nounwind {
; LA32-CONTRACT-FAST-LABEL: contract_fnmadd_s_nsz:
; LA32-CONTRACT-FAST:       # %bb.0:
; LA32-CONTRACT-FAST-NEXT:    fnmadd.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-FAST-NEXT:    ret
;
; LA32-CONTRACT-ON-LABEL: contract_fnmadd_s_nsz:
; LA32-CONTRACT-ON:       # %bb.0:
; LA32-CONTRACT-ON-NEXT:    fnmadd.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-ON-NEXT:    ret
;
; LA32-CONTRACT-OFF-LABEL: contract_fnmadd_s_nsz:
; LA32-CONTRACT-OFF:       # %bb.0:
; LA32-CONTRACT-OFF-NEXT:    fnmadd.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-OFF-NEXT:    ret
;
; LA64-CONTRACT-FAST-LABEL: contract_fnmadd_s_nsz:
; LA64-CONTRACT-FAST:       # %bb.0:
; LA64-CONTRACT-FAST-NEXT:    fnmadd.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-FAST-NEXT:    ret
;
; LA64-CONTRACT-ON-LABEL: contract_fnmadd_s_nsz:
; LA64-CONTRACT-ON:       # %bb.0:
; LA64-CONTRACT-ON-NEXT:    fnmadd.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-ON-NEXT:    ret
;
; LA64-CONTRACT-OFF-LABEL: contract_fnmadd_s_nsz:
; LA64-CONTRACT-OFF:       # %bb.0:
; LA64-CONTRACT-OFF-NEXT:    fnmadd.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-OFF-NEXT:    ret
  %nega = fneg contract nsz float %a
  %negc = fneg contract nsz float %c
  %mul = fmul contract nsz float %nega, %b
  %add = fadd contract nsz float %mul, %negc
  ret float %add
}

;; Check that fnmadd.s is not emitted.
define float @not_contract_fnmadd_s(float %a, float %b, float %c) nounwind {
; LA32-CONTRACT-FAST-LABEL: not_contract_fnmadd_s:
; LA32-CONTRACT-FAST:       # %bb.0:
; LA32-CONTRACT-FAST-NEXT:    fneg.s $fa0, $fa0
; LA32-CONTRACT-FAST-NEXT:    fmsub.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-FAST-NEXT:    ret
;
; LA32-CONTRACT-ON-LABEL: not_contract_fnmadd_s:
; LA32-CONTRACT-ON:       # %bb.0:
; LA32-CONTRACT-ON-NEXT:    fneg.s $fa0, $fa0
; LA32-CONTRACT-ON-NEXT:    fmsub.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-ON-NEXT:    ret
;
; LA32-CONTRACT-OFF-LABEL: not_contract_fnmadd_s:
; LA32-CONTRACT-OFF:       # %bb.0:
; LA32-CONTRACT-OFF-NEXT:    fneg.s $fa0, $fa0
; LA32-CONTRACT-OFF-NEXT:    fmsub.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-OFF-NEXT:    ret
;
; LA64-CONTRACT-FAST-LABEL: not_contract_fnmadd_s:
; LA64-CONTRACT-FAST:       # %bb.0:
; LA64-CONTRACT-FAST-NEXT:    fneg.s $fa0, $fa0
; LA64-CONTRACT-FAST-NEXT:    fmsub.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-FAST-NEXT:    ret
;
; LA64-CONTRACT-ON-LABEL: not_contract_fnmadd_s:
; LA64-CONTRACT-ON:       # %bb.0:
; LA64-CONTRACT-ON-NEXT:    fneg.s $fa0, $fa0
; LA64-CONTRACT-ON-NEXT:    fmsub.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-ON-NEXT:    ret
;
; LA64-CONTRACT-OFF-LABEL: not_contract_fnmadd_s:
; LA64-CONTRACT-OFF:       # %bb.0:
; LA64-CONTRACT-OFF-NEXT:    fneg.s $fa0, $fa0
; LA64-CONTRACT-OFF-NEXT:    fmsub.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-OFF-NEXT:    ret
  %nega = fneg contract float %a
  %negc = fneg contract float %c
  %mul = fmul contract float %nega, %b
  %add = fadd contract float %mul, %negc
  ret float %add
}

define float @contract_fnmsub_s(float %a, float %b, float %c) nounwind {
; LA32-CONTRACT-FAST-LABEL: contract_fnmsub_s:
; LA32-CONTRACT-FAST:       # %bb.0:
; LA32-CONTRACT-FAST-NEXT:    fnmsub.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-FAST-NEXT:    ret
;
; LA32-CONTRACT-ON-LABEL: contract_fnmsub_s:
; LA32-CONTRACT-ON:       # %bb.0:
; LA32-CONTRACT-ON-NEXT:    fnmsub.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-ON-NEXT:    ret
;
; LA32-CONTRACT-OFF-LABEL: contract_fnmsub_s:
; LA32-CONTRACT-OFF:       # %bb.0:
; LA32-CONTRACT-OFF-NEXT:    fnmsub.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-OFF-NEXT:    ret
;
; LA64-CONTRACT-FAST-LABEL: contract_fnmsub_s:
; LA64-CONTRACT-FAST:       # %bb.0:
; LA64-CONTRACT-FAST-NEXT:    fnmsub.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-FAST-NEXT:    ret
;
; LA64-CONTRACT-ON-LABEL: contract_fnmsub_s:
; LA64-CONTRACT-ON:       # %bb.0:
; LA64-CONTRACT-ON-NEXT:    fnmsub.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-ON-NEXT:    ret
;
; LA64-CONTRACT-OFF-LABEL: contract_fnmsub_s:
; LA64-CONTRACT-OFF:       # %bb.0:
; LA64-CONTRACT-OFF-NEXT:    fnmsub.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-OFF-NEXT:    ret
  %negc = fneg contract float %c
  %mul = fmul contract float %a, %b
  %add = fadd contract float %mul, %negc
  %neg = fneg contract float %add
  ret float %neg
}

define float @contract_fnmsub_s_nsz(float %a, float %b, float %c) nounwind {
; LA32-CONTRACT-FAST-LABEL: contract_fnmsub_s_nsz:
; LA32-CONTRACT-FAST:       # %bb.0:
; LA32-CONTRACT-FAST-NEXT:    fnmsub.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-FAST-NEXT:    ret
;
; LA32-CONTRACT-ON-LABEL: contract_fnmsub_s_nsz:
; LA32-CONTRACT-ON:       # %bb.0:
; LA32-CONTRACT-ON-NEXT:    fnmsub.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-ON-NEXT:    ret
;
; LA32-CONTRACT-OFF-LABEL: contract_fnmsub_s_nsz:
; LA32-CONTRACT-OFF:       # %bb.0:
; LA32-CONTRACT-OFF-NEXT:    fnmsub.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-OFF-NEXT:    ret
;
; LA64-CONTRACT-FAST-LABEL: contract_fnmsub_s_nsz:
; LA64-CONTRACT-FAST:       # %bb.0:
; LA64-CONTRACT-FAST-NEXT:    fnmsub.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-FAST-NEXT:    ret
;
; LA64-CONTRACT-ON-LABEL: contract_fnmsub_s_nsz:
; LA64-CONTRACT-ON:       # %bb.0:
; LA64-CONTRACT-ON-NEXT:    fnmsub.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-ON-NEXT:    ret
;
; LA64-CONTRACT-OFF-LABEL: contract_fnmsub_s_nsz:
; LA64-CONTRACT-OFF:       # %bb.0:
; LA64-CONTRACT-OFF-NEXT:    fnmsub.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-OFF-NEXT:    ret
  %nega = fneg contract nsz float %a
  %mul = fmul contract nsz float %nega, %b
  %add = fadd contract nsz float %mul, %c
  ret float %add
}

;; Check that fnmsub.s is not emitted.
define float @not_contract_fnmsub_s(float %a, float %b, float %c) nounwind {
; LA32-CONTRACT-FAST-LABEL: not_contract_fnmsub_s:
; LA32-CONTRACT-FAST:       # %bb.0:
; LA32-CONTRACT-FAST-NEXT:    fneg.s $fa0, $fa0
; LA32-CONTRACT-FAST-NEXT:    fmadd.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-FAST-NEXT:    ret
;
; LA32-CONTRACT-ON-LABEL: not_contract_fnmsub_s:
; LA32-CONTRACT-ON:       # %bb.0:
; LA32-CONTRACT-ON-NEXT:    fneg.s $fa0, $fa0
; LA32-CONTRACT-ON-NEXT:    fmadd.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-ON-NEXT:    ret
;
; LA32-CONTRACT-OFF-LABEL: not_contract_fnmsub_s:
; LA32-CONTRACT-OFF:       # %bb.0:
; LA32-CONTRACT-OFF-NEXT:    fneg.s $fa0, $fa0
; LA32-CONTRACT-OFF-NEXT:    fmadd.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-OFF-NEXT:    ret
;
; LA64-CONTRACT-FAST-LABEL: not_contract_fnmsub_s:
; LA64-CONTRACT-FAST:       # %bb.0:
; LA64-CONTRACT-FAST-NEXT:    fneg.s $fa0, $fa0
; LA64-CONTRACT-FAST-NEXT:    fmadd.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-FAST-NEXT:    ret
;
; LA64-CONTRACT-ON-LABEL: not_contract_fnmsub_s:
; LA64-CONTRACT-ON:       # %bb.0:
; LA64-CONTRACT-ON-NEXT:    fneg.s $fa0, $fa0
; LA64-CONTRACT-ON-NEXT:    fmadd.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-ON-NEXT:    ret
;
; LA64-CONTRACT-OFF-LABEL: not_contract_fnmsub_s:
; LA64-CONTRACT-OFF:       # %bb.0:
; LA64-CONTRACT-OFF-NEXT:    fneg.s $fa0, $fa0
; LA64-CONTRACT-OFF-NEXT:    fmadd.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-OFF-NEXT:    ret
  %nega = fneg contract float %a
  %mul = fmul contract float %nega, %b
  %add = fadd contract float %mul, %c
  ret float %add
}

declare float @llvm.fma.f64(float, float, float)

define float @fmadd_s_intrinsics(float %a, float %b, float %c) nounwind {
; LA32-CONTRACT-FAST-LABEL: fmadd_s_intrinsics:
; LA32-CONTRACT-FAST:       # %bb.0:
; LA32-CONTRACT-FAST-NEXT:    fmadd.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-FAST-NEXT:    ret
;
; LA32-CONTRACT-ON-LABEL: fmadd_s_intrinsics:
; LA32-CONTRACT-ON:       # %bb.0:
; LA32-CONTRACT-ON-NEXT:    fmadd.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-ON-NEXT:    ret
;
; LA32-CONTRACT-OFF-LABEL: fmadd_s_intrinsics:
; LA32-CONTRACT-OFF:       # %bb.0:
; LA32-CONTRACT-OFF-NEXT:    fmadd.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-OFF-NEXT:    ret
;
; LA64-CONTRACT-FAST-LABEL: fmadd_s_intrinsics:
; LA64-CONTRACT-FAST:       # %bb.0:
; LA64-CONTRACT-FAST-NEXT:    fmadd.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-FAST-NEXT:    ret
;
; LA64-CONTRACT-ON-LABEL: fmadd_s_intrinsics:
; LA64-CONTRACT-ON:       # %bb.0:
; LA64-CONTRACT-ON-NEXT:    fmadd.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-ON-NEXT:    ret
;
; LA64-CONTRACT-OFF-LABEL: fmadd_s_intrinsics:
; LA64-CONTRACT-OFF:       # %bb.0:
; LA64-CONTRACT-OFF-NEXT:    fmadd.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-OFF-NEXT:    ret
  %fma = call float @llvm.fma.f64(float %a, float %b, float %c)
  ret float %fma
}

define float @fmsub_s_intrinsics(float %a, float %b, float %c) nounwind {
; LA32-CONTRACT-FAST-LABEL: fmsub_s_intrinsics:
; LA32-CONTRACT-FAST:       # %bb.0:
; LA32-CONTRACT-FAST-NEXT:    fmsub.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-FAST-NEXT:    ret
;
; LA32-CONTRACT-ON-LABEL: fmsub_s_intrinsics:
; LA32-CONTRACT-ON:       # %bb.0:
; LA32-CONTRACT-ON-NEXT:    fmsub.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-ON-NEXT:    ret
;
; LA32-CONTRACT-OFF-LABEL: fmsub_s_intrinsics:
; LA32-CONTRACT-OFF:       # %bb.0:
; LA32-CONTRACT-OFF-NEXT:    fmsub.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-OFF-NEXT:    ret
;
; LA64-CONTRACT-FAST-LABEL: fmsub_s_intrinsics:
; LA64-CONTRACT-FAST:       # %bb.0:
; LA64-CONTRACT-FAST-NEXT:    fmsub.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-FAST-NEXT:    ret
;
; LA64-CONTRACT-ON-LABEL: fmsub_s_intrinsics:
; LA64-CONTRACT-ON:       # %bb.0:
; LA64-CONTRACT-ON-NEXT:    fmsub.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-ON-NEXT:    ret
;
; LA64-CONTRACT-OFF-LABEL: fmsub_s_intrinsics:
; LA64-CONTRACT-OFF:       # %bb.0:
; LA64-CONTRACT-OFF-NEXT:    fmsub.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-OFF-NEXT:    ret
  %negc = fneg float %c
  %fma = call float @llvm.fma.f64(float %a, float %b, float %negc)
  ret float %fma
}

define float @fnmadd_s_intrinsics(float %a, float %b, float %c) nounwind {
; LA32-CONTRACT-FAST-LABEL: fnmadd_s_intrinsics:
; LA32-CONTRACT-FAST:       # %bb.0:
; LA32-CONTRACT-FAST-NEXT:    fnmadd.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-FAST-NEXT:    ret
;
; LA32-CONTRACT-ON-LABEL: fnmadd_s_intrinsics:
; LA32-CONTRACT-ON:       # %bb.0:
; LA32-CONTRACT-ON-NEXT:    fnmadd.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-ON-NEXT:    ret
;
; LA32-CONTRACT-OFF-LABEL: fnmadd_s_intrinsics:
; LA32-CONTRACT-OFF:       # %bb.0:
; LA32-CONTRACT-OFF-NEXT:    fnmadd.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-OFF-NEXT:    ret
;
; LA64-CONTRACT-FAST-LABEL: fnmadd_s_intrinsics:
; LA64-CONTRACT-FAST:       # %bb.0:
; LA64-CONTRACT-FAST-NEXT:    fnmadd.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-FAST-NEXT:    ret
;
; LA64-CONTRACT-ON-LABEL: fnmadd_s_intrinsics:
; LA64-CONTRACT-ON:       # %bb.0:
; LA64-CONTRACT-ON-NEXT:    fnmadd.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-ON-NEXT:    ret
;
; LA64-CONTRACT-OFF-LABEL: fnmadd_s_intrinsics:
; LA64-CONTRACT-OFF:       # %bb.0:
; LA64-CONTRACT-OFF-NEXT:    fnmadd.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-OFF-NEXT:    ret
  %fma = call float @llvm.fma.f64(float %a, float %b, float %c)
  %negfma = fneg float %fma
  ret float %negfma
}

define float @fnmadd_s_nsz_intrinsics(float %a, float %b, float %c) nounwind {
; LA32-CONTRACT-FAST-LABEL: fnmadd_s_nsz_intrinsics:
; LA32-CONTRACT-FAST:       # %bb.0:
; LA32-CONTRACT-FAST-NEXT:    fnmadd.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-FAST-NEXT:    ret
;
; LA32-CONTRACT-ON-LABEL: fnmadd_s_nsz_intrinsics:
; LA32-CONTRACT-ON:       # %bb.0:
; LA32-CONTRACT-ON-NEXT:    fnmadd.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-ON-NEXT:    ret
;
; LA32-CONTRACT-OFF-LABEL: fnmadd_s_nsz_intrinsics:
; LA32-CONTRACT-OFF:       # %bb.0:
; LA32-CONTRACT-OFF-NEXT:    fnmadd.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-OFF-NEXT:    ret
;
; LA64-CONTRACT-FAST-LABEL: fnmadd_s_nsz_intrinsics:
; LA64-CONTRACT-FAST:       # %bb.0:
; LA64-CONTRACT-FAST-NEXT:    fnmadd.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-FAST-NEXT:    ret
;
; LA64-CONTRACT-ON-LABEL: fnmadd_s_nsz_intrinsics:
; LA64-CONTRACT-ON:       # %bb.0:
; LA64-CONTRACT-ON-NEXT:    fnmadd.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-ON-NEXT:    ret
;
; LA64-CONTRACT-OFF-LABEL: fnmadd_s_nsz_intrinsics:
; LA64-CONTRACT-OFF:       # %bb.0:
; LA64-CONTRACT-OFF-NEXT:    fnmadd.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-OFF-NEXT:    ret
  %nega = fneg float %a
  %negc = fneg float %c
  %fma = call nsz float @llvm.fma.f64(float %nega, float %b, float %negc)
  ret float %fma
}

;; Check that fnmadd.s is not emitted.
define float @not_fnmadd_s_intrinsics(float %a, float %b, float %c) nounwind {
; LA32-CONTRACT-FAST-LABEL: not_fnmadd_s_intrinsics:
; LA32-CONTRACT-FAST:       # %bb.0:
; LA32-CONTRACT-FAST-NEXT:    fneg.s $fa0, $fa0
; LA32-CONTRACT-FAST-NEXT:    fmsub.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-FAST-NEXT:    ret
;
; LA32-CONTRACT-ON-LABEL: not_fnmadd_s_intrinsics:
; LA32-CONTRACT-ON:       # %bb.0:
; LA32-CONTRACT-ON-NEXT:    fneg.s $fa0, $fa0
; LA32-CONTRACT-ON-NEXT:    fmsub.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-ON-NEXT:    ret
;
; LA32-CONTRACT-OFF-LABEL: not_fnmadd_s_intrinsics:
; LA32-CONTRACT-OFF:       # %bb.0:
; LA32-CONTRACT-OFF-NEXT:    fneg.s $fa0, $fa0
; LA32-CONTRACT-OFF-NEXT:    fmsub.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-OFF-NEXT:    ret
;
; LA64-CONTRACT-FAST-LABEL: not_fnmadd_s_intrinsics:
; LA64-CONTRACT-FAST:       # %bb.0:
; LA64-CONTRACT-FAST-NEXT:    fneg.s $fa0, $fa0
; LA64-CONTRACT-FAST-NEXT:    fmsub.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-FAST-NEXT:    ret
;
; LA64-CONTRACT-ON-LABEL: not_fnmadd_s_intrinsics:
; LA64-CONTRACT-ON:       # %bb.0:
; LA64-CONTRACT-ON-NEXT:    fneg.s $fa0, $fa0
; LA64-CONTRACT-ON-NEXT:    fmsub.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-ON-NEXT:    ret
;
; LA64-CONTRACT-OFF-LABEL: not_fnmadd_s_intrinsics:
; LA64-CONTRACT-OFF:       # %bb.0:
; LA64-CONTRACT-OFF-NEXT:    fneg.s $fa0, $fa0
; LA64-CONTRACT-OFF-NEXT:    fmsub.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-OFF-NEXT:    ret
  %nega = fneg float %a
  %negc = fneg float %c
  %fma = call float @llvm.fma.f64(float %nega, float %b, float %negc)
  ret float %fma
}

define float @fnmsub_s_intrinsics(float %a, float %b, float %c) nounwind {
; LA32-CONTRACT-FAST-LABEL: fnmsub_s_intrinsics:
; LA32-CONTRACT-FAST:       # %bb.0:
; LA32-CONTRACT-FAST-NEXT:    fnmsub.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-FAST-NEXT:    ret
;
; LA32-CONTRACT-ON-LABEL: fnmsub_s_intrinsics:
; LA32-CONTRACT-ON:       # %bb.0:
; LA32-CONTRACT-ON-NEXT:    fnmsub.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-ON-NEXT:    ret
;
; LA32-CONTRACT-OFF-LABEL: fnmsub_s_intrinsics:
; LA32-CONTRACT-OFF:       # %bb.0:
; LA32-CONTRACT-OFF-NEXT:    fnmsub.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-OFF-NEXT:    ret
;
; LA64-CONTRACT-FAST-LABEL: fnmsub_s_intrinsics:
; LA64-CONTRACT-FAST:       # %bb.0:
; LA64-CONTRACT-FAST-NEXT:    fnmsub.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-FAST-NEXT:    ret
;
; LA64-CONTRACT-ON-LABEL: fnmsub_s_intrinsics:
; LA64-CONTRACT-ON:       # %bb.0:
; LA64-CONTRACT-ON-NEXT:    fnmsub.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-ON-NEXT:    ret
;
; LA64-CONTRACT-OFF-LABEL: fnmsub_s_intrinsics:
; LA64-CONTRACT-OFF:       # %bb.0:
; LA64-CONTRACT-OFF-NEXT:    fnmsub.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-OFF-NEXT:    ret
  %negc = fneg float %c
  %fma = call float @llvm.fma.f64(float %a, float %b, float %negc)
  %negfma = fneg float %fma
  ret float %negfma
}

define float @fnmsub_s_nsz_intrinsics(float %a, float %b, float %c) nounwind {
; LA32-CONTRACT-FAST-LABEL: fnmsub_s_nsz_intrinsics:
; LA32-CONTRACT-FAST:       # %bb.0:
; LA32-CONTRACT-FAST-NEXT:    fnmsub.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-FAST-NEXT:    ret
;
; LA32-CONTRACT-ON-LABEL: fnmsub_s_nsz_intrinsics:
; LA32-CONTRACT-ON:       # %bb.0:
; LA32-CONTRACT-ON-NEXT:    fnmsub.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-ON-NEXT:    ret
;
; LA32-CONTRACT-OFF-LABEL: fnmsub_s_nsz_intrinsics:
; LA32-CONTRACT-OFF:       # %bb.0:
; LA32-CONTRACT-OFF-NEXT:    fnmsub.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-OFF-NEXT:    ret
;
; LA64-CONTRACT-FAST-LABEL: fnmsub_s_nsz_intrinsics:
; LA64-CONTRACT-FAST:       # %bb.0:
; LA64-CONTRACT-FAST-NEXT:    fnmsub.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-FAST-NEXT:    ret
;
; LA64-CONTRACT-ON-LABEL: fnmsub_s_nsz_intrinsics:
; LA64-CONTRACT-ON:       # %bb.0:
; LA64-CONTRACT-ON-NEXT:    fnmsub.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-ON-NEXT:    ret
;
; LA64-CONTRACT-OFF-LABEL: fnmsub_s_nsz_intrinsics:
; LA64-CONTRACT-OFF:       # %bb.0:
; LA64-CONTRACT-OFF-NEXT:    fnmsub.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-OFF-NEXT:    ret
  %nega = fneg float %a
  %fma = call nsz float @llvm.fma.f64(float %nega, float %b, float %c)
  ret float %fma
}

;; Check that fnmsub.s is not emitted.
define float @not_fnmsub_s_intrinsics(float %a, float %b, float %c) nounwind {
; LA32-CONTRACT-FAST-LABEL: not_fnmsub_s_intrinsics:
; LA32-CONTRACT-FAST:       # %bb.0:
; LA32-CONTRACT-FAST-NEXT:    fneg.s $fa0, $fa0
; LA32-CONTRACT-FAST-NEXT:    fmadd.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-FAST-NEXT:    ret
;
; LA32-CONTRACT-ON-LABEL: not_fnmsub_s_intrinsics:
; LA32-CONTRACT-ON:       # %bb.0:
; LA32-CONTRACT-ON-NEXT:    fneg.s $fa0, $fa0
; LA32-CONTRACT-ON-NEXT:    fmadd.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-ON-NEXT:    ret
;
; LA32-CONTRACT-OFF-LABEL: not_fnmsub_s_intrinsics:
; LA32-CONTRACT-OFF:       # %bb.0:
; LA32-CONTRACT-OFF-NEXT:    fneg.s $fa0, $fa0
; LA32-CONTRACT-OFF-NEXT:    fmadd.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-OFF-NEXT:    ret
;
; LA64-CONTRACT-FAST-LABEL: not_fnmsub_s_intrinsics:
; LA64-CONTRACT-FAST:       # %bb.0:
; LA64-CONTRACT-FAST-NEXT:    fneg.s $fa0, $fa0
; LA64-CONTRACT-FAST-NEXT:    fmadd.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-FAST-NEXT:    ret
;
; LA64-CONTRACT-ON-LABEL: not_fnmsub_s_intrinsics:
; LA64-CONTRACT-ON:       # %bb.0:
; LA64-CONTRACT-ON-NEXT:    fneg.s $fa0, $fa0
; LA64-CONTRACT-ON-NEXT:    fmadd.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-ON-NEXT:    ret
;
; LA64-CONTRACT-OFF-LABEL: not_fnmsub_s_intrinsics:
; LA64-CONTRACT-OFF:       # %bb.0:
; LA64-CONTRACT-OFF-NEXT:    fneg.s $fa0, $fa0
; LA64-CONTRACT-OFF-NEXT:    fmadd.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-OFF-NEXT:    ret
  %nega = fneg float %a
  %fma = call float @llvm.fma.f64(float %nega, float %b, float %c)
  ret float %fma
}

define float @fmadd_s_contract(float %a, float %b, float %c) nounwind {
; LA32-CONTRACT-FAST-LABEL: fmadd_s_contract:
; LA32-CONTRACT-FAST:       # %bb.0:
; LA32-CONTRACT-FAST-NEXT:    fmadd.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-FAST-NEXT:    ret
;
; LA32-CONTRACT-ON-LABEL: fmadd_s_contract:
; LA32-CONTRACT-ON:       # %bb.0:
; LA32-CONTRACT-ON-NEXT:    fmadd.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-ON-NEXT:    ret
;
; LA32-CONTRACT-OFF-LABEL: fmadd_s_contract:
; LA32-CONTRACT-OFF:       # %bb.0:
; LA32-CONTRACT-OFF-NEXT:    fmadd.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-OFF-NEXT:    ret
;
; LA64-CONTRACT-FAST-LABEL: fmadd_s_contract:
; LA64-CONTRACT-FAST:       # %bb.0:
; LA64-CONTRACT-FAST-NEXT:    fmadd.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-FAST-NEXT:    ret
;
; LA64-CONTRACT-ON-LABEL: fmadd_s_contract:
; LA64-CONTRACT-ON:       # %bb.0:
; LA64-CONTRACT-ON-NEXT:    fmadd.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-ON-NEXT:    ret
;
; LA64-CONTRACT-OFF-LABEL: fmadd_s_contract:
; LA64-CONTRACT-OFF:       # %bb.0:
; LA64-CONTRACT-OFF-NEXT:    fmadd.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-OFF-NEXT:    ret
  %mul = fmul contract float %a, %b
  %add = fadd contract float %mul, %c
  ret float %add
}

define float @fmsub_s_contract(float %a, float %b, float %c) nounwind {
; LA32-CONTRACT-FAST-LABEL: fmsub_s_contract:
; LA32-CONTRACT-FAST:       # %bb.0:
; LA32-CONTRACT-FAST-NEXT:    fmsub.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-FAST-NEXT:    ret
;
; LA32-CONTRACT-ON-LABEL: fmsub_s_contract:
; LA32-CONTRACT-ON:       # %bb.0:
; LA32-CONTRACT-ON-NEXT:    fmsub.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-ON-NEXT:    ret
;
; LA32-CONTRACT-OFF-LABEL: fmsub_s_contract:
; LA32-CONTRACT-OFF:       # %bb.0:
; LA32-CONTRACT-OFF-NEXT:    fmsub.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-OFF-NEXT:    ret
;
; LA64-CONTRACT-FAST-LABEL: fmsub_s_contract:
; LA64-CONTRACT-FAST:       # %bb.0:
; LA64-CONTRACT-FAST-NEXT:    fmsub.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-FAST-NEXT:    ret
;
; LA64-CONTRACT-ON-LABEL: fmsub_s_contract:
; LA64-CONTRACT-ON:       # %bb.0:
; LA64-CONTRACT-ON-NEXT:    fmsub.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-ON-NEXT:    ret
;
; LA64-CONTRACT-OFF-LABEL: fmsub_s_contract:
; LA64-CONTRACT-OFF:       # %bb.0:
; LA64-CONTRACT-OFF-NEXT:    fmsub.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-OFF-NEXT:    ret
  %mul = fmul contract float %a, %b
  %sub = fsub contract float %mul, %c
  ret float %sub
}

define float @fnmadd_s_contract(float %a, float %b, float %c) nounwind {
; LA32-CONTRACT-FAST-LABEL: fnmadd_s_contract:
; LA32-CONTRACT-FAST:       # %bb.0:
; LA32-CONTRACT-FAST-NEXT:    fnmadd.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-FAST-NEXT:    ret
;
; LA32-CONTRACT-ON-LABEL: fnmadd_s_contract:
; LA32-CONTRACT-ON:       # %bb.0:
; LA32-CONTRACT-ON-NEXT:    fnmadd.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-ON-NEXT:    ret
;
; LA32-CONTRACT-OFF-LABEL: fnmadd_s_contract:
; LA32-CONTRACT-OFF:       # %bb.0:
; LA32-CONTRACT-OFF-NEXT:    fnmadd.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-OFF-NEXT:    ret
;
; LA64-CONTRACT-FAST-LABEL: fnmadd_s_contract:
; LA64-CONTRACT-FAST:       # %bb.0:
; LA64-CONTRACT-FAST-NEXT:    fnmadd.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-FAST-NEXT:    ret
;
; LA64-CONTRACT-ON-LABEL: fnmadd_s_contract:
; LA64-CONTRACT-ON:       # %bb.0:
; LA64-CONTRACT-ON-NEXT:    fnmadd.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-ON-NEXT:    ret
;
; LA64-CONTRACT-OFF-LABEL: fnmadd_s_contract:
; LA64-CONTRACT-OFF:       # %bb.0:
; LA64-CONTRACT-OFF-NEXT:    fnmadd.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-OFF-NEXT:    ret
  %mul = fmul contract float %a, %b
  %add = fadd contract float %mul, %c
  %negadd = fneg contract float %add
  ret float %negadd
}

define float @fnmsub_s_contract(float %a, float %b, float %c) nounwind {
; LA32-CONTRACT-FAST-LABEL: fnmsub_s_contract:
; LA32-CONTRACT-FAST:       # %bb.0:
; LA32-CONTRACT-FAST-NEXT:    fnmsub.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-FAST-NEXT:    ret
;
; LA32-CONTRACT-ON-LABEL: fnmsub_s_contract:
; LA32-CONTRACT-ON:       # %bb.0:
; LA32-CONTRACT-ON-NEXT:    fnmsub.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-ON-NEXT:    ret
;
; LA32-CONTRACT-OFF-LABEL: fnmsub_s_contract:
; LA32-CONTRACT-OFF:       # %bb.0:
; LA32-CONTRACT-OFF-NEXT:    fnmsub.s $fa0, $fa0, $fa1, $fa2
; LA32-CONTRACT-OFF-NEXT:    ret
;
; LA64-CONTRACT-FAST-LABEL: fnmsub_s_contract:
; LA64-CONTRACT-FAST:       # %bb.0:
; LA64-CONTRACT-FAST-NEXT:    fnmsub.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-FAST-NEXT:    ret
;
; LA64-CONTRACT-ON-LABEL: fnmsub_s_contract:
; LA64-CONTRACT-ON:       # %bb.0:
; LA64-CONTRACT-ON-NEXT:    fnmsub.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-ON-NEXT:    ret
;
; LA64-CONTRACT-OFF-LABEL: fnmsub_s_contract:
; LA64-CONTRACT-OFF:       # %bb.0:
; LA64-CONTRACT-OFF-NEXT:    fnmsub.s $fa0, $fa0, $fa1, $fa2
; LA64-CONTRACT-OFF-NEXT:    ret
  %mul = fmul contract float %a, %b
  %negc = fneg contract float %c
  %add = fadd contract float %negc, %mul
  %negadd = fneg contract float %add
  ret float %negadd
}