xref: /llvm-project/llvm/test/CodeGen/WebAssembly/simd-reductions.ll (revision 122b0220fd45ee71acda912b0b712bb8edb6ba46)
1; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=+simd128 | FileCheck %s
2
3; Tests that redundant masking and conversions are folded out
4; following SIMD reduction instructions.
5
6target triple = "wasm32-unknown-unknown"
7
8; ==============================================================================
9; 16 x i8
10; ==============================================================================
11declare i32 @llvm.wasm.anytrue.v16i8(<16 x i8>)
12declare i32 @llvm.wasm.alltrue.v16i8(<16 x i8>)
13
14; CHECK-LABEL: any_v16i8_trunc:
15; CHECK-NEXT: .functype any_v16i8_trunc (v128) -> (i32){{$}}
16; CHECK-NEXT: v128.any_true $push[[R:[0-9]+]]=, $0{{$}}
17; CHECK-NEXT: return $pop[[R]]{{$}}
18define i32 @any_v16i8_trunc(<16 x i8> %x) {
19  %a = call i32 @llvm.wasm.anytrue.v16i8(<16 x i8> %x)
20  %b = trunc i32 %a to i1
21  %c = zext i1 %b to i32
22  ret i32 %c
23}
24
25; CHECK-LABEL: any_v16i8_ne:
26; CHECK-NEXT: .functype any_v16i8_ne (v128) -> (i32){{$}}
27; CHECK-NEXT: v128.any_true $push[[R:[0-9]+]]=, $0{{$}}
28; CHECK-NEXT: return $pop[[R]]{{$}}
29define i32 @any_v16i8_ne(<16 x i8> %x) {
30  %a = call i32 @llvm.wasm.anytrue.v16i8(<16 x i8> %x)
31  %b = icmp ne i32 %a, 0
32  %c = zext i1 %b to i32
33  ret i32 %c
34}
35
36; CHECK-LABEL: any_v16i8_eq:
37; CHECK-NEXT: .functype any_v16i8_eq (v128) -> (i32){{$}}
38; CHECK-NEXT: v128.any_true $push[[R:[0-9]+]]=, $0{{$}}
39; CHECK-NEXT: return $pop[[R]]{{$}}
40define i32 @any_v16i8_eq(<16 x i8> %x) {
41  %a = call i32 @llvm.wasm.anytrue.v16i8(<16 x i8> %x)
42  %b = icmp eq i32 %a, 1
43  %c = zext i1 %b to i32
44  ret i32 %c
45}
46
47; CHECK-LABEL: all_v16i8_trunc:
48; CHECK-NEXT: .functype all_v16i8_trunc (v128) -> (i32){{$}}
49; CHECK-NEXT: i8x16.all_true $push[[R:[0-9]+]]=, $0{{$}}
50; CHECK-NEXT: return $pop[[R]]{{$}}
51define i32 @all_v16i8_trunc(<16 x i8> %x) {
52  %a = call i32 @llvm.wasm.alltrue.v16i8(<16 x i8> %x)
53  %b = trunc i32 %a to i1
54  %c = zext i1 %b to i32
55  ret i32 %c
56}
57
58; CHECK-LABEL: all_v16i8_ne:
59; CHECK-NEXT: .functype all_v16i8_ne (v128) -> (i32){{$}}
60; CHECK-NEXT: i8x16.all_true $push[[R:[0-9]+]]=, $0{{$}}
61; CHECK-NEXT: return $pop[[R]]{{$}}
62define i32 @all_v16i8_ne(<16 x i8> %x) {
63  %a = call i32 @llvm.wasm.alltrue.v16i8(<16 x i8> %x)
64  %b = icmp ne i32 %a, 0
65  %c = zext i1 %b to i32
66  ret i32 %c
67}
68
69; CHECK-LABEL: all_v16i8_eq:
70; CHECK-NEXT: .functype all_v16i8_eq (v128) -> (i32){{$}}
71; CHECK-NEXT: i8x16.all_true $push[[R:[0-9]+]]=, $0{{$}}
72; CHECK-NEXT: return $pop[[R]]{{$}}
73define i32 @all_v16i8_eq(<16 x i8> %x) {
74  %a = call i32 @llvm.wasm.alltrue.v16i8(<16 x i8> %x)
75  %b = icmp eq i32 %a, 1
76  %c = zext i1 %b to i32
77  ret i32 %c
78}
79
80; ==============================================================================
81; 8 x i16
82; ==============================================================================
83declare i32 @llvm.wasm.anytrue.v8i16(<8 x i16>)
84declare i32 @llvm.wasm.alltrue.v8i16(<8 x i16>)
85
86; CHECK-LABEL: any_v8i16_trunc:
87; CHECK-NEXT: .functype any_v8i16_trunc (v128) -> (i32){{$}}
88; CHECK-NEXT: v128.any_true $push[[R:[0-9]+]]=, $0{{$}}
89; CHECK-NEXT: return $pop[[R]]{{$}}
90define i32 @any_v8i16_trunc(<8 x i16> %x) {
91  %a = call i32 @llvm.wasm.anytrue.v8i16(<8 x i16> %x)
92  %b = trunc i32 %a to i1
93  %c = zext i1 %b to i32
94  ret i32 %c
95}
96
97; CHECK-LABEL: any_v8i16_ne:
98; CHECK-NEXT: .functype any_v8i16_ne (v128) -> (i32){{$}}
99; CHECK-NEXT: v128.any_true $push[[R:[0-9]+]]=, $0{{$}}
100; CHECK-NEXT: return $pop[[R]]{{$}}
101define i32 @any_v8i16_ne(<8 x i16> %x) {
102  %a = call i32 @llvm.wasm.anytrue.v8i16(<8 x i16> %x)
103  %b = icmp ne i32 %a, 0
104  %c = zext i1 %b to i32
105  ret i32 %c
106}
107
108; CHECK-LABEL: any_v8i16_eq:
109; CHECK-NEXT: .functype any_v8i16_eq (v128) -> (i32){{$}}
110; CHECK-NEXT: v128.any_true $push[[R:[0-9]+]]=, $0{{$}}
111; CHECK-NEXT: return $pop[[R]]{{$}}
112define i32 @any_v8i16_eq(<8 x i16> %x) {
113  %a = call i32 @llvm.wasm.anytrue.v8i16(<8 x i16> %x)
114  %b = icmp eq i32 %a, 1
115  %c = zext i1 %b to i32
116  ret i32 %c
117}
118
119; CHECK-LABEL: all_v8i16_trunc:
120; CHECK-NEXT: .functype all_v8i16_trunc (v128) -> (i32){{$}}
121; CHECK-NEXT: i16x8.all_true $push[[R:[0-9]+]]=, $0{{$}}
122; CHECK-NEXT: return $pop[[R]]{{$}}
123define i32 @all_v8i16_trunc(<8 x i16> %x) {
124  %a = call i32 @llvm.wasm.alltrue.v8i16(<8 x i16> %x)
125  %b = trunc i32 %a to i1
126  %c = zext i1 %b to i32
127  ret i32 %c
128}
129
130; CHECK-LABEL: all_v8i16_ne:
131; CHECK-NEXT: .functype all_v8i16_ne (v128) -> (i32){{$}}
132; CHECK-NEXT: i16x8.all_true $push[[R:[0-9]+]]=, $0{{$}}
133; CHECK-NEXT: return $pop[[R]]{{$}}
134define i32 @all_v8i16_ne(<8 x i16> %x) {
135  %a = call i32 @llvm.wasm.alltrue.v8i16(<8 x i16> %x)
136  %b = icmp ne i32 %a, 0
137  %c = zext i1 %b to i32
138  ret i32 %c
139}
140
141; CHECK-LABEL: all_v8i16_eq:
142; CHECK-NEXT: .functype all_v8i16_eq (v128) -> (i32){{$}}
143; CHECK-NEXT: i16x8.all_true $push[[R:[0-9]+]]=, $0{{$}}
144; CHECK-NEXT: return $pop[[R]]{{$}}
145define i32 @all_v8i16_eq(<8 x i16> %x) {
146  %a = call i32 @llvm.wasm.alltrue.v8i16(<8 x i16> %x)
147  %b = icmp eq i32 %a, 1
148  %c = zext i1 %b to i32
149  ret i32 %c
150}
151
152; ==============================================================================
153; 4 x i32
154; ==============================================================================
155declare i32 @llvm.wasm.anytrue.v4i32(<4 x i32>)
156declare i32 @llvm.wasm.alltrue.v4i32(<4 x i32>)
157
158; CHECK-LABEL: any_v4i32_trunc:
159; CHECK-NEXT: .functype any_v4i32_trunc (v128) -> (i32){{$}}
160; CHECK-NEXT: v128.any_true $push[[R:[0-9]+]]=, $0{{$}}
161; CHECK-NEXT: return $pop[[R]]{{$}}
162define i32 @any_v4i32_trunc(<4 x i32> %x) {
163  %a = call i32 @llvm.wasm.anytrue.v4i32(<4 x i32> %x)
164  %b = trunc i32 %a to i1
165  %c = zext i1 %b to i32
166  ret i32 %c
167}
168
169; CHECK-LABEL: any_v4i32_ne:
170; CHECK-NEXT: .functype any_v4i32_ne (v128) -> (i32){{$}}
171; CHECK-NEXT: v128.any_true $push[[R:[0-9]+]]=, $0{{$}}
172; CHECK-NEXT: return $pop[[R]]{{$}}
173define i32 @any_v4i32_ne(<4 x i32> %x) {
174  %a = call i32 @llvm.wasm.anytrue.v4i32(<4 x i32> %x)
175  %b = icmp ne i32 %a, 0
176  %c = zext i1 %b to i32
177  ret i32 %c
178}
179
180; CHECK-LABEL: any_v4i32_eq:
181; CHECK-NEXT: .functype any_v4i32_eq (v128) -> (i32){{$}}
182; CHECK-NEXT: v128.any_true $push[[R:[0-9]+]]=, $0{{$}}
183; CHECK-NEXT: return $pop[[R]]{{$}}
184define i32 @any_v4i32_eq(<4 x i32> %x) {
185  %a = call i32 @llvm.wasm.anytrue.v4i32(<4 x i32> %x)
186  %b = icmp eq i32 %a, 1
187  %c = zext i1 %b to i32
188  ret i32 %c
189}
190
191; CHECK-LABEL: all_v4i32_trunc:
192; CHECK-NEXT: .functype all_v4i32_trunc (v128) -> (i32){{$}}
193; CHECK-NEXT: i32x4.all_true $push[[R:[0-9]+]]=, $0{{$}}
194; CHECK-NEXT: return $pop[[R]]{{$}}
195define i32 @all_v4i32_trunc(<4 x i32> %x) {
196  %a = call i32 @llvm.wasm.alltrue.v4i32(<4 x i32> %x)
197  %b = trunc i32 %a to i1
198  %c = zext i1 %b to i32
199  ret i32 %c
200}
201
202; CHECK-LABEL: all_v4i32_ne:
203; CHECK-NEXT: .functype all_v4i32_ne (v128) -> (i32){{$}}
204; CHECK-NEXT: i32x4.all_true $push[[R:[0-9]+]]=, $0{{$}}
205; CHECK-NEXT: return $pop[[R]]{{$}}
206define i32 @all_v4i32_ne(<4 x i32> %x) {
207  %a = call i32 @llvm.wasm.alltrue.v4i32(<4 x i32> %x)
208  %b = icmp ne i32 %a, 0
209  %c = zext i1 %b to i32
210  ret i32 %c
211}
212
213; CHECK-LABEL: all_v4i32_eq:
214; CHECK-NEXT: .functype all_v4i32_eq (v128) -> (i32){{$}}
215; CHECK-NEXT: i32x4.all_true $push[[R:[0-9]+]]=, $0{{$}}
216; CHECK-NEXT: return $pop[[R]]{{$}}
217define i32 @all_v4i32_eq(<4 x i32> %x) {
218  %a = call i32 @llvm.wasm.alltrue.v4i32(<4 x i32> %x)
219  %b = icmp eq i32 %a, 1
220  %c = zext i1 %b to i32
221  ret i32 %c
222}
223
224; ==============================================================================
225; 2 x i64
226; ==============================================================================
227declare i32 @llvm.wasm.anytrue.v2i64(<2 x i64>)
228declare i32 @llvm.wasm.alltrue.v2i64(<2 x i64>)
229
230; CHECK-LABEL: any_v2i64_trunc:
231; CHECK-NEXT: .functype any_v2i64_trunc (v128) -> (i32){{$}}
232; CHECK-NEXT: v128.any_true $push[[R:[0-9]+]]=, $0{{$}}
233; CHECK-NEXT: return $pop[[R]]{{$}}
234define i32 @any_v2i64_trunc(<2 x i64> %x) {
235  %a = call i32 @llvm.wasm.anytrue.v2i64(<2 x i64> %x)
236  %b = trunc i32 %a to i1
237  %c = zext i1 %b to i32
238  ret i32 %c
239}
240
241; CHECK-LABEL: any_v2i64_ne:
242; CHECK-NEXT: .functype any_v2i64_ne (v128) -> (i32){{$}}
243; CHECK-NEXT: v128.any_true $push[[R:[0-9]+]]=, $0{{$}}
244; CHECK-NEXT: return $pop[[R]]{{$}}
245define i32 @any_v2i64_ne(<2 x i64> %x) {
246  %a = call i32 @llvm.wasm.anytrue.v2i64(<2 x i64> %x)
247  %b = icmp ne i32 %a, 0
248  %c = zext i1 %b to i32
249  ret i32 %c
250}
251
252; CHECK-LABEL: any_v2i64_eq:
253; CHECK-NEXT: .functype any_v2i64_eq (v128) -> (i32){{$}}
254; CHECK-NEXT: v128.any_true $push[[R:[0-9]+]]=, $0{{$}}
255; CHECK-NEXT: return $pop[[R]]{{$}}
256define i32 @any_v2i64_eq(<2 x i64> %x) {
257  %a = call i32 @llvm.wasm.anytrue.v2i64(<2 x i64> %x)
258  %b = icmp eq i32 %a, 1
259  %c = zext i1 %b to i32
260  ret i32 %c
261}
262
263; CHECK-LABEL: all_v2i64_trunc:
264; CHECK-NEXT: .functype all_v2i64_trunc (v128) -> (i32){{$}}
265; CHECK-NEXT: i64x2.all_true $push[[R:[0-9]+]]=, $0{{$}}
266; CHECK-NEXT: return $pop[[R]]{{$}}
267define i32 @all_v2i64_trunc(<2 x i64> %x) {
268  %a = call i32 @llvm.wasm.alltrue.v2i64(<2 x i64> %x)
269  %b = trunc i32 %a to i1
270  %c = zext i1 %b to i32
271  ret i32 %c
272}
273
274; CHECK-LABEL: all_v2i64_ne:
275; CHECK-NEXT: .functype all_v2i64_ne (v128) -> (i32){{$}}
276; CHECK-NEXT: i64x2.all_true $push[[R:[0-9]+]]=, $0{{$}}
277; CHECK-NEXT: return $pop[[R]]{{$}}
278define i32 @all_v2i64_ne(<2 x i64> %x) {
279  %a = call i32 @llvm.wasm.alltrue.v2i64(<2 x i64> %x)
280  %b = icmp ne i32 %a, 0
281  %c = zext i1 %b to i32
282  ret i32 %c
283}
284
285; CHECK-LABEL: all_v2i64_eq:
286; CHECK-NEXT: .functype all_v2i64_eq (v128) -> (i32){{$}}
287; CHECK-NEXT: i64x2.all_true $push[[R:[0-9]+]]=, $0{{$}}
288; CHECK-NEXT: return $pop[[R]]{{$}}
289define i32 @all_v2i64_eq(<2 x i64> %x) {
290  %a = call i32 @llvm.wasm.alltrue.v2i64(<2 x i64> %x)
291  %b = icmp eq i32 %a, 1
292  %c = zext i1 %b to i32
293  ret i32 %c
294}
295