Skip to content

Commit 2b30a76

Browse files
committed
[InstCombine] Add select of clamped shifts test coverage based off #109888
Add baseline tests for removing shift amount clamps which are also bound by a select: Fold (select (icmp_ugt A, BW-1), (shift X, (and A, C)), Y) --> (select (icmp_ugt A, BW-1), (shift X, A), T) Fold (select (icmp_ugt A, BW-1), Y, (shift X, (umin A, C))) --> (select (icmp_ugt A, BW-1), Y, (shift X, A))
1 parent 8ff2da7 commit 2b30a76

File tree

1 file changed

+236
-0
lines changed

1 file changed

+236
-0
lines changed
Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2+
; RUN: opt -S -passes=instcombine < %s | FileCheck %s
3+
4+
declare void @use_i17(i17)
5+
declare void @use_i32(i32)
6+
7+
; Fold (select (icmp_ugt A, BW-1), (shift X, (and A, C)), FalseVal)
8+
; --> (select (icmp_ugt A, BW-1), (shift X, A), FalseVal)
9+
; Fold (select (icmp_ult A, BW), (shift X, (and A, C)), FalseVal)
10+
; --> (select (icmp_ult A, BW), (shift X, A), FalseVal)
11+
; iff Pow2 element width and C masks all amt bits.
12+
13+
define i32 @select_ult_shl_clamp_and_i32(i32 %a0, i32 %a1, i32 %a2) {
14+
; CHECK-LABEL: @select_ult_shl_clamp_and_i32(
15+
; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[A1:%.*]], 32
16+
; CHECK-NEXT: [[M:%.*]] = and i32 [[A1]], 31
17+
; CHECK-NEXT: [[TMP1:%.*]] = shl i32 [[A0:%.*]], [[M]]
18+
; CHECK-NEXT: [[R:%.*]] = select i1 [[C]], i32 [[TMP1]], i32 [[A2:%.*]]
19+
; CHECK-NEXT: ret i32 [[R]]
20+
;
21+
%c = icmp ult i32 %a1, 32
22+
%m = and i32 %a1, 31
23+
%s = shl i32 %a0, %m
24+
%r = select i1 %c, i32 %s, i32 %a2
25+
ret i32 %r
26+
}
27+
28+
define i32 @select_ule_ashr_clamp_and_i32(i32 %a0, i32 %a1, i32 %a2) {
29+
; CHECK-LABEL: @select_ule_ashr_clamp_and_i32(
30+
; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[A1:%.*]], 32
31+
; CHECK-NEXT: [[M:%.*]] = and i32 [[A1]], 127
32+
; CHECK-NEXT: [[TMP1:%.*]] = ashr i32 [[A0:%.*]], [[M]]
33+
; CHECK-NEXT: [[R:%.*]] = select i1 [[C]], i32 [[TMP1]], i32 [[A2:%.*]]
34+
; CHECK-NEXT: ret i32 [[R]]
35+
;
36+
%c = icmp ule i32 %a1, 31
37+
%m = and i32 %a1, 127
38+
%s = ashr i32 %a0, %m
39+
%r = select i1 %c, i32 %s, i32 %a2
40+
ret i32 %r
41+
}
42+
43+
define i32 @select_ugt_lshr_clamp_and_i32(i32 %a0, i32 %a1, i32 %a2) {
44+
; CHECK-LABEL: @select_ugt_lshr_clamp_and_i32(
45+
; CHECK-NEXT: [[C:%.*]] = icmp ugt i32 [[A1:%.*]], 31
46+
; CHECK-NEXT: [[M:%.*]] = and i32 [[A1]], 31
47+
; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[A0:%.*]], [[M]]
48+
; CHECK-NEXT: [[R:%.*]] = select i1 [[C]], i32 [[A2:%.*]], i32 [[TMP1]]
49+
; CHECK-NEXT: ret i32 [[R]]
50+
;
51+
%c = icmp ugt i32 %a1, 31
52+
%m = and i32 %a1, 31
53+
%s = lshr i32 %a0, %m
54+
%r = select i1 %c, i32 %a2, i32 %s
55+
ret i32 %r
56+
}
57+
58+
define i32 @select_uge_shl_clamp_and_i32(i32 %a0, i32 %a1, i32 %a2) {
59+
; CHECK-LABEL: @select_uge_shl_clamp_and_i32(
60+
; CHECK-NEXT: [[C:%.*]] = icmp ugt i32 [[A1:%.*]], 31
61+
; CHECK-NEXT: [[M:%.*]] = and i32 [[A1]], 63
62+
; CHECK-NEXT: [[TMP1:%.*]] = shl i32 [[A0:%.*]], [[M]]
63+
; CHECK-NEXT: [[R:%.*]] = select i1 [[C]], i32 [[A2:%.*]], i32 [[TMP1]]
64+
; CHECK-NEXT: ret i32 [[R]]
65+
;
66+
%c = icmp uge i32 %a1, 32
67+
%m = and i32 %a1, 63
68+
%s = shl i32 %a0, %m
69+
%r = select i1 %c, i32 %a2, i32 %s
70+
ret i32 %r
71+
}
72+
73+
; negative test - multiuse
74+
define i32 @select_ule_ashr_clamp_and_i32_multiuse(i32 %a0, i32 %a1, i32 %a2) {
75+
; CHECK-LABEL: @select_ule_ashr_clamp_and_i32_multiuse(
76+
; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[A1:%.*]], 32
77+
; CHECK-NEXT: [[M:%.*]] = and i32 [[A1]], 127
78+
; CHECK-NEXT: [[S:%.*]] = ashr i32 [[A0:%.*]], [[M]]
79+
; CHECK-NEXT: [[R:%.*]] = select i1 [[C]], i32 [[S]], i32 [[A2:%.*]]
80+
; CHECK-NEXT: call void @use_i32(i32 [[S]])
81+
; CHECK-NEXT: ret i32 [[R]]
82+
;
83+
%c = icmp ule i32 %a1, 31
84+
%m = and i32 %a1, 127
85+
%s = ashr i32 %a0, %m
86+
%r = select i1 %c, i32 %s, i32 %a2
87+
call void @use_i32(i32 %s)
88+
ret i32 %r
89+
}
90+
91+
; negative test - mask doesn't cover all legal amount bit
92+
define i32 @select_ult_shl_clamp_and_i32_badmask(i32 %a0, i32 %a1, i32 %a2) {
93+
; CHECK-LABEL: @select_ult_shl_clamp_and_i32_badmask(
94+
; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[A1:%.*]], 32
95+
; CHECK-NEXT: [[M:%.*]] = and i32 [[A1]], 28
96+
; CHECK-NEXT: [[S:%.*]] = shl i32 [[A0:%.*]], [[M]]
97+
; CHECK-NEXT: [[R:%.*]] = select i1 [[C]], i32 [[S]], i32 [[A2:%.*]]
98+
; CHECK-NEXT: ret i32 [[R]]
99+
;
100+
%c = icmp ult i32 %a1, 32
101+
%m = and i32 %a1, 28
102+
%s = shl i32 %a0, %m
103+
%r = select i1 %c, i32 %s, i32 %a2
104+
ret i32 %r
105+
}
106+
107+
; negative test - non-pow2
108+
define i17 @select_uge_lshr_clamp_and_i17_nonpow2(i17 %a0, i17 %a1, i17 %a2) {
109+
; CHECK-LABEL: @select_uge_lshr_clamp_and_i17_nonpow2(
110+
; CHECK-NEXT: [[C:%.*]] = icmp ugt i17 [[A1:%.*]], 16
111+
; CHECK-NEXT: [[M:%.*]] = and i17 [[A1]], 255
112+
; CHECK-NEXT: [[S:%.*]] = lshr i17 [[A0:%.*]], [[M]]
113+
; CHECK-NEXT: [[R:%.*]] = select i1 [[C]], i17 [[A2:%.*]], i17 [[S]]
114+
; CHECK-NEXT: ret i17 [[R]]
115+
;
116+
%c = icmp uge i17 %a1, 17
117+
%m = and i17 %a1, 255
118+
%s = lshr i17 %a0, %m
119+
%r = select i1 %c, i17 %a2, i17 %s
120+
ret i17 %r
121+
}
122+
123+
; Fold (select (icmp_ugt A, BW-1), TrueVal, (shift X, (umin A, C)))
124+
; --> (select (icmp_ugt A, BW-1), TrueVal, (shift X, A))
125+
; Fold (select (icmp_ult A, BW), (shift X, (umin A, C)), FalseVal)
126+
; --> (select (icmp_ult A, BW), (shift X, A), FalseVal)
127+
; iff C >= BW-1
128+
129+
define i32 @select_ult_shl_clamp_umin_i32(i32 %a0, i32 %a1, i32 %a2) {
130+
; CHECK-LABEL: @select_ult_shl_clamp_umin_i32(
131+
; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[A1:%.*]], 32
132+
; CHECK-NEXT: [[M:%.*]] = call i32 @llvm.umin.i32(i32 [[A1]], i32 31)
133+
; CHECK-NEXT: [[TMP1:%.*]] = shl i32 [[A0:%.*]], [[M]]
134+
; CHECK-NEXT: [[R:%.*]] = select i1 [[C]], i32 [[TMP1]], i32 [[A2:%.*]]
135+
; CHECK-NEXT: ret i32 [[R]]
136+
;
137+
%c = icmp ult i32 %a1, 32
138+
%m = call i32 @llvm.umin.i32(i32 %a1, i32 31)
139+
%s = shl i32 %a0, %m
140+
%r = select i1 %c, i32 %s, i32 %a2
141+
ret i32 %r
142+
}
143+
144+
define i17 @select_ule_ashr_clamp_umin_i17(i17 %a0, i17 %a1, i17 %a2) {
145+
; CHECK-LABEL: @select_ule_ashr_clamp_umin_i17(
146+
; CHECK-NEXT: [[C:%.*]] = icmp ult i17 [[A1:%.*]], 17
147+
; CHECK-NEXT: [[M:%.*]] = call i17 @llvm.umin.i17(i17 [[A1]], i17 17)
148+
; CHECK-NEXT: [[TMP1:%.*]] = ashr i17 [[A0:%.*]], [[M]]
149+
; CHECK-NEXT: [[R:%.*]] = select i1 [[C]], i17 [[TMP1]], i17 [[A2:%.*]]
150+
; CHECK-NEXT: ret i17 [[R]]
151+
;
152+
%c = icmp ule i17 %a1, 16
153+
%m = call i17 @llvm.umin.i17(i17 %a1, i17 17)
154+
%s = ashr i17 %a0, %m
155+
%r = select i1 %c, i17 %s, i17 %a2
156+
ret i17 %r
157+
}
158+
159+
define i32 @select_ugt_shl_clamp_umin_i32(i32 %a0, i32 %a1, i32 %a2) {
160+
; CHECK-LABEL: @select_ugt_shl_clamp_umin_i32(
161+
; CHECK-NEXT: [[C:%.*]] = icmp ugt i32 [[A1:%.*]], 31
162+
; CHECK-NEXT: [[M:%.*]] = call i32 @llvm.umin.i32(i32 [[A1]], i32 128)
163+
; CHECK-NEXT: [[S:%.*]] = shl i32 [[A0:%.*]], [[M]]
164+
; CHECK-NEXT: [[R:%.*]] = select i1 [[C]], i32 [[A2:%.*]], i32 [[S]]
165+
; CHECK-NEXT: ret i32 [[R]]
166+
;
167+
%c = icmp ugt i32 %a1, 31
168+
%m = call i32 @llvm.umin.i32(i32 %a1, i32 128)
169+
%s = shl i32 %a0, %m
170+
%r = select i1 %c, i32 %a2, i32 %s
171+
ret i32 %r
172+
}
173+
174+
define <2 x i32> @select_uge_lshr_clamp_umin_v2i32(<2 x i32> %a0, <2 x i32> %a1, <2 x i32> %a2) {
175+
; CHECK-LABEL: @select_uge_lshr_clamp_umin_v2i32(
176+
; CHECK-NEXT: [[C:%.*]] = icmp ugt <2 x i32> [[A1:%.*]], <i32 31, i32 31>
177+
; CHECK-NEXT: [[M:%.*]] = call <2 x i32> @llvm.umin.v2i32(<2 x i32> [[A1]], <2 x i32> <i32 63, i32 31>)
178+
; CHECK-NEXT: [[S:%.*]] = lshr <2 x i32> [[A0:%.*]], [[M]]
179+
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[C]], <2 x i32> [[A2:%.*]], <2 x i32> [[S]]
180+
; CHECK-NEXT: ret <2 x i32> [[R]]
181+
;
182+
%c = icmp uge <2 x i32> %a1, <i32 32, i32 32>
183+
%m = call <2 x i32> @llvm.umin.v2i32(<2 x i32> %a1, <2 x i32> <i32 63, i32 31>)
184+
%s = lshr <2 x i32> %a0, %m
185+
%r = select <2 x i1> %c, <2 x i32> %a2, <2 x i32> %s
186+
ret <2 x i32> %r
187+
}
188+
189+
; negative test - multiuse
190+
define i32 @select_ugt_shl_clamp_umin_i32_multiuse(i32 %a0, i32 %a1, i32 %a2) {
191+
; CHECK-LABEL: @select_ugt_shl_clamp_umin_i32_multiuse(
192+
; CHECK-NEXT: [[C:%.*]] = icmp ugt i32 [[A1:%.*]], 32
193+
; CHECK-NEXT: [[M:%.*]] = call i32 @llvm.umin.i32(i32 [[A1]], i32 128)
194+
; CHECK-NEXT: [[S:%.*]] = shl i32 [[A0:%.*]], [[M]]
195+
; CHECK-NEXT: [[R:%.*]] = select i1 [[C]], i32 [[A2:%.*]], i32 [[S]]
196+
; CHECK-NEXT: call void @use_i32(i32 [[S]])
197+
; CHECK-NEXT: ret i32 [[R]]
198+
;
199+
%c = icmp ugt i32 %a1, 32
200+
%m = call i32 @llvm.umin.i32(i32 %a1, i32 128)
201+
%s = shl i32 %a0, %m
202+
%r = select i1 %c, i32 %a2, i32 %s
203+
call void @use_i32(i32 %s)
204+
ret i32 %r
205+
}
206+
207+
; negative test - umin limit doesn't cover all legal amounts
208+
define i17 @select_uge_lshr_clamp_umin_i17_badlimit(i17 %a0, i17 %a1, i17 %a2) {
209+
; CHECK-LABEL: @select_uge_lshr_clamp_umin_i17_badlimit(
210+
; CHECK-NEXT: [[C:%.*]] = icmp ugt i17 [[A1:%.*]], 15
211+
; CHECK-NEXT: [[M:%.*]] = call i17 @llvm.umin.i17(i17 [[A1]], i17 12)
212+
; CHECK-NEXT: [[S:%.*]] = lshr i17 [[A0:%.*]], [[M]]
213+
; CHECK-NEXT: [[R:%.*]] = select i1 [[C]], i17 [[A2:%.*]], i17 [[S]]
214+
; CHECK-NEXT: ret i17 [[R]]
215+
;
216+
%c = icmp uge i17 %a1, 16
217+
%m = call i17 @llvm.umin.i17(i17 %a1, i17 12)
218+
%s = lshr i17 %a0, %m
219+
%r = select i1 %c, i17 %a2, i17 %s
220+
ret i17 %r
221+
}
222+
223+
define range(i64 0, -9223372036854775807) <4 x i64> @PR109888(<4 x i64> %0) {
224+
; CHECK-LABEL: @PR109888(
225+
; CHECK-NEXT: [[C:%.*]] = icmp ult <4 x i64> [[TMP0:%.*]], <i64 64, i64 64, i64 64, i64 64>
226+
; CHECK-NEXT: [[M:%.*]] = and <4 x i64> [[TMP0]], <i64 63, i64 63, i64 63, i64 63>
227+
; CHECK-NEXT: [[TMP2:%.*]] = shl nuw <4 x i64> <i64 1, i64 1, i64 1, i64 1>, [[M]]
228+
; CHECK-NEXT: [[R:%.*]] = select <4 x i1> [[C]], <4 x i64> [[TMP2]], <4 x i64> zeroinitializer
229+
; CHECK-NEXT: ret <4 x i64> [[R]]
230+
;
231+
%c = icmp ult <4 x i64> %0, <i64 64, i64 64, i64 64, i64 64>
232+
%m = and <4 x i64> %0, <i64 63, i64 63, i64 63, i64 63>
233+
%s = shl nuw <4 x i64> <i64 1, i64 1, i64 1, i64 1>, %m
234+
%r = select <4 x i1> %c, <4 x i64> %s, <4 x i64> zeroinitializer
235+
ret <4 x i64> %r
236+
}

0 commit comments

Comments
 (0)