xref: /llvm-project/llvm/test/Transforms/AggressiveInstCombine/trunc_shl.ll (revision 3f8027fb67bc4efae9959a4d75f8f37ecf0c3985)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=aggressive-instcombine -S | FileCheck %s
3
4define i16 @shl_1(i8 %x) {
5; CHECK-LABEL: @shl_1(
6; CHECK-NEXT:    [[ZEXT:%.*]] = zext i8 [[X:%.*]] to i16
7; CHECK-NEXT:    [[SHL:%.*]] = shl i16 [[ZEXT]], 1
8; CHECK-NEXT:    ret i16 [[SHL]]
9;
10  %zext = zext i8 %x to i32
11  %shl = shl i32 %zext, 1
12  %trunc = trunc i32 %shl to i16
13  ret i16 %trunc
14}
15
16define i16 @shl_15(i8 %x) {
17; CHECK-LABEL: @shl_15(
18; CHECK-NEXT:    [[ZEXT:%.*]] = zext i8 [[X:%.*]] to i16
19; CHECK-NEXT:    [[SHL:%.*]] = shl i16 [[ZEXT]], 15
20; CHECK-NEXT:    ret i16 [[SHL]]
21;
22  %zext = zext i8 %x to i32
23  %shl = shl i32 %zext, 15
24  %trunc = trunc i32 %shl to i16
25  ret i16 %trunc
26}
27
28; Negative test - shift amount isn't less than target bitwidth
29
30define i16 @shl_16(i8 %x) {
31; CHECK-LABEL: @shl_16(
32; CHECK-NEXT:    [[ZEXT:%.*]] = zext i8 [[X:%.*]] to i32
33; CHECK-NEXT:    [[SHL:%.*]] = shl i32 [[ZEXT]], 16
34; CHECK-NEXT:    [[TRUNC:%.*]] = trunc i32 [[SHL]] to i16
35; CHECK-NEXT:    ret i16 [[TRUNC]]
36;
37  %zext = zext i8 %x to i32
38  %shl = shl i32 %zext, 16
39  %trunc = trunc i32 %shl to i16
40  ret i16 %trunc
41}
42
43; Negative test -- variable shift amount
44
45define i16 @shl_var_shift_amount(i8 %x, i8 %y) {
46; CHECK-LABEL: @shl_var_shift_amount(
47; CHECK-NEXT:    [[ZEXT_X:%.*]] = zext i8 [[X:%.*]] to i32
48; CHECK-NEXT:    [[ZEXT_Y:%.*]] = zext i8 [[Y:%.*]] to i32
49; CHECK-NEXT:    [[SHL:%.*]] = shl i32 [[ZEXT_X]], [[ZEXT_Y]]
50; CHECK-NEXT:    [[TRUNC:%.*]] = trunc i32 [[SHL]] to i16
51; CHECK-NEXT:    ret i16 [[TRUNC]]
52;
53  %zext.x = zext i8 %x to i32
54  %zext.y = zext i8 %y to i32
55  %shl = shl i32 %zext.x, %zext.y
56  %trunc = trunc i32 %shl to i16
57  ret i16 %trunc
58}
59
60define i16 @shl_var_bounded_shift_amount(i8 %x, i8 %y) {
61; CHECK-LABEL: @shl_var_bounded_shift_amount(
62; CHECK-NEXT:    [[ZEXT_X:%.*]] = zext i8 [[X:%.*]] to i16
63; CHECK-NEXT:    [[ZEXT_Y:%.*]] = zext i8 [[Y:%.*]] to i16
64; CHECK-NEXT:    [[AND:%.*]] = and i16 [[ZEXT_Y]], 15
65; CHECK-NEXT:    [[SHL:%.*]] = shl i16 [[ZEXT_X]], [[AND]]
66; CHECK-NEXT:    ret i16 [[SHL]]
67;
68  %zext.x = zext i8 %x to i32
69  %zext.y = zext i8 %y to i32
70  %and = and i32 %zext.y, 15
71  %shl = shl i32 %zext.x, %and
72  %trunc = trunc i32 %shl to i16
73  ret i16 %trunc
74}
75
76; Negative test (https://reviews.llvm.org/D108091#2950930)
77
78define i32 @shl_check_no_overflow(i32 %x, i16 %amt) {
79; CHECK-LABEL: @shl_check_no_overflow(
80; CHECK-NEXT:    [[ZEXT:%.*]] = zext i32 [[X:%.*]] to i64
81; CHECK-NEXT:    [[SEXT:%.*]] = sext i16 [[AMT:%.*]] to i64
82; CHECK-NEXT:    [[AND:%.*]] = and i64 [[SEXT]], 4294967295
83; CHECK-NEXT:    [[SHL:%.*]] = shl i64 [[ZEXT]], [[AND]]
84; CHECK-NEXT:    [[TRUNC:%.*]] = trunc i64 [[SHL]] to i32
85; CHECK-NEXT:    ret i32 [[TRUNC]]
86;
87  %zext = zext i32 %x to i64
88  %sext = sext i16 %amt to i64
89  %and = and i64 %sext, 4294967295
90  %shl = shl i64 %zext, %and
91  %trunc = trunc i64 %shl to i32
92  ret i32 %trunc
93}
94
95define <2 x i16> @shl_vector(<2 x i8> %x) {
96; CHECK-LABEL: @shl_vector(
97; CHECK-NEXT:    [[Z:%.*]] = zext <2 x i8> [[X:%.*]] to <2 x i16>
98; CHECK-NEXT:    [[S:%.*]] = shl <2 x i16> [[Z]], <i16 4, i16 10>
99; CHECK-NEXT:    ret <2 x i16> [[S]]
100;
101  %z = zext <2 x i8> %x to <2 x i32>
102  %s = shl <2 x i32> %z, <i32 4, i32 10>
103  %t = trunc <2 x i32> %s to <2 x i16>
104  ret <2 x i16> %t
105}
106
107; Negative test - can only fold to <2 x i16>, requiring new vector type
108
109define <2 x i8> @shl_vector_no_new_vector_type(<2 x i8> %x) {
110; CHECK-LABEL: @shl_vector_no_new_vector_type(
111; CHECK-NEXT:    [[Z:%.*]] = zext <2 x i8> [[X:%.*]] to <2 x i32>
112; CHECK-NEXT:    [[S:%.*]] = shl <2 x i32> [[Z]], <i32 4, i32 10>
113; CHECK-NEXT:    [[T:%.*]] = trunc <2 x i32> [[S]] to <2 x i8>
114; CHECK-NEXT:    ret <2 x i8> [[T]]
115;
116  %z = zext <2 x i8> %x to <2 x i32>
117  %s = shl <2 x i32> %z, <i32 4, i32 10>
118  %t = trunc <2 x i32> %s to <2 x i8>
119  ret <2 x i8> %t
120}
121
122; Negative test
123
124define <2 x i16> @shl_vector_large_shift_amount(<2 x i8> %x) {
125; CHECK-LABEL: @shl_vector_large_shift_amount(
126; CHECK-NEXT:    [[Z:%.*]] = zext <2 x i8> [[X:%.*]] to <2 x i32>
127; CHECK-NEXT:    [[S:%.*]] = shl <2 x i32> [[Z]], <i32 16, i32 5>
128; CHECK-NEXT:    [[T:%.*]] = trunc <2 x i32> [[S]] to <2 x i16>
129; CHECK-NEXT:    ret <2 x i16> [[T]]
130;
131  %z = zext <2 x i8> %x to <2 x i32>
132  %s = shl <2 x i32> %z, <i32 16, i32 5>
133  %t = trunc <2 x i32> %s to <2 x i16>
134  ret <2 x i16> %t
135}
136
137define i16 @shl_nuw(i8 %x) {
138; CHECK-LABEL: @shl_nuw(
139; CHECK-NEXT:    [[Z:%.*]] = zext i8 [[X:%.*]] to i16
140; CHECK-NEXT:    [[S:%.*]] = shl i16 [[Z]], 15
141; CHECK-NEXT:    ret i16 [[S]]
142;
143  %z = zext i8 %x to i32
144  %s = shl nuw i32 %z, 15
145  %t = trunc i32 %s to i16
146  ret i16 %t
147}
148
149define i16 @shl_nsw(i8 %x) {
150; CHECK-LABEL: @shl_nsw(
151; CHECK-NEXT:    [[Z:%.*]] = zext i8 [[X:%.*]] to i16
152; CHECK-NEXT:    [[S:%.*]] = shl i16 [[Z]], 15
153; CHECK-NEXT:    ret i16 [[S]]
154;
155  %z = zext i8 %x to i32
156  %s = shl nsw i32 %z, 15
157  %t = trunc i32 %s to i16
158  ret i16 %t
159}
160