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

llvm noalias data gets lost when passing large structs #131905

Open
sarah-quinones opened this issue Oct 18, 2024 · 2 comments
Open

llvm noalias data gets lost when passing large structs #131905

sarah-quinones opened this issue Oct 18, 2024 · 2 comments
Labels
A-ABI Area: Concerning the application binary interface (ABI) C-bug Category: This is a bug. needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@sarah-quinones
Copy link

https://godbolt.org/z/b8as1TxdP

#[repr(C)]
pub struct Big<'a>(&'a mut u64, &'a mut u64, usize);

#[inline(never)]
pub unsafe fn bad(a: Big) -> u64 {
    *a.0 = 0;
    *a.1 = 1;
    *a.0
}

#[repr(C)]
pub struct Good<'a>(&'a mut u64, &'a mut u64);

#[inline(never)]
pub unsafe fn good(a: Good) -> u64 {
    *a.0 = 0;
    *a.1 = 1;
    *a.0
}
example::bad::h15eeefb1851d2a2e:
        mov     rax, qword ptr [rdi]
        mov     qword ptr [rax], 0
        mov     rcx, qword ptr [rdi + 8]
        mov     qword ptr [rcx], 1
        mov     rax, qword ptr [rax]
        ret

example::good::h034657cbabb42f00:
        mov     qword ptr [rdi], 0
        mov     qword ptr [rsi], 1
        xor     eax, eax
        ret

i expected the functions to emit similar codegen, but the bad one doesn't get the noalias on the references themselves because llvm thinks they're passed by pointer since the struct is large.

maybe alias.scope can help with this?

Meta

rustc --version --verbose:

rustc 1.84.0-nightly (3ed6e3cc6 2024-10-17)
binary: rustc
commit-hash: 3ed6e3cc69857129c1d314daec00119ff47986ed
commit-date: 2024-10-17
host: x86_64-unknown-linux-gnu
release: 1.84.0-nightly
LLVM version: 19.1.1
Compiler returned: 0
@sarah-quinones sarah-quinones added the C-bug Category: This is a bug. label Oct 18, 2024
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Oct 18, 2024
@saethlin
Copy link
Member

saethlin commented Oct 19, 2024

because llvm thinks they're passed by pointer since the struct is large.

LLVM doesn't just think this, it knows that the struct has been passed by pointer. The rustc ABI (at least for cg_ssa) has Scalar, ScalarPair, and Aggregate ABIs (this link will probably rot but here's the ABI enum currently: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_abi/enum.Abi.html). Your type Good is a ScalarPair and your Big is an Aggregate, and that ABI is always by-pointer.

So there might be another solution here: Figure out how to splat types with more than 2 fields.

@saethlin saethlin added A-ABI Area: Concerning the application binary interface (ABI) T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Oct 19, 2024
@sarah-quinones
Copy link
Author

sarah-quinones commented Oct 19, 2024

is there room for an opt-in attribute that tells rustc that i want to pass a struct as scalars (in the rust abi)?
for example

#[repr(scalar)]
struct Matrix {
  ptr: *mut f64,
  nrows: usize,
  ncols: usize,
  row_stride: isize,
  col_stride: isize,
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-ABI Area: Concerning the application binary interface (ABI) C-bug Category: This is a bug. needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

3 participants