Change:
<!-- Thank you for filing a bug report! Please provide a short summary of the bug, along with any information you feel relevant to replicating the bug. --I tried this code: I expected to see this happen: After compiling to assembly with to generate the following x86 assembly code. Instead, this happened: <!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --:
(EDIT: was wrong, see below)  say it it will round towards negative infinity if ; while always rounds towards positive infinity. A simple with proves that they do not return the same value: However if you use (or any unsigned integer) you will get the expected assembly. labels -C-bug -needs-triage +C-discussion
I believe and (not to be confused with ) are in fact equivalent, and Alive2 tells me that this optimization is valid (), albeit I tested it with (testing with gets a timeout). on the other hand compiles down to the following: Note how the generated code adds sign bit, which is correct. is not the same thing as specifically because it rounds towards 0, and not negative infinity.
labels +C-bug +needs-triage -C-discussion I-heavy I-slow A-LLVM A-codegen T-compiler
LLVM issue: Worth noting that the problem only occurs with 2, not other power of two constants.
My bad, I wrongly deduced that you meant not . I even checked under Alive2. :eyes:
Confirmed fixed by , needs codegen test.

Discussion:
<ins> //@ assembly-output: emit-asm //@ compile-flags:-Copt-level=3 //@ only-x86_64 #![crate_type = "lib"] #[no_mangle] type T = u8; type T1 = (T, T, T, T, T, T, T, T); type T2 = [T; 8]; #[no_mangle] // CHECK-LABEL: foo1a // CHECK: cmp // CHECK-NEXT: set // CHECK-NEXT: ret pub fn foo1a(a: T1, b: T1) -> bool { a == b } #[no_mangle] // CHECK-LABEL: foo1b // CHECK: mov // CHECK-NEXT: cmp // CHECK-NEXT: set // CHECK-NEXT: ret pub fn foo1b(a: &T1, b: &T1) -> bool { a == b } </ins>

<ins> //@ compile-flags: -O //@ min-llvm-version: 17 #![crate_type = "lib"] #[no_mangle] // CHECK-LABEL: @foo // CHECK: getelementptr inbounds // CHECK-NEXT: load i64 // CHECK-NEXT: icmp eq i64 // CHECK-NEXT: br i1 #[no_mangle] pub fn foo(input: &mut &[u64]) -> Option<u64> { let (first, rest) = input.split_first()?; *input = rest; Some(*first) } </ins>

<ins> //@ compile-flags: -O // XXX: The x86-64 assembly get optimized correclty. But llvm-ir output is not until llvm 18? //@ min-llvm-version: 18 #![crate_type = "lib"] pub enum K{ A(Box<[i32]>), B(Box<[u8]>), C(Box<[String]>), D(Box<[u16]>), } #[no_mangle] // CHECK-LABEL: @get_len // CHECK: getelementptr inbounds // CHECK-NEXT: load // CHECK-NEXT: ret i64 // CHECK-NOT: switch pub fn get_len(arg: &K)->usize{ match arg { K::A(ref lst)=>lst.len(), K::B(ref lst)=>lst.len(), K::C(ref lst)=>lst.len(), K::D(ref lst)=>lst.len(), } } </ins>

<ins> //@ compile-flags: -O // This regress since Rust version 1.72. //@ min-llvm-version: 18.1.4 #![crate_type = "lib"] use std::convert::TryInto; const N: usize = 24; #[no_mangle] // CHECK-LABEL: @example // CHECK-NOT: unwrap_failed pub fn example(a: Vec<u8>) -> u8 { if a.len() != 32 { return 0; } let a: [u8; 32] = a.try_into().unwrap(); a[15] + a[N] } </ins>

<ins> //@ compile-flags: -O //@ min-llvm-version: 17 #![crate_type = "lib"] // CHECK-LABEL: @write_u8_variant_a // CHECK: getelementptr // CHECK-NEXT: icmp ugt #[no_mangle] pub fn write_u8_variant_a( bytes: &mut [u8], buf: u8, offset: usize, ) -> Option<&mut [u8]> { let buf = buf.to_le_bytes(); bytes .get_mut(offset..).and_then(|bytes| bytes.get_mut(..buf.len())) } </ins>

<ins> // in Rust 1.73, -O and opt-level=3 optimizes differently //@ compile-flags: -C opt-level=3 //@ min-llvm-version: 17 #![crate_type = "lib"] use std::cmp::max; #[no_mangle] // CHECK-LABEL: @foo // CHECK-NOT: slice_start_index_len_fail // CHECK-NOT: unreachable pub fn foo(v: &mut Vec<u8>, size: usize)-> Option<&mut [u8]> { if v.len() > max(1, size) { let start = v.len() - size; Some(&mut v[start..]) } else { None } } </ins>

<ins> //@ compile-flags: -O //@ min-llvm-version: 18 #![crate_type = "lib"] // CHECK-LABEL: @div2 // CHECK: ashr i32 %a, 1 // CHECK-NEXT: ret i32 #[no_mangle] pub fn div2(a: i32) -> i32 { a.div_euclid(2) } </ins>

<ins> //@ compile-flags: -O #![crate_type = "lib"] const N: usize = 3; pub type T = u8; #[no_mangle] // CHECK-LABEL: @split_mutiple // CHECK-NOT: unreachable pub fn split_mutiple(slice: &[T]) -> (&[T], &[T]) { let len = slice.len() / N; slice.split_at(len * N) } </ins>

<ins> //@ compile-flags: -O //@ min-llvm-version: 17 #![crate_type = "lib"] #[no_mangle] // CHECK-LABEL: @foo // CHECK: {{.*}}: // CHECK: ret // CHECK-NOT: unreachable pub fn foo(arr: &mut [u32]) { for i in 0..arr.len() { for j in 0..i { assert!(j < arr.len()); } } } </ins>

<ins> //@ compile-flags: -O //@ min-llvm-version: 18 #![crate_type = "lib"] use std::ptr::NonNull; // CHECK-LABEL: @slice_ptr_len_1 // CHECK: {{.*}}: // CHECK-NEXT: ret i64 %ptr.1 #[no_mangle] pub fn slice_ptr_len_1(ptr: *const [u8]) -> usize { let ptr = ptr.cast_mut(); if let Some(ptr) = NonNull::new(ptr) { ptr.len() } else { // We know ptr is null, so we know ptr.wrapping_byte_add(1) is not null. NonNull::new(ptr.wrapping_byte_add(1)).unwrap().len() } } </ins>