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

rustc: Use LLVM's new saturating float-to-int intrinsics #84339

Merged
merged 3 commits into from
Apr 23, 2021

Conversation

alexcrichton
Copy link
Member

@alexcrichton alexcrichton commented Apr 19, 2021

This commit updates rustc, with an applicable LLVM version, to use
LLVM's new llvm.fpto{u,s}i.sat.*.* intrinsics to implement saturating
floating-point-to-int conversions. This results in a little bit tighter
codegen for x86/x86_64, but the main purpose of this is to prepare for
upcoming changes to the WebAssembly backend in LLVM where wasm's
saturating float-to-int instructions will now be implemented with these
intrinsics.

This change allows simplifying a good deal of surrounding code, namely
removing a lot of wasm-specific behavior. WebAssembly no longer has any
special-casing of saturating arithmetic instructions and the need for
fptoint_may_trap is gone and all handling code for that is now
removed. This means that the only wasm-specific logic is in the
fpto{s,u}i instructions which only get used for "out of bounds is
undefined behavior". This does mean that for the WebAssembly target
specifically the Rust compiler will no longer be 100% compatible with
pre-LLVM 12 versions, but it seems like that's unlikely to be relied on
by too many folks.

Note that this change does immediately regress the codegen of saturating
float-to-int casts on WebAssembly due to the specialization of the LLVM
intrinsic not being present in our LLVM fork just yet. I'll be following
up with an LLVM update to pull in those patches, but affects a few other
SIMD things in flight for WebAssembly so I wanted to separate this change.

Eventually the entire cast_float_to_int function can be removed when
LLVM 12 is the minimum version, but that will require sinking the
complexity of it into other backends such as Cranelfit.

@rust-highfive
Copy link
Collaborator

r? @matthewjasper

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Apr 19, 2021
@alexcrichton
Copy link
Member Author

For comparison, this is the difference on x86_64 of the codegen differences.

@alexcrichton
Copy link
Member Author

Also, on second though, I went ahead and removed as many WebAssembly-specific bits here as I could, so I think that this represents the final state of what this will look like in the long run (until pre-LLVM-12 is dropped). The consequences of this though is that WebAssembly targets on pre-LLVM-12 won't work (because the intrinsic won't be defined) and the WebAssembly target with +nontrapping-fptoint will not have as great codegen as before until llvm/llvm-project@5c72975 is cherry-picked to our LLVM fork. I plan to do this soon once some other SIMD related things have landed.

@nagisa
Copy link
Member

nagisa commented Apr 20, 2021

r? @nagisa

I don't believe @matthewjasper been active lately.

Copy link
Member

@nagisa nagisa left a comment

Choose a reason for hiding this comment

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

This broadly speaking seems good to me, but see remarks inline on some sticking points.

r=me once those are resolved.

compiler/rustc_codegen_llvm/src/builder.rs Show resolved Hide resolved
compiler/rustc_codegen_ssa/src/mir/rvalue.rs Show resolved Hide resolved
// Note that we skip the wasm intrinsics for vector types where `fptoui`
// must be used instead.
if self.wasm_and_missing_nontrapping_fptoint() {
// This intrinsic is only used with non-saturating casts that have UB on
Copy link
Member

Choose a reason for hiding this comment

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

Nit: this is not really an intrinsic, but rather a builder method/instruction builder/etc?

From this comment it is no longer clear why it is important that we specifically go through an effort on wasm to pick a behaviour for what's otherwise an undefined behaviour. It would be good to keep the remark about the intrinsics producing better machine code.

(as a side note: From spelunking it seems that simd_cast also uses this (cc @workingjubilee @calebzulawski) which is potentially undesired (similar to the issue fixed in #84274). This implementation would also crash in a simd setting on wasm, but that's a future improvement)

Copy link
Member

Choose a reason for hiding this comment

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

It does seem a little odd to trap on UB, my understanding is that this function is really only for {f32,f64}::to_int_unchecked which assumes the caller already checked the bounds.

This doesn't crash on wasm simd (we test the simd version of to_int_unchecked on wasm)--it looks like it falls back to the generic llvm instruction which supports vectors

Copy link
Member Author

Choose a reason for hiding this comment

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

I've changed "intrinsic" to "method", and I've elaborated on the comment to hopefully help explain why wasm is different here.

This should work for SIMD types since it specifically avoids (a few lines below) any input types that are vectors.

@bjorn3
Copy link
Member

bjorn3 commented Apr 21, 2021

Eventually the entire cast_float_to_int function can be removed when
LLVM 12 is the minimum version, but that will require sinking the
complexity of it into other backends such as Cranelfit.

Cranelift specifically only has a saturating and trapping version of the float-to-int conversion instruction. There is none that has UB or returns a bogus result.

This commit updates rustc, with an applicable LLVM version, to use
LLVM's new `llvm.fpto{u,s}i.sat.*.*` intrinsics to implement saturating
floating-point-to-int conversions. This results in a little bit tighter
codegen for x86/x86_64, but the main purpose of this is to prepare for
upcoming changes to the WebAssembly backend in LLVM where wasm's
saturating float-to-int instructions will now be implemented with these
intrinsics.

This change allows simplifying a good deal of surrounding code, namely
removing a lot of wasm-specific behavior. WebAssembly no longer has any
special-casing of saturating arithmetic instructions and the need for
`fptoint_may_trap` is gone and all handling code for that is now
removed. This means that the only wasm-specific logic is in the
`fpto{s,u}i` instructions which only get used for "out of bounds is
undefined behavior". This does mean that for the WebAssembly target
specifically the Rust compiler will no longer be 100% compatible with
pre-LLVM 12 versions, but it seems like that's unlikely to be relied on
by too many folks.

Note that this change does immediately regress the codegen of saturating
float-to-int casts on WebAssembly due to the specialization of the LLVM
intrinsic not being present in our LLVM fork just yet. I'll be following
up with an LLVM update to pull in those patches, but affects a few other
SIMD things in flight for WebAssembly so I wanted to separate this change.

Eventually the entire `cast_float_to_int` function can be removed when
LLVM 12 is the minimum version, but that will require sinking the
complexity of it into other backends such as Cranelfit.
@alexcrichton
Copy link
Member Author

Great! Then when LLVM 12 is the minimum supported version we can delete even more code and just assume the builder methods do the right thing.

@alexcrichton
Copy link
Member Author

@bors: r=nagisa

@bors
Copy link
Contributor

bors commented Apr 21, 2021

📌 Commit de2a460 has been approved by nagisa

@bors
Copy link
Contributor

bors commented Apr 21, 2021

🌲 The tree is currently closed for pull requests below priority 1000. This pull request will be tested once the tree is reopened.

@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 Apr 21, 2021
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this pull request Apr 22, 2021
…gisa

rustc: Use LLVM's new saturating float-to-int intrinsics

This commit updates rustc, with an applicable LLVM version, to use
LLVM's new `llvm.fpto{u,s}i.sat.*.*` intrinsics to implement saturating
floating-point-to-int conversions. This results in a little bit tighter
codegen for x86/x86_64, but the main purpose of this is to prepare for
upcoming changes to the WebAssembly backend in LLVM where wasm's
saturating float-to-int instructions will now be implemented with these
intrinsics.

This change allows simplifying a good deal of surrounding code, namely
removing a lot of wasm-specific behavior. WebAssembly no longer has any
special-casing of saturating arithmetic instructions and the need for
`fptoint_may_trap` is gone and all handling code for that is now
removed. This means that the only wasm-specific logic is in the
`fpto{s,u}i` instructions which only get used for "out of bounds is
undefined behavior". This does mean that for the WebAssembly target
specifically the Rust compiler will no longer be 100% compatible with
pre-LLVM 12 versions, but it seems like that's unlikely to be relied on
by too many folks.

Note that this change does immediately regress the codegen of saturating
float-to-int casts on WebAssembly due to the specialization of the LLVM
intrinsic not being present in our LLVM fork just yet. I'll be following
up with an LLVM update to pull in those patches, but affects a few other
SIMD things in flight for WebAssembly so I wanted to separate this change.

Eventually the entire `cast_float_to_int` function can be removed when
LLVM 12 is the minimum version, but that will require sinking the
complexity of it into other backends such as Cranelfit.
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this pull request Apr 22, 2021
…gisa

rustc: Use LLVM's new saturating float-to-int intrinsics

This commit updates rustc, with an applicable LLVM version, to use
LLVM's new `llvm.fpto{u,s}i.sat.*.*` intrinsics to implement saturating
floating-point-to-int conversions. This results in a little bit tighter
codegen for x86/x86_64, but the main purpose of this is to prepare for
upcoming changes to the WebAssembly backend in LLVM where wasm's
saturating float-to-int instructions will now be implemented with these
intrinsics.

This change allows simplifying a good deal of surrounding code, namely
removing a lot of wasm-specific behavior. WebAssembly no longer has any
special-casing of saturating arithmetic instructions and the need for
`fptoint_may_trap` is gone and all handling code for that is now
removed. This means that the only wasm-specific logic is in the
`fpto{s,u}i` instructions which only get used for "out of bounds is
undefined behavior". This does mean that for the WebAssembly target
specifically the Rust compiler will no longer be 100% compatible with
pre-LLVM 12 versions, but it seems like that's unlikely to be relied on
by too many folks.

Note that this change does immediately regress the codegen of saturating
float-to-int casts on WebAssembly due to the specialization of the LLVM
intrinsic not being present in our LLVM fork just yet. I'll be following
up with an LLVM update to pull in those patches, but affects a few other
SIMD things in flight for WebAssembly so I wanted to separate this change.

Eventually the entire `cast_float_to_int` function can be removed when
LLVM 12 is the minimum version, but that will require sinking the
complexity of it into other backends such as Cranelfit.
@ehuss
Copy link
Contributor

ehuss commented Apr 22, 2021

@bors r-

This failed on the dist-riscv64-linux job with a seg fault building gimli: #84432 (comment) Confirmed by running that job locally.

@bors bors added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Apr 22, 2021
@nagisa
Copy link
Member

nagisa commented Apr 23, 2021

@bors r+

@bors
Copy link
Contributor

bors commented Apr 23, 2021

📌 Commit 35ae752 has been approved by nagisa

@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-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Apr 23, 2021
@bors
Copy link
Contributor

bors commented Apr 23, 2021

⌛ Testing commit 35ae752 with merge 1e747ccec99be0974f47d70abed4d94eafa1d4d9...

@rust-log-analyzer

This comment has been minimized.

@bors
Copy link
Contributor

bors commented Apr 23, 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 Apr 23, 2021
@alexcrichton
Copy link
Member Author

I updated the assertions in wasm_casts_trapping.rs and renamed the file to wasm_float_to_int_casts.rs. I then deleted wasm_casts_nontrapping.rs since rustc no longer has any special handling of that feature and the test would just be the same.

@bors: r=nagisa

@bors
Copy link
Contributor

bors commented Apr 23, 2021

📌 Commit ed6dd40 has been approved by nagisa

@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 Apr 23, 2021
@bors
Copy link
Contributor

bors commented Apr 23, 2021

⌛ Testing commit ed6dd40 with merge 481ba16...

@bors
Copy link
Contributor

bors commented Apr 23, 2021

☀️ Test successful - checks-actions
Approved by: nagisa
Pushing 481ba16 to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Apr 23, 2021
@bors bors merged commit 481ba16 into rust-lang:master Apr 23, 2021
@rustbot rustbot added this to the 1.53.0 milestone Apr 23, 2021
@alexcrichton alexcrichton deleted the llvm-fptoint-sat branch April 23, 2021 21:08
alexcrichton added a commit to alexcrichton/rust that referenced this pull request Apr 28, 2021
This fixes the temporary regression introduced in rust-lang#84339 where the wasm
target uses `fpto{s,u}i` intrinsics but the codegen for those intrinsics
with the `+nontrapping-fptoint` LLVM feature wasn't very good (aka it
didn't use the wasm instruction). The fixes brought in here fix that and
also implement the second-to-last simd instruction in LLVM.
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this pull request Apr 29, 2021
Update LLVM for more wasm simd updates

This fixes the temporary regression introduced in rust-lang#84339 where the wasm
target uses `fpto{s,u}i` intrinsics but the codegen for those intrinsics
with the `+nontrapping-fptoint` LLVM feature wasn't very good (aka it
didn't use the wasm instruction). The fixes brought in here fix that and
also implement the second-to-last simd instruction in LLVM.
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this pull request Apr 29, 2021
Update LLVM for more wasm simd updates

This fixes the temporary regression introduced in rust-lang#84339 where the wasm
target uses `fpto{s,u}i` intrinsics but the codegen for those intrinsics
with the `+nontrapping-fptoint` LLVM feature wasn't very good (aka it
didn't use the wasm instruction). The fixes brought in here fix that and
also implement the second-to-last simd instruction in LLVM.
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this pull request Apr 29, 2021
Update LLVM for more wasm simd updates

This fixes the temporary regression introduced in rust-lang#84339 where the wasm
target uses `fpto{s,u}i` intrinsics but the codegen for those intrinsics
with the `+nontrapping-fptoint` LLVM feature wasn't very good (aka it
didn't use the wasm instruction). The fixes brought in here fix that and
also implement the second-to-last simd instruction in LLVM.
alexcrichton added a commit to alexcrichton/rust that referenced this pull request Apr 30, 2021
This fixes the temporary regression introduced in rust-lang#84339 where the wasm
target uses `fpto{s,u}i` intrinsics but the codegen for those intrinsics
with the `+nontrapping-fptoint` LLVM feature wasn't very good (aka it
didn't use the wasm instruction). The fixes brought in here fix that and
also implement the second-to-last simd instruction in LLVM.
bors added a commit to rust-lang-ci/rust that referenced this pull request Apr 30, 2021
Update LLVM for more wasm simd updates

This fixes the temporary regression introduced in rust-lang#84339 where the wasm
target uses `fpto{s,u}i` intrinsics but the codegen for those intrinsics
with the `+nontrapping-fptoint` LLVM feature wasn't very good (aka it
didn't use the wasm instruction). The fixes brought in here fix that and
also implement the second-to-last simd instruction in LLVM.
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.

10 participants