[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / InstCombine / or-shifted-masks.ll
blobd67b4597a9df9dc69c6fca9b99e0ad6c3838c7e2
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -instcombine < %s | FileCheck %s
4 define i32 @or_and_shifts1(i32 %x) {
5 ; CHECK-LABEL: @or_and_shifts1(
6 ; CHECK-NEXT:    [[TMP1:%.*]] = shl i32 [[X:%.*]], 3
7 ; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[TMP1]], 8
8 ; CHECK-NEXT:    [[TMP3:%.*]] = shl i32 [[X]], 5
9 ; CHECK-NEXT:    [[TMP4:%.*]] = and i32 [[TMP3]], 32
10 ; CHECK-NEXT:    [[TMP5:%.*]] = or i32 [[TMP2]], [[TMP4]]
11 ; CHECK-NEXT:    ret i32 [[TMP5]]
13   %1 = shl i32 %x, 3
14   %2 = and i32 %1, 15
15   %3 = shl i32 %x, 5
16   %4 = and i32 %3, 60
17   %5 = or i32 %2, %4
18   ret i32 %5
21 define i32 @or_and_shifts2(i32 %x) {
22 ; CHECK-LABEL: @or_and_shifts2(
23 ; CHECK-NEXT:    [[TMP1:%.*]] = shl i32 [[X:%.*]], 3
24 ; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[TMP1]], 896
25 ; CHECK-NEXT:    [[TMP3:%.*]] = lshr i32 [[X]], 4
26 ; CHECK-NEXT:    [[TMP4:%.*]] = and i32 [[TMP3]], 7
27 ; CHECK-NEXT:    [[TMP5:%.*]] = or i32 [[TMP2]], [[TMP4]]
28 ; CHECK-NEXT:    ret i32 [[TMP5]]
30   %1 = shl i32 %x, 3
31   %2 = and i32 %1, 896
32   %3 = lshr i32 %x, 4
33   %4 = and i32 %3, 7
34   %5 = or i32 %2, %4
35   ret i32 %5
38 define i32 @or_and_shift_shift_and(i32 %x) {
39 ; CHECK-LABEL: @or_and_shift_shift_and(
40 ; CHECK-NEXT:    [[TMP1:%.*]] = shl i32 [[X:%.*]], 3
41 ; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[TMP1]], 56
42 ; CHECK-NEXT:    [[TMP3:%.*]] = shl i32 [[X]], 2
43 ; CHECK-NEXT:    [[TMP4:%.*]] = and i32 [[TMP3]], 28
44 ; CHECK-NEXT:    [[TMP5:%.*]] = or i32 [[TMP2]], [[TMP4]]
45 ; CHECK-NEXT:    ret i32 [[TMP5]]
47   %1 = and i32 %x, 7
48   %2 = shl i32 %1, 3
49   %3 = shl i32 %x, 2
50   %4 = and i32 %3, 28
51   %5 = or i32 %2, %4
52   ret i32 %5
55 define i32 @multiuse1(i32 %x) {
56 ; CHECK-LABEL: @multiuse1(
57 ; CHECK-NEXT:    [[TMP1:%.*]] = shl i32 [[X:%.*]], 6
58 ; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[TMP1]], 384
59 ; CHECK-NEXT:    [[TMP3:%.*]] = lshr i32 [[X]], 1
60 ; CHECK-NEXT:    [[TMP4:%.*]] = and i32 [[TMP3]], 3
61 ; CHECK-NEXT:    [[TMP5:%.*]] = or i32 [[TMP4]], [[TMP2]]
62 ; CHECK-NEXT:    ret i32 [[TMP5]]
64   %1 = and i32 %x, 2
65   %2 = and i32 %x, 4
66   %3 = shl nuw nsw i32 %1, 6
67   %4 = lshr exact i32 %1, 1
68   %5 = shl nuw nsw i32 %2, 6
69   %6 = lshr exact i32 %2, 1
70   %7 = or i32 %3, %5
71   %8 = or i32 %4, %6
72   %9 = or i32 %8, %7
73   ret i32 %9
76 define i32 @multiuse2(i32 %x) {
77 ; CHECK-LABEL: @multiuse2(
78 ; CHECK-NEXT:    [[TMP1:%.*]] = shl i32 [[X:%.*]], 1
79 ; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[TMP1]], 12
80 ; CHECK-NEXT:    [[TMP3:%.*]] = shl i32 [[X]], 8
81 ; CHECK-NEXT:    [[TMP4:%.*]] = and i32 [[TMP3]], 24576
82 ; CHECK-NEXT:    [[TMP5:%.*]] = shl i32 [[X]], 8
83 ; CHECK-NEXT:    [[TMP6:%.*]] = and i32 [[TMP5]], 7680
84 ; CHECK-NEXT:    [[TMP7:%.*]] = or i32 [[TMP4]], [[TMP6]]
85 ; CHECK-NEXT:    [[TMP8:%.*]] = shl i32 [[X]], 1
86 ; CHECK-NEXT:    [[TMP9:%.*]] = and i32 [[TMP8]], 240
87 ; CHECK-NEXT:    [[TMP10:%.*]] = or i32 [[TMP2]], [[TMP9]]
88 ; CHECK-NEXT:    [[TMP11:%.*]] = or i32 [[TMP7]], [[TMP10]]
89 ; CHECK-NEXT:    ret i32 [[TMP11]]
91   %1 = and i32 %x, 6
92   %2 = shl nuw nsw i32 %1, 8
93   %3 = shl nuw nsw i32 %1, 1
94   %4 = and i32 %x, 24
95   %5 = shl nuw nsw i32 %4, 8
96   %6 = shl nuw nsw i32 %4, 1
97   %7 = and i32 %x, 96
98   %8 = shl nuw nsw i32 %7, 8
99   %9 = shl nuw nsw i32 %7, 1
100   %10 = or i32 %2, %5
101   %11 = or i32 %8, %10
102   %12 = or i32 %9, %6
103   %13 = or i32 %3, %12
104   %14 = or i32 %11, %13
105   ret i32 %14
108 define i32 @multiuse3(i32 %x) {
109 ; CHECK-LABEL: @multiuse3(
110 ; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[X:%.*]], 96
111 ; CHECK-NEXT:    [[TMP2:%.*]] = shl nuw nsw i32 [[TMP1]], 6
112 ; CHECK-NEXT:    [[TMP3:%.*]] = lshr exact i32 [[TMP1]], 1
113 ; CHECK-NEXT:    [[TMP4:%.*]] = shl i32 [[X]], 6
114 ; CHECK-NEXT:    [[TMP5:%.*]] = and i32 [[TMP4]], 1920
115 ; CHECK-NEXT:    [[TMP6:%.*]] = or i32 [[TMP2]], [[TMP5]]
116 ; CHECK-NEXT:    [[TMP7:%.*]] = lshr i32 [[X]], 1
117 ; CHECK-NEXT:    [[TMP8:%.*]] = and i32 [[TMP7]], 15
118 ; CHECK-NEXT:    [[TMP9:%.*]] = or i32 [[TMP3]], [[TMP8]]
119 ; CHECK-NEXT:    [[TMP10:%.*]] = or i32 [[TMP9]], [[TMP6]]
120 ; CHECK-NEXT:    ret i32 [[TMP10]]
122   %1 = and i32 %x, 96
123   %2 = shl nuw nsw i32 %1, 6
124   %3 = lshr exact i32 %1, 1
125   %4 = shl i32 %x, 6
126   %5 = and i32 %4, 1920
127   %6 = or i32 %2, %5
128   %7 = lshr i32 %x, 1
129   %8 = and i32 %7, 15
130   %9 = or i32 %3, %8
131   %10 = or i32 %9, %6
132   ret i32 %10
135 define i32 @multiuse4(i32 %x) local_unnamed_addr #0 {
136 ; CHECK-LABEL: @multiuse4(
137 ; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[X:%.*]], 100663296
138 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp sgt i32 [[X]], -1
139 ; CHECK-NEXT:    br i1 [[TMP2]], label [[IF:%.*]], label [[ELSE:%.*]]
140 ; CHECK:       if:
141 ; CHECK-NEXT:    [[TMP3:%.*]] = lshr exact i32 [[TMP1]], 22
142 ; CHECK-NEXT:    [[TMP4:%.*]] = lshr i32 [[X]], 22
143 ; CHECK-NEXT:    [[TMP5:%.*]] = and i32 [[TMP4]], 480
144 ; CHECK-NEXT:    [[TMP6:%.*]] = or i32 [[TMP5]], [[TMP3]]
145 ; CHECK-NEXT:    br label [[END:%.*]]
146 ; CHECK:       else:
147 ; CHECK-NEXT:    [[TMP7:%.*]] = lshr exact i32 [[TMP1]], 17
148 ; CHECK-NEXT:    [[TMP8:%.*]] = lshr i32 [[X]], 17
149 ; CHECK-NEXT:    [[TMP9:%.*]] = and i32 [[TMP8]], 15360
150 ; CHECK-NEXT:    [[TMP10:%.*]] = or i32 [[TMP9]], [[TMP7]]
151 ; CHECK-NEXT:    br label [[END]]
152 ; CHECK:       end:
153 ; CHECK-NEXT:    [[TMP11:%.*]] = phi i32 [ [[TMP6]], [[IF]] ], [ [[TMP10]], [[ELSE]] ]
154 ; CHECK-NEXT:    ret i32 [[TMP11]]
156   %1 = and i32 %x, 100663296
157   %2 = icmp sgt i32 %x, -1
158   br i1 %2, label %if, label %else
161   %3 = lshr exact i32 %1, 22
162   %4 = lshr i32 %x, 22
163   %5 = and i32 %4, 480
164   %6 = or i32 %5, %3
165   br label %end
167 else:
168   %7 = lshr exact i32 %1, 17
169   %8 = lshr i32 %x, 17
170   %9 = and i32 %8, 15360
171   %10 = or i32 %9, %7
172   br label %end
174 end:
175   %11 = phi i32 [ %6, %if ], [ %10, %else ]
176   ret i32 %11
179 define i32 @multiuse5(i32 %x) local_unnamed_addr #0 {
180 ; CHECK-LABEL: @multiuse5(
181 ; CHECK-NEXT:    [[TMP1:%.*]] = shl i32 [[X:%.*]], 5
182 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp sgt i32 [[X]], -1
183 ; CHECK-NEXT:    br i1 [[TMP2]], label [[IF:%.*]], label [[ELSE:%.*]]
184 ; CHECK:       if:
185 ; CHECK-NEXT:    [[TMP3:%.*]] = and i32 [[TMP1]], 21760
186 ; CHECK-NEXT:    [[TMP4:%.*]] = shl i32 [[X]], 5
187 ; CHECK-NEXT:    [[TMP5:%.*]] = and i32 [[TMP4]], 43520
188 ; CHECK-NEXT:    [[TMP6:%.*]] = or i32 [[TMP5]], [[TMP3]]
189 ; CHECK-NEXT:    br label [[END:%.*]]
190 ; CHECK:       else:
191 ; CHECK-NEXT:    [[TMP7:%.*]] = and i32 [[TMP1]], 5570560
192 ; CHECK-NEXT:    [[TMP8:%.*]] = shl i32 [[X]], 5
193 ; CHECK-NEXT:    [[TMP9:%.*]] = and i32 [[TMP8]], 11141120
194 ; CHECK-NEXT:    [[TMP10:%.*]] = or i32 [[TMP9]], [[TMP7]]
195 ; CHECK-NEXT:    br label [[END]]
196 ; CHECK:       end:
197 ; CHECK-NEXT:    [[TMP11:%.*]] = phi i32 [ [[TMP6]], [[IF]] ], [ [[TMP10]], [[ELSE]] ]
198 ; CHECK-NEXT:    ret i32 [[TMP11]]
200   %1 = shl i32 %x, 5
201   %2 = icmp sgt i32 %x, -1
202   br i1 %2, label %if, label %else
205   %3 = and i32 %1, 21760
206   %4 = and i32 %x, 1360
207   %5 = shl nuw nsw i32 %4, 5
208   %6 = or i32 %5, %3
209   br label %end
211 else:
212   %7 = and i32 %1, 5570560
213   %8 = and i32 %x, 348160
214   %9 = shl nuw nsw i32 %8, 5
215   %10 = or i32 %9, %7
216   br label %end
218 end:
219   %11 = phi i32 [ %6, %if ], [ %10, %else ]
220   ret i32 %11
223 define i32 @shl_mask(i32 %x) {
224 ; CHECK-LABEL: @shl_mask(
225 ; CHECK-NEXT:    [[Z:%.*]] = and i32 [[X:%.*]], 255
226 ; CHECK-NEXT:    [[S:%.*]] = shl nuw nsw i32 [[Z]], 8
227 ; CHECK-NEXT:    [[R:%.*]] = or i32 [[Z]], [[S]]
228 ; CHECK-NEXT:    ret i32 [[R]]
230   %z = and i32 %x, 255
231   %s = shl i32 %z, 8
232   %r = or i32 %z, %s
233   ret i32 %r
236 define i32 @shl_mask_wrong_shl_const(i32 %x) {
237 ; CHECK-LABEL: @shl_mask_wrong_shl_const(
238 ; CHECK-NEXT:    [[Z:%.*]] = and i32 [[X:%.*]], 255
239 ; CHECK-NEXT:    [[S:%.*]] = shl nuw nsw i32 [[Z]], 7
240 ; CHECK-NEXT:    [[R:%.*]] = or i32 [[Z]], [[S]]
241 ; CHECK-NEXT:    ret i32 [[R]]
243   %z = and i32 %x, 255
244   %s = shl i32 %z, 7
245   %r = or i32 %z, %s
246   ret i32 %r
249 define i37 @shl_mask_weird_type(i37 %x) {
250 ; CHECK-LABEL: @shl_mask_weird_type(
251 ; CHECK-NEXT:    [[Z:%.*]] = and i37 [[X:%.*]], 255
252 ; CHECK-NEXT:    [[S:%.*]] = shl nuw nsw i37 [[Z]], 8
253 ; CHECK-NEXT:    [[R:%.*]] = or i37 [[Z]], [[S]]
254 ; CHECK-NEXT:    ret i37 [[R]]
256   %z = and i37 %x, 255
257   %s = shl i37 %z, 8
258   %r = or i37 %z, %s
259   ret i37 %r
262 define i32 @shl_mask_extra_use(i32 %x, i32* %p) {
263 ; CHECK-LABEL: @shl_mask_extra_use(
264 ; CHECK-NEXT:    [[Z:%.*]] = and i32 [[X:%.*]], 255
265 ; CHECK-NEXT:    [[S:%.*]] = shl nuw nsw i32 [[Z]], 8
266 ; CHECK-NEXT:    store i32 [[S]], i32* [[P:%.*]], align 4
267 ; CHECK-NEXT:    [[R:%.*]] = or i32 [[Z]], [[S]]
268 ; CHECK-NEXT:    ret i32 [[R]]
270   %z = and i32 %x, 255
271   %s = shl i32 %z, 8
272   store i32 %s, i32* %p
273   %r = or i32 %z, %s
274   ret i32 %r
277 ; This could be "Z * 65793".
279 define i32 @shl_mul_mask(i32 %x) {
280 ; CHECK-LABEL: @shl_mul_mask(
281 ; CHECK-NEXT:    [[Z:%.*]] = and i32 [[X:%.*]], 255
282 ; CHECK-NEXT:    [[M:%.*]] = mul nuw nsw i32 [[Z]], 65537
283 ; CHECK-NEXT:    [[S:%.*]] = shl nuw nsw i32 [[Z]], 8
284 ; CHECK-NEXT:    [[R:%.*]] = or i32 [[M]], [[S]]
285 ; CHECK-NEXT:    ret i32 [[R]]
287   %z = and i32 %x, 255
288   %m = mul i32 %z, 65537
289   %s = shl i32 %z, 8
290   %r = or i32 %m, %s
291   ret i32 %r
294 define i32 @shl_mul_mask_wrong_mul_const(i32 %x) {
295 ; CHECK-LABEL: @shl_mul_mask_wrong_mul_const(
296 ; CHECK-NEXT:    [[Z:%.*]] = and i32 [[X:%.*]], 255
297 ; CHECK-NEXT:    [[M:%.*]] = mul nuw nsw i32 [[Z]], 65535
298 ; CHECK-NEXT:    [[S:%.*]] = shl nuw nsw i32 [[Z]], 8
299 ; CHECK-NEXT:    [[R:%.*]] = or i32 [[M]], [[S]]
300 ; CHECK-NEXT:    ret i32 [[R]]
302   %z = and i32 %x, 255
303   %m = mul i32 %z, 65535
304   %s = shl i32 %z, 8
305   %r = or i32 %m, %s
306   ret i32 %r