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

SIMD groundwork part 1 #27169

Merged
merged 40 commits into from Aug 18, 2015

Conversation

Projects
None yet
7 participants
@huonw
Copy link
Member

huonw commented Jul 20, 2015

This implements rust-lang/rfcs#1199 (except for doing all the platform intrinsics).

Things remaining for SIMD (not necessarily in this PR):

  • I (@huonw) am signed up to ensure the compiler matches the RFC, when it lands
  • the platform specific intrinsics aren't properly type checked at the moment (LLVM will throw a "random" assertion)
  • there's a lot of useful intrinsics that are missing, including whole platforms (mips, powerpc)
  • the target-feature cfg detection/adding is not so great at the moment
  • I think the platform specific intrinsics should go in their own extern ABI (i.e. not "rust-intrinsic")

(I'm adjusting the RFC to reflect the latter.)

I think it would be very nice for this to land without requiring the RFC to land first, because of the first point, and because this is the only way for any further work to happen/be experimented with, without requiring people to build/install/multirust a compiler from a custom branch.

r? @alexcrichton

let llet = in_memory_type_of(cx, t.simd_type(cx.tcx()));
let elem_ty = match t.simd_machine_type(cx.tcx()) {
Some(e) => e,
None => cx.sess().fatal("monomorphising SIMD type to an incompatible element")

This comment has been minimized.

@eefriedman

eefriedman Jul 20, 2015

Contributor

This is ugly... is allowing generic SIMD types actually important in practice? It seems like you could accomplish most of what is necessary with traits and maybe a few macros.

This comment has been minimized.

@huonw

huonw Jul 20, 2015

Author Member

I agree it isn't so great, but note that in practice type safety is ensured via traits, e.g. struct Simd4<T: SimdElem>(T, T, T, T);.

This is the major difference to our current #[simd] scheme. Being generic is extremely useful, or else there is some extreme code-duplication and the compiler/library can't "synthesize" random types for helpers easily (i.e. forcing that duplication), e.g. fn get_high<T: SimdElem>(Simd4<T>) -> Simd2<T> works with any T but would require manually writing out for every Tx4 concrete type. (It'd be good to keep this sort of "high level" discussion on rust-lang/rfcs#1199 .)

This comment has been minimized.

@eefriedman

eefriedman Jul 20, 2015

Contributor

Still not sure this is a great... but okay, I'll move the discussion.

@huonw huonw force-pushed the huonw:simd branch 2 times, most recently from 68fb467 to 88cdfbd Jul 20, 2015


fn features_contain(sess: &Session, s: &str) -> bool {
sess.target.target.options.features.contains(s) ||
sess.opts.cg.target_feature.contains(s)

This comment has been minimized.

@alexcrichton

alexcrichton Jul 21, 2015

Member

Isn't querying LLVM the "most robust" thing to do here? I guess all of these are disabled by default, though?

This comment has been minimized.

@huonw

huonw Jul 30, 2015

Author Member

They're all disabled by default, yeah; and querying LLVM doesn't seem overly possible, unfortunately. You have a better idea about LLVM's structure so maybe you can wrangle something, though.

This comment has been minimized.

@alexcrichton

alexcrichton Jul 31, 2015

Member

I believe you can get ahold of a TargetMachineRef, get ahold of the MCSubtargetInfo, get the list of features, and then test for various features being available.

It's probably not super critical that this happens immediately though.

This comment has been minimized.

@alexcrichton

alexcrichton Aug 14, 2015

Member

Could you add a comment to this function with the results of this investigation? Basically something along the lines of "we'd love to do X but we couldn't do it because of Y, hence we're doing the 'poor mans' version Z"

Float(u8),
Pointer(Box<Type>),
Vector(Box<Type>, u8),
}

This comment has been minimized.

@alexcrichton

alexcrichton Jul 21, 2015

Member

If this enum is just translated straight to a Ty below, perhaps this could just be a Ty in-memory and there could be an initialization pass for loading intrinsics into the tcx?

This comment has been minimized.

@huonw

huonw Jul 30, 2015

Author Member

What do you mean by "loading intrinsics into the tcx"?

This comment has been minimized.

@alexcrichton

alexcrichton Jul 31, 2015

Member

Just in the sense of instead of building up the custom Type here for signatures of all the functions and then pushing them into the tcx (with a translation layer), instead just push all the types into the tcx directly.

"vminq_f32" => p!("fmin.v4f32", (f32x4, f32x4) -> f32x4),
"vminq_f64" => p!("fmin.v2f64", (f64x2, f64x2) -> f64x2),
_ => return None,
})

This comment has been minimized.

@alexcrichton

alexcrichton Jul 21, 2015

Member

These blocks seem pretty similar to the pre-existing "intrinsic declaration" location. Perhaps these paths could be unified?

Also, do you know if all of these intrinsics are available on all of llvm 3.5+? I guess in general do you know if LLVM is adding new intrinsics basically every day, or are they kinda frozen now?

This comment has been minimized.

@huonw

huonw Jul 30, 2015

Author Member

My (weak) intention is to somehow have this autogenerated, and there will be a lot (thousands), so having it separated seems better.

This comment has been minimized.

@alexcrichton

alexcrichton Jul 31, 2015

Member

Hm ok, this probably isn't too too bad in that case.

Cmp::Ge => llvm::RealOGE,
};
SExt(bcx, FCmp(bcx, op, llargs[0], llargs[1], call_debug_location), llret_ty)
};

This comment has been minimized.

@alexcrichton

alexcrichton Jul 21, 2015

Member

Could this leverage compare_scalar_types instead?

This comment has been minimized.

@huonw

huonw Jul 30, 2015

Author Member

Theoretically, but compare_simd_types is probably the more appropriate variant.

This comment has been minimized.

@alexcrichton

alexcrichton Jul 31, 2015

Member

Aha! That would also make sense!

name if name.starts_with("x86_") ||
name.starts_with("arm_") ||
name.starts_with("aarch64_") => {
// FIXME: skip checking these for now

This comment has been minimized.

@alexcrichton

alexcrichton Jul 21, 2015

Member

Would this be easier to wire up if the Ty representation was used already for the intrinsic definitions?

This comment has been minimized.

@huonw

huonw Jul 30, 2015

Author Member

Probably

@alexcrichton

This comment has been minimized.

Copy link
Member

alexcrichton commented Jul 21, 2015

Nice work @huonw!

I think the platform specific intrinsics should go in their own extern ABI (i.e. not "rust-intrinsic")

I agree, not having the namespace of "simd_" made me a tad uneasy.

I think it would be very nice for this to land without requiring the RFC to land first, because of the first point, and because this is the only way for any further work to happen/be experimented with, without requiring people to build/install/multirust a compiler from a custom branch.

I would personally be ok with this, but I'm curious to hear what others think as well? Also, do you think the RFC basically has "broad consensus" modulo minor details by this point? If there are still some somewhat contentious decisions here and there it may be worth waiting a little longer before landing this, but if we're all in agreement pretty much then any future minor updates can be easily reflected here (as everything is unstable anyway).

cc @rust-lang/lang

@bors

This comment has been minimized.

Copy link
Contributor

bors commented Jul 22, 2015

☔️ The latest upstream changes (presumably #27176) made this pull request unmergeable. Please resolve the merge conflicts.

@huonw huonw force-pushed the huonw:simd branch from 88cdfbd to 4de6fab Jul 29, 2015

@bors

This comment has been minimized.

Copy link
Contributor

bors commented Jul 31, 2015

☔️ The latest upstream changes (presumably #27382) made this pull request unmergeable. Please resolve the merge conflicts.

@huonw huonw force-pushed the huonw:simd branch 3 times, most recently from fe76451 to 16c5c37 Aug 6, 2015

@huonw

This comment has been minimized.

Copy link
Member Author

huonw commented Aug 6, 2015

Ok, rebased and updated to be better, including

  • intrinsics for casts and arithmetic (i.e. operators don't work automatically for SIMD types: they have to go via the normal traits)
  • a special platform-intrinsic extern ABI for these intrinsics,
  • type-checking the platform-specific intrinsics,
  • some general refactorings

(I'm updating the RFC to ensure it matches the things I've learned while implementing, as we speak.)

cesarb added a commit to cesarb/blake2-rfc that referenced this pull request Aug 7, 2015

@cesarb cesarb referenced this pull request Aug 7, 2015

Merged

SIMD groundwork #1199

@bors

This comment has been minimized.

Copy link
Contributor

bors commented Aug 7, 2015

☔️ The latest upstream changes (presumably #27551) made this pull request unmergeable. Please resolve the merge conflicts.

cesarb added a commit to cesarb/blake2-rfc that referenced this pull request Aug 8, 2015

@@ -897,7 +906,41 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,

}

(_, _) => ccx.sess().span_bug(foreign_item.span, "unknown intrinsic")
(_, _) => {
match Intrinsic::find(tcx, &name) {

This comment has been minimized.

@alexcrichton

alexcrichton Aug 11, 2015

Member

Could this de-indent a level via:

let intr = match ... {
    None => ccx.sess().span_bug(...),
    Some(intr) => intr,
};
@alexcrichton

This comment has been minimized.

Copy link
Member

alexcrichton commented Aug 11, 2015

Looking good to me! Just a minor nit so far

@huonw

This comment has been minimized.

Copy link
Member Author

huonw commented Aug 13, 2015

Updated (will rebase in a bit), includes addressing the nit, adding a pile of platform intrinsic definitions (gets much of x86-64 from SSE to AVX2 and ARM NEON), and adding tests.

@huonw huonw force-pushed the huonw:simd branch from b05b2a4 to d3ba568 Aug 13, 2015

@huonw

This comment has been minimized.

Copy link
Member Author

huonw commented Aug 13, 2015

(There's still some more tests I want to add, particularly run-pass tests making sure the various generic intrinsics behave sanely.)

@@ -223,7 +224,14 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ

ty::TyStruct(..) => {
if t.is_simd(cx.tcx()) {
let llet = type_of(cx, t.simd_type(cx.tcx()));
let e = t.simd_type(cx.tcx());
println!("sizing_type_of: simd: {}", e);

This comment has been minimized.

@cesarb

cesarb Aug 13, 2015

Contributor

This seems to be a stray debugging println!, which is hit while compiling libcore.

@@ -405,7 +417,14 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
}
ty::TyStruct(did, ref substs) => {
if t.is_simd(cx.tcx()) {
let llet = in_memory_type_of(cx, t.simd_type(cx.tcx()));
let e = t.simd_type(cx.tcx());
println!("in_memory_type_of: simd: {}", e);

This comment has been minimized.

@cesarb

cesarb Aug 13, 2015

Contributor

This seems to be a stray debugging println!, which is hit while compiling libcore.

This comment has been minimized.

@huonw

huonw Aug 13, 2015

Author Member

Whoops!

@huonw huonw force-pushed the huonw:simd branch from 3d5cb38 to 4c92357 Aug 17, 2015

huonw added some commits Aug 14, 2015

Shim some of the old std::simd functionality.
Overload the operators using the traits so that things mostly keep
working during the deprecation period.
simd_shuffleNNN returns its type parameter directly.
I.e. the signature now must be

    fn simd_shuffleNNN<T, U>(x: T, y: T, idx: [u32; NNN]) -> U;

(modulo names.)
Revamp SIMD intrinsic trans error handling.
Factor out common pieces, follow `expected ..., found ...` convention
everywhere.

@huonw huonw force-pushed the huonw:simd branch from 4c92357 to 02e9734 Aug 17, 2015

@huonw

This comment has been minimized.

Copy link
Member Author

huonw commented Aug 17, 2015

@bors r=alexcrichton

@bors

This comment has been minimized.

Copy link
Contributor

bors commented Aug 17, 2015

📌 Commit 02e9734 has been approved by alexcrichton

@bors

This comment has been minimized.

Copy link
Contributor

bors commented Aug 17, 2015

⌛️ Testing commit 02e9734 with merge e35fd74...

bors added a commit that referenced this pull request Aug 17, 2015

Auto merge of #27169 - huonw:simd, r=alexcrichton
This implements rust-lang/rfcs#1199 (except for doing all the platform intrinsics).

Things remaining for SIMD (not necessarily in this PR):

- [x] I (@huonw) am signed up to ensure the compiler matches the RFC, when it lands
- [x] the platform specific intrinsics aren't properly type checked at the moment (LLVM will throw a "random" assertion)
- [ ] there's a lot of useful intrinsics that are missing, including whole platforms (mips, powerpc)
- [ ] the target-feature `cfg` detection/adding is not so great at the moment
- [x] I think the platform specific intrinsics should go in their own `extern` ABI (i.e. not `"rust-intrinsic"`)

(I'm adjusting the RFC to reflect the latter.)

I think it would be very nice for this to land without requiring the RFC to land first, because of the first point, and because this is the only way for any further work to happen/be experimented with, without requiring people to build/install/multirust a compiler from a custom branch.

r? @alexcrichton

@bors bors merged commit 02e9734 into rust-lang:master Aug 18, 2015

2 checks passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details
homu Test successful
Details

bors-servo pushed a commit to servo/euclid that referenced this pull request Aug 28, 2015

bors-servo
Auto merge of #101 - bjwbell:simd_to_repr_simd, r=metajack
Change simd to repr simd & bump version number

With [SIMD groundwork part 1](rust-lang/rust#27169)
the simd feature is now repr_simd.

Bump the version number since this relies on the rust PR. 

r? @metajack

<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/euclid/101)
<!-- Reviewable:end -->

bors-servo pushed a commit to servo/euclid that referenced this pull request Aug 29, 2015

bors-servo
Auto merge of #101 - bjwbell:simd_to_repr_simd, r=metajack
Change simd to repr simd & bump version number

With [SIMD groundwork part 1](rust-lang/rust#27169)
the simd feature is now repr_simd.

Bump the version number since this relies on the rust PR. 

r? @metajack

<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/euclid/101)
<!-- Reviewable:end -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.