1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2 ; RUN: opt < %s -instcombine -S | FileCheck %s 3 4 define i64 @rem_signed(i64 %x1, i64 %y2) { 5 ; CHECK-LABEL: @rem_signed( 6 ; CHECK-NEXT: [[TMP1:%.*]] = srem i64 [[X1:%.*]], [[Y2:%.*]] 7 ; CHECK-NEXT: ret i64 [[TMP1]] 8 ; 9 %r = sdiv i64 %x1, %y2 10 %r7 = mul i64 %r, %y2 11 %r8 = sub i64 %x1, %r7 12 ret i64 %r8 13 } 14 15 define <4 x i32> @rem_signed_vec(<4 x i32> %t, <4 x i32> %u) { 16 ; CHECK-LABEL: @rem_signed_vec( 17 ; CHECK-NEXT: [[TMP1:%.*]] = srem <4 x i32> [[T:%.*]], [[U:%.*]] 18 ; CHECK-NEXT: ret <4 x i32> [[TMP1]] 19 ; 20 %k = sdiv <4 x i32> %t, %u 21 %l = mul <4 x i32> %k, %u 22 %m = sub <4 x i32> %t, %l 23 ret <4 x i32> %m 24 } 25 26 define i64 @rem_unsigned(i64 %x1, i64 %y2) { 27 ; CHECK-LABEL: @rem_unsigned( 28 ; CHECK-NEXT: [[TMP1:%.*]] = urem i64 [[X1:%.*]], [[Y2:%.*]] 29 ; CHECK-NEXT: ret i64 [[TMP1]] 30 ; 31 %r = udiv i64 %x1, %y2 32 %r7 = mul i64 %r, %y2 33 %r8 = sub i64 %x1, %r7 34 ret i64 %r8 35 } 36 37 ; PR28672 - https://llvm.org/bugs/show_bug.cgi?id=28672 38 39 define i8 @big_divisor(i8 %x) { 40 ; CHECK-LABEL: @big_divisor( 41 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i8 [[X:%.*]], -127 42 ; CHECK-NEXT: [[TMP2:%.*]] = add i8 [[X]], 127 43 ; CHECK-NEXT: [[REM:%.*]] = select i1 [[TMP1]], i8 [[X]], i8 [[TMP2]] 44 ; CHECK-NEXT: ret i8 [[REM]] 45 ; 46 %rem = urem i8 %x, 129 47 ret i8 %rem 48 } 49 50 define i5 @biggest_divisor(i5 %x) { 51 ; CHECK-LABEL: @biggest_divisor( 52 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i5 [[X:%.*]], -1 53 ; CHECK-NEXT: [[TMP2:%.*]] = zext i1 [[TMP1]] to i5 54 ; CHECK-NEXT: [[REM:%.*]] = add i5 [[TMP2]], [[X]] 55 ; CHECK-NEXT: ret i5 [[REM]] 56 ; 57 %rem = urem i5 %x, -1 58 ret i5 %rem 59 } 60 61 define i8 @urem_with_sext_bool_divisor(i1 %x, i8 %y) { 62 ; CHECK-LABEL: @urem_with_sext_bool_divisor( 63 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8 [[Y:%.*]], -1 64 ; CHECK-NEXT: [[REM:%.*]] = select i1 [[TMP1]], i8 0, i8 [[Y]] 65 ; CHECK-NEXT: ret i8 [[REM]] 66 ; 67 %s = sext i1 %x to i8 68 %rem = urem i8 %y, %s 69 ret i8 %rem 70 } 71 72 define <2 x i8> @urem_with_sext_bool_divisor_vec(<2 x i1> %x, <2 x i8> %y) { 73 ; CHECK-LABEL: @urem_with_sext_bool_divisor_vec( 74 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i8> [[Y:%.*]], <i8 -1, i8 -1> 75 ; CHECK-NEXT: [[REM:%.*]] = select <2 x i1> [[TMP1]], <2 x i8> zeroinitializer, <2 x i8> [[Y]] 76 ; CHECK-NEXT: ret <2 x i8> [[REM]] 77 ; 78 %s = sext <2 x i1> %x to <2 x i8> 79 %rem = urem <2 x i8> %y, %s 80 ret <2 x i8> %rem 81 } 82 83 define <2 x i4> @big_divisor_vec(<2 x i4> %x) { 84 ; CHECK-LABEL: @big_divisor_vec( 85 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult <2 x i4> [[X:%.*]], <i4 -3, i4 -3> 86 ; CHECK-NEXT: [[TMP2:%.*]] = add <2 x i4> [[X]], <i4 3, i4 3> 87 ; CHECK-NEXT: [[REM:%.*]] = select <2 x i1> [[TMP1]], <2 x i4> [[X]], <2 x i4> [[TMP2]] 88 ; CHECK-NEXT: ret <2 x i4> [[REM]] 89 ; 90 %rem = urem <2 x i4> %x, <i4 13, i4 13> 91 ret <2 x i4> %rem 92 } 93 94 define i8 @urem1(i8 %x, i8 %y) { 95 ; CHECK-LABEL: @urem1( 96 ; CHECK-NEXT: [[TMP1:%.*]] = urem i8 [[X:%.*]], [[Y:%.*]] 97 ; CHECK-NEXT: ret i8 [[TMP1]] 98 ; 99 %A = udiv i8 %x, %y 100 %B = mul i8 %A, %y 101 %C = sub i8 %x, %B 102 ret i8 %C 103 } 104 105 define i8 @srem1(i8 %x, i8 %y) { 106 ; CHECK-LABEL: @srem1( 107 ; CHECK-NEXT: [[TMP1:%.*]] = srem i8 [[X:%.*]], [[Y:%.*]] 108 ; CHECK-NEXT: ret i8 [[TMP1]] 109 ; 110 %A = sdiv i8 %x, %y 111 %B = mul i8 %A, %y 112 %C = sub i8 %x, %B 113 ret i8 %C 114 } 115 116 define i8 @urem2(i8 %x, i8 %y) { 117 ; CHECK-LABEL: @urem2( 118 ; CHECK-NEXT: [[TMP1:%.*]] = urem i8 [[X:%.*]], [[Y:%.*]] 119 ; CHECK-NEXT: [[C:%.*]] = sub i8 0, [[TMP1]] 120 ; CHECK-NEXT: ret i8 [[C]] 121 ; 122 %A = udiv i8 %x, %y 123 %B = mul i8 %A, %y 124 %C = sub i8 %B, %x 125 ret i8 %C 126 } 127 128 define i8 @urem3(i8 %x) { 129 ; CHECK-LABEL: @urem3( 130 ; CHECK-NEXT: [[TMP1:%.*]] = urem i8 [[X:%.*]], 3 131 ; CHECK-NEXT: [[B1:%.*]] = sub i8 [[X]], [[TMP1]] 132 ; CHECK-NEXT: [[C:%.*]] = add i8 [[B1]], [[X]] 133 ; CHECK-NEXT: ret i8 [[C]] 134 ; 135 %A = udiv i8 %x, 3 136 %B = mul i8 %A, -3 137 %C = sub i8 %x, %B 138 ret i8 %C 139 } 140 141 ; (((X / Y) * Y) / Y) -> X / Y 142 143 define i32 @sdiv_mul_sdiv(i32 %x, i32 %y) { 144 ; CHECK-LABEL: @sdiv_mul_sdiv( 145 ; CHECK-NEXT: [[R:%.*]] = sdiv i32 [[X:%.*]], [[Y:%.*]] 146 ; CHECK-NEXT: ret i32 [[R]] 147 ; 148 %div = sdiv i32 %x, %y 149 %mul = mul i32 %div, %y 150 %r = sdiv i32 %mul, %y 151 ret i32 %r 152 } 153 154 ; (((X / Y) * Y) / Y) -> X / Y 155 156 define i32 @udiv_mul_udiv(i32 %x, i32 %y) { 157 ; CHECK-LABEL: @udiv_mul_udiv( 158 ; CHECK-NEXT: [[R:%.*]] = udiv i32 [[X:%.*]], [[Y:%.*]] 159 ; CHECK-NEXT: ret i32 [[R]] 160 ; 161 %div = udiv i32 %x, %y 162 %mul = mul i32 %div, %y 163 %r = udiv i32 %mul, %y 164 ret i32 %r 165 } 166 167 define i32 @test1(i32 %A) { 168 ; CHECK-LABEL: @test1( 169 ; CHECK-NEXT: ret i32 0 170 ; 171 %B = srem i32 %A, 1 ; ISA constant 0 172 ret i32 %B 173 } 174 175 define i32 @test3(i32 %A) { 176 ; CHECK-LABEL: @test3( 177 ; CHECK-NEXT: [[B:%.*]] = and i32 [[A:%.*]], 7 178 ; CHECK-NEXT: ret i32 [[B]] 179 ; 180 %B = urem i32 %A, 8 181 ret i32 %B 182 } 183 184 define <2 x i32> @vec_power_of_2_constant_splat_divisor(<2 x i32> %A) { 185 ; CHECK-LABEL: @vec_power_of_2_constant_splat_divisor( 186 ; CHECK-NEXT: [[B:%.*]] = and <2 x i32> [[A:%.*]], <i32 7, i32 7> 187 ; CHECK-NEXT: ret <2 x i32> [[B]] 188 ; 189 %B = urem <2 x i32> %A, <i32 8, i32 8> 190 ret <2 x i32> %B 191 } 192 193 define <2 x i19> @weird_vec_power_of_2_constant_splat_divisor(<2 x i19> %A) { 194 ; CHECK-LABEL: @weird_vec_power_of_2_constant_splat_divisor( 195 ; CHECK-NEXT: [[B:%.*]] = and <2 x i19> [[A:%.*]], <i19 7, i19 7> 196 ; CHECK-NEXT: ret <2 x i19> [[B]] 197 ; 198 %B = urem <2 x i19> %A, <i19 8, i19 8> 199 ret <2 x i19> %B 200 } 201 202 define i1 @test3a(i32 %A) { 203 ; CHECK-LABEL: @test3a( 204 ; CHECK-NEXT: [[B1:%.*]] = and i32 [[A:%.*]], 7 205 ; CHECK-NEXT: [[C:%.*]] = icmp ne i32 [[B1]], 0 206 ; CHECK-NEXT: ret i1 [[C]] 207 ; 208 %B = srem i32 %A, -8 209 %C = icmp ne i32 %B, 0 210 ret i1 %C 211 } 212 213 define <2 x i1> @test3a_vec(<2 x i32> %A) { 214 ; CHECK-LABEL: @test3a_vec( 215 ; CHECK-NEXT: [[B1:%.*]] = and <2 x i32> [[A:%.*]], <i32 7, i32 7> 216 ; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i32> [[B1]], zeroinitializer 217 ; CHECK-NEXT: ret <2 x i1> [[C]] 218 ; 219 %B = srem <2 x i32> %A, <i32 -8, i32 -8> 220 %C = icmp ne <2 x i32> %B, zeroinitializer 221 ret <2 x i1> %C 222 } 223 224 define i32 @test4(i32 %X, i1 %C) { 225 ; CHECK-LABEL: @test4( 226 ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C:%.*]], i32 0, i32 7 227 ; CHECK-NEXT: [[R:%.*]] = and i32 [[TMP1]], [[X:%.*]] 228 ; CHECK-NEXT: ret i32 [[R]] 229 ; 230 %V = select i1 %C, i32 1, i32 8 231 %R = urem i32 %X, %V 232 ret i32 %R 233 } 234 235 define i32 @test5(i32 %X, i8 %B) { 236 ; CHECK-LABEL: @test5( 237 ; CHECK-NEXT: [[SHIFT_UPGRD_1:%.*]] = zext i8 [[B:%.*]] to i32 238 ; CHECK-NEXT: [[AMT:%.*]] = shl nuw i32 32, [[SHIFT_UPGRD_1]] 239 ; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[AMT]], -1 240 ; CHECK-NEXT: [[V:%.*]] = and i32 [[TMP1]], [[X:%.*]] 241 ; CHECK-NEXT: ret i32 [[V]] 242 ; 243 %shift.upgrd.1 = zext i8 %B to i32 244 %Amt = shl i32 32, %shift.upgrd.1 245 %V = urem i32 %X, %Amt 246 ret i32 %V 247 } 248 249 define i32 @test6(i32 %A) { 250 ; CHECK-LABEL: @test6( 251 ; CHECK-NEXT: ret i32 undef 252 ; 253 %B = srem i32 %A, 0 ;; undef 254 ret i32 %B 255 } 256 257 define i32 @test7(i32 %A) { 258 ; CHECK-LABEL: @test7( 259 ; CHECK-NEXT: ret i32 0 260 ; 261 %B = mul i32 %A, 8 262 %C = srem i32 %B, 4 263 ret i32 %C 264 } 265 266 define i32 @test8(i32 %A) { 267 ; CHECK-LABEL: @test8( 268 ; CHECK-NEXT: ret i32 0 269 ; 270 %B = shl i32 %A, 4 271 %C = srem i32 %B, 8 272 ret i32 %C 273 } 274 275 define i32 @test9(i32 %A) { 276 ; CHECK-LABEL: @test9( 277 ; CHECK-NEXT: ret i32 0 278 ; 279 %B = mul i32 %A, 64 280 %C = urem i32 %B, 32 281 ret i32 %C 282 } 283 284 define i32 @test10(i8 %c) { 285 ; CHECK-LABEL: @test10( 286 ; CHECK-NEXT: ret i32 0 287 ; 288 %tmp.1 = zext i8 %c to i32 289 %tmp.2 = mul i32 %tmp.1, 4 290 %tmp.3 = sext i32 %tmp.2 to i64 291 %tmp.5 = urem i64 %tmp.3, 4 292 %tmp.6 = trunc i64 %tmp.5 to i32 293 ret i32 %tmp.6 294 } 295 296 define i32 @test11(i32 %i) { 297 ; CHECK-LABEL: @test11( 298 ; CHECK-NEXT: ret i32 0 299 ; 300 %tmp.1 = and i32 %i, -2 301 %tmp.3 = mul i32 %tmp.1, 2 302 %tmp.5 = urem i32 %tmp.3, 4 303 ret i32 %tmp.5 304 } 305 306 define i32 @test12(i32 %i) { 307 ; CHECK-LABEL: @test12( 308 ; CHECK-NEXT: ret i32 0 309 ; 310 %tmp.1 = and i32 %i, -4 311 %tmp.5 = srem i32 %tmp.1, 2 312 ret i32 %tmp.5 313 } 314 315 define i32 @test13(i32 %i) { 316 ; CHECK-LABEL: @test13( 317 ; CHECK-NEXT: ret i32 0 318 ; 319 %x = srem i32 %i, %i 320 ret i32 %x 321 } 322 323 define i64 @test14(i64 %x, i32 %y) { 324 ; CHECK-LABEL: @test14( 325 ; CHECK-NEXT: [[SHL:%.*]] = shl i32 1, [[Y:%.*]] 326 ; CHECK-NEXT: [[ZEXT:%.*]] = zext i32 [[SHL]] to i64 327 ; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[ZEXT]], -1 328 ; CHECK-NEXT: [[UREM:%.*]] = and i64 [[TMP1]], [[X:%.*]] 329 ; CHECK-NEXT: ret i64 [[UREM]] 330 ; 331 %shl = shl i32 1, %y 332 %zext = zext i32 %shl to i64 333 %urem = urem i64 %x, %zext 334 ret i64 %urem 335 } 336 337 define i64 @test15(i32 %x, i32 %y) { 338 ; CHECK-LABEL: @test15( 339 ; CHECK-NEXT: [[NOTMASK:%.*]] = shl nsw i32 -1, [[Y:%.*]] 340 ; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[NOTMASK]], -1 341 ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[X:%.*]] 342 ; CHECK-NEXT: [[UREM:%.*]] = zext i32 [[TMP2]] to i64 343 ; CHECK-NEXT: ret i64 [[UREM]] 344 ; 345 %shl = shl i32 1, %y 346 %zext0 = zext i32 %shl to i64 347 %zext1 = zext i32 %x to i64 348 %urem = urem i64 %zext1, %zext0 349 ret i64 %urem 350 } 351 352 define i32 @test16(i32 %x, i32 %y) { 353 ; CHECK-LABEL: @test16( 354 ; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[Y:%.*]], 11 355 ; CHECK-NEXT: [[AND:%.*]] = and i32 [[SHR]], 4 356 ; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[AND]], 3 357 ; CHECK-NEXT: [[REM:%.*]] = and i32 [[TMP1]], [[X:%.*]] 358 ; CHECK-NEXT: ret i32 [[REM]] 359 ; 360 %shr = lshr i32 %y, 11 361 %and = and i32 %shr, 4 362 %add = add i32 %and, 4 363 %rem = urem i32 %x, %add 364 ret i32 %rem 365 } 366 367 define i32 @test17(i32 %X) { 368 ; CHECK-LABEL: @test17( 369 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i32 [[X:%.*]], 1 370 ; CHECK-NEXT: [[TMP2:%.*]] = zext i1 [[TMP1]] to i32 371 ; CHECK-NEXT: ret i32 [[TMP2]] 372 ; 373 %A = urem i32 1, %X 374 ret i32 %A 375 } 376 377 define i32 @test18(i16 %x, i32 %y) { 378 ; CHECK-LABEL: @test18( 379 ; CHECK-NEXT: [[TMP1:%.*]] = and i16 [[X:%.*]], 4 380 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i16 [[TMP1]], 0 381 ; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i32 63, i32 31 382 ; CHECK-NEXT: [[TMP4:%.*]] = and i32 [[TMP3]], [[Y:%.*]] 383 ; CHECK-NEXT: ret i32 [[TMP4]] 384 ; 385 %1 = and i16 %x, 4 386 %2 = icmp ne i16 %1, 0 387 %3 = select i1 %2, i32 32, i32 64 388 %4 = urem i32 %y, %3 389 ret i32 %4 390 } 391 392 define i32 @test19(i32 %x, i32 %y) { 393 ; CHECK-LABEL: @test19( 394 ; CHECK-NEXT: [[A:%.*]] = shl i32 1, [[X:%.*]] 395 ; CHECK-NEXT: [[B:%.*]] = shl i32 1, [[Y:%.*]] 396 ; CHECK-NEXT: [[C:%.*]] = and i32 [[A]], [[B]] 397 ; CHECK-NEXT: [[D:%.*]] = add i32 [[C]], [[A]] 398 ; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[D]], -1 399 ; CHECK-NEXT: [[E:%.*]] = and i32 [[TMP1]], [[Y]] 400 ; CHECK-NEXT: ret i32 [[E]] 401 ; 402 %A = shl i32 1, %x 403 %B = shl i32 1, %y 404 %C = and i32 %A, %B 405 %D = add i32 %C, %A 406 %E = urem i32 %y, %D 407 ret i32 %E 408 } 409 410 define i32 @test19_commutative0(i32 %x, i32 %y) { 411 ; CHECK-LABEL: @test19_commutative0( 412 ; CHECK-NEXT: [[A:%.*]] = shl i32 1, [[X:%.*]] 413 ; CHECK-NEXT: [[B:%.*]] = shl i32 1, [[Y:%.*]] 414 ; CHECK-NEXT: [[C:%.*]] = and i32 [[B]], [[A]] 415 ; CHECK-NEXT: [[D:%.*]] = add i32 [[C]], [[A]] 416 ; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[D]], -1 417 ; CHECK-NEXT: [[E:%.*]] = and i32 [[TMP1]], [[Y]] 418 ; CHECK-NEXT: ret i32 [[E]] 419 ; 420 %A = shl i32 1, %x 421 %B = shl i32 1, %y 422 %C = and i32 %B, %A ; swapped 423 %D = add i32 %C, %A 424 %E = urem i32 %y, %D 425 ret i32 %E 426 } 427 428 define i32 @test19_commutative1(i32 %x, i32 %y) { 429 ; CHECK-LABEL: @test19_commutative1( 430 ; CHECK-NEXT: [[A:%.*]] = shl i32 1, [[X:%.*]] 431 ; CHECK-NEXT: [[B:%.*]] = shl i32 1, [[Y:%.*]] 432 ; CHECK-NEXT: [[C:%.*]] = and i32 [[A]], [[B]] 433 ; CHECK-NEXT: [[D:%.*]] = add i32 [[A]], [[C]] 434 ; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[D]], -1 435 ; CHECK-NEXT: [[E:%.*]] = and i32 [[TMP1]], [[Y]] 436 ; CHECK-NEXT: ret i32 [[E]] 437 ; 438 %A = shl i32 1, %x 439 %B = shl i32 1, %y 440 %C = and i32 %A, %B 441 %D = add i32 %A, %C ; swapped 442 %E = urem i32 %y, %D 443 ret i32 %E 444 } 445 446 define i32 @test19_commutative2(i32 %x, i32 %y) { 447 ; CHECK-LABEL: @test19_commutative2( 448 ; CHECK-NEXT: [[A:%.*]] = shl i32 1, [[X:%.*]] 449 ; CHECK-NEXT: [[B:%.*]] = shl i32 1, [[Y:%.*]] 450 ; CHECK-NEXT: [[C:%.*]] = and i32 [[B]], [[A]] 451 ; CHECK-NEXT: [[D:%.*]] = add i32 [[A]], [[C]] 452 ; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[D]], -1 453 ; CHECK-NEXT: [[E:%.*]] = and i32 [[TMP1]], [[Y]] 454 ; CHECK-NEXT: ret i32 [[E]] 455 ; 456 %A = shl i32 1, %x 457 %B = shl i32 1, %y 458 %C = and i32 %B, %A ; swapped 459 %D = add i32 %A, %C ; swapped 460 %E = urem i32 %y, %D 461 ret i32 %E 462 } 463 464 define <2 x i64> @test20(<2 x i64> %X, <2 x i1> %C) { 465 ; CHECK-LABEL: @test20( 466 ; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[C:%.*]], <2 x i64> <i64 1, i64 2>, <2 x i64> zeroinitializer 467 ; CHECK-NEXT: ret <2 x i64> [[R]] 468 ; 469 %V = select <2 x i1> %C, <2 x i64> <i64 1, i64 2>, <2 x i64> <i64 8, i64 9> 470 %R = urem <2 x i64> %V, <i64 2, i64 3> 471 ret <2 x i64> %R 472 } 473 474 define i32 @test21(i1 %c0, i32* %p) { 475 ; CHECK-LABEL: @test21( 476 ; CHECK-NEXT: entry: 477 ; CHECK-NEXT: br i1 [[C0:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 478 ; CHECK: if.then: 479 ; CHECK-NEXT: [[V:%.*]] = load volatile i32, i32* [[P:%.*]], align 4 480 ; CHECK-NEXT: [[PHITMP:%.*]] = srem i32 [[V]], 5 481 ; CHECK-NEXT: br label [[IF_END]] 482 ; CHECK: if.end: 483 ; CHECK-NEXT: [[LHS:%.*]] = phi i32 [ [[PHITMP]], [[IF_THEN]] ], [ 0, [[ENTRY:%.*]] ] 484 ; CHECK-NEXT: ret i32 [[LHS]] 485 ; 486 entry: 487 br i1 %c0, label %if.then, label %if.end 488 489 if.then: 490 %v = load volatile i32, i32* %p 491 br label %if.end 492 493 if.end: 494 %lhs = phi i32 [ %v, %if.then ], [ 5, %entry ] 495 %rem = srem i32 %lhs, 5 496 ret i32 %rem 497 } 498 499 @a = common global [5 x i16] zeroinitializer, align 2 500 @b = common global i16 0, align 2 501 502 define i32 @pr27968_0(i1 %c0, i32* %p) { 503 ; CHECK-LABEL: @pr27968_0( 504 ; CHECK-NEXT: entry: 505 ; CHECK-NEXT: br i1 [[C0:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 506 ; CHECK: if.then: 507 ; CHECK-NEXT: [[V:%.*]] = load volatile i32, i32* [[P:%.*]], align 4 508 ; CHECK-NEXT: br label [[IF_END]] 509 ; CHECK: if.end: 510 ; CHECK-NEXT: br i1 icmp eq (i16* getelementptr inbounds ([5 x i16], [5 x i16]* @a, i64 0, i64 4), i16* @b), label [[REM_IS_SAFE:%.*]], label [[REM_IS_UNSAFE:%.*]] 511 ; CHECK: rem.is.safe: 512 ; CHECK-NEXT: ret i32 0 513 ; CHECK: rem.is.unsafe: 514 ; CHECK-NEXT: ret i32 0 515 ; 516 entry: 517 br i1 %c0, label %if.then, label %if.end 518 519 if.then: 520 %v = load volatile i32, i32* %p 521 br label %if.end 522 523 if.end: 524 %lhs = phi i32 [ %v, %if.then ], [ 5, %entry ] 525 br i1 icmp eq (i16* getelementptr inbounds ([5 x i16], [5 x i16]* @a, i64 0, i64 4), i16* @b), label %rem.is.safe, label %rem.is.unsafe 526 527 rem.is.safe: 528 %rem = srem i32 %lhs, zext (i1 icmp eq (i16* getelementptr inbounds ([5 x i16], [5 x i16]* @a, i64 0, i64 4), i16* @b) to i32) 529 ret i32 %rem 530 531 rem.is.unsafe: 532 ret i32 0 533 } 534 535 define i32 @pr27968_1(i1 %c0, i1 %always_false, i32* %p) { 536 ; CHECK-LABEL: @pr27968_1( 537 ; CHECK-NEXT: entry: 538 ; CHECK-NEXT: br i1 [[C0:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 539 ; CHECK: if.then: 540 ; CHECK-NEXT: [[V:%.*]] = load volatile i32, i32* [[P:%.*]], align 4 541 ; CHECK-NEXT: br label [[IF_END]] 542 ; CHECK: if.end: 543 ; CHECK-NEXT: [[LHS:%.*]] = phi i32 [ [[V]], [[IF_THEN]] ], [ 5, [[ENTRY:%.*]] ] 544 ; CHECK-NEXT: br i1 [[ALWAYS_FALSE:%.*]], label [[REM_IS_SAFE:%.*]], label [[REM_IS_UNSAFE:%.*]] 545 ; CHECK: rem.is.safe: 546 ; CHECK-NEXT: [[REM:%.*]] = srem i32 [[LHS]], -2147483648 547 ; CHECK-NEXT: ret i32 [[REM]] 548 ; CHECK: rem.is.unsafe: 549 ; CHECK-NEXT: ret i32 0 550 ; 551 entry: 552 br i1 %c0, label %if.then, label %if.end 553 554 if.then: 555 %v = load volatile i32, i32* %p 556 br label %if.end 557 558 if.end: 559 %lhs = phi i32 [ %v, %if.then ], [ 5, %entry ] 560 br i1 %always_false, label %rem.is.safe, label %rem.is.unsafe 561 562 rem.is.safe: 563 %rem = srem i32 %lhs, -2147483648 564 ret i32 %rem 565 566 rem.is.unsafe: 567 ret i32 0 568 } 569 570 define i32 @pr27968_2(i1 %c0, i32* %p) { 571 ; CHECK-LABEL: @pr27968_2( 572 ; CHECK-NEXT: entry: 573 ; CHECK-NEXT: br i1 [[C0:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 574 ; CHECK: if.then: 575 ; CHECK-NEXT: [[V:%.*]] = load volatile i32, i32* [[P:%.*]], align 4 576 ; CHECK-NEXT: br label [[IF_END]] 577 ; CHECK: if.end: 578 ; CHECK-NEXT: br i1 icmp eq (i16* getelementptr inbounds ([5 x i16], [5 x i16]* @a, i64 0, i64 4), i16* @b), label [[REM_IS_SAFE:%.*]], label [[REM_IS_UNSAFE:%.*]] 579 ; CHECK: rem.is.safe: 580 ; CHECK-NEXT: ret i32 0 581 ; CHECK: rem.is.unsafe: 582 ; CHECK-NEXT: ret i32 0 583 ; 584 entry: 585 br i1 %c0, label %if.then, label %if.end 586 587 if.then: 588 %v = load volatile i32, i32* %p 589 br label %if.end 590 591 if.end: 592 %lhs = phi i32 [ %v, %if.then ], [ 5, %entry ] 593 br i1 icmp eq (i16* getelementptr inbounds ([5 x i16], [5 x i16]* @a, i64 0, i64 4), i16* @b), label %rem.is.safe, label %rem.is.unsafe 594 595 rem.is.safe: 596 %rem = urem i32 %lhs, zext (i1 icmp eq (i16* getelementptr inbounds ([5 x i16], [5 x i16]* @a, i64 0, i64 4), i16* @b) to i32) 597 ret i32 %rem 598 599 rem.is.unsafe: 600 ret i32 0 601 } 602 603 define i32 @pr27968_3(i1 %c0, i1 %always_false, i32* %p) { 604 ; CHECK-LABEL: @pr27968_3( 605 ; CHECK-NEXT: entry: 606 ; CHECK-NEXT: br i1 [[C0:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 607 ; CHECK: if.then: 608 ; CHECK-NEXT: [[V:%.*]] = load volatile i32, i32* [[P:%.*]], align 4 609 ; CHECK-NEXT: [[PHITMP:%.*]] = and i32 [[V]], 2147483647 610 ; CHECK-NEXT: br label [[IF_END]] 611 ; CHECK: if.end: 612 ; CHECK-NEXT: [[LHS:%.*]] = phi i32 [ [[PHITMP]], [[IF_THEN]] ], [ 5, [[ENTRY:%.*]] ] 613 ; CHECK-NEXT: br i1 [[ALWAYS_FALSE:%.*]], label [[REM_IS_SAFE:%.*]], label [[REM_IS_UNSAFE:%.*]] 614 ; CHECK: rem.is.safe: 615 ; CHECK-NEXT: ret i32 [[LHS]] 616 ; CHECK: rem.is.unsafe: 617 ; CHECK-NEXT: ret i32 0 618 ; 619 entry: 620 br i1 %c0, label %if.then, label %if.end 621 622 if.then: 623 %v = load volatile i32, i32* %p 624 br label %if.end 625 626 if.end: 627 %lhs = phi i32 [ %v, %if.then ], [ 5, %entry ] 628 br i1 %always_false, label %rem.is.safe, label %rem.is.unsafe 629 630 rem.is.safe: 631 %rem = urem i32 %lhs, -2147483648 632 ret i32 %rem 633 634 rem.is.unsafe: 635 ret i32 0 636 } 637 638 define i32 @test22(i32 %A) { 639 ; CHECK-LABEL: @test22( 640 ; CHECK-NEXT: [[AND:%.*]] = and i32 [[A:%.*]], 2147483647 641 ; CHECK-NEXT: [[MUL:%.*]] = urem i32 [[AND]], 2147483647 642 ; CHECK-NEXT: ret i32 [[MUL]] 643 ; 644 %and = and i32 %A, 2147483647 645 %mul = srem i32 %and, 2147483647 646 ret i32 %mul 647 } 648 649 define <2 x i32> @test23(<2 x i32> %A) { 650 ; CHECK-LABEL: @test23( 651 ; CHECK-NEXT: [[AND:%.*]] = and <2 x i32> [[A:%.*]], <i32 2147483647, i32 2147483647> 652 ; CHECK-NEXT: [[MUL:%.*]] = urem <2 x i32> [[AND]], <i32 2147483647, i32 2147483647> 653 ; CHECK-NEXT: ret <2 x i32> [[MUL]] 654 ; 655 %and = and <2 x i32> %A, <i32 2147483647, i32 2147483647> 656 %mul = srem <2 x i32> %and, <i32 2147483647, i32 2147483647> 657 ret <2 x i32> %mul 658 } 659 660 ; FP division-by-zero is not UB. 661 662 define double @PR34870(i1 %cond, double %x, double %y) { 663 ; CHECK-LABEL: @PR34870( 664 ; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], double [[Y:%.*]], double 0.000000e+00 665 ; CHECK-NEXT: [[FMOD:%.*]] = frem double [[X:%.*]], [[SEL]] 666 ; CHECK-NEXT: ret double [[FMOD]] 667 ; 668 %sel = select i1 %cond, double %y, double 0.0 669 %fmod = frem double %x, %sel 670 ret double %fmod 671 } 672 673