Skip to content

Commit

Permalink
Auto merge of #58791 - denzp:asm-compile-tests, r=alexcrichton
Browse files Browse the repository at this point in the history
Introduce assembly tests suite

The change introduces a new test suite - **Assembly** tests. The motivation behind this is an ability to perform end-to-end codegen testing with LLVM backend. Turned out, NVPTX backend sometimes missing common Rust features (`i128` and libcalls in the past, and still full atomics support) due to different reasons.

Prior to this change, basic NVPTX assembly tests were implemented within `run-make` suite. Now, it's easier to write additional and maintain existing tests for the target.

cc @gnzlbg @peterhj
cc @eddyb I adjusted mangling scheme expectation, so there is no need to change the tests for #57967
  • Loading branch information
bors committed Mar 20, 2019
2 parents 9c499cc + 60f1644 commit 82e2f3e
Show file tree
Hide file tree
Showing 23 changed files with 327 additions and 140 deletions.
1 change: 1 addition & 0 deletions src/bootstrap/builder.rs
Expand Up @@ -374,6 +374,7 @@ impl<'a> Builder<'a> {
test::MirOpt,
test::Codegen,
test::CodegenUnits,
test::Assembly,
test::Incremental,
test::Debuginfo,
test::UiFullDeps,
Expand Down
6 changes: 6 additions & 0 deletions src/bootstrap/test.rs
Expand Up @@ -936,6 +936,12 @@ host_test!(RunMakeFullDeps {
suite: "run-make-fulldeps"
});

default_test!(Assembly {
path: "src/test/assembly",
mode: "assembly",
suite: "assembly"
});

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
struct Compiletest {
compiler: Compiler,
Expand Down
3 changes: 2 additions & 1 deletion src/ci/docker/test-various/Dockerfile
Expand Up @@ -53,7 +53,8 @@ ENV WASM_SCRIPT python2.7 /checkout/x.py test --target $WASM_TARGETS \

ENV NVPTX_TARGETS=nvptx64-nvidia-cuda
ENV NVPTX_SCRIPT python2.7 /checkout/x.py test --target $NVPTX_TARGETS \
src/test/run-make
src/test/run-make \
src/test/assembly

ENV MUSL_TARGETS=x86_64-unknown-linux-musl \
CC_x86_64_unknown_linux_musl=x86_64-linux-musl-gcc \
Expand Down
8 changes: 8 additions & 0 deletions src/test/assembly/auxiliary/breakpoint-panic-handler.rs
@@ -0,0 +1,8 @@
#![feature(core_intrinsics)]
#![no_std]

#[panic_handler]
unsafe fn breakpoint_panic_handler(_: &::core::panic::PanicInfo) -> ! {
core::intrinsics::breakpoint();
core::hint::unreachable_unchecked();
}
File renamed without changes.
12 changes: 12 additions & 0 deletions src/test/assembly/nvptx-arch-default.rs
@@ -0,0 +1,12 @@
// assembly-output: ptx-linker
// compile-flags: --crate-type cdylib
// only-nvptx64

#![no_std]

// aux-build: breakpoint-panic-handler.rs
extern crate breakpoint_panic_handler;

// Verify default target arch with ptx-linker.
// CHECK: .target sm_30
// CHECK: .address_size 64
9 changes: 9 additions & 0 deletions src/test/assembly/nvptx-arch-emit-asm.rs
@@ -0,0 +1,9 @@
// assembly-output: emit-asm
// compile-flags: --crate-type rlib
// only-nvptx64

#![no_std]

// Verify default arch without ptx-linker involved.
// CHECK: .target sm_30
// CHECK: .address_size 64
12 changes: 12 additions & 0 deletions src/test/assembly/nvptx-arch-link-arg.rs
@@ -0,0 +1,12 @@
// assembly-output: ptx-linker
// compile-flags: --crate-type cdylib -C link-arg=--arch=sm_60
// only-nvptx64

#![no_std]

// aux-build: breakpoint-panic-handler.rs
extern crate breakpoint_panic_handler;

// Verify target arch override via `link-arg`.
// CHECK: .target sm_60
// CHECK: .address_size 64
12 changes: 12 additions & 0 deletions src/test/assembly/nvptx-arch-target-cpu.rs
@@ -0,0 +1,12 @@
// assembly-output: ptx-linker
// compile-flags: --crate-type cdylib -C target-cpu=sm_50
// only-nvptx64

#![no_std]

// aux-build: breakpoint-panic-handler.rs
extern crate breakpoint_panic_handler;

// Verify target arch override via `target-cpu`.
// CHECK: .target sm_50
// CHECK: .address_size 64
85 changes: 85 additions & 0 deletions src/test/assembly/nvptx-atomics.rs
@@ -0,0 +1,85 @@
// assembly-output: ptx-linker
// compile-flags: --crate-type cdylib
// only-nvptx64

#![feature(abi_ptx, core_intrinsics)]
#![no_std]

use core::intrinsics::*;

// aux-build: breakpoint-panic-handler.rs
extern crate breakpoint_panic_handler;

// Currently, LLVM NVPTX backend can only emit atomic instructions with
// `relaxed` (PTX default) ordering. But it's also useful to make sure
// the backend won't fail with other orders. Apparently, the backend
// doesn't support fences as well. As a workaround `llvm.nvvm.membar.*`
// could work, and perhaps on the long run, all the atomic operations
// should rather be provided by `core::arch::nvptx`.

// Also, PTX ISA doesn't have atomic `load`, `store` and `nand`.

// FIXME(denzp): add tests for `core::sync::atomic::*`.

#[no_mangle]
pub unsafe extern "ptx-kernel" fn atomics_kernel(a: *mut u32) {
// CHECK: atom.global.and.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
// CHECK: atom.global.and.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
atomic_and(a, 1);
atomic_and_relaxed(a, 1);

// CHECK: atom.global.cas.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1, 2;
// CHECK: atom.global.cas.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1, 2;
atomic_cxchg(a, 1, 2);
atomic_cxchg_relaxed(a, 1, 2);

// CHECK: atom.global.max.s32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
// CHECK: atom.global.max.s32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
atomic_max(a, 1);
atomic_max_relaxed(a, 1);

// CHECK: atom.global.min.s32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
// CHECK: atom.global.min.s32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
atomic_min(a, 1);
atomic_min_relaxed(a, 1);

// CHECK: atom.global.or.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
// CHECK: atom.global.or.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
atomic_or(a, 1);
atomic_or_relaxed(a, 1);

// CHECK: atom.global.max.u32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
// CHECK: atom.global.max.u32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
atomic_umax(a, 1);
atomic_umax_relaxed(a, 1);

// CHECK: atom.global.min.u32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
// CHECK: atom.global.min.u32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
atomic_umin(a, 1);
atomic_umin_relaxed(a, 1);

// CHECK: atom.global.add.u32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
// CHECK: atom.global.add.u32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
atomic_xadd(a, 1);
atomic_xadd_relaxed(a, 1);

// CHECK: atom.global.exch.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
// CHECK: atom.global.exch.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
atomic_xchg(a, 1);
atomic_xchg_relaxed(a, 1);

// CHECK: atom.global.xor.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
// CHECK: atom.global.xor.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
atomic_xor(a, 1);
atomic_xor_relaxed(a, 1);

// CHECK: mov.u32 %[[sub_0_arg:r[0-9]+]], 100;
// CHECK: neg.s32 temp, %[[sub_0_arg]];
// CHECK: atom.global.add.u32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], temp;
atomic_xsub(a, 100);

// CHECK: mov.u32 %[[sub_1_arg:r[0-9]+]], 200;
// CHECK: neg.s32 temp, %[[sub_1_arg]];
// CHECK: atom.global.add.u32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], temp;
atomic_xsub_relaxed(a, 200);
}
27 changes: 27 additions & 0 deletions src/test/assembly/nvptx-internalizing.rs
@@ -0,0 +1,27 @@
// assembly-output: ptx-linker
// compile-flags: --crate-type cdylib
// only-nvptx64

#![feature(abi_ptx)]
#![no_std]

// aux-build: breakpoint-panic-handler.rs
extern crate breakpoint_panic_handler;

// aux-build: non-inline-dependency.rs
extern crate non_inline_dependency as dep;

// Verify that no extra function declarations are present.
// CHECK-NOT: .func

// CHECK: .visible .entry top_kernel(
#[no_mangle]
pub unsafe extern "ptx-kernel" fn top_kernel(a: *const u32, b: *mut u32) {
// CHECK: add.s32 %{{r[0-9]+}}, %{{r[0-9]+}}, 5;
*b = *a + 5;
}

// Verify that no extra function definitions are here.
// CHECK-NOT: .func
// CHECK-NOT: .entry

39 changes: 39 additions & 0 deletions src/test/assembly/nvptx-linking-binary.rs
@@ -0,0 +1,39 @@
// assembly-output: ptx-linker
// compile-flags: --crate-type bin
// only-nvptx64

#![feature(abi_ptx)]
#![no_main]
#![no_std]

// aux-build: breakpoint-panic-handler.rs
extern crate breakpoint_panic_handler;

// aux-build: non-inline-dependency.rs
extern crate non_inline_dependency as dep;

// Make sure declarations are there.
// CHECK: .func (.param .b32 func_retval0) wrapping_external_fn
// CHECK: .func (.param .b32 func_retval0) panicking_external_fn

// CHECK-LABEL: .visible .entry top_kernel(
#[no_mangle]
pub unsafe extern "ptx-kernel" fn top_kernel(a: *const u32, b: *mut u32) {
// CHECK: call.uni (retval0),
// CHECK-NEXT: wrapping_external_fn
// CHECK: ld.param.b32 %[[LHS:r[0-9]+]], [retval0+0];
let lhs = dep::wrapping_external_fn(*a);

// CHECK: call.uni (retval0),
// CHECK-NEXT: panicking_external_fn
// CHECK: ld.param.b32 %[[RHS:r[0-9]+]], [retval0+0];
let rhs = dep::panicking_external_fn(*a);

// CHECK: add.s32 %[[RES:r[0-9]+]], %[[RHS]], %[[LHS]];
// CHECK: st.global.u32 [%{{rd[0-9]+}}], %[[RES]];
*b = lhs + rhs;
}

// Verify that external function bodies are available.
// CHECK: .func (.param .b32 func_retval0) wrapping_external_fn
// CHECK: .func (.param .b32 func_retval0) panicking_external_fn
38 changes: 38 additions & 0 deletions src/test/assembly/nvptx-linking-cdylib.rs
@@ -0,0 +1,38 @@
// assembly-output: ptx-linker
// compile-flags: --crate-type cdylib
// only-nvptx64

#![feature(abi_ptx)]
#![no_std]

// aux-build: breakpoint-panic-handler.rs
extern crate breakpoint_panic_handler;

// aux-build: non-inline-dependency.rs
extern crate non_inline_dependency as dep;

// Make sure declarations are there.
// CHECK: .func (.param .b32 func_retval0) wrapping_external_fn
// CHECK: .func (.param .b32 func_retval0) panicking_external_fn

// CHECK-LABEL: .visible .entry top_kernel(
#[no_mangle]
pub unsafe extern "ptx-kernel" fn top_kernel(a: *const u32, b: *mut u32) {
// CHECK: call.uni (retval0),
// CHECK-NEXT: wrapping_external_fn
// CHECK: ld.param.b32 %[[LHS:r[0-9]+]], [retval0+0];
let lhs = dep::wrapping_external_fn(*a);

// CHECK: call.uni (retval0),
// CHECK-NEXT: panicking_external_fn
// CHECK: ld.param.b32 %[[RHS:r[0-9]+]], [retval0+0];
let rhs = dep::panicking_external_fn(*a);

// CHECK: add.s32 %[[RES:r[0-9]+]], %[[RHS]], %[[LHS]];
// CHECK: st.global.u32 [%{{rd[0-9]+}}], %[[RES]];
*b = lhs + rhs;
}

// Verify that external function bodies are available.
// CHECK: .func (.param .b32 func_retval0) wrapping_external_fn
// CHECK: .func (.param .b32 func_retval0) panicking_external_fn
@@ -1,13 +1,15 @@
#![no_std]
#![deny(warnings)]
// assembly-output: ptx-linker
// compile-flags: --crate-type cdylib
// only-nvptx64

#![feature(abi_ptx)]
#![no_std]

// Verify the default CUDA arch.
// CHECK: .target sm_30
// CHECK: .address_size 64
// aux-build: breakpoint-panic-handler.rs
extern crate breakpoint_panic_handler;

// Verify function name doesn't contain unacceaptable characters.
// CHECK: .func (.param .b32 func_retval0) [[IMPL_FN:_ZN[a-zA-Z0-9$_]+square[a-zA-Z0-9$_]+]]
// CHECK: .func (.param .b32 func_retval0) [[IMPL_FN:[a-zA-Z0-9$_]+square[a-zA-Z0-9$_]+]](

// CHECK-LABEL: .visible .entry top_kernel(
#[no_mangle]
Expand All @@ -33,9 +35,3 @@ pub mod deep {
}
}
}

// Verify that external function bodies are available.
// CHECK: .func (.param .b32 func_retval0) [[IMPL_FN]]
// CHECK: {
// CHECK: mul.lo.s32 %{{r[0-9]+}}, %{{r[0-9]+}}, %{{r[0-9]+}}
// CHECK: }
12 changes: 0 additions & 12 deletions src/test/run-make/nvptx-binary-crate/Makefile

This file was deleted.

28 changes: 0 additions & 28 deletions src/test/run-make/nvptx-binary-crate/main.rs

This file was deleted.

10 changes: 0 additions & 10 deletions src/test/run-make/nvptx-dylib-crate/Makefile

This file was deleted.

0 comments on commit 82e2f3e

Please sign in to comment.