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

asm: Since nightly-2024-08-01 (LLVM 19), in and out is sometime allocated to the same register #129585

Open
taiki-e opened this issue Aug 25, 2024 · 4 comments
Labels
A-inline-assembly Area: Inline assembly (`asm!(…)`) A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. C-bug Category: This is a bug. I-miscompile Issue: Correct Rust code lowers to incorrect machine code I-unsound Issue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness llvm-fixed-upstream Issue expected to be fixed by the next major LLVM upgrade P-high High priority regression-untriaged Untriaged performance or correctness regression. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@taiki-e
Copy link
Member

taiki-e commented Aug 25, 2024

Repro:

# Prerequisite: Environment that can compile or cross-compile aach64-linux-gnu
git clone https://github.com/taiki-e/atomic-maybe-uninit.git
cd atomic-maybe-uninit
git checkout v0.3.2
RUSTFLAGS='-C target-feature=+lse' \
  ./tools/test.sh --tests --target aarch64-unknown-linux-gnu --release --no-run

I expected to see this happen: compile pass

Instead, this happened:

error: unpredictable STXP instruction, status is also a source
   --> src/arch/aarch64.rs:571:37
    |
571 | ...                   concat!("st", $release, "xp {tmp:w}, {val_lo}, {val_hi}, [{dst}]"),
    |                       ^
    |
note: instantiated into assembly here
   --> <inline asm>:3:6
    |
3   | stxp w8, x8, x23, [x9]
    |      ^

error: unpredictable STXP instruction, status is also a source
   --> src/arch/aarch64.rs:571:37
    |
571 | ...                   concat!("st", $release, "xp {tmp:w}, {val_lo}, {val_hi}, [{dst}]"),
    |                       ^
    |
note: instantiated into assembly here
   --> <inline asm>:3:7
    |
3   | stlxp w8, x8, x23, [x9]
    |       ^

This is the inline assembly that received the error, and tmp and val_lo which the compiler assigned the same registers are out and in, respectively.

                                val_lo = in(reg) val.pair.lo,
                                val_hi = in(reg) val.pair.hi,
                                tmp = out(reg) _,

Those two must not be allocated the same register, but for some reason the compiler seems to be treating out as if it were lateout.

lateout(<reg>) <expr>
Identical to out except that the register allocator can reuse a register allocated to an in.

I have confirmed that at least the following three targets are affected:

  • aarch64-unknown-linux-gnu (ci log)
  • aarch64_be-unknown-linux-gnu (ci log)
  • riscv64gc-unknown-linux-gnu (ci log)

As for riscv64gc-unknown-linux-gnu, I consistently get the unexpected result at runtime (not compile error) in exactly the same version range.

In the aarch64 case, the problem appeared in a form that the assembler could detect as an error, resulting in a compilation error, but in some situations, as in the riscv64 case, the code may be silently miscompiled.

Meta

rustc --version --verbose:

rustc 1.82.0-nightly (f167efad2 2024-08-24)
binary: rustc
commit-hash: f167efad2f51088d86180ee89177b3d7c9e7c2f5
commit-date: 2024-08-24
host: aarch64-unknown-linux-gnu
release: 1.82.0-nightly
LLVM version: 19.1.0

It can be reproduced with nightly-2024-08-01 or later.

rustc 1.82.0-nightly (28a58f2fa 2024-07-31)
binary: rustc
commit-hash: 28a58f2fa7f0c46b8fab8237c02471a915924fe5
commit-date: 2024-07-31
host: aarch64-unknown-linux-gnu
release: 1.82.0-nightly
LLVM version: 19.1.0

The last version not affected by the problem is nightly-2024-07-31, which uses LLVM 18, so it seems likely that the update to LLVM 19 (#127513) caused this regression.
cc @nikic

rustc 1.82.0-nightly (f8060d282 2024-07-30)
binary: rustc
commit-hash: f8060d282d42770fadd73905e3eefb85660d3278
commit-date: 2024-07-30
host: aarch64-unknown-linux-gnu
release: 1.82.0-nightly
LLVM version: 18.1.7

@rustbot label +I-unsound, +A-LLVM, +A-inline-assembly

@taiki-e taiki-e added C-bug Category: This is a bug. regression-untriaged Untriaged performance or correctness regression. labels Aug 25, 2024
@rustbot rustbot added I-prioritize Issue: Indicates that prioritization has been requested for this issue. needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. A-inline-assembly Area: Inline assembly (`asm!(…)`) A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. I-unsound Issue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness labels Aug 25, 2024
taiki-e added a commit to taiki-e/atomic-maybe-uninit that referenced this issue Aug 25, 2024
taiki-e added a commit to taiki-e/atomic-maybe-uninit that referenced this issue Aug 25, 2024
taiki-e added a commit to taiki-e/atomic-maybe-uninit that referenced this issue Aug 25, 2024
@jieyouxu jieyouxu added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Aug 26, 2024
@apiraino
Copy link
Contributor

WG-prioritization assigning priority (Zulip discussion).

@rustbot label -I-prioritize +P-high

@rustbot rustbot added P-high High priority and removed I-prioritize Issue: Indicates that prioritization has been requested for this issue. labels Aug 27, 2024
@nikic nikic added E-needs-mcve Call for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example and removed E-needs-mcve Call for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example labels Aug 28, 2024
@nikic
Copy link
Contributor

nikic commented Aug 28, 2024

Upstream issue: llvm/llvm-project#106380

@nikic
Copy link
Contributor

nikic commented Aug 28, 2024

Worth noting that the LLVM IR reduction also fails in the same way in previous LLVM versions, so this is not an LLVM 19 regression in register allocations -- likely things just get perturbed enough that we now hit a pre-existing issue.

@saethlin saethlin removed the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Aug 31, 2024
@nikic nikic added the llvm-fixed-upstream Issue expected to be fixed by the next major LLVM upgrade label Sep 19, 2024
@nikic
Copy link
Contributor

nikic commented Sep 19, 2024

This is fixed upstream now, but the required changes were fairly extensive, so this won't get backported to LLVM 19. I'd suggest working around this by laundering the possibly-uninitialized inputs through a black_box. That should prevent LLVM from incorrectly allocating the registers.

@workingjubilee workingjubilee added the I-miscompile Issue: Correct Rust code lowers to incorrect machine code label Oct 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-inline-assembly Area: Inline assembly (`asm!(…)`) A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. C-bug Category: This is a bug. I-miscompile Issue: Correct Rust code lowers to incorrect machine code I-unsound Issue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness llvm-fixed-upstream Issue expected to be fixed by the next major LLVM upgrade P-high High priority regression-untriaged Untriaged performance or correctness regression. 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

7 participants