1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -instcombine -S | FileCheck %s 3target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" 4 5; Instcombine should be able to eliminate all of these ext casts. 6 7declare void @use(i32) 8 9define i64 @test1(i64 %a) { 10; CHECK-LABEL: @test1( 11; CHECK-NEXT: [[B:%.*]] = trunc i64 %a to i32 12; CHECK-NEXT: [[C:%.*]] = and i64 %a, 15 13; CHECK-NEXT: call void @use(i32 [[B]]) 14; CHECK-NEXT: ret i64 [[C]] 15; 16 %b = trunc i64 %a to i32 17 %c = and i32 %b, 15 18 %d = zext i32 %c to i64 19 call void @use(i32 %b) 20 ret i64 %d 21} 22 23define i64 @test2(i64 %a) { 24; CHECK-LABEL: @test2( 25; CHECK-NEXT: [[B:%.*]] = trunc i64 %a to i32 26; CHECK-NEXT: [[D1:%.*]] = shl i64 %a, 36 27; CHECK-NEXT: [[D:%.*]] = ashr exact i64 [[D:%.*]]1, 36 28; CHECK-NEXT: call void @use(i32 [[B]]) 29; CHECK-NEXT: ret i64 [[D]] 30; 31 %b = trunc i64 %a to i32 32 %c = shl i32 %b, 4 33 %q = ashr i32 %c, 4 34 %d = sext i32 %q to i64 35 call void @use(i32 %b) 36 ret i64 %d 37} 38 39define i64 @test3(i64 %a) { 40; CHECK-LABEL: @test3( 41; CHECK-NEXT: [[B:%.*]] = trunc i64 %a to i32 42; CHECK-NEXT: [[C:%.*]] = and i64 %a, 8 43; CHECK-NEXT: call void @use(i32 [[B]]) 44; CHECK-NEXT: ret i64 [[C]] 45; 46 %b = trunc i64 %a to i32 47 %c = and i32 %b, 8 48 %d = zext i32 %c to i64 49 call void @use(i32 %b) 50 ret i64 %d 51} 52 53define i64 @test4(i64 %a) { 54; CHECK-LABEL: @test4( 55; CHECK-NEXT: [[B:%.*]] = trunc i64 %a to i32 56; CHECK-NEXT: [[C:%.*]] = and i64 %a, 8 57; CHECK-NEXT: [[X:%.*]] = xor i64 [[C]], 8 58; CHECK-NEXT: call void @use(i32 [[B]]) 59; CHECK-NEXT: ret i64 [[X]] 60; 61 %b = trunc i64 %a to i32 62 %c = and i32 %b, 8 63 %x = xor i32 %c, 8 64 %d = zext i32 %x to i64 65 call void @use(i32 %b) 66 ret i64 %d 67} 68 69define i32 @test5(i32 %A) { 70; CHECK-LABEL: @test5( 71; CHECK-NEXT: [[C:%.*]] = lshr i32 %A, 16 72; CHECK-NEXT: ret i32 [[C]] 73; 74 %B = zext i32 %A to i128 75 %C = lshr i128 %B, 16 76 %D = trunc i128 %C to i32 77 ret i32 %D 78} 79 80define i32 @test6(i64 %A) { 81; CHECK-LABEL: @test6( 82; CHECK-NEXT: [[C:%.*]] = lshr i64 %A, 32 83; CHECK-NEXT: [[D:%.*]] = trunc i64 [[C]] to i32 84; CHECK-NEXT: ret i32 [[D]] 85; 86 %B = zext i64 %A to i128 87 %C = lshr i128 %B, 32 88 %D = trunc i128 %C to i32 89 ret i32 %D 90} 91 92define i92 @test7(i64 %A) { 93; CHECK-LABEL: @test7( 94; CHECK-NEXT: [[B:%.*]] = zext i64 %A to i92 95; CHECK-NEXT: [[C:%.*]] = lshr i92 [[B]], 32 96; CHECK-NEXT: ret i92 [[C]] 97; 98 %B = zext i64 %A to i128 99 %C = lshr i128 %B, 32 100 %D = trunc i128 %C to i92 101 ret i92 %D 102} 103 104define i64 @test8(i32 %A, i32 %B) { 105; CHECK-LABEL: @test8( 106; CHECK-NEXT: [[TMP38:%.*]] = zext i32 %A to i64 107; CHECK-NEXT: [[TMP32:%.*]] = zext i32 %B to i64 108; CHECK-NEXT: [[TMP33:%.*]] = shl nuw i64 [[TMP32]], 32 109; CHECK-NEXT: [[INS35:%.*]] = or i64 [[TMP33]], [[TMP38]] 110; CHECK-NEXT: ret i64 [[INS35]] 111; 112 %tmp38 = zext i32 %A to i128 113 %tmp32 = zext i32 %B to i128 114 %tmp33 = shl i128 %tmp32, 32 115 %ins35 = or i128 %tmp33, %tmp38 116 %tmp42 = trunc i128 %ins35 to i64 117 ret i64 %tmp42 118} 119 120define i8 @test9(i32 %X) { 121; CHECK-LABEL: @test9( 122; CHECK-NEXT: [[X_TR:%.*]] = trunc i32 %X to i8 123; CHECK-NEXT: [[Z:%.*]] = and i8 [[X_TR]], 42 124; CHECK-NEXT: ret i8 [[Z]] 125; 126 %Y = and i32 %X, 42 127 %Z = trunc i32 %Y to i8 128 ret i8 %Z 129} 130 131; rdar://8808586 132define i8 @test10(i32 %X) { 133; CHECK-LABEL: @test10( 134; CHECK-NEXT: [[Y:%.*]] = trunc i32 %X to i8 135; CHECK-NEXT: [[Z:%.*]] = and i8 [[Y]], 42 136; CHECK-NEXT: ret i8 [[Z]] 137; 138 %Y = trunc i32 %X to i8 139 %Z = and i8 %Y, 42 140 ret i8 %Z 141} 142 143; PR25543 144; https://llvm.org/bugs/show_bug.cgi?id=25543 145; This is an extractelement. 146 147define i32 @trunc_bitcast1(<4 x i32> %v) { 148; CHECK-LABEL: @trunc_bitcast1( 149; CHECK-NEXT: [[EXT:%.*]] = extractelement <4 x i32> %v, i32 1 150; CHECK-NEXT: ret i32 [[EXT]] 151; 152 %bc = bitcast <4 x i32> %v to i128 153 %shr = lshr i128 %bc, 32 154 %ext = trunc i128 %shr to i32 155 ret i32 %ext 156} 157 158; A bitcast may still be required. 159 160define i32 @trunc_bitcast2(<2 x i64> %v) { 161; CHECK-LABEL: @trunc_bitcast2( 162; CHECK-NEXT: [[BC1:%.*]] = bitcast <2 x i64> %v to <4 x i32> 163; CHECK-NEXT: [[EXT:%.*]] = extractelement <4 x i32> [[BC1]], i32 2 164; CHECK-NEXT: ret i32 [[EXT]] 165; 166 %bc = bitcast <2 x i64> %v to i128 167 %shr = lshr i128 %bc, 64 168 %ext = trunc i128 %shr to i32 169 ret i32 %ext 170} 171 172; The right shift is optional. 173 174define i32 @trunc_bitcast3(<4 x i32> %v) { 175; CHECK-LABEL: @trunc_bitcast3( 176; CHECK-NEXT: [[EXT:%.*]] = extractelement <4 x i32> %v, i32 0 177; CHECK-NEXT: ret i32 [[EXT]] 178; 179 %bc = bitcast <4 x i32> %v to i128 180 %ext = trunc i128 %bc to i32 181 ret i32 %ext 182} 183 184define i32 @trunc_shl_31_i32_i64(i64 %val) { 185; CHECK-LABEL: @trunc_shl_31_i32_i64( 186; CHECK-NEXT: [[VAL_TR:%.*]] = trunc i64 %val to i32 187; CHECK-NEXT: [[TRUNC:%.*]] = shl i32 [[VAL_TR]], 31 188; CHECK-NEXT: ret i32 [[TRUNC]] 189; 190 %shl = shl i64 %val, 31 191 %trunc = trunc i64 %shl to i32 192 ret i32 %trunc 193} 194 195define i32 @trunc_shl_nsw_31_i32_i64(i64 %val) { 196; CHECK-LABEL: @trunc_shl_nsw_31_i32_i64( 197; CHECK-NEXT: [[VAL_TR:%.*]] = trunc i64 %val to i32 198; CHECK-NEXT: [[TRUNC:%.*]] = shl i32 [[VAL_TR]], 31 199; CHECK-NEXT: ret i32 [[TRUNC]] 200; 201 %shl = shl nsw i64 %val, 31 202 %trunc = trunc i64 %shl to i32 203 ret i32 %trunc 204} 205 206define i32 @trunc_shl_nuw_31_i32_i64(i64 %val) { 207; CHECK-LABEL: @trunc_shl_nuw_31_i32_i64( 208; CHECK-NEXT: [[VAL_TR:%.*]] = trunc i64 %val to i32 209; CHECK-NEXT: [[TRUNC:%.*]] = shl i32 [[VAL_TR]], 31 210; CHECK-NEXT: ret i32 [[TRUNC]] 211; 212 %shl = shl nuw i64 %val, 31 213 %trunc = trunc i64 %shl to i32 214 ret i32 %trunc 215} 216 217define i32 @trunc_shl_nsw_nuw_31_i32_i64(i64 %val) { 218; CHECK-LABEL: @trunc_shl_nsw_nuw_31_i32_i64( 219; CHECK-NEXT: [[VAL_TR:%.*]] = trunc i64 %val to i32 220; CHECK-NEXT: [[TRUNC:%.*]] = shl i32 [[VAL_TR]], 31 221; CHECK-NEXT: ret i32 [[TRUNC]] 222; 223 %shl = shl nsw nuw i64 %val, 31 224 %trunc = trunc i64 %shl to i32 225 ret i32 %trunc 226} 227 228define i16 @trunc_shl_15_i16_i64(i64 %val) { 229; CHECK-LABEL: @trunc_shl_15_i16_i64( 230; CHECK-NEXT: [[VAL_TR:%.*]] = trunc i64 %val to i16 231; CHECK-NEXT: [[TRUNC:%.*]] = shl i16 [[VAL_TR]], 15 232; CHECK-NEXT: ret i16 [[TRUNC]] 233; 234 %shl = shl i64 %val, 15 235 %trunc = trunc i64 %shl to i16 236 ret i16 %trunc 237} 238 239define i16 @trunc_shl_15_i16_i32(i32 %val) { 240; CHECK-LABEL: @trunc_shl_15_i16_i32( 241; CHECK-NEXT: [[VAL_TR:%.*]] = trunc i32 %val to i16 242; CHECK-NEXT: [[TRUNC:%.*]] = shl i16 [[VAL_TR]], 15 243; CHECK-NEXT: ret i16 [[TRUNC]] 244; 245 %shl = shl i32 %val, 15 246 %trunc = trunc i32 %shl to i16 247 ret i16 %trunc 248} 249 250define i8 @trunc_shl_7_i8_i64(i64 %val) { 251; CHECK-LABEL: @trunc_shl_7_i8_i64( 252; CHECK-NEXT: [[VAL_TR:%.*]] = trunc i64 %val to i8 253; CHECK-NEXT: [[TRUNC:%.*]] = shl i8 [[VAL_TR]], 7 254; CHECK-NEXT: ret i8 [[TRUNC]] 255; 256 %shl = shl i64 %val, 7 257 %trunc = trunc i64 %shl to i8 258 ret i8 %trunc 259} 260 261define i2 @trunc_shl_1_i2_i64(i64 %val) { 262; CHECK-LABEL: @trunc_shl_1_i2_i64( 263; CHECK-NEXT: [[SHL:%.*]] = shl i64 %val, 1 264; CHECK-NEXT: [[TRUNC:%.*]] = trunc i64 [[SHL]] to i2 265; CHECK-NEXT: ret i2 [[TRUNC]] 266; 267 %shl = shl i64 %val, 1 268 %trunc = trunc i64 %shl to i2 269 ret i2 %trunc 270} 271 272define i32 @trunc_shl_1_i32_i64(i64 %val) { 273; CHECK-LABEL: @trunc_shl_1_i32_i64( 274; CHECK-NEXT: [[VAL_TR:%.*]] = trunc i64 %val to i32 275; CHECK-NEXT: [[TRUNC:%.*]] = shl i32 [[VAL_TR]], 1 276; CHECK-NEXT: ret i32 [[TRUNC]] 277; 278 %shl = shl i64 %val, 1 279 %trunc = trunc i64 %shl to i32 280 ret i32 %trunc 281} 282 283define i32 @trunc_shl_16_i32_i64(i64 %val) { 284; CHECK-LABEL: @trunc_shl_16_i32_i64( 285; CHECK-NEXT: [[VAL_TR:%.*]] = trunc i64 %val to i32 286; CHECK-NEXT: [[TRUNC:%.*]] = shl i32 [[VAL_TR]], 16 287; CHECK-NEXT: ret i32 [[TRUNC]] 288; 289 %shl = shl i64 %val, 16 290 %trunc = trunc i64 %shl to i32 291 ret i32 %trunc 292} 293 294define i32 @trunc_shl_33_i32_i64(i64 %val) { 295; CHECK-LABEL: @trunc_shl_33_i32_i64( 296; CHECK-NEXT: ret i32 0 297; 298 %shl = shl i64 %val, 33 299 %trunc = trunc i64 %shl to i32 300 ret i32 %trunc 301} 302 303define i32 @trunc_shl_32_i32_i64(i64 %val) { 304; CHECK-LABEL: @trunc_shl_32_i32_i64( 305; CHECK-NEXT: ret i32 0 306; 307 %shl = shl i64 %val, 32 308 %trunc = trunc i64 %shl to i32 309 ret i32 %trunc 310} 311 312; TODO: Should be able to handle vectors 313define <2 x i32> @trunc_shl_16_v2i32_v2i64(<2 x i64> %val) { 314; CHECK-LABEL: @trunc_shl_16_v2i32_v2i64( 315; CHECK-NEXT: [[SHL:%.*]] = shl <2 x i64> %val, <i64 16, i64 16> 316; CHECK-NEXT: [[TRUNC:%.*]] = trunc <2 x i64> [[SHL]] to <2 x i32> 317; CHECK-NEXT: ret <2 x i32> [[TRUNC]] 318; 319 %shl = shl <2 x i64> %val, <i64 16, i64 16> 320 %trunc = trunc <2 x i64> %shl to <2 x i32> 321 ret <2 x i32> %trunc 322} 323 324define <2 x i32> @trunc_shl_nosplat_v2i32_v2i64(<2 x i64> %val) { 325; CHECK-LABEL: @trunc_shl_nosplat_v2i32_v2i64( 326; CHECK-NEXT: [[SHL:%.*]] = shl <2 x i64> %val, <i64 15, i64 16> 327; CHECK-NEXT: [[TRUNC:%.*]] = trunc <2 x i64> [[SHL]] to <2 x i32> 328; CHECK-NEXT: ret <2 x i32> [[TRUNC]] 329; 330 %shl = shl <2 x i64> %val, <i64 15, i64 16> 331 %trunc = trunc <2 x i64> %shl to <2 x i32> 332 ret <2 x i32> %trunc 333} 334 335define void @trunc_shl_31_i32_i64_multi_use(i64 %val, i32 addrspace(1)* %ptr0, i64 addrspace(1)* %ptr1) { 336; CHECK-LABEL: @trunc_shl_31_i32_i64_multi_use( 337; CHECK-NEXT: [[SHL:%.*]] = shl i64 %val, 31 338; CHECK-NEXT: [[TRUNC:%.*]] = trunc i64 [[SHL]] to i32 339; CHECK-NEXT: store volatile i32 [[TRUNC]], i32 addrspace(1)* %ptr0, align 4 340; CHECK-NEXT: store volatile i64 [[SHL]], i64 addrspace(1)* %ptr1, align 8 341; CHECK-NEXT: ret void 342; 343 %shl = shl i64 %val, 31 344 %trunc = trunc i64 %shl to i32 345 store volatile i32 %trunc, i32 addrspace(1)* %ptr0 346 store volatile i64 %shl, i64 addrspace(1)* %ptr1 347 ret void 348} 349 350define i32 @trunc_shl_lshr_infloop(i64 %arg) { 351; CHECK-LABEL: @trunc_shl_lshr_infloop( 352; CHECK-NEXT: [[TMP0:%.*]] = lshr i64 %arg, 1 353; CHECK-NEXT: [[TMP1:%.*]] = shl i64 [[TMP0]], 2 354; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[TMP1]] to i32 355; CHECK-NEXT: ret i32 [[TMP2]] 356; 357 %tmp0 = lshr i64 %arg, 1 358 %tmp1 = shl i64 %tmp0, 2 359 %tmp2 = trunc i64 %tmp1 to i32 360 ret i32 %tmp2 361} 362 363define i32 @trunc_shl_ashr_infloop(i64 %arg) { 364; CHECK-LABEL: @trunc_shl_ashr_infloop( 365; CHECK-NEXT: [[TMP0:%.*]] = ashr i64 %arg, 3 366; CHECK-NEXT: [[TMP1:%.*]] = shl nsw i64 [[TMP0]], 2 367; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[TMP1]] to i32 368; CHECK-NEXT: ret i32 [[TMP2]] 369; 370 %tmp0 = ashr i64 %arg, 3 371 %tmp1 = shl i64 %tmp0, 2 372 %tmp2 = trunc i64 %tmp1 to i32 373 ret i32 %tmp2 374} 375 376define i32 @trunc_shl_shl_infloop(i64 %arg) { 377; CHECK-LABEL: @trunc_shl_shl_infloop( 378; CHECK-NEXT: [[ARG_TR:%.*]] = trunc i64 %arg to i32 379; CHECK-NEXT: [[TMP2:%.*]] = shl i32 [[ARG_TR]], 3 380; CHECK-NEXT: ret i32 [[TMP2]] 381; 382 %tmp0 = shl i64 %arg, 1 383 %tmp1 = shl i64 %tmp0, 2 384 %tmp2 = trunc i64 %tmp1 to i32 385 ret i32 %tmp2 386} 387 388define i32 @trunc_shl_lshr_var(i64 %arg, i64 %val) { 389; CHECK-LABEL: @trunc_shl_lshr_var( 390; CHECK-NEXT: [[TMP0:%.*]] = lshr i64 %arg, %val 391; CHECK-NEXT: [[TMP0_TR:%.*]] = trunc i64 [[TMP0]] to i32 392; CHECK-NEXT: [[TMP2:%.*]] = shl i32 [[TMP0_TR]], 2 393; CHECK-NEXT: ret i32 [[TMP2]] 394; 395 %tmp0 = lshr i64 %arg, %val 396 %tmp1 = shl i64 %tmp0, 2 397 %tmp2 = trunc i64 %tmp1 to i32 398 ret i32 %tmp2 399} 400 401define i32 @trunc_shl_ashr_var(i64 %arg, i64 %val) { 402; CHECK-LABEL: @trunc_shl_ashr_var( 403; CHECK-NEXT: [[TMP0:%.*]] = ashr i64 %arg, %val 404; CHECK-NEXT: [[TMP0_TR:%.*]] = trunc i64 [[TMP0]] to i32 405; CHECK-NEXT: [[TMP2:%.*]] = shl i32 [[TMP0_TR]], 2 406; CHECK-NEXT: ret i32 [[TMP2]] 407; 408 %tmp0 = ashr i64 %arg, %val 409 %tmp1 = shl i64 %tmp0, 2 410 %tmp2 = trunc i64 %tmp1 to i32 411 ret i32 %tmp2 412} 413 414define i32 @trunc_shl_shl_var(i64 %arg, i64 %val) { 415; CHECK-LABEL: @trunc_shl_shl_var( 416; CHECK-NEXT: [[TMP0:%.*]] = shl i64 %arg, %val 417; CHECK-NEXT: [[TMP0_TR:%.*]] = trunc i64 [[TMP0]] to i32 418; CHECK-NEXT: [[TMP2:%.*]] = shl i32 [[TMP0_TR]], 2 419; CHECK-NEXT: ret i32 [[TMP2]] 420; 421 %tmp0 = shl i64 %arg, %val 422 %tmp1 = shl i64 %tmp0, 2 423 %tmp2 = trunc i64 %tmp1 to i32 424 ret i32 %tmp2 425} 426 427define <8 x i16> @trunc_shl_v8i15_v8i32_15(<8 x i32> %a) { 428; CHECK-LABEL: @trunc_shl_v8i15_v8i32_15( 429; CHECK-NEXT: [[SHL:%.*]] = shl <8 x i32> %a, <i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15> 430; CHECK-NEXT: [[CONV:%.*]] = trunc <8 x i32> [[SHL]] to <8 x i16> 431; CHECK-NEXT: ret <8 x i16> [[CONV]] 432; 433 %shl = shl <8 x i32> %a, <i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15> 434 %conv = trunc <8 x i32> %shl to <8 x i16> 435 ret <8 x i16> %conv 436} 437 438define <8 x i16> @trunc_shl_v8i16_v8i32_16(<8 x i32> %a) { 439; CHECK-LABEL: @trunc_shl_v8i16_v8i32_16( 440; CHECK-NEXT: ret <8 x i16> zeroinitializer 441; 442 %shl = shl <8 x i32> %a, <i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16> 443 %conv = trunc <8 x i32> %shl to <8 x i16> 444 ret <8 x i16> %conv 445} 446 447define <8 x i16> @trunc_shl_v8i16_v8i32_17(<8 x i32> %a) { 448; CHECK-LABEL: @trunc_shl_v8i16_v8i32_17( 449; CHECK-NEXT: ret <8 x i16> zeroinitializer 450; 451 %shl = shl <8 x i32> %a, <i32 17, i32 17, i32 17, i32 17, i32 17, i32 17, i32 17, i32 17> 452 %conv = trunc <8 x i32> %shl to <8 x i16> 453 ret <8 x i16> %conv 454} 455 456define <8 x i16> @trunc_shl_v8i16_v8i32_4(<8 x i32> %a) { 457; CHECK-LABEL: @trunc_shl_v8i16_v8i32_4( 458; CHECK-NEXT: [[SHL:%.*]] = shl <8 x i32> %a, <i32 4, i32 4, i32 4, i32 4, i32 4, i32 4, i32 4, i32 4> 459; CHECK-NEXT: [[CONV:%.*]] = trunc <8 x i32> [[SHL]] to <8 x i16> 460; CHECK-NEXT: ret <8 x i16> [[CONV]] 461; 462 %shl = shl <8 x i32> %a, <i32 4, i32 4, i32 4, i32 4, i32 4, i32 4, i32 4, i32 4> 463 %conv = trunc <8 x i32> %shl to <8 x i16> 464 ret <8 x i16> %conv 465} 466 467