xref: /llvm-project/llvm/test/CodeGen/WebAssembly/i32.ll (revision 122b0220fd45ee71acda912b0b712bb8edb6ba46)
1; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s
2
3; Test that basic 32-bit integer operations assemble as expected.
4
5target triple = "wasm32-unknown-unknown"
6
7declare i32 @llvm.ctlz.i32(i32, i1)
8declare i32 @llvm.cttz.i32(i32, i1)
9declare i32 @llvm.ctpop.i32(i32)
10
11; CHECK-LABEL: add32:
12; CHECK-NEXT: .functype add32 (i32, i32) -> (i32){{$}}
13; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
14; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}}
15; CHECK-NEXT: i32.add $push0=, $pop[[L0]], $pop[[L1]]{{$}}
16; CHECK-NEXT: return $pop0{{$}}
17define i32 @add32(i32 %x, i32 %y) {
18  %a = add i32 %x, %y
19  ret i32 %a
20}
21
22; CHECK-LABEL: sub32:
23; CHECK-NEXT: .functype sub32 (i32, i32) -> (i32){{$}}
24; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
25; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}}
26; CHECK-NEXT: i32.sub $push0=, $pop[[L0]], $pop[[L1]]{{$}}
27; CHECK-NEXT: return $pop0{{$}}
28define i32 @sub32(i32 %x, i32 %y) {
29  %a = sub i32 %x, %y
30  ret i32 %a
31}
32
33; CHECK-LABEL: mul32:
34; CHECK-NEXT: .functype mul32 (i32, i32) -> (i32){{$}}
35; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
36; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}}
37; CHECK-NEXT: i32.mul $push0=, $pop[[L0]], $pop[[L1]]{{$}}
38; CHECK-NEXT: return $pop0{{$}}
39define i32 @mul32(i32 %x, i32 %y) {
40  %a = mul i32 %x, %y
41  ret i32 %a
42}
43
44; CHECK-LABEL: sdiv32:
45; CHECK-NEXT: .functype sdiv32 (i32, i32) -> (i32){{$}}
46; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
47; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}}
48; CHECK-NEXT: i32.div_s $push0=, $pop[[L0]], $pop[[L1]]{{$}}
49; CHECK-NEXT: return $pop0{{$}}
50define i32 @sdiv32(i32 %x, i32 %y) {
51  %a = sdiv i32 %x, %y
52  ret i32 %a
53}
54
55; CHECK-LABEL: udiv32:
56; CHECK-NEXT: .functype udiv32 (i32, i32) -> (i32){{$}}
57; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
58; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}}
59; CHECK-NEXT: i32.div_u $push0=, $pop[[L0]], $pop[[L1]]{{$}}
60; CHECK-NEXT: return $pop0{{$}}
61define i32 @udiv32(i32 %x, i32 %y) {
62  %a = udiv i32 %x, %y
63  ret i32 %a
64}
65
66; CHECK-LABEL: srem32:
67; CHECK-NEXT: .functype srem32 (i32, i32) -> (i32){{$}}
68; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
69; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}}
70; CHECK-NEXT: i32.rem_s $push0=, $pop[[L0]], $pop[[L1]]{{$}}
71; CHECK-NEXT: return $pop0{{$}}
72define i32 @srem32(i32 %x, i32 %y) {
73  %a = srem i32 %x, %y
74  ret i32 %a
75}
76
77; CHECK-LABEL: urem32:
78; CHECK-NEXT: .functype urem32 (i32, i32) -> (i32){{$}}
79; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
80; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}}
81; CHECK-NEXT: i32.rem_u $push0=, $pop[[L0]], $pop[[L1]]{{$}}
82; CHECK-NEXT: return $pop0{{$}}
83define i32 @urem32(i32 %x, i32 %y) {
84  %a = urem i32 %x, %y
85  ret i32 %a
86}
87
88; CHECK-LABEL: and32:
89; CHECK-NEXT: .functype and32 (i32, i32) -> (i32){{$}}
90; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
91; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}}
92; CHECK-NEXT: i32.and $push0=, $pop[[L0]], $pop[[L1]]{{$}}
93; CHECK-NEXT: return $pop0{{$}}
94define i32 @and32(i32 %x, i32 %y) {
95  %a = and i32 %x, %y
96  ret i32 %a
97}
98
99; CHECK-LABEL: or32:
100; CHECK-NEXT: .functype or32 (i32, i32) -> (i32){{$}}
101; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
102; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}}
103; CHECK-NEXT: i32.or $push0=, $pop[[L0]], $pop[[L1]]{{$}}
104; CHECK-NEXT: return $pop0{{$}}
105define i32 @or32(i32 %x, i32 %y) {
106  %a = or i32 %x, %y
107  ret i32 %a
108}
109
110; CHECK-LABEL: xor32:
111; CHECK-NEXT: .functype xor32 (i32, i32) -> (i32){{$}}
112; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
113; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}}
114; CHECK-NEXT: i32.xor $push0=, $pop[[L0]], $pop[[L1]]{{$}}
115; CHECK-NEXT: return $pop0{{$}}
116define i32 @xor32(i32 %x, i32 %y) {
117  %a = xor i32 %x, %y
118  ret i32 %a
119}
120
121; CHECK-LABEL: shl32:
122; CHECK-NEXT: .functype shl32 (i32, i32) -> (i32){{$}}
123; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
124; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}}
125; CHECK-NEXT: i32.shl $push0=, $pop[[L0]], $pop[[L1]]{{$}}
126; CHECK-NEXT: return $pop0{{$}}
127define i32 @shl32(i32 %x, i32 %y) {
128  %a = shl i32 %x, %y
129  ret i32 %a
130}
131
132; CHECK-LABEL: shr32:
133; CHECK-NEXT: .functype shr32 (i32, i32) -> (i32){{$}}
134; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
135; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}}
136; CHECK-NEXT: i32.shr_u $push0=, $pop[[L0]], $pop[[L1]]{{$}}
137; CHECK-NEXT: return $pop0{{$}}
138define i32 @shr32(i32 %x, i32 %y) {
139  %a = lshr i32 %x, %y
140  ret i32 %a
141}
142
143; CHECK-LABEL: sar32:
144; CHECK-NEXT: .functype sar32 (i32, i32) -> (i32){{$}}
145; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
146; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}}
147; CHECK-NEXT: i32.shr_s $push0=, $pop[[L0]], $pop[[L1]]{{$}}
148; CHECK-NEXT: return $pop0{{$}}
149define i32 @sar32(i32 %x, i32 %y) {
150  %a = ashr i32 %x, %y
151  ret i32 %a
152}
153
154; CHECK-LABEL: clz32:
155; CHECK-NEXT: .functype clz32 (i32) -> (i32){{$}}
156; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
157; CHECK-NEXT: i32.clz $push0=, $pop[[L0]]{{$}}
158; CHECK-NEXT: return $pop0{{$}}
159define i32 @clz32(i32 %x) {
160  %a = call i32 @llvm.ctlz.i32(i32 %x, i1 false)
161  ret i32 %a
162}
163
164; CHECK-LABEL: clz32_zero_undef:
165; CHECK-NEXT: .functype clz32_zero_undef (i32) -> (i32){{$}}
166; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
167; CHECK-NEXT: i32.clz $push0=, $pop[[L0]]{{$}}
168; CHECK-NEXT: return $pop0{{$}}
169define i32 @clz32_zero_undef(i32 %x) {
170  %a = call i32 @llvm.ctlz.i32(i32 %x, i1 true)
171  ret i32 %a
172}
173
174; CHECK-LABEL: ctz32:
175; CHECK-NEXT: .functype ctz32 (i32) -> (i32){{$}}
176; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
177; CHECK-NEXT: i32.ctz $push0=, $pop[[L0]]{{$}}
178; CHECK-NEXT: return $pop0{{$}}
179define i32 @ctz32(i32 %x) {
180  %a = call i32 @llvm.cttz.i32(i32 %x, i1 false)
181  ret i32 %a
182}
183
184; CHECK-LABEL: ctz32_zero_undef:
185; CHECK-NEXT: .functype ctz32_zero_undef (i32) -> (i32){{$}}
186; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
187; CHECK-NEXT: i32.ctz $push0=, $pop[[L0]]{{$}}
188; CHECK-NEXT: return $pop0{{$}}
189define i32 @ctz32_zero_undef(i32 %x) {
190  %a = call i32 @llvm.cttz.i32(i32 %x, i1 true)
191  ret i32 %a
192}
193
194; CHECK-LABEL: popcnt32:
195; CHECK-NEXT: .functype popcnt32 (i32) -> (i32){{$}}
196; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
197; CHECK-NEXT: i32.popcnt $push0=, $pop[[L0]]{{$}}
198; CHECK-NEXT: return $pop0{{$}}
199define i32 @popcnt32(i32 %x) {
200  %a = call i32 @llvm.ctpop.i32(i32 %x)
201  ret i32 %a
202}
203
204; CHECK-LABEL: eqz32:
205; CHECK-NEXT: .functype eqz32 (i32) -> (i32){{$}}
206; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
207; CHECK-NEXT: i32.eqz $push0=, $pop[[L0]]{{$}}
208; CHECK-NEXT: return $pop0{{$}}
209define i32 @eqz32(i32 %x) {
210  %a = icmp eq i32 %x, 0
211  %b = zext i1 %a to i32
212  ret i32 %b
213}
214
215; CHECK-LABEL: rotl:
216; CHECK-NEXT: .functype rotl (i32, i32) -> (i32){{$}}
217; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
218; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}}
219; CHECK-NEXT: i32.rotl $push0=, $pop[[L0]], $pop[[L1]]
220; CHECK-NEXT: return $pop0{{$}}
221define i32 @rotl(i32 %x, i32 %y) {
222  %z = sub i32 32, %y
223  %b = shl i32 %x, %y
224  %c = lshr i32 %x, %z
225  %d = or i32 %b, %c
226  ret i32 %d
227}
228
229; CHECK-LABEL: masked_rotl:
230; CHECK-NEXT: .functype masked_rotl (i32, i32) -> (i32){{$}}
231; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
232; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}}
233; CHECK-NEXT: i32.rotl $push0=, $pop[[L0]], $pop[[L1]]
234; CHECK-NEXT: return $pop0{{$}}
235define i32 @masked_rotl(i32 %x, i32 %y) {
236  %a = and i32 %y, 31
237  %z = sub i32 32, %a
238  %b = shl i32 %x, %a
239  %c = lshr i32 %x, %z
240  %d = or i32 %b, %c
241  ret i32 %d
242}
243
244; CHECK-LABEL: rotr:
245; CHECK-NEXT: .functype rotr (i32, i32) -> (i32){{$}}
246; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
247; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}}
248; CHECK-NEXT: i32.rotr $push0=, $pop[[L0]], $pop[[L1]]
249; CHECK-NEXT: return $pop0{{$}}
250define i32 @rotr(i32 %x, i32 %y) {
251  %z = sub i32 32, %y
252  %b = lshr i32 %x, %y
253  %c = shl i32 %x, %z
254  %d = or i32 %b, %c
255  ret i32 %d
256}
257
258; CHECK-LABEL: masked_rotr:
259; CHECK-NEXT: .functype masked_rotr (i32, i32) -> (i32){{$}}
260; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
261; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}}
262; CHECK-NEXT: i32.rotr $push0=, $pop[[L0]], $pop[[L1]]
263; CHECK-NEXT: return $pop0{{$}}
264define i32 @masked_rotr(i32 %x, i32 %y) {
265  %a = and i32 %y, 31
266  %z = sub i32 32, %a
267  %b = lshr i32 %x, %a
268  %c = shl i32 %x, %z
269  %d = or i32 %b, %c
270  ret i32 %d
271}
272