1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4; ========================================================================= 5; 6; Test FP factorization with patterns: 7; X * Z + Y * Z --> (X + Y) * Z (including all 4 commuted variants) 8; X * Z - Y * Z --> (X - Y) * Z (including all 4 commuted variants) 9; X / Z + Y / Z --> (X + Y) / Z 10; X / Z - Y / Z --> (X - Y) / Z 11; 12; ========================================================================= 13 14; Minimum FMF - the final result requires/propagates FMF. 15 16define float @fmul_fadd(float %x, float %y, float %z) { 17; CHECK-LABEL: @fmul_fadd( 18; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[X:%.*]], [[Y:%.*]] 19; CHECK-NEXT: [[R:%.*]] = fmul reassoc nsz float [[TMP1]], [[Z:%.*]] 20; CHECK-NEXT: ret float [[R]] 21; 22 %t1 = fmul float %x, %z 23 %t2 = fmul float %y, %z 24 %r = fadd reassoc nsz float %t1, %t2 25 ret float %r 26} 27 28; Verify vector types and commuted operands. 29 30define <2 x float> @fmul_fadd_commute1_vec(<2 x float> %x, <2 x float> %y, <2 x float> %z) { 31; CHECK-LABEL: @fmul_fadd_commute1_vec( 32; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz <2 x float> [[X:%.*]], [[Y:%.*]] 33; CHECK-NEXT: [[R:%.*]] = fmul reassoc nsz <2 x float> [[TMP1]], [[Z:%.*]] 34; CHECK-NEXT: ret <2 x float> [[R]] 35; 36 %t1 = fmul <2 x float> %z, %x 37 %t2 = fmul <2 x float> %z, %y 38 %r = fadd reassoc nsz <2 x float> %t1, %t2 39 ret <2 x float> %r 40} 41 42; Verify vector types, commuted operands, FMF propagation. 43 44define <2 x float> @fmul_fadd_commute2_vec(<2 x float> %x, <2 x float> %y, <2 x float> %z) { 45; CHECK-LABEL: @fmul_fadd_commute2_vec( 46; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc ninf nsz <2 x float> [[X:%.*]], [[Y:%.*]] 47; CHECK-NEXT: [[R:%.*]] = fmul reassoc ninf nsz <2 x float> [[TMP1]], [[Z:%.*]] 48; CHECK-NEXT: ret <2 x float> [[R]] 49; 50 %t1 = fmul fast <2 x float> %x, %z 51 %t2 = fmul nnan <2 x float> %z, %y 52 %r = fadd reassoc nsz ninf <2 x float> %t1, %t2 53 ret <2 x float> %r 54} 55 56; Verify different scalar type, commuted operands, FMF propagation. 57 58define double @fmul_fadd_commute3(double %x, double %y, double %z) { 59; CHECK-LABEL: @fmul_fadd_commute3( 60; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nnan nsz double [[X:%.*]], [[Y:%.*]] 61; CHECK-NEXT: [[R:%.*]] = fmul reassoc nnan nsz double [[TMP1]], [[Z:%.*]] 62; CHECK-NEXT: ret double [[R]] 63; 64 %t1 = fmul double %z, %x 65 %t2 = fmul fast double %y, %z 66 %r = fadd reassoc nsz nnan double %t1, %t2 67 ret double %r 68} 69 70; Negative test - verify the fold is not done with only 'reassoc' ('nsz' is required). 71 72define float @fmul_fadd_not_enough_FMF(float %x, float %y, float %z) { 73; CHECK-LABEL: @fmul_fadd_not_enough_FMF( 74; CHECK-NEXT: [[T1:%.*]] = fmul fast float [[X:%.*]], [[Z:%.*]] 75; CHECK-NEXT: [[T2:%.*]] = fmul fast float [[Y:%.*]], [[Z]] 76; CHECK-NEXT: [[R:%.*]] = fadd reassoc float [[T1]], [[T2]] 77; CHECK-NEXT: ret float [[R]] 78; 79 %t1 = fmul fast float %x, %z 80 %t2 = fmul fast float %y, %z 81 %r = fadd reassoc float %t1, %t2 82 ret float %r 83} 84 85declare void @use(float) 86 87; Negative test - extra uses should disable the fold. 88 89define float @fmul_fadd_uses1(float %x, float %y, float %z) { 90; CHECK-LABEL: @fmul_fadd_uses1( 91; CHECK-NEXT: [[T1:%.*]] = fmul float [[Z:%.*]], [[X:%.*]] 92; CHECK-NEXT: [[T2:%.*]] = fmul float [[Y:%.*]], [[Z]] 93; CHECK-NEXT: [[R:%.*]] = fadd reassoc nsz float [[T1]], [[T2]] 94; CHECK-NEXT: call void @use(float [[T1]]) 95; CHECK-NEXT: ret float [[R]] 96; 97 %t1 = fmul float %z, %x 98 %t2 = fmul float %y, %z 99 %r = fadd reassoc nsz float %t1, %t2 100 call void @use(float %t1) 101 ret float %r 102} 103 104; Negative test - extra uses should disable the fold. 105 106define float @fmul_fadd_uses2(float %x, float %y, float %z) { 107; CHECK-LABEL: @fmul_fadd_uses2( 108; CHECK-NEXT: [[T1:%.*]] = fmul float [[Z:%.*]], [[X:%.*]] 109; CHECK-NEXT: [[T2:%.*]] = fmul float [[Z]], [[Y:%.*]] 110; CHECK-NEXT: [[R:%.*]] = fadd reassoc nsz float [[T1]], [[T2]] 111; CHECK-NEXT: call void @use(float [[T2]]) 112; CHECK-NEXT: ret float [[R]] 113; 114 %t1 = fmul float %z, %x 115 %t2 = fmul float %z, %y 116 %r = fadd reassoc nsz float %t1, %t2 117 call void @use(float %t2) 118 ret float %r 119} 120 121; Negative test - extra uses should disable the fold. 122 123define float @fmul_fadd_uses3(float %x, float %y, float %z) { 124; CHECK-LABEL: @fmul_fadd_uses3( 125; CHECK-NEXT: [[T1:%.*]] = fmul float [[X:%.*]], [[Z:%.*]] 126; CHECK-NEXT: [[T2:%.*]] = fmul float [[Z]], [[Y:%.*]] 127; CHECK-NEXT: [[R:%.*]] = fadd reassoc nsz float [[T1]], [[T2]] 128; CHECK-NEXT: call void @use(float [[T1]]) 129; CHECK-NEXT: call void @use(float [[T2]]) 130; CHECK-NEXT: ret float [[R]] 131; 132 %t1 = fmul float %x, %z 133 %t2 = fmul float %z, %y 134 %r = fadd reassoc nsz float %t1, %t2 135 call void @use(float %t1) 136 call void @use(float %t2) 137 ret float %r 138} 139 140; Minimum FMF - the final result requires/propagates FMF. 141 142define half @fmul_fsub(half %x, half %y, half %z) { 143; CHECK-LABEL: @fmul_fsub( 144; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc nsz half [[X:%.*]], [[Y:%.*]] 145; CHECK-NEXT: [[R:%.*]] = fmul reassoc nsz half [[TMP1]], [[Z:%.*]] 146; CHECK-NEXT: ret half [[R]] 147; 148 %t1 = fmul half %x, %z 149 %t2 = fmul half %y, %z 150 %r = fsub reassoc nsz half %t1, %t2 151 ret half %r 152} 153 154; Verify vector types and commuted operands. 155 156define <2 x float> @fmul_fsub_commute1_vec(<2 x float> %x, <2 x float> %y, <2 x float> %z) { 157; CHECK-LABEL: @fmul_fsub_commute1_vec( 158; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc nsz <2 x float> [[X:%.*]], [[Y:%.*]] 159; CHECK-NEXT: [[R:%.*]] = fmul reassoc nsz <2 x float> [[TMP1]], [[Z:%.*]] 160; CHECK-NEXT: ret <2 x float> [[R]] 161; 162 %t1 = fmul <2 x float> %z, %x 163 %t2 = fmul <2 x float> %y, %z 164 %r = fsub reassoc nsz <2 x float> %t1, %t2 165 ret <2 x float> %r 166} 167 168; Verify vector types, commuted operands, FMF propagation. 169 170define <2 x float> @fmul_fsub_commute2_vec(<2 x float> %x, <2 x float> %y, <2 x float> %z) { 171; CHECK-LABEL: @fmul_fsub_commute2_vec( 172; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc ninf nsz <2 x float> [[X:%.*]], [[Y:%.*]] 173; CHECK-NEXT: [[R:%.*]] = fmul reassoc ninf nsz <2 x float> [[TMP1]], [[Z:%.*]] 174; CHECK-NEXT: ret <2 x float> [[R]] 175; 176 %t1 = fmul fast <2 x float> %x, %z 177 %t2 = fmul nnan <2 x float> %z, %y 178 %r = fsub reassoc nsz ninf <2 x float> %t1, %t2 179 ret <2 x float> %r 180} 181 182; Verify different scalar type, commuted operands, FMF propagation. 183 184define double @fmul_fsub_commute3(double %x, double %y, double %z) { 185; CHECK-LABEL: @fmul_fsub_commute3( 186; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc nnan nsz double [[X:%.*]], [[Y:%.*]] 187; CHECK-NEXT: [[R:%.*]] = fmul reassoc nnan nsz double [[TMP1]], [[Z:%.*]] 188; CHECK-NEXT: ret double [[R]] 189; 190 %t1 = fmul double %z, %x 191 %t2 = fmul fast double %z, %y 192 %r = fsub reassoc nsz nnan double %t1, %t2 193 ret double %r 194} 195 196; Negative test - verify the fold is not done with only 'nsz' ('reassoc' is required). 197 198define float @fmul_fsub_not_enough_FMF(float %x, float %y, float %z) { 199; CHECK-LABEL: @fmul_fsub_not_enough_FMF( 200; CHECK-NEXT: [[T1:%.*]] = fmul fast float [[Z:%.*]], [[X:%.*]] 201; CHECK-NEXT: [[T2:%.*]] = fmul fast float [[Y:%.*]], [[Z]] 202; CHECK-NEXT: [[R:%.*]] = fsub nsz float [[T1]], [[T2]] 203; CHECK-NEXT: ret float [[R]] 204; 205 %t1 = fmul fast float %z, %x 206 %t2 = fmul fast float %y, %z 207 %r = fsub nsz float %t1, %t2 208 ret float %r 209} 210 211; Negative test - extra uses should disable the fold. 212 213define float @fmul_fsub_uses1(float %x, float %y, float %z) { 214; CHECK-LABEL: @fmul_fsub_uses1( 215; CHECK-NEXT: [[T1:%.*]] = fmul float [[X:%.*]], [[Z:%.*]] 216; CHECK-NEXT: [[T2:%.*]] = fmul float [[Y:%.*]], [[Z]] 217; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz float [[T1]], [[T2]] 218; CHECK-NEXT: call void @use(float [[T1]]) 219; CHECK-NEXT: ret float [[R]] 220; 221 %t1 = fmul float %x, %z 222 %t2 = fmul float %y, %z 223 %r = fsub reassoc nsz float %t1, %t2 224 call void @use(float %t1) 225 ret float %r 226} 227 228; Negative test - extra uses should disable the fold. 229 230define float @fmul_fsub_uses2(float %x, float %y, float %z) { 231; CHECK-LABEL: @fmul_fsub_uses2( 232; CHECK-NEXT: [[T1:%.*]] = fmul float [[Z:%.*]], [[X:%.*]] 233; CHECK-NEXT: [[T2:%.*]] = fmul float [[Z]], [[Y:%.*]] 234; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz float [[T1]], [[T2]] 235; CHECK-NEXT: call void @use(float [[T2]]) 236; CHECK-NEXT: ret float [[R]] 237; 238 %t1 = fmul float %z, %x 239 %t2 = fmul float %z, %y 240 %r = fsub reassoc nsz float %t1, %t2 241 call void @use(float %t2) 242 ret float %r 243} 244 245; Negative test - extra uses should disable the fold. 246 247define float @fmul_fsub_uses3(float %x, float %y, float %z) { 248; CHECK-LABEL: @fmul_fsub_uses3( 249; CHECK-NEXT: [[T1:%.*]] = fmul float [[X:%.*]], [[Z:%.*]] 250; CHECK-NEXT: [[T2:%.*]] = fmul float [[Y:%.*]], [[Z]] 251; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz float [[T1]], [[T2]] 252; CHECK-NEXT: call void @use(float [[T1]]) 253; CHECK-NEXT: call void @use(float [[T2]]) 254; CHECK-NEXT: ret float [[R]] 255; 256 %t1 = fmul float %x, %z 257 %t2 = fmul float %y, %z 258 %r = fsub reassoc nsz float %t1, %t2 259 call void @use(float %t1) 260 call void @use(float %t2) 261 ret float %r 262} 263 264; Common divisor 265 266define double @fdiv_fadd(double %x, double %y, double %z) { 267; CHECK-LABEL: @fdiv_fadd( 268; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz double [[X:%.*]], [[Y:%.*]] 269; CHECK-NEXT: [[R:%.*]] = fdiv reassoc nsz double [[TMP1]], [[Z:%.*]] 270; CHECK-NEXT: ret double [[R]] 271; 272 %t1 = fdiv double %x, %z 273 %t2 = fdiv double %y, %z 274 %r = fadd reassoc nsz double %t1, %t2 275 ret double %r 276} 277 278define float @fdiv_fsub(float %x, float %y, float %z) { 279; CHECK-LABEL: @fdiv_fsub( 280; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc nsz float [[X:%.*]], [[Y:%.*]] 281; CHECK-NEXT: [[R:%.*]] = fdiv reassoc nsz float [[TMP1]], [[Z:%.*]] 282; CHECK-NEXT: ret float [[R]] 283; 284 %t1 = fdiv fast float %x, %z 285 %t2 = fdiv nnan float %y, %z 286 %r = fsub reassoc nsz float %t1, %t2 287 ret float %r 288} 289 290; Verify vector types. 291 292define <2 x double> @fdiv_fadd_vec(<2 x double> %x, <2 x double> %y, <2 x double> %z) { 293; CHECK-LABEL: @fdiv_fadd_vec( 294; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz <2 x double> [[X:%.*]], [[Y:%.*]] 295; CHECK-NEXT: [[R:%.*]] = fdiv reassoc nsz <2 x double> [[TMP1]], [[Z:%.*]] 296; CHECK-NEXT: ret <2 x double> [[R]] 297; 298 %t1 = fdiv fast <2 x double> %x, %z 299 %t2 = fdiv <2 x double> %y, %z 300 %r = fadd reassoc nsz <2 x double> %t1, %t2 301 ret <2 x double> %r 302} 303 304; Verify vector types. 305 306define <2 x float> @fdiv_fsub_vec(<2 x float> %x, <2 x float> %y, <2 x float> %z) { 307; CHECK-LABEL: @fdiv_fsub_vec( 308; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc nsz <2 x float> [[X:%.*]], [[Y:%.*]] 309; CHECK-NEXT: [[R:%.*]] = fdiv reassoc nsz <2 x float> [[TMP1]], [[Z:%.*]] 310; CHECK-NEXT: ret <2 x float> [[R]] 311; 312 %t1 = fdiv <2 x float> %x, %z 313 %t2 = fdiv nnan <2 x float> %y, %z 314 %r = fsub reassoc nsz <2 x float> %t1, %t2 315 ret <2 x float> %r 316} 317 318; Negative test - common operand is not divisor. 319 320define float @fdiv_fadd_commute1(float %x, float %y, float %z) { 321; CHECK-LABEL: @fdiv_fadd_commute1( 322; CHECK-NEXT: [[T1:%.*]] = fdiv fast float [[Z:%.*]], [[Y:%.*]] 323; CHECK-NEXT: [[T2:%.*]] = fdiv fast float [[Z]], [[X:%.*]] 324; CHECK-NEXT: [[R:%.*]] = fadd fast float [[T1]], [[T2]] 325; CHECK-NEXT: ret float [[R]] 326; 327 %t1 = fdiv fast float %z, %y 328 %t2 = fdiv fast float %z, %x 329 %r = fadd fast float %t1, %t2 330 ret float %r 331} 332 333; Negative test - common operand is not divisor. 334 335define float @fdiv_fsub_commute2(float %x, float %y, float %z) { 336; CHECK-LABEL: @fdiv_fsub_commute2( 337; CHECK-NEXT: [[T1:%.*]] = fdiv fast float [[Z:%.*]], [[Y:%.*]] 338; CHECK-NEXT: [[T2:%.*]] = fdiv fast float [[X:%.*]], [[Z]] 339; CHECK-NEXT: [[R:%.*]] = fsub fast float [[T1]], [[T2]] 340; CHECK-NEXT: ret float [[R]] 341; 342 %t1 = fdiv fast float %z, %y 343 %t2 = fdiv fast float %x, %z 344 %r = fsub fast float %t1, %t2 345 ret float %r 346} 347 348; Negative test - verify the fold is not done with only 'nsz' ('reassoc' is required). 349 350define float @fdiv_fadd_not_enough_FMF(float %x, float %y, float %z) { 351; CHECK-LABEL: @fdiv_fadd_not_enough_FMF( 352; CHECK-NEXT: [[T1:%.*]] = fdiv fast float [[Y:%.*]], [[X:%.*]] 353; CHECK-NEXT: [[T2:%.*]] = fdiv fast float [[Z:%.*]], [[X]] 354; CHECK-NEXT: [[T3:%.*]] = fadd nsz float [[T1]], [[T2]] 355; CHECK-NEXT: ret float [[T3]] 356; 357 %t1 = fdiv fast float %y, %x 358 %t2 = fdiv fast float %z, %x 359 %t3 = fadd nsz float %t1, %t2 360 ret float %t3 361} 362 363; Negative test - verify the fold is not done with only 'reassoc' ('nsz' is required). 364 365define float @fdiv_fsub_not_enough_FMF(float %x, float %y, float %z) { 366; CHECK-LABEL: @fdiv_fsub_not_enough_FMF( 367; CHECK-NEXT: [[T1:%.*]] = fdiv fast float [[Y:%.*]], [[X:%.*]] 368; CHECK-NEXT: [[T2:%.*]] = fdiv fast float [[Z:%.*]], [[X]] 369; CHECK-NEXT: [[T3:%.*]] = fsub reassoc float [[T1]], [[T2]] 370; CHECK-NEXT: ret float [[T3]] 371; 372 %t1 = fdiv fast float %y, %x 373 %t2 = fdiv fast float %z, %x 374 %t3 = fsub reassoc float %t1, %t2 375 ret float %t3 376} 377 378; Negative test - extra uses should disable the fold. 379 380define float @fdiv_fadd_uses1(float %x, float %y, float %z) { 381; CHECK-LABEL: @fdiv_fadd_uses1( 382; CHECK-NEXT: [[T1:%.*]] = fdiv fast float [[X:%.*]], [[Z:%.*]] 383; CHECK-NEXT: [[T2:%.*]] = fdiv fast float [[Y:%.*]], [[Z]] 384; CHECK-NEXT: [[R:%.*]] = fadd fast float [[T1]], [[T2]] 385; CHECK-NEXT: call void @use(float [[T1]]) 386; CHECK-NEXT: ret float [[R]] 387; 388 %t1 = fdiv fast float %x, %z 389 %t2 = fdiv fast float %y, %z 390 %r = fadd fast float %t1, %t2 391 call void @use(float %t1) 392 ret float %r 393} 394 395; Negative test - extra uses should disable the fold. 396 397define float @fdiv_fsub_uses2(float %x, float %y, float %z) { 398; CHECK-LABEL: @fdiv_fsub_uses2( 399; CHECK-NEXT: [[T1:%.*]] = fdiv fast float [[X:%.*]], [[Z:%.*]] 400; CHECK-NEXT: [[T2:%.*]] = fdiv fast float [[Y:%.*]], [[Z]] 401; CHECK-NEXT: [[R:%.*]] = fsub fast float [[T1]], [[T2]] 402; CHECK-NEXT: call void @use(float [[T2]]) 403; CHECK-NEXT: ret float [[R]] 404; 405 %t1 = fdiv fast float %x, %z 406 %t2 = fdiv fast float %y, %z 407 %r = fsub fast float %t1, %t2 408 call void @use(float %t2) 409 ret float %r 410} 411 412; Negative test - extra uses should disable the fold. 413 414define float @fdiv_fsub_uses3(float %x, float %y, float %z) { 415; CHECK-LABEL: @fdiv_fsub_uses3( 416; CHECK-NEXT: [[T1:%.*]] = fdiv fast float [[X:%.*]], [[Z:%.*]] 417; CHECK-NEXT: [[T2:%.*]] = fdiv fast float [[Y:%.*]], [[Z]] 418; CHECK-NEXT: [[R:%.*]] = fsub fast float [[T1]], [[T2]] 419; CHECK-NEXT: call void @use(float [[T1]]) 420; CHECK-NEXT: call void @use(float [[T2]]) 421; CHECK-NEXT: ret float [[R]] 422; 423 %t1 = fdiv fast float %x, %z 424 %t2 = fdiv fast float %y, %z 425 %r = fsub fast float %t1, %t2 426 call void @use(float %t1) 427 call void @use(float %t2) 428 ret float %r 429} 430 431; Constants are fine to combine if they are not denorms. 432 433define float @fdiv_fadd_not_denorm(float %x) { 434; CHECK-LABEL: @fdiv_fadd_not_denorm( 435; CHECK-NEXT: [[R:%.*]] = fdiv fast float 0x3818000000000000, [[X:%.*]] 436; CHECK-NEXT: ret float [[R]] 437; 438 %t1 = fdiv fast float 0x3810000000000000, %x 439 %t2 = fdiv fast float 0x3800000000000000, %x 440 %r = fadd fast float %t1, %t2 441 ret float %r 442} 443 444; Negative test - disabled if x+y is denormal. 445 446define float @fdiv_fadd_denorm(float %x) { 447; CHECK-LABEL: @fdiv_fadd_denorm( 448; CHECK-NEXT: [[T1:%.*]] = fdiv fast float 0xB810000000000000, [[X:%.*]] 449; CHECK-NEXT: [[T2:%.*]] = fdiv fast float 0x3800000000000000, [[X]] 450; CHECK-NEXT: [[R:%.*]] = fadd fast float [[T1]], [[T2]] 451; CHECK-NEXT: ret float [[R]] 452; 453 %t1 = fdiv fast float 0xB810000000000000, %x 454 %t2 = fdiv fast float 0x3800000000000000, %x 455 %r = fadd fast float %t1, %t2 456 ret float %r 457} 458 459; Negative test - disabled if x-y is denormal. 460 461define float @fdiv_fsub_denorm(float %x) { 462; CHECK-LABEL: @fdiv_fsub_denorm( 463; CHECK-NEXT: [[T1:%.*]] = fdiv fast float 0x3810000000000000, [[X:%.*]] 464; CHECK-NEXT: [[T2:%.*]] = fdiv fast float 0x3800000000000000, [[X]] 465; CHECK-NEXT: [[R:%.*]] = fsub fast float [[T1]], [[T2]] 466; CHECK-NEXT: ret float [[R]] 467; 468 %t1 = fdiv fast float 0x3810000000000000, %x 469 %t2 = fdiv fast float 0x3800000000000000, %x 470 %r = fsub fast float %t1, %t2 471 ret float %r 472} 473 474define float @lerp_commute0(float %a, float %b, float %c) { 475; CHECK-LABEL: @lerp_commute0( 476; CHECK-NEXT: [[TMP1:%.*]] = fsub fast float [[B:%.*]], [[A:%.*]] 477; CHECK-NEXT: [[TMP2:%.*]] = fmul fast float [[C:%.*]], [[TMP1]] 478; CHECK-NEXT: [[ADD:%.*]] = fadd fast float [[A]], [[TMP2]] 479; CHECK-NEXT: ret float [[ADD]] 480; 481 %sub = fsub fast float 1.0, %c 482 %mul = fmul fast float %sub, %a 483 %bc = fmul fast float %c, %b 484 %add = fadd fast float %mul, %bc 485 ret float %add 486} 487 488define <2 x float> @lerp_commute1(<2 x float> %a, <2 x float> %b, <2 x float> %c) { 489; CHECK-LABEL: @lerp_commute1( 490; CHECK-NEXT: [[TMP1:%.*]] = fsub fast <2 x float> [[B:%.*]], [[A:%.*]] 491; CHECK-NEXT: [[TMP2:%.*]] = fmul fast <2 x float> [[C:%.*]], [[TMP1]] 492; CHECK-NEXT: [[ADD:%.*]] = fadd fast <2 x float> [[A]], [[TMP2]] 493; CHECK-NEXT: ret <2 x float> [[ADD]] 494; 495 %sub = fsub <2 x float> <float 1.0, float 1.0>, %c 496 %mul = fmul <2 x float> %sub, %a 497 %bc = fmul <2 x float> %c, %b 498 %add = fadd fast <2 x float> %bc, %mul 499 ret <2 x float> %add 500} 501 502define float @lerp_commute2(float %a, float %b, float %c) { 503; CHECK-LABEL: @lerp_commute2( 504; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc nsz float [[B:%.*]], [[A:%.*]] 505; CHECK-NEXT: [[TMP2:%.*]] = fmul reassoc nsz float [[C:%.*]], [[TMP1]] 506; CHECK-NEXT: [[ADD:%.*]] = fadd reassoc nsz float [[A]], [[TMP2]] 507; CHECK-NEXT: ret float [[ADD]] 508; 509 %sub = fsub float 1.0, %c 510 %mul = fmul float %sub, %a 511 %bc = fmul float %b, %c 512 %add = fadd reassoc nsz float %mul, %bc 513 ret float %add 514} 515 516define float @lerp_commute3(float %a, float %b, float %c) { 517; CHECK-LABEL: @lerp_commute3( 518; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc ninf nsz float [[B:%.*]], [[A:%.*]] 519; CHECK-NEXT: [[TMP2:%.*]] = fmul reassoc ninf nsz float [[C:%.*]], [[TMP1]] 520; CHECK-NEXT: [[ADD:%.*]] = fadd reassoc ninf nsz float [[A]], [[TMP2]] 521; CHECK-NEXT: ret float [[ADD]] 522; 523 %sub = fsub fast float 1.0, %c 524 %mul = fmul float %sub, %a 525 %bc = fmul float %b, %c 526 %add = fadd reassoc nsz ninf float %bc, %mul 527 ret float %add 528} 529 530define double @lerp_commute4(double %a, double %b, double %c) { 531; CHECK-LABEL: @lerp_commute4( 532; CHECK-NEXT: [[TMP1:%.*]] = fsub fast double [[B:%.*]], [[A:%.*]] 533; CHECK-NEXT: [[TMP2:%.*]] = fmul fast double [[C:%.*]], [[TMP1]] 534; CHECK-NEXT: [[ADD:%.*]] = fadd fast double [[A]], [[TMP2]] 535; CHECK-NEXT: ret double [[ADD]] 536; 537 %sub = fsub fast double 1.0, %c 538 %mul = fmul fast double %a, %sub 539 %bc = fmul fast double %c, %b 540 %add = fadd fast double %mul, %bc 541 ret double %add 542} 543 544define double @lerp_commute5(double %a, double %b, double %c) { 545; CHECK-LABEL: @lerp_commute5( 546; CHECK-NEXT: [[TMP1:%.*]] = fsub fast double [[B:%.*]], [[A:%.*]] 547; CHECK-NEXT: [[TMP2:%.*]] = fmul fast double [[C:%.*]], [[TMP1]] 548; CHECK-NEXT: [[ADD:%.*]] = fadd fast double [[A]], [[TMP2]] 549; CHECK-NEXT: ret double [[ADD]] 550; 551 %sub = fsub fast double 1.0, %c 552 %mul = fmul fast double %a, %sub 553 %bc = fmul fast double %c, %b 554 %add = fadd fast double %bc, %mul 555 ret double %add 556} 557 558define half @lerp_commute6(half %a, half %b, half %c) { 559; CHECK-LABEL: @lerp_commute6( 560; CHECK-NEXT: [[TMP1:%.*]] = fsub fast half [[B:%.*]], [[A:%.*]] 561; CHECK-NEXT: [[TMP2:%.*]] = fmul fast half [[C:%.*]], [[TMP1]] 562; CHECK-NEXT: [[ADD:%.*]] = fadd fast half [[A]], [[TMP2]] 563; CHECK-NEXT: ret half [[ADD]] 564; 565 %sub = fsub fast half 1.0, %c 566 %mul = fmul fast half %a, %sub 567 %bc = fmul fast half %b, %c 568 %add = fadd fast half %mul, %bc 569 ret half %add 570} 571 572define half @lerp_commute7(half %a, half %b, half %c) { 573; CHECK-LABEL: @lerp_commute7( 574; CHECK-NEXT: [[TMP1:%.*]] = fsub fast half [[B:%.*]], [[A:%.*]] 575; CHECK-NEXT: [[TMP2:%.*]] = fmul fast half [[C:%.*]], [[TMP1]] 576; CHECK-NEXT: [[ADD:%.*]] = fadd fast half [[A]], [[TMP2]] 577; CHECK-NEXT: ret half [[ADD]] 578; 579 %sub = fsub fast half 1.0, %c 580 %mul = fmul fast half %a, %sub 581 %bc = fmul fast half %b, %c 582 %add = fadd fast half %bc, %mul 583 ret half %add 584} 585 586define float @lerp_extra_use1(float %a, float %b, float %c) { 587; CHECK-LABEL: @lerp_extra_use1( 588; CHECK-NEXT: [[SUB:%.*]] = fsub fast float 1.000000e+00, [[C:%.*]] 589; CHECK-NEXT: [[MUL:%.*]] = fmul fast float [[A:%.*]], [[SUB]] 590; CHECK-NEXT: [[BC:%.*]] = fmul fast float [[B:%.*]], [[C]] 591; CHECK-NEXT: call void @use(float [[BC]]) 592; CHECK-NEXT: [[ADD:%.*]] = fadd fast float [[BC]], [[MUL]] 593; CHECK-NEXT: ret float [[ADD]] 594; 595 %sub = fsub fast float 1.0, %c 596 %mul = fmul fast float %a, %sub 597 %bc = fmul fast float %b, %c 598 call void @use(float %bc) 599 %add = fadd fast float %bc, %mul 600 ret float %add 601} 602 603define float @lerp_extra_use2(float %a, float %b, float %c) { 604; CHECK-LABEL: @lerp_extra_use2( 605; CHECK-NEXT: [[SUB:%.*]] = fsub fast float 1.000000e+00, [[C:%.*]] 606; CHECK-NEXT: [[MUL:%.*]] = fmul fast float [[A:%.*]], [[SUB]] 607; CHECK-NEXT: call void @use(float [[MUL]]) 608; CHECK-NEXT: [[BC:%.*]] = fmul fast float [[B:%.*]], [[C]] 609; CHECK-NEXT: [[ADD:%.*]] = fadd fast float [[BC]], [[MUL]] 610; CHECK-NEXT: ret float [[ADD]] 611; 612 %sub = fsub fast float 1.0, %c 613 %mul = fmul fast float %a, %sub 614 call void @use(float %mul) 615 %bc = fmul fast float %b, %c 616 %add = fadd fast float %bc, %mul 617 ret float %add 618} 619 620define float @lerp_extra_use3(float %a, float %b, float %c) { 621; CHECK-LABEL: @lerp_extra_use3( 622; CHECK-NEXT: [[SUB:%.*]] = fsub fast float 1.000000e+00, [[C:%.*]] 623; CHECK-NEXT: call void @use(float [[SUB]]) 624; CHECK-NEXT: [[MUL:%.*]] = fmul fast float [[A:%.*]], [[SUB]] 625; CHECK-NEXT: [[BC:%.*]] = fmul fast float [[B:%.*]], [[C]] 626; CHECK-NEXT: [[ADD:%.*]] = fadd fast float [[BC]], [[MUL]] 627; CHECK-NEXT: ret float [[ADD]] 628; 629 %sub = fsub fast float 1.0, %c 630 call void @use(float %sub) 631 %mul = fmul fast float %a, %sub 632 %bc = fmul fast float %b, %c 633 %add = fadd fast float %bc, %mul 634 ret float %add 635} 636