rust-lang / rust-lang/rust

borrowing_sub chain is not recognized if sub result is unused

Open
#143,517 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-LLVM C-optimization P-medium regression-from-stable-to-stable T-compiler
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

Code

I tried this code (godbolt):

#[no_mangle]
pub fn lt_thru_sub(a: &[u64; 4], b: &[u64; 4]) -> bool {
    let mut borrow = false;
    for i in 0..a.len() {
        (_, borrow) = borrowing_sub(a[i], b[i], borrow);
    }
    borrow
}

#[inline]
fn borrowing_sub(lhs: u64, rhs: u64, borrow: bool) -> (u64, bool) {
    let (result, borrow_1) = lhs.overflowing_sub(rhs);
    let (result, borrow_2) = result.overflowing_sub(borrow as u64);
    (result, borrow_1 | borrow_2)
}

I expected to see this happen: compiles down to a few sub and sbb instructions (bigint subtraction)

Instead, this happened: compiles to a bunch of cmp, set*, or, and

If the first result of borrowing_sub is observed, like accumulating it or storing it to an out pointer, then it will codegen the sbb chain. As an example, you can uncomment the black_box line in the godbolt link above

Note that using core::arch::x86_64::_subborrow_u64 produces the correct result: https://godbolt.org/z/WrYThbfMn

Version it worked on

It most recently worked on: 1.66

rustc 1.66.0 (69f9c33d7 2022-12-12)
binary: rustc
commit-hash: 69f9c33d71c871fc16ac445211281c6e7a340943
commit-date: 2022-12-12
host: x86_64-unknown-linux-gnu
release: 1.66.0
LLVM version: 15.0.2
Version with regression

rustc --version --verbose:

rustc 1.67.0 (fc594f156 2023-01-24)
binary: rustc
commit-hash: fc594f15669680fa70d255faec3ca3fb507c3405
commit-date: 2023-01-24
host: x86_64-unknown-linux-gnu
release: 1.67.0
LLVM version: 15.0.6
rustc 1.90.0-nightly (da58c0513 2025-07-03)
binary: rustc
commit-hash: da58c051315268a197ce280f6ba07bbd03c66535
commit-date: 2025-07-03
host: x86_64-unknown-linux-gnu
release: 1.90.0-nightly
LLVM version: 20.1.7

Regressed in #103299 and/or #103479, cc @nikic

searched toolchains nightly-2022-10-29 through nightly-2022-12-09


********************************************************************************
Regression in nightly-2022-10-31
********************************************************************************

fetching https://static.rust-lang.org/dist/2022-10-30/channel-rust-nightly-git-commit-hash.txt
nightly manifest 2022-10-30: 40 B / 40 B [=========================================================================] 100.00 % 1.38 MB/s converted 2022-10-30 to 5e9772042948002f9c6f60c4c81603170035fffa
fetching https://static.rust-lang.org/dist/2022-10-31/channel-rust-nightly-git-commit-hash.txt
nightly manifest 2022-10-31: 40 B / 40 B [=========================================================================] 100.00 % 1.35 MB/s converted 2022-10-31 to 77e57db384aca99444c3b5f6a9c86bc58a804d89
looking for regression commit between 2022-10-30 and 2022-10-31
fetching (via remote github) commits from max(5e9772042948002f9c6f60c4c81603170035fffa, 2022-10-28) to 77e57db384aca99444c3b5f6a9c86bc58a804d89
ending github query because we found starting sha: 5e9772042948002f9c6f60c4c81603170035fffa
get_commits_between returning commits, len: 9
  commit[0] 2022-10-29: Auto merge of #103450 - cjgillot:elision-nodedup, r=Mark-Simulacrum
  commit[1] 2022-10-29: Auto merge of #103731 - Mark-Simulacrum:new-version, r=Mark-Simulacrum
  commit[2] 2022-10-30: Auto merge of #103745 - matthiaskrgr:rollup-hipjva8, r=matthiaskrgr
  commit[3] 2022-10-30: Auto merge of #103721 - RalfJung:miri, r=RalfJung
  commit[4] 2022-10-30: Auto merge of #103755 - Dylan-DPC:rollup-dl2hups, r=Dylan-DPC
  commit[5] 2022-10-30: Auto merge of #103010 - petrochenkov:effvisdoc, r=GuillaumeGomez
  commit[6] 2022-10-30: Auto merge of #103295 - ishitatsuyuki:ninja, r=cuviper
  commit[7] 2022-10-30: Auto merge of #103299 - nikic:usub-overflow, r=wesleywiser
  commit[8] 2022-10-30: Auto merge of #103479 - nikic:update-llvm-9, r=cuviper
ERROR: no CI builds available between 5e9772042948002f9c6f60c4c81603170035fffa and 77e57db384aca99444c3b5f6a9c86bc58a804d89 within last 167 days

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

Contributor guide

Open the contributing guide

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.

Research direction

Start by reproducing the lt_thru_sub and borrowing_sub example from the Godbolt link with the listed Rust versions, checking the generated assembly when the first tuple result is unused. Compare the behavior around the reported regressions in #103299 and #103479; done means the unused-result case again produces the expected subtraction and borrow chain rather than the larger comparison sequence.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.