Merge pull request #36 from alexcrichton/arm-ci

Add CI for more platforms
This commit is contained in:
Alex Crichton 2017-09-25 14:04:33 -05:00 committed by GitHub
commit d888d2d350
18 changed files with 241 additions and 86 deletions

View file

@ -1,15 +1,24 @@
language: rust
sudo: false
rust: nightly
matrix:
include:
- rust: nightly
- rust: nightly
os: osx
- env: TARGET=i686-unknown-linux-gnu
- env: TARGET=x86_64-unknown-linux-gnu NO_ADD=1
- env: TARGET=arm-unknown-linux-gnueabihf
- env: TARGET=armv7-unknown-linux-gnueabihf
- env: TARGET=aarch64-unknown-linux-gnu
- os: osx
env: TARGET=x86_64-apple-darwin NO_ADD=1
script: ci/run.sh
install:
- if [ "$NO_ADD" = "" ]; then rustup target add $TARGET; fi
script:
- cargo test
- cargo test --release
- cargo generate-lockfile
- ci/run-docker.sh $TARGET
notifications:
email:

View file

@ -58,7 +58,8 @@ fn disassemble_myself() -> HashMap<String, Vec<Function>> {
parse_otool(&str::from_utf8(&output.stdout).expect("stdout not utf8"))
} else {
let output = Command::new("objdump")
let objdump = env::var("OBJDUMP").unwrap_or("objdump".to_string());
let output = Command::new(objdump)
.arg("--disassemble")
.arg(&me)
.output()
@ -72,6 +73,13 @@ fn disassemble_myself() -> HashMap<String, Vec<Function>> {
fn parse_objdump(output: &str) -> HashMap<String, Vec<Function>> {
let mut lines = output.lines();
let expected_len = if cfg!(target_arch = "arm") {
8
} else if cfg!(target_arch = "aarch64") {
8
} else {
2
};
for line in output.lines().take(100) {
println!("{}", line);
@ -97,7 +105,7 @@ fn parse_objdump(output: &str) -> HashMap<String, Vec<Function>> {
let parts = instruction.split_whitespace()
.skip(1)
.skip_while(|s| {
s.len() == 2 && usize::from_str_radix(s, 16).is_ok()
s.len() == expected_len && usize::from_str_radix(s, 16).is_ok()
})
.map(|s| s.to_string())
.collect::<Vec<String>>();

View file

@ -0,0 +1,13 @@
FROM ubuntu:17.10
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc \
ca-certificates \
libc6-dev \
gcc-aarch64-linux-gnu \
libc6-dev-arm64-cross \
qemu-user \
make \
file
ENV CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc \
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUNNER="qemu-aarch64 -L /usr/aarch64-linux-gnu" \
OBJDUMP=aarch64-linux-gnu-objdump

View file

@ -0,0 +1,13 @@
FROM ubuntu:17.10
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc \
ca-certificates \
libc6-dev \
gcc-arm-linux-gnueabihf \
libc6-dev-armhf-cross \
qemu-user \
make \
file
ENV CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER=arm-linux-gnueabihf-gcc \
CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_RUNNER="qemu-arm -L /usr/arm-linux-gnueabihf" \
OBJDUMP=arm-linux-gnueabihf-objdump

View file

@ -0,0 +1,13 @@
FROM ubuntu:17.10
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc \
ca-certificates \
libc6-dev \
gcc-arm-linux-gnueabihf \
libc6-dev-armhf-cross \
qemu-user \
make \
file
ENV CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_LINKER=arm-linux-gnueabihf-gcc \
CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_RUNNER="qemu-arm -L /usr/arm-linux-gnueabihf" \
OBJDUMP=arm-linux-gnueabihf-objdump

View file

@ -0,0 +1,7 @@
FROM ubuntu:17.04
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc-multilib \
libc6-dev \
file \
make \
ca-certificates

View file

@ -0,0 +1,7 @@
FROM ubuntu:17.04
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc \
libc6-dev \
file \
make \
ca-certificates

View file

@ -0,0 +1,32 @@
# Small script to run tests for a target (or all targets) inside all the
# respective docker images.
set -ex
run() {
echo $1
docker build -t stdsimd ci/docker/$1
mkdir -p target
docker run \
--user `id -u`:`id -g` \
--rm \
--init \
--volume $HOME/.cargo:/cargo \
--env CARGO_HOME=/cargo \
--volume `rustc --print sysroot`:/rust:ro \
--env TARGET=$1 \
--volume `pwd`:/checkout:ro \
--volume `pwd`/target:/checkout/target \
--workdir /checkout \
stdsimd \
bash \
-c 'PATH=$PATH:/rust/bin exec ci/run.sh $1'
}
if [ -z "$1" ]; then
for d in `ls ci/docker/`; do
run $d
done
else
run $1
fi

6
library/stdarch/ci/run.sh Executable file
View file

@ -0,0 +1,6 @@
#!/bin/sh
set -ex
cargo test --target $TARGET
cargo test --release --target $TARGET

View file

@ -1,48 +1,57 @@
#![feature(target_feature)]
extern crate stdsimd;
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
mod example {
use std::env;
use stdsimd::simd as s;
use stdsimd::vendor;
extern crate stdsimd;
#[inline(never)]
#[target_feature = "+sse4.2"]
fn index(needle: &str, haystack: &str) -> usize {
assert!(needle.len() <= 16 && haystack.len() <= 16);
use std::env;
use self::stdsimd::simd as s;
use self::stdsimd::vendor;
let (needle_len, hay_len) = (needle.len(), haystack.len());
#[inline(never)]
#[target_feature = "+sse4.2"]
fn index(needle: &str, haystack: &str) -> usize {
assert!(needle.len() <= 16 && haystack.len() <= 16);
let mut needle = needle.to_string().into_bytes();
needle.resize(16, 0);
let vneedle = vendor::__m128i::from(s::u8x16::load(&needle, 0));
let (needle_len, hay_len) = (needle.len(), haystack.len());
let mut haystack = haystack.to_string().into_bytes();
haystack.resize(16, 0);
let vhaystack = vendor::__m128i::from(s::u8x16::load(&haystack, 0));
let mut needle = needle.to_string().into_bytes();
needle.resize(16, 0);
let vneedle = vendor::__m128i::from(s::u8x16::load(&needle, 0));
vendor::_mm_cmpestri(
vneedle, needle_len as i32, vhaystack, hay_len as i32,
vendor::_SIDD_CMP_EQUAL_ORDERED) as usize
let mut haystack = haystack.to_string().into_bytes();
haystack.resize(16, 0);
let vhaystack = vendor::__m128i::from(s::u8x16::load(&haystack, 0));
vendor::_mm_cmpestri(
vneedle, needle_len as i32, vhaystack, hay_len as i32,
vendor::_SIDD_CMP_EQUAL_ORDERED) as usize
}
pub fn main() {
// let x0: f64 = env::args().nth(1).unwrap().parse().unwrap();
// let x1: f64 = env::args().nth(2).unwrap().parse().unwrap();
// let x2: f64 = env::args().nth(3).unwrap().parse().unwrap();
// let x3: f64 = env::args().nth(4).unwrap().parse().unwrap();
// let y0: i32 = env::args().nth(5).unwrap().parse().unwrap();
// let y1: i32 = env::args().nth(6).unwrap().parse().unwrap();
// let y2: i32 = env::args().nth(7).unwrap().parse().unwrap();
// let y3: i32 = env::args().nth(8).unwrap().parse().unwrap();
// let a = s::f64x2::new(x0, x1);
// let b = s::f64x2::new(x2, x3);
// let r = s::_mm_cmplt_sd(a, b);
// let r = foobar(a, b);
let needle = env::args().nth(1).unwrap();
let haystack = env::args().nth(2).unwrap();
println!("{:?}", index(&needle, &haystack));
}
}
fn main() {
// let x0: f64 = env::args().nth(1).unwrap().parse().unwrap();
// let x1: f64 = env::args().nth(2).unwrap().parse().unwrap();
// let x2: f64 = env::args().nth(3).unwrap().parse().unwrap();
// let x3: f64 = env::args().nth(4).unwrap().parse().unwrap();
// let y0: i32 = env::args().nth(5).unwrap().parse().unwrap();
// let y1: i32 = env::args().nth(6).unwrap().parse().unwrap();
// let y2: i32 = env::args().nth(7).unwrap().parse().unwrap();
// let y3: i32 = env::args().nth(8).unwrap().parse().unwrap();
// let a = s::f64x2::new(x0, x1);
// let b = s::f64x2::new(x2, x3);
// let r = s::_mm_cmplt_sd(a, b);
// let r = foobar(a, b);
let needle = env::args().nth(1).unwrap();
let haystack = env::args().nth(2).unwrap();
println!("{:?}", index(&needle, &haystack));
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
example::main();
}

View file

@ -1,25 +1,33 @@
#![feature(target_feature)]
extern crate stdsimd;
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
mod example {
extern crate stdsimd;
use std::env;
use stdsimd::simd;
use std::env;
use self::stdsimd::simd;
#[inline(never)]
#[target_feature = "-sse2"]
fn myop(
(x0, x1, x2, x3): (u64, u64, u64, u64),
(y0, y1, y2, y3): (u64, u64, u64, u64),
) -> (u64, u64, u64, u64) {
let x = simd::u64x4::new(x0, x1, x2, x3);
let y = simd::u64x4::new(y0, y1, y2, y3);
let r = x * y;
(r.extract(0), r.extract(1), r.extract(2), r.extract(3))
#[inline(never)]
#[target_feature = "-sse2"]
fn myop(
(x0, x1, x2, x3): (u64, u64, u64, u64),
(y0, y1, y2, y3): (u64, u64, u64, u64),
) -> (u64, u64, u64, u64) {
let x = simd::u64x4::new(x0, x1, x2, x3);
let y = simd::u64x4::new(y0, y1, y2, y3);
let r = x * y;
(r.extract(0), r.extract(1), r.extract(2), r.extract(3))
}
pub fn main() {
let x = env::args().nth(1).unwrap().parse().unwrap();
let y = env::args().nth(1).unwrap().parse().unwrap();
let r = myop((x, x, x, x), (y, y, y, y));
println!("{:?}", r);
}
}
fn main() {
let x = env::args().nth(1).unwrap().parse().unwrap();
let y = env::args().nth(1).unwrap().parse().unwrap();
let r = myop((x, x, x, x), (y, y, y, y));
println!("{:?}", r);
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
example::main();
}

View file

@ -1,25 +1,33 @@
#![feature(target_feature)]
extern crate stdsimd;
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
mod example {
extern crate stdsimd;
use std::env;
use stdsimd::simd;
use std::env;
use self::stdsimd::simd;
#[inline(never)]
#[target_feature = "-sse2"]
fn myop(
(x0, x1, x2, x3): (u64, u64, u64, u64),
(y0, y1, y2, y3): (u64, u64, u64, u64),
) -> (u64, u64, u64, u64) {
let x = simd::u64x4::new(x0, x1, x2, x3);
let y = simd::u64x4::new(y0, y1, y2, y3);
let r = x * y;
(r.extract(0), r.extract(1), r.extract(2), r.extract(3))
#[inline(never)]
#[target_feature = "-sse2"]
fn myop(
(x0, x1, x2, x3): (u64, u64, u64, u64),
(y0, y1, y2, y3): (u64, u64, u64, u64),
) -> (u64, u64, u64, u64) {
let x = simd::u64x4::new(x0, x1, x2, x3);
let y = simd::u64x4::new(y0, y1, y2, y3);
let r = x * y;
(r.extract(0), r.extract(1), r.extract(2), r.extract(3))
}
pub fn main() {
let x = env::args().nth(1).unwrap().parse().unwrap();
let y = env::args().nth(2).unwrap().parse().unwrap();
let r = myop((x, x, x, x), (y, y, y, y));
println!("{:?}", r);
}
}
fn main() {
let x = env::args().nth(1).unwrap().parse().unwrap();
let y = env::args().nth(2).unwrap().parse().unwrap();
let r = myop((x, x, x, x), (y, y, y, y));
println!("{:?}", r);
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
example::main();
}

View file

@ -3,12 +3,8 @@
//! The reference is [ARMv6-M Architecture Reference
//! Manual](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0419c/index.html).
/// Reverse the order of the bytes.
#[inline(always)]
#[cfg_attr(test, assert_instr(rev))]
pub fn _rev_u8(x: u8) -> u8 {
x.swap_bytes() as u8
}
#[cfg(test)]
use assert_instr::assert_instr;
/// Reverse the order of the bytes.
#[inline(always)]

View file

@ -5,6 +5,9 @@
pub use super::v6::*;
#[cfg(test)]
use assert_instr::assert_instr;
/// Count Leading Zeros.
#[inline(always)]
#[cfg_attr(test, assert_instr(clz))]
@ -35,6 +38,7 @@ extern "C" {
/// Reverse the bit order.
#[inline(always)]
#[cfg_attr(test, assert_instr(rbit))]
#[cfg_attr(target_arch = "arm", target_feature = "+v7")]
pub fn _rbit_u32(x: u32) -> u32 {
unsafe { rbit_u32(x as i32) as u32 }
}

View file

@ -4,6 +4,9 @@
pub use super::v7::*;
#[cfg(test)]
use assert_instr::assert_instr;
/// Reverse the order of the bytes.
#[inline(always)]
#[cfg_attr(test, assert_instr(rev))]
@ -37,7 +40,7 @@ pub fn _rbit_u64(x: u64) -> u64 {
/// bits.
#[inline(always)]
// LLVM Bug (should be cls): https://bugs.llvm.org/show_bug.cgi?id=31802
#[cfg_attr(test, assert_instr(clz))]
#[cfg_attr(test, assert_instr(clz))]
pub fn _cls_u32(x: u32) -> u32 {
u32::leading_zeros(!x) as u32
}
@ -48,7 +51,7 @@ pub fn _cls_u32(x: u32) -> u32 {
/// bits.
#[inline(always)]
// LLVM Bug (should be cls): https://bugs.llvm.org/show_bug.cgi?id=31802
#[cfg_attr(test, assert_instr(clz))]
#[cfg_attr(test, assert_instr(clz))]
pub fn _cls_u64(x: u64) -> u64 {
u64::leading_zeros(!x) as u64
}

View file

@ -32,6 +32,7 @@ pub fn _bextr_u32(a: u32, start: u32, len: u32) -> u32 {
#[inline(always)]
#[target_feature = "+bmi"]
#[cfg_attr(test, assert_instr(bextr))]
#[cfg(not(target_arch = "x86"))]
pub fn _bextr_u64(a: u64, start: u64, len: u64) -> u64 {
_bextr2_u64(a, (start & 0xffu64) | ((len & 0xffu64) << 8u64))
}
@ -56,6 +57,7 @@ pub fn _bextr2_u32(a: u32, control: u32) -> u32 {
#[inline(always)]
#[target_feature = "+bmi"]
#[cfg_attr(test, assert_instr(bextr))]
#[cfg(not(target_arch = "x86"))]
pub fn _bextr2_u64(a: u64, control: u64) -> u64 {
unsafe { x86_bmi_bextr_64(a, control) }
}
@ -88,6 +90,7 @@ pub fn _blsi_u32(x: u32) -> u32 {
#[inline(always)]
#[target_feature = "+bmi"]
#[cfg_attr(test, assert_instr(blsi))]
#[cfg(not(target_arch = "x86"))] // generates lots of instructions
pub fn _blsi_u64(x: u64) -> u64 {
x & x.wrapping_neg()
}
@ -104,6 +107,7 @@ pub fn _blsmsk_u32(x: u32) -> u32 {
#[inline(always)]
#[target_feature = "+bmi"]
#[cfg_attr(test, assert_instr(blsmsk))]
#[cfg(not(target_arch = "x86"))] // generates lots of instructions
pub fn _blsmsk_u64(x: u64) -> u64 {
x ^ (x.wrapping_sub(1u64))
}
@ -124,6 +128,7 @@ pub fn _blsr_u32(x: u32) -> u32 {
#[inline(always)]
#[target_feature = "+bmi"]
#[cfg_attr(test, assert_instr(blsr))]
#[cfg(not(target_arch = "x86"))] // generates lots of instructions
pub fn _blsr_u64(x: u64) -> u64 {
x & (x.wrapping_sub(1))
}

View file

@ -16,7 +16,8 @@ use assert_instr::assert_instr;
/// the low half and the high half of the result.
#[inline(always)]
// LLVM BUG (should be mulxl): https://bugs.llvm.org/show_bug.cgi?id=34232
#[cfg_attr(test, assert_instr(imul))]
#[cfg_attr(all(test, target_arch = "x86_64"), assert_instr(imul))]
#[cfg_attr(all(test, target_arch = "x86"), assert_instr(mulx))]
#[target_feature = "+bmi2"]
pub fn _mulx_u32(a: u32, b: u32) -> (u32, u32) {
let result: u64 = (a as u64) * (b as u64);
@ -31,6 +32,7 @@ pub fn _mulx_u32(a: u32, b: u32) -> (u32, u32) {
#[inline(always)]
#[cfg_attr(test, assert_instr(mulx))]
#[target_feature = "+bmi2"]
#[cfg(not(target_arch = "x86"))] // calls an intrinsic
pub fn _mulx_u64(a: u64, b: u64) -> (u64, u64) {
let result: u128 = (a as u128) * (b as u128);
let hi = (result >> 64) as u64;
@ -66,6 +68,7 @@ pub fn _bzhi_u32(a: u32, index: u32) -> u32 {
#[inline(always)]
#[target_feature = "+bmi2"]
#[cfg_attr(test, assert_instr(bzhi))]
#[cfg(not(target_arch = "x86"))]
pub fn _bzhi_u64(a: u64, index: u64) -> u64 {
unsafe { x86_bmi2_bzhi_64(a, index) }
}
@ -85,6 +88,7 @@ pub fn _pdep_u32(a: u32, mask: u32) -> u32 {
#[inline(always)]
#[target_feature = "+bmi2"]
#[cfg_attr(test, assert_instr(pdep))]
#[cfg(not(target_arch = "x86"))]
pub fn _pdep_u64(a: u64, mask: u64) -> u64 {
unsafe { x86_bmi2_pdep_64(a, mask) }
}
@ -103,6 +107,7 @@ pub fn _pext_u32(a: u32, mask: u32) -> u32 {
#[inline(always)]
#[target_feature = "+bmi2"]
#[cfg_attr(test, assert_instr(pext))]
#[cfg(not(target_arch = "x86"))]
pub fn _pext_u64(a: u64, mask: u64) -> u64 {
unsafe { x86_bmi2_pext_64(a, mask) }
}

View file

@ -75,6 +75,7 @@ pub fn _blcfill_u32(x: u32) -> u32 {
#[inline(always)]
#[target_feature = "+tbm"]
#[cfg_attr(test, assert_instr(blcfill))]
#[cfg(not(target_arch = "x86"))] // generates lots of instructions
pub fn _blcfill_u64(x: u64) -> u64 {
x & (x.wrapping_add(1))
}
@ -95,6 +96,7 @@ pub fn _blci_u32(x: u32) -> u32 {
#[inline(always)]
#[target_feature = "+tbm"]
#[cfg_attr(test, assert_instr(blci))]
#[cfg(not(target_arch = "x86"))] // generates lots of instructions
pub fn _blci_u64(x: u64) -> u64 {
x | !(x.wrapping_add(1))
}
@ -115,6 +117,7 @@ pub fn _blcic_u32(x: u32) -> u32 {
#[inline(always)]
#[target_feature = "+tbm"]
#[cfg_attr(test, assert_instr(blcic))]
#[cfg(not(target_arch = "x86"))] // generates lots of instructions
pub fn _blcic_u64(x: u64) -> u64 {
!x & (x.wrapping_add(1))
}
@ -135,6 +138,7 @@ pub fn _blcmsk_u32(x: u32) -> u32 {
#[inline(always)]
#[target_feature = "+tbm"]
#[cfg_attr(test, assert_instr(blcmsk))]
#[cfg(not(target_arch = "x86"))] // generates lots of instructions
pub fn _blcmsk_u64(x: u64) -> u64 {
x ^ (x.wrapping_add(1))
}
@ -155,6 +159,7 @@ pub fn _blcs_u32(x: u32) -> u32 {
#[inline(always)]
#[target_feature = "+tbm"]
#[cfg_attr(test, assert_instr(blcs))]
#[cfg(not(target_arch = "x86"))] // generates lots of instructions
pub fn _blcs_u64(x: u64) -> u64 {
x | x.wrapping_add(1)
}
@ -175,6 +180,7 @@ pub fn _blsfill_u32(x: u32) -> u32 {
#[inline(always)]
#[target_feature = "+tbm"]
#[cfg_attr(test, assert_instr(blsfill))]
#[cfg(not(target_arch = "x86"))] // generates lots of instructions
pub fn _blsfill_u64(x: u64) -> u64 {
x | (x.wrapping_sub(1))
}
@ -195,6 +201,7 @@ pub fn _blsic_u32(x: u32) -> u32 {
#[inline(always)]
#[target_feature = "+tbm"]
#[cfg_attr(test, assert_instr(blsic))]
#[cfg(not(target_arch = "x86"))] // generates lots of instructions
pub fn _blsic_u64(x: u64) -> u64 {
!x | (x.wrapping_sub(1))
}
@ -217,6 +224,7 @@ pub fn _t1mskc_u32(x: u32) -> u32 {
#[inline(always)]
#[target_feature = "+tbm"]
#[cfg_attr(test, assert_instr(t1mskc))]
#[cfg(not(target_arch = "x86"))] // generates lots of instructions
pub fn _t1mskc_u64(x: u64) -> u64 {
!x | (x.wrapping_add(1))
}
@ -239,6 +247,7 @@ pub fn _tzmsk_u32(x: u32) -> u32 {
#[inline(always)]
#[target_feature = "+tbm"]
#[cfg_attr(test, assert_instr(tzmsk))]
#[cfg(not(target_arch = "x86"))] // generates lots of instructions
pub fn _tzmsk_u64(x: u64) -> u64 {
!x & (x.wrapping_sub(1))
}