OLD | NEW |
---|---|
1 ; This tests the NaCl intrinsics not related to atomic operations. | 1 ; This tests the NaCl intrinsics not related to atomic operations. |
2 | 2 |
3 ; RUN: %llvm2ice -O2 --verbose none %s | FileCheck %s | 3 ; RUN: %llvm2ice -O2 --verbose none %s | FileCheck %s |
4 ; RUN: %llvm2ice -O2 --verbose none %s | FileCheck %s --check-prefix=CHECKO2REM | 4 ; RUN: %llvm2ice -O2 --verbose none %s | FileCheck %s --check-prefix=CHECKO2REM |
5 ; RUN: %llvm2ice -Om1 --verbose none %s | FileCheck %s | 5 ; RUN: %llvm2ice -Om1 --verbose none %s | FileCheck %s |
6 ; RUN: %llvm2ice --verbose none %s | FileCheck --check-prefix=ERRORS %s | 6 ; RUN: %llvm2ice --verbose none %s | FileCheck --check-prefix=ERRORS %s |
7 | 7 |
8 ; RUN: %llvm2iceinsts %s | %szdiff %s | FileCheck --check-prefix=DUMP %s | 8 ; RUN: %llvm2iceinsts %s | %szdiff %s | FileCheck --check-prefix=DUMP %s |
9 ; RUN: %llvm2iceinsts --pnacl %s | %szdiff %s \ | 9 ; RUN: %llvm2iceinsts --pnacl %s | %szdiff %s \ |
10 ; RUN: | FileCheck --check-prefix=DUMP %s | 10 ; RUN: | FileCheck --check-prefix=DUMP %s |
11 | 11 |
12 declare i8* @llvm.nacl.read.tp() | 12 declare i8* @llvm.nacl.read.tp() |
13 declare void @llvm.memcpy.p0i8.p0i8.i32(i8*, i8*, i32, i32, i1) | 13 declare void @llvm.memcpy.p0i8.p0i8.i32(i8*, i8*, i32, i32, i1) |
14 declare void @llvm.memmove.p0i8.p0i8.i32(i8*, i8*, i32, i32, i1) | 14 declare void @llvm.memmove.p0i8.p0i8.i32(i8*, i8*, i32, i32, i1) |
15 declare void @llvm.memset.p0i8.i32(i8*, i8, i32, i32, i1) | 15 declare void @llvm.memset.p0i8.i32(i8*, i8, i32, i32, i1) |
16 declare void @llvm.nacl.longjmp(i8*, i32) | 16 declare void @llvm.nacl.longjmp(i8*, i32) |
17 declare i32 @llvm.nacl.setjmp(i8*) | 17 declare i32 @llvm.nacl.setjmp(i8*) |
18 declare float @llvm.sqrt.f32(float) | 18 declare float @llvm.sqrt.f32(float) |
19 declare double @llvm.sqrt.f64(double) | 19 declare double @llvm.sqrt.f64(double) |
20 declare void @llvm.trap() | 20 declare void @llvm.trap() |
21 declare i32 @llvm.ctlz.i32(i32, i1) | |
22 declare i64 @llvm.ctlz.i64(i64, i1) | |
23 declare i32 @llvm.cttz.i32(i32, i1) | |
24 declare i64 @llvm.cttz.i64(i64, i1) | |
25 declare i32 @llvm.ctpop.i32(i32) | |
26 declare i64 @llvm.ctpop.i64(i64) | |
21 | 27 |
22 define i32 @test_nacl_read_tp() { | 28 define i32 @test_nacl_read_tp() { |
23 entry: | 29 entry: |
24 %ptr = call i8* @llvm.nacl.read.tp() | 30 %ptr = call i8* @llvm.nacl.read.tp() |
25 %__1 = ptrtoint i8* %ptr to i32 | 31 %__1 = ptrtoint i8* %ptr to i32 |
26 ret i32 %__1 | 32 ret i32 %__1 |
27 } | 33 } |
28 ; CHECK-LABEL: test_nacl_read_tp | 34 ; CHECK-LABEL: test_nacl_read_tp |
29 ; CHECK: mov e{{.*}}, dword ptr gs:[0] | 35 ; CHECK: mov e{{.*}}, dword ptr gs:[0] |
30 ; CHECKO2REM-LABEL: test_nacl_read_tp | 36 ; CHECKO2REM-LABEL: test_nacl_read_tp |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
225 br i1 %r1, label %Zero, label %NonZero | 231 br i1 %r1, label %Zero, label %NonZero |
226 Zero: | 232 Zero: |
227 call void @llvm.trap() | 233 call void @llvm.trap() |
228 unreachable | 234 unreachable |
229 NonZero: | 235 NonZero: |
230 ret i32 1 | 236 ret i32 1 |
231 } | 237 } |
232 ; CHECK-LABEL: test_trap | 238 ; CHECK-LABEL: test_trap |
233 ; CHECK: ud2 | 239 ; CHECK: ud2 |
234 | 240 |
241 define i32 @test_ctlz_32(i32 %x) { | |
242 entry: | |
243 %r = call i32 @llvm.ctlz.i32(i32 %x, i1 0) | |
244 ret i32 %r | |
245 } | |
246 ; CHECK-LABEL: test_ctlz_32 | |
247 ; TODO(jvoung): If we detect that LZCNT is supported, then use that | |
248 ; and avoid the need to do the cmovne and xor stuff to guarantee that | |
249 ; the result is well-defined w/ input == 0. | |
250 ; CHECK: bsr [[REG_TMP:e.*]], {{.*}} | |
251 ; CHECK: mov [[REG_RES:e.*]], 63 | |
252 ; CHECK: cmovne [[REG_RES]], [[REG_TMP]] | |
253 ; CHECK: xor [[REG_RES]], 31 | |
254 | |
255 define i32 @test_ctlz_32_const() { | |
256 entry: | |
257 %r = call i32 @llvm.ctlz.i32(i32 123456, i1 0) | |
258 ret i32 %r | |
259 } | |
260 ; Could potentially constant fold this, but the front-end should have done that. | |
261 ; CHECK-LABEL: test_ctlz_32_const | |
262 ; CHECK: bsr | |
263 | |
264 define i32 @test_ctlz_32_ignored(i32 %x) { | |
265 entry: | |
266 %ignored = call i32 @llvm.ctlz.i32(i32 %x, i1 0) | |
267 ret i32 1 | |
268 } | |
269 ; CHECKO2REM-LABEL: test_ctlz_32_ignored | |
Jim Stichnoth
2014/07/15 17:15:02
It took me some time to remember what the O2REM te
jvoung (off chromium)
2014/07/15 21:30:23
Done.
| |
270 ; CHECKO2REM-NOT: bsr | |
271 | |
272 define i64 @test_ctlz_64(i64 %x) { | |
273 entry: | |
274 %r = call i64 @llvm.ctlz.i64(i64 %x, i1 0) | |
275 ret i64 %r | |
276 } | |
277 ; CHECKO2REM-LABEL: test_ctlz_64 | |
278 ; CHECK-LABEL: test_ctlz_64 | |
279 ; TODO(jvoung): If we detect that LZCNT is supported. | |
Jim Stichnoth
2014/07/15 17:15:02
The todo comment is a little odd...
jvoung (off chromium)
2014/07/15 21:30:23
Uh hmm.. I think I'll just remove it. There's alre
| |
280 ; CHECK: bsr [[REG_TMP1:e.*]], {{.*}} | |
281 ; CHECK: mov [[REG_RES1:e.*]], 63 | |
282 ; CHECK: cmovne [[REG_RES1]], [[REG_TMP1]] | |
283 ; CHECK: xor [[REG_RES1]], 31 | |
284 ; CHECK: add [[REG_RES1]], 32 | |
285 ; CHECK: bsr [[REG_RES2:e.*]], {{.*}} | |
286 ; CHECK: xor [[REG_RES2]], 31 | |
287 ; CHECK: test [[REG_UPPER:.*]], [[REG_UPPER]] | |
288 ; CHECK: cmove [[REG_RES2]], [[REG_RES1]] | |
289 ; CHECK: mov {{.*}}, 0 | |
290 | |
291 define i32 @test_ctlz_64_const(i64 %x) { | |
292 entry: | |
293 %r = call i64 @llvm.ctlz.i64(i64 123456789012, i1 0) | |
294 %r2 = trunc i64 %r to i32 | |
295 ret i32 %r2 | |
296 } | |
297 ; CHECK-LABEL: test_ctlz_64_const | |
298 ; CHECK: bsr | |
299 ; CHECK: bsr | |
300 | |
301 define i32 @test_ctlz_64_ignored(i64 %x) { | |
302 entry: | |
303 %ignored = call i64 @llvm.ctlz.i64(i64 1234567890, i1 0) | |
304 ret i32 2 | |
305 } | |
306 ; CHECKO2REM-LABEL: test_ctlz_64_ignored | |
307 ; CHECKO2REM-NOT: bsr | |
308 | |
309 define i32 @test_cttz_32(i32 %x) { | |
310 entry: | |
311 %r = call i32 @llvm.cttz.i32(i32 %x, i1 0) | |
312 ret i32 %r | |
313 } | |
314 ; CHECK-LABEL: test_cttz_32 | |
315 ; CHECK: bsf [[REG_IF_NOTZERO:e.*]], {{.*}} | |
316 ; CHECK: mov [[REG_IF_ZERO:e.*]], 32 | |
317 ; CHECK: cmovne [[REG_IF_ZERO]], [[REG_IF_NOTZERO]] | |
318 | |
319 define i64 @test_cttz_64(i64 %x) { | |
320 entry: | |
321 %r = call i64 @llvm.cttz.i64(i64 %x, i1 0) | |
322 ret i64 %r | |
323 } | |
324 ; CHECK-LABEL: test_cttz_64 | |
325 ; CHECK: bsf [[REG_IF_NOTZERO:e.*]], {{.*}} | |
326 ; CHECK: mov [[REG_RES1:e.*]], 32 | |
327 ; CHECK: cmovne [[REG_RES1]], [[REG_IF_NOTZERO]] | |
328 ; CHECK: add [[REG_RES1]], 32 | |
329 ; CHECK: bsf [[REG_RES2:e.*]], [[REG_LOWER:.*]] | |
330 ; CHECK: test [[REG_LOWER]], [[REG_LOWER]] | |
331 ; CHECK: cmove [[REG_RES2]], [[REG_RES1]] | |
332 ; CHECK: mov {{.*}}, 0 | |
333 | |
334 define i32 @test_popcount_32(i32 %x) { | |
335 entry: | |
336 %r = call i32 @llvm.ctpop.i32(i32 %x) | |
337 ret i32 %r | |
338 } | |
339 ; CHECK-LABEL: test_popcount_32 | |
340 ; CHECK: call __popcountsi2 | |
341 | |
342 define i64 @test_popcount_64(i64 %x) { | |
343 entry: | |
344 %r = call i64 @llvm.ctpop.i64(i64 %x) | |
345 ret i64 %r | |
346 } | |
347 ; CHECK-LABEL: test_popcount_64 | |
348 ; CHECK: call __popcountdi2 | |
349 ; __popcountdi2 only returns a 32-bit result, so clear the upper bits of | |
350 ; the return value just in case. | |
351 ; CHECK: mov {{.*}}, 0 | |
352 | |
353 define i32 @test_popcount_64_ret_i32(i64 %x) { | |
354 entry: | |
355 %r_i64 = call i64 @llvm.ctpop.i64(i64 %x) | |
356 %r = trunc i64 %r_i64 to i32 | |
357 ret i32 %r | |
358 } | |
359 ; If there is a trunc, then the mov {{.*}}, 0 is dead and gets optimized out. | |
360 ; CHECKO2REM-LABEL: test_popcount_64_ret_i32 | |
361 ; CHECKO2REM: call __popcountdi2 | |
362 ; CHECKO2REM-NOT: mov {{.*}}, 0 | |
363 | |
364 | |
235 ; ERRORS-NOT: ICE translation error | 365 ; ERRORS-NOT: ICE translation error |
236 ; DUMP-NOT: SZ | 366 ; DUMP-NOT: SZ |
OLD | NEW |