summaryrefslogtreecommitdiff
path: root/test/Transforms/InstCombine/shift.ll
diff options
context:
space:
mode:
Diffstat (limited to 'test/Transforms/InstCombine/shift.ll')
-rw-r--r--test/Transforms/InstCombine/shift.ll253
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
+}
+