1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instsimplify -S | FileCheck %s 3 4define i32 @zero_dividend(i32 %A) { 5; CHECK-LABEL: @zero_dividend( 6; CHECK-NEXT: ret i32 0 7; 8 %B = sdiv i32 0, %A 9 ret i32 %B 10} 11 12define <2 x i32> @zero_dividend_vector(<2 x i32> %A) { 13; CHECK-LABEL: @zero_dividend_vector( 14; CHECK-NEXT: ret <2 x i32> zeroinitializer 15; 16 %B = udiv <2 x i32> zeroinitializer, %A 17 ret <2 x i32> %B 18} 19 20define <2 x i32> @zero_dividend_vector_poison_elt(<2 x i32> %A) { 21; CHECK-LABEL: @zero_dividend_vector_poison_elt( 22; CHECK-NEXT: ret <2 x i32> zeroinitializer 23; 24 %B = sdiv <2 x i32> <i32 0, i32 poison>, %A 25 ret <2 x i32> %B 26} 27 28; Division-by-zero is poison. UB in any vector lane means the whole op is poison. 29 30define <2 x i8> @sdiv_zero_elt_vec_constfold(<2 x i8> %x) { 31; CHECK-LABEL: @sdiv_zero_elt_vec_constfold( 32; CHECK-NEXT: ret <2 x i8> <i8 poison, i8 0> 33; 34 %div = sdiv <2 x i8> <i8 1, i8 2>, <i8 0, i8 -42> 35 ret <2 x i8> %div 36} 37 38define <2 x i8> @udiv_zero_elt_vec_constfold(<2 x i8> %x) { 39; CHECK-LABEL: @udiv_zero_elt_vec_constfold( 40; CHECK-NEXT: ret <2 x i8> <i8 0, i8 poison> 41; 42 %div = udiv <2 x i8> <i8 1, i8 2>, <i8 42, i8 0> 43 ret <2 x i8> %div 44} 45 46define <2 x i8> @sdiv_zero_elt_vec(<2 x i8> %x) { 47; CHECK-LABEL: @sdiv_zero_elt_vec( 48; CHECK-NEXT: [[DIV:%.*]] = sdiv <2 x i8> [[X:%.*]], <i8 -42, i8 0> 49; CHECK-NEXT: ret <2 x i8> [[DIV]] 50; 51 %div = sdiv <2 x i8> %x, <i8 -42, i8 0> 52 ret <2 x i8> %div 53} 54 55define <2 x i8> @udiv_zero_elt_vec(<2 x i8> %x) { 56; CHECK-LABEL: @udiv_zero_elt_vec( 57; CHECK-NEXT: [[DIV:%.*]] = udiv <2 x i8> [[X:%.*]], <i8 0, i8 42> 58; CHECK-NEXT: ret <2 x i8> [[DIV]] 59; 60 %div = udiv <2 x i8> %x, <i8 0, i8 42> 61 ret <2 x i8> %div 62} 63 64define <2 x i8> @sdiv_poison_elt_vec(<2 x i8> %x) { 65; CHECK-LABEL: @sdiv_poison_elt_vec( 66; CHECK-NEXT: [[DIV:%.*]] = sdiv <2 x i8> [[X:%.*]], <i8 -42, i8 poison> 67; CHECK-NEXT: ret <2 x i8> [[DIV]] 68; 69 %div = sdiv <2 x i8> %x, <i8 -42, i8 poison> 70 ret <2 x i8> %div 71} 72 73define <2 x i8> @udiv_poison_elt_vec(<2 x i8> %x) { 74; CHECK-LABEL: @udiv_poison_elt_vec( 75; CHECK-NEXT: [[DIV:%.*]] = udiv <2 x i8> [[X:%.*]], <i8 poison, i8 42> 76; CHECK-NEXT: ret <2 x i8> [[DIV]] 77; 78 %div = udiv <2 x i8> %x, <i8 poison, i8 42> 79 ret <2 x i8> %div 80} 81 82; Division-by-zero is poison. UB in any vector lane means the whole op is poison. 83; Thus, we can simplify this: if any element of 'y' is 0, we can do anything. 84; Therefore, assume that all elements of 'y' must be 1. 85 86define <2 x i1> @sdiv_bool_vec(<2 x i1> %x, <2 x i1> %y) { 87; CHECK-LABEL: @sdiv_bool_vec( 88; CHECK-NEXT: ret <2 x i1> [[X:%.*]] 89; 90 %div = sdiv <2 x i1> %x, %y 91 ret <2 x i1> %div 92} 93 94define <2 x i1> @udiv_bool_vec(<2 x i1> %x, <2 x i1> %y) { 95; CHECK-LABEL: @udiv_bool_vec( 96; CHECK-NEXT: ret <2 x i1> [[X:%.*]] 97; 98 %div = udiv <2 x i1> %x, %y 99 ret <2 x i1> %div 100} 101 102define i32 @zext_bool_udiv_divisor(i1 %x, i32 %y) { 103; CHECK-LABEL: @zext_bool_udiv_divisor( 104; CHECK-NEXT: ret i32 [[Y:%.*]] 105; 106 %ext = zext i1 %x to i32 107 %r = udiv i32 %y, %ext 108 ret i32 %r 109} 110 111define <2 x i32> @zext_bool_sdiv_divisor_vec(<2 x i1> %x, <2 x i32> %y) { 112; CHECK-LABEL: @zext_bool_sdiv_divisor_vec( 113; CHECK-NEXT: ret <2 x i32> [[Y:%.*]] 114; 115 %ext = zext <2 x i1> %x to <2 x i32> 116 %r = sdiv <2 x i32> %y, %ext 117 ret <2 x i32> %r 118} 119 120define i32 @udiv_dividend_known_smaller_than_constant_divisor(i32 %x) { 121; CHECK-LABEL: @udiv_dividend_known_smaller_than_constant_divisor( 122; CHECK-NEXT: ret i32 0 123; 124 %and = and i32 %x, 250 125 %div = udiv i32 %and, 251 126 ret i32 %div 127} 128 129define i32 @not_udiv_dividend_known_smaller_than_constant_divisor(i32 %x) { 130; CHECK-LABEL: @not_udiv_dividend_known_smaller_than_constant_divisor( 131; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 251 132; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[AND]], 251 133; CHECK-NEXT: ret i32 [[DIV]] 134; 135 %and = and i32 %x, 251 136 %div = udiv i32 %and, 251 137 ret i32 %div 138} 139 140define i32 @udiv_constant_dividend_known_smaller_than_divisor(i32 %x) { 141; CHECK-LABEL: @udiv_constant_dividend_known_smaller_than_divisor( 142; CHECK-NEXT: ret i32 0 143; 144 %or = or i32 %x, 251 145 %div = udiv i32 250, %or 146 ret i32 %div 147} 148 149define i32 @not_udiv_constant_dividend_known_smaller_than_divisor(i32 %x) { 150; CHECK-LABEL: @not_udiv_constant_dividend_known_smaller_than_divisor( 151; CHECK-NEXT: [[OR:%.*]] = or i32 [[X:%.*]], 251 152; CHECK-NEXT: [[DIV:%.*]] = udiv i32 251, [[OR]] 153; CHECK-NEXT: ret i32 [[DIV]] 154; 155 %or = or i32 %x, 251 156 %div = udiv i32 251, %or 157 ret i32 %div 158} 159 160define i8 @udiv_dividend_known_smaller_than_constant_divisor2(i1 %b) { 161; CHECK-LABEL: @udiv_dividend_known_smaller_than_constant_divisor2( 162; CHECK-NEXT: ret i8 0 163; 164 %t0 = zext i1 %b to i8 165 %xor = xor i8 %t0, 12 166 %r = udiv i8 %xor, 14 167 ret i8 %r 168} 169 170; negative test - dividend can equal 13 171 172define i8 @not_udiv_dividend_known_smaller_than_constant_divisor2(i1 %b) { 173; CHECK-LABEL: @not_udiv_dividend_known_smaller_than_constant_divisor2( 174; CHECK-NEXT: [[T0:%.*]] = zext i1 [[B:%.*]] to i8 175; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[T0]], 12 176; CHECK-NEXT: [[R:%.*]] = udiv i8 [[XOR]], 13 177; CHECK-NEXT: ret i8 [[R]] 178; 179 %t0 = zext i1 %b to i8 180 %xor = xor i8 %t0, 12 181 %r = udiv i8 %xor, 13 182 ret i8 %r 183} 184 185; This would require computing known bits on both x and y. Is it worth doing? 186 187define i32 @udiv_dividend_known_smaller_than_divisor(i32 %x, i32 %y) { 188; CHECK-LABEL: @udiv_dividend_known_smaller_than_divisor( 189; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 250 190; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], 251 191; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[AND]], [[OR]] 192; CHECK-NEXT: ret i32 [[DIV]] 193; 194 %and = and i32 %x, 250 195 %or = or i32 %y, 251 196 %div = udiv i32 %and, %or 197 ret i32 %div 198} 199 200define i32 @not_udiv_dividend_known_smaller_than_divisor(i32 %x, i32 %y) { 201; CHECK-LABEL: @not_udiv_dividend_known_smaller_than_divisor( 202; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 251 203; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], 251 204; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[AND]], [[OR]] 205; CHECK-NEXT: ret i32 [[DIV]] 206; 207 %and = and i32 %x, 251 208 %or = or i32 %y, 251 209 %div = udiv i32 %and, %or 210 ret i32 %div 211} 212 213declare i32 @external() 214 215define i32 @div1() { 216; CHECK-LABEL: @div1( 217; CHECK-NEXT: [[CALL:%.*]] = call i32 @external(), !range [[RNG0:![0-9]+]] 218; CHECK-NEXT: ret i32 0 219; 220 %call = call i32 @external(), !range !0 221 %urem = udiv i32 %call, 3 222 ret i32 %urem 223} 224 225define i8 @sdiv_minusone_divisor() { 226; CHECK-LABEL: @sdiv_minusone_divisor( 227; CHECK-NEXT: ret i8 poison 228; 229 %v = sdiv i8 -128, -1 230 ret i8 %v 231} 232 233@g = external global i64 234@g2 = external global i64 235 236define i64 @const_sdiv_one() { 237; CHECK-LABEL: @const_sdiv_one( 238; CHECK-NEXT: ret i64 ptrtoint (ptr @g to i64) 239; 240 %div = sdiv i64 ptrtoint (ptr @g to i64), 1 241 ret i64 %div 242} 243 244define i64 @const_srem_one() { 245; CHECK-LABEL: @const_srem_one( 246; CHECK-NEXT: ret i64 0 247; 248 %rem = srem i64 ptrtoint (ptr @g to i64), 1 249 ret i64 %rem 250} 251 252define i64 @const_udiv_one() { 253; CHECK-LABEL: @const_udiv_one( 254; CHECK-NEXT: ret i64 ptrtoint (ptr @g to i64) 255; 256 %div = udiv i64 ptrtoint (ptr @g to i64), 1 257 ret i64 %div 258} 259 260define i64 @const_urem_one() { 261; CHECK-LABEL: @const_urem_one( 262; CHECK-NEXT: ret i64 0 263; 264 %rem = urem i64 ptrtoint (ptr @g to i64), 1 265 ret i64 %rem 266} 267 268define i64 @const_sdiv_zero() { 269; CHECK-LABEL: @const_sdiv_zero( 270; CHECK-NEXT: ret i64 0 271; 272 %div = sdiv i64 0, ptrtoint (ptr @g to i64) 273 ret i64 %div 274} 275 276define i64 @const_srem_zero() { 277; CHECK-LABEL: @const_srem_zero( 278; CHECK-NEXT: ret i64 0 279; 280 %rem = srem i64 0, ptrtoint (ptr @g to i64) 281 ret i64 %rem 282} 283 284define i64 @const_udiv_zero() { 285; CHECK-LABEL: @const_udiv_zero( 286; CHECK-NEXT: ret i64 0 287; 288 %div = udiv i64 0, ptrtoint (ptr @g to i64) 289 ret i64 %div 290} 291 292define i64 @const_urem_zero() { 293; CHECK-LABEL: @const_urem_zero( 294; CHECK-NEXT: ret i64 0 295; 296 %rem = urem i64 0, ptrtoint (ptr @g to i64) 297 ret i64 %rem 298} 299 300define i64 @const_sdiv_zero_negone() { 301; CHECK-LABEL: @const_sdiv_zero_negone( 302; CHECK-NEXT: ret i64 0 303; 304 %div = sdiv i64 0, -1 305 ret i64 %div 306} 307 308define i1 @const_sdiv_i1() { 309; CHECK-LABEL: @const_sdiv_i1( 310; CHECK-NEXT: ret i1 ptrtoint (ptr @g to i1) 311; 312 %div = sdiv i1 ptrtoint (ptr @g to i1), ptrtoint (ptr @g2 to i1) 313 ret i1 %div 314} 315 316define i1 @const_srem_1() { 317; CHECK-LABEL: @const_srem_1( 318; CHECK-NEXT: ret i1 false 319; 320 %rem = srem i1 ptrtoint (ptr @g to i1), ptrtoint (ptr @g2 to i1) 321 ret i1 %rem 322} 323 324define i1 @const_udiv_i1() { 325; CHECK-LABEL: @const_udiv_i1( 326; CHECK-NEXT: ret i1 ptrtoint (ptr @g to i1) 327; 328 %div = udiv i1 ptrtoint (ptr @g to i1), ptrtoint (ptr @g2 to i1) 329 ret i1 %div 330} 331 332define i1 @const_urem_1() { 333; CHECK-LABEL: @const_urem_1( 334; CHECK-NEXT: ret i1 false 335; 336 %rem = urem i1 ptrtoint (ptr @g to i1), ptrtoint (ptr @g2 to i1) 337 ret i1 %rem 338} 339 340; Can't divide evenly, so create poison. 341 342define i8 @sdiv_exact_trailing_zeros(i8 %x) { 343; CHECK-LABEL: @sdiv_exact_trailing_zeros( 344; CHECK-NEXT: ret i8 poison 345; 346 %o = or i8 %x, 1 ; odd number 347 %r = sdiv exact i8 %o, -42 ; can't divide exactly 348 ret i8 %r 349} 350 351; Negative test - could divide evenly. 352 353define i8 @sdiv_exact_trailing_zeros_eq(i8 %x) { 354; CHECK-LABEL: @sdiv_exact_trailing_zeros_eq( 355; CHECK-NEXT: [[O:%.*]] = or i8 [[X:%.*]], 2 356; CHECK-NEXT: [[R:%.*]] = sdiv exact i8 [[O]], -42 357; CHECK-NEXT: ret i8 [[R]] 358; 359 %o = or i8 %x, 2 360 %r = sdiv exact i8 %o, -42 361 ret i8 %r 362} 363 364; Negative test - must be exact div. 365 366define i8 @sdiv_trailing_zeros(i8 %x) { 367; CHECK-LABEL: @sdiv_trailing_zeros( 368; CHECK-NEXT: [[O:%.*]] = or i8 [[X:%.*]], 1 369; CHECK-NEXT: [[R:%.*]] = sdiv i8 [[O]], -12 370; CHECK-NEXT: ret i8 [[R]] 371; 372 %o = or i8 %x, 1 373 %r = sdiv i8 %o, -12 374 ret i8 %r 375} 376 377; TODO: Match non-splat vector constants. 378 379define <2 x i8> @sdiv_exact_trailing_zeros_nonuniform_vector(<2 x i8> %x) { 380; CHECK-LABEL: @sdiv_exact_trailing_zeros_nonuniform_vector( 381; CHECK-NEXT: [[O:%.*]] = or <2 x i8> [[X:%.*]], <i8 3, i8 1> 382; CHECK-NEXT: [[R:%.*]] = sdiv exact <2 x i8> [[O]], <i8 12, i8 2> 383; CHECK-NEXT: ret <2 x i8> [[R]] 384; 385 %o = or <2 x i8> %x, <i8 3, i8 1> 386 %r = sdiv exact <2 x i8> %o, <i8 12, i8 2> 387 ret <2 x i8> %r 388} 389 390; Can't divide evenly, so create poison. 391 392define <2 x i8> @udiv_exact_trailing_zeros(<2 x i8> %x) { 393; CHECK-LABEL: @udiv_exact_trailing_zeros( 394; CHECK-NEXT: ret <2 x i8> poison 395; 396 %o = or <2 x i8> %x, <i8 3, i8 3> 397 %r = udiv exact <2 x i8> %o, <i8 12, i8 12> ; can't divide exactly 398 ret <2 x i8> %r 399} 400 401; Negative test - could divide evenly. 402 403define <2 x i8> @udiv_exact_trailing_zeros_eq(<2 x i8> %x) { 404; CHECK-LABEL: @udiv_exact_trailing_zeros_eq( 405; CHECK-NEXT: [[O:%.*]] = or <2 x i8> [[X:%.*]], splat (i8 28) 406; CHECK-NEXT: [[R:%.*]] = udiv exact <2 x i8> [[O]], splat (i8 12) 407; CHECK-NEXT: ret <2 x i8> [[R]] 408; 409 %o = or <2 x i8> %x, <i8 28, i8 28> 410 %r = udiv exact <2 x i8> %o, <i8 12, i8 12> 411 ret <2 x i8> %r 412} 413 414; Negative test - must be exact div. 415 416define i8 @udiv_trailing_zeros(i8 %x) { 417; CHECK-LABEL: @udiv_trailing_zeros( 418; CHECK-NEXT: [[O:%.*]] = or i8 [[X:%.*]], 1 419; CHECK-NEXT: [[R:%.*]] = udiv i8 [[O]], 12 420; CHECK-NEXT: ret i8 [[R]] 421; 422 %o = or i8 %x, 1 423 %r = udiv i8 %o, 12 424 ret i8 %r 425} 426 427; Negative test - only the first element is poison 428 429define <2 x i8> @udiv_exact_trailing_zeros_nonuniform_vector(<2 x i8> %x) { 430; CHECK-LABEL: @udiv_exact_trailing_zeros_nonuniform_vector( 431; CHECK-NEXT: [[O:%.*]] = or <2 x i8> [[X:%.*]], splat (i8 3) 432; CHECK-NEXT: [[R:%.*]] = udiv exact <2 x i8> [[O]], <i8 12, i8 1> 433; CHECK-NEXT: ret <2 x i8> [[R]] 434; 435 %o = or <2 x i8> %x, <i8 3, i8 3> 436 %r = udiv exact <2 x i8> %o, <i8 12, i8 1> 437 ret <2 x i8> %r 438} 439 440!0 = !{i32 0, i32 3} 441 442define i32 @sdiv_one_srem_divisor(i32 %a, i32 %b) { 443; CHECK-LABEL: @sdiv_one_srem_divisor( 444; CHECK-NEXT: ret i32 [[A:%.*]] 445; 446 %srem = srem i32 1, %b 447 %sdiv = sdiv i32 %a, %srem 448 ret i32 %sdiv 449} 450 451define i32 @sdiv_one_urem_divisor(i32 %a, i32 %b) { 452; CHECK-LABEL: @sdiv_one_urem_divisor( 453; CHECK-NEXT: ret i32 [[A:%.*]] 454; 455 %urem = urem i32 1, %b 456 %sdiv = sdiv i32 %a, %urem 457 ret i32 %sdiv 458} 459 460define i32 @udiv_one_srem_divisor(i32 %a, i32 %b) { 461; CHECK-LABEL: @udiv_one_srem_divisor( 462; CHECK-NEXT: ret i32 [[A:%.*]] 463; 464 %srem = srem i32 1, %b 465 %udiv = udiv i32 %a, %srem 466 ret i32 %udiv 467} 468 469define i32 @udiv_one_urem_divisor(i32 %a, i32 %b) { 470; CHECK-LABEL: @udiv_one_urem_divisor( 471; CHECK-NEXT: ret i32 [[A:%.*]] 472; 473 %urem = urem i32 1, %b 474 %udiv = udiv i32 %a, %urem 475 ret i32 %udiv 476} 477 478define i32 @srem_one_srem_divisor(i32 %a, i32 %b) { 479; CHECK-LABEL: @srem_one_srem_divisor( 480; CHECK-NEXT: ret i32 0 481; 482 %srem = srem i32 1, %b 483 %srem1 = srem i32 %a, %srem 484 ret i32 %srem1 485} 486 487define i32 @urem_one_srem_divisor(i32 %a, i32 %b) { 488; CHECK-LABEL: @urem_one_srem_divisor( 489; CHECK-NEXT: ret i32 0 490; 491 %srem = srem i32 1, %b 492 %urem = urem i32 %a, %srem 493 ret i32 %urem 494} 495 496define i32 @srem_one_urem_divisor(i32 %a, i32 %b) { 497; CHECK-LABEL: @srem_one_urem_divisor( 498; CHECK-NEXT: ret i32 0 499; 500 %urem = urem i32 1, %b 501 %srem = srem i32 %a, %urem 502 ret i32 %srem 503} 504 505define i32 @urem_one_urem_divisor(i32 %a, i32 %b) { 506; CHECK-LABEL: @urem_one_urem_divisor( 507; CHECK-NEXT: ret i32 0 508; 509 %urem = urem i32 1, %b 510 %urem1 = urem i32 %a, %urem 511 ret i32 %urem1 512} 513 514define <2 x i8> @sdiv_one_vec_srem_divisor(<2 x i8> %a, <2 x i8> %b) { 515; CHECK-LABEL: @sdiv_one_vec_srem_divisor( 516; CHECK-NEXT: ret <2 x i8> [[A:%.*]] 517; 518 %srem = srem <2 x i8> <i8 1, i8 1>, %b 519 %sdiv = sdiv <2 x i8> %a, %srem 520 ret <2 x i8> %sdiv 521} 522 523define i32 @sdiv_and_one_divisor(i32 %x, i32 %y) { 524; CHECK-LABEL: @sdiv_and_one_divisor( 525; CHECK-NEXT: ret i32 [[Y:%.*]] 526; 527 %and = and i32 %x, 1 528 %res = sdiv i32 %y, %and 529 ret i32 %res 530} 531 532define <2 x i8> @sdiv_and_one_vec_divisor(<2 x i8> %x, <2 x i8> %y) { 533; CHECK-LABEL: @sdiv_and_one_vec_divisor( 534; CHECK-NEXT: ret <2 x i8> [[Y:%.*]] 535; 536 %and = and <2 x i8> %x, <i8 1, i8 1> 537 %res = sdiv <2 x i8> %y, %and 538 ret <2 x i8> %res 539} 540 541define i32 @sdiv_neg_or_divisor(i32 %x, i32 %y) { 542; CHECK-LABEL: @sdiv_neg_or_divisor( 543; CHECK-NEXT: ret i32 [[Y:%.*]] 544; 545 %or = or i32 %x, -2 546 %neg = xor i32 %or, -1 547 %res = sdiv i32 %y, %neg 548 ret i32 %res 549} 550 551define i32 @sdiv_neg_or_multi_one_bit_divisor(i32 %x, i32 %y) { 552; CHECK-LABEL: @sdiv_neg_or_multi_one_bit_divisor( 553; CHECK-NEXT: [[OR:%.*]] = or i32 [[X:%.*]], -3 554; CHECK-NEXT: [[NEG:%.*]] = xor i32 [[OR]], -1 555; CHECK-NEXT: [[RES:%.*]] = sdiv i32 [[Y:%.*]], [[NEG]] 556; CHECK-NEXT: ret i32 [[RES]] 557; 558 %or = or i32 %x, -3 559 %neg = xor i32 %or, -1 560 %res = sdiv i32 %y, %neg 561 ret i32 %res 562} 563 564define <2 x i8> @sdiv_vec_multi_one_bit_divisor(<2 x i8> %x, <2 x i8> %y) { 565; CHECK-LABEL: @sdiv_vec_multi_one_bit_divisor( 566; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[X:%.*]], <i8 1, i8 3> 567; CHECK-NEXT: [[RES:%.*]] = sdiv <2 x i8> [[Y:%.*]], [[AND]] 568; CHECK-NEXT: ret <2 x i8> [[RES]] 569; 570 %and = and <2 x i8> %x, <i8 1, i8 3> 571 %res = sdiv <2 x i8> %y, %and 572 ret <2 x i8> %res 573} 574 575define i8 @udiv_exact_mul_nsw(i8 %x) { 576; CHECK-LABEL: @udiv_exact_mul_nsw( 577; CHECK-NEXT: ret i8 [[X:%.*]] 578; 579 %a = mul nsw i8 %x, 24 580 %b = udiv exact i8 %a, 24 581 ret i8 %b 582} 583 584define i8 @sdiv_exact_mul_nuw(i8 %x) { 585; CHECK-LABEL: @sdiv_exact_mul_nuw( 586; CHECK-NEXT: ret i8 [[X:%.*]] 587; 588 %a = mul nuw i8 %x, 24 589 %b = sdiv exact i8 %a, 24 590 ret i8 %b 591} 592 593; Negative tests 594 595define i8 @udiv_exact_mul_nsw_mismatch(i8 %x) { 596; CHECK-LABEL: @udiv_exact_mul_nsw_mismatch( 597; CHECK-NEXT: [[A:%.*]] = mul nsw i8 [[X:%.*]], 24 598; CHECK-NEXT: [[B:%.*]] = udiv exact i8 [[A]], 12 599; CHECK-NEXT: ret i8 [[B]] 600; 601 %a = mul nsw i8 %x, 24 602 %b = udiv exact i8 %a, 12 603 ret i8 %b 604} 605 606define i8 @udiv_exact_mul_nsw_power_of_2(i8 %x) { 607; CHECK-LABEL: @udiv_exact_mul_nsw_power_of_2( 608; CHECK-NEXT: [[A:%.*]] = mul nsw i8 [[X:%.*]], 8 609; CHECK-NEXT: [[B:%.*]] = udiv exact i8 [[A]], 8 610; CHECK-NEXT: ret i8 [[B]] 611; 612 %a = mul nsw i8 %x, 8 613 %b = udiv exact i8 %a, 8 614 ret i8 %b 615} 616 617define i8 @sdiv_exact_mul_nuw_power_of_2(i8 %x) { 618; CHECK-LABEL: @sdiv_exact_mul_nuw_power_of_2( 619; CHECK-NEXT: [[A:%.*]] = mul nuw i8 [[X:%.*]], 8 620; CHECK-NEXT: [[B:%.*]] = sdiv exact i8 [[A]], 8 621; CHECK-NEXT: ret i8 [[B]] 622; 623 %a = mul nuw i8 %x, 8 624 %b = sdiv exact i8 %a, 8 625 ret i8 %b 626} 627 628define i8 @udiv_exact_mul(i8 %x) { 629; CHECK-LABEL: @udiv_exact_mul( 630; CHECK-NEXT: [[A:%.*]] = mul i8 [[X:%.*]], 24 631; CHECK-NEXT: [[B:%.*]] = udiv exact i8 [[A]], 24 632; CHECK-NEXT: ret i8 [[B]] 633; 634 %a = mul i8 %x, 24 635 %b = udiv exact i8 %a, 24 636 ret i8 %b 637} 638 639define i8 @sdiv_exact_mul(i8 %x) { 640; CHECK-LABEL: @sdiv_exact_mul( 641; CHECK-NEXT: [[A:%.*]] = mul i8 [[X:%.*]], 24 642; CHECK-NEXT: [[B:%.*]] = sdiv exact i8 [[A]], 24 643; CHECK-NEXT: ret i8 [[B]] 644; 645 %a = mul i8 %x, 24 646 %b = sdiv exact i8 %a, 24 647 ret i8 %b 648} 649 650define i8 @udiv_mul_nsw(i8 %x) { 651; CHECK-LABEL: @udiv_mul_nsw( 652; CHECK-NEXT: [[A:%.*]] = mul nsw i8 [[X:%.*]], 24 653; CHECK-NEXT: [[B:%.*]] = udiv i8 [[A]], 24 654; CHECK-NEXT: ret i8 [[B]] 655; 656 %a = mul nsw i8 %x, 24 657 %b = udiv i8 %a, 24 658 ret i8 %b 659} 660 661define i8 @sdiv_mul_nuw(i8 %x) { 662; CHECK-LABEL: @sdiv_mul_nuw( 663; CHECK-NEXT: [[A:%.*]] = mul nuw i8 [[X:%.*]], 24 664; CHECK-NEXT: [[B:%.*]] = sdiv i8 [[A]], 24 665; CHECK-NEXT: ret i8 [[B]] 666; 667 %a = mul nuw i8 %x, 24 668 %b = sdiv i8 %a, 24 669 ret i8 %b 670} 671