Skip to content

Commit d55c2d6

Browse files
[ConstantTime][WebAssembly] Add comprehensive tests for ct.select
1 parent cbb5490 commit d55c2d6

File tree

5 files changed

+2509
-0
lines changed

5 files changed

+2509
-0
lines changed
Lines changed: 376 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,376 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
2+
; RUN: llc < %s -mtriple=wasm32-unknown-unknown -O3 -filetype=asm | FileCheck %s --check-prefix=W32
3+
; RUN: llc < %s -mtriple=wasm64-unknown-unknown -O3 -filetype=asm | FileCheck %s --check-prefix=W64
4+
5+
; Test with small integer types
6+
define i1 @test_ctselect_i1(i1 %cond, i1 %a, i1 %b) {
7+
; W32-LABEL: test_ctselect_i1:
8+
; W32: .functype test_ctselect_i1 (i32, i32, i32) -> (i32)
9+
; W32-NEXT: # %bb.0:
10+
; W32-NEXT: local.get 0
11+
; W32-NEXT: local.get 1
12+
; W32-NEXT: i32.and
13+
; W32-NEXT: local.get 0
14+
; W32-NEXT: i32.const 1
15+
; W32-NEXT: i32.xor
16+
; W32-NEXT: local.get 2
17+
; W32-NEXT: i32.and
18+
; W32-NEXT: i32.or
19+
; W32-NEXT: # fallthrough-return
20+
;
21+
; W64-LABEL: test_ctselect_i1:
22+
; W64: .functype test_ctselect_i1 (i32, i32, i32) -> (i32)
23+
; W64-NEXT: # %bb.0:
24+
; W64-NEXT: local.get 0
25+
; W64-NEXT: local.get 1
26+
; W64-NEXT: i32.and
27+
; W64-NEXT: local.get 0
28+
; W64-NEXT: i32.const 1
29+
; W64-NEXT: i32.xor
30+
; W64-NEXT: local.get 2
31+
; W64-NEXT: i32.and
32+
; W64-NEXT: i32.or
33+
; W64-NEXT: # fallthrough-return
34+
%result = call i1 @llvm.ct.select.i1(i1 %cond, i1 %a, i1 %b)
35+
ret i1 %result
36+
}
37+
38+
; Test with extremal values
39+
define i32 @test_ctselect_extremal_values(i1 %cond) {
40+
; W32-LABEL: test_ctselect_extremal_values:
41+
; W32: .functype test_ctselect_extremal_values (i32) -> (i32)
42+
; W32-NEXT: # %bb.0:
43+
; W32-NEXT: i32.const 0
44+
; W32-NEXT: local.get 0
45+
; W32-NEXT: i32.const 1
46+
; W32-NEXT: i32.and
47+
; W32-NEXT: local.tee 0
48+
; W32-NEXT: i32.sub
49+
; W32-NEXT: i32.const 2147483647
50+
; W32-NEXT: i32.and
51+
; W32-NEXT: local.get 0
52+
; W32-NEXT: i32.const -1
53+
; W32-NEXT: i32.add
54+
; W32-NEXT: i32.const -2147483648
55+
; W32-NEXT: i32.and
56+
; W32-NEXT: i32.or
57+
; W32-NEXT: # fallthrough-return
58+
;
59+
; W64-LABEL: test_ctselect_extremal_values:
60+
; W64: .functype test_ctselect_extremal_values (i32) -> (i32)
61+
; W64-NEXT: # %bb.0:
62+
; W64-NEXT: i32.const 0
63+
; W64-NEXT: local.get 0
64+
; W64-NEXT: i32.const 1
65+
; W64-NEXT: i32.and
66+
; W64-NEXT: local.tee 0
67+
; W64-NEXT: i32.sub
68+
; W64-NEXT: i32.const 2147483647
69+
; W64-NEXT: i32.and
70+
; W64-NEXT: local.get 0
71+
; W64-NEXT: i32.const -1
72+
; W64-NEXT: i32.add
73+
; W64-NEXT: i32.const -2147483648
74+
; W64-NEXT: i32.and
75+
; W64-NEXT: i32.or
76+
; W64-NEXT: # fallthrough-return
77+
%result = call i32 @llvm.ct.select.i32(i1 %cond, i32 2147483647, i32 -2147483648)
78+
ret i32 %result
79+
}
80+
81+
; Test with null pointers
82+
define ptr @test_ctselect_null_ptr(i1 %cond, ptr %ptr) {
83+
; W32-LABEL: test_ctselect_null_ptr:
84+
; W32: .functype test_ctselect_null_ptr (i32, i32) -> (i32)
85+
; W32-NEXT: # %bb.0:
86+
; W32-NEXT: i32.const 0
87+
; W32-NEXT: local.get 0
88+
; W32-NEXT: i32.const 1
89+
; W32-NEXT: i32.and
90+
; W32-NEXT: i32.sub
91+
; W32-NEXT: local.get 1
92+
; W32-NEXT: i32.and
93+
; W32-NEXT: # fallthrough-return
94+
;
95+
; W64-LABEL: test_ctselect_null_ptr:
96+
; W64: .functype test_ctselect_null_ptr (i32, i64) -> (i64)
97+
; W64-NEXT: # %bb.0:
98+
; W64-NEXT: i64.const 0
99+
; W64-NEXT: local.get 0
100+
; W64-NEXT: i64.extend_i32_u
101+
; W64-NEXT: i64.const 1
102+
; W64-NEXT: i64.and
103+
; W64-NEXT: i64.sub
104+
; W64-NEXT: local.get 1
105+
; W64-NEXT: i64.and
106+
; W64-NEXT: # fallthrough-return
107+
%result = call ptr @llvm.ct.select.p0(i1 %cond, ptr %ptr, ptr null)
108+
ret ptr %result
109+
}
110+
111+
; Test with function pointers
112+
define ptr @test_ctselect_function_ptr(i1 %cond, ptr %func1, ptr %func2) {
113+
; W32-LABEL: test_ctselect_function_ptr:
114+
; W32: .functype test_ctselect_function_ptr (i32, i32, i32) -> (i32)
115+
; W32-NEXT: # %bb.0:
116+
; W32-NEXT: i32.const 0
117+
; W32-NEXT: local.get 0
118+
; W32-NEXT: i32.const 1
119+
; W32-NEXT: i32.and
120+
; W32-NEXT: local.tee 0
121+
; W32-NEXT: i32.sub
122+
; W32-NEXT: local.get 1
123+
; W32-NEXT: i32.and
124+
; W32-NEXT: local.get 0
125+
; W32-NEXT: i32.const -1
126+
; W32-NEXT: i32.add
127+
; W32-NEXT: local.get 2
128+
; W32-NEXT: i32.and
129+
; W32-NEXT: i32.or
130+
; W32-NEXT: # fallthrough-return
131+
;
132+
; W64-LABEL: test_ctselect_function_ptr:
133+
; W64: .functype test_ctselect_function_ptr (i32, i64, i64) -> (i64)
134+
; W64-NEXT: .local i64
135+
; W64-NEXT: # %bb.0:
136+
; W64-NEXT: i64.const 0
137+
; W64-NEXT: local.get 0
138+
; W64-NEXT: i64.extend_i32_u
139+
; W64-NEXT: i64.const 1
140+
; W64-NEXT: i64.and
141+
; W64-NEXT: local.tee 3
142+
; W64-NEXT: i64.sub
143+
; W64-NEXT: local.get 1
144+
; W64-NEXT: i64.and
145+
; W64-NEXT: local.get 3
146+
; W64-NEXT: i64.const -1
147+
; W64-NEXT: i64.add
148+
; W64-NEXT: local.get 2
149+
; W64-NEXT: i64.and
150+
; W64-NEXT: i64.or
151+
; W64-NEXT: # fallthrough-return
152+
%result = call ptr @llvm.ct.select.p0(i1 %cond, ptr %func1, ptr %func2)
153+
ret ptr %result
154+
}
155+
156+
; Test with condition from icmp on pointers
157+
define ptr @test_ctselect_ptr_cmp(ptr %p1, ptr %p2, ptr %a, ptr %b) {
158+
; W32-LABEL: test_ctselect_ptr_cmp:
159+
; W32: .functype test_ctselect_ptr_cmp (i32, i32, i32, i32) -> (i32)
160+
; W32-NEXT: # %bb.0:
161+
; W32-NEXT: i32.const -1
162+
; W32-NEXT: i32.const 0
163+
; W32-NEXT: local.get 0
164+
; W32-NEXT: local.get 1
165+
; W32-NEXT: i32.eq
166+
; W32-NEXT: i32.select
167+
; W32-NEXT: local.tee 1
168+
; W32-NEXT: local.get 2
169+
; W32-NEXT: i32.and
170+
; W32-NEXT: local.get 1
171+
; W32-NEXT: i32.const -1
172+
; W32-NEXT: i32.xor
173+
; W32-NEXT: local.get 3
174+
; W32-NEXT: i32.and
175+
; W32-NEXT: i32.or
176+
; W32-NEXT: # fallthrough-return
177+
;
178+
; W64-LABEL: test_ctselect_ptr_cmp:
179+
; W64: .functype test_ctselect_ptr_cmp (i64, i64, i64, i64) -> (i64)
180+
; W64-NEXT: # %bb.0:
181+
; W64-NEXT: i64.const -1
182+
; W64-NEXT: i64.const 0
183+
; W64-NEXT: local.get 0
184+
; W64-NEXT: local.get 1
185+
; W64-NEXT: i64.eq
186+
; W64-NEXT: i64.select
187+
; W64-NEXT: local.tee 1
188+
; W64-NEXT: local.get 2
189+
; W64-NEXT: i64.and
190+
; W64-NEXT: local.get 1
191+
; W64-NEXT: i64.const -1
192+
; W64-NEXT: i64.xor
193+
; W64-NEXT: local.get 3
194+
; W64-NEXT: i64.and
195+
; W64-NEXT: i64.or
196+
; W64-NEXT: # fallthrough-return
197+
%cmp = icmp eq ptr %p1, %p2
198+
%result = call ptr @llvm.ct.select.p0(i1 %cmp, ptr %a, ptr %b)
199+
ret ptr %result
200+
}
201+
202+
; Test with struct pointer types
203+
%struct.pair = type { i32, i32 }
204+
205+
define ptr @test_ctselect_struct_ptr(i1 %cond, ptr %a, ptr %b) {
206+
; W32-LABEL: test_ctselect_struct_ptr:
207+
; W32: .functype test_ctselect_struct_ptr (i32, i32, i32) -> (i32)
208+
; W32-NEXT: # %bb.0:
209+
; W32-NEXT: i32.const 0
210+
; W32-NEXT: local.get 0
211+
; W32-NEXT: i32.const 1
212+
; W32-NEXT: i32.and
213+
; W32-NEXT: local.tee 0
214+
; W32-NEXT: i32.sub
215+
; W32-NEXT: local.get 1
216+
; W32-NEXT: i32.and
217+
; W32-NEXT: local.get 0
218+
; W32-NEXT: i32.const -1
219+
; W32-NEXT: i32.add
220+
; W32-NEXT: local.get 2
221+
; W32-NEXT: i32.and
222+
; W32-NEXT: i32.or
223+
; W32-NEXT: # fallthrough-return
224+
;
225+
; W64-LABEL: test_ctselect_struct_ptr:
226+
; W64: .functype test_ctselect_struct_ptr (i32, i64, i64) -> (i64)
227+
; W64-NEXT: .local i64
228+
; W64-NEXT: # %bb.0:
229+
; W64-NEXT: i64.const 0
230+
; W64-NEXT: local.get 0
231+
; W64-NEXT: i64.extend_i32_u
232+
; W64-NEXT: i64.const 1
233+
; W64-NEXT: i64.and
234+
; W64-NEXT: local.tee 3
235+
; W64-NEXT: i64.sub
236+
; W64-NEXT: local.get 1
237+
; W64-NEXT: i64.and
238+
; W64-NEXT: local.get 3
239+
; W64-NEXT: i64.const -1
240+
; W64-NEXT: i64.add
241+
; W64-NEXT: local.get 2
242+
; W64-NEXT: i64.and
243+
; W64-NEXT: i64.or
244+
; W64-NEXT: # fallthrough-return
245+
%result = call ptr @llvm.ct.select.p0(i1 %cond, ptr %a, ptr %b)
246+
ret ptr %result
247+
}
248+
249+
; Test with deeply nested conditions
250+
define i32 @test_ctselect_deeply_nested(i1 %c1, i1 %c2, i1 %c3, i1 %c4, i32 %a, i32 %b, i32 %c, i32 %d, i32 %e) {
251+
; W32-LABEL: test_ctselect_deeply_nested:
252+
; W32: .functype test_ctselect_deeply_nested (i32, i32, i32, i32, i32, i32, i32, i32, i32) -> (i32)
253+
; W32-NEXT: # %bb.0:
254+
; W32-NEXT: i32.const 0
255+
; W32-NEXT: local.get 3
256+
; W32-NEXT: i32.const 1
257+
; W32-NEXT: i32.and
258+
; W32-NEXT: local.tee 3
259+
; W32-NEXT: i32.sub
260+
; W32-NEXT: i32.const 0
261+
; W32-NEXT: local.get 2
262+
; W32-NEXT: i32.const 1
263+
; W32-NEXT: i32.and
264+
; W32-NEXT: local.tee 2
265+
; W32-NEXT: i32.sub
266+
; W32-NEXT: i32.const 0
267+
; W32-NEXT: local.get 1
268+
; W32-NEXT: i32.const 1
269+
; W32-NEXT: i32.and
270+
; W32-NEXT: local.tee 1
271+
; W32-NEXT: i32.sub
272+
; W32-NEXT: i32.const 0
273+
; W32-NEXT: local.get 0
274+
; W32-NEXT: i32.const 1
275+
; W32-NEXT: i32.and
276+
; W32-NEXT: local.tee 0
277+
; W32-NEXT: i32.sub
278+
; W32-NEXT: local.get 4
279+
; W32-NEXT: i32.and
280+
; W32-NEXT: local.get 0
281+
; W32-NEXT: i32.const -1
282+
; W32-NEXT: i32.add
283+
; W32-NEXT: local.get 5
284+
; W32-NEXT: i32.and
285+
; W32-NEXT: i32.or
286+
; W32-NEXT: i32.and
287+
; W32-NEXT: local.get 1
288+
; W32-NEXT: i32.const -1
289+
; W32-NEXT: i32.add
290+
; W32-NEXT: local.get 6
291+
; W32-NEXT: i32.and
292+
; W32-NEXT: i32.or
293+
; W32-NEXT: i32.and
294+
; W32-NEXT: local.get 2
295+
; W32-NEXT: i32.const -1
296+
; W32-NEXT: i32.add
297+
; W32-NEXT: local.get 7
298+
; W32-NEXT: i32.and
299+
; W32-NEXT: i32.or
300+
; W32-NEXT: i32.and
301+
; W32-NEXT: local.get 3
302+
; W32-NEXT: i32.const -1
303+
; W32-NEXT: i32.add
304+
; W32-NEXT: local.get 8
305+
; W32-NEXT: i32.and
306+
; W32-NEXT: i32.or
307+
; W32-NEXT: # fallthrough-return
308+
;
309+
; W64-LABEL: test_ctselect_deeply_nested:
310+
; W64: .functype test_ctselect_deeply_nested (i32, i32, i32, i32, i32, i32, i32, i32, i32) -> (i32)
311+
; W64-NEXT: # %bb.0:
312+
; W64-NEXT: i32.const 0
313+
; W64-NEXT: local.get 3
314+
; W64-NEXT: i32.const 1
315+
; W64-NEXT: i32.and
316+
; W64-NEXT: local.tee 3
317+
; W64-NEXT: i32.sub
318+
; W64-NEXT: i32.const 0
319+
; W64-NEXT: local.get 2
320+
; W64-NEXT: i32.const 1
321+
; W64-NEXT: i32.and
322+
; W64-NEXT: local.tee 2
323+
; W64-NEXT: i32.sub
324+
; W64-NEXT: i32.const 0
325+
; W64-NEXT: local.get 1
326+
; W64-NEXT: i32.const 1
327+
; W64-NEXT: i32.and
328+
; W64-NEXT: local.tee 1
329+
; W64-NEXT: i32.sub
330+
; W64-NEXT: i32.const 0
331+
; W64-NEXT: local.get 0
332+
; W64-NEXT: i32.const 1
333+
; W64-NEXT: i32.and
334+
; W64-NEXT: local.tee 0
335+
; W64-NEXT: i32.sub
336+
; W64-NEXT: local.get 4
337+
; W64-NEXT: i32.and
338+
; W64-NEXT: local.get 0
339+
; W64-NEXT: i32.const -1
340+
; W64-NEXT: i32.add
341+
; W64-NEXT: local.get 5
342+
; W64-NEXT: i32.and
343+
; W64-NEXT: i32.or
344+
; W64-NEXT: i32.and
345+
; W64-NEXT: local.get 1
346+
; W64-NEXT: i32.const -1
347+
; W64-NEXT: i32.add
348+
; W64-NEXT: local.get 6
349+
; W64-NEXT: i32.and
350+
; W64-NEXT: i32.or
351+
; W64-NEXT: i32.and
352+
; W64-NEXT: local.get 2
353+
; W64-NEXT: i32.const -1
354+
; W64-NEXT: i32.add
355+
; W64-NEXT: local.get 7
356+
; W64-NEXT: i32.and
357+
; W64-NEXT: i32.or
358+
; W64-NEXT: i32.and
359+
; W64-NEXT: local.get 3
360+
; W64-NEXT: i32.const -1
361+
; W64-NEXT: i32.add
362+
; W64-NEXT: local.get 8
363+
; W64-NEXT: i32.and
364+
; W64-NEXT: i32.or
365+
; W64-NEXT: # fallthrough-return
366+
%sel1 = call i32 @llvm.ct.select.i32(i1 %c1, i32 %a, i32 %b)
367+
%sel2 = call i32 @llvm.ct.select.i32(i1 %c2, i32 %sel1, i32 %c)
368+
%sel3 = call i32 @llvm.ct.select.i32(i1 %c3, i32 %sel2, i32 %d)
369+
%sel4 = call i32 @llvm.ct.select.i32(i1 %c4, i32 %sel3, i32 %e)
370+
ret i32 %sel4
371+
}
372+
373+
; Declare the intrinsics
374+
declare i1 @llvm.ct.select.i1(i1, i1, i1)
375+
declare i32 @llvm.ct.select.i32(i1, i32, i32)
376+
declare ptr @llvm.ct.select.p0(i1, ptr, ptr)

0 commit comments

Comments
 (0)