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-int-for-fixed-length-splat -S | FileCheck %s 4 5declare i32 @llvm.abs.i32(i32, i1) 6 7define i32 @pow2_multiplier(i32 %A) { 8; CHECK-LABEL: @pow2_multiplier( 9; CHECK-NEXT: [[B:%.*]] = shl i32 [[A:%.*]], 1 10; CHECK-NEXT: ret i32 [[B]] 11; 12 %B = mul i32 %A, 2 13 ret i32 %B 14} 15 16define <2 x i32> @pow2_multiplier_vec(<2 x i32> %A) { 17; CHECK-LABEL: @pow2_multiplier_vec( 18; CHECK-NEXT: [[B:%.*]] = shl <2 x i32> [[A:%.*]], splat (i32 3) 19; CHECK-NEXT: ret <2 x i32> [[B]] 20; 21 %B = mul <2 x i32> %A, <i32 8, i32 8> 22 ret <2 x i32> %B 23} 24 25define i8 @combine_shl(i8 %A) { 26; CHECK-LABEL: @combine_shl( 27; CHECK-NEXT: [[C:%.*]] = shl i8 [[A:%.*]], 6 28; CHECK-NEXT: ret i8 [[C]] 29; 30 %B = mul i8 %A, 8 31 %C = mul i8 %B, 8 32 ret i8 %C 33} 34 35define i32 @neg(i32 %i) { 36; CHECK-LABEL: @neg( 37; CHECK-NEXT: [[T:%.*]] = sub i32 0, [[I:%.*]] 38; CHECK-NEXT: ret i32 [[T]] 39; 40 %t = mul i32 %i, -1 41 ret i32 %t 42} 43 44; Use the sign-bit as a mask: 45; (zext (A < 0)) * B --> (A >> 31) & B 46 47define i32 @test10(i32 %a, i32 %b) { 48; CHECK-LABEL: @test10( 49; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt i32 [[A:%.*]], 0 50; CHECK-NEXT: [[E:%.*]] = select i1 [[ISNEG]], i32 [[B:%.*]], i32 0 51; CHECK-NEXT: ret i32 [[E]] 52; 53 %c = icmp slt i32 %a, 0 54 %d = zext i1 %c to i32 55 %e = mul i32 %d, %b 56 ret i32 %e 57} 58 59define i32 @test11(i32 %a, i32 %b) { 60; CHECK-LABEL: @test11( 61; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt i32 [[A:%.*]], 0 62; CHECK-NEXT: [[E:%.*]] = select i1 [[ISNEG]], i32 [[B:%.*]], i32 0 63; CHECK-NEXT: ret i32 [[E]] 64; 65 %c = icmp sle i32 %a, -1 66 %d = zext i1 %c to i32 67 %e = mul i32 %d, %b 68 ret i32 %e 69} 70 71declare void @use32(i32) 72 73define i32 @test12(i32 %a, i32 %b) { 74; CHECK-LABEL: @test12( 75; CHECK-NEXT: [[A_LOBIT:%.*]] = lshr i32 [[A:%.*]], 31 76; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt i32 [[A]], 0 77; CHECK-NEXT: [[E:%.*]] = select i1 [[ISNEG]], i32 [[B:%.*]], i32 0 78; CHECK-NEXT: call void @use32(i32 [[A_LOBIT]]) 79; CHECK-NEXT: ret i32 [[E]] 80; 81 %c = icmp ugt i32 %a, 2147483647 82 %d = zext i1 %c to i32 83 %e = mul i32 %d, %b 84 call void @use32(i32 %d) 85 ret i32 %e 86} 87 88; rdar://7293527 89define i32 @shl1(i32 %a, i32 %b) { 90; CHECK-LABEL: @shl1( 91; CHECK-NEXT: [[M1:%.*]] = shl i32 [[A:%.*]], [[B:%.*]] 92; CHECK-NEXT: ret i32 [[M1]] 93; 94 %shl = shl i32 1, %b 95 %m = mul i32 %shl, %a 96 ret i32 %m 97} 98 99define i32 @shl1_nsw_nsw(i32 %A, i32 %B) { 100; CHECK-LABEL: @shl1_nsw_nsw( 101; CHECK-NEXT: [[D1:%.*]] = shl nsw i32 [[A:%.*]], [[B:%.*]] 102; CHECK-NEXT: ret i32 [[D1]] 103; 104 %shl = shl nsw i32 1, %B 105 %D = mul nsw i32 %A, %shl 106 ret i32 %D 107} 108 109define <2 x i32> @shl1_nsw_nsw_commute(<2 x i32> %A, <2 x i32> %B) { 110; CHECK-LABEL: @shl1_nsw_nsw_commute( 111; CHECK-NEXT: [[D1:%.*]] = shl nsw <2 x i32> [[A:%.*]], [[B:%.*]] 112; CHECK-NEXT: ret <2 x i32> [[D1]] 113; 114 %shl = shl nsw <2 x i32> <i32 1, i32 poison>, %B 115 %D = mul nsw <2 x i32> %shl, %A 116 ret <2 x i32> %D 117} 118 119define i32 @shl1_nuw(i32 %A, i32 %B) { 120; CHECK-LABEL: @shl1_nuw( 121; CHECK-NEXT: [[D1:%.*]] = shl nuw i32 [[A:%.*]], [[B:%.*]] 122; CHECK-NEXT: ret i32 [[D1]] 123; 124 %shl = shl i32 1, %B 125 %D = mul nuw i32 %A, %shl 126 ret i32 %D 127} 128 129define i32 @shl1_nuw_commute(i32 %A, i32 %B) { 130; CHECK-LABEL: @shl1_nuw_commute( 131; CHECK-NEXT: [[D1:%.*]] = shl i32 [[A:%.*]], [[B:%.*]] 132; CHECK-NEXT: ret i32 [[D1]] 133; 134 %shl = shl nuw i32 1, %B 135 %D = mul i32 %shl, %A 136 ret i32 %D 137} 138 139define i32 @shl1_nsw(i32 %A) { 140; CHECK-LABEL: @shl1_nsw( 141; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 1, [[A:%.*]] 142; CHECK-NEXT: [[C1:%.*]] = shl i32 [[SHL]], [[A]] 143; CHECK-NEXT: ret i32 [[C1]] 144; 145 %shl = shl i32 1, %A 146 %C = mul nsw i32 %shl, %shl 147 ret i32 %C 148} 149 150define i5 @shl1_increment(i5 %x, i5 %y) { 151; CHECK-LABEL: @shl1_increment( 152; CHECK-NEXT: [[Y_FR:%.*]] = freeze i5 [[Y:%.*]] 153; CHECK-NEXT: [[MULSHL:%.*]] = shl i5 [[Y_FR]], [[X:%.*]] 154; CHECK-NEXT: [[M1:%.*]] = add i5 [[MULSHL]], [[Y_FR]] 155; CHECK-NEXT: ret i5 [[M1]] 156; 157 %pow2x = shl i5 1, %x 158 %x1 = add i5 %pow2x, 1 159 %m = mul i5 %x1, %y 160 ret i5 %m 161} 162 163define <3 x i5> @shl1_nuw_increment_commute(<3 x i5> %x, <3 x i5> noundef %p) { 164; CHECK-LABEL: @shl1_nuw_increment_commute( 165; CHECK-NEXT: [[Y:%.*]] = ashr <3 x i5> [[P:%.*]], splat (i5 1) 166; CHECK-NEXT: [[MULSHL:%.*]] = shl nuw <3 x i5> [[Y]], [[X:%.*]] 167; CHECK-NEXT: [[M1:%.*]] = add nuw <3 x i5> [[MULSHL]], [[Y]] 168; CHECK-NEXT: ret <3 x i5> [[M1]] 169; 170 %y = ashr <3 x i5> %p, <i5 1, i5 1, i5 1> ; thwart complexity-based canonicalization 171 %pow2x = shl <3 x i5> <i5 1, i5 poison, i5 1>, %x 172 %x1 = add <3 x i5> %pow2x, <i5 1, i5 poison, i5 1> 173 %m = mul nuw <3 x i5> %y, %x1 174 ret <3 x i5> %m 175} 176 177define i5 @shl1_nsw_increment(i5 %x, i5 %y) { 178; CHECK-LABEL: @shl1_nsw_increment( 179; CHECK-NEXT: [[Y_FR:%.*]] = freeze i5 [[Y:%.*]] 180; CHECK-NEXT: [[MULSHL:%.*]] = shl i5 [[Y_FR]], [[X:%.*]] 181; CHECK-NEXT: [[M1:%.*]] = add i5 [[MULSHL]], [[Y_FR]] 182; CHECK-NEXT: ret i5 [[M1]] 183; 184 %pow2x = shl i5 1, %x 185 %x1 = add i5 %pow2x, 1 186 %m = mul nsw i5 %x1, %y 187 ret i5 %m 188} 189 190define i5 @shl1_nsw_nsw_increment(i5 %x, i5 %y) { 191; CHECK-LABEL: @shl1_nsw_nsw_increment( 192; CHECK-NEXT: [[Y_FR:%.*]] = freeze i5 [[Y:%.*]] 193; CHECK-NEXT: [[MULSHL:%.*]] = shl nsw i5 [[Y_FR]], [[X:%.*]] 194; CHECK-NEXT: [[M1:%.*]] = add nsw i5 [[MULSHL]], [[Y_FR]] 195; CHECK-NEXT: ret i5 [[M1]] 196; 197 %pow2x = shl nsw i5 1, %x 198 %x1 = add i5 %pow2x, 1 199 %m = mul nsw i5 %y, %x1 200 ret i5 %m 201} 202 203define i5 @shl1_nsw_nsw_increment_commute(i5 %x, i5 %y) { 204; CHECK-LABEL: @shl1_nsw_nsw_increment_commute( 205; CHECK-NEXT: [[Y_FR:%.*]] = freeze i5 [[Y:%.*]] 206; CHECK-NEXT: [[MULSHL:%.*]] = shl i5 [[Y_FR]], [[X:%.*]] 207; CHECK-NEXT: [[M1:%.*]] = add i5 [[MULSHL]], [[Y_FR]] 208; CHECK-NEXT: ret i5 [[M1]] 209; 210 %pow2x = shl nsw i5 1, %x 211 %x1 = add nsw i5 %pow2x, 1 212 %m = mul i5 %x1, %y 213 ret i5 %m 214} 215 216define i32 @shl1_increment_use(i32 %x, i32 %y) { 217; CHECK-LABEL: @shl1_increment_use( 218; CHECK-NEXT: [[POW2X:%.*]] = shl nuw i32 1, [[X:%.*]] 219; CHECK-NEXT: call void @use32(i32 [[POW2X]]) 220; CHECK-NEXT: [[X1:%.*]] = add nuw i32 [[POW2X]], 1 221; CHECK-NEXT: [[M:%.*]] = mul i32 [[X1]], [[Y:%.*]] 222; CHECK-NEXT: ret i32 [[M]] 223; 224 %pow2x = shl i32 1, %x 225 call void @use32(i32 %pow2x) 226 %x1 = add i32 %pow2x, 1 227 %m = mul i32 %x1, %y 228 ret i32 %m 229} 230 231; ((-1 << x) ^ -1) * y --> (y << x) - y 232 233define i8 @shl1_decrement(i8 %x, i8 %y) { 234; CHECK-LABEL: @shl1_decrement( 235; CHECK-NEXT: [[Y_FR:%.*]] = freeze i8 [[Y:%.*]] 236; CHECK-NEXT: [[MULSHL:%.*]] = shl i8 [[Y_FR]], [[X:%.*]] 237; CHECK-NEXT: [[M1:%.*]] = sub i8 [[MULSHL]], [[Y_FR]] 238; CHECK-NEXT: ret i8 [[M1]] 239; 240 %pow2x = shl i8 -1, %x 241 %x1 = xor i8 %pow2x, -1 242 %m = mul i8 %x1, %y 243 ret i8 %m 244} 245 246define i8 @shl1_decrement_commute(i8 %x, i8 noundef %p) { 247; CHECK-LABEL: @shl1_decrement_commute( 248; CHECK-NEXT: [[Y:%.*]] = ashr i8 [[P:%.*]], 1 249; CHECK-NEXT: [[MULSHL:%.*]] = shl i8 [[Y]], [[X:%.*]] 250; CHECK-NEXT: [[M1:%.*]] = sub i8 [[MULSHL]], [[Y]] 251; CHECK-NEXT: ret i8 [[M1]] 252; 253 %y = ashr i8 %p, 1 ; thwart complexity-based canonicalization 254 %pow2x = shl i8 1, %x 255 %x1 = add i8 %pow2x, -1 256 %m = mul i8 %y, %x1 257 ret i8 %m 258} 259 260define i8 @shl1_nuw_decrement(i8 %x, i8 %y) { 261; CHECK-LABEL: @shl1_nuw_decrement( 262; CHECK-NEXT: [[Y_FR:%.*]] = freeze i8 [[Y:%.*]] 263; CHECK-NEXT: [[MULSHL:%.*]] = shl i8 [[Y_FR]], [[X:%.*]] 264; CHECK-NEXT: [[M1:%.*]] = sub i8 [[MULSHL]], [[Y_FR]] 265; CHECK-NEXT: ret i8 [[M1]] 266; 267 %pow2x = shl i8 -1, %x 268 %x1 = xor i8 %pow2x, -1 269 %m = mul nuw i8 %x1, %y 270 ret i8 %m 271} 272 273define i8 @shl1_nsw_decrement(i8 %x, i8 %y) { 274; CHECK-LABEL: @shl1_nsw_decrement( 275; CHECK-NEXT: [[Y_FR:%.*]] = freeze i8 [[Y:%.*]] 276; CHECK-NEXT: [[MULSHL:%.*]] = shl i8 [[Y_FR]], [[X:%.*]] 277; CHECK-NEXT: [[M1:%.*]] = sub i8 [[MULSHL]], [[Y_FR]] 278; CHECK-NEXT: ret i8 [[M1]] 279; 280 %pow2x = shl nsw i8 -1, %x 281 %x1 = xor i8 %pow2x, -1 282 %m = mul nsw i8 %x1, %y 283 ret i8 %m 284} 285 286; negative test - extra use would require more instructions 287 288define i32 @shl1_decrement_use(i32 %x, i32 %y) { 289; CHECK-LABEL: @shl1_decrement_use( 290; CHECK-NEXT: [[NOTMASK:%.*]] = shl nsw i32 -1, [[X:%.*]] 291; CHECK-NEXT: [[X1:%.*]] = xor i32 [[NOTMASK]], -1 292; CHECK-NEXT: call void @use32(i32 [[X1]]) 293; CHECK-NEXT: [[M:%.*]] = mul i32 [[Y:%.*]], [[X1]] 294; CHECK-NEXT: ret i32 [[M]] 295; 296 %pow2x = shl i32 1, %x 297 %x1 = add i32 %pow2x, -1 298 call void @use32(i32 %x1) 299 %m = mul i32 %x1, %y 300 ret i32 %m 301} 302 303; the fold works for vectors too and if 'y' is a constant, sub becomes add 304 305define <2 x i8> @shl1_decrement_vec(<2 x i8> %x) { 306; CHECK-LABEL: @shl1_decrement_vec( 307; CHECK-NEXT: [[MULSHL:%.*]] = shl <2 x i8> <i8 42, i8 -3>, [[X:%.*]] 308; CHECK-NEXT: [[M1:%.*]] = add <2 x i8> [[MULSHL]], <i8 -42, i8 3> 309; CHECK-NEXT: ret <2 x i8> [[M1]] 310; 311 %pow2x = shl <2 x i8> <i8 -1, i8 -1>, %x 312 %x1 = xor <2 x i8> %pow2x, <i8 -1, i8 -1> 313 %m = mul <2 x i8> %x1, <i8 42, i8 -3> 314 ret <2 x i8> %m 315} 316 317; X * Y (when Y is a boolean) --> Y ? X : 0 318 319define i32 @mul_bool(i32 %x, i1 %y) { 320; CHECK-LABEL: @mul_bool( 321; CHECK-NEXT: [[M:%.*]] = select i1 [[Y:%.*]], i32 [[X:%.*]], i32 0 322; CHECK-NEXT: ret i32 [[M]] 323; 324 %z = zext i1 %y to i32 325 %m = mul i32 %z, %x 326 ret i32 %m 327} 328 329define <2 x i32> @mul_bool_vec(<2 x i32> %x, <2 x i1> %y) { 330; CHECK-LABEL: @mul_bool_vec( 331; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[Y:%.*]], <2 x i32> [[X:%.*]], <2 x i32> zeroinitializer 332; CHECK-NEXT: ret <2 x i32> [[M]] 333; 334 %z = zext <2 x i1> %y to <2 x i32> 335 %m = mul <2 x i32> %z, %x 336 ret <2 x i32> %m 337} 338 339define <2 x i32> @mul_bool_vec_commute(<2 x i32> %px, <2 x i1> %y) { 340; CHECK-LABEL: @mul_bool_vec_commute( 341; CHECK-NEXT: [[X:%.*]] = mul <2 x i32> [[PX:%.*]], [[PX]] 342; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[Y:%.*]], <2 x i32> [[X]], <2 x i32> zeroinitializer 343; CHECK-NEXT: ret <2 x i32> [[M]] 344; 345 %x = mul <2 x i32> %px, %px ; thwart complexity-based canonicalization 346 %z = zext <2 x i1> %y to <2 x i32> 347 %m = mul <2 x i32> %x, %z 348 ret <2 x i32> %m 349} 350 351; X * C (when X is a sext boolean) --> X ? -C : 0 352 353define i32 @mul_sext_bool(i1 %x) { 354; CHECK-LABEL: @mul_sext_bool( 355; CHECK-NEXT: [[M:%.*]] = select i1 [[X:%.*]], i32 -42, i32 0 356; CHECK-NEXT: ret i32 [[M]] 357; 358 %s = sext i1 %x to i32 359 %m = mul i32 %s, 42 360 ret i32 %m 361} 362 363define i32 @mul_sext_bool_use(i1 %x) { 364; CHECK-LABEL: @mul_sext_bool_use( 365; CHECK-NEXT: [[S:%.*]] = sext i1 [[X:%.*]] to i32 366; CHECK-NEXT: call void @use32(i32 [[S]]) 367; CHECK-NEXT: [[M:%.*]] = select i1 [[X]], i32 -42, i32 0 368; CHECK-NEXT: ret i32 [[M]] 369; 370 %s = sext i1 %x to i32 371 call void @use32(i32 %s) 372 %m = mul i32 %s, 42 373 ret i32 %m 374} 375 376define <2 x i8> @mul_sext_bool_vec(<2 x i1> %x) { 377; CHECK-LABEL: @mul_sext_bool_vec( 378; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[X:%.*]], <2 x i8> <i8 -42, i8 -128>, <2 x i8> zeroinitializer 379; CHECK-NEXT: ret <2 x i8> [[M]] 380; 381 %s = sext <2 x i1> %x to <2 x i8> 382 %m = mul <2 x i8> %s, <i8 42, i8 -128> 383 ret <2 x i8> %m 384} 385 386define <3 x i7> @mul_bools(<3 x i1> %x, <3 x i1> %y) { 387; CHECK-LABEL: @mul_bools( 388; CHECK-NEXT: [[MULBOOL:%.*]] = and <3 x i1> [[X:%.*]], [[Y:%.*]] 389; CHECK-NEXT: [[R:%.*]] = zext <3 x i1> [[MULBOOL]] to <3 x i7> 390; CHECK-NEXT: ret <3 x i7> [[R]] 391; 392 %zx = zext <3 x i1> %x to <3 x i7> 393 %zy = zext <3 x i1> %y to <3 x i7> 394 %r = mul <3 x i7> %zx, %zy 395 ret <3 x i7> %r 396} 397 398define i32 @mul_bools_use1(i1 %x, i1 %y) { 399; CHECK-LABEL: @mul_bools_use1( 400; CHECK-NEXT: [[ZY:%.*]] = zext i1 [[Y:%.*]] to i32 401; CHECK-NEXT: call void @use32(i32 [[ZY]]) 402; CHECK-NEXT: [[MULBOOL:%.*]] = and i1 [[X:%.*]], [[Y]] 403; CHECK-NEXT: [[R:%.*]] = zext i1 [[MULBOOL]] to i32 404; CHECK-NEXT: ret i32 [[R]] 405; 406 %zx = zext i1 %x to i32 407 %zy = zext i1 %y to i32 408 call void @use32(i32 %zy) 409 %r = mul i32 %zx, %zy 410 ret i32 %r 411} 412 413define i32 @mul_bools_use2(i1 %x, i1 %y) { 414; CHECK-LABEL: @mul_bools_use2( 415; CHECK-NEXT: [[ZY:%.*]] = zext i1 [[Y:%.*]] to i32 416; CHECK-NEXT: call void @use32(i32 [[ZY]]) 417; CHECK-NEXT: [[MULBOOL:%.*]] = and i1 [[Y]], [[X:%.*]] 418; CHECK-NEXT: [[R:%.*]] = zext i1 [[MULBOOL]] to i32 419; CHECK-NEXT: ret i32 [[R]] 420; 421 %zx = zext i1 %x to i32 422 %zy = zext i1 %y to i32 423 call void @use32(i32 %zy) 424 %r = mul i32 %zy, %zx 425 ret i32 %r 426} 427 428define i32 @mul_bools_use3(i1 %x, i1 %y) { 429; CHECK-LABEL: @mul_bools_use3( 430; CHECK-NEXT: [[ZX:%.*]] = zext i1 [[X:%.*]] to i32 431; CHECK-NEXT: call void @use32(i32 [[ZX]]) 432; CHECK-NEXT: [[ZY:%.*]] = zext i1 [[Y:%.*]] to i32 433; CHECK-NEXT: call void @use32(i32 [[ZY]]) 434; CHECK-NEXT: [[R:%.*]] = select i1 [[X]], i32 [[ZY]], i32 0 435; CHECK-NEXT: ret i32 [[R]] 436; 437 %zx = zext i1 %x to i32 438 call void @use32(i32 %zx) 439 %zy = zext i1 %y to i32 440 call void @use32(i32 %zy) 441 %r = mul i32 %zx, %zy 442 ret i32 %r 443} 444 445define <3 x i32> @mul_bools_sext(<3 x i1> %x, <3 x i1> %y) { 446; CHECK-LABEL: @mul_bools_sext( 447; CHECK-NEXT: [[MULBOOL:%.*]] = and <3 x i1> [[X:%.*]], [[Y:%.*]] 448; CHECK-NEXT: [[R:%.*]] = zext <3 x i1> [[MULBOOL]] to <3 x i32> 449; CHECK-NEXT: ret <3 x i32> [[R]] 450; 451 %sx = sext <3 x i1> %x to <3 x i32> 452 %sy = sext <3 x i1> %y to <3 x i32> 453 %r = mul <3 x i32> %sx, %sy 454 ret <3 x i32> %r 455} 456 457define i32 @mul_bools_sext_use1(i1 %x, i1 %y) { 458; CHECK-LABEL: @mul_bools_sext_use1( 459; CHECK-NEXT: [[SY:%.*]] = sext i1 [[Y:%.*]] to i32 460; CHECK-NEXT: call void @use32(i32 [[SY]]) 461; CHECK-NEXT: [[MULBOOL:%.*]] = and i1 [[X:%.*]], [[Y]] 462; CHECK-NEXT: [[R:%.*]] = zext i1 [[MULBOOL]] to i32 463; CHECK-NEXT: ret i32 [[R]] 464; 465 %sx = sext i1 %x to i32 466 %sy = sext i1 %y to i32 467 call void @use32(i32 %sy) 468 %r = mul i32 %sx, %sy 469 ret i32 %r 470} 471 472define i32 @mul_bools_sext_use2(i1 %x, i1 %y) { 473; CHECK-LABEL: @mul_bools_sext_use2( 474; CHECK-NEXT: [[SY:%.*]] = sext i1 [[Y:%.*]] to i32 475; CHECK-NEXT: call void @use32(i32 [[SY]]) 476; CHECK-NEXT: [[MULBOOL:%.*]] = and i1 [[Y]], [[X:%.*]] 477; CHECK-NEXT: [[R:%.*]] = zext i1 [[MULBOOL]] to i32 478; CHECK-NEXT: ret i32 [[R]] 479; 480 %sx = sext i1 %x to i32 481 %sy = sext i1 %y to i32 482 call void @use32(i32 %sy) 483 %r = mul i32 %sy, %sx 484 ret i32 %r 485} 486 487define i32 @mul_bools_sext_use3(i1 %x, i1 %y) { 488; CHECK-LABEL: @mul_bools_sext_use3( 489; CHECK-NEXT: [[SX:%.*]] = sext i1 [[X:%.*]] to i32 490; CHECK-NEXT: call void @use32(i32 [[SX]]) 491; CHECK-NEXT: [[SY:%.*]] = sext i1 [[Y:%.*]] to i32 492; CHECK-NEXT: call void @use32(i32 [[SY]]) 493; CHECK-NEXT: [[R:%.*]] = mul nsw i32 [[SY]], [[SX]] 494; CHECK-NEXT: ret i32 [[R]] 495; 496 %sx = sext i1 %x to i32 497 call void @use32(i32 %sx) 498 %sy = sext i1 %y to i32 499 call void @use32(i32 %sy) 500 %r = mul i32 %sy, %sx 501 ret i32 %r 502} 503 504define i32 @mul_bools_sext_one_use_per_op(i1 %x, i1 %y) { 505; CHECK-LABEL: @mul_bools_sext_one_use_per_op( 506; CHECK-NEXT: [[MULBOOL:%.*]] = and i1 [[X:%.*]], [[Y:%.*]] 507; CHECK-NEXT: [[R:%.*]] = zext i1 [[MULBOOL]] to i32 508; CHECK-NEXT: ret i32 [[R]] 509; 510 %sx = sext i1 %x to i32 511 %sy = sext i1 %y to i32 512 %r = mul i32 %sx, %sy 513 ret i32 %r 514} 515 516define i32 @mul_bool_sext_one_user(i1 %x) { 517; CHECK-LABEL: @mul_bool_sext_one_user( 518; CHECK-NEXT: [[R:%.*]] = zext i1 [[X:%.*]] to i32 519; CHECK-NEXT: ret i32 [[R]] 520; 521 %sx = sext i1 %x to i32 522 %r = mul i32 %sx, %sx 523 ret i32 %r 524} 525 526define i32 @mul_bools_zext_one_use_per_op(i1 %x, i1 %y) { 527; CHECK-LABEL: @mul_bools_zext_one_use_per_op( 528; CHECK-NEXT: [[MULBOOL:%.*]] = and i1 [[X:%.*]], [[Y:%.*]] 529; CHECK-NEXT: [[R:%.*]] = zext i1 [[MULBOOL]] to i32 530; CHECK-NEXT: ret i32 [[R]] 531; 532 %zx = zext i1 %x to i32 533 %zy = zext i1 %y to i32 534 %r = mul i32 %zx, %zy 535 ret i32 %r 536} 537 538define i32 @mul_bool_zext_one_user(i1 %x) { 539; CHECK-LABEL: @mul_bool_zext_one_user( 540; CHECK-NEXT: [[R:%.*]] = zext i1 [[X:%.*]] to i32 541; CHECK-NEXT: ret i32 [[R]] 542; 543 %sx = zext i1 %x to i32 544 %r = mul i32 %sx, %sx 545 ret i32 %r 546} 547 548define i32 @mul_bool_sext_one_extra_user(i1 %x) { 549; CHECK-LABEL: @mul_bool_sext_one_extra_user( 550; CHECK-NEXT: [[SX:%.*]] = sext i1 [[X:%.*]] to i32 551; CHECK-NEXT: call void @use32(i32 [[SX]]) 552; CHECK-NEXT: [[R:%.*]] = zext i1 [[X]] to i32 553; CHECK-NEXT: ret i32 [[R]] 554; 555 %sx = sext i1 %x to i32 556 call void @use32(i32 %sx) 557 %r = mul i32 %sx, %sx 558 ret i32 %r 559} 560 561define i32 @mul_bool_zext_one_extra_user(i1 %x) { 562; CHECK-LABEL: @mul_bool_zext_one_extra_user( 563; CHECK-NEXT: [[SX:%.*]] = zext i1 [[X:%.*]] to i32 564; CHECK-NEXT: call void @use32(i32 [[SX]]) 565; CHECK-NEXT: [[R:%.*]] = zext i1 [[X]] to i32 566; CHECK-NEXT: ret i32 [[R]] 567; 568 %sx = zext i1 %x to i32 569 call void @use32(i32 %sx) 570 %r = mul i32 %sx, %sx 571 ret i32 %r 572} 573 574define <3 x i32> @mul_bools_mixed_ext(<3 x i1> %x, <3 x i1> %y) { 575; CHECK-LABEL: @mul_bools_mixed_ext( 576; CHECK-NEXT: [[MULBOOL:%.*]] = and <3 x i1> [[X:%.*]], [[Y:%.*]] 577; CHECK-NEXT: [[R:%.*]] = sext <3 x i1> [[MULBOOL]] to <3 x i32> 578; CHECK-NEXT: ret <3 x i32> [[R]] 579; 580 %zx = zext <3 x i1> %x to <3 x i32> 581 %sy = sext <3 x i1> %y to <3 x i32> 582 %r = mul <3 x i32> %zx, %sy 583 ret <3 x i32> %r 584} 585 586define i32 @mul_bools_mixed_ext_use1(i1 %x, i1 %y) { 587; CHECK-LABEL: @mul_bools_mixed_ext_use1( 588; CHECK-NEXT: [[ZY:%.*]] = zext i1 [[Y:%.*]] to i32 589; CHECK-NEXT: call void @use32(i32 [[ZY]]) 590; CHECK-NEXT: [[MULBOOL:%.*]] = and i1 [[X:%.*]], [[Y]] 591; CHECK-NEXT: [[R:%.*]] = sext i1 [[MULBOOL]] to i32 592; CHECK-NEXT: ret i32 [[R]] 593; 594 %sx = sext i1 %x to i32 595 %zy = zext i1 %y to i32 596 call void @use32(i32 %zy) 597 %r = mul i32 %sx, %zy 598 ret i32 %r 599} 600 601define i32 @mul_bools_mixed_ext_use2(i1 %x, i1 %y) { 602; CHECK-LABEL: @mul_bools_mixed_ext_use2( 603; CHECK-NEXT: [[SY:%.*]] = sext i1 [[Y:%.*]] to i32 604; CHECK-NEXT: call void @use32(i32 [[SY]]) 605; CHECK-NEXT: [[MULBOOL:%.*]] = and i1 [[Y]], [[X:%.*]] 606; CHECK-NEXT: [[R:%.*]] = sext i1 [[MULBOOL]] to i32 607; CHECK-NEXT: ret i32 [[R]] 608; 609 %zx = zext i1 %x to i32 610 %sy = sext i1 %y to i32 611 call void @use32(i32 %sy) 612 %r = mul i32 %sy, %zx 613 ret i32 %r 614} 615 616define i32 @mul_bools_mixed_ext_use3(i1 %x, i1 %y) { 617; CHECK-LABEL: @mul_bools_mixed_ext_use3( 618; CHECK-NEXT: [[SX:%.*]] = sext i1 [[X:%.*]] to i32 619; CHECK-NEXT: call void @use32(i32 [[SX]]) 620; CHECK-NEXT: [[ZY:%.*]] = zext i1 [[Y:%.*]] to i32 621; CHECK-NEXT: call void @use32(i32 [[ZY]]) 622; CHECK-NEXT: [[R:%.*]] = select i1 [[Y]], i32 [[SX]], i32 0 623; CHECK-NEXT: ret i32 [[R]] 624; 625 %sx = sext i1 %x to i32 626 call void @use32(i32 %sx) 627 %zy = zext i1 %y to i32 628 call void @use32(i32 %zy) 629 %r = mul i32 %zy, %sx 630 ret i32 %r 631} 632 633; (A >>u 31) * B --> (A >>s 31) & B --> A < 0 ? B : 0 634 635define i32 @signbit_mul(i32 %a, i32 %b) { 636; CHECK-LABEL: @signbit_mul( 637; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt i32 [[A:%.*]], 0 638; CHECK-NEXT: [[E:%.*]] = select i1 [[ISNEG]], i32 [[B:%.*]], i32 0 639; CHECK-NEXT: ret i32 [[E]] 640; 641 %d = lshr i32 %a, 31 642 %e = mul i32 %d, %b 643 ret i32 %e 644} 645 646define i32 @signbit_mul_commute_extra_use(i32 %a, i32 %b) { 647; CHECK-LABEL: @signbit_mul_commute_extra_use( 648; CHECK-NEXT: [[D:%.*]] = lshr i32 [[A:%.*]], 31 649; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt i32 [[A]], 0 650; CHECK-NEXT: [[E:%.*]] = select i1 [[ISNEG]], i32 [[B:%.*]], i32 0 651; CHECK-NEXT: call void @use32(i32 [[D]]) 652; CHECK-NEXT: ret i32 [[E]] 653; 654 %d = lshr i32 %a, 31 655 %e = mul i32 %b, %d 656 call void @use32(i32 %d) 657 ret i32 %e 658} 659 660; (A >>u 31)) * B --> (A >>s 31) & B --> A < 0 ? B : 0 661 662define <2 x i32> @signbit_mul_vec(<2 x i32> %a, <2 x i32> %b) { 663; CHECK-LABEL: @signbit_mul_vec( 664; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt <2 x i32> [[A:%.*]], zeroinitializer 665; CHECK-NEXT: [[E:%.*]] = select <2 x i1> [[ISNEG]], <2 x i32> [[B:%.*]], <2 x i32> zeroinitializer 666; CHECK-NEXT: ret <2 x i32> [[E]] 667; 668 %d = lshr <2 x i32> %a, <i32 31, i32 31> 669 %e = mul <2 x i32> %d, %b 670 ret <2 x i32> %e 671} 672 673define <2 x i32> @signbit_mul_vec_commute(<2 x i32> %a, <2 x i32> %b) { 674; CHECK-LABEL: @signbit_mul_vec_commute( 675; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt <2 x i32> [[A:%.*]], zeroinitializer 676; CHECK-NEXT: [[E:%.*]] = select <2 x i1> [[ISNEG]], <2 x i32> [[B:%.*]], <2 x i32> zeroinitializer 677; CHECK-NEXT: ret <2 x i32> [[E]] 678; 679 %d = lshr <2 x i32> %a, <i32 31, i32 31> 680 %e = mul <2 x i32> %b, %d 681 ret <2 x i32> %e 682} 683 684; (A & 1) * B --> (lowbit A) ? B : 0 685 686define i32 @lowbit_mul(i32 %a, i32 %b) { 687; CHECK-LABEL: @lowbit_mul( 688; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[A:%.*]] to i1 689; CHECK-NEXT: [[E:%.*]] = select i1 [[TMP1]], i32 [[B:%.*]], i32 0 690; CHECK-NEXT: ret i32 [[E]] 691; 692 %d = and i32 %a, 1 693 %e = mul i32 %d, %b 694 ret i32 %e 695} 696 697; (A & 1) * B --> (lowbit A) ? B : 0 698 699define <2 x i17> @lowbit_mul_commute(<2 x i17> %a, <2 x i17> %p) { 700; CHECK-LABEL: @lowbit_mul_commute( 701; CHECK-NEXT: [[B:%.*]] = xor <2 x i17> [[P:%.*]], <i17 42, i17 43> 702; CHECK-NEXT: [[TMP1:%.*]] = trunc <2 x i17> [[A:%.*]] to <2 x i1> 703; CHECK-NEXT: [[E:%.*]] = select <2 x i1> [[TMP1]], <2 x i17> [[B]], <2 x i17> zeroinitializer 704; CHECK-NEXT: ret <2 x i17> [[E]] 705; 706 %b = xor <2 x i17> %p, <i17 42, i17 43> ; thwart complexity-based canonicalization 707 %d = and <2 x i17> %a, <i17 1, i17 1> 708 %e = mul <2 x i17> %b, %d 709 ret <2 x i17> %e 710} 711 712; negative test - extra use 713 714define i32 @lowbit_mul_use(i32 %a, i32 %b) { 715; CHECK-LABEL: @lowbit_mul_use( 716; CHECK-NEXT: [[D:%.*]] = and i32 [[A:%.*]], 1 717; CHECK-NEXT: call void @use32(i32 [[D]]) 718; CHECK-NEXT: [[E:%.*]] = mul nuw i32 [[D]], [[B:%.*]] 719; CHECK-NEXT: ret i32 [[E]] 720; 721 %d = and i32 %a, 1 722 call void @use32(i32 %d) 723 %e = mul i32 %d, %b 724 ret i32 %e 725} 726 727; negative test - wrong mask 728 729define i32 @not_lowbit_mul(i32 %a, i32 %b) { 730; CHECK-LABEL: @not_lowbit_mul( 731; CHECK-NEXT: [[D:%.*]] = and i32 [[A:%.*]], 2 732; CHECK-NEXT: [[E:%.*]] = mul i32 [[D]], [[B:%.*]] 733; CHECK-NEXT: ret i32 [[E]] 734; 735 %d = and i32 %a, 2 736 %e = mul i32 %d, %b 737 ret i32 %e 738} 739 740define i32 @signsplat_mul(i32 %x) { 741; CHECK-LABEL: @signsplat_mul( 742; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt i32 [[X:%.*]], 0 743; CHECK-NEXT: [[MUL:%.*]] = select i1 [[ISNEG]], i32 -42, i32 0 744; CHECK-NEXT: ret i32 [[MUL]] 745; 746 %ash = ashr i32 %x, 31 747 %mul = mul i32 %ash, 42 748 ret i32 %mul 749} 750 751define <2 x i32> @signsplat_mul_vec(<2 x i32> %x) { 752; CHECK-LABEL: @signsplat_mul_vec( 753; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt <2 x i32> [[X:%.*]], zeroinitializer 754; CHECK-NEXT: [[MUL:%.*]] = select <2 x i1> [[ISNEG]], <2 x i32> <i32 -42, i32 3>, <2 x i32> zeroinitializer 755; CHECK-NEXT: ret <2 x i32> [[MUL]] 756; 757 %ash = ashr <2 x i32> %x, <i32 31, i32 31> 758 %mul = mul <2 x i32> %ash, <i32 42, i32 -3> 759 ret <2 x i32> %mul 760} 761 762; negative test - wrong shift amount 763 764define i32 @not_signsplat_mul(i32 %x) { 765; CHECK-LABEL: @not_signsplat_mul( 766; CHECK-NEXT: [[ASH:%.*]] = ashr i32 [[X:%.*]], 30 767; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[ASH]], 42 768; CHECK-NEXT: ret i32 [[MUL]] 769; 770 %ash = ashr i32 %x, 30 771 %mul = mul i32 %ash, 42 772 ret i32 %mul 773} 774 775; negative test - extra use 776 777define i32 @signsplat_mul_use(i32 %x) { 778; CHECK-LABEL: @signsplat_mul_use( 779; CHECK-NEXT: [[ASH:%.*]] = ashr i32 [[X:%.*]], 31 780; CHECK-NEXT: call void @use32(i32 [[ASH]]) 781; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[ASH]], -42 782; CHECK-NEXT: ret i32 [[MUL]] 783; 784 %ash = ashr i32 %x, 31 785 call void @use32(i32 %ash) 786 %mul = mul i32 %ash, -42 787 ret i32 %mul 788} 789 790define i32 @test18(i32 %A, i32 %B) { 791; CHECK-LABEL: @test18( 792; CHECK-NEXT: ret i32 0 793; 794 %C = and i32 %A, 1 795 %D = and i32 %B, 1 796 %E = mul i32 %C, %D 797 %F = and i32 %E, 16 798 ret i32 %F 799} 800 801declare {i32, i1} @llvm.smul.with.overflow.i32(i32, i32) 802declare void @use(i1) 803 804define i32 @test19(i32 %A, i32 %B) { 805; CHECK-LABEL: @test19( 806; CHECK-NEXT: call void @use(i1 false) 807; CHECK-NEXT: ret i32 0 808; 809 %C = and i32 %A, 1 810 %D = and i32 %B, 1 811 812; It would be nice if we also started proving that this doesn't overflow. 813 %E = call {i32, i1} @llvm.smul.with.overflow.i32(i32 %C, i32 %D) 814 %F = extractvalue {i32, i1} %E, 0 815 %G = extractvalue {i32, i1} %E, 1 816 call void @use(i1 %G) 817 %H = and i32 %F, 16 818 ret i32 %H 819} 820 821define <2 x i64> @test20(<2 x i64> %A) { 822; CHECK-LABEL: @test20( 823; CHECK-NEXT: [[TMP1:%.*]] = mul <2 x i64> [[A:%.*]], <i64 3, i64 2> 824; CHECK-NEXT: [[C:%.*]] = add <2 x i64> [[TMP1]], <i64 36, i64 28> 825; CHECK-NEXT: ret <2 x i64> [[C]] 826; 827 %B = add <2 x i64> %A, <i64 12, i64 14> 828 %C = mul <2 x i64> %B, <i64 3, i64 2> 829 ret <2 x i64> %C 830} 831 832@g = internal global i32 0, align 4 833 834define i32 @PR20079(i32 %a) { 835; CHECK-LABEL: @PR20079( 836; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A:%.*]], -1 837; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[ADD]], ptrtoint (ptr @g to i32) 838; CHECK-NEXT: ret i32 [[MUL]] 839; 840 %add = add i32 %a, -1 841 %mul = mul nsw i32 %add, ptrtoint (ptr @g to i32) 842 ret i32 %mul 843} 844 845; Keep nuw flag in this change, https://alive2.llvm.org/ce/z/-Wowpk 846define i32 @add_mul_nuw(i32 %a) { 847; CHECK-LABEL: @add_mul_nuw( 848; CHECK-NEXT: [[TMP1:%.*]] = mul nuw i32 [[A:%.*]], 3 849; CHECK-NEXT: [[MUL:%.*]] = add nuw i32 [[TMP1]], 9 850; CHECK-NEXT: ret i32 [[MUL]] 851; 852 %add = add nuw i32 %a, 3 853 %mul = mul nuw i32 %add, 3 854 ret i32 %mul 855} 856 857; Don't propagate nsw flag in this change 858define i32 @add_mul_nsw(i32 %a) { 859; CHECK-LABEL: @add_mul_nsw( 860; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[A:%.*]], 3 861; CHECK-NEXT: [[MUL:%.*]] = add i32 [[TMP1]], 9 862; CHECK-NEXT: ret i32 [[MUL]] 863; 864 %add = add nsw i32 %a, 3 865 %mul = mul nsw i32 %add, 3 866 ret i32 %mul 867} 868 869; Only the add or only the mul has nuw, https://alive2.llvm.org/ce/z/vPwbEa 870define i32 @only_add_nuw(i32 %a) { 871; CHECK-LABEL: @only_add_nuw( 872; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[A:%.*]], 3 873; CHECK-NEXT: [[MUL:%.*]] = add i32 [[TMP1]], 9 874; CHECK-NEXT: ret i32 [[MUL]] 875; 876 %add = add nuw i32 %a, 3 877 %mul = mul i32 %add, 3 878 ret i32 %mul 879} 880 881define i32 @only_mul_nuw(i32 %a) { 882; CHECK-LABEL: @only_mul_nuw( 883; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[A:%.*]], 3 884; CHECK-NEXT: [[MUL:%.*]] = add i32 [[TMP1]], 9 885; CHECK-NEXT: ret i32 [[MUL]] 886; 887 %add = add i32 %a, 3 888 %mul = mul nuw i32 %add, 3 889 ret i32 %mul 890} 891 892; Don't propagate nsw flag in this change, https://alive2.llvm.org/ce/z/jJ8rZd 893define i32 @PR57278_shl(i32 %a) { 894; CHECK-LABEL: @PR57278_shl( 895; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[A:%.*]], 12 896; CHECK-NEXT: [[MUL:%.*]] = add i32 [[TMP1]], 9 897; CHECK-NEXT: ret i32 [[MUL]] 898; 899 %shl = shl nsw i32 %a, 2 900 %add = or i32 %shl, 3 901 %mul = mul nsw i32 %add, 3 902 ret i32 %mul 903} 904 905; Negative test: Have common bits set 906define i32 @PR57278_shl_1(i32 %a) { 907; CHECK-LABEL: @PR57278_shl_1( 908; CHECK-NEXT: [[SHL:%.*]] = shl nsw i32 [[A:%.*]], 2 909; CHECK-NEXT: [[ADD:%.*]] = or i32 [[SHL]], 4 910; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[ADD]], 3 911; CHECK-NEXT: ret i32 [[MUL]] 912; 913 %shl = shl nsw i32 %a, 2 914 %add = or i32 %shl, 4 915 %mul = mul nsw i32 %add, 3 916 ret i32 %mul 917} 918 919; Keep nuw flag in this change, https://alive2.llvm.org/ce/z/awsQrx 920define i32 @PR57278_mul(i32 %a) { 921; CHECK-LABEL: @PR57278_mul( 922; CHECK-NEXT: [[TMP1:%.*]] = mul nuw i32 [[A:%.*]], 36 923; CHECK-NEXT: [[MUL:%.*]] = add nuw i32 [[TMP1]], 9 924; CHECK-NEXT: ret i32 [[MUL]] 925; 926 %mul0 = mul nuw i32 %a, 12 927 %add = or i32 %mul0, 3 928 %mul = mul nuw i32 %add, 3 929 ret i32 %mul 930} 931 932; Negative test: Have common bits set, https://alive2.llvm.org/ce/z/bHZRh5 933define i32 @PR57278_mul_1(i32 %a) { 934; CHECK-LABEL: @PR57278_mul_1( 935; CHECK-NEXT: [[MUL0:%.*]] = mul nuw i32 [[A:%.*]], 12 936; CHECK-NEXT: [[ADD:%.*]] = or i32 [[MUL0]], 4 937; CHECK-NEXT: [[MUL:%.*]] = mul nuw i32 [[ADD]], 3 938; CHECK-NEXT: ret i32 [[MUL]] 939; 940 %mul0 = mul nuw i32 %a, 12 941 %add = or i32 %mul0, 4 942 %mul = mul nuw i32 %add, 3 943 ret i32 %mul 944} 945 946; Test the haveNoCommonBitsSet with assume, https://alive2.llvm.org/ce/z/AXKBjK 947define i32 @PR57278_mul_assume(i32 %a) { 948; CHECK-LABEL: @PR57278_mul_assume( 949; CHECK-NEXT: [[COMBITS:%.*]] = and i32 [[A:%.*]], 3 950; CHECK-NEXT: [[NOCOMBITS:%.*]] = icmp eq i32 [[COMBITS]], 0 951; CHECK-NEXT: call void @llvm.assume(i1 [[NOCOMBITS]]) 952; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[A]], 5 953; CHECK-NEXT: [[MUL:%.*]] = add i32 [[TMP1]], 15 954; CHECK-NEXT: ret i32 [[MUL]] 955; 956 %combits = and i32 %a , 3 957 %nocombits = icmp eq i32 %combits, 0 958 call void @llvm.assume(i1 %nocombits) 959 960 %add = or i32 %a, 3 961 %mul = mul i32 %add, 5 962 ret i32 %mul 963} 964 965declare void @llvm.assume(i1) 966 967define i32 @PR57278_or_disjoint_nuw(i32 %a) { 968; CHECK-LABEL: @PR57278_or_disjoint_nuw( 969; CHECK-NEXT: [[TMP1:%.*]] = mul nuw i32 [[A:%.*]], 3 970; CHECK-NEXT: [[MUL:%.*]] = add nuw i32 [[TMP1]], 9 971; CHECK-NEXT: ret i32 [[MUL]] 972; 973 %add = or disjoint i32 %a, 3 974 %mul = mul nuw i32 %add, 3 975 ret i32 %mul 976} 977 978define i32 @PR57278_or_disjoint_nsw(i32 %a) { 979; CHECK-LABEL: @PR57278_or_disjoint_nsw( 980; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[A:%.*]], 3 981; CHECK-NEXT: [[MUL:%.*]] = add i32 [[TMP1]], 9 982; CHECK-NEXT: ret i32 [[MUL]] 983; 984 %add = or disjoint i32 %a, 3 985 %mul = mul nsw i32 %add, 3 986 ret i32 %mul 987} 988 989; https://alive2.llvm.org/ce/z/XYpv9q 990define <2 x i32> @PR57278_shl_vec(<2 x i32> %v1) { 991; CHECK-LABEL: @PR57278_shl_vec( 992; CHECK-NEXT: [[TMP1:%.*]] = mul nuw <2 x i32> [[V1:%.*]], <i32 12, i32 24> 993; CHECK-NEXT: [[MUL:%.*]] = add nuw <2 x i32> [[TMP1]], splat (i32 9) 994; CHECK-NEXT: ret <2 x i32> [[MUL]] 995; 996 %shl = shl nuw <2 x i32> %v1, <i32 2, i32 3> 997 %add = or <2 x i32> %shl, <i32 3, i32 3> 998 %mul = mul nuw <2 x i32> %add, <i32 3, i32 3> 999 ret <2 x i32> %mul 1000} 1001 1002; TODO: vector with poison should also be supported, https://alive2.llvm.org/ce/z/XYpv9q 1003define <2 x i32> @PR57278_shl_vec_poison(<2 x i32> %v1) { 1004; CHECK-LABEL: @PR57278_shl_vec_poison( 1005; CHECK-NEXT: [[SHL:%.*]] = shl nuw <2 x i32> [[V1:%.*]], <i32 2, i32 poison> 1006; CHECK-NEXT: [[TMP1:%.*]] = mul nuw <2 x i32> [[SHL]], <i32 3, i32 poison> 1007; CHECK-NEXT: [[MUL:%.*]] = add nuw <2 x i32> [[TMP1]], <i32 9, i32 poison> 1008; CHECK-NEXT: ret <2 x i32> [[MUL]] 1009; 1010 %shl = shl nuw <2 x i32> %v1, <i32 2, i32 poison> 1011 %add = or <2 x i32> %shl, <i32 3, i32 poison> 1012 %mul = mul nuw <2 x i32> %add, <i32 3, i32 poison> 1013 ret <2 x i32> %mul 1014} 1015 1016define <2 x i1> @test21(<2 x i1> %A, <2 x i1> %B) { 1017; CHECK-LABEL: @test21( 1018; CHECK-NEXT: [[C:%.*]] = and <2 x i1> [[A:%.*]], [[B:%.*]] 1019; CHECK-NEXT: ret <2 x i1> [[C]] 1020; 1021 %C = mul <2 x i1> %A, %B 1022 ret <2 x i1> %C 1023} 1024 1025define i32 @test22(i32 %A) { 1026; CHECK-LABEL: @test22( 1027; CHECK-NEXT: [[B:%.*]] = sub nsw i32 0, [[A:%.*]] 1028; CHECK-NEXT: ret i32 [[B]] 1029; 1030 %B = mul nsw i32 %A, -1 1031 ret i32 %B 1032} 1033 1034define i32 @test23(i32 %A) { 1035; CHECK-LABEL: @test23( 1036; CHECK-NEXT: [[C:%.*]] = mul nuw i32 [[A:%.*]], 6 1037; CHECK-NEXT: ret i32 [[C]] 1038; 1039 %B = shl nuw i32 %A, 1 1040 %C = mul nuw i32 %B, 3 1041 ret i32 %C 1042} 1043 1044define i32 @test24(i32 %A) { 1045; CHECK-LABEL: @test24( 1046; CHECK-NEXT: [[C:%.*]] = mul nsw i32 [[A:%.*]], 6 1047; CHECK-NEXT: ret i32 [[C]] 1048; 1049 %B = shl nsw i32 %A, 1 1050 %C = mul nsw i32 %B, 3 1051 ret i32 %C 1052} 1053 1054define i32 @neg_neg_mul(i32 %A, i32 %B) { 1055; CHECK-LABEL: @neg_neg_mul( 1056; CHECK-NEXT: [[E:%.*]] = mul i32 [[A:%.*]], [[B:%.*]] 1057; CHECK-NEXT: ret i32 [[E]] 1058; 1059 %C = sub i32 0, %A 1060 %D = sub i32 0, %B 1061 %E = mul i32 %C, %D 1062 ret i32 %E 1063} 1064 1065define i32 @neg_neg_mul_nsw(i32 %A, i32 %B) { 1066; CHECK-LABEL: @neg_neg_mul_nsw( 1067; CHECK-NEXT: [[E:%.*]] = mul nsw i32 [[A:%.*]], [[B:%.*]] 1068; CHECK-NEXT: ret i32 [[E]] 1069; 1070 %C = sub nsw i32 0, %A 1071 %D = sub nsw i32 0, %B 1072 %E = mul nsw i32 %C, %D 1073 ret i32 %E 1074} 1075 1076define i124 @neg_neg_mul_apint(i124 %A, i124 %B) { 1077; CHECK-LABEL: @neg_neg_mul_apint( 1078; CHECK-NEXT: [[E:%.*]] = mul i124 [[A:%.*]], [[B:%.*]] 1079; CHECK-NEXT: ret i124 [[E]] 1080; 1081 %C = sub i124 0, %A 1082 %D = sub i124 0, %B 1083 %E = mul i124 %C, %D 1084 ret i124 %E 1085} 1086 1087define i32 @neg_mul_constant(i32 %A) { 1088; CHECK-LABEL: @neg_mul_constant( 1089; CHECK-NEXT: [[E:%.*]] = mul i32 [[A:%.*]], -7 1090; CHECK-NEXT: ret i32 [[E]] 1091; 1092 %C = sub i32 0, %A 1093 %E = mul i32 %C, 7 1094 ret i32 %E 1095} 1096 1097define i55 @neg_mul_constant_apint(i55 %A) { 1098; CHECK-LABEL: @neg_mul_constant_apint( 1099; CHECK-NEXT: [[E:%.*]] = mul i55 [[A:%.*]], -7 1100; CHECK-NEXT: ret i55 [[E]] 1101; 1102 %C = sub i55 0, %A 1103 %E = mul i55 %C, 7 1104 ret i55 %E 1105} 1106 1107define <3 x i8> @neg_mul_constant_vec(<3 x i8> %a) { 1108; CHECK-LABEL: @neg_mul_constant_vec( 1109; CHECK-NEXT: [[B:%.*]] = mul <3 x i8> [[A:%.*]], splat (i8 -5) 1110; CHECK-NEXT: ret <3 x i8> [[B]] 1111; 1112 %A = sub <3 x i8> zeroinitializer, %a 1113 %B = mul <3 x i8> %A, <i8 5, i8 5, i8 5> 1114 ret <3 x i8> %B 1115} 1116 1117define <3 x i4> @neg_mul_constant_vec_weird(<3 x i4> %a) { 1118; CHECK-LABEL: @neg_mul_constant_vec_weird( 1119; CHECK-NEXT: [[B:%.*]] = mul <3 x i4> [[A:%.*]], splat (i4 -5) 1120; CHECK-NEXT: ret <3 x i4> [[B]] 1121; 1122 %A = sub <3 x i4> zeroinitializer, %a 1123 %B = mul <3 x i4> %A, <i4 5, i4 5, i4 5> 1124 ret <3 x i4> %B 1125} 1126 1127define i64 @test29(i31 %A, i31 %B) { 1128; CHECK-LABEL: @test29( 1129; CHECK-NEXT: [[C:%.*]] = sext i31 [[A:%.*]] to i64 1130; CHECK-NEXT: [[D:%.*]] = sext i31 [[B:%.*]] to i64 1131; CHECK-NEXT: [[E:%.*]] = mul nsw i64 [[C]], [[D]] 1132; CHECK-NEXT: ret i64 [[E]] 1133; 1134 %C = sext i31 %A to i64 1135 %D = sext i31 %B to i64 1136 %E = mul i64 %C, %D 1137 ret i64 %E 1138} 1139 1140define i64 @test30(i32 %A, i32 %B) { 1141; CHECK-LABEL: @test30( 1142; CHECK-NEXT: [[C:%.*]] = zext i32 [[A:%.*]] to i64 1143; CHECK-NEXT: [[D:%.*]] = zext i32 [[B:%.*]] to i64 1144; CHECK-NEXT: [[E:%.*]] = mul nuw i64 [[C]], [[D]] 1145; CHECK-NEXT: ret i64 [[E]] 1146; 1147 %C = zext i32 %A to i64 1148 %D = zext i32 %B to i64 1149 %E = mul i64 %C, %D 1150 ret i64 %E 1151} 1152 1153@PR22087 = external global i32 1154define i32 @test31(i32 %V) { 1155; CHECK-LABEL: @test31( 1156; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr inttoptr (i64 4 to ptr), @PR22087 1157; CHECK-NEXT: [[EXT:%.*]] = zext i1 [[CMP]] to i32 1158; CHECK-NEXT: [[MUL1:%.*]] = shl i32 [[V:%.*]], [[EXT]] 1159; CHECK-NEXT: ret i32 [[MUL1]] 1160; 1161 %cmp = icmp ne ptr inttoptr (i64 4 to ptr), @PR22087 1162 %ext = zext i1 %cmp to i32 1163 %shl = shl i32 1, %ext 1164 %mul = mul i32 %V, %shl 1165 ret i32 %mul 1166} 1167 1168define i32 @test32(i32 %X) { 1169; CHECK-LABEL: @test32( 1170; CHECK-NEXT: [[MUL:%.*]] = shl i32 [[X:%.*]], 31 1171; CHECK-NEXT: ret i32 [[MUL]] 1172; 1173 %mul = mul nsw i32 %X, -2147483648 1174 ret i32 %mul 1175} 1176 1177define <2 x i32> @test32vec(<2 x i32> %X) { 1178; CHECK-LABEL: @test32vec( 1179; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i32> [[X:%.*]], splat (i32 31) 1180; CHECK-NEXT: ret <2 x i32> [[MUL]] 1181; 1182 %mul = mul nsw <2 x i32> %X, <i32 -2147483648, i32 -2147483648> 1183 ret <2 x i32> %mul 1184} 1185 1186define i32 @test33(i32 %X) { 1187; CHECK-LABEL: @test33( 1188; CHECK-NEXT: [[MUL:%.*]] = shl nsw i32 [[X:%.*]], 30 1189; CHECK-NEXT: ret i32 [[MUL]] 1190; 1191 %mul = mul nsw i32 %X, 1073741824 1192 ret i32 %mul 1193} 1194 1195define <2 x i32> @test33vec(<2 x i32> %X) { 1196; CHECK-LABEL: @test33vec( 1197; CHECK-NEXT: [[MUL:%.*]] = shl nsw <2 x i32> [[X:%.*]], splat (i32 30) 1198; CHECK-NEXT: ret <2 x i32> [[MUL]] 1199; 1200 %mul = mul nsw <2 x i32> %X, <i32 1073741824, i32 1073741824> 1201 ret <2 x i32> %mul 1202} 1203 1204define i128 @test34(i128 %X) { 1205; CHECK-LABEL: @test34( 1206; CHECK-NEXT: [[MUL:%.*]] = shl nsw i128 [[X:%.*]], 1 1207; CHECK-NEXT: ret i128 [[MUL]] 1208; 1209 %mul = mul nsw i128 %X, 2 1210 ret i128 %mul 1211} 1212 1213define i32 @test_mul_canonicalize_op0(i32 %x, i32 %y) { 1214; CHECK-LABEL: @test_mul_canonicalize_op0( 1215; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[X:%.*]], [[Y:%.*]] 1216; CHECK-NEXT: [[MUL:%.*]] = sub i32 0, [[TMP1]] 1217; CHECK-NEXT: ret i32 [[MUL]] 1218; 1219 %neg = sub i32 0, %x 1220 %mul = mul i32 %neg, %y 1221 ret i32 %mul 1222} 1223 1224define i32 @test_mul_canonicalize_op1(i32 %x, i32 %z) { 1225; CHECK-LABEL: @test_mul_canonicalize_op1( 1226; CHECK-NEXT: [[Y_NEG:%.*]] = mul i32 [[Z:%.*]], -3 1227; CHECK-NEXT: [[DOTNEG:%.*]] = mul i32 [[Y_NEG]], [[X:%.*]] 1228; CHECK-NEXT: ret i32 [[DOTNEG]] 1229; 1230 %y = mul i32 %z, 3 1231 %neg = sub i32 0, %x 1232 %mul = mul i32 %y, %neg 1233 ret i32 %mul 1234} 1235 1236define i32 @test_mul_canonicalize_nsw(i32 %x, i32 %y) { 1237; CHECK-LABEL: @test_mul_canonicalize_nsw( 1238; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[X:%.*]], [[Y:%.*]] 1239; CHECK-NEXT: [[MUL:%.*]] = sub i32 0, [[TMP1]] 1240; CHECK-NEXT: ret i32 [[MUL]] 1241; 1242 %neg = sub nsw i32 0, %x 1243 %mul = mul nsw i32 %neg, %y 1244 ret i32 %mul 1245} 1246 1247define <2 x i32> @test_mul_canonicalize_vec(<2 x i32> %x, <2 x i32> %y) { 1248; CHECK-LABEL: @test_mul_canonicalize_vec( 1249; CHECK-NEXT: [[TMP1:%.*]] = mul <2 x i32> [[X:%.*]], [[Y:%.*]] 1250; CHECK-NEXT: [[MUL:%.*]] = sub <2 x i32> zeroinitializer, [[TMP1]] 1251; CHECK-NEXT: ret <2 x i32> [[MUL]] 1252; 1253 %neg = sub <2 x i32> <i32 0, i32 0>, %x 1254 %mul = mul <2 x i32> %neg, %y 1255 ret <2 x i32> %mul 1256} 1257 1258define i32 @test_mul_canonicalize_multiple_uses(i32 %x, i32 %y) { 1259; CHECK-LABEL: @test_mul_canonicalize_multiple_uses( 1260; CHECK-NEXT: [[MUL_NEG:%.*]] = mul i32 [[X:%.*]], [[Y:%.*]] 1261; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[MUL_NEG]], [[X]] 1262; CHECK-NEXT: ret i32 [[MUL2]] 1263; 1264 %neg = sub i32 0, %x 1265 %mul = mul i32 %neg, %y 1266 %mul2 = mul i32 %mul, %neg 1267 ret i32 %mul2 1268} 1269 1270define i32 @mul_nsw_mul_nsw_neg(i32 %x, i32 %y) { 1271; CHECK-LABEL: @mul_nsw_mul_nsw_neg( 1272; CHECK-NEXT: [[MUL_NEG:%.*]] = mul i32 [[X:%.*]], [[Y:%.*]] 1273; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[MUL_NEG]], [[X]] 1274; CHECK-NEXT: ret i32 [[MUL2]] 1275; 1276 %neg = sub i32 0, %x 1277 %mul = mul nsw i32 %neg, %y 1278 %mul2 = mul nsw i32 %mul, %neg 1279 ret i32 %mul2 1280} 1281 1282define i32 @mul_mul_nsw_neg(i32 %x,i32 %y) { 1283; CHECK-LABEL: @mul_mul_nsw_neg( 1284; CHECK-NEXT: [[MUL_NEG:%.*]] = mul i32 [[X:%.*]], [[Y:%.*]] 1285; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[MUL_NEG]], [[X]] 1286; CHECK-NEXT: ret i32 [[MUL2]] 1287; 1288 %neg = sub i32 0, %x 1289 %mul = mul nsw i32 %neg, %y 1290 %mul2 = mul i32 %mul, %neg 1291 ret i32 %mul2 1292} 1293 1294define i32 @mul_nsw_mul_neg(i32 %x,i32 %y) { 1295; CHECK-LABEL: @mul_nsw_mul_neg( 1296; CHECK-NEXT: [[MUL_NEG:%.*]] = mul i32 [[X:%.*]], [[Y:%.*]] 1297; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[MUL_NEG]], [[X]] 1298; CHECK-NEXT: ret i32 [[MUL2]] 1299; 1300 %neg = sub i32 0, %x 1301 %mul = mul i32 %neg, %y 1302 %mul2 = mul nsw i32 %mul, %neg 1303 ret i32 %mul2 1304} 1305 1306define i32 @mul_nsw_mul_neg_onearg(i32 %x) { 1307; CHECK-LABEL: @mul_nsw_mul_neg_onearg( 1308; CHECK-NEXT: [[MUL_NEG:%.*]] = mul i32 [[X:%.*]], [[X]] 1309; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[MUL_NEG]], [[X]] 1310; CHECK-NEXT: ret i32 [[MUL2]] 1311; 1312 %neg = sub i32 0, %x 1313 %mul = mul i32 %neg, %x 1314 %mul2 = mul nsw i32 %mul, %neg 1315 ret i32 %mul2 1316} 1317 1318define i8 @mul_mul_nsw_neg_onearg(i8 %x) { 1319; CHECK-LABEL: @mul_mul_nsw_neg_onearg( 1320; CHECK-NEXT: [[MUL_NEG:%.*]] = mul i8 [[X:%.*]], [[X]] 1321; CHECK-NEXT: [[MUL2:%.*]] = mul i8 [[MUL_NEG]], [[X]] 1322; CHECK-NEXT: ret i8 [[MUL2]] 1323; 1324 %neg = sub i8 0, %x 1325 %mul = mul nsw i8 %neg, %x 1326 %mul2 = mul i8 %mul, %neg 1327 ret i8 %mul2 1328} 1329 1330define i32 @mul_nsw_mul_nsw_neg_onearg(i32 %x) { 1331; CHECK-LABEL: @mul_nsw_mul_nsw_neg_onearg( 1332; CHECK-NEXT: [[MUL_NEG:%.*]] = mul i32 [[X:%.*]], [[X]] 1333; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[MUL_NEG]], [[X]] 1334; CHECK-NEXT: ret i32 [[MUL2]] 1335; 1336 %neg = sub i32 0, %x 1337 %mul = mul nsw i32 %neg, %x 1338 %mul2 = mul nsw i32 %mul, %neg 1339 ret i32 %mul2 1340} 1341 1342define i32 @mul_nsw_shl_nsw_neg(i32 %x, i32 %y) { 1343; CHECK-LABEL: @mul_nsw_shl_nsw_neg( 1344; CHECK-NEXT: [[SHL_NEG:%.*]] = shl i32 [[X:%.*]], [[Y:%.*]] 1345; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[SHL_NEG]], [[X]] 1346; CHECK-NEXT: ret i32 [[MUL]] 1347; 1348 %neg = sub i32 0, %x 1349 %shl = shl nsw i32 %neg, %y 1350 %mul = mul nsw i32 %shl, %neg 1351 ret i32 %mul 1352} 1353 1354define i32 @mul_shl_nsw_neg(i32 %x,i32 %y) { 1355; CHECK-LABEL: @mul_shl_nsw_neg( 1356; CHECK-NEXT: [[SHL_NEG:%.*]] = shl i32 [[X:%.*]], [[Y:%.*]] 1357; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[SHL_NEG]], [[X]] 1358; CHECK-NEXT: ret i32 [[MUL]] 1359; 1360 %neg = sub i32 0, %x 1361 %shl = shl nsw i32 %neg, %y 1362 %mul = mul i32 %shl, %neg 1363 ret i32 %mul 1364} 1365 1366define i32 @mul_nsw_shl_neg(i32 %x,i32 %y) { 1367; CHECK-LABEL: @mul_nsw_shl_neg( 1368; CHECK-NEXT: [[SHL_NEG:%.*]] = shl i32 [[X:%.*]], [[Y:%.*]] 1369; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[SHL_NEG]], [[X]] 1370; CHECK-NEXT: ret i32 [[MUL]] 1371; 1372 %neg = sub i32 0, %x 1373 %shl = shl i32 %neg, %y 1374 %mul = mul nsw i32 %shl, %neg 1375 ret i32 %mul 1376} 1377 1378define i32 @mul_nsw_shl_neg_onearg(i32 %x) { 1379; CHECK-LABEL: @mul_nsw_shl_neg_onearg( 1380; CHECK-NEXT: [[SHL_NEG:%.*]] = shl i32 [[X:%.*]], [[X]] 1381; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[SHL_NEG]], [[X]] 1382; CHECK-NEXT: ret i32 [[MUL]] 1383; 1384 %neg = sub i32 0, %x 1385 %shl = shl i32 %neg, %x 1386 %mul = mul nsw i32 %shl, %neg 1387 ret i32 %mul 1388} 1389 1390define i8 @mul_shl_nsw_neg_onearg(i8 %x) { 1391; CHECK-LABEL: @mul_shl_nsw_neg_onearg( 1392; CHECK-NEXT: [[SHL_NEG:%.*]] = shl i8 [[X:%.*]], [[X]] 1393; CHECK-NEXT: [[MUL:%.*]] = mul i8 [[SHL_NEG]], [[X]] 1394; CHECK-NEXT: ret i8 [[MUL]] 1395; 1396 %neg = sub i8 0, %x 1397 %shl = shl nsw i8 %neg, %x 1398 %mul = mul i8 %shl, %neg 1399 ret i8 %mul 1400} 1401 1402define i32 @mul_nsw_shl_nsw_neg_onearg(i32 %x) { 1403; CHECK-LABEL: @mul_nsw_shl_nsw_neg_onearg( 1404; CHECK-NEXT: [[SHL_NEG:%.*]] = mul i32 [[X:%.*]], [[X]] 1405; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[SHL_NEG]], [[X]] 1406; CHECK-NEXT: ret i32 [[MUL]] 1407; 1408 %neg = sub i32 0, %x 1409 %shl = mul nsw i32 %neg, %x 1410 %mul = mul nsw i32 %shl, %neg 1411 ret i32 %mul 1412} 1413 1414define i32 @mul_use_mul_neg(i32 %x,i32 %y) { 1415; CHECK-LABEL: @mul_use_mul_neg( 1416; CHECK-NEXT: [[NEG:%.*]] = sub i32 0, [[X:%.*]] 1417; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[Y:%.*]], [[NEG]] 1418; CHECK-NEXT: call void @use32(i32 [[MUL]]) 1419; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[MUL]], [[NEG]] 1420; CHECK-NEXT: ret i32 [[MUL2]] 1421; 1422 %neg = sub i32 0, %x 1423 %mul = mul i32 %neg, %y 1424 call void @use32(i32 %mul) 1425 %mul2 = mul i32 %mul, %neg 1426 ret i32 %mul2 1427} 1428 1429define i32 @mul_shl_use_mul_neg(i32 %x,i32 %y) { 1430; CHECK-LABEL: @mul_shl_use_mul_neg( 1431; CHECK-NEXT: [[NEG:%.*]] = sub i32 0, [[X:%.*]] 1432; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[NEG]], [[Y:%.*]] 1433; CHECK-NEXT: call void @use32(i32 [[SHL]]) 1434; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[SHL]], [[NEG]] 1435; CHECK-NEXT: ret i32 [[MUL2]] 1436; 1437 %neg = sub i32 0, %x 1438 %shl = shl i32 %neg, %y 1439 call void @use32(i32 %shl) 1440 %mul2 = mul i32 %shl, %neg 1441 ret i32 %mul2 1442} 1443 1444@X = global i32 5 1445 1446define i64 @test_mul_canonicalize_neg_is_not_undone(i64 %L1) { 1447; Check we do not undo the canonicalization of 0 - (X * Y), if Y is a constant 1448; expr. 1449; CHECK-LABEL: @test_mul_canonicalize_neg_is_not_undone( 1450; CHECK-NEXT: [[B4:%.*]] = mul i64 [[L1:%.*]], sub (i64 0, i64 ptrtoint (ptr @X to i64)) 1451; CHECK-NEXT: ret i64 [[B4]] 1452; 1453 %v1 = ptrtoint ptr @X to i64 1454 %B8 = sub i64 0, %v1 1455 %B4 = mul i64 %B8, %L1 1456 ret i64 %B4 1457} 1458 1459define i32 @negate_if_true(i32 %x, i1 %cond) { 1460; CHECK-LABEL: @negate_if_true( 1461; CHECK-NEXT: [[TMP1:%.*]] = sub i32 0, [[X:%.*]] 1462; CHECK-NEXT: [[R:%.*]] = select i1 [[COND:%.*]], i32 [[TMP1]], i32 [[X]] 1463; CHECK-NEXT: ret i32 [[R]] 1464; 1465 %sel = select i1 %cond, i32 -1, i32 1 1466 %r = mul i32 %sel, %x 1467 ret i32 %r 1468} 1469 1470define i32 @negate_if_false(i32 %x, i1 %cond) { 1471; CHECK-LABEL: @negate_if_false( 1472; CHECK-NEXT: [[TMP1:%.*]] = sub i32 0, [[X:%.*]] 1473; CHECK-NEXT: [[R:%.*]] = select i1 [[COND:%.*]], i32 [[X]], i32 [[TMP1]] 1474; CHECK-NEXT: ret i32 [[R]] 1475; 1476 %sel = select i1 %cond, i32 1, i32 -1 1477 %r = mul i32 %sel, %x 1478 ret i32 %r 1479} 1480 1481define <2 x i8> @negate_if_true_commute(<2 x i8> %px, i1 %cond) { 1482; CHECK-LABEL: @negate_if_true_commute( 1483; CHECK-NEXT: [[X:%.*]] = sdiv <2 x i8> splat (i8 42), [[PX:%.*]] 1484; CHECK-NEXT: [[TMP1:%.*]] = sub nsw <2 x i8> zeroinitializer, [[X]] 1485; CHECK-NEXT: [[R:%.*]] = select i1 [[COND:%.*]], <2 x i8> [[TMP1]], <2 x i8> [[X]] 1486; CHECK-NEXT: ret <2 x i8> [[R]] 1487; 1488 %x = sdiv <2 x i8> <i8 42, i8 42>, %px ; thwart complexity-based canonicalization 1489 %sel = select i1 %cond, <2 x i8> <i8 -1, i8 -1>, <2 x i8> <i8 1, i8 1> 1490 %r = mul <2 x i8> %x, %sel 1491 ret <2 x i8> %r 1492} 1493 1494define <2 x i8> @negate_if_false_commute(<2 x i8> %px, <2 x i1> %cond) { 1495; CHECK-LABEL: @negate_if_false_commute( 1496; CHECK-NEXT: [[X:%.*]] = sdiv <2 x i8> <i8 42, i8 5>, [[PX:%.*]] 1497; CHECK-NEXT: [[TMP1:%.*]] = sub <2 x i8> zeroinitializer, [[X]] 1498; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[COND:%.*]], <2 x i8> [[X]], <2 x i8> [[TMP1]] 1499; CHECK-NEXT: ret <2 x i8> [[R]] 1500; 1501 %x = sdiv <2 x i8> <i8 42, i8 5>, %px ; thwart complexity-based canonicalization 1502 %sel = select <2 x i1> %cond, <2 x i8> <i8 1, i8 poison>, <2 x i8> <i8 -1, i8 -1> 1503 %r = mul <2 x i8> %x, %sel 1504 ret <2 x i8> %r 1505} 1506 1507; Negative test 1508 1509define i32 @negate_if_true_extra_use(i32 %x, i1 %cond) { 1510; CHECK-LABEL: @negate_if_true_extra_use( 1511; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i32 -1, i32 1 1512; CHECK-NEXT: call void @use32(i32 [[SEL]]) 1513; CHECK-NEXT: [[R:%.*]] = mul i32 [[SEL]], [[X:%.*]] 1514; CHECK-NEXT: ret i32 [[R]] 1515; 1516 %sel = select i1 %cond, i32 -1, i32 1 1517 call void @use32(i32 %sel) 1518 %r = mul i32 %sel, %x 1519 ret i32 %r 1520} 1521 1522; Negative test 1523 1524define <2 x i8> @negate_if_true_wrong_constant(<2 x i8> %px, i1 %cond) { 1525; CHECK-LABEL: @negate_if_true_wrong_constant( 1526; CHECK-NEXT: [[X:%.*]] = sdiv <2 x i8> splat (i8 42), [[PX:%.*]] 1527; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], <2 x i8> <i8 -1, i8 0>, <2 x i8> splat (i8 1) 1528; CHECK-NEXT: [[R:%.*]] = mul <2 x i8> [[X]], [[SEL]] 1529; CHECK-NEXT: ret <2 x i8> [[R]] 1530; 1531 %x = sdiv <2 x i8> <i8 42, i8 42>, %px ; thwart complexity-based canonicalization 1532 %sel = select i1 %cond, <2 x i8> <i8 -1, i8 0>, <2 x i8> <i8 1, i8 1> 1533 %r = mul <2 x i8> %x, %sel 1534 ret <2 x i8> %r 1535} 1536 1537; (C ? (X /exact Y) : 1) * Y -> C ? X : Y 1538define i32 @mul_div_select(i32 %x, i32 %y, i1 %c) { 1539; CHECK-LABEL: @mul_div_select( 1540; CHECK-NEXT: [[MUL:%.*]] = select i1 [[C:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]] 1541; CHECK-NEXT: ret i32 [[MUL]] 1542; 1543 %div = udiv exact i32 %x, %y 1544 %sel = select i1 %c, i32 %div, i32 1 1545 %mul = mul i32 %sel, %y 1546 ret i32 %mul 1547} 1548 1549; fold mul(abs(x),abs(x)) -> mul(x,x) 1550define i31 @combine_mul_abs_i31(i31 %0) { 1551; CHECK-LABEL: @combine_mul_abs_i31( 1552; CHECK-NEXT: [[M:%.*]] = mul i31 [[TMP0:%.*]], [[TMP0]] 1553; CHECK-NEXT: ret i31 [[M]] 1554; 1555 %c = icmp slt i31 %0, 0 1556 %s = sub nsw i31 0, %0 1557 %r = select i1 %c, i31 %s, i31 %0 1558 %m = mul i31 %r, %r 1559 ret i31 %m 1560} 1561 1562define i32 @combine_mul_abs_i32(i32 %0) { 1563; CHECK-LABEL: @combine_mul_abs_i32( 1564; CHECK-NEXT: [[M:%.*]] = mul i32 [[TMP0:%.*]], [[TMP0]] 1565; CHECK-NEXT: ret i32 [[M]] 1566; 1567 %c = icmp slt i32 %0, 0 1568 %s = sub nsw i32 0, %0 1569 %r = select i1 %c, i32 %s, i32 %0 1570 %m = mul i32 %r, %r 1571 ret i32 %m 1572} 1573 1574define <4 x i32> @combine_mul_abs_v4i32(<4 x i32> %0) { 1575; CHECK-LABEL: @combine_mul_abs_v4i32( 1576; CHECK-NEXT: [[M:%.*]] = mul <4 x i32> [[TMP0:%.*]], [[TMP0]] 1577; CHECK-NEXT: ret <4 x i32> [[M]] 1578; 1579 %c = icmp slt <4 x i32> %0, zeroinitializer 1580 %s = sub nsw <4 x i32> zeroinitializer, %0 1581 %r = select <4 x i1> %c, <4 x i32> %s, <4 x i32> %0 1582 %m = mul <4 x i32> %r, %r 1583 ret <4 x i32> %m 1584} 1585 1586; fold mul(nabs(x),nabs(x)) -> mul(x,x) 1587define i31 @combine_mul_nabs_i31(i31 %0) { 1588; CHECK-LABEL: @combine_mul_nabs_i31( 1589; CHECK-NEXT: [[M:%.*]] = mul i31 [[TMP0:%.*]], [[TMP0]] 1590; CHECK-NEXT: ret i31 [[M]] 1591; 1592 %c = icmp slt i31 %0, 0 1593 %s = sub nsw i31 0, %0 1594 %r = select i1 %c, i31 %0, i31 %s 1595 %m = mul i31 %r, %r 1596 ret i31 %m 1597} 1598 1599define i32 @combine_mul_nabs_i32(i32 %0) { 1600; CHECK-LABEL: @combine_mul_nabs_i32( 1601; CHECK-NEXT: [[M:%.*]] = mul i32 [[TMP0:%.*]], [[TMP0]] 1602; CHECK-NEXT: ret i32 [[M]] 1603; 1604 %c = icmp slt i32 %0, 0 1605 %s = sub nsw i32 0, %0 1606 %r = select i1 %c, i32 %0, i32 %s 1607 %m = mul i32 %r, %r 1608 ret i32 %m 1609} 1610 1611define <4 x i32> @combine_mul_nabs_v4i32(<4 x i32> %0) { 1612; CHECK-LABEL: @combine_mul_nabs_v4i32( 1613; CHECK-NEXT: [[M:%.*]] = mul <4 x i32> [[TMP0:%.*]], [[TMP0]] 1614; CHECK-NEXT: ret <4 x i32> [[M]] 1615; 1616 %c = icmp slt <4 x i32> %0, zeroinitializer 1617 %s = sub nsw <4 x i32> zeroinitializer, %0 1618 %r = select <4 x i1> %c, <4 x i32> %0, <4 x i32> %s 1619 %m = mul <4 x i32> %r, %r 1620 ret <4 x i32> %m 1621} 1622 1623define i32 @combine_mul_abs_intrin(i32 %x) { 1624; CHECK-LABEL: @combine_mul_abs_intrin( 1625; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X:%.*]], [[X]] 1626; CHECK-NEXT: ret i32 [[MUL]] 1627; 1628 %abs = call i32 @llvm.abs.i32(i32 %x, i1 false) 1629 %mul = mul i32 %abs, %abs 1630 ret i32 %mul 1631} 1632 1633define i32 @combine_mul_nabs_intrin(i32 %x) { 1634; CHECK-LABEL: @combine_mul_nabs_intrin( 1635; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X:%.*]], [[X]] 1636; CHECK-NEXT: ret i32 [[MUL]] 1637; 1638 %abs = call i32 @llvm.abs.i32(i32 %x, i1 false) 1639 %neg = sub i32 0, %abs 1640 %mul = mul i32 %neg, %neg 1641 ret i32 %mul 1642} 1643 1644; z * splat(0) = splat(0), even for scalable vectors 1645define <vscale x 2 x i64> @mul_scalable_splat_zero(<vscale x 2 x i64> %z) { 1646; CHECK-LABEL: @mul_scalable_splat_zero( 1647; CHECK-NEXT: ret <vscale x 2 x i64> zeroinitializer 1648; 1649 %shuf = shufflevector <vscale x 2 x i64> insertelement (<vscale x 2 x i64> poison, i64 0, i32 0), <vscale x 2 x i64> poison, <vscale x 2 x i32> zeroinitializer 1650 %t3 = mul <vscale x 2 x i64> %shuf, %z 1651 ret <vscale x 2 x i64> %t3 1652} 1653 1654; fold mul(abs(x),abs(y)) -> abs(mul(x,y)) 1655define i32 @combine_mul_abs_x_abs_y(i32 %x, i32 %y) { 1656; CHECK-LABEL: @combine_mul_abs_x_abs_y( 1657; CHECK-NEXT: [[TMP1:%.*]] = mul nsw i32 [[X:%.*]], [[Y:%.*]] 1658; CHECK-NEXT: [[MUL:%.*]] = call i32 @llvm.abs.i32(i32 [[TMP1]], i1 true) 1659; CHECK-NEXT: ret i32 [[MUL]] 1660; 1661 %abs_x = call i32 @llvm.abs.i32(i32 %x, i1 true) 1662 %abs_y = call i32 @llvm.abs.i32(i32 %y, i1 true) 1663 %mul = mul nsw i32 %abs_x, %abs_y 1664 ret i32 %mul 1665} 1666 1667define i32 @combine_mul_abs_x_abs_y_no_nsw(i32 %x, i32 %y) { 1668; CHECK-LABEL: @combine_mul_abs_x_abs_y_no_nsw( 1669; CHECK-NEXT: [[ABS_X:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 true) 1670; CHECK-NEXT: [[ABS_Y:%.*]] = call i32 @llvm.abs.i32(i32 [[Y:%.*]], i1 true) 1671; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[ABS_X]], [[ABS_Y]] 1672; CHECK-NEXT: ret i32 [[MUL]] 1673; 1674 %abs_x = call i32 @llvm.abs.i32(i32 %x, i1 true) 1675 %abs_y = call i32 @llvm.abs.i32(i32 %y, i1 true) 1676 %mul = mul i32 %abs_x, %abs_y 1677 ret i32 %mul 1678} 1679 1680define i32 @combine_mul_abs_x_abs_y_poison_1(i32 %x, i32 %y) { 1681; CHECK-LABEL: @combine_mul_abs_x_abs_y_poison_1( 1682; CHECK-NEXT: [[ABS_X:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 true) 1683; CHECK-NEXT: [[ABS_Y:%.*]] = call i32 @llvm.abs.i32(i32 [[Y:%.*]], i1 false) 1684; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[ABS_X]], [[ABS_Y]] 1685; CHECK-NEXT: ret i32 [[MUL]] 1686; 1687 %abs_x = call i32 @llvm.abs.i32(i32 %x, i1 true) 1688 %abs_y = call i32 @llvm.abs.i32(i32 %y, i1 false) 1689 %mul = mul nsw i32 %abs_x, %abs_y 1690 ret i32 %mul 1691} 1692 1693define i32 @combine_mul_abs_x_abs_y_poison_2(i32 %x, i32 %y) { 1694; CHECK-LABEL: @combine_mul_abs_x_abs_y_poison_2( 1695; CHECK-NEXT: [[ABS_X:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 false) 1696; CHECK-NEXT: [[ABS_Y:%.*]] = call i32 @llvm.abs.i32(i32 [[Y:%.*]], i1 false) 1697; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[ABS_X]], [[ABS_Y]] 1698; CHECK-NEXT: ret i32 [[MUL]] 1699; 1700 %abs_x = call i32 @llvm.abs.i32(i32 %x, i1 false) 1701 %abs_y = call i32 @llvm.abs.i32(i32 %y, i1 false) 1702 %mul = mul nsw i32 %abs_x, %abs_y 1703 ret i32 %mul 1704} 1705 1706define i32 @combine_mul_abs_x_abs_y_not_oneuse(i32 %x, i32 %y) { 1707; CHECK-LABEL: @combine_mul_abs_x_abs_y_not_oneuse( 1708; CHECK-NEXT: [[ABS_X:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 true) 1709; CHECK-NEXT: [[ABS_Y:%.*]] = call i32 @llvm.abs.i32(i32 [[Y:%.*]], i1 true) 1710; CHECK-NEXT: [[ABS_X1:%.*]] = add nuw i32 [[ABS_Y]], 1 1711; CHECK-NEXT: [[RET:%.*]] = mul i32 [[ABS_X]], [[ABS_X1]] 1712; CHECK-NEXT: ret i32 [[RET]] 1713; 1714 %abs_x = call i32 @llvm.abs.i32(i32 %x, i1 true) 1715 %abs_y = call i32 @llvm.abs.i32(i32 %y, i1 true) 1716 %mul = mul nsw i32 %abs_x, %abs_y 1717 %ret = add i32 %mul, %abs_x 1718 ret i32 %ret 1719} 1720 1721; 1722; fold mul(sub(x,y),negpow2) -> shl(sub(y,x),log2(pow2)) 1723; 1724 1725define i32 @mulsub1(i32 %a0, i32 %a1) { 1726; CHECK-LABEL: @mulsub1( 1727; CHECK-NEXT: [[SUB_NEG:%.*]] = sub i32 [[A0:%.*]], [[A1:%.*]] 1728; CHECK-NEXT: [[MUL:%.*]] = shl i32 [[SUB_NEG]], 2 1729; CHECK-NEXT: ret i32 [[MUL]] 1730; 1731 %sub = sub i32 %a1, %a0 1732 %mul = mul i32 %sub, -4 1733 ret i32 %mul 1734} 1735 1736define <2 x i32> @mulsub1_vec(<2 x i32> %a0, <2 x i32> %a1) { 1737; CHECK-LABEL: @mulsub1_vec( 1738; CHECK-NEXT: [[SUB_NEG:%.*]] = sub <2 x i32> [[A0:%.*]], [[A1:%.*]] 1739; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i32> [[SUB_NEG]], splat (i32 2) 1740; CHECK-NEXT: ret <2 x i32> [[MUL]] 1741; 1742 %sub = sub <2 x i32> %a1, %a0 1743 %mul = mul <2 x i32> %sub, <i32 -4, i32 -4> 1744 ret <2 x i32> %mul 1745} 1746 1747define <2 x i32> @mulsub1_vec_nonuniform(<2 x i32> %a0, <2 x i32> %a1) { 1748; CHECK-LABEL: @mulsub1_vec_nonuniform( 1749; CHECK-NEXT: [[SUB_NEG:%.*]] = sub <2 x i32> [[A0:%.*]], [[A1:%.*]] 1750; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i32> [[SUB_NEG]], <i32 2, i32 3> 1751; CHECK-NEXT: ret <2 x i32> [[MUL]] 1752; 1753 %sub = sub <2 x i32> %a1, %a0 1754 %mul = mul <2 x i32> %sub, <i32 -4, i32 -8> 1755 ret <2 x i32> %mul 1756} 1757 1758define <2 x i32> @mulsub1_vec_nonuniform_poison(<2 x i32> %a0, <2 x i32> %a1) { 1759; CHECK-LABEL: @mulsub1_vec_nonuniform_poison( 1760; CHECK-NEXT: [[SUB_NEG:%.*]] = sub <2 x i32> [[A0:%.*]], [[A1:%.*]] 1761; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i32> [[SUB_NEG]], <i32 2, i32 0> 1762; CHECK-NEXT: ret <2 x i32> [[MUL]] 1763; 1764 %sub = sub <2 x i32> %a1, %a0 1765 %mul = mul <2 x i32> %sub, <i32 -4, i32 poison> 1766 ret <2 x i32> %mul 1767} 1768 1769define i32 @mulsub2(i32 %a0) { 1770; CHECK-LABEL: @mulsub2( 1771; CHECK-NEXT: [[SUB_NEG:%.*]] = shl i32 [[A0:%.*]], 2 1772; CHECK-NEXT: [[MUL:%.*]] = add i32 [[SUB_NEG]], -64 1773; CHECK-NEXT: ret i32 [[MUL]] 1774; 1775 %sub = sub i32 16, %a0 1776 %mul = mul i32 %sub, -4 1777 ret i32 %mul 1778} 1779 1780define <2 x i32> @mulsub2_vec(<2 x i32> %a0) { 1781; CHECK-LABEL: @mulsub2_vec( 1782; CHECK-NEXT: [[SUB_NEG:%.*]] = shl <2 x i32> [[A0:%.*]], splat (i32 2) 1783; CHECK-NEXT: [[MUL:%.*]] = add <2 x i32> [[SUB_NEG]], splat (i32 -64) 1784; CHECK-NEXT: ret <2 x i32> [[MUL]] 1785; 1786 %sub = sub <2 x i32> <i32 16, i32 16>, %a0 1787 %mul = mul <2 x i32> %sub, <i32 -4, i32 -4> 1788 ret <2 x i32> %mul 1789} 1790 1791define <2 x i32> @mulsub2_vec_nonuniform(<2 x i32> %a0) { 1792; CHECK-LABEL: @mulsub2_vec_nonuniform( 1793; CHECK-NEXT: [[SUB_NEG:%.*]] = add <2 x i32> [[A0:%.*]], <i32 -16, i32 -32> 1794; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i32> [[SUB_NEG]], <i32 2, i32 3> 1795; CHECK-NEXT: ret <2 x i32> [[MUL]] 1796; 1797 %sub = sub <2 x i32> <i32 16, i32 32>, %a0 1798 %mul = mul <2 x i32> %sub, <i32 -4, i32 -8> 1799 ret <2 x i32> %mul 1800} 1801 1802define <2 x i32> @mulsub2_vec_nonuniform_poison(<2 x i32> %a0) { 1803; CHECK-LABEL: @mulsub2_vec_nonuniform_poison( 1804; CHECK-NEXT: [[SUB_NEG:%.*]] = add <2 x i32> [[A0:%.*]], <i32 -16, i32 -32> 1805; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i32> [[SUB_NEG]], <i32 2, i32 0> 1806; CHECK-NEXT: ret <2 x i32> [[MUL]] 1807; 1808 %sub = sub <2 x i32> <i32 16, i32 32>, %a0 1809 %mul = mul <2 x i32> %sub, <i32 -4, i32 poison> 1810 ret <2 x i32> %mul 1811} 1812 1813define i8 @mulsub_nsw(i8 %a1, i8 %a2) { 1814; CHECK-LABEL: @mulsub_nsw( 1815; CHECK-NEXT: [[A_NEG:%.*]] = sub nsw i8 [[A2:%.*]], [[A1:%.*]] 1816; CHECK-NEXT: [[MUL:%.*]] = shl nsw i8 [[A_NEG]], 1 1817; CHECK-NEXT: ret i8 [[MUL]] 1818; 1819 %a = sub nsw i8 %a1, %a2 1820 %mul = mul nsw i8 %a, -2 1821 ret i8 %mul 1822} 1823 1824; It would be safe to keep the nsw on the shl here, but only because the mul 1825; to shl transform happens to replace poison with 0. 1826define <2 x i8> @mulsub_nsw_poison(<2 x i8> %a1, <2 x i8> %a2) { 1827; CHECK-LABEL: @mulsub_nsw_poison( 1828; CHECK-NEXT: [[A_NEG:%.*]] = sub nsw <2 x i8> [[A2:%.*]], [[A1:%.*]] 1829; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i8> [[A_NEG]], <i8 1, i8 0> 1830; CHECK-NEXT: ret <2 x i8> [[MUL]] 1831; 1832 %a = sub nsw <2 x i8> %a1, %a2 1833 %mul = mul nsw <2 x i8> %a, <i8 -2, i8 poison> 1834 ret <2 x i8> %mul 1835} 1836 1837define i32 @muladd2(i32 %a0) { 1838; CHECK-LABEL: @muladd2( 1839; CHECK-NEXT: [[TMP1:%.*]] = shl i32 [[A0:%.*]], 2 1840; CHECK-NEXT: [[MUL:%.*]] = sub i32 -64, [[TMP1]] 1841; CHECK-NEXT: ret i32 [[MUL]] 1842; 1843 %add = add i32 %a0, 16 1844 %mul = mul i32 %add, -4 1845 ret i32 %mul 1846} 1847 1848define <2 x i32> @muladd2_vec(<2 x i32> %a0) { 1849; CHECK-LABEL: @muladd2_vec( 1850; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i32> [[A0:%.*]], splat (i32 2) 1851; CHECK-NEXT: [[MUL:%.*]] = sub <2 x i32> splat (i32 -64), [[TMP1]] 1852; CHECK-NEXT: ret <2 x i32> [[MUL]] 1853; 1854 %add = add <2 x i32> %a0, <i32 16, i32 16> 1855 %mul = mul <2 x i32> %add, <i32 -4, i32 -4> 1856 ret <2 x i32> %mul 1857} 1858 1859define <2 x i32> @muladd2_vec_nonuniform(<2 x i32> %a0) { 1860; CHECK-LABEL: @muladd2_vec_nonuniform( 1861; CHECK-NEXT: [[ADD_NEG:%.*]] = sub <2 x i32> <i32 -16, i32 -32>, [[A0:%.*]] 1862; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i32> [[ADD_NEG]], <i32 2, i32 3> 1863; CHECK-NEXT: ret <2 x i32> [[MUL]] 1864; 1865 %add = add <2 x i32> %a0, <i32 16, i32 32> 1866 %mul = mul <2 x i32> %add, <i32 -4, i32 -8> 1867 ret <2 x i32> %mul 1868} 1869 1870define <2 x i32> @muladd2_vec_nonuniform_poison(<2 x i32> %a0) { 1871; CHECK-LABEL: @muladd2_vec_nonuniform_poison( 1872; CHECK-NEXT: [[ADD_NEG:%.*]] = sub <2 x i32> <i32 -16, i32 -32>, [[A0:%.*]] 1873; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i32> [[ADD_NEG]], <i32 2, i32 0> 1874; CHECK-NEXT: ret <2 x i32> [[MUL]] 1875; 1876 %add = add <2 x i32> %a0, <i32 16, i32 32> 1877 %mul = mul <2 x i32> %add, <i32 -4, i32 poison> 1878 ret <2 x i32> %mul 1879} 1880 1881define i32 @mulmuladd2(i32 %a0, i32 %a1) { 1882; CHECK-LABEL: @mulmuladd2( 1883; CHECK-NEXT: [[ADD_NEG:%.*]] = sub i32 1073741808, [[A0:%.*]] 1884; CHECK-NEXT: [[MUL1_NEG:%.*]] = mul i32 [[ADD_NEG]], [[A1:%.*]] 1885; CHECK-NEXT: [[MUL2:%.*]] = shl i32 [[MUL1_NEG]], 2 1886; CHECK-NEXT: ret i32 [[MUL2]] 1887; 1888 %add = add i32 %a0, 16 1889 %mul1 = mul i32 %add, %a1 1890 %mul2 = mul i32 %mul1, -4 1891 ret i32 %mul2 1892} 1893define i32 @mulmuladd2_extrause0(i32 %a0, i32 %a1) { 1894; CHECK-LABEL: @mulmuladd2_extrause0( 1895; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A0:%.*]], 16 1896; CHECK-NEXT: [[MUL1:%.*]] = mul i32 [[ADD]], [[A1:%.*]] 1897; CHECK-NEXT: call void @use32(i32 [[MUL1]]) 1898; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[MUL1]], -4 1899; CHECK-NEXT: ret i32 [[MUL2]] 1900; 1901 %add = add i32 %a0, 16 1902 %mul1 = mul i32 %add, %a1 1903 call void @use32(i32 %mul1) 1904 %mul2 = mul i32 %mul1, -4 1905 ret i32 %mul2 1906} 1907define i32 @mulmuladd2_extrause1(i32 %a0, i32 %a1) { 1908; CHECK-LABEL: @mulmuladd2_extrause1( 1909; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A0:%.*]], 16 1910; CHECK-NEXT: call void @use32(i32 [[ADD]]) 1911; CHECK-NEXT: [[MUL1:%.*]] = mul i32 [[ADD]], [[A1:%.*]] 1912; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[MUL1]], -4 1913; CHECK-NEXT: ret i32 [[MUL2]] 1914; 1915 %add = add i32 %a0, 16 1916 call void @use32(i32 %add) 1917 %mul1 = mul i32 %add, %a1 1918 %mul2 = mul i32 %mul1, -4 1919 ret i32 %mul2 1920} 1921define i32 @mulmuladd2_extrause2(i32 %a0, i32 %a1) { 1922; CHECK-LABEL: @mulmuladd2_extrause2( 1923; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A0:%.*]], 16 1924; CHECK-NEXT: call void @use32(i32 [[ADD]]) 1925; CHECK-NEXT: [[MUL1:%.*]] = mul i32 [[ADD]], [[A1:%.*]] 1926; CHECK-NEXT: call void @use32(i32 [[MUL1]]) 1927; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[MUL1]], -4 1928; CHECK-NEXT: ret i32 [[MUL2]] 1929; 1930 %add = add i32 %a0, 16 1931 call void @use32(i32 %add) 1932 %mul1 = mul i32 %add, %a1 1933 call void @use32(i32 %mul1) 1934 %mul2 = mul i32 %mul1, -4 1935 ret i32 %mul2 1936} 1937 1938define i32 @mulnot(i32 %a0) { 1939; CHECK-LABEL: @mulnot( 1940; CHECK-NEXT: [[ADD_NEG:%.*]] = shl i32 [[A0:%.*]], 2 1941; CHECK-NEXT: [[MUL:%.*]] = add i32 [[ADD_NEG]], 4 1942; CHECK-NEXT: ret i32 [[MUL]] 1943; 1944 %add = xor i32 %a0, -1 1945 %mul = mul i32 %add, -4 1946 ret i32 %mul 1947} 1948 1949define i32 @mulnot_extrause(i32 %a0) { 1950; CHECK-LABEL: @mulnot_extrause( 1951; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[A0:%.*]], -1 1952; CHECK-NEXT: call void @use32(i32 [[NOT]]) 1953; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[NOT]], -4 1954; CHECK-NEXT: ret i32 [[MUL]] 1955; 1956 %not = xor i32 %a0, -1 1957 call void @use32(i32 %not) 1958 %mul = mul i32 %not, -4 1959 ret i32 %mul 1960} 1961 1962define i32 @zext_negpow2(i8 %x) { 1963; CHECK-LABEL: @zext_negpow2( 1964; CHECK-NEXT: [[X_NEG:%.*]] = sub i8 0, [[X:%.*]] 1965; CHECK-NEXT: [[X_NEG_Z:%.*]] = zext i8 [[X_NEG]] to i32 1966; CHECK-NEXT: [[R:%.*]] = shl nuw i32 [[X_NEG_Z]], 24 1967; CHECK-NEXT: ret i32 [[R]] 1968; 1969 %zx = zext i8 %x to i32 1970 %r = mul i32 %zx, -16777216 ; -1 << 24 1971 ret i32 %r 1972} 1973 1974; splat constant 1975 1976define <2 x i14> @zext_negpow2_vec(<2 x i5> %x) { 1977; CHECK-LABEL: @zext_negpow2_vec( 1978; CHECK-NEXT: [[X_NEG:%.*]] = sub <2 x i5> zeroinitializer, [[X:%.*]] 1979; CHECK-NEXT: [[X_NEG_Z:%.*]] = zext <2 x i5> [[X_NEG]] to <2 x i14> 1980; CHECK-NEXT: [[R:%.*]] = shl <2 x i14> [[X_NEG_Z]], splat (i14 11) 1981; CHECK-NEXT: ret <2 x i14> [[R]] 1982; 1983 %zx = zext <2 x i5> %x to <2 x i14> 1984 %r = mul <2 x i14> %zx, <i14 -2048, i14 -2048> ; -1 << 11 1985 ret <2 x i14> %r 1986} 1987 1988; negative test - mul must be big enough to cover bitwidth diff 1989 1990define i32 @zext_negpow2_too_small(i8 %x) { 1991; CHECK-LABEL: @zext_negpow2_too_small( 1992; CHECK-NEXT: [[ZX:%.*]] = zext i8 [[X:%.*]] to i32 1993; CHECK-NEXT: [[R:%.*]] = mul nsw i32 [[ZX]], -8388608 1994; CHECK-NEXT: ret i32 [[R]] 1995; 1996 %zx = zext i8 %x to i32 1997 %r = mul i32 %zx, -8388608 ; -1 << 23 1998 ret i32 %r 1999} 2000 2001define i16 @sext_negpow2(i9 %x) { 2002; CHECK-LABEL: @sext_negpow2( 2003; CHECK-NEXT: [[X_NEG:%.*]] = sub i9 0, [[X:%.*]] 2004; CHECK-NEXT: [[X_NEG_Z:%.*]] = zext i9 [[X_NEG]] to i16 2005; CHECK-NEXT: [[R:%.*]] = shl i16 [[X_NEG_Z]], 10 2006; CHECK-NEXT: ret i16 [[R]] 2007; 2008 %sx = sext i9 %x to i16 2009 %r = mul i16 %sx, -1024 ; -1 << 10 2010 ret i16 %r 2011} 2012 2013; splat constant with poison element(s) 2014 2015define <2 x i16> @sext_negpow2_vec(<2 x i8> %x) { 2016; CHECK-LABEL: @sext_negpow2_vec( 2017; CHECK-NEXT: [[X_NEG:%.*]] = sub <2 x i8> zeroinitializer, [[X:%.*]] 2018; CHECK-NEXT: [[X_NEG_Z:%.*]] = zext <2 x i8> [[X_NEG]] to <2 x i16> 2019; CHECK-NEXT: [[R:%.*]] = shl nuw <2 x i16> [[X_NEG_Z]], splat (i16 8) 2020; CHECK-NEXT: ret <2 x i16> [[R]] 2021; 2022 %sx = sext <2 x i8> %x to <2 x i16> 2023 %r = mul <2 x i16> %sx, <i16 -256, i16 poison> ; -1 << 8 2024 ret <2 x i16> %r 2025} 2026 2027; negative test - mul must be big enough to cover bitwidth diff 2028 2029define <2 x i16> @sext_negpow2_too_small_vec(<2 x i8> %x) { 2030; CHECK-LABEL: @sext_negpow2_too_small_vec( 2031; CHECK-NEXT: [[SX:%.*]] = sext <2 x i8> [[X:%.*]] to <2 x i16> 2032; CHECK-NEXT: [[R:%.*]] = mul nsw <2 x i16> [[SX]], <i16 -128, i16 poison> 2033; CHECK-NEXT: ret <2 x i16> [[R]] 2034; 2035 %sx = sext <2 x i8> %x to <2 x i16> 2036 %r = mul <2 x i16> %sx, <i16 -128, i16 poison> ; -1 << 7 2037 ret <2 x i16> %r 2038} 2039 2040; negative test - too many uses 2041 2042define i32 @zext_negpow2_use(i8 %x) { 2043; CHECK-LABEL: @zext_negpow2_use( 2044; CHECK-NEXT: [[ZX:%.*]] = zext i8 [[X:%.*]] to i32 2045; CHECK-NEXT: call void @use32(i32 [[ZX]]) 2046; CHECK-NEXT: [[R:%.*]] = mul i32 [[ZX]], -16777216 2047; CHECK-NEXT: ret i32 [[R]] 2048; 2049 %zx = zext i8 %x to i32 2050 call void @use32(i32 %zx) 2051 %r = mul i32 %zx, -16777216 ; -1 << 24 2052 ret i32 %r 2053} 2054 2055define i32 @mul_sext_icmp_with_zero(i32 %x) { 2056; CHECK-LABEL: @mul_sext_icmp_with_zero( 2057; CHECK-NEXT: ret i32 0 2058; 2059 %cmp = icmp eq i32 %x, 0 2060 %sext = sext i1 %cmp to i32 2061 %mul = mul i32 %sext, %x 2062 ret i32 %mul 2063} 2064 2065define i32 @test_mul_sext_bool(i1 %x, i32 %y) { 2066; CHECK-LABEL: @test_mul_sext_bool( 2067; CHECK-NEXT: [[TMP1:%.*]] = sub i32 0, [[Y:%.*]] 2068; CHECK-NEXT: [[MUL:%.*]] = select i1 [[X:%.*]], i32 [[TMP1]], i32 0 2069; CHECK-NEXT: ret i32 [[MUL]] 2070; 2071 %sext = sext i1 %x to i32 2072 %mul = mul i32 %sext, %y 2073 ret i32 %mul 2074} 2075 2076define i32 @test_mul_sext_bool_nuw(i1 %x, i32 %y) { 2077; CHECK-LABEL: @test_mul_sext_bool_nuw( 2078; CHECK-NEXT: [[TMP1:%.*]] = sub i32 0, [[Y:%.*]] 2079; CHECK-NEXT: [[MUL:%.*]] = select i1 [[X:%.*]], i32 [[TMP1]], i32 0 2080; CHECK-NEXT: ret i32 [[MUL]] 2081; 2082 %sext = sext i1 %x to i32 2083 %mul = mul nuw i32 %sext, %y 2084 ret i32 %mul 2085} 2086 2087define i32 @test_mul_sext_bool_nsw(i1 %x, i32 %y) { 2088; CHECK-LABEL: @test_mul_sext_bool_nsw( 2089; CHECK-NEXT: [[TMP1:%.*]] = sub nsw i32 0, [[Y:%.*]] 2090; CHECK-NEXT: [[MUL:%.*]] = select i1 [[X:%.*]], i32 [[TMP1]], i32 0 2091; CHECK-NEXT: ret i32 [[MUL]] 2092; 2093 %sext = sext i1 %x to i32 2094 %mul = mul nsw i32 %sext, %y 2095 ret i32 %mul 2096} 2097 2098define i32 @test_mul_sext_bool_nuw_nsw(i1 %x, i32 %y) { 2099; CHECK-LABEL: @test_mul_sext_bool_nuw_nsw( 2100; CHECK-NEXT: [[TMP1:%.*]] = sub nsw i32 0, [[Y:%.*]] 2101; CHECK-NEXT: [[MUL:%.*]] = select i1 [[X:%.*]], i32 [[TMP1]], i32 0 2102; CHECK-NEXT: ret i32 [[MUL]] 2103; 2104 %sext = sext i1 %x to i32 2105 %mul = mul nuw nsw i32 %sext, %y 2106 ret i32 %mul 2107} 2108 2109define i32 @test_mul_sext_bool_commuted(i1 %x, i32 %y) { 2110; CHECK-LABEL: @test_mul_sext_bool_commuted( 2111; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[Y:%.*]], -2 2112; CHECK-NEXT: [[YY_NEG:%.*]] = add i32 [[TMP1]], 1 2113; CHECK-NEXT: [[MUL:%.*]] = select i1 [[X:%.*]], i32 [[YY_NEG]], i32 0 2114; CHECK-NEXT: ret i32 [[MUL]] 2115; 2116 %yy = xor i32 %y, 1 2117 %sext = sext i1 %x to i32 2118 %mul = mul i32 %yy, %sext 2119 ret i32 %mul 2120} 2121 2122define i32 @test_mul_sext_nonbool(i2 %x, i32 %y) { 2123; CHECK-LABEL: @test_mul_sext_nonbool( 2124; CHECK-NEXT: [[SEXT:%.*]] = sext i2 [[X:%.*]] to i32 2125; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[Y:%.*]], [[SEXT]] 2126; CHECK-NEXT: ret i32 [[MUL]] 2127; 2128 %sext = sext i2 %x to i32 2129 %mul = mul i32 %sext, %y 2130 ret i32 %mul 2131} 2132 2133define i32 @test_mul_sext_multiuse(i1 %x, i32 %y) { 2134; CHECK-LABEL: @test_mul_sext_multiuse( 2135; CHECK-NEXT: [[SEXT:%.*]] = sext i1 [[X:%.*]] to i32 2136; CHECK-NEXT: tail call void @use(i32 [[SEXT]]) 2137; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[Y:%.*]], [[SEXT]] 2138; CHECK-NEXT: ret i32 [[MUL]] 2139; 2140 %sext = sext i1 %x to i32 2141 tail call void @use(i32 %sext) 2142 %mul = mul i32 %sext, %y 2143 ret i32 %mul 2144} 2145 2146define i8 @mul_nsw_nonneg(i8 %x, i8 %y) { 2147; CHECK-LABEL: @mul_nsw_nonneg( 2148; CHECK-NEXT: [[X_NNEG:%.*]] = icmp sgt i8 [[X:%.*]], -1 2149; CHECK-NEXT: call void @llvm.assume(i1 [[X_NNEG]]) 2150; CHECK-NEXT: [[Y_NNEG:%.*]] = icmp sgt i8 [[Y:%.*]], -1 2151; CHECK-NEXT: call void @llvm.assume(i1 [[Y_NNEG]]) 2152; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i8 [[X]], [[Y]] 2153; CHECK-NEXT: ret i8 [[MUL]] 2154; 2155 %x.nneg = icmp sge i8 %x, 0 2156 call void @llvm.assume(i1 %x.nneg) 2157 %y.nneg = icmp sge i8 %y, 0 2158 call void @llvm.assume(i1 %y.nneg) 2159 %mul = mul nsw i8 %x, %y 2160 ret i8 %mul 2161} 2162 2163define i8 @mul_nsw_not_nonneg1(i8 %x, i8 %y) { 2164; CHECK-LABEL: @mul_nsw_not_nonneg1( 2165; CHECK-NEXT: [[Y_NNEG:%.*]] = icmp sgt i8 [[Y:%.*]], -1 2166; CHECK-NEXT: call void @llvm.assume(i1 [[Y_NNEG]]) 2167; CHECK-NEXT: [[MUL:%.*]] = mul nsw i8 [[X:%.*]], [[Y]] 2168; CHECK-NEXT: ret i8 [[MUL]] 2169; 2170 %y.nneg = icmp sge i8 %y, 0 2171 call void @llvm.assume(i1 %y.nneg) 2172 %mul = mul nsw i8 %x, %y 2173 ret i8 %mul 2174} 2175 2176define i8 @mul_nsw_not_nonneg2(i8 %x, i8 %y) { 2177; CHECK-LABEL: @mul_nsw_not_nonneg2( 2178; CHECK-NEXT: [[X_NNEG:%.*]] = icmp sgt i8 [[X:%.*]], -1 2179; CHECK-NEXT: call void @llvm.assume(i1 [[X_NNEG]]) 2180; CHECK-NEXT: [[MUL:%.*]] = mul nsw i8 [[X]], [[Y:%.*]] 2181; CHECK-NEXT: ret i8 [[MUL]] 2182; 2183 %x.nneg = icmp sge i8 %x, 0 2184 call void @llvm.assume(i1 %x.nneg) 2185 %mul = mul nsw i8 %x, %y 2186 ret i8 %mul 2187} 2188 2189define i8 @mul_not_nsw_nonneg(i8 %x, i8 %y) { 2190; CHECK-LABEL: @mul_not_nsw_nonneg( 2191; CHECK-NEXT: [[X_NNEG:%.*]] = icmp sgt i8 [[X:%.*]], -1 2192; CHECK-NEXT: call void @llvm.assume(i1 [[X_NNEG]]) 2193; CHECK-NEXT: [[Y_NNEG:%.*]] = icmp sgt i8 [[Y:%.*]], -1 2194; CHECK-NEXT: call void @llvm.assume(i1 [[Y_NNEG]]) 2195; CHECK-NEXT: [[MUL:%.*]] = mul i8 [[X]], [[Y]] 2196; CHECK-NEXT: ret i8 [[MUL]] 2197; 2198 %x.nneg = icmp sge i8 %x, 0 2199 call void @llvm.assume(i1 %x.nneg) 2200 %y.nneg = icmp sge i8 %y, 0 2201 call void @llvm.assume(i1 %y.nneg) 2202 %mul = mul i8 %x, %y 2203 ret i8 %mul 2204} 2205