• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
2
3; Test that basic 128-bit integer operations assemble as expected.
4
5target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
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
12; CHECK-LABEL: add128:
13; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}}
14; CHECK-NOT:  .result
15; CHECK:      i64.add
16; CHECK:      i64.store
17; CHECK:      i64.add
18; CHECK:      i64.store
19; CHECK-NEXT: return{{$}}
20define i128 @add128(i128 %x, i128 %y) {
21  %a = add i128 %x, %y
22  ret i128 %a
23}
24
25; CHECK-LABEL: sub128:
26; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}}
27; CHECK-NOT: .result
28; CHECK:      i64.sub
29; CHECK:      i64.store
30; CHECK:      i64.sub
31; CHECK:      i64.store
32; CHECK-NEXT: return{{$}}
33define i128 @sub128(i128 %x, i128 %y) {
34  %a = sub i128 %x, %y
35  ret i128 %a
36}
37
38; CHECK-LABEL: mul128:
39; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}}
40; CHECK-NOT: .result
41; CHECK: call __multi3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}}
42; CHECK: return{{$}}
43define i128 @mul128(i128 %x, i128 %y) {
44  %a = mul i128 %x, %y
45  ret i128 %a
46}
47
48; CHECK-LABEL: sdiv128:
49; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}}
50; CHECK-NOT: .result
51; CHECK: call __divti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}}
52; CHECK: return{{$}}
53define i128 @sdiv128(i128 %x, i128 %y) {
54  %a = sdiv i128 %x, %y
55  ret i128 %a
56}
57
58; CHECK-LABEL: udiv128:
59; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}}
60; CHECK-NOT: .result
61; CHECK: call __udivti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}}
62; CHECK: return{{$}}
63define i128 @udiv128(i128 %x, i128 %y) {
64  %a = udiv i128 %x, %y
65  ret i128 %a
66}
67
68; CHECK-LABEL: srem128:
69; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}}
70; CHECK-NOT: .result
71; CHECK: call __modti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}}
72; CHECK: return{{$}}
73define i128 @srem128(i128 %x, i128 %y) {
74  %a = srem i128 %x, %y
75  ret i128 %a
76}
77
78; CHECK-LABEL: urem128:
79; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}}
80; CHECK-NOT: .result
81; CHECK: call __umodti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}}
82; CHECK: return{{$}}
83define i128 @urem128(i128 %x, i128 %y) {
84  %a = urem i128 %x, %y
85  ret i128 %a
86}
87
88; CHECK-LABEL: and128:
89; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}}
90; CHECK-NOT:  .result
91; CHECK:      i64.and
92; CHECK:      i64.store
93; CHECK:      i64.and
94; CHECK:      i64.store
95; CHECK-NEXT: return{{$}}
96define i128 @and128(i128 %x, i128 %y) {
97  %a = and i128 %x, %y
98  ret i128 %a
99}
100
101; CHECK-LABEL: or128:
102; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}}
103; CHECK-NOT: .result
104; CHECK:      i64.or
105; CHECK:      i64.store
106; CHECK:      i64.or
107; CHECK:      i64.store
108; CHECK-NEXT: return{{$}}
109define i128 @or128(i128 %x, i128 %y) {
110  %a = or i128 %x, %y
111  ret i128 %a
112}
113
114; CHECK-LABEL: xor128:
115; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}}
116; CHECK-NOT: .result
117; CHECK:      i64.xor
118; CHECK:      i64.store
119; CHECK:      i64.xor
120; CHECK:      i64.store
121; CHECK-NEXT: return{{$}}
122define i128 @xor128(i128 %x, i128 %y) {
123  %a = xor i128 %x, %y
124  ret i128 %a
125}
126
127; CHECK-LABEL: shl128:
128; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}}
129; CHECK-NOT: .result
130; CHECK: call __ashlti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}}
131; CHECK: return{{$}}
132define i128 @shl128(i128 %x, i128 %y) {
133  %a = shl i128 %x, %y
134  ret i128 %a
135}
136
137; CHECK-LABEL: shr128:
138; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}}
139; CHECK-NOT: .result
140; CHECK: call __lshrti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}}
141; CHECK: return{{$}}
142define i128 @shr128(i128 %x, i128 %y) {
143  %a = lshr i128 %x, %y
144  ret i128 %a
145}
146
147; CHECK-LABEL: sar128:
148; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}}
149; CHECK-NOT: .result
150; CHECK: call __ashrti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}}
151; CHECK: return{{$}}
152define i128 @sar128(i128 %x, i128 %y) {
153  %a = ashr i128 %x, %y
154  ret i128 %a
155}
156
157; CHECK-LABEL: clz128:
158; CHECK-NEXT: .param i32, i64, i64{{$}}
159; CHECK-NOT:  .result
160; CHECK:      i64.clz
161; CHECK:      i64.clz
162; CHECK:      return{{$}}
163define i128 @clz128(i128 %x) {
164  %a = call i128 @llvm.ctlz.i128(i128 %x, i1 false)
165  ret i128 %a
166}
167
168; CHECK-LABEL: clz128_zero_undef:
169; CHECK-NEXT: .param i32, i64, i64{{$}}
170; CHECK-NOT: .result
171; CHECK:      i64.clz
172; CHECK:      i64.clz
173; CHECK:      return{{$}}
174define i128 @clz128_zero_undef(i128 %x) {
175  %a = call i128 @llvm.ctlz.i128(i128 %x, i1 true)
176  ret i128 %a
177}
178
179; CHECK-LABEL: ctz128:
180; CHECK-NEXT: .param i32, i64, i64{{$}}
181; CHECK-NOT: .result
182; CHECK:      i64.ctz
183; CHECK:      i64.ctz
184; CHECK:      return{{$}}
185define i128 @ctz128(i128 %x) {
186  %a = call i128 @llvm.cttz.i128(i128 %x, i1 false)
187  ret i128 %a
188}
189
190; CHECK-LABEL: ctz128_zero_undef:
191; CHECK-NEXT: .param i32, i64, i64{{$}}
192; CHECK-NOT: .result
193; CHECK:      i64.ctz
194; CHECK:      i64.ctz
195; CHECK:      return{{$}}
196define i128 @ctz128_zero_undef(i128 %x) {
197  %a = call i128 @llvm.cttz.i128(i128 %x, i1 true)
198  ret i128 %a
199}
200
201; CHECK-LABEL: popcnt128:
202; CHECK-NEXT: .param i32, i64, i64{{$}}
203; CHECK-NOT: .result
204; CHECK:      i64.popcnt
205; CHECK:      i64.popcnt
206; CHECK:      return{{$}}
207define i128 @popcnt128(i128 %x) {
208  %a = call i128 @llvm.ctpop.i128(i128 %x)
209  ret i128 %a
210}
211
212; CHECK-LABEL: eqz128:
213; CHECK-NEXT: .param i64, i64{{$}}
214; CHECK-NEXT: .result i32{{$}}
215; CHECK:     i64.or
216; CHECK:     i64.eqz
217; CHECK:     return $
218define i32 @eqz128(i128 %x) {
219  %a = icmp eq i128 %x, 0
220  %b = zext i1 %a to i32
221  ret i32 %b
222}
223
224; CHECK-LABEL: rotl:
225; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}}
226; CHECK-NOT: .result
227; CHECK: call __ashlti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}}
228; CHECK: call __lshrti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}}
229; CHECK: return{{$}}
230define i128 @rotl(i128 %x, i128 %y) {
231  %z = sub i128 128, %y
232  %b = shl i128 %x, %y
233  %c = lshr i128 %x, %z
234  %d = or i128 %b, %c
235  ret i128 %d
236}
237
238; CHECK-LABEL: masked_rotl:
239; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}}
240; CHECK-NOT: .result
241; CHECK: call __ashlti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}}
242; CHECK: call __lshrti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}}
243; CHECK: return{{$}}
244define i128 @masked_rotl(i128 %x, i128 %y) {
245  %a = and i128 %y, 127
246  %z = sub i128 128, %a
247  %b = shl i128 %x, %a
248  %c = lshr i128 %x, %z
249  %d = or i128 %b, %c
250  ret i128 %d
251}
252
253; CHECK-LABEL: rotr:
254; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}}
255; CHECK-NOT: .result
256; CHECK: call __lshrti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}}
257; CHECK: call __ashlti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}}
258; CHECK: return{{$}}
259define i128 @rotr(i128 %x, i128 %y) {
260  %z = sub i128 128, %y
261  %b = lshr i128 %x, %y
262  %c = shl i128 %x, %z
263  %d = or i128 %b, %c
264  ret i128 %d
265}
266
267; CHECK-LABEL: masked_rotr:
268; CHECK-NEXT: .param i32, i64, i64, i64, i64{{$}}
269; CHECK-NOT: .result
270; CHECK: call __lshrti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}}
271; CHECK: call __ashlti3@FUNCTION, ${{.+}}, ${{.+}}, ${{.+}}, ${{.+}}{{$}}
272; CHECK: return{{$}}
273define i128 @masked_rotr(i128 %x, i128 %y) {
274  %a = and i128 %y, 127
275  %z = sub i128 128, %a
276  %b = lshr i128 %x, %a
277  %c = shl i128 %x, %z
278  %d = or i128 %b, %c
279  ret i128 %d
280}
281