Add noundef metadata for fits-in-target-pointer-size array immediate arguments#123425
Add noundef metadata for fits-in-target-pointer-size array immediate arguments#123425jieyouxu wants to merge 6 commits intorust-lang:masterfrom
noundef metadata for fits-in-target-pointer-size array immediate arguments#123425Conversation
|
@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
dianqk
left a comment
There was a problem hiding this comment.
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.
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.
Note that unions can be transparent, so wouldn't this do the wrong thing then?
There was a problem hiding this comment.
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.
Why "must not"? With the layout we pick this would still be correct.
There was a problem hiding this comment.
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? |
| // 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.
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)
noundefis only added if the small array immediate fits in the target pointer size and if optimizations are enabled.Closes #123183.