Change:
If a signed integer is divided by a power of two using Euclidean division, it is equivalent to an arithmetic shift, but this is not caught. For example produces the assembly code while it could simply be The LLVM IR is which I interpret to be something like (I did check that this function produces the same LLVM IR.) I don't know LLVM enough to know whether there is some kind of flooring division intrinsic that could be used to optimize this, or whether this a missed optimization in the LLVM side and LLVM can recognize that pattern into an arithmetic shift.
I market this as A-LLVM as it could also be an opttimisation in LLVM, but I suspect that we may just need to write the function in a way that would make this more obvious to LLVM.
rustc 1.70 has already fixed this issue: label E-needs-test -llvm-fixed-upstream

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>