diff options
Diffstat (limited to 'test/Transforms/InstCombine/shift.ll')
-rw-r--r-- | test/Transforms/InstCombine/shift.ll | 253 |
1 files changed, 230 insertions, 23 deletions
diff --git a/test/Transforms/InstCombine/shift.ll b/test/Transforms/InstCombine/shift.ll index c046a72110c2..60ba35557f70 100644 --- a/test/Transforms/InstCombine/shift.ll +++ b/test/Transforms/InstCombine/shift.ll @@ -1,6 +1,4 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; This test makes sure that these instructions are properly eliminated. -; ; RUN: opt < %s -instcombine -S | FileCheck %s define i32 @test1(i32 %A) { @@ -161,9 +159,8 @@ define i8 @test9(i8 %A) { ret i8 %C } -;; This transformation is deferred to DAGCombine: ;; (A >> 7) << 7 === A & 128 -;; The shl may be valuable to scalar evolution. + define i8 @test10(i8 %A) { ; CHECK-LABEL: @test10( ; CHECK-NEXT: [[B:%.*]] = and i8 %A, -128 @@ -454,9 +451,8 @@ define i32 @test25(i32 %tmp.2, i32 %AA) { define <2 x i32> @test25_vector(<2 x i32> %tmp.2, <2 x i32> %AA) { ; CHECK-LABEL: @test25_vector( -; CHECK-NEXT: [[TMP_3:%.*]] = lshr <2 x i32> %tmp.2, <i32 17, i32 17> -; CHECK-NEXT: [[TMP_51:%.*]] = shl <2 x i32> [[TMP_3]], <i32 17, i32 17> -; CHECK-NEXT: [[X2:%.*]] = add <2 x i32> [[TMP_51]], %AA +; CHECK-NEXT: [[TMP_3:%.*]] = and <2 x i32> %tmp.2, <i32 -131072, i32 -131072> +; CHECK-NEXT: [[X2:%.*]] = add <2 x i32> [[TMP_3]], %AA ; CHECK-NEXT: [[TMP_6:%.*]] = and <2 x i32> [[X2]], <i32 -131072, i32 -131072> ; CHECK-NEXT: ret <2 x i32> [[TMP_6]] ; @@ -640,30 +636,25 @@ define <2 x i1> @test35vec(<2 x i32> %X) { define i128 @test36(i128 %A, i128 %B) { ; CHECK-LABEL: @test36( -; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP231:%.*]] = or i128 %B, %A ; CHECK-NEXT: [[INS:%.*]] = and i128 [[TMP231]], 18446744073709551615 ; CHECK-NEXT: ret i128 [[INS]] ; -entry: %tmp27 = shl i128 %A, 64 %tmp23 = shl i128 %B, 64 %ins = or i128 %tmp23, %tmp27 %tmp45 = lshr i128 %ins, 64 ret i128 %tmp45 - } define i64 @test37(i128 %A, i32 %B) { ; CHECK-LABEL: @test37( -; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP22:%.*]] = zext i32 %B to i128 ; CHECK-NEXT: [[TMP23:%.*]] = shl nuw nsw i128 [[TMP22]], 32 ; CHECK-NEXT: [[INS:%.*]] = or i128 [[TMP23]], %A ; CHECK-NEXT: [[TMP46:%.*]] = trunc i128 [[INS]] to i64 ; CHECK-NEXT: ret i64 [[TMP46]] ; -entry: %tmp27 = shl i128 %A, 64 %tmp22 = zext i32 %B to i128 %tmp23 = shl i128 %tmp22, 96 @@ -671,7 +662,17 @@ entry: %tmp45 = lshr i128 %ins, 64 %tmp46 = trunc i128 %tmp45 to i64 ret i64 %tmp46 +} +define <2 x i32> @shl_nuw_nsw_splat_vec(<2 x i8> %x) { +; CHECK-LABEL: @shl_nuw_nsw_splat_vec( +; CHECK-NEXT: [[T2:%.*]] = zext <2 x i8> %x to <2 x i32> +; CHECK-NEXT: [[T3:%.*]] = shl nuw nsw <2 x i32> [[T2]], <i32 17, i32 17> +; CHECK-NEXT: ret <2 x i32> [[T3]] +; + %t2 = zext <2 x i8> %x to <2 x i32> + %t3 = shl <2 x i32> %t2, <i32 17, i32 17> + ret <2 x i32> %t3 } define i32 @test38(i32 %x) nounwind readnone { @@ -789,6 +790,8 @@ define i32 @test45(i32 %a) nounwind { ret i32 %z } +; (X >>?exact C1) << C2 --> X >>?exact (C1-C2) + define i32 @test46(i32 %a) { ; CHECK-LABEL: @test46( ; CHECK-NEXT: [[Z:%.*]] = ashr exact i32 %a, 2 @@ -799,16 +802,44 @@ define i32 @test46(i32 %a) { ret i32 %z } -define i32 @test47(i32 %a) { +; (X >>?exact C1) << C2 --> X >>?exact (C1-C2) + +define <2 x i32> @test46_splat_vec(<2 x i32> %a) { +; CHECK-LABEL: @test46_splat_vec( +; CHECK-NEXT: [[Z:%.*]] = ashr exact <2 x i32> %a, <i32 2, i32 2> +; CHECK-NEXT: ret <2 x i32> [[Z]] +; + %y = ashr exact <2 x i32> %a, <i32 3, i32 3> + %z = shl <2 x i32> %y, <i32 1, i32 1> + ret <2 x i32> %z +} + +; (X >>?exact C1) << C2 --> X >>?exact (C1-C2) + +define i8 @test47(i8 %a) { ; CHECK-LABEL: @test47( -; CHECK-NEXT: [[Z:%.*]] = lshr exact i32 %a, 2 -; CHECK-NEXT: ret i32 [[Z]] +; CHECK-NEXT: [[Z:%.*]] = lshr exact i8 %a, 2 +; CHECK-NEXT: ret i8 [[Z]] ; - %y = lshr exact i32 %a, 3 - %z = shl i32 %y, 1 - ret i32 %z + %y = lshr exact i8 %a, 3 + %z = shl i8 %y, 1 + ret i8 %z +} + +; (X >>?exact C1) << C2 --> X >>?exact (C1-C2) + +define <2 x i8> @test47_splat_vec(<2 x i8> %a) { +; CHECK-LABEL: @test47_splat_vec( +; CHECK-NEXT: [[Z:%.*]] = lshr exact <2 x i8> %a, <i8 2, i8 2> +; CHECK-NEXT: ret <2 x i8> [[Z]] +; + %y = lshr exact <2 x i8> %a, <i8 3, i8 3> + %z = shl <2 x i8> %y, <i8 1, i8 1> + ret <2 x i8> %z } +; (X >>u,exact C1) << C2 --> X << (C2-C1) when C2 > C1 + define i32 @test48(i32 %x) { ; CHECK-LABEL: @test48( ; CHECK-NEXT: [[B:%.*]] = shl i32 %x, 2 @@ -819,6 +850,32 @@ define i32 @test48(i32 %x) { ret i32 %B } +; Verify that wrap flags are preserved from the original 'shl'. + +define i32 @test48_nuw_nsw(i32 %x) { +; CHECK-LABEL: @test48_nuw_nsw( +; CHECK-NEXT: [[B:%.*]] = shl nuw nsw i32 %x, 2 +; CHECK-NEXT: ret i32 [[B]] +; + %A = lshr exact i32 %x, 1 + %B = shl nuw nsw i32 %A, 3 + ret i32 %B +} + +; (X >>u,exact C1) << C2 --> X << (C2-C1) when splatted C2 > C1 + +define <2 x i32> @test48_splat_vec(<2 x i32> %x) { +; CHECK-LABEL: @test48_splat_vec( +; CHECK-NEXT: [[B:%.*]] = shl nuw nsw <2 x i32> %x, <i32 2, i32 2> +; CHECK-NEXT: ret <2 x i32> [[B]] +; + %A = lshr exact <2 x i32> %x, <i32 1, i32 1> + %B = shl nsw nuw <2 x i32> %A, <i32 3, i32 3> + ret <2 x i32> %B +} + +; (X >>s,exact C1) << C2 --> X << (C2-C1) when C2 > C1 + define i32 @test49(i32 %x) { ; CHECK-LABEL: @test49( ; CHECK-NEXT: [[B:%.*]] = shl i32 %x, 2 @@ -829,6 +886,32 @@ define i32 @test49(i32 %x) { ret i32 %B } +; Verify that wrap flags are preserved from the original 'shl'. + +define i32 @test49_nuw_nsw(i32 %x) { +; CHECK-LABEL: @test49_nuw_nsw( +; CHECK-NEXT: [[B:%.*]] = shl nuw nsw i32 %x, 2 +; CHECK-NEXT: ret i32 [[B]] +; + %A = ashr exact i32 %x, 1 + %B = shl nuw nsw i32 %A, 3 + ret i32 %B +} + +; (X >>s,exact C1) << C2 --> X << (C2-C1) when splatted C2 > C1 + +define <2 x i32> @test49_splat_vec(<2 x i32> %x) { +; CHECK-LABEL: @test49_splat_vec( +; CHECK-NEXT: [[B:%.*]] = shl nuw nsw <2 x i32> %x, <i32 2, i32 2> +; CHECK-NEXT: ret <2 x i32> [[B]] +; + %A = ashr exact <2 x i32> %x, <i32 1, i32 1> + %B = shl nsw nuw <2 x i32> %A, <i32 3, i32 3> + ret <2 x i32> %B +} + +; (X <<nsw C1) >>s C2 --> X >>s (C2-C1) + define i32 @test50(i32 %x) { ; CHECK-LABEL: @test50( ; CHECK-NEXT: [[B:%.*]] = ashr i32 %x, 2 @@ -839,6 +922,21 @@ define i32 @test50(i32 %x) { ret i32 %B } +; (X <<nsw C1) >>s C2 --> X >>s (C2-C1) +; Also, check that exact is propagated. + +define <2 x i32> @test50_splat_vec(<2 x i32> %x) { +; CHECK-LABEL: @test50_splat_vec( +; CHECK-NEXT: [[B:%.*]] = ashr exact <2 x i32> %x, <i32 2, i32 2> +; CHECK-NEXT: ret <2 x i32> [[B]] +; + %A = shl nsw <2 x i32> %x, <i32 1, i32 1> + %B = ashr exact <2 x i32> %A, <i32 3, i32 3> + ret <2 x i32> %B +} + +; (X <<nuw C1) >>u C2 --> X >>u (C2-C1) + define i32 @test51(i32 %x) { ; CHECK-LABEL: @test51( ; CHECK-NEXT: [[B:%.*]] = lshr i32 %x, 2 @@ -849,6 +947,48 @@ define i32 @test51(i32 %x) { ret i32 %B } +; (X <<nuw C1) >>u C2 --> X >>u (C2-C1) with splats +; Also, check that exact is propagated. + +define <2 x i32> @test51_splat_vec(<2 x i32> %x) { +; CHECK-LABEL: @test51_splat_vec( +; CHECK-NEXT: [[B:%.*]] = lshr exact <2 x i32> %x, <i32 2, i32 2> +; CHECK-NEXT: ret <2 x i32> [[B]] +; + %A = shl nuw <2 x i32> %x, <i32 1, i32 1> + %B = lshr exact <2 x i32> %A, <i32 3, i32 3> + ret <2 x i32> %B +} + +; (X << C1) >>u C2 --> X >>u (C2-C1) & (-1 >> C2) +; Also, check that exact is propagated. + +define i32 @test51_no_nuw(i32 %x) { +; CHECK-LABEL: @test51_no_nuw( +; CHECK-NEXT: [[TMP1:%.*]] = lshr exact i32 %x, 2 +; CHECK-NEXT: [[B:%.*]] = and i32 [[TMP1]], 536870911 +; CHECK-NEXT: ret i32 [[B]] +; + %A = shl i32 %x, 1 + %B = lshr exact i32 %A, 3 + ret i32 %B +} + +; (X << C1) >>u C2 --> X >>u (C2-C1) & (-1 >> C2) + +define <2 x i32> @test51_no_nuw_splat_vec(<2 x i32> %x) { +; CHECK-LABEL: @test51_no_nuw_splat_vec( +; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i32> %x, <i32 2, i32 2> +; CHECK-NEXT: [[B:%.*]] = and <2 x i32> [[TMP1]], <i32 536870911, i32 536870911> +; CHECK-NEXT: ret <2 x i32> [[B]] +; + %A = shl <2 x i32> %x, <i32 1, i32 1> + %B = lshr <2 x i32> %A, <i32 3, i32 3> + ret <2 x i32> %B +} + +; (X <<nsw C1) >>s C2 --> X <<nsw (C1 - C2) + define i32 @test52(i32 %x) { ; CHECK-LABEL: @test52( ; CHECK-NEXT: [[B:%.*]] = shl nsw i32 %x, 2 @@ -859,6 +999,20 @@ define i32 @test52(i32 %x) { ret i32 %B } +; (X <<nsw C1) >>s C2 --> X <<nsw (C1 - C2) + +define <2 x i32> @test52_splat_vec(<2 x i32> %x) { +; CHECK-LABEL: @test52_splat_vec( +; CHECK-NEXT: [[B:%.*]] = shl nsw <2 x i32> %x, <i32 2, i32 2> +; CHECK-NEXT: ret <2 x i32> [[B]] +; + %A = shl nsw <2 x i32> %x, <i32 3, i32 3> + %B = ashr <2 x i32> %A, <i32 1, i32 1> + ret <2 x i32> %B +} + +; (X <<nuw C1) >>u C2 --> X <<nuw (C1 - C2) + define i32 @test53(i32 %x) { ; CHECK-LABEL: @test53( ; CHECK-NEXT: [[B:%.*]] = shl nuw i32 %x, 2 @@ -869,6 +1023,45 @@ define i32 @test53(i32 %x) { ret i32 %B } +; (X <<nuw C1) >>u C2 --> X <<nuw (C1 - C2) + +define <2 x i32> @test53_splat_vec(<2 x i32> %x) { +; CHECK-LABEL: @test53_splat_vec( +; CHECK-NEXT: [[B:%.*]] = shl nuw <2 x i32> %x, <i32 2, i32 2> +; CHECK-NEXT: ret <2 x i32> [[B]] +; + %A = shl nuw <2 x i32> %x, <i32 3, i32 3> + %B = lshr <2 x i32> %A, <i32 1, i32 1> + ret <2 x i32> %B +} + +; (X << C1) >>u C2 --> X << (C1 - C2) & (-1 >> C2) + +define i8 @test53_no_nuw(i8 %x) { +; CHECK-LABEL: @test53_no_nuw( +; CHECK-NEXT: [[TMP1:%.*]] = shl i8 %x, 2 +; CHECK-NEXT: [[B:%.*]] = and i8 [[TMP1]], 124 +; CHECK-NEXT: ret i8 [[B]] +; + %A = shl i8 %x, 3 + %B = lshr i8 %A, 1 + ret i8 %B +} + +; (X << C1) >>u C2 --> X << (C1 - C2) & (-1 >> C2) +; FIXME: Demanded bits should change the mask constant as it does for the scalar case. + +define <2 x i8> @test53_no_nuw_splat_vec(<2 x i8> %x) { +; CHECK-LABEL: @test53_no_nuw_splat_vec( +; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i8> %x, <i8 2, i8 2> +; CHECK-NEXT: [[B:%.*]] = and <2 x i8> [[TMP1]], <i8 127, i8 127> +; CHECK-NEXT: ret <2 x i8> [[B]] +; + %A = shl <2 x i8> %x, <i8 3, i8 3> + %B = lshr <2 x i8> %A, <i8 1, i8 1> + ret <2 x i8> %B +} + define i32 @test54(i32 %x) { ; CHECK-LABEL: @test54( ; CHECK-NEXT: [[TMP1:%.*]] = shl i32 %x, 3 @@ -1041,7 +1234,7 @@ define <2 x i65> @test_63(<2 x i64> %t) { ; CHECK-LABEL: @test_63( ; CHECK-NEXT: [[A:%.*]] = zext <2 x i64> %t to <2 x i65> ; CHECK-NEXT: [[SEXT:%.*]] = shl <2 x i65> [[A]], <i65 33, i65 33> -; CHECK-NEXT: [[B:%.*]] = ashr <2 x i65> [[SEXT]], <i65 33, i65 33> +; CHECK-NEXT: [[B:%.*]] = ashr exact <2 x i65> [[SEXT]], <i65 33, i65 33> ; CHECK-NEXT: ret <2 x i65> [[B]] ; %a = zext <2 x i64> %t to <2 x i65> @@ -1052,12 +1245,26 @@ define <2 x i65> @test_63(<2 x i64> %t) { define i64 @test_64(i32 %t) { ; CHECK-LABEL: @test_64( -; CHECK-NEXT: [[SHL:%.*]] = shl i32 %t, 8 -; CHECK-NEXT: [[EXT:%.*]] = zext i32 [[SHL]] to i64 -; CHECK-NEXT: ret i64 [[EXT]] - +; CHECK-NEXT: [[TMP1:%.*]] = shl i32 %t, 8 +; CHECK-NEXT: [[SHL:%.*]] = zext i32 [[TMP1]] to i64 +; CHECK-NEXT: ret i64 [[SHL]] +; %and = and i32 %t, 16777215 %ext = zext i32 %and to i64 %shl = shl i64 %ext, 8 ret i64 %shl } + +define <2 x i64> @test_64_splat_vec(<2 x i32> %t) { +; CHECK-LABEL: @test_64_splat_vec( +; CHECK-NEXT: [[AND:%.*]] = and <2 x i32> %t, <i32 16777215, i32 16777215> +; CHECK-NEXT: [[TMP1:%.*]] = shl nuw <2 x i32> [[AND]], <i32 8, i32 8> +; CHECK-NEXT: [[SHL:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64> +; CHECK-NEXT: ret <2 x i64> [[SHL]] +; + %and = and <2 x i32> %t, <i32 16777215, i32 16777215> + %ext = zext <2 x i32> %and to <2 x i64> + %shl = shl <2 x i64> %ext, <i64 8, i64 8> + ret <2 x i64> %shl +} + |