Miscompilation with `-C opt-level=2 -C codegen-units=1`(but not with opt-level=3) due `loop-vectorize` llvm pass

Open
#165,325 2 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
8/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Active
Tech stack
rust
Domain
compilers

Research direction

The miscompilation shows up only at opt-level=2 with codegen-units=1, and bisection points at the LLVM loop-vectorize pass on the generic reduced::e::<i128> instance. Start by reproducing with the reduced program and the -C llvm-args=-opt-bisect-limit flag, then inspect the LLVM IR before and after vectorization. Done means identifying the root cause, whether in the Rust codegen of the i128 wrapping ops or in LLVM, and adding a regression test.

Written by the indexing model from the issue text.

Description

A-LLVM C-bug I-miscompile S-found-by-fuzzing T-compiler WG-llvm

I tried this code:

use std::hint::black_box;
trait Num: Copy + PartialOrd {
    fn wadd(self, o: Self) -> Self;
    fn wsub(self, o: Self) -> Self;
    fn from_u64(v: u64) -> Self;
    fn hi(self) -> u64;
}
impl Num for i128 {
    fn wadd(self, o: Self) -> Self {
        self.wrapping_add(o)
    }
    fn wsub(self, o: Self) -> Self {
        self.wrapping_sub(o)
    }
    fn from_u64(v: u64) -> Self {
        v as i128
    }
    fn hi(self) -> u64 {
        self as u64
    }
}
fn e<T: Num>(a: T, b: T, n: u32) -> T {
    let mut d = T::from_u64(0);
    for i in 0..n {
        let a = a.wadd(T::from_u64(i as u64));
        d = if T::from_u64(i as u64) >= T::from_u64(if T::from_u64(19937u64) >= a { a } else { T::from_u64(6u64) }.hi()) {
            T::from_u64(if T::from_u64(19937u64) >= a { T::from_u64(19937u64).wsub(a) } else { a }.hi())
        } else {
            T::from_u64(if T::from_u64(19937u64) >= a { T::from_u64(19937u64).wsub(a) } else { a }.hi()).wsub(T::from_u64(1))
        }
    }
    match 0 {
        _ => d,
    }
}
fn main() {
    let c: fn(i128, i128, u32) -> i128 = black_box(e);
    println!("{}", c(Num::from_u64(2961832378146261130u64), 0, 2))
}

Rust compiled with

rustc +nightly reduced.rs; ./reduced
rustc +nightly reduced.rs -C opt-level=3 -C codegen-units=1; ./reduced # Same with opt-level=0/1/s/z

prints

2961832378146261130

but compiled with

rustc +nightly reduced.rs -C opt-level=2 -C codegen-units=1; ./reduced
rustc +nightly reduced.rs -C opt-level=2 -C codegen-units=1 -Zmir-opt-level=0; ./reduced # Same with mir-opt-level=1/2/3

prints

15484911695563310421

Bisecting the optimization passes with -C llvm-args=-opt-bisect-limit: the first LLVM pass that changes the result is pass 744 of 1301, loop-vectorize on reduced::e::<i128>.

Meta

rustc --version --verbose:

rustc 1.99.1 (58cf8f9c3 2026-10-13)
binary: rustc
commit-hash: 58cf8f9c35b355199727627d07ae34a4e2846d67
commit-date: 2026-10-13
host: x86_64-unknown-linux-gnu
release: 1.99.1
LLVM version: 23.1.1
channel reproducible
stable (rustc 1.99.1 (58cf8f9c3 2026-10-13)) yes
beta (rustc 1.100.0-beta.7 (fd8e211ae 2026-10-17)) yes
nightly (rustc 1.101.0-nightly (16d1ffac1 2026-10-26)) yes
stable 1.98.0 (rustc 1.98.0 (88d9e12ae 2026-08-18)) no
stable 1.99.0 (rustc 1.99.0 (b940084d7 2026-09-28)) yes
nightly-2026-08-05 (rustc 1.99.0-nightly (1ed2df61a 2026-08-04)) no
nightly-2026-08-06 (rustc 1.99.0-nightly (7608eb7b0 2026-08-05)) yes

Bisected with cargo bisect-rustc:

Problem was found by and minimized by rust fuzzer(created by llm) - https://github.com/qarmin/rs-compiler-fuzzer (the latest findings of the fuzzer can be checked by hand in https://github.com/qarmin/rs-compiler-fuzzer/releases/download/Nightly/findings.zip)

Dominant language
Rust
Stars
121k
Forks
17.3k
Avg merge
2d 21h
Merged PRs (30d)
531

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from rust-lang/rust

All issues in rust-lang/rust

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.