1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3; RUN: opt < %s -passes=instcombine -use-constant-fp-for-fixed-length-splat -S | FileCheck %s 4 5declare void @use(float) 6declare void @use_vec(<2 x float>) 7declare float @llvm.vector.reduce.fadd.v4f32(float, <4 x float>) 8 9; -x + y => y - x 10 11define float @fneg_op0(float %x, float %y) { 12; CHECK-LABEL: @fneg_op0( 13; CHECK-NEXT: [[ADD:%.*]] = fsub float [[Y:%.*]], [[X:%.*]] 14; CHECK-NEXT: ret float [[ADD]] 15; 16 %neg = fsub float -0.0, %x 17 %add = fadd float %neg, %y 18 ret float %add 19} 20 21; x + -y => x - y 22 23define float @fneg_op1(float %x, float %y) { 24; CHECK-LABEL: @fneg_op1( 25; CHECK-NEXT: [[ADD:%.*]] = fsub float [[X:%.*]], [[Y:%.*]] 26; CHECK-NEXT: ret float [[ADD]] 27; 28 %neg = fsub float -0.0, %y 29 %add = fadd float %x, %neg 30 ret float %add 31} 32 33; Z + (-X / Y) --> Z - (X / Y) 34 35define double @fdiv_fneg1(double %x, double %y, double %pz) { 36; CHECK-LABEL: @fdiv_fneg1( 37; CHECK-NEXT: [[Z:%.*]] = frem double 4.200000e+01, [[PZ:%.*]] 38; CHECK-NEXT: [[TMP1:%.*]] = fdiv double [[X:%.*]], [[Y:%.*]] 39; CHECK-NEXT: [[R:%.*]] = fsub double [[Z]], [[TMP1]] 40; CHECK-NEXT: ret double [[R]] 41; 42 %z = frem double 42.0, %pz ; thwart complexity-based canonicalization 43 %neg = fsub double -0.000000e+00, %x 44 %div = fdiv double %neg, %y 45 %r = fadd double %z, %div 46 ret double %r 47} 48 49; Z + (Y / -X) --> Z - (Y / X) 50 51define <2 x double> @fdiv_fneg2(<2 x double> %x, <2 x double> %y, <2 x double> %pz) { 52; CHECK-LABEL: @fdiv_fneg2( 53; CHECK-NEXT: [[Z:%.*]] = frem <2 x double> <double 4.200000e+01, double 8.000000e+00>, [[PZ:%.*]] 54; CHECK-NEXT: [[TMP1:%.*]] = fdiv <2 x double> [[Y:%.*]], [[X:%.*]] 55; CHECK-NEXT: [[R:%.*]] = fsub <2 x double> [[Z]], [[TMP1]] 56; CHECK-NEXT: ret <2 x double> [[R]] 57; 58 %z = frem <2 x double> <double 42.0, double 8.0>, %pz ; thwart complexity-based canonicalization 59 %neg = fsub <2 x double> <double -0.0, double -0.0>, %x 60 %div = fdiv <2 x double> %y, %neg 61 %r = fadd <2 x double> %z, %div 62 ret <2 x double> %r 63} 64 65; Z + (-X * Y) --> Z - (X * Y) 66 67define double @fmul_fneg1(double %x, double %y, double %pz) { 68; CHECK-LABEL: @fmul_fneg1( 69; CHECK-NEXT: [[Z:%.*]] = frem double 4.200000e+01, [[PZ:%.*]] 70; CHECK-NEXT: [[TMP1:%.*]] = fmul double [[X:%.*]], [[Y:%.*]] 71; CHECK-NEXT: [[R:%.*]] = fsub double [[Z]], [[TMP1]] 72; CHECK-NEXT: ret double [[R]] 73; 74 %z = frem double 42.0, %pz ; thwart complexity-based canonicalization 75 %neg = fsub double -0.000000e+00, %x 76 %mul = fmul double %neg, %y 77 %r = fadd double %z, %mul 78 ret double %r 79} 80 81; Z + (Y * -X) --> Z - (Y * X) 82 83define double @fmul_fneg2(double %x, double %py, double %pz) { 84; CHECK-LABEL: @fmul_fneg2( 85; CHECK-NEXT: [[Y:%.*]] = frem double -4.200000e+01, [[PY:%.*]] 86; CHECK-NEXT: [[Z:%.*]] = frem double 4.200000e+01, [[PZ:%.*]] 87; CHECK-NEXT: [[TMP1:%.*]] = fmul double [[X:%.*]], [[Y]] 88; CHECK-NEXT: [[R:%.*]] = fsub double [[Z]], [[TMP1]] 89; CHECK-NEXT: ret double [[R]] 90; 91 %y = frem double -42.0, %py ; thwart complexity-based canonicalization 92 %z = frem double 42.0, %pz ; thwart complexity-based canonicalization 93 %neg = fsub double -0.000000e+00, %x 94 %mul = fmul double %y, %neg 95 %r = fadd double %z, %mul 96 ret double %r 97} 98 99; (-X / Y) + Z --> Z - (X / Y) 100 101define double @fdiv_fneg1_commute(double %x, double %y, double %pz) { 102; CHECK-LABEL: @fdiv_fneg1_commute( 103; CHECK-NEXT: [[Z:%.*]] = frem double 4.200000e+01, [[PZ:%.*]] 104; CHECK-NEXT: [[TMP1:%.*]] = fdiv double [[X:%.*]], [[Y:%.*]] 105; CHECK-NEXT: [[R:%.*]] = fsub double [[Z]], [[TMP1]] 106; CHECK-NEXT: ret double [[R]] 107; 108 %z = frem double 42.0, %pz ; thwart complexity-based canonicalization 109 %neg = fsub double -0.000000e+00, %x 110 %div = fdiv double %neg, %y 111 %r = fadd double %div, %z 112 ret double %r 113} 114 115; (Y / -X) + Z --> Z - (Y / X) 116 117define <2 x double> @fdiv_fneg2_commute(<2 x double> %x, <2 x double> %y, <2 x double> %pz) { 118; CHECK-LABEL: @fdiv_fneg2_commute( 119; CHECK-NEXT: [[Z:%.*]] = frem <2 x double> <double 4.200000e+01, double 8.000000e+00>, [[PZ:%.*]] 120; CHECK-NEXT: [[TMP1:%.*]] = fdiv <2 x double> [[Y:%.*]], [[X:%.*]] 121; CHECK-NEXT: [[R:%.*]] = fsub <2 x double> [[Z]], [[TMP1]] 122; CHECK-NEXT: ret <2 x double> [[R]] 123; 124 %z = frem <2 x double> <double 42.0, double 8.0>, %pz ; thwart complexity-based canonicalization 125 %neg = fsub <2 x double> <double -0.0, double -0.0>, %x 126 %div = fdiv <2 x double> %y, %neg 127 %r = fadd <2 x double> %div, %z 128 ret <2 x double> %r 129} 130 131; (-X * Y) + Z --> Z - (X * Y) 132 133define double @fmul_fneg1_commute(double %x, double %y, double %pz) { 134; CHECK-LABEL: @fmul_fneg1_commute( 135; CHECK-NEXT: [[Z:%.*]] = frem double 4.200000e+01, [[PZ:%.*]] 136; CHECK-NEXT: [[TMP1:%.*]] = fmul double [[X:%.*]], [[Y:%.*]] 137; CHECK-NEXT: [[R:%.*]] = fsub double [[Z]], [[TMP1]] 138; CHECK-NEXT: ret double [[R]] 139; 140 %z = frem double 42.0, %pz ; thwart complexity-based canonicalization 141 %neg = fsub double -0.000000e+00, %x 142 %mul = fmul double %neg, %y 143 %r = fadd double %mul, %z 144 ret double %r 145} 146 147; (Y * -X) + Z --> Z - (Y * X) 148 149define double @fmul_fneg2_commute(double %x, double %py, double %pz) { 150; CHECK-LABEL: @fmul_fneg2_commute( 151; CHECK-NEXT: [[Y:%.*]] = frem double 4.100000e+01, [[PY:%.*]] 152; CHECK-NEXT: [[Z:%.*]] = frem double 4.200000e+01, [[PZ:%.*]] 153; CHECK-NEXT: [[TMP1:%.*]] = fmul double [[X:%.*]], [[Y]] 154; CHECK-NEXT: [[R:%.*]] = fsub double [[Z]], [[TMP1]] 155; CHECK-NEXT: ret double [[R]] 156; 157 %y = frem double 41.0, %py ; thwart complexity-based canonicalization 158 %z = frem double 42.0, %pz ; thwart complexity-based canonicalization 159 %neg = fsub double -0.000000e+00, %x 160 %mul = fmul double %y, %neg 161 %r = fadd double %mul, %z 162 ret double %r 163} 164 165; Z + (-X / Y) - extra use means we can't transform to fsub without an extra instruction 166 167define float @fdiv_fneg1_extra_use(float %x, float %y, float %pz) { 168; CHECK-LABEL: @fdiv_fneg1_extra_use( 169; CHECK-NEXT: [[Z:%.*]] = frem float 4.200000e+01, [[PZ:%.*]] 170; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X:%.*]] 171; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[NEG]], [[Y:%.*]] 172; CHECK-NEXT: call void @use(float [[DIV]]) 173; CHECK-NEXT: [[R:%.*]] = fadd float [[Z]], [[DIV]] 174; CHECK-NEXT: ret float [[R]] 175; 176 %z = frem float 42.0, %pz ; thwart complexity-based canonicalization 177 %neg = fsub float -0.000000e+00, %x 178 %div = fdiv float %neg, %y 179 call void @use(float %div) 180 %r = fadd float %z, %div 181 ret float %r 182} 183 184; Z + (Y / -X) - extra use means we can't transform to fsub without an extra instruction 185 186define float @fdiv_fneg2_extra_use(float %x, float %py, float %pz) { 187; CHECK-LABEL: @fdiv_fneg2_extra_use( 188; CHECK-NEXT: [[Y:%.*]] = frem float -4.200000e+01, [[PY:%.*]] 189; CHECK-NEXT: [[Z:%.*]] = frem float 4.200000e+01, [[PZ:%.*]] 190; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X:%.*]] 191; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[Y]], [[NEG]] 192; CHECK-NEXT: call void @use(float [[DIV]]) 193; CHECK-NEXT: [[R:%.*]] = fadd float [[Z]], [[DIV]] 194; CHECK-NEXT: ret float [[R]] 195; 196 %y = frem float -42.0, %py ; thwart complexity-based canonicalization 197 %z = frem float 42.0, %pz ; thwart complexity-based canonicalization 198 %neg = fsub float -0.000000e+00, %x 199 %div = fdiv float %y, %neg 200 call void @use(float %div) 201 %r = fadd float %z, %div 202 ret float %r 203} 204 205; Z + (-X * Y) - extra use means we can't transform to fsub without an extra instruction 206 207define <2 x float> @fmul_fneg1_extra_use(<2 x float> %x, <2 x float> %y, <2 x float> %pz) { 208; CHECK-LABEL: @fmul_fneg1_extra_use( 209; CHECK-NEXT: [[Z:%.*]] = frem <2 x float> <float 4.200000e+01, float -1.000000e+00>, [[PZ:%.*]] 210; CHECK-NEXT: [[NEG:%.*]] = fneg <2 x float> [[X:%.*]] 211; CHECK-NEXT: [[MUL:%.*]] = fmul <2 x float> [[Y:%.*]], [[NEG]] 212; CHECK-NEXT: call void @use_vec(<2 x float> [[MUL]]) 213; CHECK-NEXT: [[R:%.*]] = fadd <2 x float> [[Z]], [[MUL]] 214; CHECK-NEXT: ret <2 x float> [[R]] 215; 216 %z = frem <2 x float> <float 42.0, float -1.0>, %pz ; thwart complexity-based canonicalization 217 %neg = fsub <2 x float> <float -0.0, float -0.0>, %x 218 %mul = fmul <2 x float> %neg, %y 219 call void @use_vec(<2 x float> %mul) 220 %r = fadd <2 x float> %z, %mul 221 ret <2 x float> %r 222} 223 224; Z + (Y * -X) - extra use means we can't transform to fsub without an extra instruction 225 226define float @fmul_fneg2_extra_use(float %x, float %py, float %pz) { 227; CHECK-LABEL: @fmul_fneg2_extra_use( 228; CHECK-NEXT: [[Y:%.*]] = frem float -4.200000e+01, [[PY:%.*]] 229; CHECK-NEXT: [[Z:%.*]] = frem float 4.200000e+01, [[PZ:%.*]] 230; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X:%.*]] 231; CHECK-NEXT: [[MUL:%.*]] = fmul float [[Y]], [[NEG]] 232; CHECK-NEXT: call void @use(float [[MUL]]) 233; CHECK-NEXT: [[R:%.*]] = fadd float [[Z]], [[MUL]] 234; CHECK-NEXT: ret float [[R]] 235; 236 %y = frem float -42.0, %py ; thwart complexity-based canonicalization 237 %z = frem float 42.0, %pz ; thwart complexity-based canonicalization 238 %neg = fsub float -0.000000e+00, %x 239 %mul = fmul float %y, %neg 240 call void @use(float %mul) 241 %r = fadd float %z, %mul 242 ret float %r 243} 244 245; (-X / Y) + Z --> Z - (X / Y) 246 247define float @fdiv_fneg1_extra_use2(float %x, float %y, float %z) { 248; CHECK-LABEL: @fdiv_fneg1_extra_use2( 249; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X:%.*]] 250; CHECK-NEXT: call void @use(float [[NEG]]) 251; CHECK-NEXT: [[TMP1:%.*]] = fdiv float [[X]], [[Y:%.*]] 252; CHECK-NEXT: [[R:%.*]] = fsub float [[Z:%.*]], [[TMP1]] 253; CHECK-NEXT: ret float [[R]] 254; 255 %neg = fsub float -0.000000e+00, %x 256 call void @use(float %neg) 257 %div = fdiv float %neg, %y 258 %r = fadd float %div, %z 259 ret float %r 260} 261 262; (Y / -X) + Z --> Z - (Y / X) 263 264define float @fdiv_fneg2_extra_use2(float %x, float %y, float %z) { 265; CHECK-LABEL: @fdiv_fneg2_extra_use2( 266; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X:%.*]] 267; CHECK-NEXT: call void @use(float [[NEG]]) 268; CHECK-NEXT: [[TMP1:%.*]] = fdiv float [[Y:%.*]], [[X]] 269; CHECK-NEXT: [[R:%.*]] = fsub float [[Z:%.*]], [[TMP1]] 270; CHECK-NEXT: ret float [[R]] 271; 272 %neg = fsub float -0.000000e+00, %x 273 call void @use(float %neg) 274 %div = fdiv float %y, %neg 275 %r = fadd float %div, %z 276 ret float %r 277} 278 279; (-X * Y) + Z --> Z - (X * Y) 280 281define <2 x float> @fmul_fneg1_extra_use2(<2 x float> %x, <2 x float> %y, <2 x float> %z) { 282; CHECK-LABEL: @fmul_fneg1_extra_use2( 283; CHECK-NEXT: [[NEG:%.*]] = fneg <2 x float> [[X:%.*]] 284; CHECK-NEXT: call void @use_vec(<2 x float> [[NEG]]) 285; CHECK-NEXT: [[TMP1:%.*]] = fmul <2 x float> [[X]], [[Y:%.*]] 286; CHECK-NEXT: [[R:%.*]] = fsub <2 x float> [[Z:%.*]], [[TMP1]] 287; CHECK-NEXT: ret <2 x float> [[R]] 288; 289 %neg = fsub <2 x float> <float -0.0, float -0.0>, %x 290 call void @use_vec(<2 x float> %neg) 291 %mul = fmul <2 x float> %neg, %y 292 %r = fadd <2 x float> %mul, %z 293 ret <2 x float> %r 294} 295 296; (Y * -X) + Z --> Z - (Y * X) 297 298define float @fmul_fneg2_extra_use2(float %x, float %py, float %z) { 299; CHECK-LABEL: @fmul_fneg2_extra_use2( 300; CHECK-NEXT: [[Y:%.*]] = frem float -4.200000e+01, [[PY:%.*]] 301; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X:%.*]] 302; CHECK-NEXT: call void @use(float [[NEG]]) 303; CHECK-NEXT: [[TMP1:%.*]] = fmul float [[X]], [[Y]] 304; CHECK-NEXT: [[R:%.*]] = fsub float [[Z:%.*]], [[TMP1]] 305; CHECK-NEXT: ret float [[R]] 306; 307 %y = frem float -42.0, %py ; thwart complexity-based canonicalization 308 %neg = fsub float -0.000000e+00, %x 309 call void @use(float %neg) 310 %mul = fmul float %y, %neg 311 %r = fadd float %mul, %z 312 ret float %r 313} 314 315; (-X / Y) + Z --> Z - (X / Y) 316 317define float @fdiv_fneg1_extra_use3(float %x, float %y, float %z) { 318; CHECK-LABEL: @fdiv_fneg1_extra_use3( 319; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X:%.*]] 320; CHECK-NEXT: call void @use(float [[NEG]]) 321; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[NEG]], [[Y:%.*]] 322; CHECK-NEXT: call void @use(float [[DIV]]) 323; CHECK-NEXT: [[R:%.*]] = fadd float [[DIV]], [[Z:%.*]] 324; CHECK-NEXT: ret float [[R]] 325; 326 %neg = fsub float -0.000000e+00, %x 327 call void @use(float %neg) 328 %div = fdiv float %neg, %y 329 call void @use(float %div) 330 %r = fadd float %div, %z 331 ret float %r 332} 333 334; (Y / -X) + Z --> Z - (Y / X) 335 336define float @fdiv_fneg2_extra_use3(float %x, float %y, float %z) { 337; CHECK-LABEL: @fdiv_fneg2_extra_use3( 338; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X:%.*]] 339; CHECK-NEXT: call void @use(float [[NEG]]) 340; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[Y:%.*]], [[NEG]] 341; CHECK-NEXT: call void @use(float [[DIV]]) 342; CHECK-NEXT: [[R:%.*]] = fadd float [[DIV]], [[Z:%.*]] 343; CHECK-NEXT: ret float [[R]] 344; 345 %neg = fsub float -0.000000e+00, %x 346 call void @use(float %neg) 347 %div = fdiv float %y, %neg 348 call void @use(float %div) 349 %r = fadd float %div, %z 350 ret float %r 351} 352 353; (-X * Y) + Z --> Z - (X * Y) 354 355define <2 x float> @fmul_fneg1_extra_use3(<2 x float> %x, <2 x float> %y, <2 x float> %z) { 356; CHECK-LABEL: @fmul_fneg1_extra_use3( 357; CHECK-NEXT: [[NEG:%.*]] = fneg <2 x float> [[X:%.*]] 358; CHECK-NEXT: call void @use_vec(<2 x float> [[NEG]]) 359; CHECK-NEXT: [[MUL:%.*]] = fmul <2 x float> [[Y:%.*]], [[NEG]] 360; CHECK-NEXT: call void @use_vec(<2 x float> [[MUL]]) 361; CHECK-NEXT: [[R:%.*]] = fadd <2 x float> [[MUL]], [[Z:%.*]] 362; CHECK-NEXT: ret <2 x float> [[R]] 363; 364 %neg = fsub <2 x float> <float -0.0, float -0.0>, %x 365 call void @use_vec(<2 x float> %neg) 366 %mul = fmul <2 x float> %neg, %y 367 call void @use_vec(<2 x float> %mul) 368 %r = fadd <2 x float> %mul, %z 369 ret <2 x float> %r 370} 371 372; (Y * -X) + Z --> Z - (Y * X) 373 374define float @fmul_fneg2_extra_use3(float %x, float %py, float %z) { 375; CHECK-LABEL: @fmul_fneg2_extra_use3( 376; CHECK-NEXT: [[Y:%.*]] = frem float -4.200000e+01, [[PY:%.*]] 377; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X:%.*]] 378; CHECK-NEXT: call void @use(float [[NEG]]) 379; CHECK-NEXT: [[MUL:%.*]] = fmul float [[Y]], [[NEG]] 380; CHECK-NEXT: call void @use(float [[MUL]]) 381; CHECK-NEXT: [[R:%.*]] = fadd float [[MUL]], [[Z:%.*]] 382; CHECK-NEXT: ret float [[R]] 383; 384 %y = frem float -42.0, %py ; thwart complexity-based canonicalization 385 %neg = fsub float -0.000000e+00, %x 386 call void @use(float %neg) 387 %mul = fmul float %y, %neg 388 call void @use(float %mul) 389 %r = fadd float %mul, %z 390 ret float %r 391} 392 393define float @fadd_rdx(float %x, <4 x float> %v) { 394; CHECK-LABEL: @fadd_rdx( 395; CHECK-NEXT: [[ADD:%.*]] = call fast float @llvm.vector.reduce.fadd.v4f32(float [[X:%.*]], <4 x float> [[V:%.*]]) 396; CHECK-NEXT: ret float [[ADD]] 397; 398 %rdx = call fast float @llvm.vector.reduce.fadd.v4f32(float 0.0, <4 x float> %v) 399 %add = fadd fast float %rdx, %x 400 ret float %add 401} 402 403define float @fadd_rdx_commute(float %x, <4 x float> %v) { 404; CHECK-LABEL: @fadd_rdx_commute( 405; CHECK-NEXT: [[D:%.*]] = fdiv float 4.200000e+01, [[X:%.*]] 406; CHECK-NEXT: [[ADD:%.*]] = call reassoc nsz float @llvm.vector.reduce.fadd.v4f32(float [[D]], <4 x float> [[V:%.*]]) 407; CHECK-NEXT: ret float [[ADD]] 408; 409 %d = fdiv float 42.0, %x 410 %rdx = call float @llvm.vector.reduce.fadd.v4f32(float -0.0, <4 x float> %v) 411 %add = fadd reassoc nsz float %d, %rdx 412 ret float %add 413} 414 415; Negative test - require nsz to be safer (and reassoc obviously). 416 417define float @fadd_rdx_fmf(float %x, <4 x float> %v) { 418; CHECK-LABEL: @fadd_rdx_fmf( 419; CHECK-NEXT: [[RDX:%.*]] = call float @llvm.vector.reduce.fadd.v4f32(float 0.000000e+00, <4 x float> [[V:%.*]]) 420; CHECK-NEXT: [[ADD:%.*]] = fadd reassoc float [[RDX]], [[X:%.*]] 421; CHECK-NEXT: ret float [[ADD]] 422; 423 %rdx = call float @llvm.vector.reduce.fadd.v4f32(float 0.0, <4 x float> %v) 424 %add = fadd reassoc float %rdx, %x 425 ret float %add 426} 427 428; Negative test - don't replace a single add with another reduction. 429 430define float @fadd_rdx_extra_use(float %x, <4 x float> %v) { 431; CHECK-LABEL: @fadd_rdx_extra_use( 432; CHECK-NEXT: [[RDX:%.*]] = call float @llvm.vector.reduce.fadd.v4f32(float 0.000000e+00, <4 x float> [[V:%.*]]) 433; CHECK-NEXT: call void @use(float [[RDX]]) 434; CHECK-NEXT: [[ADD:%.*]] = fadd fast float [[RDX]], [[X:%.*]] 435; CHECK-NEXT: ret float [[ADD]] 436; 437 %rdx = call float @llvm.vector.reduce.fadd.v4f32(float 0.0, <4 x float> %v) 438 call void @use(float %rdx) 439 %add = fadd fast float %rdx, %x 440 ret float %add 441} 442 443define float @fadd_rdx_nonzero_start_const_op(<4 x float> %v) { 444; CHECK-LABEL: @fadd_rdx_nonzero_start_const_op( 445; CHECK-NEXT: [[ADD:%.*]] = call reassoc ninf nsz float @llvm.vector.reduce.fadd.v4f32(float 3.300000e+01, <4 x float> [[V:%.*]]) 446; CHECK-NEXT: ret float [[ADD]] 447; 448 %rdx = call float @llvm.vector.reduce.fadd.v4f32(float 42.0, <4 x float> %v) 449 %add = fadd reassoc nsz ninf float %rdx, -9.0 450 ret float %add 451} 452 453; Negative test - we don't change the order of ops unless it saves an instruction. 454 455define float @fadd_rdx_nonzero_start_variable_op(float %x, <4 x float> %v) { 456; CHECK-LABEL: @fadd_rdx_nonzero_start_variable_op( 457; CHECK-NEXT: [[RDX:%.*]] = call float @llvm.vector.reduce.fadd.v4f32(float 4.200000e+01, <4 x float> [[V:%.*]]) 458; CHECK-NEXT: [[ADD:%.*]] = fadd fast float [[RDX]], [[X:%.*]] 459; CHECK-NEXT: ret float [[ADD]] 460; 461 %rdx = call float @llvm.vector.reduce.fadd.v4f32(float 42.0, <4 x float> %v) 462 %add = fadd fast float %rdx, %x 463 ret float %add 464} 465 466; (X * C) + X --> X * (C + 1) 467 468define float @fadd_fmul_common_op(float %x) { 469; CHECK-LABEL: @fadd_fmul_common_op( 470; CHECK-NEXT: [[A:%.*]] = fmul reassoc nsz float [[X:%.*]], 4.300000e+01 471; CHECK-NEXT: ret float [[A]] 472; 473 %m = fmul reassoc nsz float %x, 42.0 474 %a = fadd reassoc nsz float %m, %x 475 ret float %a 476} 477 478; Splat constant is ok. 479 480define <2 x float> @fadd_fmul_common_op_vec(<2 x float> %x) { 481; CHECK-LABEL: @fadd_fmul_common_op_vec( 482; CHECK-NEXT: [[A:%.*]] = fmul reassoc nsz <2 x float> [[X:%.*]], splat (float 4.300000e+01) 483; CHECK-NEXT: ret <2 x float> [[A]] 484; 485 %m = fmul reassoc nsz <2 x float> %x, <float 42.0, float 42.0> 486 %a = fadd reassoc nsz <2 x float> %m, %x 487 ret <2 x float> %a 488} 489 490; Non-splat constant is ok. 491 492define <2 x float> @fadd_fmul_common_op_commute_vec(<2 x float> %px) { 493; CHECK-LABEL: @fadd_fmul_common_op_commute_vec( 494; CHECK-NEXT: [[X:%.*]] = fmul <2 x float> [[PX:%.*]], [[PX]] 495; CHECK-NEXT: [[A:%.*]] = fmul reassoc nsz <2 x float> [[X]], <float 4.300000e+01, float -4.200000e+01> 496; CHECK-NEXT: ret <2 x float> [[A]] 497; 498 %x = fmul <2 x float> %px, %px ; thwart complexity-based canonicalization 499 %m = fmul reassoc nsz <2 x float> %x, <float 42.0, float -43.0> 500 %a = fadd reassoc nsz <2 x float> %x, %m 501 ret <2 x float> %a 502} 503 504; Extra use is ok. 505 506define float @fadd_fmul_common_op_use(float %x) { 507; CHECK-LABEL: @fadd_fmul_common_op_use( 508; CHECK-NEXT: [[M:%.*]] = fmul reassoc nsz float [[X:%.*]], 4.200000e+01 509; CHECK-NEXT: call void @use(float [[M]]) 510; CHECK-NEXT: [[A:%.*]] = fmul reassoc nsz float [[X]], 4.300000e+01 511; CHECK-NEXT: ret float [[A]] 512; 513 %m = fmul reassoc nsz float %x, 42.0 514 call void @use(float %m) 515 %a = fadd reassoc nsz float %m, %x 516 ret float %a 517} 518 519; Negative test - must have 'reassoc' FMF 520 521define float @fadd_fmul_common_op_wrong_fmf(float %x) { 522; CHECK-LABEL: @fadd_fmul_common_op_wrong_fmf( 523; CHECK-NEXT: [[M:%.*]] = fmul ninf nsz float [[X:%.*]], 4.200000e+01 524; CHECK-NEXT: [[A:%.*]] = fadd ninf nsz float [[M]], [[X]] 525; CHECK-NEXT: ret float [[A]] 526; 527 %m = fmul ninf nsz float %x, 42.0 528 %a = fadd ninf nsz float %m, %x 529 ret float %a 530} 531 532; (-x - y) + (x + z) --> z - y 533 534define float @fadd_fneg_reass_commute0(float %x, float %y, float %z) { 535; CHECK-LABEL: @fadd_fneg_reass_commute0( 536; CHECK-NEXT: [[N:%.*]] = fneg reassoc nsz float [[X:%.*]] 537; CHECK-NEXT: call void @use(float [[N]]) 538; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz float [[Z:%.*]], [[Y:%.*]] 539; CHECK-NEXT: ret float [[R]] 540; 541 %n = fneg reassoc nsz float %x 542 call void @use(float %n) 543 %s = fsub reassoc nsz float %n, %y 544 %a = fadd reassoc nsz float %x, %z 545 %r = fadd reassoc nsz float %s, %a 546 ret float %r 547} 548 549define float @fadd_fneg_reass_commute1(float %x, float %y, float %z) { 550; CHECK-LABEL: @fadd_fneg_reass_commute1( 551; CHECK-NEXT: [[N:%.*]] = fneg float [[X:%.*]] 552; CHECK-NEXT: call void @use(float [[N]]) 553; CHECK-NEXT: [[S:%.*]] = fsub float [[N]], [[Y:%.*]] 554; CHECK-NEXT: call void @use(float [[S]]) 555; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz float [[Z:%.*]], [[Y]] 556; CHECK-NEXT: ret float [[R]] 557; 558 %n = fneg float %x 559 call void @use(float %n) 560 %s = fsub float %n, %y 561 call void @use(float %s) 562 %a = fadd float %x, %z 563 %r = fadd reassoc nsz float %a, %s 564 ret float %r 565} 566 567define float @fadd_fneg_reass_commute2(float %x, float %y, float %z) { 568; CHECK-LABEL: @fadd_fneg_reass_commute2( 569; CHECK-NEXT: [[N:%.*]] = fneg float [[X:%.*]] 570; CHECK-NEXT: call void @use(float [[N]]) 571; CHECK-NEXT: [[S:%.*]] = fsub float [[N]], [[Y:%.*]] 572; CHECK-NEXT: call void @use(float [[S]]) 573; CHECK-NEXT: [[A:%.*]] = fadd float [[Z:%.*]], [[X]] 574; CHECK-NEXT: call void @use(float [[A]]) 575; CHECK-NEXT: [[R:%.*]] = fsub fast float [[Z]], [[Y]] 576; CHECK-NEXT: ret float [[R]] 577; 578 %n = fneg float %x 579 call void @use(float %n) 580 %s = fsub float %n, %y 581 call void @use(float %s) 582 %a = fadd float %z, %x 583 call void @use(float %a) 584 %r = fadd fast float %s, %a 585 ret float %r 586} 587 588define <2 x float> @fadd_fneg_reass_commute3(<2 x float> %x, <2 x float> %y, <2 x float> %z) { 589; CHECK-LABEL: @fadd_fneg_reass_commute3( 590; CHECK-NEXT: [[N:%.*]] = fneg reassoc nsz <2 x float> [[X:%.*]] 591; CHECK-NEXT: call void @use_vec(<2 x float> [[N]]) 592; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz <2 x float> [[Z:%.*]], [[Y:%.*]] 593; CHECK-NEXT: ret <2 x float> [[R]] 594; 595 %n = fneg reassoc nsz <2 x float> %x 596 call void @use_vec(<2 x float> %n) 597 %s = fsub reassoc nsz <2 x float> %n, %y 598 %a = fadd reassoc nsz <2 x float> %z, %x 599 %r = fadd reassoc nsz <2 x float> %a, %s 600 ret <2 x float> %r 601} 602 603; negative test - need reassoc (+ nsz) 604 605define float @fadd_fneg_commute0(float %x, float %y, float %z) { 606; CHECK-LABEL: @fadd_fneg_commute0( 607; CHECK-NEXT: [[N:%.*]] = fneg float [[X:%.*]] 608; CHECK-NEXT: call void @use(float [[N]]) 609; CHECK-NEXT: [[S:%.*]] = fsub float [[N]], [[Y:%.*]] 610; CHECK-NEXT: [[A:%.*]] = fadd float [[X]], [[Z:%.*]] 611; CHECK-NEXT: [[R:%.*]] = fadd nsz float [[S]], [[A]] 612; CHECK-NEXT: ret float [[R]] 613; 614 %n = fneg float %x 615 call void @use(float %n) 616 %s = fsub float %n, %y 617 %a = fadd float %x, %z 618 %r = fadd nsz float %s, %a 619 ret float %r 620} 621 622define float @fadd_reduce_sqr_sum_varA(float %a, float %b) { 623; CHECK-LABEL: @fadd_reduce_sqr_sum_varA( 624; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[A:%.*]], [[B:%.*]] 625; CHECK-NEXT: [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]] 626; CHECK-NEXT: ret float [[ADD]] 627; 628 %a_sq = fmul float %a, %a 629 %two_a = fmul float %a, 2.0 630 %two_a_plus_b = fadd float %two_a, %b 631 %mul = fmul float %two_a_plus_b, %b 632 %add = fadd reassoc nsz float %mul, %a_sq 633 ret float %add 634} 635 636define float @fadd_reduce_sqr_sum_varA_order2(float %a, float %b) { 637; CHECK-LABEL: @fadd_reduce_sqr_sum_varA_order2( 638; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[A:%.*]], [[B:%.*]] 639; CHECK-NEXT: [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]] 640; CHECK-NEXT: ret float [[ADD]] 641; 642 %a_sq = fmul float %a, %a 643 %two_a = fmul float %a, 2.0 644 %two_a_plus_b = fadd float %two_a, %b 645 %mul = fmul float %two_a_plus_b, %b 646 %add = fadd reassoc nsz float %a_sq, %mul 647 ret float %add 648} 649 650define float @fadd_reduce_sqr_sum_varA_order3(float %a, float %b) { 651; CHECK-LABEL: @fadd_reduce_sqr_sum_varA_order3( 652; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[A:%.*]], [[B:%.*]] 653; CHECK-NEXT: [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]] 654; CHECK-NEXT: ret float [[ADD]] 655; 656 %a_sq = fmul float %a, %a 657 %two_a = fmul float %a, 2.0 658 %two_a_plus_b = fadd float %two_a, %b 659 %mul = fmul float %b, %two_a_plus_b 660 %add = fadd reassoc nsz float %mul, %a_sq 661 ret float %add 662} 663 664define float @fadd_reduce_sqr_sum_varA_order4(float %a, float %b) { 665; CHECK-LABEL: @fadd_reduce_sqr_sum_varA_order4( 666; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[A:%.*]], [[B:%.*]] 667; CHECK-NEXT: [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]] 668; CHECK-NEXT: ret float [[ADD]] 669; 670 %a_sq = fmul float %a, %a 671 %two_a = fmul float %a, 2.0 672 %two_a_plus_b = fadd float %b, %two_a 673 %mul = fmul float %two_a_plus_b, %b 674 %add = fadd reassoc nsz float %mul, %a_sq 675 ret float %add 676} 677 678define float @fadd_reduce_sqr_sum_varA_order5(float %a, float %b) { 679; CHECK-LABEL: @fadd_reduce_sqr_sum_varA_order5( 680; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[A:%.*]], [[B:%.*]] 681; CHECK-NEXT: [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]] 682; CHECK-NEXT: ret float [[ADD]] 683; 684 %a_sq = fmul float %a, %a 685 %two_a = fmul float 2.0, %a 686 %two_a_plus_b = fadd float %two_a, %b 687 %mul = fmul float %two_a_plus_b, %b 688 %add = fadd reassoc nsz float %mul, %a_sq 689 ret float %add 690} 691 692define float @fadd_reduce_sqr_sum_varB(float %a, float %b) { 693; CHECK-LABEL: @fadd_reduce_sqr_sum_varB( 694; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[A:%.*]], [[B:%.*]] 695; CHECK-NEXT: [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]] 696; CHECK-NEXT: ret float [[ADD]] 697; 698 %a_b = fmul float %a, %b 699 %a_b_2 = fmul float %a_b, 2.0 700 %a_sq = fmul float %a, %a 701 %b_sq = fmul float %b, %b 702 %a_sq_b_sq = fadd float %a_sq, %b_sq 703 %add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq 704 ret float %add 705} 706 707define float @fadd_reduce_sqr_sum_varB_order1(float %a, float %b) { 708; CHECK-LABEL: @fadd_reduce_sqr_sum_varB_order1( 709; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[A:%.*]], [[B:%.*]] 710; CHECK-NEXT: [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]] 711; CHECK-NEXT: ret float [[ADD]] 712; 713 %a_b = fmul float %a, %b 714 %a_b_2 = fmul float %a_b, 2.0 715 %a_sq = fmul float %a, %a 716 %b_sq = fmul float %b, %b 717 %a_sq_b_sq = fadd float %a_sq, %b_sq 718 %add = fadd reassoc nsz float %a_sq_b_sq, %a_b_2 719 ret float %add 720} 721 722define float @fadd_reduce_sqr_sum_varB_order2(float %a, float %b) { 723; CHECK-LABEL: @fadd_reduce_sqr_sum_varB_order2( 724; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[A:%.*]], [[B:%.*]] 725; CHECK-NEXT: [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]] 726; CHECK-NEXT: ret float [[ADD]] 727; 728 %a_b = fmul float %a, %b 729 %a_b_2 = fmul float %a_b, 2.0 730 %a_sq = fmul float %a, %a 731 %b_sq = fmul float %b, %b 732 %a_sq_b_sq = fadd float %b_sq, %a_sq 733 %add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq 734 ret float %add 735} 736 737define float @fadd_reduce_sqr_sum_varB_order3(float %a, float %b) { 738; CHECK-LABEL: @fadd_reduce_sqr_sum_varB_order3( 739; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[B:%.*]], [[A:%.*]] 740; CHECK-NEXT: [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]] 741; CHECK-NEXT: ret float [[ADD]] 742; 743 %a_b = fmul float %b, %a 744 %a_b_2 = fmul float 2.0, %a_b 745 %a_sq = fmul float %a, %a 746 %b_sq = fmul float %b, %b 747 %a_sq_b_sq = fadd float %a_sq, %b_sq 748 %add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq 749 ret float %add 750} 751 752define float @fadd_reduce_sqr_sum_varB2(float %a, float %b) { 753; CHECK-LABEL: @fadd_reduce_sqr_sum_varB2( 754; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[A:%.*]], [[B:%.*]] 755; CHECK-NEXT: [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]] 756; CHECK-NEXT: ret float [[ADD]] 757; 758 %a_2 = fmul float %a, 2.0 759 %a_b_2 = fmul float %a_2, %b 760 %a_sq = fmul float %a, %a 761 %b_sq = fmul float %b, %b 762 %a_sq_b_sq = fadd float %a_sq, %b_sq 763 %add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq 764 ret float %add 765} 766 767define float @fadd_reduce_sqr_sum_varB2_order1(float %a, float %b) { 768; CHECK-LABEL: @fadd_reduce_sqr_sum_varB2_order1( 769; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[A:%.*]], [[B:%.*]] 770; CHECK-NEXT: [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]] 771; CHECK-NEXT: ret float [[ADD]] 772; 773 %a_2 = fmul float %a, 2.0 774 %a_b_2 = fmul float %a_2, %b 775 %a_sq = fmul float %a, %a 776 %b_sq = fmul float %b, %b 777 %a_sq_b_sq = fadd float %a_sq, %b_sq 778 %add = fadd reassoc nsz float %a_sq_b_sq, %a_b_2 779 ret float %add 780} 781 782define float @fadd_reduce_sqr_sum_varB2_order2(float %a, float %b) { 783; CHECK-LABEL: @fadd_reduce_sqr_sum_varB2_order2( 784; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[A:%.*]], [[B:%.*]] 785; CHECK-NEXT: [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]] 786; CHECK-NEXT: ret float [[ADD]] 787; 788 %a_2 = fmul float %a, 2.0 789 %a_b_2 = fmul float %b, %a_2 790 %a_sq = fmul float %a, %a 791 %b_sq = fmul float %b, %b 792 %a_sq_b_sq = fadd float %a_sq, %b_sq 793 %add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq 794 ret float %add 795} 796 797define float @fadd_reduce_sqr_sum_varB2_order3(float %a, float %b) { 798; CHECK-LABEL: @fadd_reduce_sqr_sum_varB2_order3( 799; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[A:%.*]], [[B:%.*]] 800; CHECK-NEXT: [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]] 801; CHECK-NEXT: ret float [[ADD]] 802; 803 %a_2 = fmul float 2.0, %a 804 %a_b_2 = fmul float %a_2, %b 805 %a_sq = fmul float %a, %a 806 %b_sq = fmul float %b, %b 807 %a_sq_b_sq = fadd float %a_sq, %b_sq 808 %add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq 809 ret float %add 810} 811 812define float @fadd_reduce_sqr_sum_varA_not_one_use1(float %a, float %b) { 813; CHECK-LABEL: @fadd_reduce_sqr_sum_varA_not_one_use1( 814; CHECK-NEXT: [[A_SQ:%.*]] = fmul float [[A:%.*]], [[A]] 815; CHECK-NEXT: [[TWO_A:%.*]] = fmul float [[A]], 2.000000e+00 816; CHECK-NEXT: [[TWO_A_PLUS_B:%.*]] = fadd float [[TWO_A]], [[B:%.*]] 817; CHECK-NEXT: [[MUL:%.*]] = fmul float [[TWO_A_PLUS_B]], [[B]] 818; CHECK-NEXT: [[ADD:%.*]] = fadd reassoc nsz float [[MUL]], [[A_SQ]] 819; CHECK-NEXT: tail call void @fake_func(float [[MUL]]) 820; CHECK-NEXT: ret float [[ADD]] 821; 822 %a_sq = fmul float %a, %a 823 %two_a = fmul float %a, 2.0 824 %two_a_plus_b = fadd float %two_a, %b 825 %mul = fmul float %two_a_plus_b, %b 826 %add = fadd reassoc nsz float %mul, %a_sq 827 tail call void @fake_func (float %mul) 828 ret float %add 829} 830 831define float @fadd_reduce_sqr_sum_varA_not_one_use2(float %a, float %b) { 832; CHECK-LABEL: @fadd_reduce_sqr_sum_varA_not_one_use2( 833; CHECK-NEXT: [[A_SQ:%.*]] = fmul float [[A:%.*]], [[A]] 834; CHECK-NEXT: [[TWO_A:%.*]] = fmul float [[A]], 2.000000e+00 835; CHECK-NEXT: [[TWO_A_PLUS_B:%.*]] = fadd float [[TWO_A]], [[B:%.*]] 836; CHECK-NEXT: [[MUL:%.*]] = fmul float [[TWO_A_PLUS_B]], [[B]] 837; CHECK-NEXT: [[ADD:%.*]] = fadd reassoc nsz float [[MUL]], [[A_SQ]] 838; CHECK-NEXT: tail call void @fake_func(float [[A_SQ]]) 839; CHECK-NEXT: ret float [[ADD]] 840; 841 %a_sq = fmul float %a, %a 842 %two_a = fmul float %a, 2.0 843 %two_a_plus_b = fadd float %two_a, %b 844 %mul = fmul float %two_a_plus_b, %b 845 %add = fadd reassoc nsz float %mul, %a_sq 846 tail call void @fake_func (float %a_sq) 847 ret float %add 848} 849 850define float @fadd_reduce_sqr_sum_varB_not_one_use1(float %a, float %b) { 851; CHECK-LABEL: @fadd_reduce_sqr_sum_varB_not_one_use1( 852; CHECK-NEXT: [[A_B:%.*]] = fmul float [[A:%.*]], [[B:%.*]] 853; CHECK-NEXT: [[A_B_2:%.*]] = fmul float [[A_B]], 2.000000e+00 854; CHECK-NEXT: [[A_SQ:%.*]] = fmul float [[A]], [[A]] 855; CHECK-NEXT: [[B_SQ:%.*]] = fmul float [[B]], [[B]] 856; CHECK-NEXT: [[A_SQ_B_SQ:%.*]] = fadd float [[A_SQ]], [[B_SQ]] 857; CHECK-NEXT: [[ADD:%.*]] = fadd reassoc nsz float [[A_B_2]], [[A_SQ_B_SQ]] 858; CHECK-NEXT: tail call void @fake_func(float [[A_B_2]]) 859; CHECK-NEXT: ret float [[ADD]] 860; 861 %a_b = fmul float %a, %b 862 %a_b_2 = fmul float %a_b, 2.0 863 %a_sq = fmul float %a, %a 864 %b_sq = fmul float %b, %b 865 %a_sq_b_sq = fadd float %a_sq, %b_sq 866 %add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq 867 tail call void @fake_func (float %a_b_2) 868 ret float %add 869} 870 871define float @fadd_reduce_sqr_sum_varB_not_one_use2(float %a, float %b) { 872; CHECK-LABEL: @fadd_reduce_sqr_sum_varB_not_one_use2( 873; CHECK-NEXT: [[A_B:%.*]] = fmul float [[A:%.*]], [[B:%.*]] 874; CHECK-NEXT: [[A_B_2:%.*]] = fmul float [[A_B]], 2.000000e+00 875; CHECK-NEXT: [[A_SQ:%.*]] = fmul float [[A]], [[A]] 876; CHECK-NEXT: [[B_SQ:%.*]] = fmul float [[B]], [[B]] 877; CHECK-NEXT: [[A_SQ_B_SQ:%.*]] = fadd float [[A_SQ]], [[B_SQ]] 878; CHECK-NEXT: [[ADD:%.*]] = fadd reassoc nsz float [[A_B_2]], [[A_SQ_B_SQ]] 879; CHECK-NEXT: tail call void @fake_func(float [[A_SQ_B_SQ]]) 880; CHECK-NEXT: ret float [[ADD]] 881; 882 %a_b = fmul float %a, %b 883 %a_b_2 = fmul float %a_b, 2.0 884 %a_sq = fmul float %a, %a 885 %b_sq = fmul float %b, %b 886 %a_sq_b_sq = fadd float %a_sq, %b_sq 887 %add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq 888 tail call void @fake_func (float %a_sq_b_sq) 889 ret float %add 890} 891 892define float @fadd_reduce_sqr_sum_varB2_not_one_use(float %a, float %b) { 893; CHECK-LABEL: @fadd_reduce_sqr_sum_varB2_not_one_use( 894; CHECK-NEXT: [[A_2:%.*]] = fmul float [[A:%.*]], 2.000000e+00 895; CHECK-NEXT: [[A_B_2:%.*]] = fmul float [[A_2]], [[B:%.*]] 896; CHECK-NEXT: [[A_SQ:%.*]] = fmul float [[A]], [[A]] 897; CHECK-NEXT: [[B_SQ:%.*]] = fmul float [[B]], [[B]] 898; CHECK-NEXT: [[A_SQ_B_SQ:%.*]] = fadd float [[A_SQ]], [[B_SQ]] 899; CHECK-NEXT: [[ADD:%.*]] = fadd reassoc nsz float [[A_B_2]], [[A_SQ_B_SQ]] 900; CHECK-NEXT: tail call void @fake_func(float [[A_B_2]]) 901; CHECK-NEXT: ret float [[ADD]] 902; 903 %a_2 = fmul float %a, 2.0 904 %a_b_2 = fmul float %a_2, %b 905 %a_sq = fmul float %a, %a 906 %b_sq = fmul float %b, %b 907 %a_sq_b_sq = fadd float %a_sq, %b_sq 908 %add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq 909 tail call void @fake_func (float %a_b_2) 910 ret float %add 911} 912 913define float @fadd_reduce_sqr_sum_varA_invalid1(float %a, float %b) { 914; CHECK-LABEL: @fadd_reduce_sqr_sum_varA_invalid1( 915; CHECK-NEXT: [[TWO_A:%.*]] = fmul float [[A:%.*]], 2.000000e+00 916; CHECK-NEXT: [[TWO_A_PLUS_B:%.*]] = fadd float [[TWO_A]], [[B:%.*]] 917; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[TWO_A_PLUS_B]], [[A]] 918; CHECK-NEXT: [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[A]] 919; CHECK-NEXT: ret float [[ADD]] 920; 921 %a_sq = fmul float %a, %a 922 %two_a = fmul float %a, 2.0 923 %two_a_plus_b = fadd float %two_a, %b 924 %mul = fmul float %two_a_plus_b, %a 925 %add = fadd reassoc nsz float %mul, %a_sq 926 ret float %add 927} 928 929define float @fadd_reduce_sqr_sum_varA_invalid2(float %a, float %b) { 930; CHECK-LABEL: @fadd_reduce_sqr_sum_varA_invalid2( 931; CHECK-NEXT: [[A_SQ:%.*]] = fmul float [[A:%.*]], [[A]] 932; CHECK-NEXT: [[TWO_A:%.*]] = fmul float [[A]], 2.000000e+00 933; CHECK-NEXT: [[NOT_TWO_A_PLUS_B:%.*]] = fadd float [[TWO_A]], [[A]] 934; CHECK-NEXT: [[MUL:%.*]] = fmul float [[NOT_TWO_A_PLUS_B]], [[B:%.*]] 935; CHECK-NEXT: [[ADD:%.*]] = fadd reassoc nsz float [[MUL]], [[A_SQ]] 936; CHECK-NEXT: ret float [[ADD]] 937; 938 %a_sq = fmul float %a, %a 939 %two_a = fmul float %a, 2.0 940 %not_two_a_plus_b = fadd float %two_a, %a 941 %mul = fmul float %not_two_a_plus_b, %b 942 %add = fadd reassoc nsz float %mul, %a_sq 943 ret float %add 944} 945 946define float @fadd_reduce_sqr_sum_varA_invalid3(float %a, float %b) { 947; CHECK-LABEL: @fadd_reduce_sqr_sum_varA_invalid3( 948; CHECK-NEXT: [[A_SQ:%.*]] = fmul float [[A:%.*]], [[A]] 949; CHECK-NEXT: [[NOT_TWO_A:%.*]] = fmul float [[A]], 0x4000CCCCC0000000 950; CHECK-NEXT: [[TWO_A_PLUS_B:%.*]] = fadd float [[NOT_TWO_A]], [[B:%.*]] 951; CHECK-NEXT: [[MUL:%.*]] = fmul float [[TWO_A_PLUS_B]], [[B]] 952; CHECK-NEXT: [[ADD:%.*]] = fadd reassoc nsz float [[MUL]], [[A_SQ]] 953; CHECK-NEXT: ret float [[ADD]] 954; 955 %a_sq = fmul float %a, %a 956 %not_two_a = fmul float %a, 0x4000CCCCC0000000 ; 2.1 957 %two_a_plus_b = fadd float %not_two_a, %b 958 %mul = fmul float %two_a_plus_b, %b 959 %add = fadd reassoc nsz float %mul, %a_sq 960 ret float %add 961} 962 963define float @fadd_reduce_sqr_sum_varA_invalid4(float %a, float %b) { 964; CHECK-LABEL: @fadd_reduce_sqr_sum_varA_invalid4( 965; CHECK-NEXT: [[A_SQ:%.*]] = fmul float [[A:%.*]], [[A]] 966; CHECK-NEXT: [[NOT_TWO_A:%.*]] = fmul float [[B:%.*]], 2.000000e+00 967; CHECK-NEXT: [[TWO_A_PLUS_B:%.*]] = fadd float [[NOT_TWO_A]], [[B]] 968; CHECK-NEXT: [[MUL:%.*]] = fmul float [[TWO_A_PLUS_B]], [[B]] 969; CHECK-NEXT: [[ADD:%.*]] = fadd reassoc nsz float [[MUL]], [[A_SQ]] 970; CHECK-NEXT: ret float [[ADD]] 971; 972 %a_sq = fmul float %a, %a 973 %not_two_a = fmul float %b, 2.0 974 %two_a_plus_b = fadd float %not_two_a, %b 975 %mul = fmul float %two_a_plus_b, %b 976 %add = fadd reassoc nsz float %mul, %a_sq 977 ret float %add 978} 979 980define float @fadd_reduce_sqr_sum_varA_invalid5(float %a, float %b) { 981; CHECK-LABEL: @fadd_reduce_sqr_sum_varA_invalid5( 982; CHECK-NEXT: [[TWO_A:%.*]] = fmul float [[A:%.*]], 2.000000e+00 983; CHECK-NEXT: [[TWO_A_PLUS_B:%.*]] = fadd float [[TWO_A]], [[B:%.*]] 984; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[TWO_A_PLUS_B]], [[A]] 985; CHECK-NEXT: [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[B]] 986; CHECK-NEXT: ret float [[ADD]] 987; 988 %not_a_sq = fmul float %a, %b 989 %two_a = fmul float %a, 2.0 990 %two_a_plus_b = fadd float %two_a, %b 991 %mul = fmul float %two_a_plus_b, %b 992 %add = fadd reassoc nsz float %mul, %not_a_sq 993 ret float %add 994} 995 996define float @fadd_reduce_sqr_sum_varB_invalid1(float %a, float %b) { 997; CHECK-LABEL: @fadd_reduce_sqr_sum_varB_invalid1( 998; CHECK-NEXT: [[A_B:%.*]] = fmul float [[A:%.*]], [[B:%.*]] 999; CHECK-NEXT: [[A_B_2:%.*]] = fmul float [[A_B]], 2.000000e+00 1000; CHECK-NEXT: [[A_SQ:%.*]] = fmul float [[A]], [[A]] 1001; CHECK-NEXT: [[NOT_B_SQ:%.*]] = fmul float [[B]], [[A]] 1002; CHECK-NEXT: [[A_SQ_B_SQ:%.*]] = fadd float [[A_SQ]], [[NOT_B_SQ]] 1003; CHECK-NEXT: [[ADD:%.*]] = fadd reassoc nsz float [[A_B_2]], [[A_SQ_B_SQ]] 1004; CHECK-NEXT: ret float [[ADD]] 1005; 1006 %a_b = fmul float %a, %b 1007 %a_b_2 = fmul float %a_b, 2.0 1008 %a_sq = fmul float %a, %a 1009 %not_b_sq = fmul float %b, %a 1010 %a_sq_b_sq = fadd float %a_sq, %not_b_sq 1011 %add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq 1012 ret float %add 1013} 1014 1015define float @fadd_reduce_sqr_sum_varB_invalid2(float %a, float %b) { 1016; CHECK-LABEL: @fadd_reduce_sqr_sum_varB_invalid2( 1017; CHECK-NEXT: [[A_B:%.*]] = fmul float [[A:%.*]], [[B:%.*]] 1018; CHECK-NEXT: [[A_B_2:%.*]] = fmul float [[A_B]], 2.000000e+00 1019; CHECK-NEXT: [[NOT_A_SQ:%.*]] = fmul float [[A]], [[B]] 1020; CHECK-NEXT: [[B_SQ:%.*]] = fmul float [[B]], [[B]] 1021; CHECK-NEXT: [[A_SQ_B_SQ:%.*]] = fadd float [[NOT_A_SQ]], [[B_SQ]] 1022; CHECK-NEXT: [[ADD:%.*]] = fadd reassoc nsz float [[A_B_2]], [[A_SQ_B_SQ]] 1023; CHECK-NEXT: ret float [[ADD]] 1024; 1025 %a_b = fmul float %a, %b 1026 %a_b_2 = fmul float %a_b, 2.0 1027 %not_a_sq = fmul float %a, %b 1028 %b_sq = fmul float %b, %b 1029 %a_sq_b_sq = fadd float %not_a_sq, %b_sq 1030 %add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq 1031 ret float %add 1032} 1033 1034define float @fadd_reduce_sqr_sum_varB_invalid3(float %a, float %b) { 1035; CHECK-LABEL: @fadd_reduce_sqr_sum_varB_invalid3( 1036; CHECK-NEXT: [[A_B:%.*]] = fmul float [[A:%.*]], [[B:%.*]] 1037; CHECK-NEXT: [[NOT_A_B_2:%.*]] = fmul float [[A_B]], 0x4000CCCCC0000000 1038; CHECK-NEXT: [[A_SQ:%.*]] = fmul float [[A]], [[A]] 1039; CHECK-NEXT: [[B_SQ:%.*]] = fmul float [[B]], [[B]] 1040; CHECK-NEXT: [[A_SQ_B_SQ:%.*]] = fadd float [[A_SQ]], [[B_SQ]] 1041; CHECK-NEXT: [[ADD:%.*]] = fadd reassoc nsz float [[NOT_A_B_2]], [[A_SQ_B_SQ]] 1042; CHECK-NEXT: ret float [[ADD]] 1043; 1044 %a_b = fmul float %a, %b 1045 %not_a_b_2 = fmul float %a_b, 0x4000CCCCC0000000 ; 2.1 1046 %a_sq = fmul float %a, %a 1047 %b_sq = fmul float %b, %b 1048 %a_sq_b_sq = fadd float %a_sq, %b_sq 1049 %add = fadd reassoc nsz float %not_a_b_2, %a_sq_b_sq 1050 ret float %add 1051} 1052 1053define float @fadd_reduce_sqr_sum_varB_invalid4(float %a, float %b) { 1054; CHECK-LABEL: @fadd_reduce_sqr_sum_varB_invalid4( 1055; CHECK-NEXT: [[NOT_A_B:%.*]] = fmul float [[A:%.*]], [[A]] 1056; CHECK-NEXT: [[A_B_2:%.*]] = fmul float [[NOT_A_B]], 2.000000e+00 1057; CHECK-NEXT: [[A_SQ:%.*]] = fmul float [[A]], [[A]] 1058; CHECK-NEXT: [[B_SQ:%.*]] = fmul float [[B:%.*]], [[B]] 1059; CHECK-NEXT: [[A_SQ_B_SQ:%.*]] = fadd float [[A_SQ]], [[B_SQ]] 1060; CHECK-NEXT: [[ADD:%.*]] = fadd reassoc nsz float [[A_B_2]], [[A_SQ_B_SQ]] 1061; CHECK-NEXT: ret float [[ADD]] 1062; 1063 %not_a_b = fmul float %a, %a 1064 %a_b_2 = fmul float %not_a_b, 2.0 1065 %a_sq = fmul float %a, %a 1066 %b_sq = fmul float %b, %b 1067 %a_sq_b_sq = fadd float %a_sq, %b_sq 1068 %add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq 1069 ret float %add 1070} 1071 1072define float @fadd_reduce_sqr_sum_varB_invalid5(float %a, float %b) { 1073; CHECK-LABEL: @fadd_reduce_sqr_sum_varB_invalid5( 1074; CHECK-NEXT: [[NOT_A_B:%.*]] = fmul float [[B:%.*]], [[B]] 1075; CHECK-NEXT: [[A_B_2:%.*]] = fmul float [[NOT_A_B]], 2.000000e+00 1076; CHECK-NEXT: [[A_SQ:%.*]] = fmul float [[A:%.*]], [[A]] 1077; CHECK-NEXT: [[B_SQ:%.*]] = fmul float [[B]], [[B]] 1078; CHECK-NEXT: [[A_SQ_B_SQ:%.*]] = fadd float [[A_SQ]], [[B_SQ]] 1079; CHECK-NEXT: [[ADD:%.*]] = fadd reassoc nsz float [[A_B_2]], [[A_SQ_B_SQ]] 1080; CHECK-NEXT: ret float [[ADD]] 1081; 1082 %not_a_b = fmul float %b, %b 1083 %a_b_2 = fmul float %not_a_b, 2.0 1084 %a_sq = fmul float %a, %a 1085 %b_sq = fmul float %b, %b 1086 %a_sq_b_sq = fadd float %a_sq, %b_sq 1087 %add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq 1088 ret float %add 1089} 1090 1091define float @fadd_reduce_sqr_sum_varB2_invalid1(float %a, float %b) { 1092; CHECK-LABEL: @fadd_reduce_sqr_sum_varB2_invalid1( 1093; CHECK-NEXT: [[A_2:%.*]] = fmul float [[A:%.*]], 2.000000e+00 1094; CHECK-NEXT: [[NOT_A_B_2:%.*]] = fmul float [[A_2]], [[A]] 1095; CHECK-NEXT: [[A_SQ:%.*]] = fmul float [[A]], [[A]] 1096; CHECK-NEXT: [[B_SQ:%.*]] = fmul float [[B:%.*]], [[B]] 1097; CHECK-NEXT: [[A_SQ_B_SQ:%.*]] = fadd float [[A_SQ]], [[B_SQ]] 1098; CHECK-NEXT: [[ADD:%.*]] = fadd reassoc nsz float [[NOT_A_B_2]], [[A_SQ_B_SQ]] 1099; CHECK-NEXT: ret float [[ADD]] 1100; 1101 %a_2 = fmul float %a, 2.0 1102 %not_a_b_2 = fmul float %a_2, %a 1103 %a_sq = fmul float %a, %a 1104 %b_sq = fmul float %b, %b 1105 %a_sq_b_sq = fadd float %a_sq, %b_sq 1106 %add = fadd reassoc nsz float %not_a_b_2, %a_sq_b_sq 1107 ret float %add 1108} 1109 1110define float @fadd_reduce_sqr_sum_varB2_invalid2(float %a, float %b) { 1111; CHECK-LABEL: @fadd_reduce_sqr_sum_varB2_invalid2( 1112; CHECK-NEXT: [[NOT_A_2:%.*]] = fmul float [[A:%.*]], 0x4000CCCCC0000000 1113; CHECK-NEXT: [[A_B_2:%.*]] = fmul float [[NOT_A_2]], [[B:%.*]] 1114; CHECK-NEXT: [[A_SQ:%.*]] = fmul float [[A]], [[A]] 1115; CHECK-NEXT: [[B_SQ:%.*]] = fmul float [[B]], [[B]] 1116; CHECK-NEXT: [[A_SQ_B_SQ:%.*]] = fadd float [[A_SQ]], [[B_SQ]] 1117; CHECK-NEXT: [[ADD:%.*]] = fadd reassoc nsz float [[A_B_2]], [[A_SQ_B_SQ]] 1118; CHECK-NEXT: ret float [[ADD]] 1119; 1120 %not_a_2 = fmul float %a, 0x4000CCCCC0000000 ; 2.1 1121 %a_b_2 = fmul float %not_a_2, %b 1122 %a_sq = fmul float %a, %a 1123 %b_sq = fmul float %b, %b 1124 %a_sq_b_sq = fadd float %a_sq, %b_sq 1125 %add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq 1126 ret float %add 1127} 1128 1129define float @fadd_reduce_sqr_sum_varB2_invalid3(float %a, float %b) { 1130; CHECK-LABEL: @fadd_reduce_sqr_sum_varB2_invalid3( 1131; CHECK-NEXT: [[NOT_A_2:%.*]] = fmul float [[B:%.*]], 2.000000e+00 1132; CHECK-NEXT: [[A_B_2:%.*]] = fmul float [[NOT_A_2]], [[B]] 1133; CHECK-NEXT: [[A_SQ:%.*]] = fmul float [[A:%.*]], [[A]] 1134; CHECK-NEXT: [[B_SQ:%.*]] = fmul float [[B]], [[B]] 1135; CHECK-NEXT: [[A_SQ_B_SQ:%.*]] = fadd float [[A_SQ]], [[B_SQ]] 1136; CHECK-NEXT: [[ADD:%.*]] = fadd reassoc nsz float [[A_B_2]], [[A_SQ_B_SQ]] 1137; CHECK-NEXT: ret float [[ADD]] 1138; 1139 %not_a_2 = fmul float %b, 2.0 1140 %a_b_2 = fmul float %not_a_2, %b 1141 %a_sq = fmul float %a, %a 1142 %b_sq = fmul float %b, %b 1143 %a_sq_b_sq = fadd float %a_sq, %b_sq 1144 %add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq 1145 ret float %add 1146} 1147 1148declare void @fake_func(float) 1149