Skip to content

i128::saturating_add returns -1 instead of i128::MAX at -O2 with the gcc backend #1027

Open

Description

@0xalpharush

Repro

#[inline(never)]
fn f(x: &[u8; 16]) -> i128 { i128::from_ne_bytes(*x).saturating_add(1) }
fn main() { println!("{}", f(&i128::MAX.to_ne_bytes())); }
$ rustc +nightly -Zcodegen-backend=gcc -Copt-level=2 repro.rs && ./repro
-1

Expected 170141183460469231731687303715884105727 (i128::MAX), which is what -Copt-level=0/1, the LLVM backend at every level, and Miri print. -Copt-level=3 also prints -1.

Variants
  • Also wrong: an i128 field of a #[repr(packed)] struct (saturating_add(1) on MAX gives -1, saturating_sub(1) on MIN gives -2); read_unaligned; a field of a #[repr(align(32))] struct.
  • Correct: passing the i128 by value; u128; i64; checked_add / overflowing_add on the same load.
  • Only the saturating case is wrong: 5.saturating_add(1) gives 6.

Versions: rustc 1.102.0-nightly (5b7b37aef 2026-11-08), libgccjit 17.0.0 20261006, x86_64-unknown-linux-gnu. Wrong on every nightly that ships rustc-codegen-gcc (checked 2026-06-05, 2026-09-01, 2026-11-08).

Activity

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

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions