Skip to content

Extra instructions in as_chunks remainder loop between beta and nightly #147459

@okaneco

Description

@okaneco

While working on #147436, I noticed a regression in codegen between nightly and stable 1.90/beta.

Code

I tried this code that checks two slices for ASCII equality ignoring case, a modification of the current implementation.
#[inline(never)]
pub const fn eq_ignore_ascii_case_chunks(s: &[u8], other: &[u8]) -> bool {
    if s.len() != other.len() {
        return false;
    }

    const N: usize = 16;
    let (a, a_rem) = s.as_chunks::<N>();
    let (b, b_rem) = other.as_chunks::<N>();

    let mut i = 0;
    while i < a.len() && i < b.len() {
        let mut equal_ascii = true;
        let mut j = 0;
        while j < N {
            equal_ascii &= a[i][j].eq_ignore_ascii_case(&b[i][j]);
            j += 1;
        }

        if !equal_ascii {
            return false;
        }

        i += 1;
    }

    let mut a = a_rem;
    let mut b = b_rem;

    while let ([first_a, rest_a @ ..], [first_b, rest_b @ ..]) = (a, b) {
        if first_a.eq_ignore_ascii_case(&first_b) {
            a = rest_a;
            b = rest_b;
        } else {
            return false;
        }
    }

    true
}

https://rust.godbolt.org/z/17zKoqGvc

The remainder loop should look like this

.LBB0_8:
        cmp     rsi, rcx
        sete    al
        je      .LBB0_2
        ;; elided, identical in both outputs
        je      .LBB0_8
.LBB0_2:
        ret
.LBB0_1:
        xor     eax, eax
        ret

Instead, there are extra or, test, and and instructions in nightly.

.LBB0_8:
        cmp     rsi, rcx
        sete    al
        or      al, al
        test    al, 1
        jne     .LBB0_2
        ;; elided, identical in both outputs
        je      .LBB0_8
.LBB0_2:
        and     al, 1
        ret
.LBB0_1:
        xor     eax, eax
        and     al, 1
        ret

The LLVM IR differs in this block, where the regressed form uses a select and the "good" version uses or.

nightly

bb20:
  %b_rem.sroa.5.0 = phi i64 [ %rest_b.1, %bb22 ], [ %1, %bb20.preheader ]
  %b_rem.sroa.0.0 = phi ptr [ %rest_b.0, %bb22 ], [ %3, %bb20.preheader ]
  %a_rem.sroa.5.0 = phi i64 [ %rest_a.1, %bb22 ], [ %1, %bb20.preheader ]
  %a_rem.sroa.0.0 = phi ptr [ %rest_a.0, %bb22 ], [ %0, %bb20.preheader ]
  %_37.not = icmp eq i64 %a_rem.sroa.5.0, 0
  %_35.not = icmp eq i64 %b_rem.sroa.5.0, 0
  %or.cond21 = select i1 %_37.not, i1 true, i1 %_35.not
  br i1 %or.cond21, label %bb27, label %bb22

stable

bb20:
  %b.sroa.6.0 = phi i64 [ %rest_b.1, %bb22 ], [ %1, %bb20.preheader ]
  %b.sroa.0.0 = phi ptr [ %rest_b.0, %bb22 ], [ %3, %bb20.preheader ]
  %a.sroa.6.0 = phi i64 [ %rest_a.1, %bb22 ], [ %1, %bb20.preheader ]
  %a.sroa.0.0 = phi ptr [ %rest_a.0, %bb22 ], [ %0, %bb20.preheader ]
  %_42 = icmp eq i64 %a.sroa.6.0, 0
  %_40 = icmp eq i64 %b.sroa.6.0, 0
  %or.cond.not = or i1 %_40, %_42
  br i1 %or.cond.not, label %bb27, label %bb22

Version it worked on

It most recently worked on:

binary: rustc
commit-hash: aa7859c0dec2de6c9cab34b03028bcef7b1fc25d
commit-date: 2025-09-27
host: x86_64-unknown-linux-gnu
release: 1.91.0-beta.4
LLVM version: 21.1.1
Internal compiler ID: beta

Version with regression

Playground nightly

Build using the Nightly version: 1.92.0-nightly
(2025-10-06 3d8c1c1fc077d04658de)

@rustbot modify labels: +regression-from-stable-to-nightly -regression-untriaged

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-codegenArea: Code generationC-bugCategory: This is a bug.P-mediumMedium priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.regression-from-stable-to-nightlyPerformance or correctness regression from stable to nightly.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions