[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / InstCombine / exact.ll
blobe87e12cc1bea16f291259e93f47e495ae64db618
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -instcombine -S | FileCheck %s
4 define i32 @sdiv1(i32 %x) {
5 ; CHECK-LABEL: @sdiv1(
6 ; CHECK-NEXT:    [[Y:%.*]] = sdiv i32 [[X:%.*]], 8
7 ; CHECK-NEXT:    ret i32 [[Y]]
9   %y = sdiv i32 %x, 8
10   ret i32 %y
13 define i32 @sdiv2(i32 %x) {
14 ; CHECK-LABEL: @sdiv2(
15 ; CHECK-NEXT:    [[Y:%.*]] = ashr exact i32 [[X:%.*]], 3
16 ; CHECK-NEXT:    ret i32 [[Y]]
18   %y = sdiv exact i32 %x, 8
19   ret i32 %y
22 define <2 x i32> @sdiv2_vec(<2 x i32> %x) {
23 ; CHECK-LABEL: @sdiv2_vec(
24 ; CHECK-NEXT:    [[Y:%.*]] = ashr exact <2 x i32> [[X:%.*]], <i32 7, i32 7>
25 ; CHECK-NEXT:    ret <2 x i32> [[Y]]
27   %y = sdiv exact <2 x i32> %x, <i32 128, i32 128>
28   ret <2 x i32> %y
31 define i32 @sdiv3(i32 %x) {
32 ; CHECK-LABEL: @sdiv3(
33 ; CHECK-NEXT:    [[TMP1:%.*]] = srem i32 [[X:%.*]], 3
34 ; CHECK-NEXT:    [[Z:%.*]] = sub i32 [[X]], [[TMP1]]
35 ; CHECK-NEXT:    ret i32 [[Z]]
37   %y = sdiv i32 %x, 3
38   %z = mul i32 %y, 3
39   ret i32 %z
42 define i32 @sdiv4(i32 %x) {
43 ; CHECK-LABEL: @sdiv4(
44 ; CHECK-NEXT:    ret i32 [[X:%.*]]
46   %y = sdiv exact i32 %x, 3
47   %z = mul i32 %y, 3
48   ret i32 %z
51 define i32 @sdiv5(i32 %x) {
52 ; CHECK-LABEL: @sdiv5(
53 ; CHECK-NEXT:    [[TMP1:%.*]] = srem i32 [[X:%.*]], 3
54 ; CHECK-NEXT:    [[Z:%.*]] = sub i32 [[TMP1]], [[X]]
55 ; CHECK-NEXT:    ret i32 [[Z]]
57   %y = sdiv i32 %x, 3
58   %z = mul i32 %y, -3
59   ret i32 %z
62 define i32 @sdiv6(i32 %x) {
63 ; CHECK-LABEL: @sdiv6(
64 ; CHECK-NEXT:    [[Z:%.*]] = sub i32 0, [[X:%.*]]
65 ; CHECK-NEXT:    ret i32 [[Z]]
67   %y = sdiv exact i32 %x, 3
68   %z = mul i32 %y, -3
69   ret i32 %z
72 define i32 @udiv1(i32 %x, i32 %w) {
73 ; CHECK-LABEL: @udiv1(
74 ; CHECK-NEXT:    ret i32 [[X:%.*]]
76   %y = udiv exact i32 %x, %w
77   %z = mul i32 %y, %w
78   ret i32 %z
81 define i32 @udiv2(i32 %x, i32 %w) {
82 ; CHECK-LABEL: @udiv2(
83 ; CHECK-NEXT:    [[Z:%.*]] = lshr exact i32 [[X:%.*]], [[W:%.*]]
84 ; CHECK-NEXT:    ret i32 [[Z]]
86   %y = shl i32 1, %w
87   %z = udiv exact i32 %x, %y
88   ret i32 %z
91 define i64 @ashr1(i64 %X) {
92 ; CHECK-LABEL: @ashr1(
93 ; CHECK-NEXT:    [[A:%.*]] = shl i64 [[X:%.*]], 8
94 ; CHECK-NEXT:    [[B:%.*]] = ashr exact i64 [[A]], 2
95 ; CHECK-NEXT:    ret i64 [[B]]
97   %A = shl i64 %X, 8
98   %B = ashr i64 %A, 2
99   ret i64 %B
102 ; The vector ashr should be exact (like it is in the preceding test).
104 define <2 x i64> @ashr1_vec(<2 x i64> %X) {
105 ; CHECK-LABEL: @ashr1_vec(
106 ; CHECK-NEXT:    [[A:%.*]] = shl <2 x i64> [[X:%.*]], <i64 8, i64 8>
107 ; CHECK-NEXT:    [[B:%.*]] = ashr exact <2 x i64> [[A]], <i64 2, i64 2>
108 ; CHECK-NEXT:    ret <2 x i64> [[B]]
110   %A = shl <2 x i64> %X, <i64 8, i64 8>
111   %B = ashr <2 x i64> %A, <i64 2, i64 2>
112   ret <2 x i64> %B
115 ; PR9120
116 define i1 @ashr_icmp1(i64 %X) {
117 ; CHECK-LABEL: @ashr_icmp1(
118 ; CHECK-NEXT:    [[B:%.*]] = icmp eq i64 [[X:%.*]], 0
119 ; CHECK-NEXT:    ret i1 [[B]]
121   %A = ashr exact i64 %X, 2   ; X/4
122   %B = icmp eq i64 %A, 0
123   ret i1 %B
126 define i1 @ashr_icmp2(i64 %X) {
127 ; CHECK-LABEL: @ashr_icmp2(
128 ; CHECK-NEXT:    [[Z:%.*]] = icmp slt i64 [[X:%.*]], 16
129 ; CHECK-NEXT:    ret i1 [[Z]]
131   %Y = ashr exact i64 %X, 2  ; x / 4
132   %Z = icmp slt i64 %Y, 4    ; x < 16
133   ret i1 %Z
136 define <2 x i1> @ashr_icmp2_vec(<2 x i64> %X) {
137 ; CHECK-LABEL: @ashr_icmp2_vec(
138 ; CHECK-NEXT:    [[Z:%.*]] = icmp slt <2 x i64> [[X:%.*]], <i64 16, i64 16>
139 ; CHECK-NEXT:    ret <2 x i1> [[Z]]
141   %Y = ashr exact <2 x i64> %X, <i64 2, i64 2>
142   %Z = icmp slt <2 x i64> %Y, <i64 4, i64 4>
143   ret <2 x i1> %Z
146 ; PR9998
147 ; Make sure we don't transform the ashr here into an sdiv
148 define i1 @pr9998(i32 %V) {
149 ; CHECK-LABEL: @pr9998(
150 ; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[V:%.*]], 1
151 ; CHECK-NEXT:    [[Z:%.*]] = icmp ne i32 [[TMP1]], 0
152 ; CHECK-NEXT:    ret i1 [[Z]]
154   %W = shl i32 %V, 31
155   %X = ashr exact i32 %W, 31
156   %Y = sext i32 %X to i64
157   %Z = icmp ugt i64 %Y, 7297771788697658747
158   ret i1 %Z
161 ; FIXME: Vectors should fold the same way.
162 define <2 x i1> @pr9998vec(<2 x i32> %V) {
163 ; CHECK-LABEL: @pr9998vec(
164 ; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i32> [[V:%.*]], <i32 1, i32 1>
165 ; CHECK-NEXT:    [[X:%.*]] = sub nsw <2 x i32> zeroinitializer, [[TMP1]]
166 ; CHECK-NEXT:    [[Y:%.*]] = sext <2 x i32> [[X]] to <2 x i64>
167 ; CHECK-NEXT:    [[Z:%.*]] = icmp ugt <2 x i64> [[Y]], <i64 7297771788697658747, i64 7297771788697658747>
168 ; CHECK-NEXT:    ret <2 x i1> [[Z]]
170   %W = shl <2 x i32> %V, <i32 31, i32 31>
171   %X = ashr exact <2 x i32> %W, <i32 31, i32 31>
172   %Y = sext <2 x i32> %X to <2 x i64>
173   %Z = icmp ugt <2 x i64> %Y, <i64 7297771788697658747, i64 7297771788697658747>
174   ret <2 x i1> %Z
177 define i1 @udiv_icmp1(i64 %X) {
178 ; CHECK-LABEL: @udiv_icmp1(
179 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i64 [[X:%.*]], 0
180 ; CHECK-NEXT:    ret i1 [[TMP1]]
182   %A = udiv exact i64 %X, 5   ; X/5
183   %B = icmp ne i64 %A, 0
184   ret i1 %B
187 define <2 x i1> @udiv_icmp1_vec(<2 x i64> %X) {
188 ; CHECK-LABEL: @udiv_icmp1_vec(
189 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne <2 x i64> [[X:%.*]], zeroinitializer
190 ; CHECK-NEXT:    ret <2 x i1> [[TMP1]]
192   %A = udiv exact <2 x i64> %X, <i64 5, i64 5>
193   %B = icmp ne <2 x i64> %A, zeroinitializer
194   ret <2 x i1> %B
197 define i1 @udiv_icmp2(i64 %X) {
198 ; CHECK-LABEL: @udiv_icmp2(
199 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i64 [[X:%.*]], 0
200 ; CHECK-NEXT:    ret i1 [[TMP1]]
202   %A = udiv exact i64 %X, 5   ; X/5 == 0 --> x == 0
203   %B = icmp eq i64 %A, 0
204   ret i1 %B
207 define <2 x i1> @udiv_icmp2_vec(<2 x i64> %X) {
208 ; CHECK-LABEL: @udiv_icmp2_vec(
209 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <2 x i64> [[X:%.*]], zeroinitializer
210 ; CHECK-NEXT:    ret <2 x i1> [[TMP1]]
212   %A = udiv exact <2 x i64> %X, <i64 5, i64 5>
213   %B = icmp eq <2 x i64> %A, zeroinitializer
214   ret <2 x i1> %B
217 define i1 @sdiv_icmp1(i64 %X) {
218 ; CHECK-LABEL: @sdiv_icmp1(
219 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i64 [[X:%.*]], 0
220 ; CHECK-NEXT:    ret i1 [[TMP1]]
222   %A = sdiv exact i64 %X, 5   ; X/5 == 0 --> x == 0
223   %B = icmp eq i64 %A, 0
224   ret i1 %B
227 define <2 x i1> @sdiv_icmp1_vec(<2 x i64> %X) {
228 ; CHECK-LABEL: @sdiv_icmp1_vec(
229 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <2 x i64> [[X:%.*]], zeroinitializer
230 ; CHECK-NEXT:    ret <2 x i1> [[TMP1]]
232   %A = sdiv exact <2 x i64> %X, <i64 5, i64 5>
233   %B = icmp eq <2 x i64> %A, zeroinitializer
234   ret <2 x i1> %B
237 define i1 @sdiv_icmp2(i64 %X) {
238 ; CHECK-LABEL: @sdiv_icmp2(
239 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i64 [[X:%.*]], 5
240 ; CHECK-NEXT:    ret i1 [[TMP1]]
242   %A = sdiv exact i64 %X, 5   ; X/5 == 1 --> x == 5
243   %B = icmp eq i64 %A, 1
244   ret i1 %B
247 define <2 x i1> @sdiv_icmp2_vec(<2 x i64> %X) {
248 ; CHECK-LABEL: @sdiv_icmp2_vec(
249 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <2 x i64> [[X:%.*]], <i64 5, i64 5>
250 ; CHECK-NEXT:    ret <2 x i1> [[TMP1]]
252   %A = sdiv exact <2 x i64> %X, <i64 5, i64 5>
253   %B = icmp eq <2 x i64> %A, <i64 1, i64 1>
254   ret <2 x i1> %B
257 define i1 @sdiv_icmp3(i64 %X) {
258 ; CHECK-LABEL: @sdiv_icmp3(
259 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i64 [[X:%.*]], -5
260 ; CHECK-NEXT:    ret i1 [[TMP1]]
262   %A = sdiv exact i64 %X, 5   ; X/5 == -1 --> x == -5
263   %B = icmp eq i64 %A, -1
264   ret i1 %B
267 define <2 x i1> @sdiv_icmp3_vec(<2 x i64> %X) {
268 ; CHECK-LABEL: @sdiv_icmp3_vec(
269 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <2 x i64> [[X:%.*]], <i64 -5, i64 -5>
270 ; CHECK-NEXT:    ret <2 x i1> [[TMP1]]
272   %A = sdiv exact <2 x i64> %X, <i64 5, i64 5>
273   %B = icmp eq <2 x i64> %A, <i64 -1, i64 -1>
274   ret <2 x i1> %B
277 define i1 @sdiv_icmp4(i64 %X) {
278 ; CHECK-LABEL: @sdiv_icmp4(
279 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i64 [[X:%.*]], 0
280 ; CHECK-NEXT:    ret i1 [[TMP1]]
282   %A = sdiv exact i64 %X, -5   ; X/-5 == 0 --> x == 0
283   %B = icmp eq i64 %A, 0
284   ret i1 %B
287 define <2 x i1> @sdiv_icmp4_vec(<2 x i64> %X) {
288 ; CHECK-LABEL: @sdiv_icmp4_vec(
289 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <2 x i64> [[X:%.*]], zeroinitializer
290 ; CHECK-NEXT:    ret <2 x i1> [[TMP1]]
292   %A = sdiv exact <2 x i64> %X, <i64 -5, i64 -5>
293   %B = icmp eq <2 x i64> %A, zeroinitializer
294   ret <2 x i1> %B
297 define i1 @sdiv_icmp5(i64 %X) {
298 ; CHECK-LABEL: @sdiv_icmp5(
299 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i64 [[X:%.*]], -5
300 ; CHECK-NEXT:    ret i1 [[TMP1]]
302   %A = sdiv exact i64 %X, -5   ; X/-5 == 1 --> x == -5
303   %B = icmp eq i64 %A, 1
304   ret i1 %B
307 define <2 x i1> @sdiv_icmp5_vec(<2 x i64> %X) {
308 ; CHECK-LABEL: @sdiv_icmp5_vec(
309 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <2 x i64> [[X:%.*]], <i64 -5, i64 -5>
310 ; CHECK-NEXT:    ret <2 x i1> [[TMP1]]
312   %A = sdiv exact <2 x i64> %X, <i64 -5, i64 -5>
313   %B = icmp eq <2 x i64> %A, <i64 1, i64 1>
314   ret <2 x i1> %B
317 define i1 @sdiv_icmp6(i64 %X) {
318 ; CHECK-LABEL: @sdiv_icmp6(
319 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i64 [[X:%.*]], 5
320 ; CHECK-NEXT:    ret i1 [[TMP1]]
322   %A = sdiv exact i64 %X, -5   ; X/-5 == -1 --> x == 5
323   %B = icmp eq i64 %A, -1
324   ret i1 %B
327 define <2 x i1> @sdiv_icmp6_vec(<2 x i64> %X) {
328 ; CHECK-LABEL: @sdiv_icmp6_vec(
329 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <2 x i64> [[X:%.*]], <i64 5, i64 5>
330 ; CHECK-NEXT:    ret <2 x i1> [[TMP1]]
332   %A = sdiv exact <2 x i64> %X, <i64 -5, i64 -5>
333   %B = icmp eq <2 x i64> %A, <i64 -1, i64 -1>
334   ret <2 x i1> %B