1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu -enable-no-signed-zeros-fp-math \ 3; RUN: -enable-unsafe-fp-math < %s | FileCheck -check-prefix=CHECK-FAST %s 4; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu -enable-no-signed-zeros-fp-math \ 5; RUN: -enable-unsafe-fp-math -mattr=-vsx < %s | FileCheck -check-prefix=CHECK-FAST-NOVSX %s 6; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu < %s | FileCheck %s 7 8define dso_local double @fma_combine1(double %a, double %b, double %c) { 9; CHECK-FAST-LABEL: fma_combine1: 10; CHECK-FAST: # %bb.0: # %entry 11; CHECK-FAST-NEXT: xsnmaddadp 1, 3, 2 12; CHECK-FAST-NEXT: blr 13; 14; CHECK-FAST-NOVSX-LABEL: fma_combine1: 15; CHECK-FAST-NOVSX: # %bb.0: # %entry 16; CHECK-FAST-NOVSX-NEXT: fnmadd 1, 3, 2, 1 17; CHECK-FAST-NOVSX-NEXT: blr 18; 19; CHECK-LABEL: fma_combine1: 20; CHECK: # %bb.0: # %entry 21; CHECK-NEXT: xsnegdp 0, 3 22; CHECK-NEXT: xsmuldp 0, 0, 2 23; CHECK-NEXT: xssubdp 1, 0, 1 24; CHECK-NEXT: blr 25entry: 26 %fneg1 = fneg double %c 27 %mul = fmul double %fneg1, %b 28 %add = fsub double %mul, %a 29 ret double %add 30} 31 32define dso_local double @fma_combine2(double %a, double %b, double %c) { 33; CHECK-FAST-LABEL: fma_combine2: 34; CHECK-FAST: # %bb.0: # %entry 35; CHECK-FAST-NEXT: xsnmaddadp 1, 2, 3 36; CHECK-FAST-NEXT: blr 37; 38; CHECK-FAST-NOVSX-LABEL: fma_combine2: 39; CHECK-FAST-NOVSX: # %bb.0: # %entry 40; CHECK-FAST-NOVSX-NEXT: fnmadd 1, 2, 3, 1 41; CHECK-FAST-NOVSX-NEXT: blr 42; 43; CHECK-LABEL: fma_combine2: 44; CHECK: # %bb.0: # %entry 45; CHECK-NEXT: xsnegdp 0, 3 46; CHECK-NEXT: xsmuldp 0, 2, 0 47; CHECK-NEXT: xssubdp 1, 0, 1 48; CHECK-NEXT: blr 49entry: 50 %fneg1 = fneg double %c 51 %mul = fmul double %b, %fneg1 52 %add = fsub double %mul, %a 53 ret double %add 54} 55 56@v = common dso_local local_unnamed_addr global double 0.000000e+00, align 8 57@z = common dso_local local_unnamed_addr global double 0.000000e+00, align 8 58define dso_local double @fma_combine_two_uses(double %a, double %b, double %c) { 59; CHECK-FAST-LABEL: fma_combine_two_uses: 60; CHECK-FAST: # %bb.0: # %entry 61; CHECK-FAST-NEXT: xsnegdp 0, 1 62; CHECK-FAST-NEXT: addis 3, 2, v@toc@ha 63; CHECK-FAST-NEXT: xsnmaddadp 1, 3, 2 64; CHECK-FAST-NEXT: stfd 0, v@toc@l(3) 65; CHECK-FAST-NEXT: xsnegdp 0, 3 66; CHECK-FAST-NEXT: addis 3, 2, z@toc@ha 67; CHECK-FAST-NEXT: stfd 0, z@toc@l(3) 68; CHECK-FAST-NEXT: blr 69; 70; CHECK-FAST-NOVSX-LABEL: fma_combine_two_uses: 71; CHECK-FAST-NOVSX: # %bb.0: # %entry 72; CHECK-FAST-NOVSX-NEXT: fneg 0, 1 73; CHECK-FAST-NOVSX-NEXT: addis 3, 2, v@toc@ha 74; CHECK-FAST-NOVSX-NEXT: fnmadd 1, 3, 2, 1 75; CHECK-FAST-NOVSX-NEXT: stfd 0, v@toc@l(3) 76; CHECK-FAST-NOVSX-NEXT: fneg 0, 3 77; CHECK-FAST-NOVSX-NEXT: addis 3, 2, z@toc@ha 78; CHECK-FAST-NOVSX-NEXT: stfd 0, z@toc@l(3) 79; CHECK-FAST-NOVSX-NEXT: blr 80; 81; CHECK-LABEL: fma_combine_two_uses: 82; CHECK: # %bb.0: # %entry 83; CHECK-NEXT: xsnegdp 0, 1 84; CHECK-NEXT: addis 3, 2, v@toc@ha 85; CHECK-NEXT: stfd 0, v@toc@l(3) 86; CHECK-NEXT: xsnegdp 0, 3 87; CHECK-NEXT: addis 3, 2, z@toc@ha 88; CHECK-NEXT: stfd 0, z@toc@l(3) 89; CHECK-NEXT: xsmuldp 0, 0, 2 90; CHECK-NEXT: xssubdp 1, 0, 1 91; CHECK-NEXT: blr 92entry: 93 %fneg = fneg double %a 94 store double %fneg, ptr @v, align 8 95 %fneg1 = fneg double %c 96 store double %fneg1, ptr @z, align 8 97 %mul = fmul double %fneg1, %b 98 %add = fsub double %mul, %a 99 ret double %add 100} 101 102define dso_local double @fma_combine_one_use(double %a, double %b, double %c) { 103; CHECK-FAST-LABEL: fma_combine_one_use: 104; CHECK-FAST: # %bb.0: # %entry 105; CHECK-FAST-NEXT: xsnegdp 0, 1 106; CHECK-FAST-NEXT: xsnmaddadp 1, 3, 2 107; CHECK-FAST-NEXT: addis 3, 2, v@toc@ha 108; CHECK-FAST-NEXT: stfd 0, v@toc@l(3) 109; CHECK-FAST-NEXT: blr 110; 111; CHECK-FAST-NOVSX-LABEL: fma_combine_one_use: 112; CHECK-FAST-NOVSX: # %bb.0: # %entry 113; CHECK-FAST-NOVSX-NEXT: fneg 0, 1 114; CHECK-FAST-NOVSX-NEXT: fnmadd 1, 3, 2, 1 115; CHECK-FAST-NOVSX-NEXT: addis 3, 2, v@toc@ha 116; CHECK-FAST-NOVSX-NEXT: stfd 0, v@toc@l(3) 117; CHECK-FAST-NOVSX-NEXT: blr 118; 119; CHECK-LABEL: fma_combine_one_use: 120; CHECK: # %bb.0: # %entry 121; CHECK-NEXT: xsnegdp 0, 1 122; CHECK-NEXT: addis 3, 2, v@toc@ha 123; CHECK-NEXT: stfd 0, v@toc@l(3) 124; CHECK-NEXT: xsnegdp 0, 3 125; CHECK-NEXT: xsmuldp 0, 0, 2 126; CHECK-NEXT: xssubdp 1, 0, 1 127; CHECK-NEXT: blr 128entry: 129 %fneg = fneg double %a 130 store double %fneg, ptr @v, align 8 131 %fneg1 = fneg double %c 132 %mul = fmul double %fneg1, %b 133 %add = fsub double %mul, %a 134 ret double %add 135} 136 137define dso_local float @fma_combine_no_ice() { 138; CHECK-FAST-LABEL: fma_combine_no_ice: 139; CHECK-FAST: # %bb.0: 140; CHECK-FAST-NEXT: vspltisw 2, 1 141; CHECK-FAST-NEXT: addis 3, 2, .LCPI4_0@toc@ha 142; CHECK-FAST-NEXT: xvcvsxwdp 3, 34 143; CHECK-FAST-NEXT: lfs 0, .LCPI4_0@toc@l(3) 144; CHECK-FAST-NEXT: lfs 2, 0(3) 145; CHECK-FAST-NEXT: addis 3, 2, .LCPI4_1@toc@ha 146; CHECK-FAST-NEXT: lfs 1, .LCPI4_1@toc@l(3) 147; CHECK-FAST-NEXT: xsmaddasp 3, 2, 0 148; CHECK-FAST-NEXT: xsmaddasp 1, 2, 3 149; CHECK-FAST-NEXT: xsnmsubasp 1, 3, 2 150; CHECK-FAST-NEXT: blr 151; 152; CHECK-FAST-NOVSX-LABEL: fma_combine_no_ice: 153; CHECK-FAST-NOVSX: # %bb.0: 154; CHECK-FAST-NOVSX-NEXT: lfs 0, 0(3) 155; CHECK-FAST-NOVSX-NEXT: addis 3, 2, .LCPI4_0@toc@ha 156; CHECK-FAST-NOVSX-NEXT: lfs 1, .LCPI4_0@toc@l(3) 157; CHECK-FAST-NOVSX-NEXT: addis 3, 2, .LCPI4_1@toc@ha 158; CHECK-FAST-NOVSX-NEXT: lfs 2, .LCPI4_1@toc@l(3) 159; CHECK-FAST-NOVSX-NEXT: addis 3, 2, .LCPI4_2@toc@ha 160; CHECK-FAST-NOVSX-NEXT: fmadds 1, 0, 2, 1 161; CHECK-FAST-NOVSX-NEXT: lfs 2, .LCPI4_2@toc@l(3) 162; CHECK-FAST-NOVSX-NEXT: fmadds 2, 0, 1, 2 163; CHECK-FAST-NOVSX-NEXT: fnmsubs 1, 1, 0, 2 164; CHECK-FAST-NOVSX-NEXT: blr 165; 166; CHECK-LABEL: fma_combine_no_ice: 167; CHECK: # %bb.0: 168; CHECK-NEXT: vspltisw 2, 1 169; CHECK-NEXT: addis 3, 2, .LCPI4_0@toc@ha 170; CHECK-NEXT: xvcvsxwdp 3, 34 171; CHECK-NEXT: lfs 0, .LCPI4_0@toc@l(3) 172; CHECK-NEXT: lfs 2, 0(3) 173; CHECK-NEXT: addis 3, 2, .LCPI4_1@toc@ha 174; CHECK-NEXT: lfs 1, .LCPI4_1@toc@l(3) 175; CHECK-NEXT: fmr 4, 3 176; CHECK-NEXT: xsmaddasp 3, 2, 0 177; CHECK-NEXT: xsnmaddasp 4, 2, 0 178; CHECK-NEXT: xsmaddasp 1, 2, 3 179; CHECK-NEXT: xsmaddasp 1, 4, 2 180; CHECK-NEXT: blr 181 %tmp = load float, ptr undef, align 4 182 %tmp2 = load float, ptr undef, align 4 183 %tmp3 = fmul contract reassoc float %tmp, 0x3FE372D780000000 184 %tmp4 = fadd contract reassoc float %tmp3, 1.000000e+00 185 %tmp5 = fmul contract reassoc float %tmp2, %tmp4 186 %tmp6 = load float, ptr undef, align 4 187 %tmp7 = load float, ptr undef, align 4 188 %tmp8 = fmul contract reassoc float %tmp7, 0x3FE372D780000000 189 %tmp9 = fsub contract reassoc nsz float -1.000000e+00, %tmp8 190 %tmp10 = fmul contract reassoc float %tmp9, %tmp6 191 %tmp11 = fadd contract reassoc float %tmp5, 5.000000e-01 192 %tmp12 = fadd contract reassoc float %tmp11, %tmp10 193 ret float %tmp12 194} 195 196; This would crash while trying getNegatedExpression(). 197define dso_local double @getNegatedExpression_crash(double %x, double %y) { 198; CHECK-FAST-LABEL: getNegatedExpression_crash: 199; CHECK-FAST: # %bb.0: 200; CHECK-FAST-NEXT: vspltisw 2, -1 201; CHECK-FAST-NEXT: addis 3, 2, .LCPI5_0@toc@ha 202; CHECK-FAST-NEXT: xvcvsxwdp 4, 34 203; CHECK-FAST-NEXT: lfs 3, .LCPI5_0@toc@l(3) 204; CHECK-FAST-NEXT: xssubdp 0, 1, 4 205; CHECK-FAST-NEXT: xsmaddadp 4, 1, 3 206; CHECK-FAST-NEXT: xsmaddadp 0, 4, 2 207; CHECK-FAST-NEXT: fmr 1, 0 208; CHECK-FAST-NEXT: blr 209; 210; CHECK-FAST-NOVSX-LABEL: getNegatedExpression_crash: 211; CHECK-FAST-NOVSX: # %bb.0: 212; CHECK-FAST-NOVSX-NEXT: addis 3, 2, .LCPI5_0@toc@ha 213; CHECK-FAST-NOVSX-NEXT: lfs 0, .LCPI5_0@toc@l(3) 214; CHECK-FAST-NOVSX-NEXT: addis 3, 2, .LCPI5_1@toc@ha 215; CHECK-FAST-NOVSX-NEXT: lfs 3, .LCPI5_1@toc@l(3) 216; CHECK-FAST-NOVSX-NEXT: fmadd 3, 1, 3, 0 217; CHECK-FAST-NOVSX-NEXT: fsub 0, 1, 0 218; CHECK-FAST-NOVSX-NEXT: fmadd 1, 3, 2, 0 219; CHECK-FAST-NOVSX-NEXT: blr 220; 221; CHECK-LABEL: getNegatedExpression_crash: 222; CHECK: # %bb.0: 223; CHECK-NEXT: vspltisw 2, -1 224; CHECK-NEXT: addis 3, 2, .LCPI5_0@toc@ha 225; CHECK-NEXT: xvcvsxwdp 4, 34 226; CHECK-NEXT: lfs 3, .LCPI5_0@toc@l(3) 227; CHECK-NEXT: xssubdp 0, 1, 4 228; CHECK-NEXT: xsmaddadp 4, 1, 3 229; CHECK-NEXT: xsmaddadp 0, 4, 2 230; CHECK-NEXT: fmr 1, 0 231; CHECK-NEXT: blr 232 %neg = fneg reassoc double %x 233 %fma = call reassoc nsz double @llvm.fma.f64(double %neg, double 42.0, double -1.0) 234 %add = fadd reassoc nsz double %x, 1.0 235 %fma1 = call reassoc nsz double @llvm.fma.f64(double %fma, double %y, double %add) 236 ret double %fma1 237} 238 239define dso_local double @fma_flag_propagation(double %a) { 240; CHECK-FAST-LABEL: fma_flag_propagation: 241; CHECK-FAST: # %bb.0: # %entry 242; CHECK-FAST-NEXT: xxlxor 1, 1, 1 243; CHECK-FAST-NEXT: blr 244; 245; CHECK-FAST-NOVSX-LABEL: fma_flag_propagation: 246; CHECK-FAST-NOVSX: # %bb.0: # %entry 247; CHECK-FAST-NOVSX-NEXT: addis 3, 2, .LCPI6_0@toc@ha 248; CHECK-FAST-NOVSX-NEXT: lfs 1, .LCPI6_0@toc@l(3) 249; CHECK-FAST-NOVSX-NEXT: blr 250; 251; CHECK-LABEL: fma_flag_propagation: 252; CHECK: # %bb.0: # %entry 253; CHECK-NEXT: xxlxor 1, 1, 1 254; CHECK-NEXT: blr 255entry: 256 %0 = fneg double %a 257 %1 = call reassoc nnan double @llvm.fma.f64(double %0, double 1.0, double %a) 258 ret double %1 259} 260 261define dso_local double @neg_fma_flag_propagation(double %a) { 262; CHECK-FAST-LABEL: neg_fma_flag_propagation: 263; CHECK-FAST: # %bb.0: # %entry 264; CHECK-FAST-NEXT: xxlxor 1, 1, 1 265; CHECK-FAST-NEXT: blr 266; 267; CHECK-FAST-NOVSX-LABEL: neg_fma_flag_propagation: 268; CHECK-FAST-NOVSX: # %bb.0: # %entry 269; CHECK-FAST-NOVSX-NEXT: addis 3, 2, .LCPI7_0@toc@ha 270; CHECK-FAST-NOVSX-NEXT: lfs 1, .LCPI7_0@toc@l(3) 271; CHECK-FAST-NOVSX-NEXT: blr 272; 273; CHECK-LABEL: neg_fma_flag_propagation: 274; CHECK: # %bb.0: # %entry 275; CHECK-NEXT: xxlxor 1, 1, 1 276; CHECK-NEXT: blr 277entry: 278 %0 = call reassoc nnan double @llvm.fma.f64(double %a, double -1.0, double %a) 279 ret double %0 280} 281 282define <2 x double> @vec_neg_fma_flag_propagation(<2 x double> %a) { 283; CHECK-FAST-LABEL: vec_neg_fma_flag_propagation: 284; CHECK-FAST: # %bb.0: # %entry 285; CHECK-FAST-NEXT: addis 3, 2, .LCPI8_0@toc@ha 286; CHECK-FAST-NEXT: addi 3, 3, .LCPI8_0@toc@l 287; CHECK-FAST-NEXT: lxvd2x 0, 0, 3 288; CHECK-FAST-NEXT: xvmaddadp 34, 34, 0 289; CHECK-FAST-NEXT: blr 290; 291; CHECK-FAST-NOVSX-LABEL: vec_neg_fma_flag_propagation: 292; CHECK-FAST-NOVSX: # %bb.0: # %entry 293; CHECK-FAST-NOVSX-NEXT: addis 3, 2, .LCPI8_0@toc@ha 294; CHECK-FAST-NOVSX-NEXT: lfs 1, .LCPI8_0@toc@l(3) 295; CHECK-FAST-NOVSX-NEXT: fmr 2, 1 296; CHECK-FAST-NOVSX-NEXT: blr 297; 298; CHECK-LABEL: vec_neg_fma_flag_propagation: 299; CHECK: # %bb.0: # %entry 300; CHECK-NEXT: addis 3, 2, .LCPI8_0@toc@ha 301; CHECK-NEXT: addi 3, 3, .LCPI8_0@toc@l 302; CHECK-NEXT: lxvd2x 0, 0, 3 303; CHECK-NEXT: xvmaddadp 34, 34, 0 304; CHECK-NEXT: blr 305entry: 306 %0 = call reassoc nnan <2 x double> @llvm.fma.v2f64(<2 x double> %a, <2 x double> <double -1.0, double -1.0>, <2 x double> %a) 307 ret <2 x double> %0 308} 309 310define dso_local double @fma_combine_const(double %a, double %b) { 311; CHECK-FAST-LABEL: fma_combine_const: 312; CHECK-FAST: # %bb.0: # %entry 313; CHECK-FAST-NEXT: addis 3, 2, .LCPI9_0@toc@ha 314; CHECK-FAST-NEXT: lfd 0, .LCPI9_0@toc@l(3) 315; CHECK-FAST-NEXT: xsmaddadp 2, 1, 0 316; CHECK-FAST-NEXT: fmr 1, 2 317; CHECK-FAST-NEXT: blr 318; 319; CHECK-FAST-NOVSX-LABEL: fma_combine_const: 320; CHECK-FAST-NOVSX: # %bb.0: # %entry 321; CHECK-FAST-NOVSX-NEXT: addis 3, 2, .LCPI9_0@toc@ha 322; CHECK-FAST-NOVSX-NEXT: lfd 0, .LCPI9_0@toc@l(3) 323; CHECK-FAST-NOVSX-NEXT: fmadd 1, 1, 0, 2 324; CHECK-FAST-NOVSX-NEXT: blr 325; 326; CHECK-LABEL: fma_combine_const: 327; CHECK: # %bb.0: # %entry 328; CHECK-NEXT: addis 3, 2, .LCPI9_0@toc@ha 329; CHECK-NEXT: lfd 0, .LCPI9_0@toc@l(3) 330; CHECK-NEXT: addis 3, 2, .LCPI9_1@toc@ha 331; CHECK-NEXT: xsmuldp 0, 1, 0 332; CHECK-NEXT: lfd 1, .LCPI9_1@toc@l(3) 333; CHECK-NEXT: xsmaddadp 2, 0, 1 334; CHECK-NEXT: fmr 1, 2 335; CHECK-NEXT: blr 336entry: 337 %0 = fmul double %a, 1.1 338 %1 = call contract double @llvm.fma.f64(double %0, double 2.1, double %b) 339 ret double %1 340} 341 342declare double @llvm.fma.f64(double, double, double) nounwind readnone 343declare <2 x double> @llvm.fma.v2f64(<2 x double>, <2 x double>, <2 x double>) nounwind readnone 344