1588 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -passes=instcombine -S < %s | FileCheck %s3 4target datalayout = "e-m:e-i64:64-n8:16:32:64"5 6declare i32 @llvm.bswap.i32(i32)7declare i128 @llvm.bswap.i128(i128)8declare <2 x i64> @llvm.bswap.v2i64(<2 x i64>)9declare i32 @llvm.cttz.i32(i32, i1) nounwind readnone10declare i32 @llvm.ctlz.i32(i32, i1) nounwind readnone11declare i32 @llvm.ctpop.i32(i32) nounwind readnone12declare <2 x i8> @llvm.cttz.v2i8(<2 x i8>, i1) nounwind readnone13declare <2 x i8> @llvm.ctlz.v2i8(<2 x i8>, i1) nounwind readnone14declare <2 x i8> @llvm.ctpop.v2i8(<2 x i8>) nounwind readnone15 16declare void @use(i32)17declare void @usevec(<3 x i14>)18 19define i32 @lshr_ctlz_zero_is_not_undef(i32 %x) {20; CHECK-LABEL: @lshr_ctlz_zero_is_not_undef(21; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[X:%.*]], 022; CHECK-NEXT: [[SH:%.*]] = zext i1 [[TMP1]] to i3223; CHECK-NEXT: ret i32 [[SH]]24;25 %ct = call i32 @llvm.ctlz.i32(i32 %x, i1 false)26 %sh = lshr i32 %ct, 527 ret i32 %sh28}29 30define i32 @lshr_cttz_zero_is_not_undef(i32 %x) {31; CHECK-LABEL: @lshr_cttz_zero_is_not_undef(32; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[X:%.*]], 033; CHECK-NEXT: [[SH:%.*]] = zext i1 [[TMP1]] to i3234; CHECK-NEXT: ret i32 [[SH]]35;36 %ct = call i32 @llvm.cttz.i32(i32 %x, i1 false)37 %sh = lshr i32 %ct, 538 ret i32 %sh39}40 41define i32 @lshr_ctpop(i32 %x) {42; CHECK-LABEL: @lshr_ctpop(43; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[X:%.*]], -144; CHECK-NEXT: [[SH:%.*]] = zext i1 [[TMP1]] to i3245; CHECK-NEXT: ret i32 [[SH]]46;47 %ct = call i32 @llvm.ctpop.i32(i32 %x)48 %sh = lshr i32 %ct, 549 ret i32 %sh50}51 52define <2 x i8> @lshr_ctlz_zero_is_not_undef_splat_vec(<2 x i8> %x) {53; CHECK-LABEL: @lshr_ctlz_zero_is_not_undef_splat_vec(54; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i8> [[X:%.*]], zeroinitializer55; CHECK-NEXT: [[SH:%.*]] = zext <2 x i1> [[TMP1]] to <2 x i8>56; CHECK-NEXT: ret <2 x i8> [[SH]]57;58 %ct = call <2 x i8> @llvm.ctlz.v2i8(<2 x i8> %x, i1 false)59 %sh = lshr <2 x i8> %ct, <i8 3, i8 3>60 ret <2 x i8> %sh61}62 63define <2 x i8> @lshr_cttz_zero_is_not_undef_splat_vec(<2 x i8> %x) {64; CHECK-LABEL: @lshr_cttz_zero_is_not_undef_splat_vec(65; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i8> [[X:%.*]], zeroinitializer66; CHECK-NEXT: [[SH:%.*]] = zext <2 x i1> [[TMP1]] to <2 x i8>67; CHECK-NEXT: ret <2 x i8> [[SH]]68;69 %ct = call <2 x i8> @llvm.cttz.v2i8(<2 x i8> %x, i1 false)70 %sh = lshr <2 x i8> %ct, <i8 3, i8 3>71 ret <2 x i8> %sh72}73 74define <2 x i8> @lshr_ctpop_splat_vec(<2 x i8> %x) {75; CHECK-LABEL: @lshr_ctpop_splat_vec(76; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i8> [[X:%.*]], splat (i8 -1)77; CHECK-NEXT: [[SH:%.*]] = zext <2 x i1> [[TMP1]] to <2 x i8>78; CHECK-NEXT: ret <2 x i8> [[SH]]79;80 %ct = call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)81 %sh = lshr <2 x i8> %ct, <i8 3, i8 3>82 ret <2 x i8> %sh83}84 85define i32 @lshr_ctlz_zero_is_undef(i32 %x) {86; CHECK-LABEL: @lshr_ctlz_zero_is_undef(87; CHECK-NEXT: ret i32 088;89 %ct = call i32 @llvm.ctlz.i32(i32 %x, i1 true)90 %sh = lshr i32 %ct, 591 ret i32 %sh92}93 94define i32 @lshr_cttz_zero_is_undef(i32 %x) {95; CHECK-LABEL: @lshr_cttz_zero_is_undef(96; CHECK-NEXT: ret i32 097;98 %ct = call i32 @llvm.cttz.i32(i32 %x, i1 true)99 %sh = lshr i32 %ct, 5100 ret i32 %sh101}102 103define <2 x i8> @lshr_ctlz_zero_is_undef_splat_vec(<2 x i8> %x) {104; CHECK-LABEL: @lshr_ctlz_zero_is_undef_splat_vec(105; CHECK-NEXT: ret <2 x i8> zeroinitializer106;107 %ct = call <2 x i8> @llvm.ctlz.v2i8(<2 x i8> %x, i1 true)108 %sh = lshr <2 x i8> %ct, <i8 3, i8 3>109 ret <2 x i8> %sh110}111 112define i8 @lshr_ctlz_zero_is_undef_vec(<2 x i8> %x) {113; CHECK-LABEL: @lshr_ctlz_zero_is_undef_vec(114; CHECK-NEXT: ret i8 0115;116 %ct = call <2 x i8> @llvm.ctlz.v2i8(<2 x i8> %x, i1 true)117 %sh = lshr <2 x i8> %ct, <i8 3, i8 0>118 %ex = extractelement <2 x i8> %sh, i32 0119 ret i8 %ex120}121 122define <2 x i8> @lshr_cttz_zero_is_undef_splat_vec(<2 x i8> %x) {123; CHECK-LABEL: @lshr_cttz_zero_is_undef_splat_vec(124; CHECK-NEXT: ret <2 x i8> zeroinitializer125;126 %ct = call <2 x i8> @llvm.cttz.v2i8(<2 x i8> %x, i1 true)127 %sh = lshr <2 x i8> %ct, <i8 3, i8 3>128 ret <2 x i8> %sh129}130 131define i8 @lshr_cttz_zero_is_undef_vec(<2 x i8> %x) {132; CHECK-LABEL: @lshr_cttz_zero_is_undef_vec(133; CHECK-NEXT: ret i8 0134;135 %ct = call <2 x i8> @llvm.cttz.v2i8(<2 x i8> %x, i1 true)136 %sh = lshr <2 x i8> %ct, <i8 3, i8 0>137 %ex = extractelement <2 x i8> %sh, i32 0138 ret i8 %ex139}140 141 142define i8 @lshr_exact(i8 %x) {143; CHECK-LABEL: @lshr_exact(144; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[X:%.*]], 1145; CHECK-NEXT: [[LSHR:%.*]] = and i8 [[TMP1]], 63146; CHECK-NEXT: ret i8 [[LSHR]]147;148 %shl = shl i8 %x, 2149 %add = add i8 %shl, 4150 %lshr = lshr i8 %add, 2151 ret i8 %lshr152}153 154define <2 x i8> @lshr_exact_splat_vec(<2 x i8> %x) {155; CHECK-LABEL: @lshr_exact_splat_vec(156; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i8> [[X:%.*]], splat (i8 1)157; CHECK-NEXT: [[LSHR:%.*]] = and <2 x i8> [[TMP1]], splat (i8 63)158; CHECK-NEXT: ret <2 x i8> [[LSHR]]159;160 %shl = shl <2 x i8> %x, <i8 2, i8 2>161 %add = add <2 x i8> %shl, <i8 4, i8 4>162 %lshr = lshr <2 x i8> %add, <i8 2, i8 2>163 ret <2 x i8> %lshr164}165 166define <2 x i8> @lshr_exact_splat_vec_nuw(<2 x i8> %x) {167; CHECK-LABEL: @lshr_exact_splat_vec_nuw(168; CHECK-NEXT: [[LSHR:%.*]] = add nuw <2 x i8> [[X:%.*]], splat (i8 1)169; CHECK-NEXT: ret <2 x i8> [[LSHR]]170;171 %shl = shl nuw <2 x i8> %x, <i8 2, i8 2>172 %add = add nuw <2 x i8> %shl, <i8 4, i8 4>173 %lshr = lshr <2 x i8> %add, <i8 2, i8 2>174 ret <2 x i8> %lshr175}176 177define i8 @shl_add(i8 %x, i8 %y) {178; CHECK-LABEL: @shl_add(179; CHECK-NEXT: [[TMP1:%.*]] = lshr i8 [[Y:%.*]], 2180; CHECK-NEXT: [[TMP2:%.*]] = add i8 [[TMP1]], [[X:%.*]]181; CHECK-NEXT: [[R:%.*]] = and i8 [[TMP2]], 63182; CHECK-NEXT: ret i8 [[R]]183;184 %l = shl i8 %x, 2185 %a = add i8 %l, %y186 %r = lshr i8 %a, 2187 ret i8 %r188}189 190define <2 x i8> @shl_add_commute_vec(<2 x i8> %x, <2 x i8> %py) {191; CHECK-LABEL: @shl_add_commute_vec(192; CHECK-NEXT: [[Y:%.*]] = mul <2 x i8> [[PY:%.*]], [[PY]]193; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i8> [[Y]], splat (i8 3)194; CHECK-NEXT: [[TMP2:%.*]] = add <2 x i8> [[TMP1]], [[X:%.*]]195; CHECK-NEXT: [[R:%.*]] = and <2 x i8> [[TMP2]], splat (i8 31)196; CHECK-NEXT: ret <2 x i8> [[R]]197;198 %y = mul <2 x i8> %py, %py ; thwart complexity-based canonicalization199 %l = shl <2 x i8> %x, <i8 3, i8 3>200 %a = add <2 x i8> %y, %l201 %r = lshr <2 x i8> %a, <i8 3, i8 3>202 ret <2 x i8> %r203}204 205define i32 @shl_add_use1(i32 %x, i32 %y) {206; CHECK-LABEL: @shl_add_use1(207; CHECK-NEXT: [[L:%.*]] = shl i32 [[X:%.*]], 2208; CHECK-NEXT: call void @use(i32 [[L]])209; CHECK-NEXT: [[A:%.*]] = add i32 [[L]], [[Y:%.*]]210; CHECK-NEXT: [[R:%.*]] = lshr i32 [[A]], 2211; CHECK-NEXT: ret i32 [[R]]212;213 %l = shl i32 %x, 2214 call void @use(i32 %l)215 %a = add i32 %l, %y216 %r = lshr i32 %a, 2217 ret i32 %r218}219 220define i32 @shl_add_use2(i32 %x, i32 %y) {221; CHECK-LABEL: @shl_add_use2(222; CHECK-NEXT: [[L:%.*]] = shl i32 [[X:%.*]], 2223; CHECK-NEXT: [[A:%.*]] = add i32 [[L]], [[Y:%.*]]224; CHECK-NEXT: call void @use(i32 [[A]])225; CHECK-NEXT: [[R:%.*]] = lshr i32 [[A]], 2226; CHECK-NEXT: ret i32 [[R]]227;228 %l = shl i32 %x, 2229 %a = add i32 %l, %y230 call void @use(i32 %a)231 %r = lshr i32 %a, 2232 ret i32 %r233}234 235define i16 @bool_zext(i1 %x) {236; CHECK-LABEL: @bool_zext(237; CHECK-NEXT: [[HIBIT:%.*]] = zext i1 [[X:%.*]] to i16238; CHECK-NEXT: ret i16 [[HIBIT]]239;240 %sext = sext i1 %x to i16241 %hibit = lshr i16 %sext, 15242 ret i16 %hibit243}244 245define i32 @bool_zext_use(i1 %x) {246; CHECK-LABEL: @bool_zext_use(247; CHECK-NEXT: [[SEXT:%.*]] = sext i1 [[X:%.*]] to i32248; CHECK-NEXT: call void @use(i32 [[SEXT]])249; CHECK-NEXT: [[HIBIT:%.*]] = zext i1 [[X]] to i32250; CHECK-NEXT: ret i32 [[HIBIT]]251;252 %sext = sext i1 %x to i32253 call void @use(i32 %sext)254 %hibit = lshr i32 %sext, 31255 ret i32 %hibit256}257 258define <2 x i8> @bool_zext_splat(<2 x i1> %x) {259; CHECK-LABEL: @bool_zext_splat(260; CHECK-NEXT: [[HIBIT:%.*]] = zext <2 x i1> [[X:%.*]] to <2 x i8>261; CHECK-NEXT: ret <2 x i8> [[HIBIT]]262;263 %sext = sext <2 x i1> %x to <2 x i8>264 %hibit = lshr <2 x i8> %sext, <i8 7, i8 7>265 ret <2 x i8> %hibit266}267 268define i32 @smear_sign_and_widen(i8 %x) {269; CHECK-LABEL: @smear_sign_and_widen(270; CHECK-NEXT: [[TMP1:%.*]] = ashr i8 [[X:%.*]], 7271; CHECK-NEXT: [[HIBIT:%.*]] = zext i8 [[TMP1]] to i32272; CHECK-NEXT: ret i32 [[HIBIT]]273;274 %sext = sext i8 %x to i32275 %hibit = lshr i32 %sext, 24276 ret i32 %hibit277}278 279define i16 @smear_sign_and_widen_should_not_change_type(i4 %x) {280; CHECK-LABEL: @smear_sign_and_widen_should_not_change_type(281; CHECK-NEXT: [[SEXT:%.*]] = sext i4 [[X:%.*]] to i16282; CHECK-NEXT: [[HIBIT:%.*]] = lshr i16 [[SEXT]], 12283; CHECK-NEXT: ret i16 [[HIBIT]]284;285 %sext = sext i4 %x to i16286 %hibit = lshr i16 %sext, 12287 ret i16 %hibit288}289 290define <2 x i8> @smear_sign_and_widen_splat(<2 x i6> %x) {291; CHECK-LABEL: @smear_sign_and_widen_splat(292; CHECK-NEXT: [[TMP1:%.*]] = ashr <2 x i6> [[X:%.*]], splat (i6 2)293; CHECK-NEXT: [[HIBIT:%.*]] = zext <2 x i6> [[TMP1]] to <2 x i8>294; CHECK-NEXT: ret <2 x i8> [[HIBIT]]295;296 %sext = sext <2 x i6> %x to <2 x i8>297 %hibit = lshr <2 x i8> %sext, <i8 2, i8 2>298 ret <2 x i8> %hibit299}300 301define i18 @fake_sext(i3 %x) {302; CHECK-LABEL: @fake_sext(303; CHECK-NEXT: [[TMP1:%.*]] = lshr i3 [[X:%.*]], 2304; CHECK-NEXT: [[SH:%.*]] = zext nneg i3 [[TMP1]] to i18305; CHECK-NEXT: ret i18 [[SH]]306;307 %sext = sext i3 %x to i18308 %sh = lshr i18 %sext, 17309 ret i18 %sh310}311 312; Avoid the transform if it would change the shift from a legal to illegal type.313 314define i32 @fake_sext_but_should_not_change_type(i3 %x) {315; CHECK-LABEL: @fake_sext_but_should_not_change_type(316; CHECK-NEXT: [[SEXT:%.*]] = sext i3 [[X:%.*]] to i32317; CHECK-NEXT: [[SH:%.*]] = lshr i32 [[SEXT]], 31318; CHECK-NEXT: ret i32 [[SH]]319;320 %sext = sext i3 %x to i32321 %sh = lshr i32 %sext, 31322 ret i32 %sh323}324 325define <2 x i8> @fake_sext_splat(<2 x i3> %x) {326; CHECK-LABEL: @fake_sext_splat(327; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i3> [[X:%.*]], splat (i3 2)328; CHECK-NEXT: [[SH:%.*]] = zext nneg <2 x i3> [[TMP1]] to <2 x i8>329; CHECK-NEXT: ret <2 x i8> [[SH]]330;331 %sext = sext <2 x i3> %x to <2 x i8>332 %sh = lshr <2 x i8> %sext, <i8 7, i8 7>333 ret <2 x i8> %sh334}335 336; Use a narrow shift: lshr (zext iM X to iN), C --> zext (lshr X, C) to iN337 338define <2 x i32> @narrow_lshr_constant(<2 x i8> %x, <2 x i8> %y) {339; CHECK-LABEL: @narrow_lshr_constant(340; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i8> [[X:%.*]], splat (i8 3)341; CHECK-NEXT: [[SH:%.*]] = zext nneg <2 x i8> [[TMP1]] to <2 x i32>342; CHECK-NEXT: ret <2 x i32> [[SH]]343;344 %zx = zext <2 x i8> %x to <2 x i32>345 %sh = lshr <2 x i32> %zx, <i32 3, i32 3>346 ret <2 x i32> %sh347}348 349define i32 @mul_splat_fold(i32 %x) {350; CHECK-LABEL: @mul_splat_fold(351; CHECK-NEXT: ret i32 [[X:%.*]]352;353 %m = mul nuw i32 %x, 65537354 %t = lshr i32 %m, 16355 ret i32 %t356}357 358; Vector type, extra use, weird types are all ok.359 360define <3 x i14> @mul_splat_fold_vec(<3 x i14> %x) {361; CHECK-LABEL: @mul_splat_fold_vec(362; CHECK-NEXT: [[M:%.*]] = mul nuw <3 x i14> [[X:%.*]], splat (i14 129)363; CHECK-NEXT: call void @usevec(<3 x i14> [[M]])364; CHECK-NEXT: ret <3 x i14> [[X]]365;366 %m = mul nuw <3 x i14> %x, <i14 129, i14 129, i14 129>367 call void @usevec(<3 x i14> %m)368 %t = lshr <3 x i14> %m, <i14 7, i14 7, i14 7>369 ret <3 x i14> %t370}371 372define i32 @shl_add_lshr_flag_preservation(i32 %x, i32 %c, i32 %y) {373; CHECK-LABEL: @shl_add_lshr_flag_preservation(374; CHECK-NEXT: [[TMP1:%.*]] = lshr exact i32 [[Y:%.*]], [[C:%.*]]375; CHECK-NEXT: [[LSHR:%.*]] = add nuw nsw i32 [[TMP1]], [[X:%.*]]376; CHECK-NEXT: ret i32 [[LSHR]]377;378 %shl = shl nuw i32 %x, %c379 %add = add nuw nsw i32 %shl, %y380 %lshr = lshr exact i32 %add, %c381 ret i32 %lshr382}383 384define i32 @shl_add_lshr(i32 %x, i32 %c, i32 %y) {385; CHECK-LABEL: @shl_add_lshr(386; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], [[C:%.*]]387; CHECK-NEXT: [[LSHR:%.*]] = add nuw i32 [[TMP1]], [[X:%.*]]388; CHECK-NEXT: ret i32 [[LSHR]]389;390 %shl = shl nuw i32 %x, %c391 %add = add nuw i32 %shl, %y392 %lshr = lshr i32 %add, %c393 ret i32 %lshr394}395 396define i32 @shl_add_lshr_comm(i32 %x, i32 %c, i32 %y) {397; CHECK-LABEL: @shl_add_lshr_comm(398; CHECK-NEXT: [[Y2:%.*]] = mul i32 [[Y:%.*]], [[Y]]399; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y2]], [[C:%.*]]400; CHECK-NEXT: [[LSHR:%.*]] = add nuw i32 [[TMP1]], [[X:%.*]]401; CHECK-NEXT: ret i32 [[LSHR]]402;403 %shl = shl nuw i32 %x, %c404 %y2 = mul i32 %y, %y ; thwart complexity-based canonicalization405 %add = add nuw i32 %y2, %shl406 %lshr = lshr i32 %add, %c407 ret i32 %lshr408}409 410; Negative test411 412define i32 @shl_add_lshr_no_nuw(i32 %x, i32 %c, i32 %y) {413; CHECK-LABEL: @shl_add_lshr_no_nuw(414; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]]415; CHECK-NEXT: [[ADD:%.*]] = add i32 [[SHL]], [[Y:%.*]]416; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[ADD]], [[C]]417; CHECK-NEXT: ret i32 [[LSHR]]418;419 %shl = shl nuw i32 %x, %c420 %add = add i32 %shl, %y421 %lshr = lshr i32 %add, %c422 ret i32 %lshr423}424 425; Negative test426 427define i32 @shl_sub_lshr_not_exact(i32 %x, i32 %c, i32 %y) {428; CHECK-LABEL: @shl_sub_lshr_not_exact(429; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]]430; CHECK-NEXT: [[SUB:%.*]] = sub nuw i32 [[SHL]], [[Y:%.*]]431; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[SUB]], [[C]]432; CHECK-NEXT: ret i32 [[LSHR]]433;434 %shl = shl nuw i32 %x, %c435 %sub = sub nuw i32 %shl, %y436 %lshr = lshr i32 %sub, %c437 ret i32 %lshr438}439 440; Negative test441 442define i32 @shl_sub_lshr_no_nuw(i32 %x, i32 %c, i32 %y) {443; CHECK-LABEL: @shl_sub_lshr_no_nuw(444; CHECK-NEXT: [[SHL:%.*]] = shl nsw i32 [[X:%.*]], [[C:%.*]]445; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[SHL]], [[Y:%.*]]446; CHECK-NEXT: [[LSHR:%.*]] = lshr exact i32 [[SUB]], [[C]]447; CHECK-NEXT: ret i32 [[LSHR]]448;449 %shl = shl nsw i32 %x, %c450 %sub = sub nsw i32 %shl, %y451 %lshr = lshr exact i32 %sub, %c452 ret i32 %lshr453}454 455define i32 @shl_sub_lshr(i32 %x, i32 %c, i32 %y) {456; CHECK-LABEL: @shl_sub_lshr(457; CHECK-NEXT: [[TMP1:%.*]] = lshr exact i32 [[Y:%.*]], [[C:%.*]]458; CHECK-NEXT: [[LSHR:%.*]] = sub nuw nsw i32 [[X:%.*]], [[TMP1]]459; CHECK-NEXT: ret i32 [[LSHR]]460;461 %shl = shl nuw i32 %x, %c462 %sub = sub nuw nsw i32 %shl, %y463 %lshr = lshr exact i32 %sub, %c464 ret i32 %lshr465}466 467define i32 @shl_sub_lshr_reverse(i32 %x, i32 %c, i32 %y) {468; CHECK-LABEL: @shl_sub_lshr_reverse(469; CHECK-NEXT: [[TMP1:%.*]] = lshr exact i32 [[Y:%.*]], [[C:%.*]]470; CHECK-NEXT: [[LSHR:%.*]] = sub nuw nsw i32 [[TMP1]], [[X:%.*]]471; CHECK-NEXT: ret i32 [[LSHR]]472;473 %shl = shl nuw i32 %x, %c474 %sub = sub nuw nsw i32 %y, %shl475 %lshr = lshr exact i32 %sub, %c476 ret i32 %lshr477}478 479define i32 @shl_sub_lshr_reverse_no_nsw(i32 %x, i32 %c, i32 %y) {480; CHECK-LABEL: @shl_sub_lshr_reverse_no_nsw(481; CHECK-NEXT: [[TMP1:%.*]] = lshr exact i32 [[Y:%.*]], [[C:%.*]]482; CHECK-NEXT: [[LSHR:%.*]] = sub nuw i32 [[TMP1]], [[X:%.*]]483; CHECK-NEXT: ret i32 [[LSHR]]484;485 %shl = shl nuw i32 %x, %c486 %sub = sub nuw i32 %y, %shl487 %lshr = lshr exact i32 %sub, %c488 ret i32 %lshr489}490 491define i32 @shl_sub_lshr_reverse_nsw_on_op1(i32 %x, i32 %c, i32 %y) {492; CHECK-LABEL: @shl_sub_lshr_reverse_nsw_on_op1(493; CHECK-NEXT: [[TMP1:%.*]] = lshr exact i32 [[Y:%.*]], [[C:%.*]]494; CHECK-NEXT: [[LSHR:%.*]] = sub nuw i32 [[TMP1]], [[X:%.*]]495; CHECK-NEXT: ret i32 [[LSHR]]496;497 %shl = shl nuw nsw i32 %x, %c498 %sub = sub nuw i32 %y, %shl499 %lshr = lshr exact i32 %sub, %c500 ret i32 %lshr501}502 503; Negative test504 505define i32 @shl_sub_lshr_reverse_no_exact(i32 %x, i32 %c, i32 %y) {506; CHECK-LABEL: @shl_sub_lshr_reverse_no_exact(507; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]]508; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i32 [[Y:%.*]], [[SHL]]509; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[SUB]], [[C]]510; CHECK-NEXT: ret i32 [[LSHR]]511;512 %shl = shl nuw i32 %x, %c513 %sub = sub nuw nsw i32 %y, %shl514 %lshr = lshr i32 %sub, %c515 ret i32 %lshr516}517 518; Negative test519 520define i32 @shl_sub_lshr_reverse_multiuse(i32 %x, i32 %c, i32 %y) {521; CHECK-LABEL: @shl_sub_lshr_reverse_multiuse(522; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]]523; CHECK-NEXT: [[SUB:%.*]] = sub nuw i32 [[Y:%.*]], [[SHL]]524; CHECK-NEXT: call void @use(i32 [[SUB]])525; CHECK-NEXT: [[LSHR:%.*]] = lshr exact i32 [[SUB]], [[C]]526; CHECK-NEXT: ret i32 [[LSHR]]527;528 %shl = shl nuw i32 %x, %c529 %sub = sub nuw i32 %y, %shl530 call void @use(i32 %sub)531 %lshr = lshr exact i32 %sub, %c532 ret i32 %lshr533}534 535define i32 @shl_sub_lshr_reverse_multiuse2(i32 %x, i32 %c, i32 %y) {536; CHECK-LABEL: @shl_sub_lshr_reverse_multiuse2(537; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]]538; CHECK-NEXT: call void @use(i32 [[SHL]])539; CHECK-NEXT: [[TMP1:%.*]] = lshr exact i32 [[Y:%.*]], [[C]]540; CHECK-NEXT: [[LSHR:%.*]] = sub nuw i32 [[TMP1]], [[X]]541; CHECK-NEXT: ret i32 [[LSHR]]542;543 %shl = shl nuw i32 %x, %c544 call void @use(i32 %shl)545 %sub = sub nuw i32 %y, %shl546 %lshr = lshr exact i32 %sub, %c547 ret i32 %lshr548}549 550; Negative test551 552define i32 @shl_sub_lshr_reverse_no_nuw(i32 %x, i32 %c, i32 %y) {553; CHECK-LABEL: @shl_sub_lshr_reverse_no_nuw(554; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[X:%.*]], [[C:%.*]]555; CHECK-NEXT: [[SUB:%.*]] = sub nuw i32 [[Y:%.*]], [[SHL]]556; CHECK-NEXT: [[LSHR:%.*]] = lshr exact i32 [[SUB]], [[C]]557; CHECK-NEXT: ret i32 [[LSHR]]558;559 %shl = shl i32 %x, %c560 %sub = sub nuw i32 %y, %shl561 %lshr = lshr exact i32 %sub, %c562 ret i32 %lshr563}564 565; Negative test566 567define i32 @shl_sub_lshr_reverse_no_nsw_2(i32 %x, i32 %c, i32 %y) {568; CHECK-LABEL: @shl_sub_lshr_reverse_no_nsw_2(569; CHECK-NEXT: [[SHL:%.*]] = shl nuw nsw i32 [[X:%.*]], [[C:%.*]]570; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[Y:%.*]], [[SHL]]571; CHECK-NEXT: [[LSHR:%.*]] = lshr exact i32 [[SUB]], [[C]]572; CHECK-NEXT: ret i32 [[LSHR]]573;574 %shl = shl nuw nsw i32 %x, %c575 %sub = sub i32 %y, %shl576 %lshr = lshr exact i32 %sub, %c577 ret i32 %lshr578}579 580define i32 @shl_or_lshr(i32 %x, i32 %c, i32 %y) {581; CHECK-LABEL: @shl_or_lshr(582; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], [[C:%.*]]583; CHECK-NEXT: [[LSHR:%.*]] = or i32 [[TMP1]], [[X:%.*]]584; CHECK-NEXT: ret i32 [[LSHR]]585;586 %shl = shl nuw i32 %x, %c587 %or = or i32 %shl, %y588 %lshr = lshr i32 %or, %c589 ret i32 %lshr590}591 592define i32 @shl_or_disjoint_lshr(i32 %x, i32 %c, i32 %y) {593; CHECK-LABEL: @shl_or_disjoint_lshr(594; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], [[C:%.*]]595; CHECK-NEXT: [[LSHR:%.*]] = or disjoint i32 [[TMP1]], [[X:%.*]]596; CHECK-NEXT: ret i32 [[LSHR]]597;598 %shl = shl nuw i32 %x, %c599 %or = or disjoint i32 %shl, %y600 %lshr = lshr i32 %or, %c601 ret i32 %lshr602}603 604define i32 @shl_or_lshr_comm(i32 %x, i32 %c, i32 %y) {605; CHECK-LABEL: @shl_or_lshr_comm(606; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], [[C:%.*]]607; CHECK-NEXT: [[LSHR:%.*]] = or i32 [[TMP1]], [[X:%.*]]608; CHECK-NEXT: ret i32 [[LSHR]]609;610 %shl = shl nuw i32 %x, %c611 %or = or i32 %y, %shl612 %lshr = lshr i32 %or, %c613 ret i32 %lshr614}615 616define i32 @shl_or_disjoint_lshr_comm(i32 %x, i32 %c, i32 %y) {617; CHECK-LABEL: @shl_or_disjoint_lshr_comm(618; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], [[C:%.*]]619; CHECK-NEXT: [[LSHR:%.*]] = or disjoint i32 [[TMP1]], [[X:%.*]]620; CHECK-NEXT: ret i32 [[LSHR]]621;622 %shl = shl nuw i32 %x, %c623 %or = or disjoint i32 %y, %shl624 %lshr = lshr i32 %or, %c625 ret i32 %lshr626}627 628define i32 @shl_xor_lshr(i32 %x, i32 %c, i32 %y) {629; CHECK-LABEL: @shl_xor_lshr(630; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], [[C:%.*]]631; CHECK-NEXT: [[LSHR:%.*]] = xor i32 [[TMP1]], [[X:%.*]]632; CHECK-NEXT: ret i32 [[LSHR]]633;634 %shl = shl nuw i32 %x, %c635 %xor = xor i32 %shl, %y636 %lshr = lshr i32 %xor, %c637 ret i32 %lshr638}639 640define i32 @shl_xor_lshr_comm(i32 %x, i32 %c, i32 %y) {641; CHECK-LABEL: @shl_xor_lshr_comm(642; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], [[C:%.*]]643; CHECK-NEXT: [[LSHR:%.*]] = xor i32 [[TMP1]], [[X:%.*]]644; CHECK-NEXT: ret i32 [[LSHR]]645;646 %shl = shl nuw i32 %x, %c647 %xor = xor i32 %y, %shl648 %lshr = lshr i32 %xor, %c649 ret i32 %lshr650}651 652define i32 @shl_and_lshr(i32 %x, i32 %c, i32 %y) {653; CHECK-LABEL: @shl_and_lshr(654; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], [[C:%.*]]655; CHECK-NEXT: [[LSHR:%.*]] = and i32 [[TMP1]], [[X:%.*]]656; CHECK-NEXT: ret i32 [[LSHR]]657;658 %shl = shl nuw i32 %x, %c659 %and = and i32 %shl, %y660 %lshr = lshr i32 %and, %c661 ret i32 %lshr662}663 664define i32 @shl_and_lshr_comm(i32 %x, i32 %c, i32 %y) {665; CHECK-LABEL: @shl_and_lshr_comm(666; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], [[C:%.*]]667; CHECK-NEXT: [[LSHR:%.*]] = and i32 [[TMP1]], [[X:%.*]]668; CHECK-NEXT: ret i32 [[LSHR]]669;670 %shl = shl nuw i32 %x, %c671 %and = and i32 %y, %shl672 %lshr = lshr i32 %and, %c673 ret i32 %lshr674}675 676define i32 @shl_lshr_and_exact(i32 %x, i32 %c, i32 %y) {677; CHECK-LABEL: @shl_lshr_and_exact(678; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], [[C:%.*]]679; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[X:%.*]]680; CHECK-NEXT: ret i32 [[TMP2]]681;682 %2 = shl nuw i32 %x, %c683 %3 = and i32 %2, %y684 %4 = lshr exact i32 %3, %c685 ret i32 %4686}687 688; Negative test689 690define i32 @shl_add_lshr_neg(i32 %x, i32 %y, i32 %z) {691; CHECK-LABEL: @shl_add_lshr_neg(692; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[Y:%.*]]693; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[SHL]], [[Z:%.*]]694; CHECK-NEXT: [[RES:%.*]] = lshr exact i32 [[ADD]], [[Z]]695; CHECK-NEXT: ret i32 [[RES]]696;697 %shl = shl nuw i32 %x, %y698 %add = add nuw nsw i32 %shl, %z699 %res = lshr exact i32 %add, %z700 ret i32 %res701}702 703define i32 @mul_splat_fold_wrong_mul_const(i32 %x) {704; CHECK-LABEL: @mul_splat_fold_wrong_mul_const(705; CHECK-NEXT: [[M:%.*]] = mul nuw i32 [[X:%.*]], 65538706; CHECK-NEXT: [[T:%.*]] = lshr i32 [[M]], 16707; CHECK-NEXT: ret i32 [[T]]708;709 %m = mul nuw i32 %x, 65538710 %t = lshr i32 %m, 16711 ret i32 %t712}713 714; Negative test715 716define i32 @shl_add_lshr_multiuse(i32 %x, i32 %y, i32 %z) {717; CHECK-LABEL: @shl_add_lshr_multiuse(718; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[Y:%.*]]719; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[SHL]], [[Z:%.*]]720; CHECK-NEXT: call void @use(i32 [[ADD]])721; CHECK-NEXT: [[RES:%.*]] = lshr exact i32 [[ADD]], [[Z]]722; CHECK-NEXT: ret i32 [[RES]]723;724 %shl = shl nuw i32 %x, %y725 %add = add nuw nsw i32 %shl, %z726 call void @use (i32 %add)727 %res = lshr exact i32 %add, %z728 ret i32 %res729}730 731define i32 @mul_splat_fold_wrong_lshr_const(i32 %x) {732; CHECK-LABEL: @mul_splat_fold_wrong_lshr_const(733; CHECK-NEXT: [[M:%.*]] = mul nuw i32 [[X:%.*]], 65537734; CHECK-NEXT: [[T:%.*]] = lshr i32 [[M]], 15735; CHECK-NEXT: ret i32 [[T]]736;737 %m = mul nuw i32 %x, 65537738 %t = lshr i32 %m, 15739 ret i32 %t740}741 742define i32 @mul_splat_fold_no_nuw(i32 %x) {743; CHECK-LABEL: @mul_splat_fold_no_nuw(744; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 16745; CHECK-NEXT: [[T:%.*]] = add nsw i32 [[X]], [[TMP1]]746; CHECK-NEXT: ret i32 [[T]]747;748 %m = mul nsw i32 %x, 65537749 %t = lshr i32 %m, 16750 ret i32 %t751}752 753; Negative test754 755define i32 @mul_splat_fold_no_flags(i32 %x) {756; CHECK-LABEL: @mul_splat_fold_no_flags(757; CHECK-NEXT: [[M:%.*]] = mul i32 [[X:%.*]], 65537758; CHECK-NEXT: [[T:%.*]] = lshr i32 [[M]], 16759; CHECK-NEXT: ret i32 [[T]]760;761 %m = mul i32 %x, 65537762 %t = lshr i32 %m, 16763 ret i32 %t764}765 766; Negative test (but simplifies before we reach the mul_splat transform)- need more than 2 bits767 768define i2 @mul_splat_fold_too_narrow(i2 %x) {769; CHECK-LABEL: @mul_splat_fold_too_narrow(770; CHECK-NEXT: ret i2 [[X:%.*]]771;772 %m = mul nuw i2 %x, 2773 %t = lshr i2 %m, 1774 ret i2 %t775}776 777define i32 @negative_and_odd(i32 %x) {778; CHECK-LABEL: @negative_and_odd(779; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 31780; CHECK-NEXT: [[R:%.*]] = and i32 [[TMP1]], [[X]]781; CHECK-NEXT: ret i32 [[R]]782;783 %s = srem i32 %x, 2784 %r = lshr i32 %s, 31785 ret i32 %r786}787 788define <2 x i7> @negative_and_odd_vec(<2 x i7> %x) {789; CHECK-LABEL: @negative_and_odd_vec(790; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i7> [[X:%.*]], splat (i7 6)791; CHECK-NEXT: [[R:%.*]] = and <2 x i7> [[TMP1]], [[X]]792; CHECK-NEXT: ret <2 x i7> [[R]]793;794 %s = srem <2 x i7> %x, <i7 2, i7 2>795 %r = lshr <2 x i7> %s, <i7 6, i7 6>796 ret <2 x i7> %r797}798 799; Negative test - this is still worth trying to avoid srem?800 801define i32 @negative_and_odd_uses(i32 %x, ptr %p) {802; CHECK-LABEL: @negative_and_odd_uses(803; CHECK-NEXT: [[S:%.*]] = srem i32 [[X:%.*]], 2804; CHECK-NEXT: store i32 [[S]], ptr [[P:%.*]], align 4805; CHECK-NEXT: [[R:%.*]] = lshr i32 [[S]], 31806; CHECK-NEXT: ret i32 [[R]]807;808 %s = srem i32 %x, 2809 store i32 %s, ptr %p810 %r = lshr i32 %s, 31811 ret i32 %r812}813 814; Negative test - wrong divisor815 816define i32 @srem3(i32 %x) {817; CHECK-LABEL: @srem3(818; CHECK-NEXT: [[S:%.*]] = srem i32 [[X:%.*]], 3819; CHECK-NEXT: [[R:%.*]] = lshr i32 [[S]], 31820; CHECK-NEXT: ret i32 [[R]]821;822 %s = srem i32 %x, 3823 %r = lshr i32 %s, 31824 ret i32 %r825}826 827; Negative test - wrong shift amount828 829define i32 @srem2_lshr30(i32 %x) {830; CHECK-LABEL: @srem2_lshr30(831; CHECK-NEXT: [[S:%.*]] = srem i32 [[X:%.*]], 2832; CHECK-NEXT: [[R:%.*]] = lshr i32 [[S]], 30833; CHECK-NEXT: ret i32 [[R]]834;835 %s = srem i32 %x, 2836 %r = lshr i32 %s, 30837 ret i32 %r838}839 840define i12 @trunc_sandwich(i32 %x) {841; CHECK-LABEL: @trunc_sandwich(842; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i32 [[X:%.*]], 30843; CHECK-NEXT: [[R1:%.*]] = trunc nuw nsw i32 [[SUM_SHIFT]] to i12844; CHECK-NEXT: ret i12 [[R1]]845;846 %sh = lshr i32 %x, 28847 %tr = trunc i32 %sh to i12848 %r = lshr i12 %tr, 2849 ret i12 %r850}851 852define <2 x i12> @trunc_sandwich_splat_vec(<2 x i32> %x) {853; CHECK-LABEL: @trunc_sandwich_splat_vec(854; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr <2 x i32> [[X:%.*]], splat (i32 30)855; CHECK-NEXT: [[R1:%.*]] = trunc nuw nsw <2 x i32> [[SUM_SHIFT]] to <2 x i12>856; CHECK-NEXT: ret <2 x i12> [[R1]]857;858 %sh = lshr <2 x i32> %x, <i32 22, i32 22>859 %tr = trunc <2 x i32> %sh to <2 x i12>860 %r = lshr <2 x i12> %tr, <i12 8, i12 8>861 ret <2 x i12> %r862}863 864define i12 @trunc_sandwich_min_shift1(i32 %x) {865; CHECK-LABEL: @trunc_sandwich_min_shift1(866; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i32 [[X:%.*]], 21867; CHECK-NEXT: [[R1:%.*]] = trunc nuw nsw i32 [[SUM_SHIFT]] to i12868; CHECK-NEXT: ret i12 [[R1]]869;870 %sh = lshr i32 %x, 20871 %tr = trunc i32 %sh to i12872 %r = lshr i12 %tr, 1873 ret i12 %r874}875 876define i12 @trunc_sandwich_small_shift1(i32 %x) {877; CHECK-LABEL: @trunc_sandwich_small_shift1(878; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i32 [[X:%.*]], 20879; CHECK-NEXT: [[R1:%.*]] = trunc nuw i32 [[SUM_SHIFT]] to i12880; CHECK-NEXT: [[R:%.*]] = and i12 [[R1]], 2047881; CHECK-NEXT: ret i12 [[R]]882;883 %sh = lshr i32 %x, 19884 %tr = trunc i32 %sh to i12885 %r = lshr i12 %tr, 1886 ret i12 %r887}888 889define i12 @trunc_sandwich_max_sum_shift(i32 %x) {890; CHECK-LABEL: @trunc_sandwich_max_sum_shift(891; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i32 [[X:%.*]], 31892; CHECK-NEXT: [[R1:%.*]] = trunc nuw nsw i32 [[SUM_SHIFT]] to i12893; CHECK-NEXT: ret i12 [[R1]]894;895 %sh = lshr i32 %x, 20896 %tr = trunc i32 %sh to i12897 %r = lshr i12 %tr, 11898 ret i12 %r899}900 901define i12 @trunc_sandwich_max_sum_shift2(i32 %x) {902; CHECK-LABEL: @trunc_sandwich_max_sum_shift2(903; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i32 [[X:%.*]], 31904; CHECK-NEXT: [[R1:%.*]] = trunc nuw nsw i32 [[SUM_SHIFT]] to i12905; CHECK-NEXT: ret i12 [[R1]]906;907 %sh = lshr i32 %x, 30908 %tr = trunc i32 %sh to i12909 %r = lshr i12 %tr, 1910 ret i12 %r911}912 913define i12 @trunc_sandwich_big_sum_shift1(i32 %x) {914; CHECK-LABEL: @trunc_sandwich_big_sum_shift1(915; CHECK-NEXT: ret i12 0916;917 %sh = lshr i32 %x, 21918 %tr = trunc i32 %sh to i12919 %r = lshr i12 %tr, 11920 ret i12 %r921}922 923define i12 @trunc_sandwich_big_sum_shift2(i32 %x) {924; CHECK-LABEL: @trunc_sandwich_big_sum_shift2(925; CHECK-NEXT: ret i12 0926;927 %sh = lshr i32 %x, 31928 %tr = trunc i32 %sh to i12929 %r = lshr i12 %tr, 1930 ret i12 %r931}932 933define i12 @trunc_sandwich_use1(i32 %x) {934; CHECK-LABEL: @trunc_sandwich_use1(935; CHECK-NEXT: [[SH:%.*]] = lshr i32 [[X:%.*]], 28936; CHECK-NEXT: call void @use(i32 [[SH]])937; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i32 [[X]], 30938; CHECK-NEXT: [[R1:%.*]] = trunc nuw nsw i32 [[SUM_SHIFT]] to i12939; CHECK-NEXT: ret i12 [[R1]]940;941 %sh = lshr i32 %x, 28942 call void @use(i32 %sh)943 %tr = trunc i32 %sh to i12944 %r = lshr i12 %tr, 2945 ret i12 %r946}947 948define <3 x i9> @trunc_sandwich_splat_vec_use1(<3 x i14> %x) {949; CHECK-LABEL: @trunc_sandwich_splat_vec_use1(950; CHECK-NEXT: [[SH:%.*]] = lshr <3 x i14> [[X:%.*]], splat (i14 6)951; CHECK-NEXT: call void @usevec(<3 x i14> [[SH]])952; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr <3 x i14> [[X]], splat (i14 11)953; CHECK-NEXT: [[R1:%.*]] = trunc nuw nsw <3 x i14> [[SUM_SHIFT]] to <3 x i9>954; CHECK-NEXT: ret <3 x i9> [[R1]]955;956 %sh = lshr <3 x i14> %x, <i14 6, i14 6, i14 6>957 call void @usevec(<3 x i14> %sh)958 %tr = trunc <3 x i14> %sh to <3 x i9>959 %r = lshr <3 x i9> %tr, <i9 5, i9 5, i9 5>960 ret <3 x i9> %r961}962 963define i12 @trunc_sandwich_min_shift1_use1(i32 %x) {964; CHECK-LABEL: @trunc_sandwich_min_shift1_use1(965; CHECK-NEXT: [[SH:%.*]] = lshr i32 [[X:%.*]], 20966; CHECK-NEXT: call void @use(i32 [[SH]])967; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i32 [[X]], 21968; CHECK-NEXT: [[R1:%.*]] = trunc nuw nsw i32 [[SUM_SHIFT]] to i12969; CHECK-NEXT: ret i12 [[R1]]970;971 %sh = lshr i32 %x, 20972 call void @use(i32 %sh)973 %tr = trunc i32 %sh to i12974 %r = lshr i12 %tr, 1975 ret i12 %r976}977 978; negative test - trunc is bigger than first shift979 980define i12 @trunc_sandwich_small_shift1_use1(i32 %x) {981; CHECK-LABEL: @trunc_sandwich_small_shift1_use1(982; CHECK-NEXT: [[SH:%.*]] = lshr i32 [[X:%.*]], 19983; CHECK-NEXT: call void @use(i32 [[SH]])984; CHECK-NEXT: [[TR:%.*]] = trunc i32 [[SH]] to i12985; CHECK-NEXT: [[R:%.*]] = lshr i12 [[TR]], 1986; CHECK-NEXT: ret i12 [[R]]987;988 %sh = lshr i32 %x, 19989 call void @use(i32 %sh)990 %tr = trunc i32 %sh to i12991 %r = lshr i12 %tr, 1992 ret i12 %r993}994 995define i12 @trunc_sandwich_max_sum_shift_use1(i32 %x) {996; CHECK-LABEL: @trunc_sandwich_max_sum_shift_use1(997; CHECK-NEXT: [[SH:%.*]] = lshr i32 [[X:%.*]], 20998; CHECK-NEXT: call void @use(i32 [[SH]])999; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i32 [[X]], 311000; CHECK-NEXT: [[R1:%.*]] = trunc nuw nsw i32 [[SUM_SHIFT]] to i121001; CHECK-NEXT: ret i12 [[R1]]1002;1003 %sh = lshr i32 %x, 201004 call void @use(i32 %sh)1005 %tr = trunc i32 %sh to i121006 %r = lshr i12 %tr, 111007 ret i12 %r1008}1009 1010define i12 @trunc_sandwich_max_sum_shift2_use1(i32 %x) {1011; CHECK-LABEL: @trunc_sandwich_max_sum_shift2_use1(1012; CHECK-NEXT: [[SH:%.*]] = lshr i32 [[X:%.*]], 301013; CHECK-NEXT: call void @use(i32 [[SH]])1014; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i32 [[X]], 311015; CHECK-NEXT: [[R1:%.*]] = trunc nuw nsw i32 [[SUM_SHIFT]] to i121016; CHECK-NEXT: ret i12 [[R1]]1017;1018 %sh = lshr i32 %x, 301019 call void @use(i32 %sh)1020 %tr = trunc i32 %sh to i121021 %r = lshr i12 %tr, 11022 ret i12 %r1023}1024 1025; negative test - but overshift is simplified to zero by another fold1026 1027define i12 @trunc_sandwich_big_sum_shift1_use1(i32 %x) {1028; CHECK-LABEL: @trunc_sandwich_big_sum_shift1_use1(1029; CHECK-NEXT: [[SH:%.*]] = lshr i32 [[X:%.*]], 211030; CHECK-NEXT: call void @use(i32 [[SH]])1031; CHECK-NEXT: ret i12 01032;1033 %sh = lshr i32 %x, 211034 call void @use(i32 %sh)1035 %tr = trunc i32 %sh to i121036 %r = lshr i12 %tr, 111037 ret i12 %r1038}1039 1040; negative test - but overshift is simplified to zero by another fold1041 1042define i12 @trunc_sandwich_big_sum_shift2_use1(i32 %x) {1043; CHECK-LABEL: @trunc_sandwich_big_sum_shift2_use1(1044; CHECK-NEXT: [[SH:%.*]] = lshr i32 [[X:%.*]], 311045; CHECK-NEXT: call void @use(i32 [[SH]])1046; CHECK-NEXT: ret i12 01047;1048 %sh = lshr i32 %x, 311049 call void @use(i32 %sh)1050 %tr = trunc i32 %sh to i121051 %r = lshr i12 %tr, 11052 ret i12 %r1053}1054 1055define i16 @lshr_sext_i1_to_i16(i1 %a) {1056; CHECK-LABEL: @lshr_sext_i1_to_i16(1057; CHECK-NEXT: [[LSHR:%.*]] = select i1 [[A:%.*]], i16 4095, i16 01058; CHECK-NEXT: ret i16 [[LSHR]]1059;1060 %sext = sext i1 %a to i161061 %lshr = lshr i16 %sext, 41062 ret i16 %lshr1063}1064 1065define i128 @lshr_sext_i1_to_i128(i1 %a) {1066; CHECK-LABEL: @lshr_sext_i1_to_i128(1067; CHECK-NEXT: [[LSHR:%.*]] = select i1 [[A:%.*]], i128 77371252455336267181195263, i128 01068; CHECK-NEXT: ret i128 [[LSHR]]1069;1070 %sext = sext i1 %a to i1281071 %lshr = lshr i128 %sext, 421072 ret i128 %lshr1073}1074 1075define i32 @lshr_sext_i1_to_i32_use(i1 %a) {1076; CHECK-LABEL: @lshr_sext_i1_to_i32_use(1077; CHECK-NEXT: [[SEXT:%.*]] = sext i1 [[A:%.*]] to i321078; CHECK-NEXT: call void @use(i32 [[SEXT]])1079; CHECK-NEXT: [[LSHR:%.*]] = select i1 [[A]], i32 262143, i32 01080; CHECK-NEXT: ret i32 [[LSHR]]1081;1082 %sext = sext i1 %a to i321083 call void @use(i32 %sext)1084 %lshr = lshr i32 %sext, 141085 ret i32 %lshr1086}1087 1088define <3 x i14> @lshr_sext_i1_to_i14_splat_vec_use1(<3 x i1> %a) {1089; CHECK-LABEL: @lshr_sext_i1_to_i14_splat_vec_use1(1090; CHECK-NEXT: [[SEXT:%.*]] = sext <3 x i1> [[A:%.*]] to <3 x i14>1091; CHECK-NEXT: call void @usevec(<3 x i14> [[SEXT]])1092; CHECK-NEXT: [[LSHR:%.*]] = select <3 x i1> [[A]], <3 x i14> splat (i14 1023), <3 x i14> zeroinitializer1093; CHECK-NEXT: ret <3 x i14> [[LSHR]]1094;1095 %sext = sext <3 x i1> %a to <3 x i14>1096 call void @usevec(<3 x i14> %sext)1097 %lshr = lshr <3 x i14> %sext, <i14 4, i14 4, i14 4>1098 ret <3 x i14> %lshr1099}1100 1101define i1 @icmp_ule(i32 %x, i32 %y) {1102; CHECK-LABEL: @icmp_ule(1103; CHECK-NEXT: ret i1 true1104;1105 %x.shifted = lshr i32 %x, %y1106 %cmp = icmp ule i32 %x.shifted, %x1107 ret i1 %cmp1108}1109 1110define i1 @icmp_ult(i32 %x, i32 %y) {1111; CHECK-LABEL: @icmp_ult(1112; CHECK-NEXT: [[X_SHIFTED:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]1113; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X_SHIFTED]], [[X]]1114; CHECK-NEXT: ret i1 [[CMP]]1115;1116 %x.shifted = lshr i32 %x, %y1117 %cmp = icmp ult i32 %x.shifted, %x1118 ret i1 %cmp1119}1120 1121define i1 @icmp_eq(i32 %x, i32 %y) {1122; CHECK-LABEL: @icmp_eq(1123; CHECK-NEXT: [[X_SHIFTED:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]1124; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X_SHIFTED]], [[X]]1125; CHECK-NEXT: ret i1 [[CMP]]1126;1127 %x.shifted = lshr i32 %x, %y1128 %cmp = icmp eq i32 %x.shifted, %x1129 ret i1 %cmp1130}1131 1132define i1 @icmp_ne(i32 %x, i32 %y) {1133; CHECK-LABEL: @icmp_ne(1134; CHECK-NEXT: [[X_SHIFTED:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]1135; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[X_SHIFTED]], [[X]]1136; CHECK-NEXT: ret i1 [[CMP]]1137;1138 %x.shifted = lshr i32 %x, %y1139 %cmp = icmp ne i32 %x.shifted, %x1140 ret i1 %cmp1141}1142 1143define i1 @icmp_ugt(i32 %x, i32 %y) {1144; CHECK-LABEL: @icmp_ugt(1145; CHECK-NEXT: ret i1 false1146;1147 %x.shifted = lshr i32 %x, %y1148 %cmp = icmp ugt i32 %x.shifted, %x1149 ret i1 %cmp1150}1151 1152define i1 @icmp_uge(i32 %x, i32 %y) {1153; CHECK-LABEL: @icmp_uge(1154; CHECK-NEXT: [[X_SHIFTED:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]1155; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[X_SHIFTED]], [[X]]1156; CHECK-NEXT: ret i1 [[CMP]]1157;1158 %x.shifted = lshr i32 %x, %y1159 %cmp = icmp uge i32 %x.shifted, %x1160 ret i1 %cmp1161}1162 1163define i1 @icmp_sle(i32 %x, i32 %y) {1164; CHECK-LABEL: @icmp_sle(1165; CHECK-NEXT: [[X_SHIFTED:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]1166; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[X_SHIFTED]], [[X]]1167; CHECK-NEXT: ret i1 [[CMP]]1168;1169 %x.shifted = lshr i32 %x, %y1170 %cmp = icmp sle i32 %x.shifted, %x1171 ret i1 %cmp1172}1173 1174define i1 @icmp_slt(i32 %x, i32 %y) {1175; CHECK-LABEL: @icmp_slt(1176; CHECK-NEXT: [[X_SHIFTED:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]1177; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X_SHIFTED]], [[X]]1178; CHECK-NEXT: ret i1 [[CMP]]1179;1180 %x.shifted = lshr i32 %x, %y1181 %cmp = icmp slt i32 %x.shifted, %x1182 ret i1 %cmp1183}1184 1185define i1 @icmp_sgt(i32 %x, i32 %y) {1186; CHECK-LABEL: @icmp_sgt(1187; CHECK-NEXT: [[X_SHIFTED:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]1188; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X_SHIFTED]], [[X]]1189; CHECK-NEXT: ret i1 [[CMP]]1190;1191 %x.shifted = lshr i32 %x, %y1192 %cmp = icmp sgt i32 %x.shifted, %x1193 ret i1 %cmp1194}1195 1196define i1 @icmp_sge(i32 %x, i32 %y) {1197; CHECK-LABEL: @icmp_sge(1198; CHECK-NEXT: [[X_SHIFTED:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]1199; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[X_SHIFTED]], [[X]]1200; CHECK-NEXT: ret i1 [[CMP]]1201;1202 %x.shifted = lshr i32 %x, %y1203 %cmp = icmp sge i32 %x.shifted, %x1204 ret i1 %cmp1205}1206 1207define i32 @narrow_bswap(i16 %x) {1208; CHECK-LABEL: @narrow_bswap(1209; CHECK-NEXT: [[TMP1:%.*]] = call i16 @llvm.bswap.i16(i16 [[X:%.*]])1210; CHECK-NEXT: [[S:%.*]] = zext i16 [[TMP1]] to i321211; CHECK-NEXT: ret i32 [[S]]1212;1213 %z = zext i16 %x to i321214 %b = call i32 @llvm.bswap.i32(i32 %z)1215 %s = lshr i32 %b, 161216 ret i32 %s1217}1218 1219define i128 @narrow_bswap_extra_wide(i16 %x) {1220; CHECK-LABEL: @narrow_bswap_extra_wide(1221; CHECK-NEXT: [[TMP1:%.*]] = call i16 @llvm.bswap.i16(i16 [[X:%.*]])1222; CHECK-NEXT: [[S:%.*]] = zext i16 [[TMP1]] to i1281223; CHECK-NEXT: ret i128 [[S]]1224;1225 %z = zext i16 %x to i1281226 %b = call i128 @llvm.bswap.i128(i128 %z)1227 %s = lshr i128 %b, 1121228 ret i128 %s1229}1230 1231define i32 @narrow_bswap_undershift(i16 %x) {1232; CHECK-LABEL: @narrow_bswap_undershift(1233; CHECK-NEXT: [[TMP1:%.*]] = call i16 @llvm.bswap.i16(i16 [[X:%.*]])1234; CHECK-NEXT: [[TMP2:%.*]] = zext i16 [[TMP1]] to i321235; CHECK-NEXT: [[S:%.*]] = shl nuw nsw i32 [[TMP2]], 71236; CHECK-NEXT: ret i32 [[S]]1237;1238 %z = zext i16 %x to i321239 %b = call i32 @llvm.bswap.i32(i32 %z)1240 %s = lshr i32 %b, 91241 ret i32 %s1242}1243 1244define <2 x i64> @narrow_bswap_splat(<2 x i16> %x) {1245; CHECK-LABEL: @narrow_bswap_splat(1246; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i16> @llvm.bswap.v2i16(<2 x i16> [[X:%.*]])1247; CHECK-NEXT: [[S:%.*]] = zext <2 x i16> [[TMP1]] to <2 x i64>1248; CHECK-NEXT: ret <2 x i64> [[S]]1249;1250 %z = zext <2 x i16> %x to <2 x i64>1251 %b = call <2 x i64> @llvm.bswap.v2i64(<2 x i64> %z)1252 %s = lshr <2 x i64> %b, <i64 48, i64 48>1253 ret <2 x i64> %s1254}1255 1256define <2 x i64> @narrow_bswap_splat_poison_elt(<2 x i16> %x) {1257; CHECK-LABEL: @narrow_bswap_splat_poison_elt(1258; CHECK-NEXT: [[Z:%.*]] = zext <2 x i16> [[X:%.*]] to <2 x i64>1259; CHECK-NEXT: [[B:%.*]] = call <2 x i64> @llvm.bswap.v2i64(<2 x i64> [[Z]])1260; CHECK-NEXT: [[S:%.*]] = lshr exact <2 x i64> [[B]], <i64 48, i64 poison>1261; CHECK-NEXT: ret <2 x i64> [[S]]1262;1263 %z = zext <2 x i16> %x to <2 x i64>1264 %b = call <2 x i64> @llvm.bswap.v2i64(<2 x i64> %z)1265 %s = lshr <2 x i64> %b, <i64 48, i64 poison>1266 ret <2 x i64> %s1267}1268 1269define <2 x i64> @narrow_bswap_overshift(<2 x i32> %x) {1270; CHECK-LABEL: @narrow_bswap_overshift(1271; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i32> @llvm.bswap.v2i32(<2 x i32> [[X:%.*]])1272; CHECK-NEXT: [[TMP2:%.*]] = lshr <2 x i32> [[TMP1]], splat (i32 16)1273; CHECK-NEXT: [[S:%.*]] = zext nneg <2 x i32> [[TMP2]] to <2 x i64>1274; CHECK-NEXT: ret <2 x i64> [[S]]1275;1276 %z = zext <2 x i32> %x to <2 x i64>1277 %b = call <2 x i64> @llvm.bswap.v2i64(<2 x i64> %z)1278 %s = lshr <2 x i64> %b, <i64 48, i64 48>1279 ret <2 x i64> %s1280}1281 1282define i128 @narrow_bswap_overshift2(i96 %x) {1283; CHECK-LABEL: @narrow_bswap_overshift2(1284; CHECK-NEXT: [[TMP1:%.*]] = call i96 @llvm.bswap.i96(i96 [[X:%.*]])1285; CHECK-NEXT: [[TMP2:%.*]] = lshr i96 [[TMP1]], 291286; CHECK-NEXT: [[S:%.*]] = zext nneg i96 [[TMP2]] to i1281287; CHECK-NEXT: ret i128 [[S]]1288;1289 %z = zext i96 %x to i1281290 %b = call i128 @llvm.bswap.i128(i128 %z)1291 %s = lshr i128 %b, 611292 ret i128 %s1293}1294 1295; negative test - can't make a bswap with an odd number of bytes1296 1297define i32 @not_narrow_bswap(i24 %x) {1298; CHECK-LABEL: @not_narrow_bswap(1299; CHECK-NEXT: [[Z:%.*]] = zext i24 [[X:%.*]] to i321300; CHECK-NEXT: [[B:%.*]] = call i32 @llvm.bswap.i32(i32 [[Z]])1301; CHECK-NEXT: [[R:%.*]] = lshr exact i32 [[B]], 81302; CHECK-NEXT: ret i32 [[R]]1303;1304 %z = zext i24 %x to i321305 %b = call i32 @llvm.bswap.i32(i32 %z)1306 %r = lshr i32 %b, 81307 ret i32 %r1308}1309 1310define i8 @not_signbit(i8 %x) {1311; CHECK-LABEL: @not_signbit(1312; CHECK-NEXT: [[ISNOTNEG:%.*]] = icmp sgt i8 [[X:%.*]], -11313; CHECK-NEXT: [[R:%.*]] = zext i1 [[ISNOTNEG]] to i81314; CHECK-NEXT: ret i8 [[R]]1315;1316 %a = xor i8 %x, -11317 %r = lshr i8 %a, 71318 ret i8 %r1319}1320 1321define <2 x i6> @not_signbit_vec(<2 x i6> %x) {1322; CHECK-LABEL: @not_signbit_vec(1323; CHECK-NEXT: [[ISNOTNEG:%.*]] = icmp sgt <2 x i6> [[X:%.*]], splat (i6 -1)1324; CHECK-NEXT: [[R:%.*]] = zext <2 x i1> [[ISNOTNEG]] to <2 x i6>1325; CHECK-NEXT: ret <2 x i6> [[R]]1326;1327 %a = xor <2 x i6> %x, <i6 -1, i6 poison>1328 %r = lshr <2 x i6> %a, <i6 5, i6 poison>1329 ret <2 x i6> %r1330}1331 1332define i8 @not_signbit_alt_xor(i8 %x) {1333; CHECK-LABEL: @not_signbit_alt_xor(1334; CHECK-NEXT: [[ISNOTNEG:%.*]] = icmp sgt i8 [[X:%.*]], -11335; CHECK-NEXT: [[R:%.*]] = zext i1 [[ISNOTNEG]] to i81336; CHECK-NEXT: ret i8 [[R]]1337;1338 %a = xor i8 %x, -21339 %r = lshr i8 %a, 71340 ret i8 %r1341}1342 1343define i8 @not_not_signbit(i8 %x) {1344; CHECK-LABEL: @not_not_signbit(1345; CHECK-NEXT: [[A:%.*]] = xor i8 [[X:%.*]], -11346; CHECK-NEXT: [[R:%.*]] = lshr i8 [[A]], 61347; CHECK-NEXT: ret i8 [[R]]1348;1349 %a = xor i8 %x, -11350 %r = lshr i8 %a, 61351 ret i8 %r1352}1353 1354define i32 @not_signbit_use(i32 %x) {1355; CHECK-LABEL: @not_signbit_use(1356; CHECK-NEXT: [[A:%.*]] = xor i32 [[X:%.*]], -11357; CHECK-NEXT: call void @use(i32 [[A]])1358; CHECK-NEXT: [[R:%.*]] = lshr i32 [[A]], 311359; CHECK-NEXT: ret i32 [[R]]1360;1361 %a = xor i32 %x, -11362 call void @use(i32 %a)1363 %r = lshr i32 %a, 311364 ret i32 %r1365}1366 1367define i32 @not_signbit_zext(i16 %x) {1368; CHECK-LABEL: @not_signbit_zext(1369; CHECK-NEXT: [[ISNOTNEG:%.*]] = icmp sgt i16 [[X:%.*]], -11370; CHECK-NEXT: [[R2:%.*]] = zext i1 [[ISNOTNEG]] to i321371; CHECK-NEXT: ret i32 [[R2]]1372;1373 %a = xor i16 %x, -11374 %r = lshr i16 %a, 151375 %r2 = zext i16 %r to i321376 ret i32 %r21377}1378 1379define i8 @not_signbit_trunc(i16 %x) {1380; CHECK-LABEL: @not_signbit_trunc(1381; CHECK-NEXT: [[ISNOTNEG:%.*]] = icmp sgt i16 [[X:%.*]], -11382; CHECK-NEXT: [[R2:%.*]] = zext i1 [[ISNOTNEG]] to i81383; CHECK-NEXT: ret i8 [[R2]]1384;1385 %a = xor i16 %x, -11386 %r = lshr i16 %a, 151387 %r2 = trunc i16 %r to i81388 ret i8 %r21389}1390 1391define i2 @bool_add_lshr(i1 %a, i1 %b) {1392; CHECK-LABEL: @bool_add_lshr(1393; CHECK-NEXT: [[LSHR1:%.*]] = and i1 [[A:%.*]], [[B:%.*]]1394; CHECK-NEXT: [[LSHR:%.*]] = zext i1 [[LSHR1]] to i21395; CHECK-NEXT: ret i2 [[LSHR]]1396;1397 %zext.a = zext i1 %a to i21398 %zext.b = zext i1 %b to i21399 %add = add i2 %zext.a, %zext.b1400 %lshr = lshr i2 %add, 11401 ret i2 %lshr1402}1403 1404; negative test - need bools1405 1406define i4 @not_bool_add_lshr(i2 %a, i2 %b) {1407; CHECK-LABEL: @not_bool_add_lshr(1408; CHECK-NEXT: [[TMP1:%.*]] = xor i2 [[A:%.*]], -11409; CHECK-NEXT: [[ADD_NARROWED_OVERFLOW:%.*]] = icmp ugt i2 [[B:%.*]], [[TMP1]]1410; CHECK-NEXT: [[LSHR:%.*]] = zext i1 [[ADD_NARROWED_OVERFLOW]] to i41411; CHECK-NEXT: ret i4 [[LSHR]]1412;1413 %zext.a = zext i2 %a to i41414 %zext.b = zext i2 %b to i41415 %add = add i4 %zext.a, %zext.b1416 %lshr = lshr i4 %add, 21417 ret i4 %lshr1418}1419 1420; TODO: This could be sext(and a, b).1421 1422define i2 @bool_add_ashr(i1 %a, i1 %b) {1423; CHECK-LABEL: @bool_add_ashr(1424; CHECK-NEXT: [[ZEXT_A:%.*]] = zext i1 [[A:%.*]] to i21425; CHECK-NEXT: [[ZEXT_B:%.*]] = zext i1 [[B:%.*]] to i21426; CHECK-NEXT: [[ADD:%.*]] = add nuw i2 [[ZEXT_A]], [[ZEXT_B]]1427; CHECK-NEXT: [[ASHR:%.*]] = ashr i2 [[ADD]], 11428; CHECK-NEXT: ret i2 [[ASHR]]1429;1430 %zext.a = zext i1 %a to i21431 %zext.b = zext i1 %b to i21432 %add = add i2 %zext.a, %zext.b1433 %ashr = ashr i2 %add, 11434 ret i2 %ashr1435}1436 1437define <2 x i8> @bool_add_lshr_vec(<2 x i1> %a, <2 x i1> %b) {1438; CHECK-LABEL: @bool_add_lshr_vec(1439; CHECK-NEXT: [[LSHR1:%.*]] = and <2 x i1> [[A:%.*]], [[B:%.*]]1440; CHECK-NEXT: [[LSHR:%.*]] = zext <2 x i1> [[LSHR1]] to <2 x i8>1441; CHECK-NEXT: ret <2 x i8> [[LSHR]]1442;1443 %zext.a = zext <2 x i1> %a to <2 x i8>1444 %zext.b = zext <2 x i1> %b to <2 x i8>1445 %add = add <2 x i8> %zext.a, %zext.b1446 %lshr = lshr <2 x i8> %add, <i8 1, i8 1>1447 ret <2 x i8> %lshr1448}1449 1450define i32 @bool_add_lshr_uses(i1 %a, i1 %b) {1451; CHECK-LABEL: @bool_add_lshr_uses(1452; CHECK-NEXT: [[ZEXT_A:%.*]] = zext i1 [[A:%.*]] to i321453; CHECK-NEXT: call void @use(i32 [[ZEXT_A]])1454; CHECK-NEXT: [[ZEXT_B:%.*]] = zext i1 [[B:%.*]] to i321455; CHECK-NEXT: call void @use(i32 [[ZEXT_B]])1456; CHECK-NEXT: [[LSHR:%.*]] = and i32 [[ZEXT_A]], [[ZEXT_B]]1457; CHECK-NEXT: ret i32 [[LSHR]]1458;1459 %zext.a = zext i1 %a to i321460 call void @use(i32 %zext.a)1461 %zext.b = zext i1 %b to i321462 call void @use(i32 %zext.b)1463 %add = add i32 %zext.a, %zext.b1464 %lshr = lshr i32 %add, 11465 ret i32 %lshr1466}1467 1468define i32 @bool_add_lshr_uses2(i1 %a, i1 %b) {1469; CHECK-LABEL: @bool_add_lshr_uses2(1470; CHECK-NEXT: [[ZEXT_A:%.*]] = zext i1 [[A:%.*]] to i321471; CHECK-NEXT: [[ZEXT_B:%.*]] = zext i1 [[B:%.*]] to i321472; CHECK-NEXT: call void @use(i32 [[ZEXT_B]])1473; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[ZEXT_A]], [[ZEXT_B]]1474; CHECK-NEXT: call void @use(i32 [[ADD]])1475; CHECK-NEXT: [[LSHR:%.*]] = and i32 [[ZEXT_A]], [[ZEXT_B]]1476; CHECK-NEXT: ret i32 [[LSHR]]1477;1478 %zext.a = zext i1 %a to i321479 %zext.b = zext i1 %b to i321480 call void @use(i32 %zext.b)1481 %add = add i32 %zext.a, %zext.b1482 call void @use(i32 %add)1483 %lshr = lshr i32 %add, 11484 ret i32 %lshr1485}1486 1487; negative test - too many extra uses1488 1489define i32 @bool_add_lshr_uses3(i1 %a, i1 %b) {1490; CHECK-LABEL: @bool_add_lshr_uses3(1491; CHECK-NEXT: [[ZEXT_A:%.*]] = zext i1 [[A:%.*]] to i321492; CHECK-NEXT: call void @use(i32 [[ZEXT_A]])1493; CHECK-NEXT: [[ZEXT_B:%.*]] = zext i1 [[B:%.*]] to i321494; CHECK-NEXT: call void @use(i32 [[ZEXT_B]])1495; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[ZEXT_A]], [[ZEXT_B]]1496; CHECK-NEXT: call void @use(i32 [[ADD]])1497; CHECK-NEXT: [[LSHR:%.*]] = and i32 [[ZEXT_A]], [[ZEXT_B]]1498; CHECK-NEXT: ret i32 [[LSHR]]1499;1500 %zext.a = zext i1 %a to i321501 call void @use(i32 %zext.a)1502 %zext.b = zext i1 %b to i321503 call void @use(i32 %zext.b)1504 %add = add i32 %zext.a, %zext.b1505 call void @use(i32 %add)1506 %lshr = lshr i32 %add, 11507 ret i32 %lshr1508}1509 1510; negative test1511 1512define <2 x i8> @bool_add_lshr_vec_wrong_shift_amt(<2 x i1> %a, <2 x i1> %b) {1513; CHECK-LABEL: @bool_add_lshr_vec_wrong_shift_amt(1514; CHECK-NEXT: [[ZEXT_A:%.*]] = zext <2 x i1> [[A:%.*]] to <2 x i8>1515; CHECK-NEXT: [[ZEXT_B:%.*]] = zext <2 x i1> [[B:%.*]] to <2 x i8>1516; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw <2 x i8> [[ZEXT_A]], [[ZEXT_B]]1517; CHECK-NEXT: [[LSHR:%.*]] = lshr <2 x i8> [[ADD]], <i8 1, i8 2>1518; CHECK-NEXT: ret <2 x i8> [[LSHR]]1519;1520 %zext.a = zext <2 x i1> %a to <2 x i8>1521 %zext.b = zext <2 x i1> %b to <2 x i8>1522 %add = add <2 x i8> %zext.a, %zext.b1523 %lshr = lshr <2 x i8> %add, <i8 1, i8 2>1524 ret <2 x i8> %lshr1525}1526 1527define i32 @lowbits_of_lshr_mul(i64 %x) {1528; CHECK-LABEL: @lowbits_of_lshr_mul(1529; CHECK-NEXT: entry:1530; CHECK-NEXT: [[TMP0:%.*]] = trunc i64 [[X:%.*]] to i321531; CHECK-NEXT: [[CONV:%.*]] = mul i32 [[TMP0]], 151532; CHECK-NEXT: ret i32 [[CONV]]1533;1534entry:1535 %mul = mul i64 %x, 644245094401536 %shift = lshr i64 %mul, 321537 %conv = trunc i64 %shift to i321538 ret i32 %conv1539}1540 1541define i32 @lowbits_of_lshr_mul_mask(i32 %x) {1542; CHECK-LABEL: @lowbits_of_lshr_mul_mask(1543; CHECK-NEXT: entry:1544; CHECK-NEXT: [[TMP0:%.*]] = mul i32 [[X:%.*]], 16001545; CHECK-NEXT: [[CONV:%.*]] = and i32 [[TMP0]], 327041546; CHECK-NEXT: ret i32 [[CONV]]1547;1548entry:1549 %mul = mul i32 %x, 1048576001550 %shift = lshr i32 %mul, 161551 %conv = and i32 %shift, 327671552 ret i32 %conv1553}1554 1555; Negative tests1556 1557define i32 @lowbits_of_lshr_mul_mask_multiuse(i32 %x) {1558; CHECK-LABEL: @lowbits_of_lshr_mul_mask_multiuse(1559; CHECK-NEXT: entry:1560; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X:%.*]], 1048576001561; CHECK-NEXT: call void @use(i32 [[MUL]])1562; CHECK-NEXT: [[SHIFT:%.*]] = lshr exact i32 [[MUL]], 161563; CHECK-NEXT: [[CONV:%.*]] = and i32 [[SHIFT]], 327041564; CHECK-NEXT: ret i32 [[CONV]]1565;1566entry:1567 %mul = mul i32 %x, 1048576001568 call void @use(i32 %mul)1569 %shift = lshr i32 %mul, 161570 %conv = and i32 %shift, 327671571 ret i32 %conv1572}1573 1574define i32 @lowbits_of_lshr_mul_mask_indivisible(i32 %x) {1575; CHECK-LABEL: @lowbits_of_lshr_mul_mask_indivisible(1576; CHECK-NEXT: entry:1577; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X:%.*]], 256001578; CHECK-NEXT: [[SHIFT:%.*]] = lshr i32 [[MUL]], 161579; CHECK-NEXT: [[CONV:%.*]] = and i32 [[SHIFT]], 327671580; CHECK-NEXT: ret i32 [[CONV]]1581;1582entry:1583 %mul = mul i32 %x, 256001584 %shift = lshr i32 %mul, 161585 %conv = and i32 %shift, 327671586 ret i32 %conv1587}1588