xref: /llvm-project/llvm/test/CodeGen/WebAssembly/i128.ll (revision e665e781dc3f8fac0400f6ac8e168805b0cdf74a)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s
3
4; Test that basic 128-bit integer operations assemble as expected.
5
6target triple = "wasm32-unknown-unknown"
7
8declare i128 @llvm.ctlz.i128(i128, i1)
9declare i128 @llvm.cttz.i128(i128, i1)
10declare i128 @llvm.ctpop.i128(i128)
11
12define i128 @add128(i128 %x, i128 %y) {
13; CHECK-LABEL: add128:
14; CHECK:         .functype add128 (i32, i64, i64, i64, i64) -> ()
15; CHECK-NEXT:  # %bb.0:
16; CHECK-NEXT:    local.get $push8=, 0
17; CHECK-NEXT:    local.get $push7=, 1
18; CHECK-NEXT:    local.get $push6=, 3
19; CHECK-NEXT:    i64.add $push5=, $pop7, $pop6
20; CHECK-NEXT:    local.tee $push4=, 3, $pop5
21; CHECK-NEXT:    i64.store 0($pop8), $pop4
22; CHECK-NEXT:    local.get $push13=, 0
23; CHECK-NEXT:    local.get $push10=, 2
24; CHECK-NEXT:    local.get $push9=, 4
25; CHECK-NEXT:    i64.add $push0=, $pop10, $pop9
26; CHECK-NEXT:    local.get $push12=, 3
27; CHECK-NEXT:    local.get $push11=, 1
28; CHECK-NEXT:    i64.lt_u $push1=, $pop12, $pop11
29; CHECK-NEXT:    i64.extend_i32_u $push2=, $pop1
30; CHECK-NEXT:    i64.add $push3=, $pop0, $pop2
31; CHECK-NEXT:    i64.store 8($pop13), $pop3
32; CHECK-NEXT:    return
33  %a = add i128 %x, %y
34  ret i128 %a
35}
36
37define i128 @sub128(i128 %x, i128 %y) {
38; CHECK-LABEL: sub128:
39; CHECK:         .functype sub128 (i32, i64, i64, i64, i64) -> ()
40; CHECK-NEXT:  # %bb.0:
41; CHECK-NEXT:    local.get $push7=, 0
42; CHECK-NEXT:    local.get $push6=, 1
43; CHECK-NEXT:    local.get $push5=, 3
44; CHECK-NEXT:    i64.sub $push0=, $pop6, $pop5
45; CHECK-NEXT:    i64.store 0($pop7), $pop0
46; CHECK-NEXT:    local.get $push12=, 0
47; CHECK-NEXT:    local.get $push9=, 2
48; CHECK-NEXT:    local.get $push8=, 4
49; CHECK-NEXT:    i64.sub $push1=, $pop9, $pop8
50; CHECK-NEXT:    local.get $push11=, 1
51; CHECK-NEXT:    local.get $push10=, 3
52; CHECK-NEXT:    i64.lt_u $push2=, $pop11, $pop10
53; CHECK-NEXT:    i64.extend_i32_u $push3=, $pop2
54; CHECK-NEXT:    i64.sub $push4=, $pop1, $pop3
55; CHECK-NEXT:    i64.store 8($pop12), $pop4
56; CHECK-NEXT:    return
57  %a = sub i128 %x, %y
58  ret i128 %a
59}
60
61define i128 @mul128(i128 %x, i128 %y) {
62; CHECK-LABEL: mul128:
63; CHECK:         .functype mul128 (i32, i64, i64, i64, i64) -> ()
64; CHECK-NEXT:    .local i32
65; CHECK-NEXT:  # %bb.0:
66; CHECK-NEXT:    global.get $push2=, __stack_pointer
67; CHECK-NEXT:    i32.const $push3=, 16
68; CHECK-NEXT:    i32.sub $push7=, $pop2, $pop3
69; CHECK-NEXT:    local.tee $push6=, 5, $pop7
70; CHECK-NEXT:    global.set __stack_pointer, $pop6
71; CHECK-NEXT:    local.get $push12=, 5
72; CHECK-NEXT:    local.get $push11=, 1
73; CHECK-NEXT:    local.get $push10=, 2
74; CHECK-NEXT:    local.get $push9=, 3
75; CHECK-NEXT:    local.get $push8=, 4
76; CHECK-NEXT:    call __multi3, $pop12, $pop11, $pop10, $pop9, $pop8
77; CHECK-NEXT:    local.get $push14=, 0
78; CHECK-NEXT:    local.get $push13=, 5
79; CHECK-NEXT:    i64.load $push0=, 8($pop13)
80; CHECK-NEXT:    i64.store 8($pop14), $pop0
81; CHECK-NEXT:    local.get $push16=, 0
82; CHECK-NEXT:    local.get $push15=, 5
83; CHECK-NEXT:    i64.load $push1=, 0($pop15)
84; CHECK-NEXT:    i64.store 0($pop16), $pop1
85; CHECK-NEXT:    local.get $push17=, 5
86; CHECK-NEXT:    i32.const $push4=, 16
87; CHECK-NEXT:    i32.add $push5=, $pop17, $pop4
88; CHECK-NEXT:    global.set __stack_pointer, $pop5
89; CHECK-NEXT:    return
90  %a = mul i128 %x, %y
91  ret i128 %a
92}
93
94define i128 @sdiv128(i128 %x, i128 %y) {
95; CHECK-LABEL: sdiv128:
96; CHECK:         .functype sdiv128 (i32, i64, i64, i64, i64) -> ()
97; CHECK-NEXT:    .local i32
98; CHECK-NEXT:  # %bb.0:
99; CHECK-NEXT:    global.get $push2=, __stack_pointer
100; CHECK-NEXT:    i32.const $push3=, 16
101; CHECK-NEXT:    i32.sub  $push7=, $pop2, $pop3
102; CHECK-NEXT:    local.tee $push6=, 5, $pop7
103; CHECK-NEXT:    global.set __stack_pointer, $pop6
104; CHECK-NEXT:    local.get $push12=, 5
105; CHECK-NEXT:    local.get $push11=, 1
106; CHECK-NEXT:    local.get $push10=, 2
107; CHECK-NEXT:    local.get $push9=, 3
108; CHECK-NEXT:    local.get $push8=, 4
109; CHECK-NEXT:    call __divti3, $pop12, $pop11, $pop10, $pop9, $pop8
110; CHECK-NEXT:    local.get $push14=, 0
111; CHECK-NEXT:    local.get $push13=, 5
112; CHECK-NEXT:    i64.load $push0=, 8($pop13)
113; CHECK-NEXT:    i64.store 8($pop14), $pop0
114; CHECK-NEXT:    local.get $push16=, 0
115; CHECK-NEXT:    local.get $push15=, 5
116; CHECK-NEXT:    i64.load $push1=, 0($pop15)
117; CHECK-NEXT:    i64.store 0($pop16), $pop1
118; CHECK-NEXT:    local.get $push17=, 5
119; CHECK-NEXT:    i32.const $push4=, 16
120; CHECK-NEXT:    i32.add  $push5=, $pop17, $pop4
121; CHECK-NEXT:    global.set __stack_pointer, $pop5
122; CHECK-NEXT:    return
123  %a = sdiv i128 %x, %y
124  ret i128 %a
125}
126
127define i128 @udiv128(i128 %x, i128 %y) {
128; CHECK-LABEL: udiv128:
129; CHECK:         .functype udiv128 (i32, i64, i64, i64, i64) -> ()
130; CHECK-NEXT:    .local i32
131; CHECK-NEXT:  # %bb.0:
132; CHECK-NEXT:    global.get $push2=, __stack_pointer
133; CHECK-NEXT:    i32.const $push3=, 16
134; CHECK-NEXT:    i32.sub  $push7=, $pop2, $pop3
135; CHECK-NEXT:    local.tee $push6=, 5, $pop7
136; CHECK-NEXT:    global.set __stack_pointer, $pop6
137; CHECK-NEXT:    local.get $push12=, 5
138; CHECK-NEXT:    local.get $push11=, 1
139; CHECK-NEXT:    local.get $push10=, 2
140; CHECK-NEXT:    local.get $push9=, 3
141; CHECK-NEXT:    local.get $push8=, 4
142; CHECK-NEXT:    call __udivti3, $pop12, $pop11, $pop10, $pop9, $pop8
143; CHECK-NEXT:    local.get $push14=, 0
144; CHECK-NEXT:    local.get $push13=, 5
145; CHECK-NEXT:    i64.load $push0=, 8($pop13)
146; CHECK-NEXT:    i64.store 8($pop14), $pop0
147; CHECK-NEXT:    local.get $push16=, 0
148; CHECK-NEXT:    local.get $push15=, 5
149; CHECK-NEXT:    i64.load $push1=, 0($pop15)
150; CHECK-NEXT:    i64.store 0($pop16), $pop1
151; CHECK-NEXT:    local.get $push17=, 5
152; CHECK-NEXT:    i32.const $push4=, 16
153; CHECK-NEXT:    i32.add  $push5=, $pop17, $pop4
154; CHECK-NEXT:    global.set __stack_pointer, $pop5
155; CHECK-NEXT:    return
156  %a = udiv i128 %x, %y
157  ret i128 %a
158}
159
160define i128 @srem128(i128 %x, i128 %y) {
161; CHECK-LABEL: srem128:
162; CHECK:         .functype srem128 (i32, i64, i64, i64, i64) -> ()
163; CHECK-NEXT:    .local i32
164; CHECK-NEXT:  # %bb.0:
165; CHECK-NEXT:    global.get $push2=, __stack_pointer
166; CHECK-NEXT:    i32.const $push3=, 16
167; CHECK-NEXT:    i32.sub  $push7=, $pop2, $pop3
168; CHECK-NEXT:    local.tee $push6=, 5, $pop7
169; CHECK-NEXT:    global.set __stack_pointer, $pop6
170; CHECK-NEXT:    local.get $push12=, 5
171; CHECK-NEXT:    local.get $push11=, 1
172; CHECK-NEXT:    local.get $push10=, 2
173; CHECK-NEXT:    local.get $push9=, 3
174; CHECK-NEXT:    local.get $push8=, 4
175; CHECK-NEXT:    call __modti3, $pop12, $pop11, $pop10, $pop9, $pop8
176; CHECK-NEXT:    local.get $push14=, 0
177; CHECK-NEXT:    local.get $push13=, 5
178; CHECK-NEXT:    i64.load $push0=, 8($pop13)
179; CHECK-NEXT:    i64.store 8($pop14), $pop0
180; CHECK-NEXT:    local.get $push16=, 0
181; CHECK-NEXT:    local.get $push15=, 5
182; CHECK-NEXT:    i64.load $push1=, 0($pop15)
183; CHECK-NEXT:    i64.store 0($pop16), $pop1
184; CHECK-NEXT:    local.get $push17=, 5
185; CHECK-NEXT:    i32.const $push4=, 16
186; CHECK-NEXT:    i32.add  $push5=, $pop17, $pop4
187; CHECK-NEXT:    global.set __stack_pointer, $pop5
188; CHECK-NEXT:    return
189  %a = srem i128 %x, %y
190  ret i128 %a
191}
192
193define i128 @urem128(i128 %x, i128 %y) {
194; CHECK-LABEL: urem128:
195; CHECK:         .functype urem128 (i32, i64, i64, i64, i64) -> ()
196; CHECK-NEXT:    .local i32
197; CHECK-NEXT:  # %bb.0:
198; CHECK-NEXT:    global.get $push2=, __stack_pointer
199; CHECK-NEXT:    i32.const $push3=, 16
200; CHECK-NEXT:    i32.sub  $push7=, $pop2, $pop3
201; CHECK-NEXT:    local.tee $push6=, 5, $pop7
202; CHECK-NEXT:    global.set __stack_pointer, $pop6
203; CHECK-NEXT:    local.get $push12=, 5
204; CHECK-NEXT:    local.get $push11=, 1
205; CHECK-NEXT:    local.get $push10=, 2
206; CHECK-NEXT:    local.get $push9=, 3
207; CHECK-NEXT:    local.get $push8=, 4
208; CHECK-NEXT:    call __umodti3, $pop12, $pop11, $pop10, $pop9, $pop8
209; CHECK-NEXT:    local.get $push14=, 0
210; CHECK-NEXT:    local.get $push13=, 5
211; CHECK-NEXT:    i64.load $push0=, 8($pop13)
212; CHECK-NEXT:    i64.store 8($pop14), $pop0
213; CHECK-NEXT:    local.get $push16=, 0
214; CHECK-NEXT:    local.get $push15=, 5
215; CHECK-NEXT:    i64.load $push1=, 0($pop15)
216; CHECK-NEXT:    i64.store 0($pop16), $pop1
217; CHECK-NEXT:    local.get $push17=, 5
218; CHECK-NEXT:    i32.const $push4=, 16
219; CHECK-NEXT:    i32.add  $push5=, $pop17, $pop4
220; CHECK-NEXT:    global.set __stack_pointer, $pop5
221; CHECK-NEXT:    return
222  %a = urem i128 %x, %y
223  ret i128 %a
224}
225
226define i128 @and128(i128 %x, i128 %y) {
227; CHECK-LABEL: and128:
228; CHECK:         .functype and128 (i32, i64, i64, i64, i64) -> ()
229; CHECK-NEXT:  # %bb.0:
230; CHECK-NEXT:    local.get $push4=, 0
231; CHECK-NEXT:    local.get $push3=, 2
232; CHECK-NEXT:    local.get $push2=, 4
233; CHECK-NEXT:    i64.and $push0=, $pop3, $pop2
234; CHECK-NEXT:    i64.store 8($pop4), $pop0
235; CHECK-NEXT:    local.get $push7=, 0
236; CHECK-NEXT:    local.get $push6=, 1
237; CHECK-NEXT:    local.get $push5=, 3
238; CHECK-NEXT:    i64.and $push1=, $pop6, $pop5
239; CHECK-NEXT:    i64.store 0($pop7), $pop1
240; CHECK-NEXT:    return
241  %a = and i128 %x, %y
242  ret i128 %a
243}
244
245define i128 @or128(i128 %x, i128 %y) {
246; CHECK-LABEL: or128:
247; CHECK:         .functype or128 (i32, i64, i64, i64, i64) -> ()
248; CHECK-NEXT:  # %bb.0:
249; CHECK-NEXT:    local.get $push4=, 0
250; CHECK-NEXT:    local.get $push3=, 2
251; CHECK-NEXT:    local.get $push2=, 4
252; CHECK-NEXT:    i64.or $push0=, $pop3, $pop2
253; CHECK-NEXT:    i64.store 8($pop4), $pop0
254; CHECK-NEXT:    local.get $push7=, 0
255; CHECK-NEXT:    local.get $push6=, 1
256; CHECK-NEXT:    local.get $push5=, 3
257; CHECK-NEXT:    i64.or $push1=, $pop6, $pop5
258; CHECK-NEXT:    i64.store 0($pop7), $pop1
259; CHECK-NEXT:    return
260  %a = or i128 %x, %y
261  ret i128 %a
262}
263
264define i128 @xor128(i128 %x, i128 %y) {
265; CHECK-LABEL: xor128:
266; CHECK:         .functype xor128 (i32, i64, i64, i64, i64) -> ()
267; CHECK-NEXT:  # %bb.0:
268; CHECK-NEXT:    local.get $push4=, 0
269; CHECK-NEXT:    local.get $push3=, 2
270; CHECK-NEXT:    local.get $push2=, 4
271; CHECK-NEXT:    i64.xor $push0=, $pop3, $pop2
272; CHECK-NEXT:    i64.store 8($pop4), $pop0
273; CHECK-NEXT:    local.get $push7=, 0
274; CHECK-NEXT:    local.get $push6=, 1
275; CHECK-NEXT:    local.get $push5=, 3
276; CHECK-NEXT:    i64.xor $push1=, $pop6, $pop5
277; CHECK-NEXT:    i64.store 0($pop7), $pop1
278; CHECK-NEXT:    return
279  %a = xor i128 %x, %y
280  ret i128 %a
281}
282
283define i128 @shl128(i128 %x, i128 %y) {
284; CHECK-LABEL: shl128:
285; CHECK:         .functype shl128 (i32, i64, i64, i64, i64) -> ()
286; CHECK-NEXT:    .local i32
287; CHECK-NEXT:  # %bb.0:
288; CHECK-NEXT:    global.get $push3=, __stack_pointer
289; CHECK-NEXT:    i32.const $push4=, 16
290; CHECK-NEXT:    i32.sub  $push8=, $pop3, $pop4
291; CHECK-NEXT:    local.tee $push7=, 5, $pop8
292; CHECK-NEXT:    global.set __stack_pointer, $pop7
293; CHECK-NEXT:    local.get $push12=, 5
294; CHECK-NEXT:    local.get $push11=, 1
295; CHECK-NEXT:    local.get $push10=, 2
296; CHECK-NEXT:    local.get $push9=, 3
297; CHECK-NEXT:    i32.wrap_i64 $push0=, $pop9
298; CHECK-NEXT:    call __ashlti3, $pop12, $pop11, $pop10, $pop0
299; CHECK-NEXT:    local.get $push14=, 0
300; CHECK-NEXT:    local.get $push13=, 5
301; CHECK-NEXT:    i64.load $push1=, 8($pop13)
302; CHECK-NEXT:    i64.store 8($pop14), $pop1
303; CHECK-NEXT:    local.get $push16=, 0
304; CHECK-NEXT:    local.get $push15=, 5
305; CHECK-NEXT:    i64.load $push2=, 0($pop15)
306; CHECK-NEXT:    i64.store 0($pop16), $pop2
307; CHECK-NEXT:    local.get $push17=, 5
308; CHECK-NEXT:    i32.const $push5=, 16
309; CHECK-NEXT:    i32.add  $push6=, $pop17, $pop5
310; CHECK-NEXT:    global.set __stack_pointer, $pop6
311; CHECK-NEXT:    return
312  %a = shl i128 %x, %y
313  ret i128 %a
314}
315
316define i128 @shr128(i128 %x, i128 %y) {
317; CHECK-LABEL: shr128:
318; CHECK:         .functype shr128 (i32, i64, i64, i64, i64) -> ()
319; CHECK-NEXT:    .local i32
320; CHECK-NEXT:  # %bb.0:
321; CHECK-NEXT:    global.get $push3=, __stack_pointer
322; CHECK-NEXT:    i32.const $push4=, 16
323; CHECK-NEXT:    i32.sub  $push8=, $pop3, $pop4
324; CHECK-NEXT:    local.tee $push7=, 5, $pop8
325; CHECK-NEXT:    global.set __stack_pointer, $pop7
326; CHECK-NEXT:    local.get $push12=, 5
327; CHECK-NEXT:    local.get $push11=, 1
328; CHECK-NEXT:    local.get $push10=, 2
329; CHECK-NEXT:    local.get $push9=, 3
330; CHECK-NEXT:    i32.wrap_i64 $push0=, $pop9
331; CHECK-NEXT:    call __lshrti3, $pop12, $pop11, $pop10, $pop0
332; CHECK-NEXT:    local.get $push14=, 0
333; CHECK-NEXT:    local.get $push13=, 5
334; CHECK-NEXT:    i64.load $push1=, 8($pop13)
335; CHECK-NEXT:    i64.store 8($pop14), $pop1
336; CHECK-NEXT:    local.get $push16=, 0
337; CHECK-NEXT:    local.get $push15=, 5
338; CHECK-NEXT:    i64.load $push2=, 0($pop15)
339; CHECK-NEXT:    i64.store 0($pop16), $pop2
340; CHECK-NEXT:    local.get $push17=, 5
341; CHECK-NEXT:    i32.const $push5=, 16
342; CHECK-NEXT:    i32.add  $push6=, $pop17, $pop5
343; CHECK-NEXT:    global.set __stack_pointer, $pop6
344; CHECK-NEXT:    return
345  %a = lshr i128 %x, %y
346  ret i128 %a
347}
348
349define i128 @sar128(i128 %x, i128 %y) {
350; CHECK-LABEL: sar128:
351; CHECK:         .functype sar128 (i32, i64, i64, i64, i64) -> ()
352; CHECK-NEXT:    .local i32
353; CHECK-NEXT:  # %bb.0:
354; CHECK-NEXT:    global.get $push3=, __stack_pointer
355; CHECK-NEXT:    i32.const $push4=, 16
356; CHECK-NEXT:    i32.sub  $push8=, $pop3, $pop4
357; CHECK-NEXT:    local.tee $push7=, 5, $pop8
358; CHECK-NEXT:    global.set __stack_pointer, $pop7
359; CHECK-NEXT:    local.get $push12=, 5
360; CHECK-NEXT:    local.get $push11=, 1
361; CHECK-NEXT:    local.get $push10=, 2
362; CHECK-NEXT:    local.get $push9=, 3
363; CHECK-NEXT:    i32.wrap_i64 $push0=, $pop9
364; CHECK-NEXT:    call __ashrti3, $pop12, $pop11, $pop10, $pop0
365; CHECK-NEXT:    local.get $push14=, 0
366; CHECK-NEXT:    local.get $push13=, 5
367; CHECK-NEXT:    i64.load $push1=, 8($pop13)
368; CHECK-NEXT:    i64.store 8($pop14), $pop1
369; CHECK-NEXT:    local.get $push16=, 0
370; CHECK-NEXT:    local.get $push15=, 5
371; CHECK-NEXT:    i64.load $push2=, 0($pop15)
372; CHECK-NEXT:    i64.store 0($pop16), $pop2
373; CHECK-NEXT:    local.get $push17=, 5
374; CHECK-NEXT:    i32.const $push5=, 16
375; CHECK-NEXT:    i32.add  $push6=, $pop17, $pop5
376; CHECK-NEXT:    global.set __stack_pointer, $pop6
377; CHECK-NEXT:    return
378  %a = ashr i128 %x, %y
379  ret i128 %a
380}
381
382define i128 @clz128(i128 %x) {
383; CHECK-LABEL: clz128:
384; CHECK:         .functype clz128 (i32, i64, i64) -> ()
385; CHECK-NEXT:  # %bb.0:
386; CHECK-NEXT:    local.get $push8=, 0
387; CHECK-NEXT:    i64.const $push0=, 0
388; CHECK-NEXT:    i64.store 8($pop8), $pop0
389; CHECK-NEXT:    local.get $push12=, 0
390; CHECK-NEXT:    local.get $push9=, 2
391; CHECK-NEXT:    i64.clz $push5=, $pop9
392; CHECK-NEXT:    local.get $push10=, 1
393; CHECK-NEXT:    i64.clz $push2=, $pop10
394; CHECK-NEXT:    i64.const $push3=, 64
395; CHECK-NEXT:    i64.add $push4=, $pop2, $pop3
396; CHECK-NEXT:    local.get $push11=, 2
397; CHECK-NEXT:    i64.const $push7=, 0
398; CHECK-NEXT:    i64.ne $push1=, $pop11, $pop7
399; CHECK-NEXT:    i64.select $push6=, $pop5, $pop4, $pop1
400; CHECK-NEXT:    i64.store 0($pop12), $pop6
401; CHECK-NEXT:    return
402  %a = call i128 @llvm.ctlz.i128(i128 %x, i1 false)
403  ret i128 %a
404}
405
406define i128 @clz128_zero_undef(i128 %x) {
407; CHECK-LABEL: clz128_zero_undef:
408; CHECK:         .functype clz128_zero_undef (i32, i64, i64) -> ()
409; CHECK-NEXT:  # %bb.0:
410; CHECK-NEXT:    local.get $push8=, 0
411; CHECK-NEXT:    i64.const $push0=, 0
412; CHECK-NEXT:    i64.store 8($pop8), $pop0
413; CHECK-NEXT:    local.get $push12=, 0
414; CHECK-NEXT:    local.get $push9=, 2
415; CHECK-NEXT:    i64.clz $push5=, $pop9
416; CHECK-NEXT:    local.get $push10=, 1
417; CHECK-NEXT:    i64.clz $push2=, $pop10
418; CHECK-NEXT:    i64.const $push3=, 64
419; CHECK-NEXT:    i64.add $push4=, $pop2, $pop3
420; CHECK-NEXT:    local.get $push11=, 2
421; CHECK-NEXT:    i64.const $push7=, 0
422; CHECK-NEXT:    i64.ne $push1=, $pop11, $pop7
423; CHECK-NEXT:    i64.select $push6=, $pop5, $pop4, $pop1
424; CHECK-NEXT:    i64.store 0($pop12), $pop6
425; CHECK-NEXT:    return
426  %a = call i128 @llvm.ctlz.i128(i128 %x, i1 true)
427  ret i128 %a
428}
429
430define i128 @ctz128(i128 %x) {
431; CHECK-LABEL: ctz128:
432; CHECK:         .functype ctz128 (i32, i64, i64) -> ()
433; CHECK-NEXT:  # %bb.0:
434; CHECK-NEXT:    local.get $push8=, 0
435; CHECK-NEXT:    i64.const $push0=, 0
436; CHECK-NEXT:    i64.store 8($pop8), $pop0
437; CHECK-NEXT:    local.get $push12=, 0
438; CHECK-NEXT:    local.get $push9=, 1
439; CHECK-NEXT:    i64.ctz $push5=, $pop9
440; CHECK-NEXT:    local.get $push10=, 2
441; CHECK-NEXT:    i64.ctz $push2=, $pop10
442; CHECK-NEXT:    i64.const $push3=, 64
443; CHECK-NEXT:    i64.add $push4=, $pop2, $pop3
444; CHECK-NEXT:    local.get $push11=, 1
445; CHECK-NEXT:    i64.const $push7=, 0
446; CHECK-NEXT:    i64.ne $push1=, $pop11, $pop7
447; CHECK-NEXT:    i64.select $push6=, $pop5, $pop4, $pop1
448; CHECK-NEXT:    i64.store 0($pop12), $pop6
449; CHECK-NEXT:    return
450  %a = call i128 @llvm.cttz.i128(i128 %x, i1 false)
451  ret i128 %a
452}
453
454define i128 @ctz128_zero_undef(i128 %x) {
455; CHECK-LABEL: ctz128_zero_undef:
456; CHECK:         .functype ctz128_zero_undef (i32, i64, i64) -> ()
457; CHECK-NEXT:  # %bb.0:
458; CHECK-NEXT:    local.get $push8=, 0
459; CHECK-NEXT:    i64.const $push0=, 0
460; CHECK-NEXT:    i64.store 8($pop8), $pop0
461; CHECK-NEXT:    local.get $push12=, 0
462; CHECK-NEXT:    local.get $push9=, 1
463; CHECK-NEXT:    i64.ctz $push5=, $pop9
464; CHECK-NEXT:    local.get $push10=, 2
465; CHECK-NEXT:    i64.ctz $push2=, $pop10
466; CHECK-NEXT:    i64.const $push3=, 64
467; CHECK-NEXT:    i64.add $push4=, $pop2, $pop3
468; CHECK-NEXT:    local.get $push11=, 1
469; CHECK-NEXT:    i64.const $push7=, 0
470; CHECK-NEXT:    i64.ne $push1=, $pop11, $pop7
471; CHECK-NEXT:    i64.select $push6=, $pop5, $pop4, $pop1
472; CHECK-NEXT:    i64.store 0($pop12), $pop6
473; CHECK-NEXT:    return
474  %a = call i128 @llvm.cttz.i128(i128 %x, i1 true)
475  ret i128 %a
476}
477
478define i128 @popcnt128(i128 %x) {
479; CHECK-LABEL: popcnt128:
480; CHECK:         .functype popcnt128 (i32, i64, i64) -> ()
481; CHECK-NEXT:  # %bb.0:
482; CHECK-NEXT:    local.get $push4=, 0
483; CHECK-NEXT:    i64.const $push0=, 0
484; CHECK-NEXT:    i64.store 8($pop4), $pop0
485; CHECK-NEXT:    local.get $push7=, 0
486; CHECK-NEXT:    local.get $push5=, 1
487; CHECK-NEXT:    i64.popcnt $push2=, $pop5
488; CHECK-NEXT:    local.get $push6=, 2
489; CHECK-NEXT:    i64.popcnt $push1=, $pop6
490; CHECK-NEXT:    i64.add $push3=, $pop2, $pop1
491; CHECK-NEXT:    i64.store 0($pop7), $pop3
492; CHECK-NEXT:    return
493  %a = call i128 @llvm.ctpop.i128(i128 %x)
494  ret i128 %a
495}
496
497define i32 @eqz128(i128 %x) {
498; CHECK-LABEL: eqz128:
499; CHECK:         .functype eqz128 (i64, i64) -> (i32)
500; CHECK-NEXT:  # %bb.0:
501; CHECK-NEXT:    local.get $push3=, 0
502; CHECK-NEXT:    local.get $push2=, 1
503; CHECK-NEXT:    i64.or $push0=, $pop3, $pop2
504; CHECK-NEXT:    i64.eqz $push1=, $pop0
505; CHECK-NEXT:    return $pop1
506  %a = icmp eq i128 %x, 0
507  %b = zext i1 %a to i32
508  ret i32 %b
509}
510
511define i128 @rotl(i128 %x, i128 %y) {
512; CHECK-LABEL: rotl:
513; CHECK:         .functype rotl (i32, i64, i64, i64, i64) -> ()
514; CHECK-NEXT:    .local i32, i32
515; CHECK-NEXT:  # %bb.0:
516; CHECK-NEXT:    global.get $push8=, __stack_pointer
517; CHECK-NEXT:    i32.const $push9=, 32
518; CHECK-NEXT:    i32.sub  $push17=, $pop8, $pop9
519; CHECK-NEXT:    local.tee $push16=, 5, $pop17
520; CHECK-NEXT:    global.set __stack_pointer, $pop16
521; CHECK-NEXT:    local.get $push18=, 5
522; CHECK-NEXT:    i32.const $push12=, 16
523; CHECK-NEXT:    i32.add  $push13=, $pop18, $pop12
524; CHECK-NEXT:    local.get $push21=, 1
525; CHECK-NEXT:    local.get $push20=, 2
526; CHECK-NEXT:    local.get $push19=, 3
527; CHECK-NEXT:    i32.wrap_i64 $push15=, $pop19
528; CHECK-NEXT:    local.tee $push14=, 6, $pop15
529; CHECK-NEXT:    call __ashlti3, $pop13, $pop21, $pop20, $pop14
530; CHECK-NEXT:    local.get $push25=, 5
531; CHECK-NEXT:    local.get $push24=, 1
532; CHECK-NEXT:    local.get $push23=, 2
533; CHECK-NEXT:    i32.const $push0=, 128
534; CHECK-NEXT:    local.get $push22=, 6
535; CHECK-NEXT:    i32.sub  $push1=, $pop0, $pop22
536; CHECK-NEXT:    call __lshrti3, $pop25, $pop24, $pop23, $pop1
537; CHECK-NEXT:    local.get $push28=, 0
538; CHECK-NEXT:    local.get $push26=, 5
539; CHECK-NEXT:    i64.load $push2=, 24($pop26)
540; CHECK-NEXT:    local.get $push27=, 5
541; CHECK-NEXT:    i64.load $push3=, 8($pop27)
542; CHECK-NEXT:    i64.or   $push4=, $pop2, $pop3
543; CHECK-NEXT:    i64.store 8($pop28), $pop4
544; CHECK-NEXT:    local.get $push31=, 0
545; CHECK-NEXT:    local.get $push29=, 5
546; CHECK-NEXT:    i64.load $push5=, 16($pop29)
547; CHECK-NEXT:    local.get $push30=, 5
548; CHECK-NEXT:    i64.load $push6=, 0($pop30)
549; CHECK-NEXT:    i64.or   $push7=, $pop5, $pop6
550; CHECK-NEXT:    i64.store 0($pop31), $pop7
551; CHECK-NEXT:    local.get $push32=, 5
552; CHECK-NEXT:    i32.const $push10=, 32
553; CHECK-NEXT:    i32.add  $push11=, $pop32, $pop10
554; CHECK-NEXT:    global.set __stack_pointer, $pop11
555; CHECK-NEXT:    return
556  %z = sub i128 128, %y
557  %b = shl i128 %x, %y
558  %c = lshr i128 %x, %z
559  %d = or i128 %b, %c
560  ret i128 %d
561}
562
563define i128 @masked_rotl(i128 %x, i128 %y) {
564; CHECK-LABEL: masked_rotl:
565; CHECK:         .functype masked_rotl (i32, i64, i64, i64, i64) -> ()
566; CHECK-NEXT:    .local i32, i32
567; CHECK-NEXT:  # %bb.0:
568; CHECK-NEXT:    global.get $push10=, __stack_pointer
569; CHECK-NEXT:    i32.const $push11=, 32
570; CHECK-NEXT:    i32.sub  $push19=, $pop10, $pop11
571; CHECK-NEXT:    local.tee $push18=, 5, $pop19
572; CHECK-NEXT:    global.set __stack_pointer, $pop18
573; CHECK-NEXT:    local.get $push20=, 5
574; CHECK-NEXT:    i32.const $push14=, 16
575; CHECK-NEXT:    i32.add  $push15=, $pop20, $pop14
576; CHECK-NEXT:    local.get $push23=, 1
577; CHECK-NEXT:    local.get $push22=, 2
578; CHECK-NEXT:    local.get $push21=, 3
579; CHECK-NEXT:    i32.wrap_i64 $push0=, $pop21
580; CHECK-NEXT:    i32.const $push1=, 127
581; CHECK-NEXT:    i32.and  $push17=, $pop0, $pop1
582; CHECK-NEXT:    local.tee $push16=, 6, $pop17
583; CHECK-NEXT:    call __ashlti3, $pop15, $pop23, $pop22, $pop16
584; CHECK-NEXT:    local.get $push27=, 5
585; CHECK-NEXT:    local.get $push26=, 1
586; CHECK-NEXT:    local.get $push25=, 2
587; CHECK-NEXT:    i32.const $push2=, 128
588; CHECK-NEXT:    local.get $push24=, 6
589; CHECK-NEXT:    i32.sub  $push3=, $pop2, $pop24
590; CHECK-NEXT:    call __lshrti3, $pop27, $pop26, $pop25, $pop3
591; CHECK-NEXT:    local.get $push30=, 0
592; CHECK-NEXT:    local.get $push28=, 5
593; CHECK-NEXT:    i64.load $push4=, 24($pop28)
594; CHECK-NEXT:    local.get $push29=, 5
595; CHECK-NEXT:    i64.load $push5=, 8($pop29)
596; CHECK-NEXT:    i64.or   $push6=, $pop4, $pop5
597; CHECK-NEXT:    i64.store 8($pop30), $pop6
598; CHECK-NEXT:    local.get $push33=, 0
599; CHECK-NEXT:    local.get $push31=, 5
600; CHECK-NEXT:    i64.load $push7=, 16($pop31)
601; CHECK-NEXT:    local.get $push32=, 5
602; CHECK-NEXT:    i64.load $push8=, 0($pop32)
603; CHECK-NEXT:    i64.or   $push9=, $pop7, $pop8
604; CHECK-NEXT:    i64.store 0($pop33), $pop9
605; CHECK-NEXT:    local.get $push34=, 5
606; CHECK-NEXT:    i32.const $push12=, 32
607; CHECK-NEXT:    i32.add  $push13=, $pop34, $pop12
608; CHECK-NEXT:    global.set __stack_pointer, $pop13
609; CHECK-NEXT:    return
610  %a = and i128 %y, 127
611  %z = sub i128 128, %a
612  %b = shl i128 %x, %a
613  %c = lshr i128 %x, %z
614  %d = or i128 %b, %c
615  ret i128 %d
616}
617
618define i128 @rotr(i128 %x, i128 %y) {
619; CHECK-LABEL: rotr:
620; CHECK:         .functype rotr (i32, i64, i64, i64, i64) -> ()
621; CHECK-NEXT:    .local i32, i32
622; CHECK-NEXT:  # %bb.0:
623; CHECK-NEXT:    global.get $push8=, __stack_pointer
624; CHECK-NEXT:    i32.const $push9=, 32
625; CHECK-NEXT:    i32.sub  $push17=, $pop8, $pop9
626; CHECK-NEXT:    local.tee $push16=, 5, $pop17
627; CHECK-NEXT:    global.set __stack_pointer, $pop16
628; CHECK-NEXT:    local.get $push18=, 5
629; CHECK-NEXT:    i32.const $push12=, 16
630; CHECK-NEXT:    i32.add  $push13=, $pop18, $pop12
631; CHECK-NEXT:    local.get $push21=, 1
632; CHECK-NEXT:    local.get $push20=, 2
633; CHECK-NEXT:    local.get $push19=, 3
634; CHECK-NEXT:    i32.wrap_i64 $push15=, $pop19
635; CHECK-NEXT:    local.tee $push14=, 6, $pop15
636; CHECK-NEXT:    call __lshrti3, $pop13, $pop21, $pop20, $pop14
637; CHECK-NEXT:    local.get $push25=, 5
638; CHECK-NEXT:    local.get $push24=, 1
639; CHECK-NEXT:    local.get $push23=, 2
640; CHECK-NEXT:    i32.const $push0=, 128
641; CHECK-NEXT:    local.get $push22=, 6
642; CHECK-NEXT:    i32.sub  $push1=, $pop0, $pop22
643; CHECK-NEXT:    call __ashlti3, $pop25, $pop24, $pop23, $pop1
644; CHECK-NEXT:    local.get $push28=, 0
645; CHECK-NEXT:    local.get $push26=, 5
646; CHECK-NEXT:    i64.load $push2=, 24($pop26)
647; CHECK-NEXT:    local.get $push27=, 5
648; CHECK-NEXT:    i64.load $push3=, 8($pop27)
649; CHECK-NEXT:    i64.or   $push4=, $pop2, $pop3
650; CHECK-NEXT:    i64.store 8($pop28), $pop4
651; CHECK-NEXT:    local.get $push31=, 0
652; CHECK-NEXT:    local.get $push29=, 5
653; CHECK-NEXT:    i64.load $push5=, 16($pop29)
654; CHECK-NEXT:    local.get $push30=, 5
655; CHECK-NEXT:    i64.load $push6=, 0($pop30)
656; CHECK-NEXT:    i64.or   $push7=, $pop5, $pop6
657; CHECK-NEXT:    i64.store 0($pop31), $pop7
658; CHECK-NEXT:    local.get $push32=, 5
659; CHECK-NEXT:    i32.const $push10=, 32
660; CHECK-NEXT:    i32.add  $push11=, $pop32, $pop10
661; CHECK-NEXT:    global.set __stack_pointer, $pop11
662; CHECK-NEXT:    return
663  %z = sub i128 128, %y
664  %b = lshr i128 %x, %y
665  %c = shl i128 %x, %z
666  %d = or i128 %b, %c
667  ret i128 %d
668}
669
670define i128 @masked_rotr(i128 %x, i128 %y) {
671; CHECK-LABEL: masked_rotr:
672; CHECK:         .functype masked_rotr (i32, i64, i64, i64, i64) -> ()
673; CHECK-NEXT:    .local i32, i32
674; CHECK-NEXT:  # %bb.0:
675; CHECK-NEXT:    global.get $push10=, __stack_pointer
676; CHECK-NEXT:    i32.const $push11=, 32
677; CHECK-NEXT:    i32.sub  $push19=, $pop10, $pop11
678; CHECK-NEXT:    local.tee $push18=, 5, $pop19
679; CHECK-NEXT:    global.set __stack_pointer, $pop18
680; CHECK-NEXT:    local.get $push20=, 5
681; CHECK-NEXT:    i32.const $push14=, 16
682; CHECK-NEXT:    i32.add  $push15=, $pop20, $pop14
683; CHECK-NEXT:    local.get $push23=, 1
684; CHECK-NEXT:    local.get $push22=, 2
685; CHECK-NEXT:    local.get $push21=, 3
686; CHECK-NEXT:    i32.wrap_i64 $push0=, $pop21
687; CHECK-NEXT:    i32.const $push1=, 127
688; CHECK-NEXT:    i32.and  $push17=, $pop0, $pop1
689; CHECK-NEXT:    local.tee $push16=, 6, $pop17
690; CHECK-NEXT:    call __lshrti3, $pop15, $pop23, $pop22, $pop16
691; CHECK-NEXT:    local.get $push27=, 5
692; CHECK-NEXT:    local.get $push26=, 1
693; CHECK-NEXT:    local.get $push25=, 2
694; CHECK-NEXT:    i32.const $push2=, 128
695; CHECK-NEXT:    local.get $push24=, 6
696; CHECK-NEXT:    i32.sub  $push3=, $pop2, $pop24
697; CHECK-NEXT:    call __ashlti3, $pop27, $pop26, $pop25, $pop3
698; CHECK-NEXT:    local.get $push30=, 0
699; CHECK-NEXT:    local.get $push28=, 5
700; CHECK-NEXT:    i64.load $push4=, 24($pop28)
701; CHECK-NEXT:    local.get $push29=, 5
702; CHECK-NEXT:    i64.load $push5=, 8($pop29)
703; CHECK-NEXT:    i64.or   $push6=, $pop4, $pop5
704; CHECK-NEXT:    i64.store 8($pop30), $pop6
705; CHECK-NEXT:    local.get $push33=, 0
706; CHECK-NEXT:    local.get $push31=, 5
707; CHECK-NEXT:    i64.load $push7=, 16($pop31)
708; CHECK-NEXT:    local.get $push32=, 5
709; CHECK-NEXT:    i64.load $push8=, 0($pop32)
710; CHECK-NEXT:    i64.or   $push9=, $pop7, $pop8
711; CHECK-NEXT:    i64.store 0($pop33), $pop9
712; CHECK-NEXT:    local.get $push34=, 5
713; CHECK-NEXT:    i32.const $push12=, 32
714; CHECK-NEXT:    i32.add  $push13=, $pop34, $pop12
715; CHECK-NEXT:    global.set __stack_pointer, $pop13
716; CHECK-NEXT:    return
717  %a = and i128 %y, 127
718  %z = sub i128 128, %a
719  %b = lshr i128 %x, %a
720  %c = shl i128 %x, %z
721  %d = or i128 %b, %c
722  ret i128 %d
723}
724