Skip to content

Miscompilation: program prints 3 instead of 2 at opt-level=2 and 3 #163311

Closed

Description

@466774321-code

I tried this code:

static mut OUT: u8 = 1;

unsafe fn f() {
    let (mut w, mut z, mut y, mut n, mut o, mut q, mut c, mut d, mut a) =
        (false, false, true, false, false, false, false, false, false);

    for mut x in 0..2 {
        let mut branch = false;
        loop {
            'step: {
                if x < 1 {
                    y = false;
                    branch = OUT > 0;
                    if branch {
                        break 'step;
                    }
                }
                loop {
                    if !o {
                        o = !y;
                        z = x < 1;
                        if o {
                            x = 3;
                        } else {
                            q = true;
                        }
                    }
                    if !z || q {
                        if !z {
                            OUT = x;
                            n = w;
                            d = n;
                        }
                        if !d {
                            if !z {
                                c = !n;
                            }
                            if z || !c {
                                d = true;
                            }
                            if c || !d {
                                c = false;
                                OUT = x;
                            }
                        }

                        if d {
                            return;
                        }
                    }
                    z = false;
                    w = !o;
                    if o {
                        if x < 1 {
                            a = true;
                        }
                        break;
                    }
                }
            }

            if branch {
                break;
            }
            if a {
                break;
            }
            OUT = 2;
            break;
        }

        if !branch {
            break;
        }
    }
}

fn main() {
    print!("{}", unsafe {
        f();
        OUT
    });
}

Save the code as case.rs, then run:

rustc +nightly --edition=2024 -C opt-level=1 case.rs -o case-o1
./case-o1
# Prints: 2

rustc +nightly --edition=2024 -C opt-level=2 case.rs -o case-o2
./case-o2
# Prints: 3

I expected to see this happen:

The program should print 2 at every optimization level.

On the first outer iteration (x = 0), y becomes false and
branch becomes true, so the inner processing is skipped.

On the second iteration (x = 1), the inner loop changes x to 3
and writes 3 to OUT. However, d remains false, so the function
does not return early. After leaving the inner loop, both branch
and a are false, so OUT = 2 is executed before the function exits.

Instead, this happened:

The program prints 3 at opt-level=2 and opt-level=3.
Compilation and execution succeed; the executable exits with status 0.

Additional checks on the same nightly:

Configuration Output
-C opt-level=0 2
-C opt-level=1 2
-C opt-level=2 3
-C opt-level=3 3
-C opt-level=2 -C no-prepopulate-passes 2
-C opt-level=2 -Zmir-opt-level=0 2

I also ran the program with Miri in an edition-2024 Cargo project:

  • With RUSTFLAGS="-Awarnings -Zmir-opt-level=0" and
    MIRIFLAGS="-Zmiri-strict-provenance", it prints 2 and exits
    successfully without reporting undefined behavior.
  • With RUSTFLAGS="-Awarnings -Zmir-opt-level=2", it also prints 2
    and exits successfully without reporting undefined behavior.

The program is single-threaded. The mutable static is accessed directly,
and its value is copied out for printing.

Meta

Tested in Ubuntu 22.04 under WSL, on x86_64-unknown-linux-gnu.

rustc +nightly --version --verbose:

rustc 1.100.0-nightly (f7575a9da 2026-09-24)
binary: rustc
commit-hash: f7575a9da8e4a4fca3b5668d5a2ea7476db44b3f
commit-date: 2026-09-24
host: x86_64-unknown-linux-gnu
release: 1.100.0-nightly
LLVM version: 23.1.1

Activity

  1. added
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Sep 25, 2026
  2. theemathas commented on Sep 25, 2026

    @theemathas
    Contributor

    Also reproduces on 1.99.0-beta.7 (2026-09-19 aa0593682acc35672839)

    May I know if this code is reduced from real-world code, found by a fuzzer, or something else?

  3. added
    E-needs-bisectionCall for participation: This issue needs bisection: https://github.com/rust-lang/cargo-bisect-rustc
    E-needs-mcveCall for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example
    I-miscompileIssue: Correct Rust code lowers to incorrect machine code
    on Sep 25, 2026
  4. added
    I-prioritizeIssue needs a team member to assess the impact. Will be replaced by P-{low,medium,high,critical}
    on Sep 25, 2026
  5. 466774321-code commented on Sep 25, 2026

    @466774321-code
    Author

    Also reproduces on 1.99.0-beta.7 (2026-09-19 aa0593682acc35672839)

    May I know if this code is reduced from real-world code, found by a fuzzer, or something else?

    from a fuzzer

  6. added
    A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.
    on Sep 25, 2026
  7. nikic commented on Sep 25, 2026

    @nikic
    Contributor

    https://gist.github.com/nikic/17d06ccb9a167ec350870135ebdfde41 (unreduced) produces different exit code from llubi after opt -passes=instcombine.

  8. nikic commented on Sep 25, 2026

    @nikic
    Contributor
  9. added this to the 1.99.0 milestone on Sep 25, 2026
  10. changed the title [-]Miscompilation on nightly: program prints 3 instead of 2 at opt-level=2 and 3[/-] [+]Miscompilation: program prints 3 instead of 2 at opt-level=2 and 3[/+] on Sep 25, 2026
  11. removed
    E-needs-bisectionCall for participation: This issue needs bisection: https://github.com/rust-lang/cargo-bisect-rustc
    on Sep 25, 2026
  12. 3 remaining items

  13. rustbot commented on Sep 26, 2026

    @rustbot
    Collaborator

    Assigning P-medium (discussion on Zulip).

  14. added and removed
    I-prioritizeIssue needs a team member to assess the impact. Will be replaced by P-{low,medium,high,critical}
    on Sep 26, 2026
  15. added
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    on Sep 27, 2026
  16. andjo403 commented on Sep 28, 2026

    @andjo403
    Contributor

    Fix merged upstream see llvm/llvm-project#226783

  17. added
    llvm-fixed-upstreamIssue expected to be fixed by the next major LLVM upgrade, or backported fixes
    on Sep 28, 2026
  18. Hoverbear commented on Oct 1, 2026

    @Hoverbear
    Contributor

    This started in 1b29cfd (unsurprisingly).

    searched nightlies: from nightly-2026-07-05 to nightly-2026-08-15
    regressed nightly: nightly-2026-08-06
    searched commit range: 1ed2df6...7608eb7
    regressed commit: 1b29cfd

    bisected with cargo-bisect-rustc v0.6.11

    Host triple: x86_64-unknown-linux-gnu
    Reproduce with:

    cargo bisect-rustc --start=1.98.0 --end=1.99.0 --prompt -- run --release
  19. added
    regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.
    and removed on Oct 1, 2026
  20. lqd commented on Oct 1, 2026

    @lqd
    Member

    1.99 was released earlier today, this is now on stable. Adjusting labels.

  21. added 2 commits that reference this issue on Oct 14, 2026
  22. linked a pull request that will close this issue[beta] backports #164371on Oct 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.C-bugCategory: This is a bug.I-miscompileIssue: Correct Rust code lowers to incorrect machine codeP-mediumMedium priorityS-has-mcveStatus: A Minimal Complete and Verifiable Example has been found for this issueT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.llvm-fixed-upstreamIssue expected to be fixed by the next major LLVM upgrade, or backported fixesregression-from-stable-to-stablePerformance or correctness regression from one stable version to another.

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions