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

Remove rustc_args_required_const attribute #85110

Merged
merged 5 commits into from
May 13, 2021

Conversation

RalfJung
Copy link
Member

@RalfJung RalfJung commented May 9, 2021

Now that stdarch no longer needs it (thanks @Amanieu!), we can kill the rustc_args_required_const attribute. This means that lifetime extension of references to temporaries is the only remaining job that promotion is performing. :-)

r? @oli-obk
Fixes #69493

@rust-highfive
Copy link
Collaborator

Some changes occured to the CTFE / Miri engine

cc @rust-lang/miri

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label May 9, 2021
@rust-log-analyzer

This comment has been minimized.

@oli-obk
Copy link
Contributor

oli-obk commented May 9, 2021

Looks like we need to do the same transformation that was done to stdarch for SIMD shuffle?

@RalfJung
Copy link
Member Author

RalfJung commented May 9, 2021

I am confused... so aho-corasick is somehow directly calling these intrinsics?

The attribute was removed from the shuffle intrinsics with rust-lang/stdarch#1113, but it looks like they were special-cased in the promotion code so they got the magic treatment even without the attribute.

@oli-obk
Copy link
Contributor

oli-obk commented May 9, 2021

codegen does have a special case for these, yea. So... we need a const item with the indices and use that as the argument? Then bump stdsimd again and then we can do this PR?

@RalfJung
Copy link
Member Author

RalfJung commented May 9, 2021

Not just codegen, but promotion has a special case where it treats them as rustc_args_required_const even when that attribute is not present.

@RalfJung
Copy link
Member Author

RalfJung commented May 9, 2021

But yeah, I think the shuffle functions in stdarch need to become rustc_legacy_const_generics as well.

@RalfJung
Copy link
Member Author

RalfJung commented May 9, 2021

@RalfJung
Copy link
Member Author

RalfJung commented May 9, 2021

Hm okay, this is a bit more tricky than I thought. The shuffle function cannot literally use the "legacy" attribute:

error: #[rustc_legacy_const_generics] functions must only have const generics

And moreover most (all?) calls are inside the same crate so the attribute does not even help...

The alternative is to fix all call sites of simd_shuffle to pass actual constants. I guess ideally the type checker would enforce this as part of a special check for these intrinsics?

@RalfJung
Copy link
Member Author

RalfJung commented May 9, 2021

I started seeing what it takes to fix this, and... it's a lot.^^ Here's my WIP patch. I don't like using inline_const (it is marked as incomplete_feature, we should not use those in the std library IMO); I feel the easiest way forward here might be a macro that generates code like

            const IDX: [u32; 32] = $idx;
            simd_shuffle32($x, $y, IDX)

The shuffle functions are AFAIK internal to stdarch, so we can pretty much do whatever we want here.

@RalfJung
Copy link
Member Author

RalfJung commented May 9, 2021

Yeah the macro approach looks pretty good, I think.

However, we'll need to figure out what to do with code like this that computes the mask based on other const-generic arguments...

@oli-obk
Copy link
Contributor

oli-obk commented May 10, 2021

However, we'll need to figure out what to do with code like this that computes the mask based on other const-generic arguments...

Oof. That is horrible. And the function is stable, too. The only way forward that we currently have is const_evaluatable_checked and that is nowhere near ready.

My proposal would be to compute all four constants as separate constants and do a runtime match on the generic arg and have four monomorphic calls this way.

You can keep the existing code by putting it in a const fn and calling that from each of the four constants

@RalfJung
Copy link
Member Author

RalfJung commented May 10, 2021

My proposal would be to compute all four constants as separate constants and do a runtime match on the generic arg and have four monomorphic calls this way.

Which "four constants"? There are 256 possible values for IMM8, aren't there?
I don't understand your proposal.^^

I think long-term the intrinsic itself should be changed to use const generics; this also ensures that we don't get these ICEs. Short-term we can model this with const generic wrapper like

pub fn simd_shuffle32<T, U, IDX: const [u32; 32]>(x: T, y: T) -> U { 
  extern "platform-intrinsic" {
    fn simd_shuffle32<T, U>(x: T, y: T, idx: [u32; 32]) -> U;
  }
  simd_shuffle32(x, y, IDX)
}

However, this complains that [u32; 32] can't be used as const generic yet (and I assume we'd need another incomplete_feature to get around that).

What I don't know is how to write functions like this that call such a const-generic shuffle-wrapper.

@oli-obk
Copy link
Contributor

oli-obk commented May 10, 2021

Which "four constants"? There are 256 possible values for IMM8, aren't there?
I don't understand your proposal.^^

Yes, but it is bitmasked to 0b11

What I don't know is how to write functions like this that call such a const-generic shuffle-wrapper.

That's what I was describing in my previous post. If you want to skip the runtime part and do it at compile time, you need the const_evaluatable_checked feature.

@RalfJung
Copy link
Member Author

That's what I was describing in my previous post.

Yeah and I did not (and do not) understand the description. ;)

But I think I found another way. :D This macro:

#[allow(unused_macros)]
macro_rules! simd_shuffle8_param {
    ($x:expr, $y:expr, <const $imm:ident : $ty:ty> $idx:expr $(,)?) => {{
        struct ConstParam<const $imm: $ty>;
        impl<const $imm: $ty> ConstParam<$imm> {
            const IDX: [u32; 8] = $idx;
        }

        simd_shuffle8($x, $y, ConstParam::<$imm>::IDX)
    }}
}

Lets me write callers like

pub unsafe fn _mm256_shuffle_epi32<const MASK: i32>(a: __m256i) -> __m256i {
    static_assert_imm8!(MASK);
    let r: i32x8 = simd_shuffle8_param!(
        a.as_i32x8(),
        a.as_i32x8(),
        <const MASK: i32> [
            MASK as u32 & 0b11,
            (MASK as u32 >> 2) & 0b11,
            (MASK as u32 >> 4) & 0b11,
            (MASK as u32 >> 6) & 0b11,
            (MASK as u32 & 0b11) + 4,
            ((MASK as u32 >> 2) & 0b11) + 4,
            ((MASK as u32 >> 4) & 0b11) + 4,
            ((MASK as u32 >> 6) & 0b11) + 4,
        ],
    );
    transmute(r)
}

@RalfJung
Copy link
Member Author

With this patch to stdarch, the bootstrap build completes again (or at least, aho-corasick builds; the full build is still ongoing).

@oli-obk @Amanieu would that be an okay avenue to take here?

@RalfJung
Copy link
Member Author

RalfJung commented May 10, 2021

@oli-obk I'd also like to have a reasonable error instead of the ICE when a shuffle argument is not a constant.

Currently, such an error is emitted here:

let msg = format!("argument {} is required to be a constant", index + 1);

But with promotion not having anything to do here any more, that makes little sense. What would be the right place to do that check? I thought it might be

pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {

but that function only checks the signature used in the extern block; we need something that checks each use site.

@Amanieu
Copy link
Member

Amanieu commented May 11, 2021

The patch to stdarch LGTM, but it looks incomplete (missing the ARM/AArch64 intrinsics for example).

@RalfJung
Copy link
Member Author

Yeah I just wanted to get rustc to build for now. Once I figured out how to best make rustc error when the argument is not a const, I will apply this throughout stdarch.

@oli-obk
Copy link
Contributor

oli-obk commented May 11, 2021

but that function only checks the signature used in the extern block; we need something that checks each use site.

mir validation perhaps? or just codegen, which is already checking that i thought

@RalfJung
Copy link
Member Author

Checking during codegen means we only check this when stdarch is used; I'd rather get the build errors in stdarch itself than waiting until some crate runs into the ICE.^^

MIR validation runs a lot, doesn't it? Seems excessive.
I was thinking of putting it into the lower-intrinsics pass, since at least that is already intrinsics-related...^^

@oli-obk
Copy link
Contributor

oli-obk commented May 11, 2021

Checking during codegen means we only check this when stdarch is used; I'd rather get the build errors in stdarch itself than waiting until some crate runs into the ICE.^^

MIR validation runs a lot, doesn't it? Seems excessive.
I was thinking of putting it into the lower-intrinsics pass, since at least that is already intrinsics-related...^^

Yea, that opt is always run, even without optimizations, so 👍

@RalfJung
Copy link
Member Author

Yea, that opt is always run, even without optimizations, so +1

All right, done.

The stdarch PR is on its way at rust-lang/stdarch#1160, but some arch/neon intrinsics still need to be adjusted (they are auto-generated and the generating tool needs some changes).

@RalfJung RalfJung force-pushed the no-rustc_args_required_const branch from e75a319 to 51f3e0b Compare May 11, 2021 09:57
@rust-log-analyzer

This comment has been minimized.

@bors
Copy link
Contributor

bors commented May 11, 2021

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

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 12, 2021
@RalfJung
Copy link
Member Author

@bors rollup=iffy

@bors
Copy link
Contributor

bors commented May 13, 2021

⌛ Testing commit bc2b62b1012d447e90fd5556cd84694593a987c7 with merge fcb1f66ecdd8af9435334dde4ceef8e1b2efd145...

@rust-log-analyzer

This comment has been minimized.

@bors
Copy link
Contributor

bors commented May 13, 2021

💔 Test failed - checks-actions

@bors bors added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels May 13, 2021
@RalfJung
Copy link
Member Author

Needs rust-lang/stdarch#1162

@RalfJung RalfJung force-pushed the no-rustc_args_required_const branch from bc2b62b to c61e8fa Compare May 13, 2021 13:01
@RalfJung
Copy link
Member Author

@bors r=oli-obk

@bors
Copy link
Contributor

bors commented May 13, 2021

📌 Commit c61e8fa has been approved by oli-obk

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 13, 2021
@bors
Copy link
Contributor

bors commented May 13, 2021

⌛ Testing commit c61e8fa with merge d2df620...

@bors
Copy link
Contributor

bors commented May 13, 2021

☀️ Test successful - checks-actions
Approved by: oli-obk
Pushing d2df620 to master...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Remove special-case for simd_shuffle intrinsics in promotion
7 participants