Skip to content

Commit 08de59b

Browse files
committed
[NFC][InstCombine] Tests for "fold variable mask before variable shift-of-trunc" (PR42563)
https://bugs.llvm.org/show_bug.cgi?id=42563 llvm-svn: 375135
1 parent 780f555 commit 08de59b

11 files changed

+2430
-0
lines changed
Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2+
; RUN: opt %s -instcombine -S | FileCheck %s
3+
4+
; If we have some pattern that leaves only some low bits set, and then performs
5+
; left-shift of those bits, we can combine those two shifts into a shift+mask.
6+
7+
; There are many variants to this pattern:
8+
; a) (trunc (x & ((1 << maskNbits) - 1))) << shiftNbits
9+
; simplify to:
10+
; ((trunc(x)) << shiftNbits) & (~(-1 << (maskNbits+shiftNbits)))
11+
12+
; Simple tests.
13+
14+
declare void @use32(i32)
15+
declare void @use64(i64)
16+
17+
define i32 @t0_basic(i64 %x, i32 %nbits) {
18+
; CHECK-LABEL: @t0_basic(
19+
; CHECK-NEXT: [[T0:%.*]] = add i32 [[NBITS:%.*]], -1
20+
; CHECK-NEXT: [[T1:%.*]] = zext i32 [[T0]] to i64
21+
; CHECK-NEXT: [[T2:%.*]] = shl i64 1, [[T1]]
22+
; CHECK-NEXT: [[T3:%.*]] = add i64 [[T2]], -1
23+
; CHECK-NEXT: [[T4:%.*]] = sub i32 32, [[NBITS]]
24+
; CHECK-NEXT: call void @use32(i32 [[T0]])
25+
; CHECK-NEXT: call void @use64(i64 [[T1]])
26+
; CHECK-NEXT: call void @use64(i64 [[T2]])
27+
; CHECK-NEXT: call void @use64(i64 [[T3]])
28+
; CHECK-NEXT: call void @use32(i32 [[T4]])
29+
; CHECK-NEXT: [[T5:%.*]] = and i64 [[T3]], [[X:%.*]]
30+
; CHECK-NEXT: [[T6:%.*]] = trunc i64 [[T5]] to i32
31+
; CHECK-NEXT: [[T7:%.*]] = shl i32 [[T6]], [[T4]]
32+
; CHECK-NEXT: ret i32 [[T7]]
33+
;
34+
%t0 = add i32 %nbits, -1
35+
%t1 = zext i32 %t0 to i64
36+
%t2 = shl i64 1, %t1 ; shifting by nbits-1
37+
%t3 = add i64 %t2, -1
38+
%t4 = sub i32 32, %nbits
39+
40+
call void @use32(i32 %t0)
41+
call void @use64(i64 %t1)
42+
call void @use64(i64 %t2)
43+
call void @use64(i64 %t3)
44+
call void @use32(i32 %t4)
45+
46+
%t5 = and i64 %t3, %x
47+
%t6 = trunc i64 %t5 to i32
48+
%t7 = shl i32 %t6, %t4
49+
ret i32 %t7
50+
}
51+
52+
; Vectors
53+
54+
declare void @use8xi32(<8 x i32>)
55+
declare void @use8xi64(<8 x i64>)
56+
57+
define <8 x i32> @t1_vec_splat(<8 x i64> %x, <8 x i32> %nbits) {
58+
; CHECK-LABEL: @t1_vec_splat(
59+
; CHECK-NEXT: [[T0:%.*]] = add <8 x i32> [[NBITS:%.*]], <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>
60+
; CHECK-NEXT: [[T1:%.*]] = zext <8 x i32> [[T0]] to <8 x i64>
61+
; CHECK-NEXT: [[T2:%.*]] = shl <8 x i64> <i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1>, [[T1]]
62+
; CHECK-NEXT: [[T3:%.*]] = add <8 x i64> [[T2]], <i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1>
63+
; CHECK-NEXT: [[T4:%.*]] = sub <8 x i32> <i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32>, [[NBITS]]
64+
; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T0]])
65+
; CHECK-NEXT: call void @use8xi64(<8 x i64> [[T1]])
66+
; CHECK-NEXT: call void @use8xi64(<8 x i64> [[T2]])
67+
; CHECK-NEXT: call void @use8xi64(<8 x i64> [[T3]])
68+
; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T4]])
69+
; CHECK-NEXT: [[T5:%.*]] = and <8 x i64> [[T3]], [[X:%.*]]
70+
; CHECK-NEXT: [[T6:%.*]] = trunc <8 x i64> [[T5]] to <8 x i32>
71+
; CHECK-NEXT: [[T7:%.*]] = shl <8 x i32> [[T6]], [[T4]]
72+
; CHECK-NEXT: ret <8 x i32> [[T7]]
73+
;
74+
%t0 = add <8 x i32> %nbits, <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>
75+
%t1 = zext <8 x i32> %t0 to <8 x i64>
76+
%t2 = shl <8 x i64> <i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1>, %t1 ; shifting by nbits-1
77+
%t3 = add <8 x i64> %t2, <i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1>
78+
%t4 = sub <8 x i32> <i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32>, %nbits
79+
80+
call void @use8xi32(<8 x i32> %t0)
81+
call void @use8xi64(<8 x i64> %t1)
82+
call void @use8xi64(<8 x i64> %t2)
83+
call void @use8xi64(<8 x i64> %t3)
84+
call void @use8xi32(<8 x i32> %t4)
85+
86+
%t5 = and <8 x i64> %t3, %x
87+
%t6 = trunc <8 x i64> %t5 to <8 x i32>
88+
%t7 = shl <8 x i32> %t6, %t4
89+
ret <8 x i32> %t7
90+
}
91+
92+
define <8 x i32> @t2_vec_splat_undef(<8 x i64> %x, <8 x i32> %nbits) {
93+
; CHECK-LABEL: @t2_vec_splat_undef(
94+
; CHECK-NEXT: [[T0:%.*]] = add <8 x i32> [[NBITS:%.*]], <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 undef, i32 -1>
95+
; CHECK-NEXT: [[T1:%.*]] = zext <8 x i32> [[T0]] to <8 x i64>
96+
; CHECK-NEXT: [[T2:%.*]] = shl <8 x i64> <i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 undef, i64 1>, [[T1]]
97+
; CHECK-NEXT: [[T3:%.*]] = add <8 x i64> [[T2]], <i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 undef, i64 -1>
98+
; CHECK-NEXT: [[T4:%.*]] = sub <8 x i32> <i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 undef, i32 32>, [[NBITS]]
99+
; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T0]])
100+
; CHECK-NEXT: call void @use8xi64(<8 x i64> [[T1]])
101+
; CHECK-NEXT: call void @use8xi64(<8 x i64> [[T2]])
102+
; CHECK-NEXT: call void @use8xi64(<8 x i64> [[T3]])
103+
; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T4]])
104+
; CHECK-NEXT: [[T5:%.*]] = and <8 x i64> [[T3]], [[X:%.*]]
105+
; CHECK-NEXT: [[T6:%.*]] = trunc <8 x i64> [[T5]] to <8 x i32>
106+
; CHECK-NEXT: [[T7:%.*]] = shl <8 x i32> [[T6]], [[T4]]
107+
; CHECK-NEXT: ret <8 x i32> [[T7]]
108+
;
109+
%t0 = add <8 x i32> %nbits, <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 undef, i32 -1>
110+
%t1 = zext <8 x i32> %t0 to <8 x i64>
111+
%t2 = shl <8 x i64> <i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 undef, i64 1>, %t1 ; shifting by nbits-1
112+
%t3 = add <8 x i64> %t2, <i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 undef, i64 -1>
113+
%t4 = sub <8 x i32> <i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 undef, i32 32>, %nbits
114+
115+
call void @use8xi32(<8 x i32> %t0)
116+
call void @use8xi64(<8 x i64> %t1)
117+
call void @use8xi64(<8 x i64> %t2)
118+
call void @use8xi64(<8 x i64> %t3)
119+
call void @use8xi32(<8 x i32> %t4)
120+
121+
%t5 = and <8 x i64> %t3, %x
122+
%t6 = trunc <8 x i64> %t5 to <8 x i32>
123+
%t7 = shl <8 x i32> %t6, %t4
124+
ret <8 x i32> %t7
125+
}
126+
127+
define <8 x i32> @t3_vec_nonsplat(<8 x i64> %x, <8 x i32> %nbits) {
128+
; CHECK-LABEL: @t3_vec_nonsplat(
129+
; CHECK-NEXT: [[T0:%.*]] = add <8 x i32> [[NBITS:%.*]], <i32 -33, i32 -32, i32 -31, i32 -1, i32 0, i32 1, i32 31, i32 32>
130+
; CHECK-NEXT: [[T1:%.*]] = zext <8 x i32> [[T0]] to <8 x i64>
131+
; CHECK-NEXT: [[T2:%.*]] = shl <8 x i64> <i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1>, [[T1]]
132+
; CHECK-NEXT: [[T3:%.*]] = add <8 x i64> [[T2]], <i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1>
133+
; CHECK-NEXT: [[T4:%.*]] = sub <8 x i32> <i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32>, [[NBITS]]
134+
; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T0]])
135+
; CHECK-NEXT: call void @use8xi64(<8 x i64> [[T1]])
136+
; CHECK-NEXT: call void @use8xi64(<8 x i64> [[T2]])
137+
; CHECK-NEXT: call void @use8xi64(<8 x i64> [[T3]])
138+
; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T4]])
139+
; CHECK-NEXT: [[T5:%.*]] = and <8 x i64> [[T3]], [[X:%.*]]
140+
; CHECK-NEXT: [[T6:%.*]] = trunc <8 x i64> [[T5]] to <8 x i32>
141+
; CHECK-NEXT: [[T7:%.*]] = shl <8 x i32> [[T6]], [[T4]]
142+
; CHECK-NEXT: ret <8 x i32> [[T7]]
143+
;
144+
%t0 = add <8 x i32> %nbits, <i32 -33, i32 -32, i32 -31, i32 -1, i32 0, i32 1, i32 31, i32 32>
145+
%t1 = zext <8 x i32> %t0 to <8 x i64>
146+
%t2 = shl <8 x i64> <i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1>, %t1 ; shifting by nbits-1
147+
%t3 = add <8 x i64> %t2, <i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1>
148+
%t4 = sub <8 x i32> <i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32>, %nbits
149+
150+
call void @use8xi32(<8 x i32> %t0)
151+
call void @use8xi64(<8 x i64> %t1)
152+
call void @use8xi64(<8 x i64> %t2)
153+
call void @use8xi64(<8 x i64> %t3)
154+
call void @use8xi32(<8 x i32> %t4)
155+
156+
%t5 = and <8 x i64> %t3, %x
157+
%t6 = trunc <8 x i64> %t5 to <8 x i32>
158+
%t7 = shl <8 x i32> %t6, %t4
159+
ret <8 x i32> %t7
160+
}
161+
162+
; Extra uses
163+
164+
define i32 @n4_extrause0(i64 %x, i32 %nbits) {
165+
; CHECK-LABEL: @n4_extrause0(
166+
; CHECK-NEXT: [[T0:%.*]] = add i32 [[NBITS:%.*]], -1
167+
; CHECK-NEXT: [[T1:%.*]] = zext i32 [[T0]] to i64
168+
; CHECK-NEXT: [[T2:%.*]] = shl i64 1, [[T1]]
169+
; CHECK-NEXT: [[T3:%.*]] = add i64 [[T2]], -1
170+
; CHECK-NEXT: [[T4:%.*]] = sub i32 32, [[NBITS]]
171+
; CHECK-NEXT: call void @use32(i32 [[T0]])
172+
; CHECK-NEXT: call void @use64(i64 [[T1]])
173+
; CHECK-NEXT: call void @use64(i64 [[T2]])
174+
; CHECK-NEXT: call void @use64(i64 [[T3]])
175+
; CHECK-NEXT: call void @use32(i32 [[T4]])
176+
; CHECK-NEXT: [[T5:%.*]] = and i64 [[T3]], [[X:%.*]]
177+
; CHECK-NEXT: call void @use64(i64 [[T5]])
178+
; CHECK-NEXT: [[T6:%.*]] = trunc i64 [[T5]] to i32
179+
; CHECK-NEXT: [[T7:%.*]] = shl i32 [[T6]], [[T4]]
180+
; CHECK-NEXT: ret i32 [[T7]]
181+
;
182+
%t0 = add i32 %nbits, -1
183+
%t1 = zext i32 %t0 to i64
184+
%t2 = shl i64 1, %t1 ; shifting by nbits-1
185+
%t3 = add i64 %t2, -1
186+
%t4 = sub i32 32, %nbits
187+
188+
call void @use32(i32 %t0)
189+
call void @use64(i64 %t1)
190+
call void @use64(i64 %t2)
191+
call void @use64(i64 %t3)
192+
call void @use32(i32 %t4)
193+
194+
%t5 = and i64 %t3, %x
195+
call void @use64(i64 %t5)
196+
%t6 = trunc i64 %t5 to i32
197+
%t7 = shl i32 %t6, %t4
198+
ret i32 %t7
199+
}
200+
define i32 @n5_extrause1(i64 %x, i32 %nbits) {
201+
; CHECK-LABEL: @n5_extrause1(
202+
; CHECK-NEXT: [[T0:%.*]] = add i32 [[NBITS:%.*]], -1
203+
; CHECK-NEXT: [[T1:%.*]] = zext i32 [[T0]] to i64
204+
; CHECK-NEXT: [[T2:%.*]] = shl i64 1, [[T1]]
205+
; CHECK-NEXT: [[T3:%.*]] = add i64 [[T2]], -1
206+
; CHECK-NEXT: [[T4:%.*]] = sub i32 32, [[NBITS]]
207+
; CHECK-NEXT: call void @use32(i32 [[T0]])
208+
; CHECK-NEXT: call void @use64(i64 [[T1]])
209+
; CHECK-NEXT: call void @use64(i64 [[T2]])
210+
; CHECK-NEXT: call void @use64(i64 [[T3]])
211+
; CHECK-NEXT: call void @use32(i32 [[T4]])
212+
; CHECK-NEXT: [[T5:%.*]] = and i64 [[T3]], [[X:%.*]]
213+
; CHECK-NEXT: [[T6:%.*]] = trunc i64 [[T5]] to i32
214+
; CHECK-NEXT: call void @use32(i32 [[T6]])
215+
; CHECK-NEXT: [[T7:%.*]] = shl i32 [[T6]], [[T4]]
216+
; CHECK-NEXT: ret i32 [[T7]]
217+
;
218+
%t0 = add i32 %nbits, -1
219+
%t1 = zext i32 %t0 to i64
220+
%t2 = shl i64 1, %t1 ; shifting by nbits-1
221+
%t3 = add i64 %t2, -1
222+
%t4 = sub i32 32, %nbits
223+
224+
call void @use32(i32 %t0)
225+
call void @use64(i64 %t1)
226+
call void @use64(i64 %t2)
227+
call void @use64(i64 %t3)
228+
call void @use32(i32 %t4)
229+
230+
%t5 = and i64 %t3, %x
231+
%t6 = trunc i64 %t5 to i32
232+
call void @use32(i32 %t6)
233+
%t7 = shl i32 %t6, %t4
234+
ret i32 %t7
235+
}
236+
define i32 @n6_extrause2(i64 %x, i32 %nbits) {
237+
; CHECK-LABEL: @n6_extrause2(
238+
; CHECK-NEXT: [[T0:%.*]] = add i32 [[NBITS:%.*]], -1
239+
; CHECK-NEXT: [[T1:%.*]] = zext i32 [[T0]] to i64
240+
; CHECK-NEXT: [[T2:%.*]] = shl i64 1, [[T1]]
241+
; CHECK-NEXT: [[T3:%.*]] = add i64 [[T2]], -1
242+
; CHECK-NEXT: [[T4:%.*]] = sub i32 32, [[NBITS]]
243+
; CHECK-NEXT: call void @use32(i32 [[T0]])
244+
; CHECK-NEXT: call void @use64(i64 [[T1]])
245+
; CHECK-NEXT: call void @use64(i64 [[T2]])
246+
; CHECK-NEXT: call void @use64(i64 [[T3]])
247+
; CHECK-NEXT: call void @use32(i32 [[T4]])
248+
; CHECK-NEXT: [[T5:%.*]] = and i64 [[T3]], [[X:%.*]]
249+
; CHECK-NEXT: call void @use64(i64 [[T5]])
250+
; CHECK-NEXT: [[T6:%.*]] = trunc i64 [[T5]] to i32
251+
; CHECK-NEXT: call void @use32(i32 [[T6]])
252+
; CHECK-NEXT: [[T7:%.*]] = shl i32 [[T6]], [[T4]]
253+
; CHECK-NEXT: ret i32 [[T7]]
254+
;
255+
%t0 = add i32 %nbits, -1
256+
%t1 = zext i32 %t0 to i64
257+
%t2 = shl i64 1, %t1 ; shifting by nbits-1
258+
%t3 = add i64 %t2, -1
259+
%t4 = sub i32 32, %nbits
260+
261+
call void @use32(i32 %t0)
262+
call void @use64(i64 %t1)
263+
call void @use64(i64 %t2)
264+
call void @use64(i64 %t3)
265+
call void @use32(i32 %t4)
266+
267+
%t5 = and i64 %t3, %x
268+
call void @use64(i64 %t5)
269+
%t6 = trunc i64 %t5 to i32
270+
call void @use32(i32 %t6)
271+
%t7 = shl i32 %t6, %t4
272+
ret i32 %t7
273+
}

0 commit comments

Comments
 (0)