Re-land [openmp] Fix warnings when building on Windows with latest MSVC or Clang...
[llvm-project.git] / llvm / test / Transforms / InstCombine / lshr-trunc-sext-to-ashr-sext.ll
blob8d82213d8022f7debfd007967bb0f86f4ba287b9
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
4 ; Iff trunc only chops off zero bits that were just shifted-in by the lshr,
5 ; but no other bits, then we can instead do signed shift, and signext it.
6 ; Note that we can replace trunc with trunc of new signed shift.
8 declare void @use32(i32)
9 declare void @use8(i8)
10 declare void @use4(i4)
11 declare void @usevec8(<2 x i8>)
12 declare void @usevec4(<2 x i4>)
14 define i16 @t0(i8 %x) {
15 ; CHECK-LABEL: @t0(
16 ; CHECK-NEXT:    [[TMP1:%.*]] = ashr i8 [[X:%.*]], 4
17 ; CHECK-NEXT:    [[C:%.*]] = sext i8 [[TMP1]] to i16
18 ; CHECK-NEXT:    ret i16 [[C]]
20   %a = lshr i8 %x, 4
21   %b = trunc i8 %a to i4
22   %c = sext i4 %b to i16
23   ret i16 %c
26 define i16 @t1(i8 %x) {
27 ; CHECK-LABEL: @t1(
28 ; CHECK-NEXT:    [[TMP1:%.*]] = ashr i8 [[X:%.*]], 5
29 ; CHECK-NEXT:    [[C:%.*]] = sext i8 [[TMP1]] to i16
30 ; CHECK-NEXT:    ret i16 [[C]]
32   %a = lshr i8 %x, 5
33   %b = trunc i8 %a to i3
34   %c = sext i3 %b to i16
35   ret i16 %c
38 define i16 @t2(i7 %x) {
39 ; CHECK-LABEL: @t2(
40 ; CHECK-NEXT:    [[TMP1:%.*]] = ashr i7 [[X:%.*]], 3
41 ; CHECK-NEXT:    [[C:%.*]] = sext i7 [[TMP1]] to i16
42 ; CHECK-NEXT:    ret i16 [[C]]
44   %a = lshr i7 %x, 3
45   %b = trunc i7 %a to i4
46   %c = sext i4 %b to i16
47   ret i16 %c
50 ; negative test - shift amount doesn't match trunc amount
52 define i16 @n3(i8 %x) {
53 ; CHECK-LABEL: @n3(
54 ; CHECK-NEXT:    [[A:%.*]] = lshr i8 [[X:%.*]], 3
55 ; CHECK-NEXT:    [[B:%.*]] = trunc i8 [[A]] to i4
56 ; CHECK-NEXT:    [[C:%.*]] = sext i4 [[B]] to i16
57 ; CHECK-NEXT:    ret i16 [[C]]
59   %a = lshr i8 %x, 3
60   %b = trunc i8 %a to i4
61   %c = sext i4 %b to i16
62   ret i16 %c
65 define <2 x i16> @t4_vec_splat(<2 x i8> %x) {
66 ; CHECK-LABEL: @t4_vec_splat(
67 ; CHECK-NEXT:    [[TMP1:%.*]] = ashr <2 x i8> [[X:%.*]], <i8 4, i8 4>
68 ; CHECK-NEXT:    [[C:%.*]] = sext <2 x i8> [[TMP1]] to <2 x i16>
69 ; CHECK-NEXT:    ret <2 x i16> [[C]]
71   %a = lshr <2 x i8> %x, <i8 4, i8 4>
72   %b = trunc <2 x i8> %a to <2 x i4>
73   %c = sext <2 x i4> %b to <2 x i16>
74   ret <2 x i16> %c
77 define <2 x i16> @t5_vec_undef(<2 x i8> %x) {
78 ; CHECK-LABEL: @t5_vec_undef(
79 ; CHECK-NEXT:    [[TMP1:%.*]] = ashr <2 x i8> [[X:%.*]], <i8 4, i8 4>
80 ; CHECK-NEXT:    [[C:%.*]] = sext <2 x i8> [[TMP1]] to <2 x i16>
81 ; CHECK-NEXT:    ret <2 x i16> [[C]]
83   %a = lshr <2 x i8> %x, <i8 4, i8 undef>
84   %b = trunc <2 x i8> %a to <2 x i4>
85   %c = sext <2 x i4> %b to <2 x i16>
86   ret <2 x i16> %c
89 ; TODO: We could convert %a to ashr and eliminate 2nd use of %b.
91 define i16 @t6_extrause0(i8 %x) {
92 ; CHECK-LABEL: @t6_extrause0(
93 ; CHECK-NEXT:    [[A:%.*]] = lshr i8 [[X:%.*]], 4
94 ; CHECK-NEXT:    [[B:%.*]] = trunc i8 [[A]] to i4
95 ; CHECK-NEXT:    call void @use4(i4 [[B]])
96 ; CHECK-NEXT:    [[C:%.*]] = sext i4 [[B]] to i16
97 ; CHECK-NEXT:    ret i16 [[C]]
99   %a = lshr i8 %x, 4
100   %b = trunc i8 %a to i4 ; has extra use, but we can deal with that
101   call void @use4(i4 %b)
102   %c = sext i4 %b to i16
103   ret i16 %c
106 ; TODO: We could convert %a to ashr and eliminate 2nd use of %b.
108 define <2 x i16> @t7_extrause0_vec_undef(<2 x i8> %x) {
109 ; CHECK-LABEL: @t7_extrause0_vec_undef(
110 ; CHECK-NEXT:    [[A:%.*]] = lshr <2 x i8> [[X:%.*]], <i8 4, i8 undef>
111 ; CHECK-NEXT:    [[B:%.*]] = trunc <2 x i8> [[A]] to <2 x i4>
112 ; CHECK-NEXT:    call void @usevec4(<2 x i4> [[B]])
113 ; CHECK-NEXT:    [[C:%.*]] = sext <2 x i4> [[B]] to <2 x i16>
114 ; CHECK-NEXT:    ret <2 x i16> [[C]]
116   %a = lshr <2 x i8> %x, <i8 4, i8 undef>
117   %b = trunc <2 x i8> %a to <2 x i4>
118   call void @usevec4(<2 x i4> %b)
119   %c = sext <2 x i4> %b to <2 x i16>
120   ret <2 x i16> %c
123 ; TODO: We could convert %a to ashr + mask (and) and eliminate %b.
125 define i16 @t8_extrause1(i8 %x) {
126 ; CHECK-LABEL: @t8_extrause1(
127 ; CHECK-NEXT:    [[A:%.*]] = lshr i8 [[X:%.*]], 4
128 ; CHECK-NEXT:    call void @use8(i8 [[A]])
129 ; CHECK-NEXT:    [[TMP1:%.*]] = ashr i8 [[X]], 4
130 ; CHECK-NEXT:    [[C:%.*]] = sext i8 [[TMP1]] to i16
131 ; CHECK-NEXT:    ret i16 [[C]]
133   %a = lshr i8 %x, 4 ; has extra use, but we can deal with that
134   call void @use8(i8 %a)
135   %b = trunc i8 %a to i4
136   %c = sext i4 %b to i16
137   ret i16 %c
140 ; TODO: We could convert %a to ashr + mask (and) and eliminate %b.
142 define <2 x i16> @t9_extrause1_vec_undef(<2 x i8> %x) {
143 ; CHECK-LABEL: @t9_extrause1_vec_undef(
144 ; CHECK-NEXT:    [[A:%.*]] = lshr <2 x i8> [[X:%.*]], <i8 4, i8 undef>
145 ; CHECK-NEXT:    call void @usevec8(<2 x i8> [[A]])
146 ; CHECK-NEXT:    [[TMP1:%.*]] = ashr <2 x i8> [[X]], <i8 4, i8 4>
147 ; CHECK-NEXT:    [[C:%.*]] = sext <2 x i8> [[TMP1]] to <2 x i16>
148 ; CHECK-NEXT:    ret <2 x i16> [[C]]
150   %a = lshr <2 x i8> %x, <i8 4, i8 undef>
151   call void @usevec8(<2 x i8> %a)
152   %b = trunc <2 x i8> %a to <2 x i4>
153   %c = sext <2 x i4> %b to <2 x i16>
154   ret <2 x i16> %c
156 define i16 @t10_extrause2(i8 %x) {
157 ; CHECK-LABEL: @t10_extrause2(
158 ; CHECK-NEXT:    [[A:%.*]] = lshr i8 [[X:%.*]], 4
159 ; CHECK-NEXT:    call void @use8(i8 [[A]])
160 ; CHECK-NEXT:    [[B:%.*]] = trunc i8 [[A]] to i4
161 ; CHECK-NEXT:    call void @use4(i4 [[B]])
162 ; CHECK-NEXT:    [[C:%.*]] = sext i4 [[B]] to i16
163 ; CHECK-NEXT:    ret i16 [[C]]
165   %a = lshr i8 %x, 4 ; has extra use
166   call void @use8(i8 %a)
167   %b = trunc i8 %a to i4 ; has extra use
168   call void @use4(i4 %b)
169   %c = sext i4 %b to i16
170   ret i16 %c
172 define <2 x i16> @t11_extrause2_vec_undef(<2 x i8> %x) {
173 ; CHECK-LABEL: @t11_extrause2_vec_undef(
174 ; CHECK-NEXT:    [[A:%.*]] = lshr <2 x i8> [[X:%.*]], <i8 4, i8 undef>
175 ; CHECK-NEXT:    call void @usevec8(<2 x i8> [[A]])
176 ; CHECK-NEXT:    [[B:%.*]] = trunc <2 x i8> [[A]] to <2 x i4>
177 ; CHECK-NEXT:    call void @usevec4(<2 x i4> [[B]])
178 ; CHECK-NEXT:    [[C:%.*]] = sext <2 x i4> [[B]] to <2 x i16>
179 ; CHECK-NEXT:    ret <2 x i16> [[C]]
181   %a = lshr <2 x i8> %x, <i8 4, i8 undef>
182   call void @usevec8(<2 x i8> %a)
183   %b = trunc <2 x i8> %a to <2 x i4>
184   call void @usevec4(<2 x i4> %b)
185   %c = sext <2 x i4> %b to <2 x i16>
186   ret <2 x i16> %c
189 define <2 x i10> @wide_source_shifted_signbit(<2 x i32> %x) {
190 ; CHECK-LABEL: @wide_source_shifted_signbit(
191 ; CHECK-NEXT:    [[TMP1:%.*]] = ashr <2 x i32> [[X:%.*]], <i32 24, i32 24>
192 ; CHECK-NEXT:    [[C:%.*]] = trunc <2 x i32> [[TMP1]] to <2 x i10>
193 ; CHECK-NEXT:    ret <2 x i10> [[C]]
195   %a = lshr <2 x i32> %x, <i32 24, i32 24>
196   %b = trunc <2 x i32> %a to <2 x i8>
197   %c = sext <2 x i8> %b to <2 x i10>
198   ret <2 x i10> %c
201 define i10 @wide_source_shifted_signbit_use1(i32 %x) {
202 ; CHECK-LABEL: @wide_source_shifted_signbit_use1(
203 ; CHECK-NEXT:    [[A:%.*]] = lshr i32 [[X:%.*]], 24
204 ; CHECK-NEXT:    call void @use32(i32 [[A]])
205 ; CHECK-NEXT:    [[TMP1:%.*]] = ashr i32 [[X]], 24
206 ; CHECK-NEXT:    [[C:%.*]] = trunc i32 [[TMP1]] to i10
207 ; CHECK-NEXT:    ret i10 [[C]]
209   %a = lshr i32 %x, 24
210   call void @use32(i32 %a)
211   %b = trunc i32 %a to i8
212   %c = sext i8 %b to i10
213   ret i10 %c
216 define i10 @wide_source_shifted_signbit_use2(i32 %x) {
217 ; CHECK-LABEL: @wide_source_shifted_signbit_use2(
218 ; CHECK-NEXT:    [[A:%.*]] = lshr i32 [[X:%.*]], 24
219 ; CHECK-NEXT:    [[B:%.*]] = trunc i32 [[A]] to i8
220 ; CHECK-NEXT:    call void @use8(i8 [[B]])
221 ; CHECK-NEXT:    [[C:%.*]] = sext i8 [[B]] to i10
222 ; CHECK-NEXT:    ret i10 [[C]]
224   %a = lshr i32 %x, 24
225   %b = trunc i32 %a to i8
226   call void @use8(i8 %b)
227   %c = sext i8 %b to i10
228   ret i10 %c
231 define i32 @same_source_shifted_signbit(i32 %x) {
232 ; CHECK-LABEL: @same_source_shifted_signbit(
233 ; CHECK-NEXT:    [[C:%.*]] = ashr i32 [[X:%.*]], 24
234 ; CHECK-NEXT:    ret i32 [[C]]
236   %a = lshr i32 %x, 24
237   %b = trunc i32 %a to i8
238   %c = sext i8 %b to i32
239   ret i32 %c
242 define i32 @same_source_shifted_signbit_use1(i32 %x) {
243 ; CHECK-LABEL: @same_source_shifted_signbit_use1(
244 ; CHECK-NEXT:    [[A:%.*]] = lshr i32 [[X:%.*]], 24
245 ; CHECK-NEXT:    call void @use32(i32 [[A]])
246 ; CHECK-NEXT:    [[C:%.*]] = ashr i32 [[X]], 24
247 ; CHECK-NEXT:    ret i32 [[C]]
249   %a = lshr i32 %x, 24
250   call void @use32(i32 %a)
251   %b = trunc i32 %a to i8
252   %c = sext i8 %b to i32
253   ret i32 %c
256 define i32 @same_source_shifted_signbit_use2(i32 %x) {
257 ; CHECK-LABEL: @same_source_shifted_signbit_use2(
258 ; CHECK-NEXT:    [[A:%.*]] = lshr i32 [[X:%.*]], 24
259 ; CHECK-NEXT:    [[B:%.*]] = trunc i32 [[A]] to i8
260 ; CHECK-NEXT:    call void @use8(i8 [[B]])
261 ; CHECK-NEXT:    [[C:%.*]] = sext i8 [[B]] to i32
262 ; CHECK-NEXT:    ret i32 [[C]]
264   %a = lshr i32 %x, 24
265   %b = trunc i32 %a to i8
266   call void @use8(i8 %b)
267   %c = sext i8 %b to i32
268   ret i32 %c