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 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 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 local_unnamed_addr global double 0.000000e+00, align 8 57@z = common local_unnamed_addr global double 0.000000e+00, align 8 58define 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: addis 4, 2, z@toc@ha 64; CHECK-FAST-NEXT: xsnmaddadp 1, 3, 2 65; CHECK-FAST-NEXT: xsnegdp 2, 3 66; CHECK-FAST-NEXT: stfd 0, v@toc@l(3) 67; CHECK-FAST-NEXT: stfd 2, z@toc@l(4) 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: fnmadd 0, 3, 2, 1 73; CHECK-FAST-NOVSX-NEXT: fneg 2, 1 74; CHECK-FAST-NOVSX-NEXT: addis 3, 2, v@toc@ha 75; CHECK-FAST-NOVSX-NEXT: addis 4, 2, z@toc@ha 76; CHECK-FAST-NOVSX-NEXT: fneg 3, 3 77; CHECK-FAST-NOVSX-NEXT: fmr 1, 0 78; CHECK-FAST-NOVSX-NEXT: stfd 2, v@toc@l(3) 79; CHECK-FAST-NOVSX-NEXT: stfd 3, z@toc@l(4) 80; CHECK-FAST-NOVSX-NEXT: blr 81; 82; CHECK-LABEL: fma_combine_two_uses: 83; CHECK: # %bb.0: # %entry 84; CHECK-NEXT: xsnegdp 3, 3 85; CHECK-NEXT: addis 3, 2, v@toc@ha 86; CHECK-NEXT: addis 4, 2, z@toc@ha 87; CHECK-NEXT: xsmuldp 0, 3, 2 88; CHECK-NEXT: stfd 3, z@toc@l(4) 89; CHECK-NEXT: xsnegdp 2, 1 90; CHECK-NEXT: xssubdp 0, 0, 1 91; CHECK-NEXT: stfd 2, v@toc@l(3) 92; CHECK-NEXT: fmr 1, 0 93; CHECK-NEXT: blr 94entry: 95 %fneg = fneg double %a 96 store double %fneg, double* @v, align 8 97 %fneg1 = fneg double %c 98 store double %fneg1, double* @z, align 8 99 %mul = fmul double %fneg1, %b 100 %add = fsub double %mul, %a 101 ret double %add 102} 103 104define double @fma_combine_one_use(double %a, double %b, double %c) { 105; CHECK-FAST-LABEL: fma_combine_one_use: 106; CHECK-FAST: # %bb.0: # %entry 107; CHECK-FAST-NEXT: xsnegdp 0, 1 108; CHECK-FAST-NEXT: addis 3, 2, v@toc@ha 109; CHECK-FAST-NEXT: xsnmaddadp 1, 3, 2 110; CHECK-FAST-NEXT: stfd 0, v@toc@l(3) 111; CHECK-FAST-NEXT: blr 112; 113; CHECK-FAST-NOVSX-LABEL: fma_combine_one_use: 114; CHECK-FAST-NOVSX: # %bb.0: # %entry 115; CHECK-FAST-NOVSX-NEXT: fnmadd 0, 3, 2, 1 116; CHECK-FAST-NOVSX-NEXT: fneg 2, 1 117; CHECK-FAST-NOVSX-NEXT: addis 3, 2, v@toc@ha 118; CHECK-FAST-NOVSX-NEXT: fmr 1, 0 119; CHECK-FAST-NOVSX-NEXT: stfd 2, v@toc@l(3) 120; CHECK-FAST-NOVSX-NEXT: blr 121; 122; CHECK-LABEL: fma_combine_one_use: 123; CHECK: # %bb.0: # %entry 124; CHECK-NEXT: xsnegdp 0, 3 125; CHECK-NEXT: addis 3, 2, v@toc@ha 126; CHECK-NEXT: xsmuldp 0, 0, 2 127; CHECK-NEXT: xsnegdp 2, 1 128; CHECK-NEXT: xssubdp 0, 0, 1 129; CHECK-NEXT: stfd 2, v@toc@l(3) 130; CHECK-NEXT: fmr 1, 0 131; CHECK-NEXT: blr 132entry: 133 %fneg = fneg double %a 134 store double %fneg, double* @v, align 8 135 %fneg1 = fneg double %c 136 %mul = fmul double %fneg1, %b 137 %add = fsub double %mul, %a 138 ret double %add 139} 140 141define float @fma_combine_no_ice() { 142; CHECK-FAST-LABEL: fma_combine_no_ice: 143; CHECK-FAST: # %bb.0: 144; CHECK-FAST-NEXT: addis 3, 2, .LCPI4_0@toc@ha 145; CHECK-FAST-NEXT: addis 4, 2, .LCPI4_1@toc@ha 146; CHECK-FAST-NEXT: lfs 0, .LCPI4_0@toc@l(3) 147; CHECK-FAST-NEXT: lfsx 2, 0, 3 148; CHECK-FAST-NEXT: addis 3, 2, .LCPI4_2@toc@ha 149; CHECK-FAST-NEXT: lfs 3, .LCPI4_1@toc@l(4) 150; CHECK-FAST-NEXT: lfs 1, .LCPI4_2@toc@l(3) 151; CHECK-FAST-NEXT: xsmaddasp 3, 2, 0 152; CHECK-FAST-NEXT: xsmaddasp 1, 2, 3 153; CHECK-FAST-NEXT: xsnmsubasp 1, 3, 2 154; CHECK-FAST-NEXT: blr 155; 156; CHECK-FAST-NOVSX-LABEL: fma_combine_no_ice: 157; CHECK-FAST-NOVSX: # %bb.0: 158; CHECK-FAST-NOVSX-NEXT: addis 3, 2, .LCPI4_0@toc@ha 159; CHECK-FAST-NOVSX-NEXT: lfs 0, .LCPI4_0@toc@l(3) 160; CHECK-FAST-NOVSX-NEXT: addis 3, 2, .LCPI4_1@toc@ha 161; CHECK-FAST-NOVSX-NEXT: lfs 1, 0(3) 162; CHECK-FAST-NOVSX-NEXT: lfs 2, .LCPI4_1@toc@l(3) 163; CHECK-FAST-NOVSX-NEXT: addis 3, 2, .LCPI4_2@toc@ha 164; CHECK-FAST-NOVSX-NEXT: fmadds 0, 1, 2, 0 165; CHECK-FAST-NOVSX-NEXT: lfs 2, .LCPI4_2@toc@l(3) 166; CHECK-FAST-NOVSX-NEXT: fmadds 2, 1, 0, 2 167; CHECK-FAST-NOVSX-NEXT: fnmsubs 1, 0, 1, 2 168; CHECK-FAST-NOVSX-NEXT: blr 169; 170; CHECK-LABEL: fma_combine_no_ice: 171; CHECK: # %bb.0: 172; CHECK-NEXT: addis 3, 2, .LCPI4_0@toc@ha 173; CHECK-NEXT: addis 4, 2, .LCPI4_1@toc@ha 174; CHECK-NEXT: lfs 0, .LCPI4_0@toc@l(3) 175; CHECK-NEXT: lfsx 2, 0, 3 176; CHECK-NEXT: addis 3, 2, .LCPI4_2@toc@ha 177; CHECK-NEXT: lfs 3, .LCPI4_1@toc@l(4) 178; CHECK-NEXT: lfs 1, .LCPI4_2@toc@l(3) 179; CHECK-NEXT: fmr 4, 3 180; CHECK-NEXT: xsmaddasp 3, 2, 0 181; CHECK-NEXT: xsnmaddasp 4, 2, 0 182; CHECK-NEXT: xsmaddasp 1, 2, 3 183; CHECK-NEXT: xsmaddasp 1, 4, 2 184; CHECK-NEXT: blr 185 %tmp = load float, float* undef, align 4 186 %tmp2 = load float, float* undef, align 4 187 %tmp3 = fmul reassoc float %tmp, 0x3FE372D780000000 188 %tmp4 = fadd reassoc float %tmp3, 1.000000e+00 189 %tmp5 = fmul reassoc float %tmp2, %tmp4 190 %tmp6 = load float, float* undef, align 4 191 %tmp7 = load float, float* undef, align 4 192 %tmp8 = fmul reassoc float %tmp7, 0x3FE372D780000000 193 %tmp9 = fsub reassoc nsz float -1.000000e+00, %tmp8 194 %tmp10 = fmul reassoc float %tmp9, %tmp6 195 %tmp11 = fadd reassoc float %tmp5, 5.000000e-01 196 %tmp12 = fadd reassoc float %tmp11, %tmp10 197 ret float %tmp12 198} 199 200; This would crash while trying getNegatedExpression(). 201define double @getNegatedExpression_crash(double %x, double %y) { 202; CHECK-FAST-LABEL: getNegatedExpression_crash: 203; CHECK-FAST: # %bb.0: 204; CHECK-FAST-NEXT: addis 3, 2, .LCPI5_1@toc@ha 205; CHECK-FAST-NEXT: addis 4, 2, .LCPI5_0@toc@ha 206; CHECK-FAST-NEXT: lfs 3, .LCPI5_1@toc@l(3) 207; CHECK-FAST-NEXT: lfs 4, .LCPI5_0@toc@l(4) 208; CHECK-FAST-NEXT: xssubdp 0, 1, 3 209; CHECK-FAST-NEXT: xsmaddadp 3, 1, 4 210; CHECK-FAST-NEXT: xsmaddadp 0, 3, 2 211; CHECK-FAST-NEXT: fmr 1, 0 212; CHECK-FAST-NEXT: blr 213; 214; CHECK-FAST-NOVSX-LABEL: getNegatedExpression_crash: 215; CHECK-FAST-NOVSX: # %bb.0: 216; CHECK-FAST-NOVSX-NEXT: addis 3, 2, .LCPI5_0@toc@ha 217; CHECK-FAST-NOVSX-NEXT: addis 4, 2, .LCPI5_1@toc@ha 218; CHECK-FAST-NOVSX-NEXT: lfs 0, .LCPI5_0@toc@l(3) 219; CHECK-FAST-NOVSX-NEXT: lfs 3, .LCPI5_1@toc@l(4) 220; CHECK-FAST-NOVSX-NEXT: fmadd 3, 1, 3, 0 221; CHECK-FAST-NOVSX-NEXT: fsub 0, 1, 0 222; CHECK-FAST-NOVSX-NEXT: fmadd 1, 3, 2, 0 223; CHECK-FAST-NOVSX-NEXT: blr 224; 225; CHECK-LABEL: getNegatedExpression_crash: 226; CHECK: # %bb.0: 227; CHECK-NEXT: addis 3, 2, .LCPI5_1@toc@ha 228; CHECK-NEXT: addis 4, 2, .LCPI5_0@toc@ha 229; CHECK-NEXT: lfs 3, .LCPI5_1@toc@l(3) 230; CHECK-NEXT: lfs 4, .LCPI5_0@toc@l(4) 231; CHECK-NEXT: xssubdp 0, 1, 3 232; CHECK-NEXT: xsmaddadp 3, 1, 4 233; CHECK-NEXT: xsmaddadp 0, 3, 2 234; CHECK-NEXT: fmr 1, 0 235; CHECK-NEXT: blr 236 %neg = fneg reassoc double %x 237 %fma = call reassoc nsz double @llvm.fma.f64(double %neg, double 42.0, double -1.0) 238 %add = fadd reassoc nsz double %x, 1.0 239 %fma1 = call reassoc nsz double @llvm.fma.f64(double %fma, double %y, double %add) 240 ret double %fma1 241} 242 243define double @fma_flag_propagation(double %a) { 244; CHECK-FAST-LABEL: fma_flag_propagation: 245; CHECK-FAST: # %bb.0: # %entry 246; CHECK-FAST-NEXT: xxlxor 1, 1, 1 247; CHECK-FAST-NEXT: blr 248; 249; CHECK-FAST-NOVSX-LABEL: fma_flag_propagation: 250; CHECK-FAST-NOVSX: # %bb.0: # %entry 251; CHECK-FAST-NOVSX-NEXT: addis 3, 2, .LCPI6_0@toc@ha 252; CHECK-FAST-NOVSX-NEXT: lfs 1, .LCPI6_0@toc@l(3) 253; CHECK-FAST-NOVSX-NEXT: blr 254; 255; CHECK-LABEL: fma_flag_propagation: 256; CHECK: # %bb.0: # %entry 257; CHECK-NEXT: xxlxor 1, 1, 1 258; CHECK-NEXT: blr 259entry: 260 %0 = fneg double %a 261 %1 = call reassoc nnan double @llvm.fma.f64(double %0, double 1.0, double %a) 262 ret double %1 263} 264 265define double @neg_fma_flag_propagation(double %a) { 266; CHECK-FAST-LABEL: neg_fma_flag_propagation: 267; CHECK-FAST: # %bb.0: # %entry 268; CHECK-FAST-NEXT: xxlxor 1, 1, 1 269; CHECK-FAST-NEXT: blr 270; 271; CHECK-FAST-NOVSX-LABEL: neg_fma_flag_propagation: 272; CHECK-FAST-NOVSX: # %bb.0: # %entry 273; CHECK-FAST-NOVSX-NEXT: addis 3, 2, .LCPI7_0@toc@ha 274; CHECK-FAST-NOVSX-NEXT: lfs 1, .LCPI7_0@toc@l(3) 275; CHECK-FAST-NOVSX-NEXT: blr 276; 277; CHECK-LABEL: neg_fma_flag_propagation: 278; CHECK: # %bb.0: # %entry 279; CHECK-NEXT: xxlxor 1, 1, 1 280; CHECK-NEXT: blr 281entry: 282 %0 = call reassoc nnan double @llvm.fma.f64(double %a, double -1.0, double %a) 283 ret double %0 284} 285 286define <2 x double> @vec_neg_fma_flag_propagation(<2 x double> %a) { 287; CHECK-FAST-LABEL: vec_neg_fma_flag_propagation: 288; CHECK-FAST: # %bb.0: # %entry 289; CHECK-FAST-NEXT: addis 3, 2, .LCPI8_0@toc@ha 290; CHECK-FAST-NEXT: addi 3, 3, .LCPI8_0@toc@l 291; CHECK-FAST-NEXT: lxvd2x 0, 0, 3 292; CHECK-FAST-NEXT: xxswapd 0, 0 293; CHECK-FAST-NEXT: xvmaddadp 34, 34, 0 294; CHECK-FAST-NEXT: blr 295; 296; CHECK-FAST-NOVSX-LABEL: vec_neg_fma_flag_propagation: 297; CHECK-FAST-NOVSX: # %bb.0: # %entry 298; CHECK-FAST-NOVSX-NEXT: addis 3, 2, .LCPI8_0@toc@ha 299; CHECK-FAST-NOVSX-NEXT: lfs 1, .LCPI8_0@toc@l(3) 300; CHECK-FAST-NOVSX-NEXT: fmr 2, 1 301; CHECK-FAST-NOVSX-NEXT: blr 302; 303; CHECK-LABEL: vec_neg_fma_flag_propagation: 304; CHECK: # %bb.0: # %entry 305; CHECK-NEXT: addis 3, 2, .LCPI8_0@toc@ha 306; CHECK-NEXT: addi 3, 3, .LCPI8_0@toc@l 307; CHECK-NEXT: lxvd2x 0, 0, 3 308; CHECK-NEXT: xxswapd 0, 0 309; CHECK-NEXT: xvmaddadp 34, 34, 0 310; CHECK-NEXT: blr 311entry: 312 %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) 313 ret <2 x double> %0 314} 315 316define double @fma_combine_const(double %a, double %b) { 317; CHECK-FAST-LABEL: fma_combine_const: 318; CHECK-FAST: # %bb.0: # %entry 319; CHECK-FAST-NEXT: addis 3, 2, .LCPI9_0@toc@ha 320; CHECK-FAST-NEXT: lfd 0, .LCPI9_0@toc@l(3) 321; CHECK-FAST-NEXT: xsmaddadp 2, 1, 0 322; CHECK-FAST-NEXT: fmr 1, 2 323; CHECK-FAST-NEXT: blr 324; 325; CHECK-FAST-NOVSX-LABEL: fma_combine_const: 326; CHECK-FAST-NOVSX: # %bb.0: # %entry 327; CHECK-FAST-NOVSX-NEXT: addis 3, 2, .LCPI9_0@toc@ha 328; CHECK-FAST-NOVSX-NEXT: lfd 0, .LCPI9_0@toc@l(3) 329; CHECK-FAST-NOVSX-NEXT: fmadd 1, 1, 0, 2 330; CHECK-FAST-NOVSX-NEXT: blr 331; 332; CHECK-LABEL: fma_combine_const: 333; CHECK: # %bb.0: # %entry 334; CHECK-NEXT: addis 3, 2, .LCPI9_0@toc@ha 335; CHECK-NEXT: lfd 0, .LCPI9_0@toc@l(3) 336; CHECK-NEXT: addis 3, 2, .LCPI9_1@toc@ha 337; CHECK-NEXT: lfd 3, .LCPI9_1@toc@l(3) 338; CHECK-NEXT: xsmuldp 0, 1, 0 339; CHECK-NEXT: fmr 1, 2 340; CHECK-NEXT: xsmaddadp 1, 0, 3 341; CHECK-NEXT: blr 342entry: 343 %0 = fmul double %a, 1.1 344 %1 = call contract double @llvm.fma.f64(double %0, double 2.1, double %b) 345 ret double %1 346} 347 348declare double @llvm.fma.f64(double, double, double) nounwind readnone 349declare <2 x double> @llvm.fma.v2f64(<2 x double>, <2 x double>, <2 x double>) nounwind readnone 350