1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4define i32 @sdiv1(i32 %x) { 5; CHECK-LABEL: @sdiv1( 6; CHECK-NEXT: [[Y:%.*]] = sdiv i32 [[X:%.*]], 8 7; CHECK-NEXT: ret i32 [[Y]] 8; 9 %y = sdiv i32 %x, 8 10 ret i32 %y 11} 12 13define i32 @sdiv2(i32 %x) { 14; CHECK-LABEL: @sdiv2( 15; CHECK-NEXT: [[Y:%.*]] = ashr exact i32 [[X:%.*]], 3 16; CHECK-NEXT: ret i32 [[Y]] 17; 18 %y = sdiv exact i32 %x, 8 19 ret i32 %y 20} 21 22define <2 x i32> @sdiv2_vec(<2 x i32> %x) { 23; CHECK-LABEL: @sdiv2_vec( 24; CHECK-NEXT: [[Y:%.*]] = ashr exact <2 x i32> [[X:%.*]], splat (i32 7) 25; CHECK-NEXT: ret <2 x i32> [[Y]] 26; 27 %y = sdiv exact <2 x i32> %x, <i32 128, i32 128> 28 ret <2 x i32> %y 29} 30 31define i32 @sdiv3(i32 %x) { 32; CHECK-LABEL: @sdiv3( 33; CHECK-NEXT: [[X_FR:%.*]] = freeze i32 [[X:%.*]] 34; CHECK-NEXT: [[TMP1:%.*]] = srem i32 [[X_FR]], 3 35; CHECK-NEXT: [[Z:%.*]] = sub nsw i32 [[X_FR]], [[TMP1]] 36; CHECK-NEXT: ret i32 [[Z]] 37; 38 %y = sdiv i32 %x, 3 39 %z = mul i32 %y, 3 40 ret i32 %z 41} 42 43define i32 @sdiv4(i32 %x) { 44; CHECK-LABEL: @sdiv4( 45; CHECK-NEXT: ret i32 [[X:%.*]] 46; 47 %y = sdiv exact i32 %x, 3 48 %z = mul i32 %y, 3 49 ret i32 %z 50} 51 52define i32 @sdiv5(i32 %x) { 53; CHECK-LABEL: @sdiv5( 54; CHECK-NEXT: [[X_FR:%.*]] = freeze i32 [[X:%.*]] 55; CHECK-NEXT: [[TMP1:%.*]] = srem i32 [[X_FR]], 3 56; CHECK-NEXT: [[Z:%.*]] = sub i32 [[TMP1]], [[X_FR]] 57; CHECK-NEXT: ret i32 [[Z]] 58; 59 %y = sdiv i32 %x, 3 60 %z = mul i32 %y, -3 61 ret i32 %z 62} 63 64define i32 @sdiv6(i32 %x) { 65; CHECK-LABEL: @sdiv6( 66; CHECK-NEXT: [[Z:%.*]] = sub i32 0, [[X:%.*]] 67; CHECK-NEXT: ret i32 [[Z]] 68; 69 %y = sdiv exact i32 %x, 3 70 %z = mul i32 %y, -3 71 ret i32 %z 72} 73 74define i32 @udiv1(i32 %x, i32 %w) { 75; CHECK-LABEL: @udiv1( 76; CHECK-NEXT: ret i32 [[X:%.*]] 77; 78 %y = udiv exact i32 %x, %w 79 %z = mul i32 %y, %w 80 ret i32 %z 81} 82 83define i32 @udiv2(i32 %x, i32 %w) { 84; CHECK-LABEL: @udiv2( 85; CHECK-NEXT: [[Z1:%.*]] = lshr exact i32 [[X:%.*]], [[W:%.*]] 86; CHECK-NEXT: ret i32 [[Z1]] 87; 88 %y = shl i32 1, %w 89 %z = udiv exact i32 %x, %y 90 ret i32 %z 91} 92 93define i64 @ashr1(i64 %X) { 94; CHECK-LABEL: @ashr1( 95; CHECK-NEXT: [[A:%.*]] = shl i64 [[X:%.*]], 8 96; CHECK-NEXT: [[B:%.*]] = ashr exact i64 [[A]], 2 97; CHECK-NEXT: ret i64 [[B]] 98; 99 %A = shl i64 %X, 8 100 %B = ashr i64 %A, 2 101 ret i64 %B 102} 103 104; The vector ashr should be exact (like it is in the preceding test). 105 106define <2 x i64> @ashr1_vec(<2 x i64> %X) { 107; CHECK-LABEL: @ashr1_vec( 108; CHECK-NEXT: [[A:%.*]] = shl <2 x i64> [[X:%.*]], splat (i64 8) 109; CHECK-NEXT: [[B:%.*]] = ashr exact <2 x i64> [[A]], splat (i64 2) 110; CHECK-NEXT: ret <2 x i64> [[B]] 111; 112 %A = shl <2 x i64> %X, <i64 8, i64 8> 113 %B = ashr <2 x i64> %A, <i64 2, i64 2> 114 ret <2 x i64> %B 115} 116 117; PR9120 118define i1 @ashr_icmp1(i64 %X) { 119; CHECK-LABEL: @ashr_icmp1( 120; CHECK-NEXT: [[B:%.*]] = icmp eq i64 [[X:%.*]], 0 121; CHECK-NEXT: ret i1 [[B]] 122; 123 %A = ashr exact i64 %X, 2 ; X/4 124 %B = icmp eq i64 %A, 0 125 ret i1 %B 126} 127 128define i1 @ashr_icmp2(i64 %X) { 129; CHECK-LABEL: @ashr_icmp2( 130; CHECK-NEXT: [[Z:%.*]] = icmp slt i64 [[X:%.*]], 16 131; CHECK-NEXT: ret i1 [[Z]] 132; 133 %Y = ashr exact i64 %X, 2 ; x / 4 134 %Z = icmp slt i64 %Y, 4 ; x < 16 135 ret i1 %Z 136} 137 138define <2 x i1> @ashr_icmp2_vec(<2 x i64> %X) { 139; CHECK-LABEL: @ashr_icmp2_vec( 140; CHECK-NEXT: [[Z:%.*]] = icmp slt <2 x i64> [[X:%.*]], splat (i64 16) 141; CHECK-NEXT: ret <2 x i1> [[Z]] 142; 143 %Y = ashr exact <2 x i64> %X, <i64 2, i64 2> 144 %Z = icmp slt <2 x i64> %Y, <i64 4, i64 4> 145 ret <2 x i1> %Z 146} 147 148; PR9998 149; Make sure we don't transform the ashr here into an sdiv 150define i1 @pr9998(i32 %V) { 151; CHECK-LABEL: @pr9998( 152; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[V:%.*]], 1 153; CHECK-NEXT: [[Z:%.*]] = icmp ne i32 [[TMP1]], 0 154; CHECK-NEXT: ret i1 [[Z]] 155; 156 %W = shl i32 %V, 31 157 %X = ashr exact i32 %W, 31 158 %Y = sext i32 %X to i64 159 %Z = icmp ugt i64 %Y, 7297771788697658747 160 ret i1 %Z 161} 162 163; FIXME: Vectors should fold the same way. 164define <2 x i1> @pr9998vec(<2 x i32> %V) { 165; CHECK-LABEL: @pr9998vec( 166; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[V:%.*]], splat (i32 1) 167; CHECK-NEXT: [[X:%.*]] = sub nsw <2 x i32> zeroinitializer, [[TMP1]] 168; CHECK-NEXT: [[Y:%.*]] = sext <2 x i32> [[X]] to <2 x i64> 169; CHECK-NEXT: [[Z:%.*]] = icmp ugt <2 x i64> [[Y]], splat (i64 7297771788697658747) 170; CHECK-NEXT: ret <2 x i1> [[Z]] 171; 172 %W = shl <2 x i32> %V, <i32 31, i32 31> 173 %X = ashr exact <2 x i32> %W, <i32 31, i32 31> 174 %Y = sext <2 x i32> %X to <2 x i64> 175 %Z = icmp ugt <2 x i64> %Y, <i64 7297771788697658747, i64 7297771788697658747> 176 ret <2 x i1> %Z 177} 178 179define i1 @udiv_icmp1(i64 %X) { 180; CHECK-LABEL: @udiv_icmp1( 181; CHECK-NEXT: [[B:%.*]] = icmp ne i64 [[X:%.*]], 0 182; CHECK-NEXT: ret i1 [[B]] 183; 184 %A = udiv exact i64 %X, 5 ; X/5 185 %B = icmp ne i64 %A, 0 186 ret i1 %B 187} 188 189define <2 x i1> @udiv_icmp1_vec(<2 x i64> %X) { 190; CHECK-LABEL: @udiv_icmp1_vec( 191; CHECK-NEXT: [[B:%.*]] = icmp ne <2 x i64> [[X:%.*]], zeroinitializer 192; CHECK-NEXT: ret <2 x i1> [[B]] 193; 194 %A = udiv exact <2 x i64> %X, <i64 5, i64 5> 195 %B = icmp ne <2 x i64> %A, zeroinitializer 196 ret <2 x i1> %B 197} 198 199define i1 @udiv_icmp2(i64 %X) { 200; CHECK-LABEL: @udiv_icmp2( 201; CHECK-NEXT: [[B:%.*]] = icmp eq i64 [[X:%.*]], 0 202; CHECK-NEXT: ret i1 [[B]] 203; 204 %A = udiv exact i64 %X, 5 ; X/5 == 0 --> x == 0 205 %B = icmp eq i64 %A, 0 206 ret i1 %B 207} 208 209define <2 x i1> @udiv_icmp2_vec(<2 x i64> %X) { 210; CHECK-LABEL: @udiv_icmp2_vec( 211; CHECK-NEXT: [[B:%.*]] = icmp eq <2 x i64> [[X:%.*]], zeroinitializer 212; CHECK-NEXT: ret <2 x i1> [[B]] 213; 214 %A = udiv exact <2 x i64> %X, <i64 5, i64 5> 215 %B = icmp eq <2 x i64> %A, zeroinitializer 216 ret <2 x i1> %B 217} 218 219define i1 @sdiv_icmp1(i64 %X) { 220; CHECK-LABEL: @sdiv_icmp1( 221; CHECK-NEXT: [[B:%.*]] = icmp eq i64 [[X:%.*]], 0 222; CHECK-NEXT: ret i1 [[B]] 223; 224 %A = sdiv exact i64 %X, 5 ; X/5 == 0 --> x == 0 225 %B = icmp eq i64 %A, 0 226 ret i1 %B 227} 228 229define <2 x i1> @sdiv_icmp1_vec(<2 x i64> %X) { 230; CHECK-LABEL: @sdiv_icmp1_vec( 231; CHECK-NEXT: [[B:%.*]] = icmp eq <2 x i64> [[X:%.*]], zeroinitializer 232; CHECK-NEXT: ret <2 x i1> [[B]] 233; 234 %A = sdiv exact <2 x i64> %X, <i64 5, i64 5> 235 %B = icmp eq <2 x i64> %A, zeroinitializer 236 ret <2 x i1> %B 237} 238 239define i1 @sdiv_icmp2(i64 %X) { 240; CHECK-LABEL: @sdiv_icmp2( 241; CHECK-NEXT: [[B:%.*]] = icmp eq i64 [[X:%.*]], 5 242; CHECK-NEXT: ret i1 [[B]] 243; 244 %A = sdiv exact i64 %X, 5 ; X/5 == 1 --> x == 5 245 %B = icmp eq i64 %A, 1 246 ret i1 %B 247} 248 249define <2 x i1> @sdiv_icmp2_vec(<2 x i64> %X) { 250; CHECK-LABEL: @sdiv_icmp2_vec( 251; CHECK-NEXT: [[B:%.*]] = icmp eq <2 x i64> [[X:%.*]], splat (i64 5) 252; CHECK-NEXT: ret <2 x i1> [[B]] 253; 254 %A = sdiv exact <2 x i64> %X, <i64 5, i64 5> 255 %B = icmp eq <2 x i64> %A, <i64 1, i64 1> 256 ret <2 x i1> %B 257} 258 259define i1 @sdiv_icmp3(i64 %X) { 260; CHECK-LABEL: @sdiv_icmp3( 261; CHECK-NEXT: [[B:%.*]] = icmp eq i64 [[X:%.*]], -5 262; CHECK-NEXT: ret i1 [[B]] 263; 264 %A = sdiv exact i64 %X, 5 ; X/5 == -1 --> x == -5 265 %B = icmp eq i64 %A, -1 266 ret i1 %B 267} 268 269define <2 x i1> @sdiv_icmp3_vec(<2 x i64> %X) { 270; CHECK-LABEL: @sdiv_icmp3_vec( 271; CHECK-NEXT: [[B:%.*]] = icmp eq <2 x i64> [[X:%.*]], splat (i64 -5) 272; CHECK-NEXT: ret <2 x i1> [[B]] 273; 274 %A = sdiv exact <2 x i64> %X, <i64 5, i64 5> 275 %B = icmp eq <2 x i64> %A, <i64 -1, i64 -1> 276 ret <2 x i1> %B 277} 278 279define i1 @sdiv_icmp4(i64 %X) { 280; CHECK-LABEL: @sdiv_icmp4( 281; CHECK-NEXT: [[B:%.*]] = icmp eq i64 [[X:%.*]], 0 282; CHECK-NEXT: ret i1 [[B]] 283; 284 %A = sdiv exact i64 %X, -5 ; X/-5 == 0 --> x == 0 285 %B = icmp eq i64 %A, 0 286 ret i1 %B 287} 288 289define <2 x i1> @sdiv_icmp4_vec(<2 x i64> %X) { 290; CHECK-LABEL: @sdiv_icmp4_vec( 291; CHECK-NEXT: [[B:%.*]] = icmp eq <2 x i64> [[X:%.*]], zeroinitializer 292; CHECK-NEXT: ret <2 x i1> [[B]] 293; 294 %A = sdiv exact <2 x i64> %X, <i64 -5, i64 -5> 295 %B = icmp eq <2 x i64> %A, zeroinitializer 296 ret <2 x i1> %B 297} 298 299define i1 @sdiv_icmp5(i64 %X) { 300; CHECK-LABEL: @sdiv_icmp5( 301; CHECK-NEXT: [[B:%.*]] = icmp eq i64 [[X:%.*]], -5 302; CHECK-NEXT: ret i1 [[B]] 303; 304 %A = sdiv exact i64 %X, -5 ; X/-5 == 1 --> x == -5 305 %B = icmp eq i64 %A, 1 306 ret i1 %B 307} 308 309define <2 x i1> @sdiv_icmp5_vec(<2 x i64> %X) { 310; CHECK-LABEL: @sdiv_icmp5_vec( 311; CHECK-NEXT: [[B:%.*]] = icmp eq <2 x i64> [[X:%.*]], splat (i64 -5) 312; CHECK-NEXT: ret <2 x i1> [[B]] 313; 314 %A = sdiv exact <2 x i64> %X, <i64 -5, i64 -5> 315 %B = icmp eq <2 x i64> %A, <i64 1, i64 1> 316 ret <2 x i1> %B 317} 318 319define i1 @sdiv_icmp6(i64 %X) { 320; CHECK-LABEL: @sdiv_icmp6( 321; CHECK-NEXT: [[B:%.*]] = icmp eq i64 [[X:%.*]], 5 322; CHECK-NEXT: ret i1 [[B]] 323; 324 %A = sdiv exact i64 %X, -5 ; X/-5 == -1 --> x == 5 325 %B = icmp eq i64 %A, -1 326 ret i1 %B 327} 328 329define <2 x i1> @sdiv_icmp6_vec(<2 x i64> %X) { 330; CHECK-LABEL: @sdiv_icmp6_vec( 331; CHECK-NEXT: [[B:%.*]] = icmp eq <2 x i64> [[X:%.*]], splat (i64 5) 332; CHECK-NEXT: ret <2 x i1> [[B]] 333; 334 %A = sdiv exact <2 x i64> %X, <i64 -5, i64 -5> 335 %B = icmp eq <2 x i64> %A, <i64 -1, i64 -1> 336 ret <2 x i1> %B 337} 338 339define i8 @mul_of_udiv(i8 %x) { 340; CHECK-LABEL: @mul_of_udiv( 341; CHECK-NEXT: [[MUL1:%.*]] = lshr exact i8 [[X:%.*]], 1 342; CHECK-NEXT: ret i8 [[MUL1]] 343; 344 %div = udiv exact i8 %x, 12 345 %mul = mul i8 %div, 6 346 ret i8 %mul 347} 348 349define i8 @mul_of_sdiv(i8 %x) { 350; CHECK-LABEL: @mul_of_sdiv( 351; CHECK-NEXT: [[MUL_NEG:%.*]] = ashr exact i8 [[X:%.*]], 1 352; CHECK-NEXT: [[MUL:%.*]] = sub nsw i8 0, [[MUL_NEG]] 353; CHECK-NEXT: ret i8 [[MUL]] 354; 355 %div = sdiv exact i8 %x, 12 356 %mul = mul i8 %div, -6 357 ret i8 %mul 358} 359 360define <2 x i8> @mul_of_sdiv_non_splat(<2 x i8> %x) { 361; CHECK-LABEL: @mul_of_sdiv_non_splat( 362; CHECK-NEXT: [[MUL:%.*]] = sdiv exact <2 x i8> [[X:%.*]], <i8 1, i8 -2> 363; CHECK-NEXT: ret <2 x i8> [[MUL]] 364; 365 %div = sdiv exact <2 x i8> %x, <i8 6, i8 -12> 366 %mul = mul <2 x i8> %div, <i8 6, i8 6> 367 ret <2 x i8> %mul 368} 369 370define i8 @mul_of_sdiv_fail_missing_exact(i8 %x) { 371; CHECK-LABEL: @mul_of_sdiv_fail_missing_exact( 372; CHECK-NEXT: [[DIV:%.*]] = sdiv i8 [[X:%.*]], 12 373; CHECK-NEXT: [[MUL:%.*]] = mul i8 [[DIV]], -6 374; CHECK-NEXT: ret i8 [[MUL]] 375; 376 %div = sdiv i8 %x, 12 377 %mul = mul i8 %div, -6 378 ret i8 %mul 379} 380 381define i8 @mul_of_udiv_fail_bad_remainder(i8 %x) { 382; CHECK-LABEL: @mul_of_udiv_fail_bad_remainder( 383; CHECK-NEXT: [[DIV:%.*]] = udiv exact i8 [[X:%.*]], 11 384; CHECK-NEXT: [[MUL:%.*]] = mul nuw i8 [[DIV]], 6 385; CHECK-NEXT: ret i8 [[MUL]] 386; 387 %div = udiv exact i8 %x, 11 388 %mul = mul i8 %div, 6 389 ret i8 %mul 390} 391 392define i8 @mul_of_sdiv_fail_ub(i8 %x) { 393; CHECK-LABEL: @mul_of_sdiv_fail_ub( 394; CHECK-NEXT: [[MUL:%.*]] = sub i8 0, [[X:%.*]] 395; CHECK-NEXT: ret i8 [[MUL]] 396; 397 %div = sdiv exact i8 %x, 6 398 %mul = mul i8 %div, -6 399 ret i8 %mul 400} 401 402define <2 x i8> @mul_of_sdiv_fail_ub_non_splat(<2 x i8> %x) { 403; CHECK-LABEL: @mul_of_sdiv_fail_ub_non_splat( 404; CHECK-NEXT: [[DIV:%.*]] = sdiv exact <2 x i8> [[X:%.*]], <i8 -6, i8 -12> 405; CHECK-NEXT: [[MUL:%.*]] = mul <2 x i8> [[DIV]], splat (i8 6) 406; CHECK-NEXT: ret <2 x i8> [[MUL]] 407; 408 %div = sdiv exact <2 x i8> %x, <i8 -6, i8 -12> 409 %mul = mul <2 x i8> %div, <i8 6, i8 6> 410 ret <2 x i8> %mul 411} 412