[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / InstCombine / canonicalize-low-bit-mask-v4-and-icmp-eq-to-icmp-ule.ll
blob7a32c5e3f039778da74ac91bfe33524ada97d152
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -instcombine -S | FileCheck %s
4 ; https://bugs.llvm.org/show_bug.cgi?id=38123
6 ; Pattern:
7 ;   x & ((-1 << y) >> y) == x
8 ; Should be transformed into:
9 ;   x u<= ((-1 << y) >> y)
11 ; This pattern is uncanonical, but we can not canonicalize it due to extra uses.
13 declare void @use8(i8)
14 declare void @use2i8(<2 x i8>)
15 declare void @use3i8(<3 x i8>)
17 ; ============================================================================ ;
18 ; Basic positive tests
19 ; ============================================================================ ;
21 define i1 @p0(i8 %x, i8 %y) {
22 ; CHECK-LABEL: @p0(
23 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
24 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
25 ; CHECK-NEXT:    [[T1:%.*]] = lshr i8 [[T0]], [[Y]]
26 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp uge i8 [[T1]], [[X:%.*]]
27 ; CHECK-NEXT:    ret i1 [[TMP1]]
29   %t0 = shl i8 -1, %y
30   call void @use8(i8 %t0)
31   %t1 = lshr i8 %t0, %y
32   %t2 = and i8 %t1, %x
33   %ret = icmp eq i8 %t2, %x
34   ret i1 %ret
37 ; ============================================================================ ;
38 ; Vector tests
39 ; ============================================================================ ;
41 define <2 x i1> @p1_vec(<2 x i8> %x, <2 x i8> %y) {
42 ; CHECK-LABEL: @p1_vec(
43 ; CHECK-NEXT:    [[T0:%.*]] = shl <2 x i8> <i8 -1, i8 -1>, [[Y:%.*]]
44 ; CHECK-NEXT:    call void @use2i8(<2 x i8> [[T0]])
45 ; CHECK-NEXT:    [[T1:%.*]] = lshr <2 x i8> [[T0]], [[Y]]
46 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp uge <2 x i8> [[T1]], [[X:%.*]]
47 ; CHECK-NEXT:    ret <2 x i1> [[TMP1]]
49   %t0 = shl <2 x i8> <i8 -1, i8 -1>, %y
50   call void @use2i8(<2 x i8> %t0)
51   %t1 = lshr <2 x i8> %t0, %y
52   %t2 = and <2 x i8> %t1, %x
53   %ret = icmp eq <2 x i8> %t2, %x
54   ret <2 x i1> %ret
57 define <3 x i1> @p2_vec_undef0(<3 x i8> %x, <3 x i8> %y) {
58 ; CHECK-LABEL: @p2_vec_undef0(
59 ; CHECK-NEXT:    [[T0:%.*]] = shl <3 x i8> <i8 -1, i8 undef, i8 -1>, [[Y:%.*]]
60 ; CHECK-NEXT:    call void @use3i8(<3 x i8> [[T0]])
61 ; CHECK-NEXT:    [[T1:%.*]] = lshr <3 x i8> [[T0]], [[Y]]
62 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp uge <3 x i8> [[T1]], [[X:%.*]]
63 ; CHECK-NEXT:    ret <3 x i1> [[TMP1]]
65   %t0 = shl <3 x i8> <i8 -1, i8 undef, i8 -1>, %y
66   call void @use3i8(<3 x i8> %t0)
67   %t1 = lshr <3 x i8> %t0, %y
68   %t2 = and <3 x i8> %t1, %x
69   %ret = icmp eq <3 x i8> %t2, %x
70   ret <3 x i1> %ret
73 ; ============================================================================ ;
74 ; Commutativity tests.
75 ; ============================================================================ ;
77 declare i8 @gen8()
79 define i1 @c0(i8 %y) {
80 ; CHECK-LABEL: @c0(
81 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
82 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
83 ; CHECK-NEXT:    [[T1:%.*]] = lshr i8 [[T0]], [[Y]]
84 ; CHECK-NEXT:    [[X:%.*]] = call i8 @gen8()
85 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ule i8 [[X]], [[T1]]
86 ; CHECK-NEXT:    ret i1 [[TMP1]]
88   %t0 = shl i8 -1, %y
89   call void @use8(i8 %t0)
90   %t1 = lshr i8 %t0, %y
91   %x = call i8 @gen8()
92   %t2 = and i8 %x, %t1 ; swapped order
93   %ret = icmp eq i8 %t2, %x
94   ret i1 %ret
97 define i1 @c1(i8 %y) {
98 ; CHECK-LABEL: @c1(
99 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
100 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
101 ; CHECK-NEXT:    [[T1:%.*]] = lshr i8 [[T0]], [[Y]]
102 ; CHECK-NEXT:    [[X:%.*]] = call i8 @gen8()
103 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ule i8 [[X]], [[T1]]
104 ; CHECK-NEXT:    ret i1 [[TMP1]]
106   %t0 = shl i8 -1, %y
107   call void @use8(i8 %t0)
108   %t1 = lshr i8 %t0, %y
109   %x = call i8 @gen8()
110   %t2 = and i8 %t1, %x
111   %ret = icmp eq i8 %x, %t2 ; swapped order
112   ret i1 %ret
115 define i1 @c2(i8 %y) {
116 ; CHECK-LABEL: @c2(
117 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
118 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
119 ; CHECK-NEXT:    [[T1:%.*]] = lshr i8 [[T0]], [[Y]]
120 ; CHECK-NEXT:    [[X:%.*]] = call i8 @gen8()
121 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ule i8 [[X]], [[T1]]
122 ; CHECK-NEXT:    ret i1 [[TMP1]]
124   %t0 = shl i8 -1, %y
125   call void @use8(i8 %t0)
126   %t1 = lshr i8 %t0, %y
127   %x = call i8 @gen8()
128   %t2 = and i8 %x, %t1 ; swapped order
129   %ret = icmp eq i8 %x, %t2 ; swapped order
130   ret i1 %ret
133 ; ============================================================================ ;
134 ; One-use tests. We don't care about multi-uses here.
135 ; ============================================================================ ;
137 define i1 @oneuse0(i8 %x, i8 %y) {
138 ; CHECK-LABEL: @oneuse0(
139 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
140 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
141 ; CHECK-NEXT:    [[T1:%.*]] = lshr i8 [[T0]], [[Y]]
142 ; CHECK-NEXT:    call void @use8(i8 [[T1]])
143 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp uge i8 [[T1]], [[X:%.*]]
144 ; CHECK-NEXT:    ret i1 [[TMP1]]
146   %t0 = shl i8 -1, %y
147   call void @use8(i8 %t0) ; needed anyway
148   %t1 = lshr i8 %t0, %y
149   call void @use8(i8 %t1)
150   %t2 = and i8 %t1, %x
151   %ret = icmp eq i8 %t2, %x
152   ret i1 %ret
155 define i1 @oneuse1(i8 %x, i8 %y) {
156 ; CHECK-LABEL: @oneuse1(
157 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
158 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
159 ; CHECK-NEXT:    [[T1:%.*]] = lshr i8 [[T0]], [[Y]]
160 ; CHECK-NEXT:    [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
161 ; CHECK-NEXT:    call void @use8(i8 [[T2]])
162 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp uge i8 [[T1]], [[X]]
163 ; CHECK-NEXT:    ret i1 [[TMP1]]
165   %t0 = shl i8 -1, %y
166   call void @use8(i8 %t0) ; needed anyway
167   %t1 = lshr i8 %t0, %y
168   %t2 = and i8 %t1, %x
169   call void @use8(i8 %t2)
170   %ret = icmp eq i8 %t2, %x
171   ret i1 %ret
174 define i1 @oneuse2(i8 %x, i8 %y) {
175 ; CHECK-LABEL: @oneuse2(
176 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
177 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
178 ; CHECK-NEXT:    [[T1:%.*]] = lshr i8 [[T0]], [[Y]]
179 ; CHECK-NEXT:    call void @use8(i8 [[T1]])
180 ; CHECK-NEXT:    [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
181 ; CHECK-NEXT:    call void @use8(i8 [[T2]])
182 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp uge i8 [[T1]], [[X]]
183 ; CHECK-NEXT:    ret i1 [[TMP1]]
185   %t0 = shl i8 -1, %y
186   call void @use8(i8 %t0)
187   %t1 = lshr i8 %t0, %y
188   call void @use8(i8 %t1)
189   %t2 = and i8 %t1, %x
190   call void @use8(i8 %t2)
191   %ret = icmp eq i8 %t2, %x
192   ret i1 %ret
195 ; ============================================================================ ;
196 ; Negative tests
197 ; ============================================================================ ;
199 define i1 @n0(i8 %x, i8 %y, i8 %notx) {
200 ; CHECK-LABEL: @n0(
201 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
202 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
203 ; CHECK-NEXT:    [[T1:%.*]] = lshr i8 [[T0]], [[Y]]
204 ; CHECK-NEXT:    [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
205 ; CHECK-NEXT:    [[RET:%.*]] = icmp eq i8 [[T2]], [[NOTX:%.*]]
206 ; CHECK-NEXT:    ret i1 [[RET]]
208   %t0 = shl i8 -1, %y
209   call void @use8(i8 %t0)
210   %t1 = lshr i8 %t0, %y
211   %t2 = and i8 %t1, %x
212   %ret = icmp eq i8 %t2, %notx ; not %x
213   ret i1 %ret
216 define i1 @n1(i8 %x, i8 %y) {
217 ; CHECK-LABEL: @n1(
218 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 1, [[Y:%.*]]
219 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
220 ; CHECK-NEXT:    [[T1:%.*]] = lshr i8 [[T0]], [[Y]]
221 ; CHECK-NEXT:    [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
222 ; CHECK-NEXT:    [[RET:%.*]] = icmp eq i8 [[T2]], [[X]]
223 ; CHECK-NEXT:    ret i1 [[RET]]
225   %t0 = shl i8 1, %y ; not -1
226   call void @use8(i8 %t0)
227   %t1 = lshr i8 %t0, %y
228   %t2 = and i8 %t1, %x
229   %ret = icmp eq i8 %t2, %x
230   ret i1 %ret
233 define i1 @n2(i8 %x, i8 %y1, i8 %y2) {
234 ; CHECK-LABEL: @n2(
235 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 -1, [[Y1:%.*]]
236 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
237 ; CHECK-NEXT:    [[T1:%.*]] = lshr i8 [[T0]], [[Y2:%.*]]
238 ; CHECK-NEXT:    [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
239 ; CHECK-NEXT:    [[RET:%.*]] = icmp eq i8 [[T2]], [[X]]
240 ; CHECK-NEXT:    ret i1 [[RET]]
242   %t0 = shl i8 -1, %y1 ; not %y2
243   call void @use8(i8 %t0)
244   %t1 = lshr i8 %t0, %y2 ; not %y1
245   %t2 = and i8 %t1, %x
246   %ret = icmp eq i8 %t2, %x
247   ret i1 %ret