1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4declare void @use(i8) 5 6declare i8 @llvm.umin.i8(i8, i8) 7declare i8 @llvm.umax.i8(i8, i8) 8declare i8 @llvm.smin.i8(i8, i8) 9declare i8 @llvm.smax.i8(i8, i8) 10 11define i32 @t1(i16 zeroext %x, i32 %y) { 12; CHECK-LABEL: @t1( 13; CHECK-NEXT: [[CONV:%.*]] = zext i16 [[X:%.*]] to i32 14; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[Y:%.*]], 1 15; CHECK-NEXT: [[D1:%.*]] = lshr i32 [[CONV]], [[TMP1]] 16; CHECK-NEXT: ret i32 [[D1]] 17; 18 %conv = zext i16 %x to i32 19 %s = shl i32 2, %y 20 %d = sdiv i32 %conv, %s 21 ret i32 %d 22} 23 24define <2 x i32> @t1vec(<2 x i16> %x, <2 x i32> %y) { 25; CHECK-LABEL: @t1vec( 26; CHECK-NEXT: [[CONV:%.*]] = zext <2 x i16> [[X:%.*]] to <2 x i32> 27; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i32> [[Y:%.*]], <i32 1, i32 1> 28; CHECK-NEXT: [[D1:%.*]] = lshr <2 x i32> [[CONV]], [[TMP1]] 29; CHECK-NEXT: ret <2 x i32> [[D1]] 30; 31 %conv = zext <2 x i16> %x to <2 x i32> 32 %s = shl <2 x i32> <i32 2, i32 2>, %y 33 %d = sdiv <2 x i32> %conv, %s 34 ret <2 x i32> %d 35} 36 37; rdar://11721329 38define i64 @t2(i64 %x, i32 %y) { 39; CHECK-LABEL: @t2( 40; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[Y:%.*]] to i64 41; CHECK-NEXT: [[TMP2:%.*]] = lshr i64 [[X:%.*]], [[TMP1]] 42; CHECK-NEXT: ret i64 [[TMP2]] 43; 44 %1 = shl i32 1, %y 45 %2 = zext i32 %1 to i64 46 %3 = udiv i64 %x, %2 47 ret i64 %3 48} 49 50; PR13250 51define i64 @t3(i64 %x, i32 %y) { 52; CHECK-LABEL: @t3( 53; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[Y:%.*]], 2 54; CHECK-NEXT: [[TMP2:%.*]] = zext i32 [[TMP1]] to i64 55; CHECK-NEXT: [[TMP3:%.*]] = lshr i64 [[X:%.*]], [[TMP2]] 56; CHECK-NEXT: ret i64 [[TMP3]] 57; 58 %1 = shl i32 4, %y 59 %2 = zext i32 %1 to i64 60 %3 = udiv i64 %x, %2 61 ret i64 %3 62} 63 64define i32 @t4(i32 %x, i32 %y) { 65; CHECK-LABEL: @t4( 66; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.umax.i32(i32 [[Y:%.*]], i32 5) 67; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[X:%.*]], [[TMP1]] 68; CHECK-NEXT: ret i32 [[TMP2]] 69; 70 %1 = shl i32 1, %y 71 %2 = icmp ult i32 %1, 32 72 %3 = select i1 %2, i32 32, i32 %1 73 %4 = udiv i32 %x, %3 74 ret i32 %4 75} 76 77define i32 @t5(i1 %x, i1 %y, i32 %V) { 78; CHECK-LABEL: @t5( 79; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[X:%.*]], i32 5, i32 6 80; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[Y:%.*]], i32 [[TMP1]], i32 [[V:%.*]] 81; CHECK-NEXT: [[TMP3:%.*]] = lshr i32 [[V]], [[TMP2]] 82; CHECK-NEXT: ret i32 [[TMP3]] 83; 84 %1 = shl i32 1, %V 85 %2 = select i1 %x, i32 32, i32 64 86 %3 = select i1 %y, i32 %2, i32 %1 87 %4 = udiv i32 %V, %3 88 ret i32 %4 89} 90 91define i32 @t6(i32 %x, i32 %z) { 92; CHECK-LABEL: @t6( 93; CHECK-NEXT: [[X_IS_ZERO:%.*]] = icmp eq i32 [[X:%.*]], 0 94; CHECK-NEXT: [[DIVISOR:%.*]] = select i1 [[X_IS_ZERO]], i32 1, i32 [[X]] 95; CHECK-NEXT: [[Y:%.*]] = udiv i32 [[Z:%.*]], [[DIVISOR]] 96; CHECK-NEXT: ret i32 [[Y]] 97; 98 %x_is_zero = icmp eq i32 %x, 0 99 %divisor = select i1 %x_is_zero, i32 1, i32 %x 100 %y = udiv i32 %z, %divisor 101 ret i32 %y 102} 103 104define i8 @udiv_umin(i8 %x, i8 %y, i8 %z) { 105; CHECK-LABEL: @udiv_umin( 106; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[Y:%.*]], i8 [[Z:%.*]]) 107; CHECK-NEXT: [[D1:%.*]] = lshr i8 [[X:%.*]], [[TMP1]] 108; CHECK-NEXT: ret i8 [[D1]] 109; 110 %y2 = shl i8 1, %y 111 %z2 = shl i8 1, %z 112 %m = call i8 @llvm.umin.i8(i8 %y2, i8 %z2) 113 %d = udiv i8 %x, %m 114 ret i8 %d 115} 116 117define i8 @udiv_umax(i8 %x, i8 %y, i8 %z) { 118; CHECK-LABEL: @udiv_umax( 119; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[Y:%.*]], i8 [[Z:%.*]]) 120; CHECK-NEXT: [[D1:%.*]] = lshr i8 [[X:%.*]], [[TMP1]] 121; CHECK-NEXT: ret i8 [[D1]] 122; 123 %y2 = shl i8 1, %y 124 %z2 = shl i8 1, %z 125 %m = call i8 @llvm.umax.i8(i8 %y2, i8 %z2) 126 %d = udiv i8 %x, %m 127 ret i8 %d 128} 129 130; Negative test, cannot take exact log2 131define i8 @udiv_umin_(i8 %x, i8 %y, i8 %z) { 132; CHECK-LABEL: @udiv_umin_( 133; CHECK-NEXT: [[Y2:%.*]] = shl i8 1, [[Y:%.*]] 134; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[Y2]], i8 [[Z:%.*]]) 135; CHECK-NEXT: [[D:%.*]] = udiv i8 [[X:%.*]], [[M]] 136; CHECK-NEXT: ret i8 [[D]] 137; 138 %y2 = shl i8 1, %y 139 %m = call i8 @llvm.umin.i8(i8 %y2, i8 %z) 140 %d = udiv i8 %x, %m 141 ret i8 %d 142} 143 144; Negative test, extra use 145define i8 @udiv_umin_extra_use(i8 %x, i8 %y, i8 %z) { 146; CHECK-LABEL: @udiv_umin_extra_use( 147; CHECK-NEXT: [[Y2:%.*]] = shl i8 1, [[Y:%.*]] 148; CHECK-NEXT: [[Z2:%.*]] = shl i8 1, [[Z:%.*]] 149; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[Y2]], i8 [[Z2]]) 150; CHECK-NEXT: call void @use(i8 [[M]]) 151; CHECK-NEXT: [[D:%.*]] = udiv i8 [[X:%.*]], [[M]] 152; CHECK-NEXT: ret i8 [[D]] 153; 154 %y2 = shl i8 1, %y 155 %z2 = shl i8 1, %z 156 %m = call i8 @llvm.umin.i8(i8 %y2, i8 %z2) 157 call void @use(i8 %m) 158 %d = udiv i8 %x, %m 159 ret i8 %d 160} 161 162; Negative test, signed min/max 163define i8 @udiv_smin(i8 %x, i8 %y, i8 %z) { 164; CHECK-LABEL: @udiv_smin( 165; CHECK-NEXT: [[Y2:%.*]] = shl i8 1, [[Y:%.*]] 166; CHECK-NEXT: [[Z2:%.*]] = shl i8 1, [[Z:%.*]] 167; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[Y2]], i8 [[Z2]]) 168; CHECK-NEXT: [[D:%.*]] = udiv i8 [[X:%.*]], [[M]] 169; CHECK-NEXT: ret i8 [[D]] 170; 171 %y2 = shl i8 1, %y 172 %z2 = shl i8 1, %z 173 %m = call i8 @llvm.smin.i8(i8 %y2, i8 %z2) 174 %d = udiv i8 %x, %m 175 ret i8 %d 176} 177 178; Negative test, signed min/max 179define i8 @udiv_smax(i8 %x, i8 %y, i8 %z) { 180; CHECK-LABEL: @udiv_smax( 181; CHECK-NEXT: [[Y2:%.*]] = shl i8 1, [[Y:%.*]] 182; CHECK-NEXT: [[Z2:%.*]] = shl i8 1, [[Z:%.*]] 183; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[Y2]], i8 [[Z2]]) 184; CHECK-NEXT: [[D:%.*]] = udiv i8 [[X:%.*]], [[M]] 185; CHECK-NEXT: ret i8 [[D]] 186; 187 %y2 = shl i8 1, %y 188 %z2 = shl i8 1, %z 189 %m = call i8 @llvm.smax.i8(i8 %y2, i8 %z2) 190 %d = udiv i8 %x, %m 191 ret i8 %d 192} 193 194; (X << C1) / X -> 1 << C1 optimizations 195 196define i32 @t7(i32 %x) { 197; CHECK-LABEL: @t7( 198; CHECK-NEXT: ret i32 4 199; 200 %shl = shl nsw i32 %x, 2 201 %r = sdiv i32 %shl, %x 202 ret i32 %r 203} 204 205; make sure the previous opt doesn't take place for wrapped shifts 206 207define i32 @t8(i32 %x) { 208; CHECK-LABEL: @t8( 209; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[X:%.*]], 2 210; CHECK-NEXT: [[R:%.*]] = sdiv i32 [[SHL]], [[X]] 211; CHECK-NEXT: ret i32 [[R]] 212; 213 %shl = shl i32 %x, 2 214 %r = sdiv i32 %shl, %x 215 ret i32 %r 216} 217 218define <2 x i32> @t9(<2 x i32> %x) { 219; CHECK-LABEL: @t9( 220; CHECK-NEXT: ret <2 x i32> <i32 4, i32 8> 221; 222 %shl = shl nsw <2 x i32> %x, <i32 2, i32 3> 223 %r = sdiv <2 x i32> %shl, %x 224 ret <2 x i32> %r 225} 226 227define i32 @t10(i32 %x, i32 %y) { 228; CHECK-LABEL: @t10( 229; CHECK-NEXT: [[R:%.*]] = shl nsw i32 1, [[Y:%.*]] 230; CHECK-NEXT: ret i32 [[R]] 231; 232 %shl = shl nsw i32 %x, %y 233 %r = sdiv i32 %shl, %x 234 ret i32 %r 235} 236 237define <2 x i32> @t11(<2 x i32> %x, <2 x i32> %y) { 238; CHECK-LABEL: @t11( 239; CHECK-NEXT: [[R:%.*]] = shl nsw <2 x i32> <i32 1, i32 1>, [[Y:%.*]] 240; CHECK-NEXT: ret <2 x i32> [[R]] 241; 242 %shl = shl nsw <2 x i32> %x, %y 243 %r = sdiv <2 x i32> %shl, %x 244 ret <2 x i32> %r 245} 246 247define i32 @t12(i32 %x) { 248; CHECK-LABEL: @t12( 249; CHECK-NEXT: ret i32 4 250; 251 %shl = shl nuw i32 %x, 2 252 %r = udiv i32 %shl, %x 253 ret i32 %r 254} 255 256; make sure the previous opt doesn't take place for wrapped shifts 257 258define i32 @t13(i32 %x) { 259; CHECK-LABEL: @t13( 260; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[X:%.*]], 2 261; CHECK-NEXT: [[R:%.*]] = udiv i32 [[SHL]], [[X]] 262; CHECK-NEXT: ret i32 [[R]] 263; 264 %shl = shl i32 %x, 2 265 %r = udiv i32 %shl, %x 266 ret i32 %r 267} 268 269define <2 x i32> @t14(<2 x i32> %x) { 270; CHECK-LABEL: @t14( 271; CHECK-NEXT: ret <2 x i32> <i32 4, i32 8> 272; 273 %shl = shl nuw <2 x i32> %x, <i32 2, i32 3> 274 %r = udiv <2 x i32> %shl, %x 275 ret <2 x i32> %r 276} 277 278define i32 @t15(i32 %x, i32 %y) { 279; CHECK-LABEL: @t15( 280; CHECK-NEXT: [[R:%.*]] = shl nuw i32 1, [[Y:%.*]] 281; CHECK-NEXT: ret i32 [[R]] 282; 283 %shl = shl nuw i32 %x, %y 284 %r = udiv i32 %shl, %x 285 ret i32 %r 286} 287 288define <2 x i32> @t16(<2 x i32> %x, <2 x i32> %y) { 289; CHECK-LABEL: @t16( 290; CHECK-NEXT: [[R:%.*]] = shl nuw <2 x i32> <i32 1, i32 1>, [[Y:%.*]] 291; CHECK-NEXT: ret <2 x i32> [[R]] 292; 293 %shl = shl nuw <2 x i32> %x, %y 294 %r = udiv <2 x i32> %shl, %x 295 ret <2 x i32> %r 296} 297 298; (X * Y) s/ (X << Z) --> Y s/ (1 << Z) 299 300define i5 @sdiv_mul_shl_nsw(i5 %x, i5 %y, i5 %z) { 301; CHECK-LABEL: @sdiv_mul_shl_nsw( 302; CHECK-NEXT: [[TMP1:%.*]] = shl nuw i5 1, [[Z:%.*]] 303; CHECK-NEXT: [[D:%.*]] = sdiv i5 [[Y:%.*]], [[TMP1]] 304; CHECK-NEXT: ret i5 [[D]] 305; 306 %m1 = mul nsw i5 %x, %y 307 %m2 = shl nsw i5 %x, %z 308 %d = sdiv i5 %m1, %m2 309 ret i5 %d 310} 311 312; (Y * Z) s/ (X << Z) --> Y s/ (1 << Z) 313 314define i5 @sdiv_mul_shl_nsw_commute1(i5 %x, i5 %y, i5 %z) { 315; CHECK-LABEL: @sdiv_mul_shl_nsw_commute1( 316; CHECK-NEXT: [[TMP1:%.*]] = shl nuw i5 1, [[Z:%.*]] 317; CHECK-NEXT: [[D:%.*]] = sdiv i5 [[Y:%.*]], [[TMP1]] 318; CHECK-NEXT: ret i5 [[D]] 319; 320 %m1 = mul nsw i5 %y, %x 321 %m2 = shl nsw i5 %x, %z 322 %d = sdiv i5 %m1, %m2 323 ret i5 %d 324} 325 326; negative test - shl is not commutative 327 328define i5 @sdiv_mul_shl_nsw_commute2(i5 %x, i5 %y, i5 %z) { 329; CHECK-LABEL: @sdiv_mul_shl_nsw_commute2( 330; CHECK-NEXT: [[M1:%.*]] = mul nsw i5 [[Y:%.*]], [[X:%.*]] 331; CHECK-NEXT: [[M2:%.*]] = shl nsw i5 [[Z:%.*]], [[X]] 332; CHECK-NEXT: [[D:%.*]] = sdiv i5 [[M1]], [[M2]] 333; CHECK-NEXT: ret i5 [[D]] 334; 335 %m1 = mul nsw i5 %y, %x 336 %m2 = shl nsw i5 %z, %x 337 %d = sdiv i5 %m1, %m2 338 ret i5 %d 339} 340 341; extra use is ok 342 343define i8 @sdiv_mul_shl_nsw_use1(i8 %x, i8 %y, i8 %z) { 344; CHECK-LABEL: @sdiv_mul_shl_nsw_use1( 345; CHECK-NEXT: [[M1:%.*]] = mul nsw i8 [[X:%.*]], [[Y:%.*]] 346; CHECK-NEXT: call void @use(i8 [[M1]]) 347; CHECK-NEXT: [[TMP1:%.*]] = shl nuw i8 1, [[Z:%.*]] 348; CHECK-NEXT: [[D:%.*]] = sdiv i8 [[Y]], [[TMP1]] 349; CHECK-NEXT: ret i8 [[D]] 350; 351 %m1 = mul nsw i8 %x, %y 352 call void @use(i8 %m1) 353 %m2 = shl nsw i8 %x, %z 354 %d = sdiv i8 %m1, %m2 355 ret i8 %d 356} 357 358; extra use is ok 359 360define i8 @sdiv_mul_shl_nsw_use2(i8 %x, i8 %y, i8 %z) { 361; CHECK-LABEL: @sdiv_mul_shl_nsw_use2( 362; CHECK-NEXT: [[M2:%.*]] = shl nsw i8 [[X:%.*]], [[Z:%.*]] 363; CHECK-NEXT: call void @use(i8 [[M2]]) 364; CHECK-NEXT: [[TMP1:%.*]] = shl nuw i8 1, [[Z]] 365; CHECK-NEXT: [[D:%.*]] = sdiv i8 [[Y:%.*]], [[TMP1]] 366; CHECK-NEXT: ret i8 [[D]] 367; 368 %m1 = mul nsw i8 %x, %y 369 %m2 = shl nsw i8 %x, %z 370 call void @use(i8 %m2) 371 %d = sdiv i8 %m1, %m2 372 ret i8 %d 373} 374 375; negative test - both operands can't have extra uses 376 377define i8 @sdiv_mul_shl_nsw_use3(i8 %x, i8 %y, i8 %z) { 378; CHECK-LABEL: @sdiv_mul_shl_nsw_use3( 379; CHECK-NEXT: [[M1:%.*]] = mul nsw i8 [[X:%.*]], [[Y:%.*]] 380; CHECK-NEXT: call void @use(i8 [[M1]]) 381; CHECK-NEXT: [[M2:%.*]] = shl nsw i8 [[X]], [[Z:%.*]] 382; CHECK-NEXT: call void @use(i8 [[M2]]) 383; CHECK-NEXT: [[D:%.*]] = sdiv i8 [[M1]], [[M2]] 384; CHECK-NEXT: ret i8 [[D]] 385; 386 %m1 = mul nsw i8 %x, %y 387 call void @use(i8 %m1) 388 %m2 = shl nsw i8 %x, %z 389 call void @use(i8 %m2) 390 %d = sdiv i8 %m1, %m2 391 ret i8 %d 392} 393 394; negative test - shl must be divisor 395 396define i5 @sdiv_shl_mul_nsw(i5 %x, i5 %y, i5 %z) { 397; CHECK-LABEL: @sdiv_shl_mul_nsw( 398; CHECK-NEXT: [[M1:%.*]] = shl nsw i5 [[Z:%.*]], [[X:%.*]] 399; CHECK-NEXT: [[M2:%.*]] = mul nsw i5 [[X]], [[Y:%.*]] 400; CHECK-NEXT: [[D:%.*]] = sdiv i5 [[M1]], [[M2]] 401; CHECK-NEXT: ret i5 [[D]] 402; 403 %m1 = shl nsw i5 %z, %x 404 %m2 = mul nsw i5 %x, %y 405 %d = sdiv i5 %m1, %m2 406 ret i5 %d 407} 408 409; negative test - wrong no-wrap 410 411define i5 @sdiv_mul_shl_missing_nsw1(i5 %x, i5 %y, i5 %z) { 412; CHECK-LABEL: @sdiv_mul_shl_missing_nsw1( 413; CHECK-NEXT: [[M1:%.*]] = mul nsw i5 [[X:%.*]], [[Y:%.*]] 414; CHECK-NEXT: [[M2:%.*]] = shl nuw i5 [[Y]], [[Z:%.*]] 415; CHECK-NEXT: [[D:%.*]] = sdiv i5 [[M1]], [[M2]] 416; CHECK-NEXT: ret i5 [[D]] 417; 418 %m1 = mul nsw i5 %x, %y 419 %m2 = shl nuw i5 %y, %z 420 %d = sdiv i5 %m1, %m2 421 ret i5 %d 422} 423 424; negative test - wrong no-wrap 425 426define i5 @sdiv_mul_shl_missing_nsw2(i5 %x, i5 %y, i5 %z) { 427; CHECK-LABEL: @sdiv_mul_shl_missing_nsw2( 428; CHECK-NEXT: [[M1:%.*]] = mul nuw i5 [[X:%.*]], [[Y:%.*]] 429; CHECK-NEXT: [[M2:%.*]] = shl nsw i5 [[Y]], [[Z:%.*]] 430; CHECK-NEXT: [[D:%.*]] = sdiv i5 [[M1]], [[M2]] 431; CHECK-NEXT: ret i5 [[D]] 432; 433 %m1 = mul nuw i5 %x, %y 434 %m2 = shl nsw i5 %y, %z 435 %d = sdiv i5 %m1, %m2 436 ret i5 %d 437} 438 439; (X * Y) u/ (X << Z) --> Y u>> Z 440 441define i5 @udiv_mul_shl_nuw(i5 %x, i5 %y, i5 %z) { 442; CHECK-LABEL: @udiv_mul_shl_nuw( 443; CHECK-NEXT: [[D:%.*]] = lshr i5 [[Y:%.*]], [[Z:%.*]] 444; CHECK-NEXT: ret i5 [[D]] 445; 446 %m1 = mul nuw i5 %x, %y 447 %m2 = shl nuw i5 %x, %z 448 %d = udiv i5 %m1, %m2 449 ret i5 %d 450} 451 452; (Y * X) u/ (X << Z) --> Y u>> Z 453 454define i5 @udiv_mul_shl_nuw_commute1(i5 %x, i5 %y, i5 %z) { 455; CHECK-LABEL: @udiv_mul_shl_nuw_commute1( 456; CHECK-NEXT: [[D:%.*]] = lshr i5 [[Y:%.*]], [[Z:%.*]] 457; CHECK-NEXT: ret i5 [[D]] 458; 459 %m1 = mul nuw i5 %y, %x 460 %m2 = shl nuw i5 %x, %z 461 %d = udiv i5 %m1, %m2 462 ret i5 %d 463} 464 465; negative test - shl is not commutative 466 467define i5 @udiv_mul_shl_nuw_commute2(i5 %x, i5 %y, i5 %z) { 468; CHECK-LABEL: @udiv_mul_shl_nuw_commute2( 469; CHECK-NEXT: [[M1:%.*]] = mul nuw i5 [[X:%.*]], [[Y:%.*]] 470; CHECK-NEXT: [[M2:%.*]] = shl nuw i5 [[Z:%.*]], [[X]] 471; CHECK-NEXT: [[D:%.*]] = udiv i5 [[M1]], [[M2]] 472; CHECK-NEXT: ret i5 [[D]] 473; 474 %m1 = mul nuw i5 %x, %y 475 %m2 = shl nuw i5 %z, %x 476 %d = udiv i5 %m1, %m2 477 ret i5 %d 478} 479 480; extra uses are ok 481 482define i8 @udiv_mul_shl_nsw_use1(i8 %x, i8 %y, i8 %z) { 483; CHECK-LABEL: @udiv_mul_shl_nsw_use1( 484; CHECK-NEXT: [[M1:%.*]] = mul nuw i8 [[X:%.*]], [[Y:%.*]] 485; CHECK-NEXT: call void @use(i8 [[M1]]) 486; CHECK-NEXT: [[D:%.*]] = lshr i8 [[Y]], [[Z:%.*]] 487; CHECK-NEXT: ret i8 [[D]] 488; 489 %m1 = mul nuw i8 %x, %y 490 call void @use(i8 %m1) 491 %m2 = shl nuw i8 %x, %z 492 %d = udiv i8 %m1, %m2 493 ret i8 %d 494} 495 496; extra uses are ok 497 498define i8 @udiv_mul_shl_nsw_use2(i8 %x, i8 %y, i8 %z) { 499; CHECK-LABEL: @udiv_mul_shl_nsw_use2( 500; CHECK-NEXT: [[M2:%.*]] = shl nuw i8 [[X:%.*]], [[Z:%.*]] 501; CHECK-NEXT: call void @use(i8 [[M2]]) 502; CHECK-NEXT: [[D:%.*]] = lshr i8 [[Y:%.*]], [[Z]] 503; CHECK-NEXT: ret i8 [[D]] 504; 505 %m1 = mul nuw i8 %x, %y 506 %m2 = shl nuw i8 %x, %z 507 call void @use(i8 %m2) 508 %d = udiv i8 %m1, %m2 509 ret i8 %d 510} 511 512; extra uses are ok 513 514define i8 @udiv_mul_shl_nsw_use3(i8 %x, i8 %y, i8 %z) { 515; CHECK-LABEL: @udiv_mul_shl_nsw_use3( 516; CHECK-NEXT: [[M1:%.*]] = mul nuw i8 [[X:%.*]], [[Y:%.*]] 517; CHECK-NEXT: call void @use(i8 [[M1]]) 518; CHECK-NEXT: [[M2:%.*]] = shl nuw i8 [[X]], [[Z:%.*]] 519; CHECK-NEXT: call void @use(i8 [[M2]]) 520; CHECK-NEXT: [[D:%.*]] = lshr i8 [[Y]], [[Z]] 521; CHECK-NEXT: ret i8 [[D]] 522; 523 %m1 = mul nuw i8 %x, %y 524 call void @use(i8 %m1) 525 %m2 = shl nuw i8 %x, %z 526 call void @use(i8 %m2) 527 %d = udiv i8 %m1, %m2 528 ret i8 %d 529} 530 531; TODO: This can fold to (1<<z) / y 532 533define i5 @udiv_shl_mul_nuw(i5 %x, i5 %y, i5 %z) { 534; CHECK-LABEL: @udiv_shl_mul_nuw( 535; CHECK-NEXT: [[M1:%.*]] = shl nuw i5 [[X:%.*]], [[Z:%.*]] 536; CHECK-NEXT: [[M2:%.*]] = mul nuw i5 [[X]], [[Y:%.*]] 537; CHECK-NEXT: [[D:%.*]] = udiv i5 [[M1]], [[M2]] 538; CHECK-NEXT: ret i5 [[D]] 539; 540 %m1 = shl nuw i5 %x, %z 541 %m2 = mul nuw i5 %x, %y 542 %d = udiv i5 %m1, %m2 543 ret i5 %d 544} 545 546; negative test - wrong no-wrap 547 548define i5 @udiv_mul_shl_missing_nsw1(i5 %x, i5 %y, i5 %z) { 549; CHECK-LABEL: @udiv_mul_shl_missing_nsw1( 550; CHECK-NEXT: [[M1:%.*]] = mul nsw i5 [[X:%.*]], [[Y:%.*]] 551; CHECK-NEXT: [[M2:%.*]] = shl nuw i5 [[Y]], [[Z:%.*]] 552; CHECK-NEXT: [[D:%.*]] = udiv i5 [[M1]], [[M2]] 553; CHECK-NEXT: ret i5 [[D]] 554; 555 %m1 = mul nsw i5 %x, %y 556 %m2 = shl nuw i5 %y, %z 557 %d = udiv i5 %m1, %m2 558 ret i5 %d 559} 560 561; negative test - wrong no-wrap 562 563define i5 @udiv_mul_shl_missing_nsw2(i5 %x, i5 %y, i5 %z) { 564; CHECK-LABEL: @udiv_mul_shl_missing_nsw2( 565; CHECK-NEXT: [[M1:%.*]] = mul nuw i5 [[X:%.*]], [[Y:%.*]] 566; CHECK-NEXT: [[M2:%.*]] = shl nsw i5 [[Y]], [[Z:%.*]] 567; CHECK-NEXT: [[D:%.*]] = udiv i5 [[M1]], [[M2]] 568; CHECK-NEXT: ret i5 [[D]] 569; 570 %m1 = mul nuw i5 %x, %y 571 %m2 = shl nsw i5 %y, %z 572 %d = udiv i5 %m1, %m2 573 ret i5 %d 574} 575 576define i8 @udiv_shl_nuw(i8 %x, i8 %y, i8 %z) { 577; CHECK-LABEL: @udiv_shl_nuw( 578; CHECK-NEXT: [[S:%.*]] = shl nuw i8 [[Y:%.*]], [[Z:%.*]] 579; CHECK-NEXT: [[D:%.*]] = udiv i8 [[X:%.*]], [[S]] 580; CHECK-NEXT: ret i8 [[D]] 581; 582 %s = shl nuw i8 %y, %z 583 %d = udiv i8 %x, %s 584 ret i8 %d 585} 586 587define <2 x i4> @udiv_shl_nuw_exact(<2 x i4> %x, <2 x i4> %y, <2 x i4> %z) { 588; CHECK-LABEL: @udiv_shl_nuw_exact( 589; CHECK-NEXT: [[S:%.*]] = shl nuw <2 x i4> [[Y:%.*]], [[Z:%.*]] 590; CHECK-NEXT: [[D:%.*]] = udiv exact <2 x i4> [[X:%.*]], [[S]] 591; CHECK-NEXT: ret <2 x i4> [[D]] 592; 593 %s = shl nuw <2 x i4> %y, %z 594 %d = udiv exact <2 x i4> %x, %s 595 ret <2 x i4> %d 596} 597 598define i8 @udiv_shl(i8 %x, i8 %y, i8 %z) { 599; CHECK-LABEL: @udiv_shl( 600; CHECK-NEXT: [[S:%.*]] = shl i8 [[Y:%.*]], [[Z:%.*]] 601; CHECK-NEXT: [[D:%.*]] = udiv i8 [[X:%.*]], [[S]] 602; CHECK-NEXT: ret i8 [[D]] 603; 604 %s = shl i8 %y, %z 605 %d = udiv i8 %x, %s 606 ret i8 %d 607} 608 609define i8 @udiv_shl_nuw_use(i8 %x, i8 %y, i8 %z) { 610; CHECK-LABEL: @udiv_shl_nuw_use( 611; CHECK-NEXT: [[S:%.*]] = shl nuw i8 [[Y:%.*]], [[Z:%.*]] 612; CHECK-NEXT: call void @use(i8 [[S]]) 613; CHECK-NEXT: [[D:%.*]] = udiv i8 [[X:%.*]], [[S]] 614; CHECK-NEXT: ret i8 [[D]] 615; 616 %s = shl nuw i8 %y, %z 617 call void @use(i8 %s) 618 %d = udiv i8 %x, %s 619 ret i8 %d 620} 621