1221 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=instcombine -S | FileCheck %s3target 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)8declare void @use.i8(i8)9declare void @use_vec(<2 x i32>)10 11define i64 @test1(i64 %a) {12; CHECK-LABEL: @test1(13; CHECK-NEXT: [[B:%.*]] = trunc i64 [[A:%.*]] to i3214; CHECK-NEXT: [[C:%.*]] = and i64 [[A]], 1515; CHECK-NEXT: call void @use(i32 [[B]])16; CHECK-NEXT: ret i64 [[C]]17;18 %b = trunc i64 %a to i3219 %c = and i32 %b, 1520 %d = zext i32 %c to i6421 call void @use(i32 %b)22 ret i64 %d23}24 25define <2 x i64> @test1_vec(<2 x i64> %a) {26; CHECK-LABEL: @test1_vec(27; CHECK-NEXT: [[B:%.*]] = trunc <2 x i64> [[A:%.*]] to <2 x i32>28; CHECK-NEXT: [[D:%.*]] = and <2 x i64> [[A]], splat (i64 15)29; CHECK-NEXT: call void @use_vec(<2 x i32> [[B]])30; CHECK-NEXT: ret <2 x i64> [[D]]31;32 %b = trunc <2 x i64> %a to <2 x i32>33 %c = and <2 x i32> %b, <i32 15, i32 15>34 %d = zext <2 x i32> %c to <2 x i64>35 call void @use_vec(<2 x i32> %b)36 ret <2 x i64> %d37}38 39define <2 x i64> @test1_vec_nonuniform(<2 x i64> %a) {40; CHECK-LABEL: @test1_vec_nonuniform(41; CHECK-NEXT: [[B:%.*]] = trunc <2 x i64> [[A:%.*]] to <2 x i32>42; CHECK-NEXT: [[D:%.*]] = and <2 x i64> [[A]], <i64 15, i64 7>43; CHECK-NEXT: call void @use_vec(<2 x i32> [[B]])44; CHECK-NEXT: ret <2 x i64> [[D]]45;46 %b = trunc <2 x i64> %a to <2 x i32>47 %c = and <2 x i32> %b, <i32 15, i32 7>48 %d = zext <2 x i32> %c to <2 x i64>49 call void @use_vec(<2 x i32> %b)50 ret <2 x i64> %d51}52 53define <2 x i64> @test1_vec_poison(<2 x i64> %a) {54; CHECK-LABEL: @test1_vec_poison(55; CHECK-NEXT: [[B:%.*]] = trunc <2 x i64> [[A:%.*]] to <2 x i32>56; CHECK-NEXT: [[D:%.*]] = and <2 x i64> [[A]], <i64 15, i64 poison>57; CHECK-NEXT: call void @use_vec(<2 x i32> [[B]])58; CHECK-NEXT: ret <2 x i64> [[D]]59;60 %b = trunc <2 x i64> %a to <2 x i32>61 %c = and <2 x i32> %b, <i32 15, i32 poison>62 %d = zext <2 x i32> %c to <2 x i64>63 call void @use_vec(<2 x i32> %b)64 ret <2 x i64> %d65}66 67define i64 @test2(i64 %a) {68; CHECK-LABEL: @test2(69; CHECK-NEXT: [[B:%.*]] = trunc i64 [[A:%.*]] to i3270; CHECK-NEXT: [[D1:%.*]] = shl i64 [[A]], 3671; CHECK-NEXT: [[D:%.*]] = ashr exact i64 [[D1]], 3672; CHECK-NEXT: call void @use(i32 [[B]])73; CHECK-NEXT: ret i64 [[D]]74;75 %b = trunc i64 %a to i3276 %c = shl i32 %b, 477 %q = ashr i32 %c, 478 %d = sext i32 %q to i6479 call void @use(i32 %b)80 ret i64 %d81}82 83define <2 x i64> @test2_vec(<2 x i64> %a) {84; CHECK-LABEL: @test2_vec(85; CHECK-NEXT: [[B:%.*]] = trunc <2 x i64> [[A:%.*]] to <2 x i32>86; CHECK-NEXT: [[D1:%.*]] = shl <2 x i64> [[A]], splat (i64 36)87; CHECK-NEXT: [[D:%.*]] = ashr exact <2 x i64> [[D1]], splat (i64 36)88; CHECK-NEXT: call void @use_vec(<2 x i32> [[B]])89; CHECK-NEXT: ret <2 x i64> [[D]]90;91 %b = trunc <2 x i64> %a to <2 x i32>92 %c = shl <2 x i32> %b, <i32 4, i32 4>93 %q = ashr <2 x i32> %c, <i32 4, i32 4>94 %d = sext <2 x i32> %q to <2 x i64>95 call void @use_vec(<2 x i32> %b)96 ret <2 x i64> %d97}98 99define <2 x i64> @test2_vec_nonuniform(<2 x i64> %a) {100; CHECK-LABEL: @test2_vec_nonuniform(101; CHECK-NEXT: [[B:%.*]] = trunc <2 x i64> [[A:%.*]] to <2 x i32>102; CHECK-NEXT: [[D1:%.*]] = shl <2 x i64> [[A]], <i64 36, i64 37>103; CHECK-NEXT: [[D:%.*]] = ashr exact <2 x i64> [[D1]], <i64 36, i64 37>104; CHECK-NEXT: call void @use_vec(<2 x i32> [[B]])105; CHECK-NEXT: ret <2 x i64> [[D]]106;107 %b = trunc <2 x i64> %a to <2 x i32>108 %c = shl <2 x i32> %b, <i32 4, i32 5>109 %q = ashr <2 x i32> %c, <i32 4, i32 5>110 %d = sext <2 x i32> %q to <2 x i64>111 call void @use_vec(<2 x i32> %b)112 ret <2 x i64> %d113}114 115define <2 x i64> @test2_vec_poison(<2 x i64> %a) {116; CHECK-LABEL: @test2_vec_poison(117; CHECK-NEXT: [[B:%.*]] = trunc <2 x i64> [[A:%.*]] to <2 x i32>118; CHECK-NEXT: [[D1:%.*]] = shl <2 x i64> [[A]], <i64 36, i64 poison>119; CHECK-NEXT: [[D:%.*]] = ashr exact <2 x i64> [[D1]], <i64 36, i64 poison>120; CHECK-NEXT: call void @use_vec(<2 x i32> [[B]])121; CHECK-NEXT: ret <2 x i64> [[D]]122;123 %b = trunc <2 x i64> %a to <2 x i32>124 %c = shl <2 x i32> %b, <i32 4, i32 poison>125 %q = ashr <2 x i32> %c, <i32 4, i32 poison>126 %d = sext <2 x i32> %q to <2 x i64>127 call void @use_vec(<2 x i32> %b)128 ret <2 x i64> %d129}130 131define i64 @test3(i64 %a) {132; CHECK-LABEL: @test3(133; CHECK-NEXT: [[B:%.*]] = trunc i64 [[A:%.*]] to i32134; CHECK-NEXT: [[C:%.*]] = and i64 [[A]], 8135; CHECK-NEXT: call void @use(i32 [[B]])136; CHECK-NEXT: ret i64 [[C]]137;138 %b = trunc i64 %a to i32139 %c = and i32 %b, 8140 %d = zext i32 %c to i64141 call void @use(i32 %b)142 ret i64 %d143}144 145define i64 @test4(i64 %a) {146; CHECK-LABEL: @test4(147; CHECK-NEXT: [[B:%.*]] = trunc i64 [[A:%.*]] to i32148; CHECK-NEXT: [[C:%.*]] = and i64 [[A]], 8149; CHECK-NEXT: [[X:%.*]] = xor i64 [[C]], 8150; CHECK-NEXT: call void @use(i32 [[B]])151; CHECK-NEXT: ret i64 [[X]]152;153 %b = trunc i64 %a to i32154 %c = and i32 %b, 8155 %x = xor i32 %c, 8156 %d = zext i32 %x to i64157 call void @use(i32 %b)158 ret i64 %d159}160 161define i32 @test5(i32 %A) {162; CHECK-LABEL: @test5(163; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[A:%.*]], 16164; CHECK-NEXT: ret i32 [[TMP1]]165;166 %B = zext i32 %A to i128167 %C = lshr i128 %B, 16168 %D = trunc i128 %C to i32169 ret i32 %D170}171 172define i32 @test6(i64 %A) {173; CHECK-LABEL: @test6(174; CHECK-NEXT: [[TMP1:%.*]] = lshr i64 [[A:%.*]], 32175; CHECK-NEXT: [[D:%.*]] = trunc nuw i64 [[TMP1]] to i32176; CHECK-NEXT: ret i32 [[D]]177;178 %B = zext i64 %A to i128179 %C = lshr i128 %B, 32180 %D = trunc i128 %C to i32181 ret i32 %D182}183 184; Test case where 'ashr' demanded bits does not contain any of the high bits,185; but does contain sign bits, where the sign bit is not known to be zero.186define i16 @ashr_mul_sign_bits(i8 %X, i8 %Y) {187; CHECK-LABEL: @ashr_mul_sign_bits(188; CHECK-NEXT: [[A:%.*]] = sext i8 [[X:%.*]] to i16189; CHECK-NEXT: [[B:%.*]] = sext i8 [[Y:%.*]] to i16190; CHECK-NEXT: [[C:%.*]] = mul nsw i16 [[A]], [[B]]191; CHECK-NEXT: [[D:%.*]] = ashr i16 [[C]], 3192; CHECK-NEXT: ret i16 [[D]]193;194 %A = sext i8 %X to i32195 %B = sext i8 %Y to i32196 %C = mul i32 %A, %B197 %D = ashr i32 %C, 3198 %E = trunc i32 %D to i16199 ret i16 %E200}201 202define i16 @ashr_mul(i8 %X, i8 %Y) {203; CHECK-LABEL: @ashr_mul(204; CHECK-NEXT: [[A:%.*]] = sext i8 [[X:%.*]] to i16205; CHECK-NEXT: [[B:%.*]] = sext i8 [[Y:%.*]] to i16206; CHECK-NEXT: [[C:%.*]] = mul nsw i16 [[A]], [[B]]207; CHECK-NEXT: [[D:%.*]] = ashr i16 [[C]], 8208; CHECK-NEXT: ret i16 [[D]]209;210 %A = sext i8 %X to i20211 %B = sext i8 %Y to i20212 %C = mul i20 %A, %B213 %D = ashr i20 %C, 8214 %E = trunc i20 %D to i16215 ret i16 %E216}217 218define i32 @trunc_ashr(i32 %X) {219; CHECK-LABEL: @trunc_ashr(220; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 8221; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], -8388608222; CHECK-NEXT: ret i32 [[TMP2]]223;224 %A = zext i32 %X to i36225 %B = or i36 %A, -2147483648 ; 0xF80000000226 %C = ashr i36 %B, 8227 %T = trunc i36 %C to i32228 ret i32 %T229}230 231define <2 x i32> @trunc_ashr_vec(<2 x i32> %X) {232; CHECK-LABEL: @trunc_ashr_vec(233; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i32> [[X:%.*]], splat (i32 8)234; CHECK-NEXT: [[TMP2:%.*]] = or <2 x i32> [[TMP1]], splat (i32 -8388608)235; CHECK-NEXT: ret <2 x i32> [[TMP2]]236;237 %A = zext <2 x i32> %X to <2 x i36>238 %B = or <2 x i36> %A, <i36 -2147483648, i36 -2147483648> ; 0xF80000000239 %C = ashr <2 x i36> %B, <i36 8, i36 8>240 %T = trunc <2 x i36> %C to <2 x i32>241 ret <2 x i32> %T242}243 244define i92 @test7(i64 %A) {245; CHECK-LABEL: @test7(246; CHECK-NEXT: [[TMP1:%.*]] = lshr i64 [[A:%.*]], 32247; CHECK-NEXT: [[D:%.*]] = zext nneg i64 [[TMP1]] to i92248; CHECK-NEXT: ret i92 [[D]]249;250 %B = zext i64 %A to i128251 %C = lshr i128 %B, 32252 %D = trunc i128 %C to i92253 ret i92 %D254}255 256define i64 @test8(i32 %A, i32 %B) {257; CHECK-LABEL: @test8(258; CHECK-NEXT: [[C:%.*]] = zext i32 [[A:%.*]] to i64259; CHECK-NEXT: [[D:%.*]] = zext i32 [[B:%.*]] to i64260; CHECK-NEXT: [[E:%.*]] = shl nuw i64 [[D]], 32261; CHECK-NEXT: [[F:%.*]] = or disjoint i64 [[E]], [[C]]262; CHECK-NEXT: ret i64 [[F]]263;264 %C = zext i32 %A to i128265 %D = zext i32 %B to i128266 %E = shl i128 %D, 32267 %F = or i128 %E, %C268 %G = trunc i128 %F to i64269 ret i64 %G270}271 272define <2 x i64> @test8_vec(<2 x i32> %A, <2 x i32> %B) {273; CHECK-LABEL: @test8_vec(274; CHECK-NEXT: [[C:%.*]] = zext <2 x i32> [[A:%.*]] to <2 x i64>275; CHECK-NEXT: [[D:%.*]] = zext <2 x i32> [[B:%.*]] to <2 x i64>276; CHECK-NEXT: [[E:%.*]] = shl nuw <2 x i64> [[D]], splat (i64 32)277; CHECK-NEXT: [[F:%.*]] = or disjoint <2 x i64> [[E]], [[C]]278; CHECK-NEXT: ret <2 x i64> [[F]]279;280 %C = zext <2 x i32> %A to <2 x i128>281 %D = zext <2 x i32> %B to <2 x i128>282 %E = shl <2 x i128> %D, <i128 32, i128 32>283 %F = or <2 x i128> %E, %C284 %G = trunc <2 x i128> %F to <2 x i64>285 ret <2 x i64> %G286}287 288define <2 x i64> @test8_vec_nonuniform(<2 x i32> %A, <2 x i32> %B) {289; CHECK-LABEL: @test8_vec_nonuniform(290; CHECK-NEXT: [[C:%.*]] = zext <2 x i32> [[A:%.*]] to <2 x i64>291; CHECK-NEXT: [[D:%.*]] = zext <2 x i32> [[B:%.*]] to <2 x i64>292; CHECK-NEXT: [[E:%.*]] = shl <2 x i64> [[D]], <i64 32, i64 48>293; CHECK-NEXT: [[F:%.*]] = or disjoint <2 x i64> [[E]], [[C]]294; CHECK-NEXT: ret <2 x i64> [[F]]295;296 %C = zext <2 x i32> %A to <2 x i128>297 %D = zext <2 x i32> %B to <2 x i128>298 %E = shl <2 x i128> %D, <i128 32, i128 48>299 %F = or <2 x i128> %E, %C300 %G = trunc <2 x i128> %F to <2 x i64>301 ret <2 x i64> %G302}303 304define <2 x i64> @test8_vec_poison(<2 x i32> %A, <2 x i32> %B) {305; CHECK-LABEL: @test8_vec_poison(306; CHECK-NEXT: [[C:%.*]] = zext <2 x i32> [[A:%.*]] to <2 x i64>307; CHECK-NEXT: [[D:%.*]] = zext <2 x i32> [[B:%.*]] to <2 x i64>308; CHECK-NEXT: [[E:%.*]] = shl nuw <2 x i64> [[D]], <i64 32, i64 poison>309; CHECK-NEXT: [[F:%.*]] = or disjoint <2 x i64> [[E]], [[C]]310; CHECK-NEXT: ret <2 x i64> [[F]]311;312 %C = zext <2 x i32> %A to <2 x i128>313 %D = zext <2 x i32> %B to <2 x i128>314 %E = shl <2 x i128> %D, <i128 32, i128 poison>315 %F = or <2 x i128> %E, %C316 %G = trunc <2 x i128> %F to <2 x i64>317 ret <2 x i64> %G318}319 320define i8 @test9(i32 %X) {321; CHECK-LABEL: @test9(322; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i8323; CHECK-NEXT: [[Z:%.*]] = and i8 [[TMP1]], 42324; CHECK-NEXT: ret i8 [[Z]]325;326 %Y = and i32 %X, 42327 %Z = trunc i32 %Y to i8328 ret i8 %Z329}330 331; rdar://8808586332define i8 @test10(i32 %X) {333; CHECK-LABEL: @test10(334; CHECK-NEXT: [[Y:%.*]] = trunc i32 [[X:%.*]] to i8335; CHECK-NEXT: [[Z:%.*]] = and i8 [[Y]], 42336; CHECK-NEXT: ret i8 [[Z]]337;338 %Y = trunc i32 %X to i8339 %Z = and i8 %Y, 42340 ret i8 %Z341}342 343define i64 @test11(i32 %A, i32 %B) {344; CHECK-LABEL: @test11(345; CHECK-NEXT: [[C:%.*]] = zext i32 [[A:%.*]] to i64346; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[B:%.*]], 31347; CHECK-NEXT: [[E:%.*]] = zext nneg i32 [[TMP1]] to i64348; CHECK-NEXT: [[F:%.*]] = shl nuw nsw i64 [[C]], [[E]]349; CHECK-NEXT: ret i64 [[F]]350;351 %C = zext i32 %A to i128352 %D = zext i32 %B to i128353 %E = and i128 %D, 31354 %F = shl i128 %C, %E355 %G = trunc i128 %F to i64356 ret i64 %G357}358 359define <2 x i64> @test11_vec(<2 x i32> %A, <2 x i32> %B) {360; CHECK-LABEL: @test11_vec(361; CHECK-NEXT: [[C:%.*]] = zext <2 x i32> [[A:%.*]] to <2 x i64>362; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[B:%.*]], splat (i32 31)363; CHECK-NEXT: [[E:%.*]] = zext nneg <2 x i32> [[TMP1]] to <2 x i64>364; CHECK-NEXT: [[F:%.*]] = shl nuw nsw <2 x i64> [[C]], [[E]]365; CHECK-NEXT: ret <2 x i64> [[F]]366;367 %C = zext <2 x i32> %A to <2 x i128>368 %D = zext <2 x i32> %B to <2 x i128>369 %E = and <2 x i128> %D, <i128 31, i128 31>370 %F = shl <2 x i128> %C, %E371 %G = trunc <2 x i128> %F to <2 x i64>372 ret <2 x i64> %G373}374 375define <2 x i64> @test11_vec_nonuniform(<2 x i32> %A, <2 x i32> %B) {376; CHECK-LABEL: @test11_vec_nonuniform(377; CHECK-NEXT: [[C:%.*]] = zext <2 x i32> [[A:%.*]] to <2 x i64>378; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[B:%.*]], <i32 31, i32 15>379; CHECK-NEXT: [[E:%.*]] = zext nneg <2 x i32> [[TMP1]] to <2 x i64>380; CHECK-NEXT: [[F:%.*]] = shl nuw nsw <2 x i64> [[C]], [[E]]381; CHECK-NEXT: ret <2 x i64> [[F]]382;383 %C = zext <2 x i32> %A to <2 x i128>384 %D = zext <2 x i32> %B to <2 x i128>385 %E = and <2 x i128> %D, <i128 31, i128 15>386 %F = shl <2 x i128> %C, %E387 %G = trunc <2 x i128> %F to <2 x i64>388 ret <2 x i64> %G389}390 391define <2 x i64> @test11_vec_poison(<2 x i32> %A, <2 x i32> %B) {392; CHECK-LABEL: @test11_vec_poison(393; CHECK-NEXT: [[C:%.*]] = zext <2 x i32> [[A:%.*]] to <2 x i64>394; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[B:%.*]], <i32 31, i32 poison>395; CHECK-NEXT: [[E:%.*]] = zext nneg <2 x i32> [[TMP1]] to <2 x i64>396; CHECK-NEXT: [[F:%.*]] = shl nuw nsw <2 x i64> [[C]], [[E]]397; CHECK-NEXT: ret <2 x i64> [[F]]398;399 %C = zext <2 x i32> %A to <2 x i128>400 %D = zext <2 x i32> %B to <2 x i128>401 %E = and <2 x i128> %D, <i128 31, i128 poison>402 %F = shl <2 x i128> %C, %E403 %G = trunc <2 x i128> %F to <2 x i64>404 ret <2 x i64> %G405}406 407define i64 @test12(i32 %A, i32 %B) {408; CHECK-LABEL: @test12(409; CHECK-NEXT: [[C:%.*]] = zext i32 [[A:%.*]] to i64410; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[B:%.*]], 31411; CHECK-NEXT: [[E:%.*]] = zext nneg i32 [[TMP1]] to i64412; CHECK-NEXT: [[F:%.*]] = lshr i64 [[C]], [[E]]413; CHECK-NEXT: ret i64 [[F]]414;415 %C = zext i32 %A to i128416 %D = zext i32 %B to i128417 %E = and i128 %D, 31418 %F = lshr i128 %C, %E419 %G = trunc i128 %F to i64420 ret i64 %G421}422 423define <2 x i64> @test12_vec(<2 x i32> %A, <2 x i32> %B) {424; CHECK-LABEL: @test12_vec(425; CHECK-NEXT: [[C:%.*]] = zext <2 x i32> [[A:%.*]] to <2 x i64>426; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[B:%.*]], splat (i32 31)427; CHECK-NEXT: [[E:%.*]] = zext nneg <2 x i32> [[TMP1]] to <2 x i64>428; CHECK-NEXT: [[F:%.*]] = lshr <2 x i64> [[C]], [[E]]429; CHECK-NEXT: ret <2 x i64> [[F]]430;431 %C = zext <2 x i32> %A to <2 x i128>432 %D = zext <2 x i32> %B to <2 x i128>433 %E = and <2 x i128> %D, <i128 31, i128 31>434 %F = lshr <2 x i128> %C, %E435 %G = trunc <2 x i128> %F to <2 x i64>436 ret <2 x i64> %G437}438 439define <2 x i64> @test12_vec_nonuniform(<2 x i32> %A, <2 x i32> %B) {440; CHECK-LABEL: @test12_vec_nonuniform(441; CHECK-NEXT: [[C:%.*]] = zext <2 x i32> [[A:%.*]] to <2 x i64>442; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[B:%.*]], <i32 31, i32 15>443; CHECK-NEXT: [[E:%.*]] = zext nneg <2 x i32> [[TMP1]] to <2 x i64>444; CHECK-NEXT: [[F:%.*]] = lshr <2 x i64> [[C]], [[E]]445; CHECK-NEXT: ret <2 x i64> [[F]]446;447 %C = zext <2 x i32> %A to <2 x i128>448 %D = zext <2 x i32> %B to <2 x i128>449 %E = and <2 x i128> %D, <i128 31, i128 15>450 %F = lshr <2 x i128> %C, %E451 %G = trunc <2 x i128> %F to <2 x i64>452 ret <2 x i64> %G453}454 455define <2 x i64> @test12_vec_poison(<2 x i32> %A, <2 x i32> %B) {456; CHECK-LABEL: @test12_vec_poison(457; CHECK-NEXT: [[C:%.*]] = zext <2 x i32> [[A:%.*]] to <2 x i64>458; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[B:%.*]], <i32 31, i32 poison>459; CHECK-NEXT: [[E:%.*]] = zext nneg <2 x i32> [[TMP1]] to <2 x i64>460; CHECK-NEXT: [[F:%.*]] = lshr <2 x i64> [[C]], [[E]]461; CHECK-NEXT: ret <2 x i64> [[F]]462;463 %C = zext <2 x i32> %A to <2 x i128>464 %D = zext <2 x i32> %B to <2 x i128>465 %E = and <2 x i128> %D, <i128 31, i128 poison>466 %F = lshr <2 x i128> %C, %E467 %G = trunc <2 x i128> %F to <2 x i64>468 ret <2 x i64> %G469}470 471define i64 @test13(i32 %A, i32 %B) {472; CHECK-LABEL: @test13(473; CHECK-NEXT: [[C:%.*]] = sext i32 [[A:%.*]] to i64474; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[B:%.*]], 31475; CHECK-NEXT: [[E:%.*]] = zext nneg i32 [[TMP1]] to i64476; CHECK-NEXT: [[F:%.*]] = ashr i64 [[C]], [[E]]477; CHECK-NEXT: ret i64 [[F]]478;479 %C = sext i32 %A to i128480 %D = zext i32 %B to i128481 %E = and i128 %D, 31482 %F = ashr i128 %C, %E483 %G = trunc i128 %F to i64484 ret i64 %G485}486 487define <2 x i64> @test13_vec(<2 x i32> %A, <2 x i32> %B) {488; CHECK-LABEL: @test13_vec(489; CHECK-NEXT: [[C:%.*]] = sext <2 x i32> [[A:%.*]] to <2 x i64>490; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[B:%.*]], splat (i32 31)491; CHECK-NEXT: [[E:%.*]] = zext nneg <2 x i32> [[TMP1]] to <2 x i64>492; CHECK-NEXT: [[F:%.*]] = ashr <2 x i64> [[C]], [[E]]493; CHECK-NEXT: ret <2 x i64> [[F]]494;495 %C = sext <2 x i32> %A to <2 x i128>496 %D = zext <2 x i32> %B to <2 x i128>497 %E = and <2 x i128> %D, <i128 31, i128 31>498 %F = ashr <2 x i128> %C, %E499 %G = trunc <2 x i128> %F to <2 x i64>500 ret <2 x i64> %G501}502 503define <2 x i64> @test13_vec_nonuniform(<2 x i32> %A, <2 x i32> %B) {504; CHECK-LABEL: @test13_vec_nonuniform(505; CHECK-NEXT: [[C:%.*]] = sext <2 x i32> [[A:%.*]] to <2 x i64>506; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[B:%.*]], <i32 31, i32 15>507; CHECK-NEXT: [[E:%.*]] = zext nneg <2 x i32> [[TMP1]] to <2 x i64>508; CHECK-NEXT: [[F:%.*]] = ashr <2 x i64> [[C]], [[E]]509; CHECK-NEXT: ret <2 x i64> [[F]]510;511 %C = sext <2 x i32> %A to <2 x i128>512 %D = zext <2 x i32> %B to <2 x i128>513 %E = and <2 x i128> %D, <i128 31, i128 15>514 %F = ashr <2 x i128> %C, %E515 %G = trunc <2 x i128> %F to <2 x i64>516 ret <2 x i64> %G517}518 519define <2 x i64> @test13_vec_poison(<2 x i32> %A, <2 x i32> %B) {520; CHECK-LABEL: @test13_vec_poison(521; CHECK-NEXT: [[C:%.*]] = sext <2 x i32> [[A:%.*]] to <2 x i64>522; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[B:%.*]], <i32 31, i32 poison>523; CHECK-NEXT: [[E:%.*]] = zext nneg <2 x i32> [[TMP1]] to <2 x i64>524; CHECK-NEXT: [[F:%.*]] = ashr <2 x i64> [[C]], [[E]]525; CHECK-NEXT: ret <2 x i64> [[F]]526;527 %C = sext <2 x i32> %A to <2 x i128>528 %D = zext <2 x i32> %B to <2 x i128>529 %E = and <2 x i128> %D, <i128 31, i128 poison>530 %F = ashr <2 x i128> %C, %E531 %G = trunc <2 x i128> %F to <2 x i64>532 ret <2 x i64> %G533}534 535; PR25543536; https://llvm.org/bugs/show_bug.cgi?id=25543537; This is an extractelement.538 539define i32 @trunc_bitcast1(<4 x i32> %v) {540; CHECK-LABEL: @trunc_bitcast1(541; CHECK-NEXT: [[EXT:%.*]] = extractelement <4 x i32> [[V:%.*]], i64 1542; CHECK-NEXT: ret i32 [[EXT]]543;544 %bc = bitcast <4 x i32> %v to i128545 %shr = lshr i128 %bc, 32546 %ext = trunc i128 %shr to i32547 ret i32 %ext548}549 550; A bitcast may still be required.551 552define i32 @trunc_bitcast2(<2 x i64> %v) {553; CHECK-LABEL: @trunc_bitcast2(554; CHECK-NEXT: [[BC1:%.*]] = bitcast <2 x i64> [[V:%.*]] to <4 x i32>555; CHECK-NEXT: [[EXT:%.*]] = extractelement <4 x i32> [[BC1]], i64 2556; CHECK-NEXT: ret i32 [[EXT]]557;558 %bc = bitcast <2 x i64> %v to i128559 %shr = lshr i128 %bc, 64560 %ext = trunc i128 %shr to i32561 ret i32 %ext562}563 564; The right shift is optional.565 566define i32 @trunc_bitcast3(<4 x i32> %v) {567; CHECK-LABEL: @trunc_bitcast3(568; CHECK-NEXT: [[EXT:%.*]] = extractelement <4 x i32> [[V:%.*]], i64 0569; CHECK-NEXT: ret i32 [[EXT]]570;571 %bc = bitcast <4 x i32> %v to i128572 %ext = trunc i128 %bc to i32573 ret i32 %ext574}575 576define i32 @trunc_shl_31_i32_i64(i64 %val) {577; CHECK-LABEL: @trunc_shl_31_i32_i64(578; CHECK-NEXT: [[VAL_TR:%.*]] = trunc i64 [[VAL:%.*]] to i32579; CHECK-NEXT: [[TRUNC:%.*]] = shl i32 [[VAL_TR]], 31580; CHECK-NEXT: ret i32 [[TRUNC]]581;582 %shl = shl i64 %val, 31583 %trunc = trunc i64 %shl to i32584 ret i32 %trunc585}586 587define i32 @trunc_shl_nsw_31_i32_i64(i64 %val) {588; CHECK-LABEL: @trunc_shl_nsw_31_i32_i64(589; CHECK-NEXT: [[VAL_TR:%.*]] = trunc i64 [[VAL:%.*]] to i32590; CHECK-NEXT: [[TRUNC:%.*]] = shl i32 [[VAL_TR]], 31591; CHECK-NEXT: ret i32 [[TRUNC]]592;593 %shl = shl nsw i64 %val, 31594 %trunc = trunc i64 %shl to i32595 ret i32 %trunc596}597 598define i32 @trunc_shl_nuw_31_i32_i64(i64 %val) {599; CHECK-LABEL: @trunc_shl_nuw_31_i32_i64(600; CHECK-NEXT: [[VAL_TR:%.*]] = trunc i64 [[VAL:%.*]] to i32601; CHECK-NEXT: [[TRUNC:%.*]] = shl i32 [[VAL_TR]], 31602; CHECK-NEXT: ret i32 [[TRUNC]]603;604 %shl = shl nuw i64 %val, 31605 %trunc = trunc i64 %shl to i32606 ret i32 %trunc607}608 609define i32 @trunc_shl_nsw_nuw_31_i32_i64(i64 %val) {610; CHECK-LABEL: @trunc_shl_nsw_nuw_31_i32_i64(611; CHECK-NEXT: [[VAL_TR:%.*]] = trunc i64 [[VAL:%.*]] to i32612; CHECK-NEXT: [[TRUNC:%.*]] = shl i32 [[VAL_TR]], 31613; CHECK-NEXT: ret i32 [[TRUNC]]614;615 %shl = shl nsw nuw i64 %val, 31616 %trunc = trunc i64 %shl to i32617 ret i32 %trunc618}619 620define i16 @trunc_shl_15_i16_i64(i64 %val) {621; CHECK-LABEL: @trunc_shl_15_i16_i64(622; CHECK-NEXT: [[VAL_TR:%.*]] = trunc i64 [[VAL:%.*]] to i16623; CHECK-NEXT: [[TRUNC:%.*]] = shl i16 [[VAL_TR]], 15624; CHECK-NEXT: ret i16 [[TRUNC]]625;626 %shl = shl i64 %val, 15627 %trunc = trunc i64 %shl to i16628 ret i16 %trunc629}630 631define i16 @trunc_shl_15_i16_i32(i32 %val) {632; CHECK-LABEL: @trunc_shl_15_i16_i32(633; CHECK-NEXT: [[VAL_TR:%.*]] = trunc i32 [[VAL:%.*]] to i16634; CHECK-NEXT: [[TRUNC:%.*]] = shl i16 [[VAL_TR]], 15635; CHECK-NEXT: ret i16 [[TRUNC]]636;637 %shl = shl i32 %val, 15638 %trunc = trunc i32 %shl to i16639 ret i16 %trunc640}641 642define i8 @trunc_shl_7_i8_i64(i64 %val) {643; CHECK-LABEL: @trunc_shl_7_i8_i64(644; CHECK-NEXT: [[VAL_TR:%.*]] = trunc i64 [[VAL:%.*]] to i8645; CHECK-NEXT: [[TRUNC:%.*]] = shl i8 [[VAL_TR]], 7646; CHECK-NEXT: ret i8 [[TRUNC]]647;648 %shl = shl i64 %val, 7649 %trunc = trunc i64 %shl to i8650 ret i8 %trunc651}652 653define i2 @trunc_shl_1_i2_i64(i64 %val) {654; CHECK-LABEL: @trunc_shl_1_i2_i64(655; CHECK-NEXT: [[SHL:%.*]] = shl i64 [[VAL:%.*]], 1656; CHECK-NEXT: [[TRUNC:%.*]] = trunc i64 [[SHL]] to i2657; CHECK-NEXT: ret i2 [[TRUNC]]658;659 %shl = shl i64 %val, 1660 %trunc = trunc i64 %shl to i2661 ret i2 %trunc662}663 664define i32 @trunc_shl_1_i32_i64(i64 %val) {665; CHECK-LABEL: @trunc_shl_1_i32_i64(666; CHECK-NEXT: [[VAL_TR:%.*]] = trunc i64 [[VAL:%.*]] to i32667; CHECK-NEXT: [[TRUNC:%.*]] = shl i32 [[VAL_TR]], 1668; CHECK-NEXT: ret i32 [[TRUNC]]669;670 %shl = shl i64 %val, 1671 %trunc = trunc i64 %shl to i32672 ret i32 %trunc673}674 675define i32 @trunc_shl_16_i32_i64(i64 %val) {676; CHECK-LABEL: @trunc_shl_16_i32_i64(677; CHECK-NEXT: [[VAL_TR:%.*]] = trunc i64 [[VAL:%.*]] to i32678; CHECK-NEXT: [[TRUNC:%.*]] = shl i32 [[VAL_TR]], 16679; CHECK-NEXT: ret i32 [[TRUNC]]680;681 %shl = shl i64 %val, 16682 %trunc = trunc i64 %shl to i32683 ret i32 %trunc684}685 686define i32 @trunc_shl_33_i32_i64(i64 %val) {687; CHECK-LABEL: @trunc_shl_33_i32_i64(688; CHECK-NEXT: ret i32 0689;690 %shl = shl i64 %val, 33691 %trunc = trunc i64 %shl to i32692 ret i32 %trunc693}694 695define i32 @trunc_shl_32_i32_i64(i64 %val) {696; CHECK-LABEL: @trunc_shl_32_i32_i64(697; CHECK-NEXT: ret i32 0698;699 %shl = shl i64 %val, 32700 %trunc = trunc i64 %shl to i32701 ret i32 %trunc702}703 704; Should be able to handle vectors705define <2 x i32> @trunc_shl_16_v2i32_v2i64(<2 x i64> %val) {706; CHECK-LABEL: @trunc_shl_16_v2i32_v2i64(707; CHECK-NEXT: [[VAL_TR:%.*]] = trunc <2 x i64> [[VAL:%.*]] to <2 x i32>708; CHECK-NEXT: [[TRUNC:%.*]] = shl <2 x i32> [[VAL_TR]], splat (i32 16)709; CHECK-NEXT: ret <2 x i32> [[TRUNC]]710;711 %shl = shl <2 x i64> %val, <i64 16, i64 16>712 %trunc = trunc <2 x i64> %shl to <2 x i32>713 ret <2 x i32> %trunc714}715 716define <2 x i32> @trunc_shl_nosplat_v2i32_v2i64(<2 x i64> %val) {717; CHECK-LABEL: @trunc_shl_nosplat_v2i32_v2i64(718; CHECK-NEXT: [[VAL_TR:%.*]] = trunc <2 x i64> [[VAL:%.*]] to <2 x i32>719; CHECK-NEXT: [[TRUNC:%.*]] = shl <2 x i32> [[VAL_TR]], <i32 15, i32 16>720; CHECK-NEXT: ret <2 x i32> [[TRUNC]]721;722 %shl = shl <2 x i64> %val, <i64 15, i64 16>723 %trunc = trunc <2 x i64> %shl to <2 x i32>724 ret <2 x i32> %trunc725}726 727define void @trunc_shl_31_i32_i64_multi_use(i64 %val, ptr addrspace(1) %ptr0, ptr addrspace(1) %ptr1) {728; CHECK-LABEL: @trunc_shl_31_i32_i64_multi_use(729; CHECK-NEXT: [[SHL:%.*]] = shl i64 [[VAL:%.*]], 31730; CHECK-NEXT: [[TRUNC:%.*]] = trunc i64 [[SHL]] to i32731; CHECK-NEXT: store volatile i32 [[TRUNC]], ptr addrspace(1) [[PTR0:%.*]], align 4732; CHECK-NEXT: store volatile i64 [[SHL]], ptr addrspace(1) [[PTR1:%.*]], align 8733; CHECK-NEXT: ret void734;735 %shl = shl i64 %val, 31736 %trunc = trunc i64 %shl to i32737 store volatile i32 %trunc, ptr addrspace(1) %ptr0738 store volatile i64 %shl, ptr addrspace(1) %ptr1739 ret void740}741 742define i32 @trunc_shl_lshr_infloop(i64 %arg) {743; CHECK-LABEL: @trunc_shl_lshr_infloop(744; CHECK-NEXT: [[ARG_TR:%.*]] = trunc i64 [[ARG:%.*]] to i32745; CHECK-NEXT: [[TMP1:%.*]] = shl i32 [[ARG_TR]], 1746; CHECK-NEXT: [[C:%.*]] = and i32 [[TMP1]], -4747; CHECK-NEXT: ret i32 [[C]]748;749 %A = lshr i64 %arg, 1750 %B = shl i64 %A, 2751 %C = trunc i64 %B to i32752 ret i32 %C753}754 755define <2 x i32> @trunc_shl_v2i32_v2i64_uniform(<2 x i64> %val) {756; CHECK-LABEL: @trunc_shl_v2i32_v2i64_uniform(757; CHECK-NEXT: [[VAL_TR:%.*]] = trunc <2 x i64> [[VAL:%.*]] to <2 x i32>758; CHECK-NEXT: [[TRUNC:%.*]] = shl <2 x i32> [[VAL_TR]], splat (i32 31)759; CHECK-NEXT: ret <2 x i32> [[TRUNC]]760;761 %shl = shl <2 x i64> %val, <i64 31, i64 31>762 %trunc = trunc <2 x i64> %shl to <2 x i32>763 ret <2 x i32> %trunc764}765 766define <2 x i32> @trunc_shl_v2i32_v2i64_poison(<2 x i64> %val) {767; CHECK-LABEL: @trunc_shl_v2i32_v2i64_poison(768; CHECK-NEXT: [[VAL_TR:%.*]] = trunc <2 x i64> [[VAL:%.*]] to <2 x i32>769; CHECK-NEXT: [[TRUNC:%.*]] = shl <2 x i32> [[VAL_TR]], <i32 31, i32 poison>770; CHECK-NEXT: ret <2 x i32> [[TRUNC]]771;772 %shl = shl <2 x i64> %val, <i64 31, i64 poison>773 %trunc = trunc <2 x i64> %shl to <2 x i32>774 ret <2 x i32> %trunc775}776 777define <2 x i32> @trunc_shl_v2i32_v2i64_nonuniform(<2 x i64> %val) {778; CHECK-LABEL: @trunc_shl_v2i32_v2i64_nonuniform(779; CHECK-NEXT: [[VAL_TR:%.*]] = trunc <2 x i64> [[VAL:%.*]] to <2 x i32>780; CHECK-NEXT: [[TRUNC:%.*]] = shl <2 x i32> [[VAL_TR]], <i32 31, i32 12>781; CHECK-NEXT: ret <2 x i32> [[TRUNC]]782;783 %shl = shl <2 x i64> %val, <i64 31, i64 12>784 %trunc = trunc <2 x i64> %shl to <2 x i32>785 ret <2 x i32> %trunc786}787 788define <2 x i32> @trunc_shl_v2i32_v2i64_outofrange(<2 x i64> %val) {789; CHECK-LABEL: @trunc_shl_v2i32_v2i64_outofrange(790; CHECK-NEXT: [[SHL:%.*]] = shl <2 x i64> [[VAL:%.*]], <i64 31, i64 33>791; CHECK-NEXT: [[TRUNC:%.*]] = trunc <2 x i64> [[SHL]] to <2 x i32>792; CHECK-NEXT: ret <2 x i32> [[TRUNC]]793;794 %shl = shl <2 x i64> %val, <i64 31, i64 33>795 %trunc = trunc <2 x i64> %shl to <2 x i32>796 ret <2 x i32> %trunc797}798 799define i32 @trunc_shl_ashr_infloop(i64 %arg) {800; CHECK-LABEL: @trunc_shl_ashr_infloop(801; CHECK-NEXT: [[TMP1:%.*]] = lshr i64 [[ARG:%.*]], 1802; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[TMP1]] to i32803; CHECK-NEXT: [[C:%.*]] = and i32 [[TMP2]], -4804; CHECK-NEXT: ret i32 [[C]]805;806 %A = ashr i64 %arg, 3807 %B = shl i64 %A, 2808 %C = trunc i64 %B to i32809 ret i32 %C810}811 812define i32 @trunc_shl_shl_infloop(i64 %arg) {813; CHECK-LABEL: @trunc_shl_shl_infloop(814; CHECK-NEXT: [[ARG_TR:%.*]] = trunc i64 [[ARG:%.*]] to i32815; CHECK-NEXT: [[C:%.*]] = shl i32 [[ARG_TR]], 3816; CHECK-NEXT: ret i32 [[C]]817;818 %A = shl i64 %arg, 1819 %B = shl i64 %A, 2820 %C = trunc i64 %B to i32821 ret i32 %C822}823 824define i32 @trunc_shl_lshr_var(i64 %arg, i64 %val) {825; CHECK-LABEL: @trunc_shl_lshr_var(826; CHECK-NEXT: [[A:%.*]] = lshr i64 [[ARG:%.*]], [[VAL:%.*]]827; CHECK-NEXT: [[A_TR:%.*]] = trunc i64 [[A]] to i32828; CHECK-NEXT: [[C:%.*]] = shl i32 [[A_TR]], 2829; CHECK-NEXT: ret i32 [[C]]830;831 %A = lshr i64 %arg, %val832 %B = shl i64 %A, 2833 %C = trunc i64 %B to i32834 ret i32 %C835}836 837define i32 @trunc_shl_ashr_var(i64 %arg, i64 %val) {838; CHECK-LABEL: @trunc_shl_ashr_var(839; CHECK-NEXT: [[A:%.*]] = ashr i64 [[ARG:%.*]], [[VAL:%.*]]840; CHECK-NEXT: [[A_TR:%.*]] = trunc i64 [[A]] to i32841; CHECK-NEXT: [[C:%.*]] = shl i32 [[A_TR]], 2842; CHECK-NEXT: ret i32 [[C]]843;844 %A = ashr i64 %arg, %val845 %B = shl i64 %A, 2846 %C = trunc i64 %B to i32847 ret i32 %C848}849 850define i32 @trunc_shl_shl_var(i64 %arg, i64 %val) {851; CHECK-LABEL: @trunc_shl_shl_var(852; CHECK-NEXT: [[A:%.*]] = shl i64 [[ARG:%.*]], [[VAL:%.*]]853; CHECK-NEXT: [[A_TR:%.*]] = trunc i64 [[A]] to i32854; CHECK-NEXT: [[C:%.*]] = shl i32 [[A_TR]], 2855; CHECK-NEXT: ret i32 [[C]]856;857 %A = shl i64 %arg, %val858 %B = shl i64 %A, 2859 %C = trunc i64 %B to i32860 ret i32 %C861}862 863define <8 x i16> @trunc_shl_v8i15_v8i32_15(<8 x i32> %a) {864; CHECK-LABEL: @trunc_shl_v8i15_v8i32_15(865; CHECK-NEXT: [[A_TR:%.*]] = trunc <8 x i32> [[A:%.*]] to <8 x i16>866; CHECK-NEXT: [[CONV:%.*]] = shl <8 x i16> [[A_TR]], splat (i16 15)867; CHECK-NEXT: ret <8 x i16> [[CONV]]868;869 %shl = shl <8 x i32> %a, <i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15>870 %conv = trunc <8 x i32> %shl to <8 x i16>871 ret <8 x i16> %conv872}873 874define <8 x i16> @trunc_shl_v8i16_v8i32_16(<8 x i32> %a) {875; CHECK-LABEL: @trunc_shl_v8i16_v8i32_16(876; CHECK-NEXT: ret <8 x i16> zeroinitializer877;878 %shl = shl <8 x i32> %a, <i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16>879 %conv = trunc <8 x i32> %shl to <8 x i16>880 ret <8 x i16> %conv881}882 883define <8 x i16> @trunc_shl_v8i16_v8i32_17(<8 x i32> %a) {884; CHECK-LABEL: @trunc_shl_v8i16_v8i32_17(885; CHECK-NEXT: ret <8 x i16> zeroinitializer886;887 %shl = shl <8 x i32> %a, <i32 17, i32 17, i32 17, i32 17, i32 17, i32 17, i32 17, i32 17>888 %conv = trunc <8 x i32> %shl to <8 x i16>889 ret <8 x i16> %conv890}891 892define <8 x i16> @trunc_shl_v8i16_v8i32_4(<8 x i32> %a) {893; CHECK-LABEL: @trunc_shl_v8i16_v8i32_4(894; CHECK-NEXT: [[A_TR:%.*]] = trunc <8 x i32> [[A:%.*]] to <8 x i16>895; CHECK-NEXT: [[CONV:%.*]] = shl <8 x i16> [[A_TR]], splat (i16 4)896; CHECK-NEXT: ret <8 x i16> [[CONV]]897;898 %shl = shl <8 x i32> %a, <i32 4, i32 4, i32 4, i32 4, i32 4, i32 4, i32 4, i32 4>899 %conv = trunc <8 x i32> %shl to <8 x i16>900 ret <8 x i16> %conv901}902 903; Although the mask is the same value, we don't create a shuffle for types that the backend may not be able to handle:904; trunc (shuffle X, C, Mask) --> shuffle (trunc X), C', Mask905 906define <4 x i8> @wide_shuf(<4 x i32> %x) {907; CHECK-LABEL: @wide_shuf(908; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> <i32 poison, i32 3634, i32 90, i32 poison>, <4 x i32> <i32 1, i32 5, i32 6, i32 2>909; CHECK-NEXT: [[TRUNC:%.*]] = trunc <4 x i32> [[SHUF]] to <4 x i8>910; CHECK-NEXT: ret <4 x i8> [[TRUNC]]911;912 %shuf = shufflevector <4 x i32> %x, <4 x i32> <i32 35, i32 3634, i32 90, i32 -1>, <4 x i32> <i32 1, i32 5, i32 6, i32 2>913 %trunc = trunc <4 x i32> %shuf to <4 x i8>914 ret <4 x i8> %trunc915}916 917; trunc (shuffle X, poison, SplatMask) --> shuffle (trunc X), poison, SplatMask918 919define <4 x i8> @wide_splat1(<4 x i32> %x) {920; CHECK-LABEL: @wide_splat1(921; CHECK-NEXT: [[TMP1:%.*]] = trunc <4 x i32> [[X:%.*]] to <4 x i8>922; CHECK-NEXT: [[TRUNC:%.*]] = shufflevector <4 x i8> [[TMP1]], <4 x i8> poison, <4 x i32> <i32 2, i32 2, i32 2, i32 2>923; CHECK-NEXT: ret <4 x i8> [[TRUNC]]924;925 %shuf = shufflevector <4 x i32> %x, <4 x i32> poison, <4 x i32> <i32 2, i32 2, i32 2, i32 2>926 %trunc = trunc <4 x i32> %shuf to <4 x i8>927 ret <4 x i8> %trunc928}929 930; Test weird types.931; trunc (shuffle X, poison, SplatMask) --> shuffle (trunc X), poison, SplatMask932 933define <3 x i31> @wide_splat2(<3 x i33> %x) {934; CHECK-LABEL: @wide_splat2(935; CHECK-NEXT: [[TMP1:%.*]] = trunc <3 x i33> [[X:%.*]] to <3 x i31>936; CHECK-NEXT: [[TRUNC:%.*]] = shufflevector <3 x i31> [[TMP1]], <3 x i31> poison, <3 x i32> <i32 1, i32 1, i32 1>937; CHECK-NEXT: ret <3 x i31> [[TRUNC]]938;939 %shuf = shufflevector <3 x i33> %x, <3 x i33> poison, <3 x i32> <i32 1, i32 1, i32 1>940 %trunc = trunc <3 x i33> %shuf to <3 x i31>941 ret <3 x i31> %trunc942}943 944; FIXME:945; trunc (shuffle X, poison, SplatMask) --> shuffle (trunc X), poison, SplatMask946; A mask with poison elements should still be considered a splat mask.947 948define <3 x i31> @wide_splat3(<3 x i33> %x) {949; CHECK-LABEL: @wide_splat3(950; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <3 x i33> [[X:%.*]], <3 x i33> poison, <3 x i32> <i32 poison, i32 1, i32 1>951; CHECK-NEXT: [[TRUNC:%.*]] = trunc <3 x i33> [[SHUF]] to <3 x i31>952; CHECK-NEXT: ret <3 x i31> [[TRUNC]]953;954 %shuf = shufflevector <3 x i33> %x, <3 x i33> poison, <3 x i32> <i32 poison, i32 1, i32 1>955 %trunc = trunc <3 x i33> %shuf to <3 x i31>956 ret <3 x i31> %trunc957}958 959; TODO: The shuffle extends the length of the input vector. Should we shrink this?960 961define <8 x i8> @wide_lengthening_splat(<4 x i16> %v) {962; CHECK-LABEL: @wide_lengthening_splat(963; CHECK-NEXT: [[TMP1:%.*]] = trunc <4 x i16> [[V:%.*]] to <4 x i8>964; CHECK-NEXT: [[TR:%.*]] = shufflevector <4 x i8> [[TMP1]], <4 x i8> poison, <8 x i32> zeroinitializer965; CHECK-NEXT: ret <8 x i8> [[TR]]966;967 %shuf = shufflevector <4 x i16> %v, <4 x i16> %v, <8 x i32> zeroinitializer968 %tr = trunc <8 x i16> %shuf to <8 x i8>969 ret <8 x i8> %tr970}971 972; This is a negative test, we expect the trunc to remain after the shuffle as it973; might not be beneficial to preform trunc on a wider type974define <4 x i8> @wide_shortening_splat(<8 x i16> %v) {975; CHECK-LABEL: @wide_shortening_splat(976; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <8 x i16> [[V:%.*]], <8 x i16> poison, <4 x i32> zeroinitializer977; CHECK-NEXT: [[TR:%.*]] = trunc <4 x i16> [[SHUF]] to <4 x i8>978; CHECK-NEXT: ret <4 x i8> [[TR]]979;980 %shuf = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> zeroinitializer981 %tr = trunc <4 x i16> %shuf to <4 x i8>982 ret <4 x i8> %tr983}984 985define <2 x i8> @narrow_add_vec_constant(<2 x i32> %x) {986; CHECK-LABEL: @narrow_add_vec_constant(987; CHECK-NEXT: [[TMP1:%.*]] = trunc <2 x i32> [[X:%.*]] to <2 x i8>988; CHECK-NEXT: [[TR:%.*]] = add <2 x i8> [[TMP1]], <i8 0, i8 127>989; CHECK-NEXT: ret <2 x i8> [[TR]]990;991 %add = add <2 x i32> %x, <i32 256, i32 -129>992 %tr = trunc <2 x i32> %add to <2 x i8>993 ret <2 x i8> %tr994}995 996define <2 x i8> @narrow_mul_vec_constant(<2 x i32> %x) {997; CHECK-LABEL: @narrow_mul_vec_constant(998; CHECK-NEXT: [[TMP1:%.*]] = trunc <2 x i32> [[X:%.*]] to <2 x i8>999; CHECK-NEXT: [[TR:%.*]] = mul <2 x i8> [[TMP1]], <i8 0, i8 127>1000; CHECK-NEXT: ret <2 x i8> [[TR]]1001;1002 %add = mul <2 x i32> %x, <i32 256, i32 -129>1003 %tr = trunc <2 x i32> %add to <2 x i8>1004 ret <2 x i8> %tr1005}1006 1007define <2 x i8> @narrow_sub_vec_constant(<2 x i32> %x) {1008; CHECK-LABEL: @narrow_sub_vec_constant(1009; CHECK-NEXT: [[TMP1:%.*]] = trunc <2 x i32> [[X:%.*]] to <2 x i8>1010; CHECK-NEXT: [[TR:%.*]] = sub <2 x i8> <i8 0, i8 127>, [[TMP1]]1011; CHECK-NEXT: ret <2 x i8> [[TR]]1012;1013 %sub = sub <2 x i32> <i32 256, i32 -129>, %x1014 %tr = trunc <2 x i32> %sub to <2 x i8>1015 ret <2 x i8> %tr1016}1017 1018; If the select is narrowed based on the target's datalayout, we allow more optimizations.1019 1020define i16 @PR44545(i32 %t0, i32 %data) {1021; CHECK-LABEL: @PR44545(1022; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[DATA:%.*]], 01023; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[T0:%.*]] to i161024; CHECK-NEXT: [[SUB:%.*]] = select i1 [[ISZERO]], i16 -1, i16 [[TMP1]]1025; CHECK-NEXT: ret i16 [[SUB]]1026;1027 %t1 = add nuw nsw i32 %t0, 11028 %iszero = icmp eq i32 %data, 01029 %ffs = select i1 %iszero, i32 0, i32 %t11030 %cast = trunc i32 %ffs to i161031 %sub = add nsw i16 %cast, -11032 ret i16 %sub1033}1034 1035; Make sure that SimplifyDemandedBits drops the nowrap flags1036define i8 @drop_nsw_trunc(i16 %x, i16 %y) {1037; CHECK-LABEL: @drop_nsw_trunc(1038; CHECK-NEXT: [[AND2:%.*]] = and i16 [[X:%.*]], [[Y:%.*]]1039; CHECK-NEXT: [[RES:%.*]] = trunc i16 [[AND2]] to i81040; CHECK-NEXT: ret i8 [[RES]]1041;1042 %and = and i16 %x, 2551043 %and2 = and i16 %and, %y1044 %res = trunc nsw i16 %and2 to i81045 ret i8 %res1046}1047 1048define i8 @drop_nuw_trunc(i16 %x, i16 %y) {1049; CHECK-LABEL: @drop_nuw_trunc(1050; CHECK-NEXT: [[AND2:%.*]] = and i16 [[X:%.*]], [[Y:%.*]]1051; CHECK-NEXT: [[RES:%.*]] = trunc i16 [[AND2]] to i81052; CHECK-NEXT: ret i8 [[RES]]1053;1054 %and = and i16 %x, 2551055 %and2 = and i16 %and, %y1056 %res = trunc nuw i16 %and2 to i81057 ret i8 %res1058}1059 1060define i8 @drop_both_trunc(i16 %x, i16 %y) {1061; CHECK-LABEL: @drop_both_trunc(1062; CHECK-NEXT: [[AND2:%.*]] = and i16 [[X:%.*]], [[Y:%.*]]1063; CHECK-NEXT: [[RES:%.*]] = trunc i16 [[AND2]] to i81064; CHECK-NEXT: ret i8 [[RES]]1065;1066 %and = and i16 %x, 2551067 %and2 = and i16 %and, %y1068 %res = trunc nuw nsw i16 %and2 to i81069 ret i8 %res1070}1071 1072define i1 @trunc_xor(i8 %x, i8 %y) {1073; CHECK-LABEL: @trunc_xor(1074; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[X:%.*]], [[Y:%.*]]1075; CHECK-NEXT: [[R:%.*]] = trunc i8 [[XOR]] to i11076; CHECK-NEXT: ret i1 [[R]]1077;1078 %xor = xor i8 %x, %y1079 %r = trunc i8 %xor to i11080 ret i1 %r1081}1082 1083define i1 @trunc_nuw_xor(i8 %x, i8 %y) {1084; CHECK-LABEL: @trunc_nuw_xor(1085; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[X:%.*]], [[Y:%.*]]1086; CHECK-NEXT: ret i1 [[R]]1087;1088 %xor = xor i8 %x, %y1089 %r = trunc nuw i8 %xor to i11090 ret i1 %r1091}1092 1093define i1 @trunc_nsw_xor(i8 %x, i8 %y) {1094; CHECK-LABEL: @trunc_nsw_xor(1095; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[X:%.*]], [[Y:%.*]]1096; CHECK-NEXT: ret i1 [[R]]1097;1098 %xor = xor i8 %x, %y1099 %r = trunc nsw i8 %xor to i11100 ret i1 %r1101}1102 1103define <2 x i1> @trunc_nuw_xor_vector(<2 x i8> %x, <2 x i8> %y) {1104; CHECK-LABEL: @trunc_nuw_xor_vector(1105; CHECK-NEXT: [[R:%.*]] = icmp ne <2 x i8> [[X:%.*]], [[Y:%.*]]1106; CHECK-NEXT: ret <2 x i1> [[R]]1107;1108 %xor = xor <2 x i8> %x, %y1109 %r = trunc nuw <2 x i8> %xor to <2 x i1>1110 ret <2 x i1> %r1111}1112 1113define void @pr95547(i32 %x) {1114; CHECK-LABEL: @pr95547(1115; CHECK-NEXT: [[X_TRUNC:%.*]] = trunc i32 [[X:%.*]] to i161116; CHECK-NEXT: [[DIV:%.*]] = udiv i16 11, [[X_TRUNC]]1117; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X]], 2561118; CHECK-NEXT: br i1 [[CMP]], label [[LOOP:%.*]], label [[EXIT:%.*]]1119; CHECK: loop:1120; CHECK-NEXT: [[TRUNC:%.*]] = trunc nuw nsw i16 [[DIV]] to i81121; CHECK-NEXT: call void @use.i8(i8 [[TRUNC]])1122; CHECK-NEXT: br label [[LOOP]]1123; CHECK: exit:1124; CHECK-NEXT: ret void1125;1126 %x.trunc = trunc i32 %x to i161127 %div = udiv i16 11, %x.trunc1128 %cmp = icmp ult i32 %x, 2561129 br i1 %cmp, label %loop, label %exit1130 1131loop:1132 ; The loop is just here to prevent sinking.1133 %trunc = trunc i16 %div to i81134 call void @use.i8(i8 %trunc)1135 br label %loop1136 1137exit:1138 ret void1139}1140 1141define i1 @trunc_nuw_i1_non_zero(i8 %1) {1142; CHECK-LABEL: @trunc_nuw_i1_non_zero(1143; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i8 [[TMP0:%.*]], 01144; CHECK-NEXT: tail call void @llvm.assume(i1 [[TMP2]])1145; CHECK-NEXT: ret i1 true1146;1147 %3 = icmp ne i8 %1, 01148 tail call void @llvm.assume(i1 %3)1149 %ret = trunc nuw i8 %1 to i11150 ret i1 %ret1151}1152 1153define i1 @neg_trunc_nuw_i1_maybe_zero(i8 %1) {1154; CHECK-LABEL: @neg_trunc_nuw_i1_maybe_zero(1155; CHECK-NEXT: [[RET:%.*]] = trunc nuw i8 [[TMP0:%.*]] to i11156; CHECK-NEXT: ret i1 [[RET]]1157;1158 %ret = trunc nuw i8 %1 to i11159 ret i1 %ret1160}1161 1162define i2 @neg_trunc_nuw_i2_non_zero(i8 %1) {1163; CHECK-LABEL: @neg_trunc_nuw_i2_non_zero(1164; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i8 [[TMP0:%.*]], 01165; CHECK-NEXT: tail call void @llvm.assume(i1 [[TMP2]])1166; CHECK-NEXT: [[RET:%.*]] = trunc nuw i8 [[TMP0]] to i21167; CHECK-NEXT: ret i2 [[RET]]1168;1169 %3 = icmp ne i8 %1, 01170 tail call void @llvm.assume(i1 %3)1171 %ret = trunc nuw i8 %1 to i21172 ret i2 %ret1173}1174 1175define i1 @neg_trunc_i1_non_zero(i8 %1) {1176; CHECK-LABEL: @neg_trunc_i1_non_zero(1177; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i8 [[TMP0:%.*]], 01178; CHECK-NEXT: tail call void @llvm.assume(i1 [[TMP2]])1179; CHECK-NEXT: [[RET:%.*]] = trunc i8 [[TMP0]] to i11180; CHECK-NEXT: ret i1 [[RET]]1181;1182 %3 = icmp ne i8 %1, 01183 tail call void @llvm.assume(i1 %3)1184 %ret = trunc i8 %1 to i11185 ret i1 %ret1186}1187 1188define i1 @trunc_nsw_i1_non_zero(i8 %1) {1189; CHECK-LABEL: @trunc_nsw_i1_non_zero(1190; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i8 [[TMP0:%.*]], 01191; CHECK-NEXT: tail call void @llvm.assume(i1 [[TMP2]])1192; CHECK-NEXT: ret i1 true1193;1194 %3 = icmp ne i8 %1, 01195 tail call void @llvm.assume(i1 %3)1196 %ret = trunc nsw i8 %1 to i11197 ret i1 %ret1198}1199 1200define i1 @neg_trunc_nsw_i1_maybe_zero(i8 %1) {1201; CHECK-LABEL: @neg_trunc_nsw_i1_maybe_zero(1202; CHECK-NEXT: [[RET:%.*]] = trunc nsw i8 [[TMP0:%.*]] to i11203; CHECK-NEXT: ret i1 [[RET]]1204;1205 %ret = trunc nsw i8 %1 to i11206 ret i1 %ret1207}1208 1209define i2 @neg_trunc_nsw_i2_non_zero(i8 %1) {1210; CHECK-LABEL: @neg_trunc_nsw_i2_non_zero(1211; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i8 [[TMP0:%.*]], 01212; CHECK-NEXT: tail call void @llvm.assume(i1 [[TMP2]])1213; CHECK-NEXT: [[RET:%.*]] = trunc nsw i8 [[TMP0]] to i21214; CHECK-NEXT: ret i2 [[RET]]1215;1216 %3 = icmp ne i8 %1, 01217 tail call void @llvm.assume(i1 %3)1218 %ret = trunc nsw i8 %1 to i21219 ret i2 %ret1220}1221