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(i32) 5 6define i64 @rem_signed(i64 %x1, i64 %y2) { 7; CHECK-LABEL: @rem_signed( 8; CHECK-NEXT: [[X1_FR:%.*]] = freeze i64 [[X1:%.*]] 9; CHECK-NEXT: [[TMP1:%.*]] = srem i64 [[X1_FR]], [[Y2:%.*]] 10; CHECK-NEXT: ret i64 [[TMP1]] 11; 12 %r = sdiv i64 %x1, %y2 13 %r7 = mul i64 %r, %y2 14 %r8 = sub i64 %x1, %r7 15 ret i64 %r8 16} 17 18define <4 x i32> @rem_signed_vec(<4 x i32> %t, <4 x i32> %u) { 19; CHECK-LABEL: @rem_signed_vec( 20; CHECK-NEXT: [[T_FR:%.*]] = freeze <4 x i32> [[T:%.*]] 21; CHECK-NEXT: [[TMP1:%.*]] = srem <4 x i32> [[T_FR]], [[U:%.*]] 22; CHECK-NEXT: ret <4 x i32> [[TMP1]] 23; 24 %k = sdiv <4 x i32> %t, %u 25 %l = mul <4 x i32> %k, %u 26 %m = sub <4 x i32> %t, %l 27 ret <4 x i32> %m 28} 29 30define i64 @rem_unsigned(i64 %x1, i64 %y2) { 31; CHECK-LABEL: @rem_unsigned( 32; CHECK-NEXT: [[X1_FR:%.*]] = freeze i64 [[X1:%.*]] 33; CHECK-NEXT: [[TMP1:%.*]] = urem i64 [[X1_FR]], [[Y2:%.*]] 34; CHECK-NEXT: ret i64 [[TMP1]] 35; 36 %r = udiv i64 %x1, %y2 37 %r7 = mul i64 %r, %y2 38 %r8 = sub i64 %x1, %r7 39 ret i64 %r8 40} 41 42; PR28672 - https://llvm.org/bugs/show_bug.cgi?id=28672 43 44define i8 @big_divisor(i8 %x) { 45; CHECK-LABEL: @big_divisor( 46; CHECK-NEXT: [[X_FR:%.*]] = freeze i8 [[X:%.*]] 47; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i8 [[X_FR]], -127 48; CHECK-NEXT: [[TMP2:%.*]] = add i8 [[X_FR]], 127 49; CHECK-NEXT: [[REM:%.*]] = select i1 [[TMP1]], i8 [[X_FR]], i8 [[TMP2]] 50; CHECK-NEXT: ret i8 [[REM]] 51; 52 %rem = urem i8 %x, 129 53 ret i8 %rem 54} 55 56define i5 @biggest_divisor(i5 %x) { 57; CHECK-LABEL: @biggest_divisor( 58; CHECK-NEXT: [[X_FR:%.*]] = freeze i5 [[X:%.*]] 59; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i5 [[X_FR]], -1 60; CHECK-NEXT: [[REM:%.*]] = select i1 [[DOTNOT]], i5 0, i5 [[X_FR]] 61; CHECK-NEXT: ret i5 [[REM]] 62; 63 %rem = urem i5 %x, -1 64 ret i5 %rem 65} 66 67define i8 @urem_with_sext_bool_divisor(i1 %x, i8 %y) { 68; CHECK-LABEL: @urem_with_sext_bool_divisor( 69; CHECK-NEXT: [[Y_FROZEN:%.*]] = freeze i8 [[Y:%.*]] 70; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8 [[Y_FROZEN]], -1 71; CHECK-NEXT: [[REM:%.*]] = select i1 [[TMP1]], i8 0, i8 [[Y_FROZEN]] 72; CHECK-NEXT: ret i8 [[REM]] 73; 74 %s = sext i1 %x to i8 75 %rem = urem i8 %y, %s 76 ret i8 %rem 77} 78 79define <2 x i8> @urem_with_sext_bool_divisor_vec(<2 x i1> %x, <2 x i8> %y) { 80; CHECK-LABEL: @urem_with_sext_bool_divisor_vec( 81; CHECK-NEXT: [[Y_FROZEN:%.*]] = freeze <2 x i8> [[Y:%.*]] 82; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i8> [[Y_FROZEN]], splat (i8 -1) 83; CHECK-NEXT: [[REM:%.*]] = select <2 x i1> [[TMP1]], <2 x i8> zeroinitializer, <2 x i8> [[Y_FROZEN]] 84; CHECK-NEXT: ret <2 x i8> [[REM]] 85; 86 %s = sext <2 x i1> %x to <2 x i8> 87 %rem = urem <2 x i8> %y, %s 88 ret <2 x i8> %rem 89} 90 91define <2 x i4> @big_divisor_vec(<2 x i4> %x) { 92; CHECK-LABEL: @big_divisor_vec( 93; CHECK-NEXT: [[X_FR:%.*]] = freeze <2 x i4> [[X:%.*]] 94; CHECK-NEXT: [[TMP1:%.*]] = icmp ult <2 x i4> [[X_FR]], splat (i4 -3) 95; CHECK-NEXT: [[TMP2:%.*]] = add <2 x i4> [[X_FR]], splat (i4 3) 96; CHECK-NEXT: [[REM:%.*]] = select <2 x i1> [[TMP1]], <2 x i4> [[X_FR]], <2 x i4> [[TMP2]] 97; CHECK-NEXT: ret <2 x i4> [[REM]] 98; 99 %rem = urem <2 x i4> %x, <i4 13, i4 13> 100 ret <2 x i4> %rem 101} 102 103define i8 @urem1(i8 %x, i8 %y) { 104; CHECK-LABEL: @urem1( 105; CHECK-NEXT: [[X_FR:%.*]] = freeze i8 [[X:%.*]] 106; CHECK-NEXT: [[TMP1:%.*]] = urem i8 [[X_FR]], [[Y:%.*]] 107; CHECK-NEXT: ret i8 [[TMP1]] 108; 109 %A = udiv i8 %x, %y 110 %B = mul i8 %A, %y 111 %C = sub i8 %x, %B 112 ret i8 %C 113} 114 115define i8 @srem1(i8 %x, i8 %y) { 116; CHECK-LABEL: @srem1( 117; CHECK-NEXT: [[X_FR:%.*]] = freeze i8 [[X:%.*]] 118; CHECK-NEXT: [[TMP1:%.*]] = srem i8 [[X_FR]], [[Y:%.*]] 119; CHECK-NEXT: ret i8 [[TMP1]] 120; 121 %A = sdiv i8 %x, %y 122 %B = mul i8 %A, %y 123 %C = sub i8 %x, %B 124 ret i8 %C 125} 126 127define i8 @urem2(i8 %x, i8 %y) { 128; CHECK-LABEL: @urem2( 129; CHECK-NEXT: [[X_FR:%.*]] = freeze i8 [[X:%.*]] 130; CHECK-NEXT: [[TMP1:%.*]] = urem i8 [[X_FR]], [[Y:%.*]] 131; CHECK-NEXT: [[C:%.*]] = sub i8 0, [[TMP1]] 132; CHECK-NEXT: ret i8 [[C]] 133; 134 %A = udiv i8 %x, %y 135 %B = mul i8 %A, %y 136 %C = sub i8 %B, %x 137 ret i8 %C 138} 139 140define i8 @urem3(i8 %x) { 141; CHECK-LABEL: @urem3( 142; CHECK-NEXT: [[X_FR:%.*]] = freeze i8 [[X:%.*]] 143; CHECK-NEXT: [[TMP1:%.*]] = urem i8 [[X_FR]], 3 144; CHECK-NEXT: [[B_NEG:%.*]] = sub nuw i8 [[X_FR]], [[TMP1]] 145; CHECK-NEXT: [[C:%.*]] = add i8 [[B_NEG]], [[X_FR]] 146; CHECK-NEXT: ret i8 [[C]] 147; 148 %A = udiv i8 %x, 3 149 %B = mul i8 %A, -3 150 %C = sub i8 %x, %B 151 ret i8 %C 152} 153 154; (((X / Y) * Y) / Y) -> X / Y 155 156define i32 @sdiv_mul_sdiv(i32 %x, i32 %y) { 157; CHECK-LABEL: @sdiv_mul_sdiv( 158; CHECK-NEXT: [[X_FR:%.*]] = freeze i32 [[X:%.*]] 159; CHECK-NEXT: [[R:%.*]] = sdiv i32 [[X_FR]], [[Y:%.*]] 160; CHECK-NEXT: ret i32 [[R]] 161; 162 %div = sdiv i32 %x, %y 163 %mul = mul i32 %div, %y 164 %r = sdiv i32 %mul, %y 165 ret i32 %r 166} 167 168; (((X / Y) * Y) / Y) -> X / Y 169 170define i32 @udiv_mul_udiv(i32 %x, i32 %y) { 171; CHECK-LABEL: @udiv_mul_udiv( 172; CHECK-NEXT: [[X_FR:%.*]] = freeze i32 [[X:%.*]] 173; CHECK-NEXT: [[R:%.*]] = udiv i32 [[X_FR]], [[Y:%.*]] 174; CHECK-NEXT: ret i32 [[R]] 175; 176 %div = udiv i32 %x, %y 177 %mul = mul i32 %div, %y 178 %r = udiv i32 %mul, %y 179 ret i32 %r 180} 181 182define i32 @test1(i32 %A) { 183; CHECK-LABEL: @test1( 184; CHECK-NEXT: ret i32 0 185; 186 %B = srem i32 %A, 1 ; ISA constant 0 187 ret i32 %B 188} 189 190define i32 @test3(i32 %A) { 191; CHECK-LABEL: @test3( 192; CHECK-NEXT: [[B:%.*]] = and i32 [[A:%.*]], 7 193; CHECK-NEXT: ret i32 [[B]] 194; 195 %B = urem i32 %A, 8 196 ret i32 %B 197} 198 199define <2 x i32> @vec_power_of_2_constant_splat_divisor(<2 x i32> %A) { 200; CHECK-LABEL: @vec_power_of_2_constant_splat_divisor( 201; CHECK-NEXT: [[B:%.*]] = and <2 x i32> [[A:%.*]], splat (i32 7) 202; CHECK-NEXT: ret <2 x i32> [[B]] 203; 204 %B = urem <2 x i32> %A, <i32 8, i32 8> 205 ret <2 x i32> %B 206} 207 208define <2 x i19> @weird_vec_power_of_2_constant_splat_divisor(<2 x i19> %A) { 209; CHECK-LABEL: @weird_vec_power_of_2_constant_splat_divisor( 210; CHECK-NEXT: [[B:%.*]] = and <2 x i19> [[A:%.*]], splat (i19 7) 211; CHECK-NEXT: ret <2 x i19> [[B]] 212; 213 %B = urem <2 x i19> %A, <i19 8, i19 8> 214 ret <2 x i19> %B 215} 216 217define i1 @test3a(i32 %A) { 218; CHECK-LABEL: @test3a( 219; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[A:%.*]], 7 220; CHECK-NEXT: [[C:%.*]] = icmp ne i32 [[TMP1]], 0 221; CHECK-NEXT: ret i1 [[C]] 222; 223 %B = srem i32 %A, -8 224 %C = icmp ne i32 %B, 0 225 ret i1 %C 226} 227 228define <2 x i1> @test3a_vec(<2 x i32> %A) { 229; CHECK-LABEL: @test3a_vec( 230; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[A:%.*]], splat (i32 7) 231; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i32> [[TMP1]], zeroinitializer 232; CHECK-NEXT: ret <2 x i1> [[C]] 233; 234 %B = srem <2 x i32> %A, <i32 -8, i32 -8> 235 %C = icmp ne <2 x i32> %B, zeroinitializer 236 ret <2 x i1> %C 237} 238 239define i32 @test4(i32 %X, i1 %C) { 240; CHECK-LABEL: @test4( 241; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C:%.*]], i32 0, i32 7 242; CHECK-NEXT: [[R:%.*]] = and i32 [[X:%.*]], [[TMP1]] 243; CHECK-NEXT: ret i32 [[R]] 244; 245 %V = select i1 %C, i32 1, i32 8 246 %R = urem i32 %X, %V 247 ret i32 %R 248} 249 250define i32 @test5(i32 %X, i8 %B) { 251; CHECK-LABEL: @test5( 252; CHECK-NEXT: [[SHIFT_UPGRD_1:%.*]] = zext nneg i8 [[B:%.*]] to i32 253; CHECK-NEXT: [[AMT:%.*]] = shl nuw i32 32, [[SHIFT_UPGRD_1]] 254; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[AMT]], -1 255; CHECK-NEXT: [[V:%.*]] = and i32 [[X:%.*]], [[TMP1]] 256; CHECK-NEXT: ret i32 [[V]] 257; 258 %shift.upgrd.1 = zext i8 %B to i32 259 %Amt = shl i32 32, %shift.upgrd.1 260 %V = urem i32 %X, %Amt 261 ret i32 %V 262} 263 264define i32 @test6(i32 %A) { 265; CHECK-LABEL: @test6( 266; CHECK-NEXT: ret i32 poison 267; 268 %B = srem i32 %A, 0 ;; undef 269 ret i32 %B 270} 271 272define i32 @test7(i32 %A) { 273; CHECK-LABEL: @test7( 274; CHECK-NEXT: ret i32 0 275; 276 %B = mul i32 %A, 8 277 %C = srem i32 %B, 4 278 ret i32 %C 279} 280 281define i32 @test8(i32 %A) { 282; CHECK-LABEL: @test8( 283; CHECK-NEXT: ret i32 0 284; 285 %B = shl i32 %A, 4 286 %C = srem i32 %B, 8 287 ret i32 %C 288} 289 290define i32 @test9(i32 %A) { 291; CHECK-LABEL: @test9( 292; CHECK-NEXT: ret i32 0 293; 294 %B = mul i32 %A, 64 295 %C = urem i32 %B, 32 296 ret i32 %C 297} 298 299define i32 @test10(i8 %c) { 300; CHECK-LABEL: @test10( 301; CHECK-NEXT: ret i32 0 302; 303 %tmp.1 = zext i8 %c to i32 304 %tmp.2 = mul i32 %tmp.1, 4 305 %tmp.3 = sext i32 %tmp.2 to i64 306 %tmp.5 = urem i64 %tmp.3, 4 307 %tmp.6 = trunc i64 %tmp.5 to i32 308 ret i32 %tmp.6 309} 310 311define i32 @test11(i32 %i) { 312; CHECK-LABEL: @test11( 313; CHECK-NEXT: ret i32 0 314; 315 %tmp.1 = and i32 %i, -2 316 %tmp.3 = mul i32 %tmp.1, 2 317 %tmp.5 = urem i32 %tmp.3, 4 318 ret i32 %tmp.5 319} 320 321define i32 @test12(i32 %i) { 322; CHECK-LABEL: @test12( 323; CHECK-NEXT: ret i32 0 324; 325 %tmp.1 = and i32 %i, -4 326 %tmp.5 = srem i32 %tmp.1, 2 327 ret i32 %tmp.5 328} 329 330define i32 @test13(i32 %i) { 331; CHECK-LABEL: @test13( 332; CHECK-NEXT: ret i32 0 333; 334 %x = srem i32 %i, %i 335 ret i32 %x 336} 337 338define i64 @test14(i64 %x, i32 %y) { 339; CHECK-LABEL: @test14( 340; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 1, [[Y:%.*]] 341; CHECK-NEXT: [[ZEXT:%.*]] = zext i32 [[SHL]] to i64 342; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[ZEXT]], -1 343; CHECK-NEXT: [[UREM:%.*]] = and i64 [[X:%.*]], [[TMP1]] 344; CHECK-NEXT: ret i64 [[UREM]] 345; 346 %shl = shl i32 1, %y 347 %zext = zext i32 %shl to i64 348 %urem = urem i64 %x, %zext 349 ret i64 %urem 350} 351 352define i64 @test15(i32 %x, i32 %y) { 353; CHECK-LABEL: @test15( 354; CHECK-NEXT: [[NOTMASK:%.*]] = shl nsw i32 -1, [[Y:%.*]] 355; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[NOTMASK]], -1 356; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[X:%.*]], [[TMP1]] 357; CHECK-NEXT: [[UREM:%.*]] = zext nneg i32 [[TMP2]] to i64 358; CHECK-NEXT: ret i64 [[UREM]] 359; 360 %shl = shl i32 1, %y 361 %zext0 = zext i32 %shl to i64 362 %zext1 = zext i32 %x to i64 363 %urem = urem i64 %zext1, %zext0 364 ret i64 %urem 365} 366 367define i32 @test16(i32 %x, i32 %y) { 368; CHECK-LABEL: @test16( 369; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[Y:%.*]], 11 370; CHECK-NEXT: [[AND:%.*]] = and i32 [[SHR]], 4 371; CHECK-NEXT: [[TMP1:%.*]] = or disjoint i32 [[AND]], 3 372; CHECK-NEXT: [[REM:%.*]] = and i32 [[X:%.*]], [[TMP1]] 373; CHECK-NEXT: ret i32 [[REM]] 374; 375 %shr = lshr i32 %y, 11 376 %and = and i32 %shr, 4 377 %add = add i32 %and, 4 378 %rem = urem i32 %x, %add 379 ret i32 %rem 380} 381 382define i32 @test17(i32 %X) { 383; CHECK-LABEL: @test17( 384; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i32 [[X:%.*]], 1 385; CHECK-NEXT: [[A:%.*]] = zext i1 [[TMP1]] to i32 386; CHECK-NEXT: ret i32 [[A]] 387; 388 %A = urem i32 1, %X 389 ret i32 %A 390} 391 392define i32 @test18(i16 %x, i32 %y) { 393; CHECK-LABEL: @test18( 394; CHECK-NEXT: [[TMP1:%.*]] = and i16 [[X:%.*]], 4 395; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i16 [[TMP1]], 0 396; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[DOTNOT]], i32 63, i32 31 397; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[Y:%.*]], [[TMP2]] 398; CHECK-NEXT: ret i32 [[TMP3]] 399; 400 %1 = and i16 %x, 4 401 %2 = icmp ne i16 %1, 0 402 %3 = select i1 %2, i32 32, i32 64 403 %4 = urem i32 %y, %3 404 ret i32 %4 405} 406 407define i32 @test19(i32 %x, i32 %y) { 408; CHECK-LABEL: @test19( 409; CHECK-NEXT: [[A:%.*]] = shl nuw i32 1, [[X:%.*]] 410; CHECK-NEXT: [[B:%.*]] = shl nuw i32 1, [[Y:%.*]] 411; CHECK-NEXT: [[C:%.*]] = and i32 [[A]], [[B]] 412; CHECK-NEXT: [[D:%.*]] = add i32 [[C]], [[A]] 413; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[D]], -1 414; CHECK-NEXT: [[E:%.*]] = and i32 [[Y]], [[TMP1]] 415; CHECK-NEXT: ret i32 [[E]] 416; 417 %A = shl i32 1, %x 418 %B = shl i32 1, %y 419 %C = and i32 %A, %B 420 %D = add i32 %C, %A 421 %E = urem i32 %y, %D 422 ret i32 %E 423} 424 425define i32 @test19_commutative0(i32 %x, i32 %y) { 426; CHECK-LABEL: @test19_commutative0( 427; CHECK-NEXT: [[A:%.*]] = shl nuw i32 1, [[X:%.*]] 428; CHECK-NEXT: [[B:%.*]] = shl nuw i32 1, [[Y:%.*]] 429; CHECK-NEXT: [[C:%.*]] = and i32 [[B]], [[A]] 430; CHECK-NEXT: [[D:%.*]] = add i32 [[C]], [[A]] 431; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[D]], -1 432; CHECK-NEXT: [[E:%.*]] = and i32 [[Y]], [[TMP1]] 433; CHECK-NEXT: ret i32 [[E]] 434; 435 %A = shl i32 1, %x 436 %B = shl i32 1, %y 437 %C = and i32 %B, %A ; swapped 438 %D = add i32 %C, %A 439 %E = urem i32 %y, %D 440 ret i32 %E 441} 442 443define i32 @test19_commutative1(i32 %x, i32 %y) { 444; CHECK-LABEL: @test19_commutative1( 445; CHECK-NEXT: [[A:%.*]] = shl nuw i32 1, [[X:%.*]] 446; CHECK-NEXT: [[B:%.*]] = shl nuw i32 1, [[Y:%.*]] 447; CHECK-NEXT: [[C:%.*]] = and i32 [[A]], [[B]] 448; CHECK-NEXT: [[D:%.*]] = add i32 [[A]], [[C]] 449; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[D]], -1 450; CHECK-NEXT: [[E:%.*]] = and i32 [[Y]], [[TMP1]] 451; CHECK-NEXT: ret i32 [[E]] 452; 453 %A = shl i32 1, %x 454 %B = shl i32 1, %y 455 %C = and i32 %A, %B 456 %D = add i32 %A, %C ; swapped 457 %E = urem i32 %y, %D 458 ret i32 %E 459} 460 461define i32 @test19_commutative2(i32 %x, i32 %y) { 462; CHECK-LABEL: @test19_commutative2( 463; CHECK-NEXT: [[A:%.*]] = shl nuw i32 1, [[X:%.*]] 464; CHECK-NEXT: [[B:%.*]] = shl nuw i32 1, [[Y:%.*]] 465; CHECK-NEXT: [[C:%.*]] = and i32 [[B]], [[A]] 466; CHECK-NEXT: [[D:%.*]] = add i32 [[A]], [[C]] 467; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[D]], -1 468; CHECK-NEXT: [[E:%.*]] = and i32 [[Y]], [[TMP1]] 469; CHECK-NEXT: ret i32 [[E]] 470; 471 %A = shl i32 1, %x 472 %B = shl i32 1, %y 473 %C = and i32 %B, %A ; swapped 474 %D = add i32 %A, %C ; swapped 475 %E = urem i32 %y, %D 476 ret i32 %E 477} 478 479define <2 x i64> @test20(<2 x i64> %X, <2 x i1> %C) { 480; CHECK-LABEL: @test20( 481; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[C:%.*]], <2 x i64> <i64 1, i64 2>, <2 x i64> zeroinitializer 482; CHECK-NEXT: ret <2 x i64> [[R]] 483; 484 %V = select <2 x i1> %C, <2 x i64> <i64 1, i64 2>, <2 x i64> <i64 8, i64 9> 485 %R = urem <2 x i64> %V, <i64 2, i64 3> 486 ret <2 x i64> %R 487} 488 489define i32 @test21(i1 %c0, ptr %p) { 490; CHECK-LABEL: @test21( 491; CHECK-NEXT: entry: 492; CHECK-NEXT: br i1 [[C0:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 493; CHECK: if.then: 494; CHECK-NEXT: [[V:%.*]] = load volatile i32, ptr [[P:%.*]], align 4 495; CHECK-NEXT: [[TMP0:%.*]] = srem i32 [[V]], 5 496; CHECK-NEXT: br label [[IF_END]] 497; CHECK: if.end: 498; CHECK-NEXT: [[LHS:%.*]] = phi i32 [ [[TMP0]], [[IF_THEN]] ], [ 0, [[ENTRY:%.*]] ] 499; CHECK-NEXT: ret i32 [[LHS]] 500; 501entry: 502 br i1 %c0, label %if.then, label %if.end 503 504if.then: 505 %v = load volatile i32, ptr %p 506 br label %if.end 507 508if.end: 509 %lhs = phi i32 [ %v, %if.then ], [ 5, %entry ] 510 %rem = srem i32 %lhs, 5 511 ret i32 %rem 512} 513 514@a = common global [5 x i16] zeroinitializer, align 2 515@b = common global i16 0, align 2 516 517define i32 @pr27968_0(i1 %c0, ptr %p) { 518; CHECK-LABEL: @pr27968_0( 519; CHECK-NEXT: entry: 520; CHECK-NEXT: br i1 [[C0:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 521; CHECK: if.then: 522; CHECK-NEXT: [[V:%.*]] = load volatile i32, ptr [[P:%.*]], align 4 523; CHECK-NEXT: br label [[IF_END]] 524; CHECK: if.end: 525; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr getelementptr inbounds nuw (i8, ptr @a, i64 8), @b 526; CHECK-NEXT: br i1 [[CMP]], label [[REM_IS_SAFE:%.*]], label [[REM_IS_UNSAFE:%.*]] 527; CHECK: rem.is.safe: 528; CHECK-NEXT: ret i32 0 529; CHECK: rem.is.unsafe: 530; CHECK-NEXT: ret i32 0 531; 532entry: 533 br i1 %c0, label %if.then, label %if.end 534 535if.then: 536 %v = load volatile i32, ptr %p 537 br label %if.end 538 539if.end: 540 %lhs = phi i32 [ %v, %if.then ], [ 5, %entry ] 541 %cmp = icmp eq ptr getelementptr inbounds ([5 x i16], ptr @a, i64 0, i64 4), @b 542 br i1 %cmp, label %rem.is.safe, label %rem.is.unsafe 543 544rem.is.safe: 545 %ext = zext i1 %cmp to i32 546 %rem = srem i32 %lhs, %ext 547 ret i32 %rem 548 549rem.is.unsafe: 550 ret i32 0 551} 552 553define i32 @pr27968_1(i1 %c0, i1 %always_false, ptr %p) { 554; CHECK-LABEL: @pr27968_1( 555; CHECK-NEXT: entry: 556; CHECK-NEXT: br i1 [[C0:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 557; CHECK: if.then: 558; CHECK-NEXT: [[V:%.*]] = load volatile i32, ptr [[P:%.*]], align 4 559; CHECK-NEXT: br label [[IF_END]] 560; CHECK: if.end: 561; CHECK-NEXT: [[LHS:%.*]] = phi i32 [ [[V]], [[IF_THEN]] ], [ 5, [[ENTRY:%.*]] ] 562; CHECK-NEXT: br i1 [[ALWAYS_FALSE:%.*]], label [[REM_IS_SAFE:%.*]], label [[REM_IS_UNSAFE:%.*]] 563; CHECK: rem.is.safe: 564; CHECK-NEXT: [[REM:%.*]] = srem i32 [[LHS]], -2147483648 565; CHECK-NEXT: ret i32 [[REM]] 566; CHECK: rem.is.unsafe: 567; CHECK-NEXT: ret i32 0 568; 569entry: 570 br i1 %c0, label %if.then, label %if.end 571 572if.then: 573 %v = load volatile i32, ptr %p 574 br label %if.end 575 576if.end: 577 %lhs = phi i32 [ %v, %if.then ], [ 5, %entry ] 578 br i1 %always_false, label %rem.is.safe, label %rem.is.unsafe 579 580rem.is.safe: 581 %rem = srem i32 %lhs, -2147483648 582 ret i32 %rem 583 584rem.is.unsafe: 585 ret i32 0 586} 587 588define i32 @pr27968_2(i1 %c0, ptr %p) { 589; CHECK-LABEL: @pr27968_2( 590; CHECK-NEXT: entry: 591; CHECK-NEXT: br i1 [[C0:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 592; CHECK: if.then: 593; CHECK-NEXT: [[V:%.*]] = load volatile i32, ptr [[P:%.*]], align 4 594; CHECK-NEXT: br label [[IF_END]] 595; CHECK: if.end: 596; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr getelementptr inbounds nuw (i8, ptr @a, i64 8), @b 597; CHECK-NEXT: br i1 [[CMP]], label [[REM_IS_SAFE:%.*]], label [[REM_IS_UNSAFE:%.*]] 598; CHECK: rem.is.safe: 599; CHECK-NEXT: ret i32 0 600; CHECK: rem.is.unsafe: 601; CHECK-NEXT: ret i32 0 602; 603entry: 604 br i1 %c0, label %if.then, label %if.end 605 606if.then: 607 %v = load volatile i32, ptr %p 608 br label %if.end 609 610if.end: 611 %lhs = phi i32 [ %v, %if.then ], [ 5, %entry ] 612 %cmp = icmp eq ptr getelementptr inbounds ([5 x i16], ptr @a, i64 0, i64 4), @b 613 br i1 %cmp, label %rem.is.safe, label %rem.is.unsafe 614 615rem.is.safe: 616 %ext = zext i1 %cmp to i32 617 %rem = urem i32 %lhs, %ext 618 ret i32 %rem 619 620rem.is.unsafe: 621 ret i32 0 622} 623 624define i32 @pr27968_3(i1 %c0, i1 %always_false, ptr %p) { 625; CHECK-LABEL: @pr27968_3( 626; CHECK-NEXT: entry: 627; CHECK-NEXT: br i1 [[C0:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 628; CHECK: if.then: 629; CHECK-NEXT: [[V:%.*]] = load volatile i32, ptr [[P:%.*]], align 4 630; CHECK-NEXT: [[TMP0:%.*]] = and i32 [[V]], 2147483647 631; CHECK-NEXT: br label [[IF_END]] 632; CHECK: if.end: 633; CHECK-NEXT: [[LHS:%.*]] = phi i32 [ [[TMP0]], [[IF_THEN]] ], [ 5, [[ENTRY:%.*]] ] 634; CHECK-NEXT: br i1 [[ALWAYS_FALSE:%.*]], label [[REM_IS_SAFE:%.*]], label [[REM_IS_UNSAFE:%.*]] 635; CHECK: rem.is.safe: 636; CHECK-NEXT: ret i32 [[LHS]] 637; CHECK: rem.is.unsafe: 638; CHECK-NEXT: ret i32 0 639; 640entry: 641 br i1 %c0, label %if.then, label %if.end 642 643if.then: 644 %v = load volatile i32, ptr %p 645 br label %if.end 646 647if.end: 648 %lhs = phi i32 [ %v, %if.then ], [ 5, %entry ] 649 br i1 %always_false, label %rem.is.safe, label %rem.is.unsafe 650 651rem.is.safe: 652 %rem = urem i32 %lhs, -2147483648 653 ret i32 %rem 654 655rem.is.unsafe: 656 ret i32 0 657} 658 659define i32 @test22(i32 %A) { 660; CHECK-LABEL: @test22( 661; CHECK-NEXT: [[AND:%.*]] = and i32 [[A:%.*]], 2147483647 662; CHECK-NEXT: [[MUL:%.*]] = urem i32 [[AND]], 2147483647 663; CHECK-NEXT: ret i32 [[MUL]] 664; 665 %and = and i32 %A, 2147483647 666 %mul = srem i32 %and, 2147483647 667 ret i32 %mul 668} 669 670define <2 x i32> @test23(<2 x i32> %A) { 671; CHECK-LABEL: @test23( 672; CHECK-NEXT: [[AND:%.*]] = and <2 x i32> [[A:%.*]], splat (i32 2147483647) 673; CHECK-NEXT: [[MUL:%.*]] = urem <2 x i32> [[AND]], splat (i32 2147483647) 674; CHECK-NEXT: ret <2 x i32> [[MUL]] 675; 676 %and = and <2 x i32> %A, <i32 2147483647, i32 2147483647> 677 %mul = srem <2 x i32> %and, <i32 2147483647, i32 2147483647> 678 ret <2 x i32> %mul 679} 680 681define i1 @test24(i32 %A) { 682; CHECK-LABEL: @test24( 683; CHECK-NEXT: [[B:%.*]] = and i32 [[A:%.*]], 2147483647 684; CHECK-NEXT: [[C:%.*]] = icmp ne i32 [[B]], 0 685; CHECK-NEXT: ret i1 [[C]] 686; 687 %B = urem i32 %A, 2147483648 ; signbit 688 %C = icmp ne i32 %B, 0 689 ret i1 %C 690} 691 692define <2 x i1> @test24_vec(<2 x i32> %A) { 693; CHECK-LABEL: @test24_vec( 694; CHECK-NEXT: [[B:%.*]] = and <2 x i32> [[A:%.*]], splat (i32 2147483647) 695; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i32> [[B]], zeroinitializer 696; CHECK-NEXT: ret <2 x i1> [[C]] 697; 698 %B = urem <2 x i32> %A, <i32 2147483648, i32 2147483648> 699 %C = icmp ne <2 x i32> %B, zeroinitializer 700 ret <2 x i1> %C 701} 702 703define i1 @test25(i32 %A) { 704; CHECK-LABEL: @test25( 705; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[A:%.*]], 2147483647 706; CHECK-NEXT: [[C:%.*]] = icmp ne i32 [[TMP1]], 0 707; CHECK-NEXT: ret i1 [[C]] 708; 709 %B = srem i32 %A, 2147483648 ; signbit 710 %C = icmp ne i32 %B, 0 711 ret i1 %C 712} 713 714define <2 x i1> @test25_vec(<2 x i32> %A) { 715; CHECK-LABEL: @test25_vec( 716; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[A:%.*]], splat (i32 2147483647) 717; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i32> [[TMP1]], zeroinitializer 718; CHECK-NEXT: ret <2 x i1> [[C]] 719; 720 %B = srem <2 x i32> %A, <i32 2147483648, i32 2147483648> 721 %C = icmp ne <2 x i32> %B, zeroinitializer 722 ret <2 x i1> %C 723} 724 725define i1 @test26(i32 %A, i32 %B) { 726; CHECK-LABEL: @test26( 727; CHECK-NEXT: [[NOTMASK:%.*]] = shl nsw i32 -1, [[B:%.*]] 728; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[NOTMASK]], -1 729; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[A:%.*]], [[TMP1]] 730; CHECK-NEXT: [[E:%.*]] = icmp ne i32 [[TMP2]], 0 731; CHECK-NEXT: ret i1 [[E]] 732; 733 %C = shl i32 1, %B ; not a constant 734 %D = srem i32 %A, %C 735 %E = icmp ne i32 %D, 0 736 ret i1 %E 737} 738 739define i1 @test27(i32 %A, ptr %remdst) { 740; CHECK-LABEL: @test27( 741; CHECK-NEXT: [[B:%.*]] = srem i32 [[A:%.*]], -2147483648 742; CHECK-NEXT: store i32 [[B]], ptr [[REMDST:%.*]], align 1 743; CHECK-NEXT: [[C:%.*]] = icmp ne i32 [[B]], 0 744; CHECK-NEXT: ret i1 [[C]] 745; 746 %B = srem i32 %A, 2147483648 ; signbit 747 store i32 %B, ptr %remdst, align 1 ; extra use of rem 748 %C = icmp ne i32 %B, 0 749 ret i1 %C 750} 751 752define i1 @test28(i32 %A) { 753; CHECK-LABEL: @test28( 754; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[A:%.*]], 2147483647 755; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[TMP1]], 0 756; CHECK-NEXT: ret i1 [[C]] 757; 758 %B = srem i32 %A, 2147483648 ; signbit 759 %C = icmp eq i32 %B, 0 ; another equality predicate 760 ret i1 %C 761} 762 763define i1 @positive_and_odd_eq(i32 %A) { 764; CHECK-LABEL: @positive_and_odd_eq( 765; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[A:%.*]], -2147483647 766; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[TMP1]], 1 767; CHECK-NEXT: ret i1 [[C]] 768; 769 %B = srem i32 %A, 2 770 %C = icmp eq i32 %B, 1 771 ret i1 %C 772} 773 774define i1 @negative_and_odd_eq(i32 %A) { 775; CHECK-LABEL: @negative_and_odd_eq( 776; CHECK-NEXT: [[B:%.*]] = srem i32 [[A:%.*]], 2 777; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[B]], -1 778; CHECK-NEXT: ret i1 [[C]] 779; 780 %B = srem i32 %A, 2 781 %C = icmp eq i32 %B, -1 782 ret i1 %C 783} 784 785define i1 @positive_and_odd_ne(i32 %A) { 786; CHECK-LABEL: @positive_and_odd_ne( 787; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[A:%.*]], -2147483647 788; CHECK-NEXT: [[C:%.*]] = icmp ne i32 [[TMP1]], 1 789; CHECK-NEXT: ret i1 [[C]] 790; 791 %B = srem i32 %A, 2 792 %C = icmp ne i32 %B, 1 793 ret i1 %C 794} 795 796define i1 @negative_and_odd_ne(i32 %A) { 797; CHECK-LABEL: @negative_and_odd_ne( 798; CHECK-NEXT: [[B:%.*]] = srem i32 [[A:%.*]], 2 799; CHECK-NEXT: [[C:%.*]] = icmp ne i32 [[B]], -1 800; CHECK-NEXT: ret i1 [[C]] 801; 802 %B = srem i32 %A, 2 803 %C = icmp ne i32 %B, -1 804 ret i1 %C 805} 806 807; FP division-by-zero is not UB. 808 809define double @PR34870(i1 %cond, double %x, double %y) { 810; CHECK-LABEL: @PR34870( 811; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], double [[Y:%.*]], double 0.000000e+00 812; CHECK-NEXT: [[FMOD:%.*]] = frem double [[X:%.*]], [[SEL]] 813; CHECK-NEXT: ret double [[FMOD]] 814; 815 %sel = select i1 %cond, double %y, double 0.0 816 %fmod = frem double %x, %sel 817 ret double %fmod 818} 819 820define i32 @srem_constant_dividend_select_of_constants_divisor(i1 %b) { 821; CHECK-LABEL: @srem_constant_dividend_select_of_constants_divisor( 822; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], i32 6, i32 0 823; CHECK-NEXT: ret i32 [[R]] 824; 825 %s = select i1 %b, i32 12, i32 -3 826 %r = srem i32 42, %s 827 ret i32 %r 828} 829 830define i32 @srem_constant_dividend_select_of_constants_divisor_use(i1 %b) { 831; CHECK-LABEL: @srem_constant_dividend_select_of_constants_divisor_use( 832; CHECK-NEXT: [[S:%.*]] = select i1 [[B:%.*]], i32 12, i32 -3 833; CHECK-NEXT: call void @use(i32 [[S]]) 834; CHECK-NEXT: [[R:%.*]] = select i1 [[B]], i32 6, i32 0 835; CHECK-NEXT: ret i32 [[R]] 836; 837 %s = select i1 %b, i32 12, i32 -3 838 call void @use(i32 %s) 839 %r = srem i32 42, %s 840 ret i32 %r 841} 842 843; Rem-by-0 is immediate UB, so select is simplified. 844 845define i32 @srem_constant_dividend_select_of_constants_divisor_0_arm(i1 %b) { 846; CHECK-LABEL: @srem_constant_dividend_select_of_constants_divisor_0_arm( 847; CHECK-NEXT: ret i32 6 848; 849 %s = select i1 %b, i32 12, i32 0 850 %r = srem i32 42, %s 851 ret i32 %r 852} 853 854; negative test - not safe to speculate rem with variable divisor 855 856define i32 @srem_constant_dividend_select_divisor1(i1 %b, i32 %x) { 857; CHECK-LABEL: @srem_constant_dividend_select_divisor1( 858; CHECK-NEXT: [[S:%.*]] = select i1 [[B:%.*]], i32 [[X:%.*]], i32 -3 859; CHECK-NEXT: [[R:%.*]] = srem i32 42, [[S]] 860; CHECK-NEXT: ret i32 [[R]] 861; 862 %s = select i1 %b, i32 %x, i32 -3 863 %r = srem i32 42, %s 864 ret i32 %r 865} 866 867; negative test - not safe to speculate rem with variable divisor 868 869define i32 @srem_constant_dividend_select_divisor2(i1 %b, i32 %x) { 870; CHECK-LABEL: @srem_constant_dividend_select_divisor2( 871; CHECK-NEXT: [[S:%.*]] = select i1 [[B:%.*]], i32 12, i32 [[X:%.*]] 872; CHECK-NEXT: [[R:%.*]] = srem i32 42, [[S]] 873; CHECK-NEXT: ret i32 [[R]] 874; 875 %s = select i1 %b, i32 12, i32 %x 876 %r = srem i32 42, %s 877 ret i32 %r 878} 879 880define <2 x i8> @srem_constant_dividend_select_of_constants_divisor_vec(i1 %b) { 881; CHECK-LABEL: @srem_constant_dividend_select_of_constants_divisor_vec( 882; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], <2 x i8> <i8 6, i8 -2>, <2 x i8> <i8 2, i8 -2> 883; CHECK-NEXT: ret <2 x i8> [[R]] 884; 885 %s = select i1 %b, <2 x i8> <i8 12, i8 -5>, <2 x i8> <i8 -4, i8 4> 886 %r = srem <2 x i8> <i8 42, i8 -42>, %s 887 ret <2 x i8> %r 888} 889 890; Rem-by-0 element is immediate UB, so select is simplified. 891 892define <2 x i8> @srem_constant_dividend_select_of_constants_divisor_vec_ub1(i1 %b) { 893; CHECK-LABEL: @srem_constant_dividend_select_of_constants_divisor_vec_ub1( 894; CHECK-NEXT: ret <2 x i8> <i8 2, i8 -2> 895; 896 %s = select i1 %b, <2 x i8> <i8 0, i8 -5>, <2 x i8> <i8 -4, i8 4> 897 %r = srem <2 x i8> <i8 42, i8 -42>, %s 898 ret <2 x i8> %r 899} 900 901; SMIN % -1 element is poison. 902 903define <2 x i8> @srem_constant_dividend_select_of_constants_divisor_vec_ub2(i1 %b) { 904; CHECK-LABEL: @srem_constant_dividend_select_of_constants_divisor_vec_ub2( 905; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], <2 x i8> <i8 6, i8 -3>, <2 x i8> <i8 2, i8 poison> 906; CHECK-NEXT: ret <2 x i8> [[R]] 907; 908 %s = select i1 %b, <2 x i8> <i8 12, i8 -5>, <2 x i8> <i8 -4, i8 -1> 909 %r = srem <2 x i8> <i8 42, i8 -128>, %s 910 ret <2 x i8> %r 911} 912 913; negative test - must have constant dividend 914 915define i32 @srem_select_of_constants_divisor(i1 %b, i32 %x) { 916; CHECK-LABEL: @srem_select_of_constants_divisor( 917; CHECK-NEXT: [[S:%.*]] = select i1 [[B:%.*]], i32 12, i32 -3 918; CHECK-NEXT: [[R:%.*]] = srem i32 [[X:%.*]], [[S]] 919; CHECK-NEXT: ret i32 [[R]] 920; 921 %s = select i1 %b, i32 12, i32 -3 922 %r = srem i32 %x, %s 923 ret i32 %r 924} 925 926define i32 @urem_constant_dividend_select_of_constants_divisor(i1 %b) { 927; CHECK-LABEL: @urem_constant_dividend_select_of_constants_divisor( 928; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], i32 6, i32 42 929; CHECK-NEXT: ret i32 [[R]] 930; 931 %s = select i1 %b, i32 12, i32 -3 932 %r = urem i32 42, %s 933 ret i32 %r 934} 935 936define i32 @urem_constant_dividend_select_of_constants_divisor_use(i1 %b) { 937; CHECK-LABEL: @urem_constant_dividend_select_of_constants_divisor_use( 938; CHECK-NEXT: [[S:%.*]] = select i1 [[B:%.*]], i32 12, i32 -3 939; CHECK-NEXT: call void @use(i32 [[S]]) 940; CHECK-NEXT: [[R:%.*]] = select i1 [[B]], i32 6, i32 42 941; CHECK-NEXT: ret i32 [[R]] 942; 943 %s = select i1 %b, i32 12, i32 -3 944 call void @use(i32 %s) 945 %r = urem i32 42, %s 946 ret i32 %r 947} 948 949; Rem-by-0 is immediate UB, so select is simplified. 950 951define i32 @urem_constant_dividend_select_of_constants_divisor_0_arm(i1 %b) { 952; CHECK-LABEL: @urem_constant_dividend_select_of_constants_divisor_0_arm( 953; CHECK-NEXT: ret i32 6 954; 955 %s = select i1 %b, i32 12, i32 0 956 %r = urem i32 42, %s 957 ret i32 %r 958} 959 960; negative test - not safe to speculate rem with variable divisor 961 962define i32 @urem_constant_dividend_select_divisor1(i1 %b, i32 %x) { 963; CHECK-LABEL: @urem_constant_dividend_select_divisor1( 964; CHECK-NEXT: [[S:%.*]] = select i1 [[B:%.*]], i32 [[X:%.*]], i32 -3 965; CHECK-NEXT: [[R:%.*]] = urem i32 42, [[S]] 966; CHECK-NEXT: ret i32 [[R]] 967; 968 %s = select i1 %b, i32 %x, i32 -3 969 %r = urem i32 42, %s 970 ret i32 %r 971} 972 973; negative test - not safe to speculate rem with variable divisor 974 975define i32 @urem_constant_dividend_select_divisor2(i1 %b, i32 %x) { 976; CHECK-LABEL: @urem_constant_dividend_select_divisor2( 977; CHECK-NEXT: [[S:%.*]] = select i1 [[B:%.*]], i32 12, i32 [[X:%.*]] 978; CHECK-NEXT: [[R:%.*]] = urem i32 42, [[S]] 979; CHECK-NEXT: ret i32 [[R]] 980; 981 %s = select i1 %b, i32 12, i32 %x 982 %r = urem i32 42, %s 983 ret i32 %r 984} 985 986define <2 x i8> @urem_constant_dividend_select_of_constants_divisor_vec(i1 %b) { 987; CHECK-LABEL: @urem_constant_dividend_select_of_constants_divisor_vec( 988; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], <2 x i8> <i8 6, i8 -42>, <2 x i8> <i8 42, i8 2> 989; CHECK-NEXT: ret <2 x i8> [[R]] 990; 991 %s = select i1 %b, <2 x i8> <i8 12, i8 -5>, <2 x i8> <i8 -4, i8 4> 992 %r = urem <2 x i8> <i8 42, i8 -42>, %s 993 ret <2 x i8> %r 994} 995 996; Rem-by-0 element is immediate UB, so select is simplified. 997 998define <2 x i8> @urem_constant_dividend_select_of_constants_divisor_vec_ub1(i1 %b) { 999; CHECK-LABEL: @urem_constant_dividend_select_of_constants_divisor_vec_ub1( 1000; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], <2 x i8> <i8 poison, i8 -42>, <2 x i8> <i8 42, i8 2> 1001; CHECK-NEXT: ret <2 x i8> [[R]] 1002; 1003 %s = select i1 %b, <2 x i8> <i8 0, i8 -5>, <2 x i8> <i8 -4, i8 4> 1004 %r = urem <2 x i8> <i8 42, i8 -42>, %s 1005 ret <2 x i8> %r 1006} 1007 1008; There's no unsigned equivalent to "SMIN % -1", so this is just the usual constant folding. 1009 1010define <2 x i8> @urem_constant_dividend_select_of_constants_divisor_vec_ub2(i1 %b) { 1011; CHECK-LABEL: @urem_constant_dividend_select_of_constants_divisor_vec_ub2( 1012; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], <2 x i8> <i8 6, i8 -128>, <2 x i8> <i8 42, i8 -128> 1013; CHECK-NEXT: ret <2 x i8> [[R]] 1014; 1015 %s = select i1 %b, <2 x i8> <i8 12, i8 -5>, <2 x i8> <i8 -4, i8 -1> 1016 %r = urem <2 x i8> <i8 42, i8 -128>, %s 1017 ret <2 x i8> %r 1018} 1019 1020; negative test - must have constant dividend 1021 1022define i32 @urem_select_of_constants_divisor(i1 %b, i32 %x) { 1023; CHECK-LABEL: @urem_select_of_constants_divisor( 1024; CHECK-NEXT: [[S:%.*]] = select i1 [[B:%.*]], i32 12, i32 -3 1025; CHECK-NEXT: [[R:%.*]] = urem i32 [[X:%.*]], [[S]] 1026; CHECK-NEXT: ret i32 [[R]] 1027; 1028 %s = select i1 %b, i32 12, i32 -3 1029 %r = urem i32 %x, %s 1030 ret i32 %r 1031} 1032 1033; https://alive2.llvm.org/ce/z/bh2KHm 1034define <2 x i32> @PR62401(<2 x i1> %x, <2 x i32> %y) { 1035; CHECK-LABEL: @PR62401( 1036; CHECK-NEXT: [[Y_FROZEN:%.*]] = freeze <2 x i32> [[Y:%.*]] 1037; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i32> [[Y_FROZEN]], splat (i32 -1) 1038; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[TMP1]], <2 x i32> zeroinitializer, <2 x i32> [[Y_FROZEN]] 1039; CHECK-NEXT: ret <2 x i32> [[R]] 1040; 1041 %sext.i1 = sext <2 x i1> %x to <2 x i32> 1042 %r = urem <2 x i32> %y, %sext.i1 1043 ret <2 x i32> %r 1044} 1045 1046define i16 @rem_pow2_or_zero(i16 %x, i16 %y) { 1047; CHECK-LABEL: @rem_pow2_or_zero( 1048; CHECK-NEXT: [[POPCNT:%.*]] = call range(i16 1, 17) i16 @llvm.ctpop.i16(i16 [[Y:%.*]]) 1049; CHECK-NEXT: [[COND:%.*]] = icmp samesign ult i16 [[POPCNT]], 2 1050; CHECK-NEXT: tail call void @llvm.assume(i1 [[COND]]) 1051; CHECK-NEXT: [[TMP1:%.*]] = add i16 [[Y]], -1 1052; CHECK-NEXT: [[REM:%.*]] = and i16 [[X:%.*]], [[TMP1]] 1053; CHECK-NEXT: ret i16 [[REM]] 1054; 1055 %popcnt = call i16 @llvm.ctpop.i16(i16 %y) 1056 %cond = icmp ult i16 %popcnt, 2 1057 tail call void @llvm.assume(i1 %cond) 1058 %rem = urem i16 %x, %y 1059 ret i16 %rem 1060} 1061 1062define i16 @rem_pow2(i16 %x, i16 %y) { 1063; CHECK-LABEL: @rem_pow2( 1064; CHECK-NEXT: [[POPCNT:%.*]] = call range(i16 1, 17) i16 @llvm.ctpop.i16(i16 [[Y:%.*]]) 1065; CHECK-NEXT: [[COND:%.*]] = icmp eq i16 [[POPCNT]], 1 1066; CHECK-NEXT: tail call void @llvm.assume(i1 [[COND]]) 1067; CHECK-NEXT: [[TMP1:%.*]] = add i16 [[Y]], -1 1068; CHECK-NEXT: [[REM:%.*]] = and i16 [[X:%.*]], [[TMP1]] 1069; CHECK-NEXT: ret i16 [[REM]] 1070; 1071 %popcnt = call i16 @llvm.ctpop.i16(i16 %y) 1072 %cond = icmp eq i16 %popcnt, 1 1073 tail call void @llvm.assume(i1 %cond) 1074 %rem = urem i16 %x, %y 1075 ret i16 %rem 1076} 1077 1078define i64 @rem_pow2_domcond(i64 %a, i64 %b) { 1079; CHECK-LABEL: @rem_pow2_domcond( 1080; CHECK-NEXT: start: 1081; CHECK-NEXT: [[CPOP:%.*]] = call range(i64 0, 65) i64 @llvm.ctpop.i64(i64 [[B:%.*]]) 1082; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[CPOP]], 1 1083; CHECK-NEXT: br i1 [[COND]], label [[BB1:%.*]], label [[BB2:%.*]] 1084; CHECK: bb1: 1085; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[B]], -1 1086; CHECK-NEXT: [[REM:%.*]] = and i64 [[A:%.*]], [[TMP0]] 1087; CHECK-NEXT: ret i64 [[REM]] 1088; CHECK: bb2: 1089; CHECK-NEXT: ret i64 0 1090; 1091start: 1092 %cpop = call i64 @llvm.ctpop.i64(i64 %b) 1093 %cond = icmp eq i64 %cpop, 1 1094 br i1 %cond, label %bb1, label %bb2 1095 1096bb1: 1097 %rem = urem i64 %a, %b 1098 ret i64 %rem 1099 1100bb2: 1101 ret i64 0 1102} 1103 1104define i64 @rem_pow2_domcond_in_else(i64 %a, i64 %b) { 1105; CHECK-LABEL: @rem_pow2_domcond_in_else( 1106; CHECK-NEXT: start: 1107; CHECK-NEXT: [[CPOP:%.*]] = call range(i64 0, 65) i64 @llvm.ctpop.i64(i64 [[B:%.*]]) 1108; CHECK-NEXT: [[COND_NOT:%.*]] = icmp eq i64 [[CPOP]], 1 1109; CHECK-NEXT: br i1 [[COND_NOT]], label [[BB1:%.*]], label [[BB2:%.*]] 1110; CHECK: bb1: 1111; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[B]], -1 1112; CHECK-NEXT: [[REM:%.*]] = and i64 [[A:%.*]], [[TMP0]] 1113; CHECK-NEXT: ret i64 [[REM]] 1114; CHECK: bb2: 1115; CHECK-NEXT: ret i64 0 1116; 1117start: 1118 %cpop = call i64 @llvm.ctpop.i64(i64 %b) 1119 %cond = icmp ne i64 %cpop, 1 1120 br i1 %cond, label %bb2, label %bb1 1121 1122bb1: 1123 %rem = urem i64 %a, %b 1124 ret i64 %rem 1125 1126bb2: 1127 ret i64 0 1128} 1129 1130define i64 @rem_pow2_or_zero_domcond(i64 %a, i64 %b) { 1131; CHECK-LABEL: @rem_pow2_or_zero_domcond( 1132; CHECK-NEXT: start: 1133; CHECK-NEXT: [[CPOP:%.*]] = call range(i64 0, 65) i64 @llvm.ctpop.i64(i64 [[B:%.*]]) 1134; CHECK-NEXT: [[COND:%.*]] = icmp samesign ult i64 [[CPOP]], 2 1135; CHECK-NEXT: br i1 [[COND]], label [[BB1:%.*]], label [[BB2:%.*]] 1136; CHECK: bb1: 1137; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[B]], -1 1138; CHECK-NEXT: [[REM:%.*]] = and i64 [[A:%.*]], [[TMP0]] 1139; CHECK-NEXT: ret i64 [[REM]] 1140; CHECK: bb2: 1141; CHECK-NEXT: ret i64 0 1142; 1143start: 1144 %cpop = call i64 @llvm.ctpop.i64(i64 %b) 1145 %cond = icmp ult i64 %cpop, 2 1146 br i1 %cond, label %bb1, label %bb2 1147 1148bb1: 1149 %rem = urem i64 %a, %b 1150 ret i64 %rem 1151 1152bb2: 1153 ret i64 0 1154} 1155 1156define i64 @rem_pow2_non_domcond(i64 %a, i64 %b) { 1157; CHECK-LABEL: @rem_pow2_non_domcond( 1158; CHECK-NEXT: start: 1159; CHECK-NEXT: [[CPOP:%.*]] = call range(i64 0, 65) i64 @llvm.ctpop.i64(i64 [[B:%.*]]) 1160; CHECK-NEXT: [[COND_NOT:%.*]] = icmp eq i64 [[CPOP]], 1 1161; CHECK-NEXT: br i1 [[COND_NOT]], label [[BB1:%.*]], label [[BB2:%.*]] 1162; CHECK: bb1: 1163; CHECK-NEXT: [[REM:%.*]] = urem i64 [[A:%.*]], [[B]] 1164; CHECK-NEXT: ret i64 [[REM]] 1165; CHECK: bb2: 1166; CHECK-NEXT: br label [[BB1]] 1167; 1168start: 1169 %cpop = call i64 @llvm.ctpop.i64(i64 %b) 1170 %cond = icmp ne i64 %cpop, 1 1171 br i1 %cond, label %bb2, label %bb1 1172 1173bb1: 1174 %rem = urem i64 %a, %b 1175 ret i64 %rem 1176 1177bb2: 1178 br label %bb1 1179} 1180