1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=arm64-eabi < %s | FileCheck %s 3 4define float @fma32(float %a, float %b, float %c) nounwind readnone ssp { 5; CHECK-LABEL: fma32: 6; CHECK: // %bb.0: // %entry 7; CHECK-NEXT: fmadd s0, s0, s1, s2 8; CHECK-NEXT: ret 9entry: 10 %0 = tail call float @llvm.fma.f32(float %a, float %b, float %c) 11 ret float %0 12} 13 14define float @fnma32(float %a, float %b, float %c) nounwind readnone ssp { 15; CHECK-LABEL: fnma32: 16; CHECK: // %bb.0: // %entry 17; CHECK-NEXT: fnmadd s0, s0, s1, s2 18; CHECK-NEXT: ret 19entry: 20 %0 = tail call float @llvm.fma.f32(float %a, float %b, float %c) 21 %mul = fmul float %0, -1.000000e+00 22 ret float %mul 23} 24 25define float @fms32(float %a, float %b, float %c) nounwind readnone ssp { 26; CHECK-LABEL: fms32: 27; CHECK: // %bb.0: // %entry 28; CHECK-NEXT: fmsub s0, s0, s1, s2 29; CHECK-NEXT: ret 30entry: 31 %mul = fmul float %b, -1.000000e+00 32 %0 = tail call float @llvm.fma.f32(float %a, float %mul, float %c) 33 ret float %0 34} 35 36define float @fms32_com(float %a, float %b, float %c) nounwind readnone ssp { 37; CHECK-LABEL: fms32_com: 38; CHECK: // %bb.0: // %entry 39; CHECK-NEXT: fmsub s0, s1, s0, s2 40; CHECK-NEXT: ret 41entry: 42 %mul = fmul float %b, -1.000000e+00 43 %0 = tail call float @llvm.fma.f32(float %mul, float %a, float %c) 44 ret float %0 45} 46 47define float @fnms32(float %a, float %b, float %c) nounwind readnone ssp { 48; CHECK-LABEL: fnms32: 49; CHECK: // %bb.0: // %entry 50; CHECK-NEXT: fnmsub s0, s0, s1, s2 51; CHECK-NEXT: ret 52entry: 53 %mul = fmul float %c, -1.000000e+00 54 %0 = tail call float @llvm.fma.f32(float %a, float %b, float %mul) 55 ret float %0 56} 57 58define double @fma64(double %a, double %b, double %c) nounwind readnone ssp { 59; CHECK-LABEL: fma64: 60; CHECK: // %bb.0: // %entry 61; CHECK-NEXT: fmadd d0, d0, d1, d2 62; CHECK-NEXT: ret 63entry: 64 %0 = tail call double @llvm.fma.f64(double %a, double %b, double %c) 65 ret double %0 66} 67 68define double @fnma64(double %a, double %b, double %c) nounwind readnone ssp { 69; CHECK-LABEL: fnma64: 70; CHECK: // %bb.0: // %entry 71; CHECK-NEXT: fnmadd d0, d0, d1, d2 72; CHECK-NEXT: ret 73entry: 74 %0 = tail call double @llvm.fma.f64(double %a, double %b, double %c) 75 %mul = fmul double %0, -1.000000e+00 76 ret double %mul 77} 78 79define double @fms64(double %a, double %b, double %c) nounwind readnone ssp { 80; CHECK-LABEL: fms64: 81; CHECK: // %bb.0: // %entry 82; CHECK-NEXT: fmsub d0, d0, d1, d2 83; CHECK-NEXT: ret 84entry: 85 %mul = fneg double %b 86 %0 = tail call double @llvm.fma.f64(double %a, double %mul, double %c) 87 ret double %0 88} 89 90define double @fms64_com(double %a, double %b, double %c) nounwind readnone ssp { 91; CHECK-LABEL: fms64_com: 92; CHECK: // %bb.0: // %entry 93; CHECK-NEXT: fmsub d0, d1, d0, d2 94; CHECK-NEXT: ret 95entry: 96 %mul = fneg double %b 97 %0 = tail call double @llvm.fma.f64(double %mul, double %a, double %c) 98 ret double %0 99} 100 101define double @fnms64(double %a, double %b, double %c) nounwind readnone ssp { 102; CHECK-LABEL: fnms64: 103; CHECK: // %bb.0: // %entry 104; CHECK-NEXT: fnmsub d0, d0, d1, d2 105; CHECK-NEXT: ret 106entry: 107 %mul = fneg double %c 108 %0 = tail call double @llvm.fma.f64(double %a, double %b, double %mul) 109 ret double %0 110} 111 112define float @fma32_strict(float %a, float %b, float %c) nounwind readnone ssp strictfp { 113; CHECK-LABEL: fma32_strict: 114; CHECK: // %bb.0: // %entry 115; CHECK-NEXT: fmadd s0, s0, s1, s2 116; CHECK-NEXT: ret 117entry: 118 %0 = tail call float @llvm.experimental.constrained.fma.f32(float %a, float %b, float %c, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 119 ret float %0 120} 121 122define float @fnma32_strict(float %a, float %b, float %c) nounwind readnone ssp strictfp { 123; CHECK-LABEL: fnma32_strict: 124; CHECK: // %bb.0: // %entry 125; CHECK-NEXT: fnmadd s0, s0, s1, s2 126; CHECK-NEXT: ret 127entry: 128 %0 = tail call float @llvm.experimental.constrained.fma.f32(float %a, float %b, float %c, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 129 %neg = fneg float %0 130 ret float %neg 131} 132 133define float @fms32_strict(float %a, float %b, float %c) nounwind readnone ssp strictfp { 134; CHECK-LABEL: fms32_strict: 135; CHECK: // %bb.0: // %entry 136; CHECK-NEXT: fmsub s0, s0, s1, s2 137; CHECK-NEXT: ret 138entry: 139 %neg = fneg float %b 140 %0 = tail call float @llvm.experimental.constrained.fma.f32(float %a, float %neg, float %c, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 141 ret float %0 142} 143 144define float @fms32_com_strict(float %a, float %b, float %c) nounwind readnone ssp strictfp { 145; CHECK-LABEL: fms32_com_strict: 146; CHECK: // %bb.0: // %entry 147; CHECK-NEXT: fmsub s0, s0, s1, s2 148; CHECK-NEXT: ret 149entry: 150 %neg = fneg float %b 151 %0 = tail call float @llvm.experimental.constrained.fma.f32(float %neg, float %a, float %c, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 152 ret float %0 153} 154 155define float @fnms32_strict(float %a, float %b, float %c) nounwind readnone ssp strictfp { 156; CHECK-LABEL: fnms32_strict: 157; CHECK: // %bb.0: // %entry 158; CHECK-NEXT: fnmsub s0, s0, s1, s2 159; CHECK-NEXT: ret 160entry: 161 %neg = fneg float %c 162 %0 = tail call float @llvm.experimental.constrained.fma.f32(float %a, float %b, float %neg, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 163 ret float %0 164} 165 166define double @fma64_strict(double %a, double %b, double %c) nounwind readnone ssp strictfp { 167; CHECK-LABEL: fma64_strict: 168; CHECK: // %bb.0: // %entry 169; CHECK-NEXT: fmadd d0, d0, d1, d2 170; CHECK-NEXT: ret 171entry: 172 %0 = tail call double @llvm.experimental.constrained.fma.f64(double %a, double %b, double %c, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 173 ret double %0 174} 175 176define double @fnma64_strict(double %a, double %b, double %c) nounwind readnone ssp strictfp { 177; CHECK-LABEL: fnma64_strict: 178; CHECK: // %bb.0: // %entry 179; CHECK-NEXT: fnmadd d0, d0, d1, d2 180; CHECK-NEXT: ret 181entry: 182 %0 = tail call double @llvm.experimental.constrained.fma.f64(double %a, double %b, double %c, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 183 %neg = fneg double %0 184 ret double %neg 185} 186 187define double @fms64_strict(double %a, double %b, double %c) nounwind readnone ssp strictfp { 188; CHECK-LABEL: fms64_strict: 189; CHECK: // %bb.0: // %entry 190; CHECK-NEXT: fmsub d0, d0, d1, d2 191; CHECK-NEXT: ret 192entry: 193 %neg = fneg double %b 194 %0 = tail call double @llvm.experimental.constrained.fma.f64(double %a, double %neg, double %c, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 195 ret double %0 196} 197 198define double @fms64_com_strict(double %a, double %b, double %c) nounwind readnone ssp strictfp { 199; CHECK-LABEL: fms64_com_strict: 200; CHECK: // %bb.0: // %entry 201; CHECK-NEXT: fmsub d0, d0, d1, d2 202; CHECK-NEXT: ret 203entry: 204 %neg = fneg double %b 205 %0 = tail call double @llvm.experimental.constrained.fma.f64(double %neg, double %a, double %c, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 206 ret double %0 207} 208 209define double @fnms64_strict(double %a, double %b, double %c) nounwind readnone ssp strictfp { 210; CHECK-LABEL: fnms64_strict: 211; CHECK: // %bb.0: // %entry 212; CHECK-NEXT: fnmsub d0, d0, d1, d2 213; CHECK-NEXT: ret 214entry: 215 %neg = fneg double %c 216 %0 = tail call double @llvm.experimental.constrained.fma.f64(double %a, double %b, double %neg, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 217 ret double %0 218} 219 220; This would crash while trying getNegatedExpression(). 221 222define float @negated_constant(float %x) { 223; CHECK-LABEL: negated_constant: 224; CHECK: // %bb.0: 225; CHECK-NEXT: mov w8, #-1037565952 // =0xc2280000 226; CHECK-NEXT: fmov s1, w8 227; CHECK-NEXT: mov w8, #1109917696 // =0x42280000 228; CHECK-NEXT: fmov s2, w8 229; CHECK-NEXT: fmul s1, s0, s1 230; CHECK-NEXT: fmadd s0, s0, s2, s1 231; CHECK-NEXT: ret 232 %m = fmul float %x, 42.0 233 %fma = call nsz float @llvm.fma.f32(float %x, float -42.0, float %m) 234 %nfma = fneg float %fma 235 ret float %nfma 236} 237 238attributes #0 = { strictfp } 239 240declare float @llvm.fma.f32(float, float, float) nounwind readnone 241declare double @llvm.fma.f64(double, double, double) nounwind readnone 242declare float @llvm.experimental.constrained.fma.f32(float, float, float, metadata, metadata) 243declare double @llvm.experimental.constrained.fma.f64(double, double, double, metadata, metadata) 244