Re-land [openmp] Fix warnings when building on Windows with latest MSVC or Clang...
[llvm-project.git] / llvm / test / Transforms / InstCombine / negated-bitmask.ll
blobfe2386bd65c3180e98af58848d4b820370d82ebf
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
4 ; PR53610 - sub(0,and(lshr(X,C1),1)) --> ashr(shl(X,(BW-1)-C1),BW-1)
5 ; PR53610 - sub(C2,and(lshr(X,C1),1)) --> add(ashr(shl(X,(BW-1)-C1),BW-1),C2)
7 define i8 @neg_mask1_lshr(i8 %a0) {
8 ; CHECK-LABEL: @neg_mask1_lshr(
9 ; CHECK-NEXT:    [[TMP1:%.*]] = shl i8 [[A0:%.*]], 4
10 ; CHECK-NEXT:    [[TMP2:%.*]] = ashr i8 [[TMP1]], 7
11 ; CHECK-NEXT:    ret i8 [[TMP2]]
13   %shift = lshr i8 %a0, 3
14   %mask = and i8 %shift, 1
15   %neg = sub i8 0, %mask
16   ret i8 %neg
19 define i8 @sub_mask1_lshr(i8 %a0) {
20 ; CHECK-LABEL: @sub_mask1_lshr(
21 ; CHECK-NEXT:    [[TMP1:%.*]] = shl i8 [[A0:%.*]], 6
22 ; CHECK-NEXT:    [[TMP2:%.*]] = ashr i8 [[TMP1]], 7
23 ; CHECK-NEXT:    [[NEG:%.*]] = add nsw i8 [[TMP2]], 10
24 ; CHECK-NEXT:    ret i8 [[NEG]]
26   %shift = lshr i8 %a0, 1
27   %mask = and i8 %shift, 1
28   %neg = sub i8 10, %mask
29   ret i8 %neg
32 define <4 x i32> @neg_mask1_lshr_vector_uniform(<4 x i32> %a0) {
33 ; CHECK-LABEL: @neg_mask1_lshr_vector_uniform(
34 ; CHECK-NEXT:    [[TMP1:%.*]] = shl <4 x i32> [[A0:%.*]], <i32 28, i32 28, i32 28, i32 28>
35 ; CHECK-NEXT:    [[TMP2:%.*]] = ashr <4 x i32> [[TMP1]], <i32 31, i32 31, i32 31, i32 31>
36 ; CHECK-NEXT:    ret <4 x i32> [[TMP2]]
38   %shift = lshr <4 x i32> %a0, <i32 3, i32 3, i32 3, i32 3>
39   %mask = and <4 x i32> %shift, <i32 1, i32 1, i32 1, i32 1>
40   %neg = sub <4 x i32> zeroinitializer, %mask
41   ret <4 x i32> %neg
44 define <4 x i32> @neg_mask1_lshr_vector_nonuniform(<4 x i32> %a0) {
45 ; CHECK-LABEL: @neg_mask1_lshr_vector_nonuniform(
46 ; CHECK-NEXT:    [[TMP1:%.*]] = shl <4 x i32> [[A0:%.*]], <i32 28, i32 27, i32 26, i32 25>
47 ; CHECK-NEXT:    [[TMP2:%.*]] = ashr <4 x i32> [[TMP1]], <i32 31, i32 31, i32 31, i32 31>
48 ; CHECK-NEXT:    ret <4 x i32> [[TMP2]]
50   %shift = lshr <4 x i32> %a0, <i32 3, i32 4, i32 5, i32 6>
51   %mask = and <4 x i32> %shift, <i32 1, i32 1, i32 1, i32 1>
52   %neg = sub <4 x i32> zeroinitializer, %mask
53   ret <4 x i32> %neg
56 define <4 x i32> @sub_mask1_lshr_vector_nonuniform(<4 x i32> %a0) {
57 ; CHECK-LABEL: @sub_mask1_lshr_vector_nonuniform(
58 ; CHECK-NEXT:    [[TMP1:%.*]] = shl <4 x i32> [[A0:%.*]], <i32 28, i32 27, i32 26, i32 25>
59 ; CHECK-NEXT:    [[TMP2:%.*]] = ashr <4 x i32> [[TMP1]], <i32 31, i32 31, i32 31, i32 31>
60 ; CHECK-NEXT:    [[NEG:%.*]] = add nsw <4 x i32> [[TMP2]], <i32 5, i32 0, i32 -1, i32 65556>
61 ; CHECK-NEXT:    ret <4 x i32> [[NEG]]
63   %shift = lshr <4 x i32> %a0, <i32 3, i32 4, i32 5, i32 6>
64   %mask = and <4 x i32> %shift, <i32 1, i32 1, i32 1, i32 1>
65   %neg = sub <4 x i32> <i32 5, i32 0, i32 -1, i32 65556>, %mask
66   ret <4 x i32> %neg
69 define i8 @sub_mask1_trunc_lshr(i64 %a0) {
70 ; CHECK-LABEL: @sub_mask1_trunc_lshr(
71 ; CHECK-NEXT:    [[TMP1:%.*]] = shl i64 [[A0:%.*]], 48
72 ; CHECK-NEXT:    [[TMP2:%.*]] = ashr i64 [[TMP1]], 63
73 ; CHECK-NEXT:    [[TMP3:%.*]] = trunc i64 [[TMP2]] to i8
74 ; CHECK-NEXT:    [[NEG:%.*]] = add nsw i8 [[TMP3]], 10
75 ; CHECK-NEXT:    ret i8 [[NEG]]
77   %shift = lshr i64 %a0, 15
78   %trunc = trunc i64 %shift to i8
79   %mask = and i8 %trunc, 1
80   %neg = sub i8 10, %mask
81   ret i8 %neg
84 define i32 @sub_sext_mask1_trunc_lshr(i64 %a0) {
85 ; CHECK-LABEL: @sub_sext_mask1_trunc_lshr(
86 ; CHECK-NEXT:    [[TMP1:%.*]] = shl i64 [[A0:%.*]], 48
87 ; CHECK-NEXT:    [[TMP2:%.*]] = ashr i64 [[TMP1]], 63
88 ; CHECK-NEXT:    [[TMP3:%.*]] = trunc i64 [[TMP2]] to i8
89 ; CHECK-NEXT:    [[NARROW:%.*]] = add nsw i8 [[TMP3]], 10
90 ; CHECK-NEXT:    [[NEG:%.*]] = zext i8 [[NARROW]] to i32
91 ; CHECK-NEXT:    ret i32 [[NEG]]
93   %shift = lshr i64 %a0, 15
94   %trunc = trunc i64 %shift to i8
95   %mask = and i8 %trunc, 1
96   %sext = sext i8 %mask to i32
97   %neg = sub i32 10, %sext
98   ret i32 %neg
101 define i32 @sub_zext_trunc_lshr(i64 %a0) {
102 ; CHECK-LABEL: @sub_zext_trunc_lshr(
103 ; CHECK-NEXT:    [[TMP1:%.*]] = trunc i64 [[A0:%.*]] to i32
104 ; CHECK-NEXT:    [[TMP2:%.*]] = shl i32 [[TMP1]], 16
105 ; CHECK-NEXT:    [[TMP3:%.*]] = ashr i32 [[TMP2]], 31
106 ; CHECK-NEXT:    [[NEG:%.*]] = add nsw i32 [[TMP3]], 10
107 ; CHECK-NEXT:    ret i32 [[NEG]]
109   %shift = lshr i64 %a0, 15
110   %trunc = trunc i64 %shift to i1
111   %sext = zext i1 %trunc to i32
112   %neg = sub i32 10, %sext
113   ret i32 %neg
116 ; Negative Test - wrong mask
117 define i8 @neg_mask2_lshr(i8 %a0) {
118 ; CHECK-LABEL: @neg_mask2_lshr(
119 ; CHECK-NEXT:    [[SHIFT:%.*]] = lshr i8 [[A0:%.*]], 3
120 ; CHECK-NEXT:    [[MASK:%.*]] = and i8 [[SHIFT]], 2
121 ; CHECK-NEXT:    [[NEG:%.*]] = sub nsw i8 0, [[MASK]]
122 ; CHECK-NEXT:    ret i8 [[NEG]]
124   %shift = lshr i8 %a0, 3
125   %mask = and i8 %shift, 2
126   %neg = sub i8 0, %mask
127   ret i8 %neg
130 ; Negative Test - bad shift amount
131 define i8 @neg_mask2_lshr_outofbounds(i8 %a0) {
132 ; CHECK-LABEL: @neg_mask2_lshr_outofbounds(
133 ; CHECK-NEXT:    ret i8 poison
135   %shift = lshr i8 %a0, 8
136   %mask = and i8 %shift, 2
137   %neg = sub i8 0, %mask
138   ret i8 %neg
141 ; Negative Test - non-constant shift amount
142 define <2 x i32> @neg_mask1_lshr_vector_var(<2 x i32> %a0, <2 x i32> %a1) {
143 ; CHECK-LABEL: @neg_mask1_lshr_vector_var(
144 ; CHECK-NEXT:    [[SHIFT:%.*]] = lshr <2 x i32> [[A0:%.*]], [[A1:%.*]]
145 ; CHECK-NEXT:    [[MASK:%.*]] = and <2 x i32> [[SHIFT]], <i32 1, i32 1>
146 ; CHECK-NEXT:    [[NEG:%.*]] = sub nsw <2 x i32> zeroinitializer, [[MASK]]
147 ; CHECK-NEXT:    ret <2 x i32> [[NEG]]
149   %shift = lshr <2 x i32> %a0, %a1
150   %mask = and <2 x i32> %shift, <i32 1, i32 1>
151   %neg = sub <2 x i32> zeroinitializer, %mask
152   ret <2 x i32> %neg
155 ; Extra Use - mask
156 define i8 @neg_mask1_lshr_extrause_mask(i8 %a0) {
157 ; CHECK-LABEL: @neg_mask1_lshr_extrause_mask(
158 ; CHECK-NEXT:    [[SHIFT:%.*]] = lshr i8 [[A0:%.*]], 3
159 ; CHECK-NEXT:    [[MASK:%.*]] = and i8 [[SHIFT]], 1
160 ; CHECK-NEXT:    [[NEG:%.*]] = sub nsw i8 0, [[MASK]]
161 ; CHECK-NEXT:    call void @usei8(i8 [[MASK]])
162 ; CHECK-NEXT:    ret i8 [[NEG]]
164   %shift = lshr i8 %a0, 3
165   %mask = and i8 %shift, 1
166   %neg = sub i8 0, %mask
167   call void @usei8(i8 %mask)
168   ret i8 %neg
171 ; Extra Use - shift
172 define <2 x i32> @neg_mask1_lshr_extrause_lshr(<2 x i32> %a0) {
173 ; CHECK-LABEL: @neg_mask1_lshr_extrause_lshr(
174 ; CHECK-NEXT:    [[SHIFT:%.*]] = lshr <2 x i32> [[A0:%.*]], <i32 3, i32 3>
175 ; CHECK-NEXT:    [[MASK:%.*]] = and <2 x i32> [[SHIFT]], <i32 1, i32 1>
176 ; CHECK-NEXT:    [[NEG:%.*]] = sub nsw <2 x i32> zeroinitializer, [[MASK]]
177 ; CHECK-NEXT:    call void @usev2i32(<2 x i32> [[SHIFT]])
178 ; CHECK-NEXT:    ret <2 x i32> [[NEG]]
180   %shift = lshr <2 x i32> %a0, <i32 3, i32 3>
181   %mask = and <2 x i32> %shift, <i32 1, i32 1>
182   %neg = sub <2 x i32> zeroinitializer, %mask
183   call void @usev2i32(<2 x i32> %shift)
184   ret <2 x i32> %neg
187 define i32 @neg_signbit(i8 %x) {
188 ; CHECK-LABEL: @neg_signbit(
189 ; CHECK-NEXT:    [[TMP1:%.*]] = ashr i8 [[X:%.*]], 7
190 ; CHECK-NEXT:    [[TMP2:%.*]] = sext i8 [[TMP1]] to i32
191 ; CHECK-NEXT:    ret i32 [[TMP2]]
193   %s = lshr i8 %x, 7
194   %z = zext i8 %s to i32
195   %r = sub i32 0, %z
196   ret i32 %r
199 define <2 x i64> @neg_signbit_use1(<2 x i32> %x) {
200 ; CHECK-LABEL: @neg_signbit_use1(
201 ; CHECK-NEXT:    [[S:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 31, i32 poison>
202 ; CHECK-NEXT:    call void @usev2i32(<2 x i32> [[S]])
203 ; CHECK-NEXT:    [[TMP1:%.*]] = ashr <2 x i32> [[X]], <i32 31, i32 31>
204 ; CHECK-NEXT:    [[TMP2:%.*]] = sext <2 x i32> [[TMP1]] to <2 x i64>
205 ; CHECK-NEXT:    ret <2 x i64> [[TMP2]]
207   %s = lshr <2 x i32> %x, <i32 31, i32 poison>
208   call void @usev2i32(<2 x i32> %s)
209   %z = zext <2 x i32> %s to <2 x i64>
210   %r = sub <2 x i64> zeroinitializer, %z
211   ret <2 x i64> %r
214 ; negative test - extra use
216 define i8 @neg_signbit_use2(i5 %x) {
217 ; CHECK-LABEL: @neg_signbit_use2(
218 ; CHECK-NEXT:    [[S:%.*]] = lshr i5 [[X:%.*]], 4
219 ; CHECK-NEXT:    [[Z:%.*]] = zext nneg i5 [[S]] to i8
220 ; CHECK-NEXT:    call void @usei8(i8 [[Z]])
221 ; CHECK-NEXT:    [[R:%.*]] = sub nsw i8 0, [[Z]]
222 ; CHECK-NEXT:    ret i8 [[R]]
224   %s = lshr i5 %x, 4
225   %z = zext i5 %s to i8
226   call void @usei8(i8 %z)
227   %r = sub i8 0, %z
228   ret i8 %r
231 ; negative test - not negation
232 ; TODO: reduce to zext(x s> -1)
234 define i32 @neg_not_signbit1(i8 %x) {
235 ; CHECK-LABEL: @neg_not_signbit1(
236 ; CHECK-NEXT:    [[ISNOTNEG:%.*]] = icmp sgt i8 [[X:%.*]], -1
237 ; CHECK-NEXT:    [[R:%.*]] = zext i1 [[ISNOTNEG]] to i32
238 ; CHECK-NEXT:    ret i32 [[R]]
240   %s = lshr i8 %x, 7
241   %z = zext i8 %s to i32
242   %r = sub i32 1, %z
243   ret i32 %r
246 ; negative test - wrong shift amount
248 define i32 @neg_not_signbit2(i8 %x) {
249 ; CHECK-LABEL: @neg_not_signbit2(
250 ; CHECK-NEXT:    [[S:%.*]] = lshr i8 [[X:%.*]], 6
251 ; CHECK-NEXT:    [[Z:%.*]] = zext nneg i8 [[S]] to i32
252 ; CHECK-NEXT:    [[R:%.*]] = sub nsw i32 0, [[Z]]
253 ; CHECK-NEXT:    ret i32 [[R]]
255   %s = lshr i8 %x, 6
256   %z = zext i8 %s to i32
257   %r = sub i32 0, %z
258   ret i32 %r
261 ; negative test - wrong shift opcode
263 define i32 @neg_not_signbit3(i8 %x) {
264 ; CHECK-LABEL: @neg_not_signbit3(
265 ; CHECK-NEXT:    [[S:%.*]] = ashr i8 [[X:%.*]], 7
266 ; CHECK-NEXT:    [[Z:%.*]] = zext i8 [[S]] to i32
267 ; CHECK-NEXT:    [[R:%.*]] = sub nsw i32 0, [[Z]]
268 ; CHECK-NEXT:    ret i32 [[R]]
270   %s = ashr i8 %x, 7
271   %z = zext i8 %s to i32
272   %r = sub i32 0, %z
273   ret i32 %r
276 define i32 @neg_mask(i32 %x, i16 %y) {
277 ; CHECK-LABEL: @neg_mask(
278 ; CHECK-NEXT:    [[S:%.*]] = sext i16 [[Y:%.*]] to i32
279 ; CHECK-NEXT:    [[SUB1:%.*]] = sub nsw i32 [[X:%.*]], [[S]]
280 ; CHECK-NEXT:    [[ISNEG:%.*]] = icmp slt i16 [[Y]], 0
281 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[ISNEG]], i32 [[SUB1]], i32 0
282 ; CHECK-NEXT:    ret i32 [[R]]
284   %s = sext i16 %y to i32
285   %sub1 = sub nsw i32 %x, %s
286   %sh = lshr i16 %y, 15
287   %z = zext i16 %sh to i32
288   %sub2 = sub nsw i32 0, %z
289   %r = and i32 %sub1, %sub2
290   ret i32 %r
293 define i32 @neg_mask_const(i16 %x) {
294 ; CHECK-LABEL: @neg_mask_const(
295 ; CHECK-NEXT:    [[S:%.*]] = sext i16 [[X:%.*]] to i32
296 ; CHECK-NEXT:    [[SUB1:%.*]] = sub nsw i32 1000, [[S]]
297 ; CHECK-NEXT:    [[ISNEG:%.*]] = icmp slt i16 [[X]], 0
298 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[ISNEG]], i32 [[SUB1]], i32 0
299 ; CHECK-NEXT:    ret i32 [[R]]
301   %s = sext i16 %x to i32
302   %sub1 = sub nsw i32 1000, %s
303   %sh = lshr i16 %x, 15
304   %z = zext i16 %sh to i32
305   %sub2 = sub nsw i32 0, %z
306   %r = and i32 %sub1, %sub2
307   ret i32 %r
310 declare void @usei8(i8)
311 declare void @usev2i32(<2 x i32>)