-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Add noundef
metadata for fits-in-target-pointer-size array immediate arguments
#123425
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
Conversation
@bors try @rust-timer queue |
This comment has been minimized.
This comment has been minimized.
…<try> Add `noundef` metadata for fits-in-target-pointer-size array immediate arguments `noundef` is only added if the small array immediate fits in the target pointer size and if optimizations are enabled. Closes rust-lang#123183.
☀️ Try build successful - checks-actions |
This comment has been minimized.
This comment has been minimized.
Finished benchmarking commit (6be5114): comparison URL. Overall result: no relevant changes - no action neededBenchmarking this pull request likely means that it is perf-sensitive, so we're automatically marking it as not fit for rolling up. While you can manually mark this PR as fit for rollup, we strongly recommend not doing so since this PR may lead to changes in compiler perf. @bors rollup=never Instruction countThis benchmark run did not return any relevant results for this metric. Max RSS (memory usage)ResultsThis is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
CyclesResultsThis is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
Binary sizeThis benchmark run did not return any relevant results for this metric. Bootstrap: 666.914s -> 667.807s (0.13%) |
Is it working on the following code? #[repr(transparent)]
pub struct Foo([u8; 4]);
#[repr(transparent)]
pub struct Baz(Foo);
#[no_mangle]
pub fn replace_repr_transparent_struct_short_array_2(r: &mut Baz, v: Baz) -> Baz {
std::mem::replace(r, v)
} |
define i32 @replace_repr_transparent_struct_short_array_2(ptr noalias nocapture noundef align 1 dereferenceable(4) %r, i32 %0) unnamed_addr #0 {
start:
%result.sroa.0.0.copyload = load i32, ptr %r, align 1
store i32 %0, ptr %r, align 1
ret i32 %result.sroa.0.0.copyload
} |
aaaaa right, recursive |
31abdb2
to
e1aa348
Compare
@rustbot author |
e1aa348
to
7a67c9d
Compare
I made the is_transparent_array check recursive now, so it should see through nested @rustbot ready |
7a67c9d
to
6bf21cf
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. But I believe this still requires someone with r+ privileges to take a look.
r? compiler
@bors r=davidtwco,DianQK |
…davidtwco,DianQK Add `noundef` metadata for fits-in-target-pointer-size array immediate arguments `noundef` is only added if the small array immediate fits in the target pointer size and if optimizations are enabled. Closes rust-lang#123183.
// `#[repr(transparent)] enum` containing array. Note that `#[repr(transparent)]` | ||
// can contain other `#[repr(transparent)]` structs or enums, which can eventually | ||
// contain an array! | ||
if arg.layout.ty.is_array() || is_transparent_array(cx, arg.layout) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand why arrays would be special here. What if this is an array of unions, or something like that?
let mut adt_layout = outermost_layout; | ||
// Recursively walk a layout, seeing through all `#[repr(transparent)]` layers. | ||
while adt_layout.is_transparent::<LayoutCx<'tcx, TyCtxt<'tcx>>>() | ||
&& let Some((_, layout)) = adt_layout.non_1zst_field(cx) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that unions can be transparent, so wouldn't this do the wrong thing then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At least for structs, there's not really any need to check for is_transparent
. This is an optimization so we can just make use of the fact that a struct is a wrapper (i.e., non_1zst_field
returns Some
) even without a repr.
@bors r- |
|
||
// # Negative examples | ||
|
||
// This inner struct is *not* `#[repr(transparent)]`, so we must not emit `noundef` for the outer |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why "must not"? With the layout we pick this would still be correct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This testcase is missing negative tests with transparent unions, and arrays of unions, to ensure they do not get the attribute.
How do I get bors to process the next PR? |
@@ -784,6 +784,21 @@ fn fn_abi_adjust_for_abi<'tcx>( | |||
// an LLVM aggregate type for this leads to bad optimizations, | |||
// so we pick an appropriately sized integer type instead. | |||
arg.cast_to(Reg { kind: RegKind::Integer, size }); | |||
|
|||
// Let's see if we can add a `noundef`. This is only legal for arrays, definitely |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the elephant in the room here is padding, isn't it? Arrays are fine as they do not have any padding. But the word "padding" does not appear anywhere in the PR diff or description, so I am confused.
☀️ Try build successful - checks-actions |
I agree that there's nothing particularly special about arrays here -- it might be possible for other aggregates too. I just opened the issue saying arrays because that's the place I noticed it and I was confident about. (Since But for example we don't put |
Thanks for the catch, I'll revisit this PR in a few days when less busy |
(Still busy, will have more time towards the end of this month) |
Unfortunately I don't have the bandwidth to work on this, but other people are welcomed to pick this up. |
…<try> Annotate eligible small immediate arguments with `noundef` Retake of rust-lang#123425. We try to annotate small (fits within target pointer width) aggregate arguments passed as immediates (specifically casted as "appropriately sized integer type") with `noundef`. Example: ```rs #[no_mangle] pub fn short_array_u64x1(v: [u64; 1]) -> [u64; 1] { v } ``` currently produces ```llvm define i64 `@short_array_u64x1(i64` %0) ... ``` This PR changes that to ```llvm define noundef i64 `@short_array_u64x1(i64` noundef %0) ... ``` The `noundef` attribute is added only if the immediate value has no padding. Specifically, the conservative heuristic we use is to: - Peel away layers of `#[repr(Rust)]` or `#[repr(transparent)]` wrappers if present - Check for innermost simple arrays (whose element type is a primitive type) that can fit within target pointer width Union immediates or otherwise anything that contains unions will not have `noundef` attribute applied. Closes rust-lang#123183. cc `@/RalfJung` who pointed out various problems with the previous take, hopefully I addressed most of them in this take. r? `@ghost` (perf)
noundef
is only added if the small array immediate fits in the target pointer size and if optimizations are enabled.Closes #123183.