; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
; RUN: llc -mtriple=sparc64 --fp-contract=fast -mattr=-ua2007 < %s | FileCheck %s -check-prefix=NO-UA2007
; RUN: llc -mtriple=sparc64 --fp-contract=fast -mattr=+ua2007 < %s | FileCheck %s -check-prefix=UA2007

define float @fmadds(float %a, float %b, float %c) nounwind {
; NO-UA2007-LABEL: fmadds:
; NO-UA2007:       ! %bb.0:
; NO-UA2007-NEXT:    fmuls %f1, %f3, %f0
; NO-UA2007-NEXT:    retl
; NO-UA2007-NEXT:    fadds %f0, %f5, %f0
;
; UA2007-LABEL: fmadds:
; UA2007:       ! %bb.0:
; UA2007-NEXT:    retl
; UA2007-NEXT:    fmadds %f1, %f3, %f5, %f0
  %ret = call float @llvm.fmuladd.f32(float %a, float %b, float %c)
  ret float %ret
}

define double @fmaddd(double %a, double %b, double %c) nounwind {
; NO-UA2007-LABEL: fmaddd:
; NO-UA2007:       ! %bb.0:
; NO-UA2007-NEXT:    fmuld %f0, %f2, %f0
; NO-UA2007-NEXT:    retl
; NO-UA2007-NEXT:    faddd %f0, %f4, %f0
;
; UA2007-LABEL: fmaddd:
; UA2007:       ! %bb.0:
; UA2007-NEXT:    retl
; UA2007-NEXT:    fmaddd %f0, %f2, %f4, %f0
  %ret = call double @llvm.fmuladd.f64(double %a, double %b, double %c)
  ret double %ret
}

define float @fmsubs(float %a, float %b, float %c) nounwind {
; NO-UA2007-LABEL: fmsubs:
; NO-UA2007:       ! %bb.0:
; NO-UA2007-NEXT:    fmuls %f1, %f3, %f0
; NO-UA2007-NEXT:    retl
; NO-UA2007-NEXT:    fsubs %f0, %f5, %f0
;
; UA2007-LABEL: fmsubs:
; UA2007:       ! %bb.0:
; UA2007-NEXT:    retl
; UA2007-NEXT:    fmsubs %f1, %f3, %f5, %f0
  %neg = fneg float %c
  %ret = call float @llvm.fmuladd.f32(float %a, float %b, float %neg)
  ret float %ret
}

define double @fmsubd(double %a, double %b, double %c) nounwind {
; NO-UA2007-LABEL: fmsubd:
; NO-UA2007:       ! %bb.0:
; NO-UA2007-NEXT:    fmuld %f0, %f2, %f0
; NO-UA2007-NEXT:    retl
; NO-UA2007-NEXT:    fsubd %f0, %f4, %f0
;
; UA2007-LABEL: fmsubd:
; UA2007:       ! %bb.0:
; UA2007-NEXT:    retl
; UA2007-NEXT:    fmsubd %f0, %f2, %f4, %f0
  %neg = fneg double %c
  %ret = call double @llvm.fmuladd.f64(double %a, double %b, double %neg)
  ret double %ret
}

define float @fnmadds(float %a, float %b, float %c) nounwind {
; NO-UA2007-LABEL: fnmadds:
; NO-UA2007:       ! %bb.0:
; NO-UA2007-NEXT:    fmuls %f1, %f3, %f0
; NO-UA2007-NEXT:    fadds %f0, %f5, %f0
; NO-UA2007-NEXT:    retl
; NO-UA2007-NEXT:    fnegs %f0, %f0
;
; UA2007-LABEL: fnmadds:
; UA2007:       ! %bb.0:
; UA2007-NEXT:    retl
; UA2007-NEXT:    fnmadds %f1, %f3, %f5, %f0
  %fma = call float @llvm.fmuladd.f32(float %a, float %b, float %c)
  %ret = fneg float %fma
  ret float %ret
}

define double @fnmaddd(double %a, double %b, double %c) nounwind {
; NO-UA2007-LABEL: fnmaddd:
; NO-UA2007:       ! %bb.0:
; NO-UA2007-NEXT:    fmuld %f0, %f2, %f0
; NO-UA2007-NEXT:    faddd %f0, %f4, %f0
; NO-UA2007-NEXT:    retl
; NO-UA2007-NEXT:    fnegd %f0, %f0
;
; UA2007-LABEL: fnmaddd:
; UA2007:       ! %bb.0:
; UA2007-NEXT:    retl
; UA2007-NEXT:    fnmaddd %f0, %f2, %f4, %f0
  %fma = call double @llvm.fmuladd.f64(double %a, double %b, double %c)
  %ret = fneg double %fma
  ret double %ret
}

define float @fnmsubs(float %a, float %b, float %c) nounwind {
; NO-UA2007-LABEL: fnmsubs:
; NO-UA2007:       ! %bb.0:
; NO-UA2007-NEXT:    fmuls %f1, %f3, %f0
; NO-UA2007-NEXT:    fsubs %f0, %f5, %f0
; NO-UA2007-NEXT:    retl
; NO-UA2007-NEXT:    fnegs %f0, %f0
;
; UA2007-LABEL: fnmsubs:
; UA2007:       ! %bb.0:
; UA2007-NEXT:    retl
; UA2007-NEXT:    fnmsubs %f1, %f3, %f5, %f0
  %neg = fneg float %c
  %fma = call float @llvm.fmuladd.f32(float %a, float %b, float %neg)
  %ret = fneg float %fma
  ret float %ret
}

define double @fnmsubd(double %a, double %b, double %c) nounwind {
; NO-UA2007-LABEL: fnmsubd:
; NO-UA2007:       ! %bb.0:
; NO-UA2007-NEXT:    fmuld %f0, %f2, %f0
; NO-UA2007-NEXT:    fsubd %f0, %f4, %f0
; NO-UA2007-NEXT:    retl
; NO-UA2007-NEXT:    fnegd %f0, %f0
;
; UA2007-LABEL: fnmsubd:
; UA2007:       ! %bb.0:
; UA2007-NEXT:    retl
; UA2007-NEXT:    fnmsubd %f0, %f2, %f4, %f0
  %neg = fneg double %c
  %fma = call double @llvm.fmuladd.f64(double %a, double %b, double %neg)
  %ret = fneg double %fma
  ret double %ret
}


define float @combine_madds(float %a, float %b, float %c) nounwind {
; NO-UA2007-LABEL: combine_madds:
; NO-UA2007:       ! %bb.0:
; NO-UA2007-NEXT:    fmuls %f1, %f3, %f0
; NO-UA2007-NEXT:    retl
; NO-UA2007-NEXT:    fadds %f0, %f5, %f0
;
; UA2007-LABEL: combine_madds:
; UA2007:       ! %bb.0:
; UA2007-NEXT:    retl
; UA2007-NEXT:    fmadds %f1, %f3, %f5, %f0
  %mul = fmul float %a, %b
  %add = fadd float %mul, %c
  ret float %add
}

define double @combine_maddd(double %a, double %b, double %c) nounwind {
; NO-UA2007-LABEL: combine_maddd:
; NO-UA2007:       ! %bb.0:
; NO-UA2007-NEXT:    fmuld %f0, %f2, %f0
; NO-UA2007-NEXT:    retl
; NO-UA2007-NEXT:    faddd %f0, %f4, %f0
;
; UA2007-LABEL: combine_maddd:
; UA2007:       ! %bb.0:
; UA2007-NEXT:    retl
; UA2007-NEXT:    fmaddd %f0, %f2, %f4, %f0
  %mul = fmul double %a, %b
  %add = fadd double %mul, %c
  ret double %add
}

define float @combine_msubs(float %a, float %b, float %c) nounwind {
; NO-UA2007-LABEL: combine_msubs:
; NO-UA2007:       ! %bb.0:
; NO-UA2007-NEXT:    fmuls %f1, %f3, %f0
; NO-UA2007-NEXT:    retl
; NO-UA2007-NEXT:    fsubs %f0, %f5, %f0
;
; UA2007-LABEL: combine_msubs:
; UA2007:       ! %bb.0:
; UA2007-NEXT:    retl
; UA2007-NEXT:    fmsubs %f1, %f3, %f5, %f0
  %mul = fmul float %a, %b
  %sub = fsub float %mul, %c
  ret float %sub
}

define double @combine_msubd(double %a, double %b, double %c) nounwind {
; NO-UA2007-LABEL: combine_msubd:
; NO-UA2007:       ! %bb.0:
; NO-UA2007-NEXT:    fmuld %f0, %f2, %f0
; NO-UA2007-NEXT:    retl
; NO-UA2007-NEXT:    fsubd %f0, %f4, %f0
;
; UA2007-LABEL: combine_msubd:
; UA2007:       ! %bb.0:
; UA2007-NEXT:    retl
; UA2007-NEXT:    fmsubd %f0, %f2, %f4, %f0
  %mul = fmul double %a, %b
  %sub = fsub double %mul, %c
  ret double %sub
}

define float @combine_nmadds(float %a, float %b, float %c) nounwind {
; NO-UA2007-LABEL: combine_nmadds:
; NO-UA2007:       ! %bb.0:
; NO-UA2007-NEXT:    fmuls %f1, %f3, %f0
; NO-UA2007-NEXT:    fadds %f0, %f5, %f0
; NO-UA2007-NEXT:    retl
; NO-UA2007-NEXT:    fnegs %f0, %f0
;
; UA2007-LABEL: combine_nmadds:
; UA2007:       ! %bb.0:
; UA2007-NEXT:    retl
; UA2007-NEXT:    fnmadds %f1, %f3, %f5, %f0
  %mul = fmul float %a, %b
  %add = fadd float %mul, %c
  %neg = fneg float %add
  ret float %neg
}

define double @combine_nmaddd(double %a, double %b, double %c) nounwind {
; NO-UA2007-LABEL: combine_nmaddd:
; NO-UA2007:       ! %bb.0:
; NO-UA2007-NEXT:    fmuld %f0, %f2, %f0
; NO-UA2007-NEXT:    faddd %f0, %f4, %f0
; NO-UA2007-NEXT:    retl
; NO-UA2007-NEXT:    fnegd %f0, %f0
;
; UA2007-LABEL: combine_nmaddd:
; UA2007:       ! %bb.0:
; UA2007-NEXT:    retl
; UA2007-NEXT:    fnmaddd %f0, %f2, %f4, %f0
  %mul = fmul double %a, %b
  %add = fadd double %mul, %c
  %neg = fneg double %add
  ret double %neg
}

define float @combine_nmsubs(float %a, float %b, float %c) nounwind {
; NO-UA2007-LABEL: combine_nmsubs:
; NO-UA2007:       ! %bb.0:
; NO-UA2007-NEXT:    fmuls %f1, %f3, %f0
; NO-UA2007-NEXT:    fsubs %f0, %f5, %f0
; NO-UA2007-NEXT:    retl
; NO-UA2007-NEXT:    fnegs %f0, %f0
;
; UA2007-LABEL: combine_nmsubs:
; UA2007:       ! %bb.0:
; UA2007-NEXT:    retl
; UA2007-NEXT:    fnmsubs %f1, %f3, %f5, %f0
  %mul = fmul float %a, %b
  %sub = fsub float %mul, %c
  %neg = fneg float %sub
  ret float %neg
}

define double @combine_nmsubd(double %a, double %b, double %c) nounwind {
; NO-UA2007-LABEL: combine_nmsubd:
; NO-UA2007:       ! %bb.0:
; NO-UA2007-NEXT:    fmuld %f0, %f2, %f0
; NO-UA2007-NEXT:    fsubd %f0, %f4, %f0
; NO-UA2007-NEXT:    retl
; NO-UA2007-NEXT:    fnegd %f0, %f0
;
; UA2007-LABEL: combine_nmsubd:
; UA2007:       ! %bb.0:
; UA2007-NEXT:    retl
; UA2007-NEXT:    fnmsubd %f0, %f2, %f4, %f0
  %mul = fmul double %a, %b
  %sub = fsub double %mul, %c
  %neg = fneg double %sub
  ret double %neg
}

declare float @llvm.fmuladd.f32(float, float, float)
declare double @llvm.fmuladd.f64(double, double, double)
