Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement vec_perm #451

Merged
merged 11 commits into from
May 23, 2018
Merged

Implement vec_perm #451

merged 11 commits into from
May 23, 2018

Conversation

lu-zero
Copy link
Contributor

@lu-zero lu-zero commented May 16, 2018

It is pretty much the opposite of vec_add: there is a single instruction vperm that works with all the possible vector types as long the operands and return type match.

The instruction has an endianness bias and it is implemented only for little endian for now.

ci/run.sh Outdated
@@ -26,6 +26,7 @@ case ${TARGET} in
export STDSIMD_DISABLE_ASSERT_INSTR=1
;;
powerpc64-*)
export RUSTFLAGS="${RUSTFLAGS} -C target-feature=+altivec"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should not be required

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is some stray from testing, let me remove it now.

@lu-zero lu-zero force-pushed the altivec branch 4 times, most recently from 47b90c2 to 20ec176 Compare May 17, 2018 11:43
@lu-zero
Copy link
Contributor Author

lu-zero commented May 17, 2018

Now using the arch-specific newtypes.

@lu-zero
Copy link
Contributor Author

lu-zero commented May 17, 2018

Now we also have xxpermdi so we can check how vsx instructions fare.

Copy link
Contributor

@gnzlbg gnzlbg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So it's looking really good. I've left some comments, mostly nitpicks.

I am worried that #[inline] won't be enough to propagate the constant through the trait method, but I don't recall if we can use #[inline(always)] here or not.

}
}

vector_perm!{ i8x16 }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should be implemented for the powerpc vector types, not the portable vector types. Right now they are type aliases, but the PowerPC vector types should be newtypes like on arm and mips.

/// Vector permute.
#[inline]
#[target_feature(enable = "altivec")]
pub unsafe fn vec_perm<T>(a: T, b: T, c: vector_unsigned_char) -> T
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assert_instr is missing, and won't work on the generic function. You are going to have to add some functions somewhere for it to work (at that point the solution will probably look very similar to that of vec_add).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vec_vperm is the function used for the test.

#[inline]
#[target_feature(enable = "altivec")]
#[cfg_attr(test, assert_instr(vperm))]
unsafe fn vec_vperm(a: vector_signed_int, b: vector_signed_int, c: vector_unsigned_char) -> vector_signed_int {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should add assert_instr tests for all vector types.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That function is the only one that is called for every vector type.

All the vector types are transmuted to i32x4.

T: sealed::VectorPerm,
{

if cfg!(target_endian = "little") {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prefer conditional compilation here: #[cfg(target_endian = "little")] and #[cfg(not(target_endian = "little"))] (or #[cfg(target_endian = "big")]).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something along the lines of

#[cfg(target_endian = "little")]
mod endian {

}
#[cfg(target_endian = "big")]
mod endian {

}
use self::endian::*;

@@ -666,6 +734,18 @@ mod tests {
use simd::*;
use stdsimd_test::simd_test;

#[simd_test(enable = "altivec")]
unsafe fn vec_perm_u16x8() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there should be one run-time test for every vector type as well

I think that for consistency with how it is done in the other architectures we should name the run-time tests: test_{intrinsic_name}_{short_vector_types}, so this becomes test_vec_perm_u16x8.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can macro those tests, but it would basically test that transmute works for those types.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would be great, testing these is tedious, but sometimes optimizations happen that break this, and we also scan for assert_instr in stdsimd-verify. It would be great if the names of these functions follows a convention so that the code that scans them automatically becomes easier to write. (I followed one convention for vec_add, but maybe there is a better one).

#[inline]
#[target_feature(enable = "vsx")]
#[cfg_attr(test, assert_instr(xxpermdi, dm = 0x0))]
unsafe fn xxpermdi(a: i64x2, b: i64x2, dm: u8) -> i64x2 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is missing a #[rustc_args_required_const(2)] to require that the user passes a compile-time constant to dm.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That won't work with the trait approach :/
crap

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe make this function and the trait method impls #[inline(always)] ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function exists mainly for the instruction test.

The const-argument is enforced on the only part that the user sees. Probably #[inline(always)] is a good idea in case the compiler decides to not const-propagate w/out the specific hint.

use stdsimd_test::simd_test;

#[simd_test(enable = "vsx")]
unsafe fn vec_xxpermdi_u62x2() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also missing tests for the other vector types.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As per vec_perm, it it would test how good mem::transmute is.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here the tests for other vector types are still missing, otherwise the rest of the PR LGTM and can be merged.

@lu-zero
Copy link
Contributor Author

lu-zero commented May 17, 2018

I refactored the endian-biased intrinsic support so it is a bit more structured.

@gnzlbg
Copy link
Contributor

gnzlbg commented May 17, 2018

So this looks good. I'll retry the tests once CI is working again.

@lu-zero lu-zero force-pushed the altivec branch 2 times, most recently from 6eba577 to 99bc589 Compare May 21, 2018 06:45
@lu-zero
Copy link
Contributor Author

lu-zero commented May 21, 2018

Now the set is rebased over #455

@alexcrichton
Copy link
Member

That's a... curious test failure!

---- coresimd::powerpc64::vsx::tests::vec_xxpermdi_u62x2 stdout ----
thread 'coresimd::powerpc64::vsx::tests::vec_xxpermdi_u62x2' panicked at 'assertion failed: `(left == right)`
  left: `u64x2(0, 2)`,
 right: `u64x2(0, 2)`', crates/coresimd/src/../../../coresimd/powerpc64/vsx.rs:293:9
note: Run with `RUST_BACKTRACE=1` for a backtrace.

@lu-zero
Copy link
Contributor Author

lu-zero commented May 21, 2018

Yes... how do we implement equality for that type on BE?

@gnzlbg
Copy link
Contributor

gnzlbg commented May 21, 2018

It's here: https://github.com/rust-lang-nursery/stdsimd/blob/master/coresimd/ppsv/api/partial_eq.rs#L9

We do a vertical equality comparison and then test if all bits are set.

@lu-zero
Copy link
Contributor Author

lu-zero commented May 22, 2018

I managed to find other unrelated problems while trying to reproduce the issue locally: rust-lang/rust#50960

Shall we demote powerpc and powerpc64 for the time being?

@gnzlbg
Copy link
Contributor

gnzlbg commented May 22, 2018

Shall we demote powerpc and powerpc64 for the time being?

That was the original plan any ways. We are currently only running the assert_instr tests on ppc64le so it makes sense to only run the run-time tests there as well.

Since ppc64le is the only practical PowerPC target, I think we should just focus on that one first.

@lu-zero
Copy link
Contributor Author

lu-zero commented May 22, 2018

Now it is all green (by cheating) :)

@gnzlbg
Copy link
Contributor

gnzlbg commented May 22, 2018

So I would prefer to just disable the run-time tests in CI e.g. by passing an environment variable that just ignores the #[simd_test]s on ppc and ppc64 instead of completely allowing them to fail. Note that all of the portable packed vector tests are currently passing on both ppc and ppc64 and I'd like to know when they break.

@lu-zero
Copy link
Contributor Author

lu-zero commented May 22, 2018

Sure, could you please point me how to do that and suggest a name for the variable?

@gnzlbg
Copy link
Contributor

gnzlbg commented May 22, 2018

We already have STDSIMD_TEST_EVERYTHING=1 so maybe STDSIMD_TEST_NORUN=1 ?

The place is the stdsimd-test-macro (https://github.com/rust-lang-nursery/stdsimd/blob/master/crates/simd-test-macro/src/lib.rs#L108) where you want to add an #[ignore] if a particular environment variable is defined, similar to how it is done in the assert-instr-macro here: https://github.com/rust-lang-nursery/stdsimd/blob/master/crates/assert-instr-macro/src/lib.rs#L42 and here https://github.com/rust-lang-nursery/stdsimd/blob/master/crates/assert-instr-macro/src/lib.rs#L135

@lu-zero
Copy link
Contributor Author

lu-zero commented May 22, 2018

Do you see something wrong in my travis update?

The big endian variant will be supported properly later.
@lu-zero
Copy link
Contributor Author

lu-zero commented May 22, 2018

The run script doesn't forward the environment set on travis. I put the env variable directly in the script.

@gnzlbg gnzlbg merged commit 137d07d into rust-lang:master May 23, 2018
@gnzlbg
Copy link
Contributor

gnzlbg commented May 23, 2018

Thanks a lot for this! This is really good work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants