-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Potentially redundant check for zero alignment in generated assembly #91438
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
Comments
Why alignment can't be zero ? Are you sure it's check for alignment ? As I read the asm using https://icscsi.org/library/Documents/Cheat_Sheets/Programming%20-%20x64%20Instructions.pdf for ref: test if I guess |
Adding fn main() {
println!("{}", std::mem::align_of::<Wrapper<dyn My>>());
} gets me error[E0277]: the size for values of type `dyn My` cannot be known at compilation time
--> <source>:19:20
|
19 | println!("{}", std::mem::align_of::<Wrapper<dyn My>>());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: within `Wrapper<dyn My>`, the trait `Sized` is not implemented for `dyn My`
note: required because it appears within the type `Wrapper<dyn My>`
--> <source>:5:12
|
5 | pub struct Wrapper<T: ?Sized>(i8, T);
| ^^^^^^^
note: required by a bound in `align_of` So, at least as far as the compiler is concerned, there is no obvious reason it could not be a zero-sized type. |
As stated in https://doc.rust-lang.org/reference/type-layout.html,
Yes. The references to |
How does the compilation error above indicate that? Also, ZSTs has alignment 1, as you can check using std::mem::align_of::<()>();
Why it's not a bug? The compiler generates a seemingly unnecessary instruction, which is an optimization issue. I agree that the issue is quite minor, though, and most probably it doesn't cause observable slowdown. Maybe there are some reasons why the alignment in vtable can be zero, but it seems to contradict the documentation. |
I fail to see any explanation in the link that say that, It's probably search the alignement of pub struct My1<T: My + ?Sized> {
field: i8, // <= default 1 alignment
my: Wrapper<T>, // <= could dynamicly change alignment of My1 ?
} Again just random guess. |
It's the alignment of the type corresponding to this vtable, not the alignment of vtable itself.
Yes, it is. The issue is that while calculating the offset dynamically, it does redundantly check whether the alignment is zero. |
why do you suppose rust internal doesn't need this ? having a zero alignment could mean something like unknown alignment ? I mean you first need to prove test for zero is useless before say it's seem useless. We don't know for sure what Rust really need to do here, the type is dyn, maybe Sized. That not trivial, one should perfectly know Rust internal to know if this check is useless. Sorry for my poor knowledge in this if my comment are just losing your time just ignore them, I just try to understand your point. |
I didn't dive into Rust internals code, but I know that the compiler doesn't always check for zero alignment. Here's the example: pub trait My {
fn f(&self) -> i32;
}
pub struct My1<T: My + ?Sized> {
field: i8,
my: T,
}
type DynMy1 = My1<dyn My>;
pub fn run(d: &DynMy1) -> &dyn My {
&d.my
} gives just example::run:
mov rdx, rsi
mov rax, qword ptr [rdx + 16]
add rax, rdi
ret But, even if I add the transparent wrapper, the check for zero is generated. See the following example: pub trait My {
fn f(&self) -> i32;
}
#[repr(transparent)]
pub struct Wrapper<T: ?Sized>(T);
pub struct My1<T: My + ?Sized> {
field: i8,
my: Wrapper<T>,
}
type DynMy1 = My1<dyn My>;
pub fn run(d: &DynMy1) -> &Wrapper<dyn My> {
&d.my
} The generated assembly becomes much more complex: example::run:
mov rdx, rsi
mov rax, qword ptr [rdx + 16]
test rax, rax
mov ecx, 1
cmove rax, rcx
add rax, rdi
ret I don't have an idea on why the check happens. If it's omitted sometimes, then the compiler kind of knows that the alignment in vtables cannot be zero, yet it generates the check in a more complex example. |
I think the diff is caused by |
This check is generated by the following code: rust/compiler/rustc_codegen_ssa/src/glue.rs Lines 78 to 93 in 772d51f
my field, which is max(<align of Wrapper>, <align of DST field from vtable>) .
In the general case, this check is required, because the alignment of In the specific cases you've identified, where the alignment of (opened #91569 for this) |
Consider the following code with custom DSTs:
The generated assembly for x86_64 is as follows (with my comments added):
This can be seen on Godbolt.
Why does the compiler check for zero alignment? It seems that it's impossible, as the alignment cannot be zero.
Meta
rustc --version --verbose
:The text was updated successfully, but these errors were encountered: