Skip to content

Add intrinsics for integer minimum and maximum - #161081

Open
scottmcm wants to merge 1 commit into
rust-lang:mainfrom
scottmcm:min-max-intrinsics
Open

Add intrinsics for integer minimum and maximum#161081
scottmcm wants to merge 1 commit into
rust-lang:mainfrom
scottmcm:min-max-intrinsics

Conversation

@scottmcm

@scottmcm scottmcm commented Aug 14, 2026

Copy link
Copy Markdown
Member

View all comments

I got inspired to do this when looking at SliceOrd::compare where I was reminded that if a < b { a } else { b } isn't great in MIR since it takes 4 BBs. Looking at the codegen side, it turns out we currently emit 42 lines of LLVM-IR including 4 allocas for u16::max (pre-optimization), which is also unnecessarily bad†.

But both LLVM and Cranelift have dedicated things for min & max:

so let's just use those directly!

This actually wouldn't have been worth doing originally, but a couple of things have happened to change that:

  • Back in 1.0 there was only cmp::min & cmp::max, so there was no place to actually do this at all, but in 2017 they were added to Ord as overridable things Tracking issue for Ord::{min, max} #25663 (comment)
  • LLVM originally used icmp+select for these, not a dedicated construct, but then added one and as of 2022 the intrinsic is fully usable https://www.npopov.com/2022/12/20/This-year-in-LLVM-2022.html#integer-minmax-intrinsics
  • Before we had intrinsic fallback this would have been more annoying to support everywhere -- GCC, 128-bit numbers on cg_clif, CTFE, anything out-of-tree -- but now that we can write the obvious fallback we don't need to worry about that.
  • The intrinsic would have helped less when it forced extra BBs and allocas in codegen anyway, but now we can keep the result in SSA without needing to make it a primitive.

† Admittedly we could clean up the gratuitous badness there without needing an intrinsic, but I like doing the intrinsic anyway because that's the only way to avoid it always being stuck in the non-SSA path from the multi-BB assignments. Even if we made it inlineable, GVN and such will still just give up on seeing the x = if a < b { a } else { b } because it's multiple assignments to the same Local, which is non-ideal for something primitive-like.


Done without LLMs.

@rustbot rustbot added A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Aug 14, 2026
Comment thread library/core/src/intrinsics/mod.rs Outdated
Comment on lines +1845 to +1848
#[miri::fallback_is_spec]
pub const fn integer_min<T: Copy + [const] PartialOrd>(a: T, b: T) -> T {
if a < b { a } else { b }
}

@scottmcm scottmcm Aug 14, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc @RalfJung because I said miri::fallback_is_spec

View changes since the review

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Odd, why did the bot not ping me...

... ah, because it's a draft. :)

@scottmcm scottmcm Aug 14, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, because I know my odds of getting a working PR first push are about 2% on a good day 🙃

EDIT: oh, and also I managed to spell it wrong 🤦

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM apart from the comment nit. :)

@rust-log-analyzer

This comment has been minimized.

@scottmcm
scottmcm force-pushed the min-max-intrinsics branch from 0392eb2 to 2560466 Compare August 14, 2026 08:07
@rust-log-analyzer

This comment has been minimized.

@scottmcm
scottmcm force-pushed the min-max-intrinsics branch 2 times, most recently from 2a35cda to 56bf46d Compare August 14, 2026 16:59
@scottmcm
scottmcm marked this pull request as ready for review August 14, 2026 18:25
@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Aug 14, 2026
@rustbot

rustbot commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

Some changes occurred to the intrinsics. Make sure the CTFE / Miri interpreter
gets adapted for the changes, if necessary.

cc @rust-lang/miri, @RalfJung, @oli-obk, @lcnr

rustc_codegen_cranelift is developed in its own repository. If possible, consider making this change to rust-lang/rustc_codegen_cranelift instead.

cc @bjorn3

Any special-casing of Miri in the standard library requires review.

cc @rust-lang/miri

⚠️ #[miri::intrinsic_fallback_is_spec] must only be used if the function actively checks for all UB cases,
and explores the possible non-determinism of the intrinsic.

cc @rust-lang/miri

@rustbot rustbot removed the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Aug 14, 2026
@rustbot

rustbot commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

r? @clarfonthey

rustbot has assigned @clarfonthey.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: libs
  • libs expanded to 12 candidates
  • Random selection from JohnTitor, Mark-Simulacrum, clarfonthey, nia-e

@scottmcm

Copy link
Copy Markdown
Member Author

Given that LLVM can collapse all the mess this probably won't show much of a difference, but might as well make sure it's at least not worse somehow
@bors try @rust-timer queue

@rust-timer

This comment has been minimized.

@rust-bors

This comment has been minimized.

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Aug 14, 2026
rust-bors Bot pushed a commit that referenced this pull request Aug 14, 2026
Add intrinsics for integer minimum and maximum
Comment thread library/core/src/intrinsics/mod.rs Outdated
#[rustc_nounwind]
#[rustc_intrinsic]
#[miri::intrinsic_fallback_is_spec]
pub const fn integer_min<T: Copy + [const] PartialOrd>(a: T, b: T) -> T {

@RalfJung RalfJung Aug 14, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name says integer but the type signature does not. If there are constraints on the type that go beyond the signature, please spell them out in the doc comment.

View changes since the review

@scottmcm scottmcm Aug 14, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have thoughts about doing it via a trait?

Like we have FloatPrimitive I could add IntegerPrimitive and bound it that way.

That exists for fallbacks more than for just type checking, though, so I don't know if it's worth doing here vs just documenting it.

Edit: Oh, actually, I think I might as well do that because then the Ord requirement can come from that trait instead of listing it out.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, with both a bound and a doc-comment update.

@rust-bors

rust-bors Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

☀️ Try build successful (CI)
Build commit: 8764a9b (8764a9b9995264025b6234cf175d01db8c729849)
Base parent: d453bdd (d453bdd8f092d099bc336f0bda4163f809ad18e0)

Comment thread compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs Outdated
@clarfonthey

clarfonthey commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

I'm happy with this and would be fine merging once you make whatever fallback changes you were mentioning. I'm not on the compiler team, but just from the perspective of optimising the giant pile of operations we have in libstd, adding more intrinsics for "obvious" primitives like this is fine, even if they're technically redundant.

For example, #161069 which also fell under my review recommended adding some potential additional reasoning for checked_next_power_of_two and I was already a bit worried that the complexity of the operations involved would not optimise correctly, which I haven't yet verified. If the codegen backends support it, I think we should go ahead with these, especially if there's some extra empirical justification as there seems to be here.


other => {
tcx.dcx().emit_err(UnrecognizedIntrinsicFunction { span, name: other });
tcx.dcx().emit_err(UnrecognizedIntrinsicFunction { span, name: other, file: file!() });

@clarfonthey clarfonthey Aug 14, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can definitely tell that this was motivated by you forgetting which file this was when you added this intrinsic. :p

View changes since the review

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💯

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this is where span_bug! might be better than emit_err. ;)
I don't know why we bother with "pretty" errors for intrinsic misuse anyway...

Comment thread compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
@scottmcm

Copy link
Copy Markdown
Member Author

Curious, the build didn't get queued
@rust-timer queue

@rust-timer

This comment has been minimized.

@clarfonthey

Copy link
Copy Markdown
Contributor

@rust-timer build 8764a9b

@scottmcm

Copy link
Copy Markdown
Member Author

Oh, locally and in CI it uses a trimmed path, but that job got

in /rustc-dev/032b936729552ee7962aa7098d05e64660f92030/compiler/rustc_hir_analysis/src/check/intrinsic.rs

I'll just remove that part of this PR (and maybe change it to an ICE later).

@scottmcm
scottmcm force-pushed the min-max-intrinsics branch from 564405d to 7519f42 Compare August 30, 2026 08:07
@rustbot

rustbot commented Aug 30, 2026

Copy link
Copy Markdown
Collaborator

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@rust-log-analyzer

Copy link
Copy Markdown
Collaborator

The job x86_64-gnu-tools failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)
100  177M  100  177M    0     0  69.3M      0  0:00:02  0:00:02 --:--:-- 69.3M
#12 DONE 2.8s

#13 [ 7/10] RUN unzip -d /usr/bin/ chrome-linux64.zip && rm chrome-linux64.zip
#13 0.049 Archive:  chrome-linux64.zip
#13 0.050   inflating: /usr/bin/chrome-linux64/ABOUT  
#13 0.051   inflating: /usr/bin/chrome-linux64/MEIPreload/manifest.json  
#13 0.051   inflating: /usr/bin/chrome-linux64/MEIPreload/preloaded_data.pb  
#13 0.051   inflating: /usr/bin/chrome-linux64/PrivacySandboxAttestationsPreloaded/manifest.json  
#13 0.051   inflating: /usr/bin/chrome-linux64/PrivacySandboxAttestationsPreloaded/privacy-sandbox-attestations.dat  
#13 0.052   inflating: /usr/bin/chrome-linux64/WidevineCdm/LICENSE  
#13 0.052   inflating: /usr/bin/chrome-linux64/WidevineCdm/_platform_specific/linux_x64/libwidevinecdm.so  
#13 0.181   inflating: /usr/bin/chrome-linux64/WidevineCdm/manifest.json  
#13 0.182   inflating: /usr/bin/chrome-linux64/chrome  
#13 2.424   inflating: /usr/bin/chrome-linux64/chrome-wrapper  
#13 2.424   inflating: /usr/bin/chrome-linux64/chrome_100_percent.pak  
#13 2.429   inflating: /usr/bin/chrome-linux64/chrome_200_percent.pak  
#13 2.438   inflating: /usr/bin/chrome-linux64/chrome_crashpad_handler  
#13 2.455   inflating: /usr/bin/chrome-linux64/chrome_sandbox  
#13 2.455   inflating: /usr/bin/chrome-linux64/deb.deps  
#13 2.456   inflating: /usr/bin/chrome-linux64/icudtl.dat  
#13 2.537   inflating: /usr/bin/chrome-linux64/libEGL.so  
#13 2.539   inflating: /usr/bin/chrome-linux64/libGLESv2.so  
#13 2.590   inflating: /usr/bin/chrome-linux64/libvk_swiftshader.so  
#13 2.628   inflating: /usr/bin/chrome-linux64/libvulkan.so.1  
#13 2.633   inflating: /usr/bin/chrome-linux64/locales/af.pak  
#13 2.638   inflating: /usr/bin/chrome-linux64/locales/af_FEMININE.pak  
#13 2.638   inflating: /usr/bin/chrome-linux64/locales/af_MASCULINE.pak  
#13 2.638   inflating: /usr/bin/chrome-linux64/locales/af_NEUTER.pak  
#13 2.638   inflating: /usr/bin/chrome-linux64/locales/am.pak  
#13 2.646   inflating: /usr/bin/chrome-linux64/locales/am_FEMININE.pak  
#13 2.646   inflating: /usr/bin/chrome-linux64/locales/am_MASCULINE.pak  
#13 2.646   inflating: /usr/bin/chrome-linux64/locales/am_NEUTER.pak  
#13 2.646   inflating: /usr/bin/chrome-linux64/locales/ar.pak  
#13 2.654   inflating: /usr/bin/chrome-linux64/locales/ar_FEMININE.pak  
#13 2.654   inflating: /usr/bin/chrome-linux64/locales/ar_MASCULINE.pak  
#13 2.654   inflating: /usr/bin/chrome-linux64/locales/ar_NEUTER.pak  
#13 2.654   inflating: /usr/bin/chrome-linux64/locales/bg.pak  
#13 2.662   inflating: /usr/bin/chrome-linux64/locales/bg_FEMININE.pak  
#13 2.662   inflating: /usr/bin/chrome-linux64/locales/bg_MASCULINE.pak  
#13 2.662   inflating: /usr/bin/chrome-linux64/locales/bg_NEUTER.pak  
#13 2.662   inflating: /usr/bin/chrome-linux64/locales/bn.pak  
#13 2.672   inflating: /usr/bin/chrome-linux64/locales/bn_FEMININE.pak  
#13 2.672   inflating: /usr/bin/chrome-linux64/locales/bn_MASCULINE.pak  
#13 2.672   inflating: /usr/bin/chrome-linux64/locales/bn_NEUTER.pak  
#13 2.673   inflating: /usr/bin/chrome-linux64/locales/ca.pak  
#13 2.678   inflating: /usr/bin/chrome-linux64/locales/ca_FEMININE.pak  
#13 2.678   inflating: /usr/bin/chrome-linux64/locales/ca_MASCULINE.pak  
#13 2.678   inflating: /usr/bin/chrome-linux64/locales/ca_NEUTER.pak  
#13 2.678   inflating: /usr/bin/chrome-linux64/locales/cs.pak  
#13 2.684   inflating: /usr/bin/chrome-linux64/locales/cs_FEMININE.pak  
#13 2.684   inflating: /usr/bin/chrome-linux64/locales/cs_MASCULINE.pak  
#13 2.684   inflating: /usr/bin/chrome-linux64/locales/cs_NEUTER.pak  
#13 2.684   inflating: /usr/bin/chrome-linux64/locales/da.pak  
#13 2.689   inflating: /usr/bin/chrome-linux64/locales/da_FEMININE.pak  
#13 2.689   inflating: /usr/bin/chrome-linux64/locales/da_MASCULINE.pak  
#13 2.689   inflating: /usr/bin/chrome-linux64/locales/da_NEUTER.pak  
#13 2.689   inflating: /usr/bin/chrome-linux64/locales/de.pak  
#13 2.695   inflating: /usr/bin/chrome-linux64/locales/de_FEMININE.pak  
#13 2.695   inflating: /usr/bin/chrome-linux64/locales/de_MASCULINE.pak  
#13 2.695   inflating: /usr/bin/chrome-linux64/locales/de_NEUTER.pak  
#13 2.696   inflating: /usr/bin/chrome-linux64/locales/el.pak  
#13 2.704   inflating: /usr/bin/chrome-linux64/locales/el_FEMININE.pak  
#13 2.704   inflating: /usr/bin/chrome-linux64/locales/el_MASCULINE.pak  
#13 2.704   inflating: /usr/bin/chrome-linux64/locales/el_NEUTER.pak  
#13 2.704   inflating: /usr/bin/chrome-linux64/locales/en-GB.pak  
#13 2.709   inflating: /usr/bin/chrome-linux64/locales/en-GB_FEMININE.pak  
#13 2.709   inflating: /usr/bin/chrome-linux64/locales/en-GB_MASCULINE.pak  
#13 2.709   inflating: /usr/bin/chrome-linux64/locales/en-GB_NEUTER.pak  
#13 2.709   inflating: /usr/bin/chrome-linux64/locales/en-US.pak  
#13 2.713   inflating: /usr/bin/chrome-linux64/locales/en-US_FEMININE.pak  
#13 2.714   inflating: /usr/bin/chrome-linux64/locales/en-US_MASCULINE.pak  
#13 2.714   inflating: /usr/bin/chrome-linux64/locales/en-US_NEUTER.pak  
#13 2.714   inflating: /usr/bin/chrome-linux64/locales/es-419.pak  
#13 2.719   inflating: /usr/bin/chrome-linux64/locales/es-419_FEMININE.pak  
#13 2.719   inflating: /usr/bin/chrome-linux64/locales/es-419_MASCULINE.pak  
#13 2.719   inflating: /usr/bin/chrome-linux64/locales/es-419_NEUTER.pak  
#13 2.720   inflating: /usr/bin/chrome-linux64/locales/es.pak  
#13 2.725   inflating: /usr/bin/chrome-linux64/locales/es_FEMININE.pak  
#13 2.725   inflating: /usr/bin/chrome-linux64/locales/es_MASCULINE.pak  
#13 2.725   inflating: /usr/bin/chrome-linux64/locales/es_NEUTER.pak  
#13 2.725   inflating: /usr/bin/chrome-linux64/locales/et.pak  
#13 2.730   inflating: /usr/bin/chrome-linux64/locales/et_FEMININE.pak  
#13 2.730   inflating: /usr/bin/chrome-linux64/locales/et_MASCULINE.pak  
#13 2.731   inflating: /usr/bin/chrome-linux64/locales/et_NEUTER.pak  
#13 2.731   inflating: /usr/bin/chrome-linux64/locales/fa.pak  
#13 2.738   inflating: /usr/bin/chrome-linux64/locales/fa_FEMININE.pak  
#13 2.738   inflating: /usr/bin/chrome-linux64/locales/fa_MASCULINE.pak  
#13 2.738   inflating: /usr/bin/chrome-linux64/locales/fa_NEUTER.pak  
#13 2.738   inflating: /usr/bin/chrome-linux64/locales/fi.pak  
#13 2.744   inflating: /usr/bin/chrome-linux64/locales/fi_FEMININE.pak  
#13 2.744   inflating: /usr/bin/chrome-linux64/locales/fi_MASCULINE.pak  
#13 2.744   inflating: /usr/bin/chrome-linux64/locales/fi_NEUTER.pak  
#13 2.744   inflating: /usr/bin/chrome-linux64/locales/fil.pak  
#13 2.749   inflating: /usr/bin/chrome-linux64/locales/fil_FEMININE.pak  
#13 2.750   inflating: /usr/bin/chrome-linux64/locales/fil_MASCULINE.pak  
#13 2.750   inflating: /usr/bin/chrome-linux64/locales/fil_NEUTER.pak  
#13 2.750   inflating: /usr/bin/chrome-linux64/locales/fr.pak  
#13 2.755   inflating: /usr/bin/chrome-linux64/locales/fr_FEMININE.pak  
#13 2.755   inflating: /usr/bin/chrome-linux64/locales/fr_MASCULINE.pak  
#13 2.756   inflating: /usr/bin/chrome-linux64/locales/fr_NEUTER.pak  
#13 2.756   inflating: /usr/bin/chrome-linux64/locales/gu.pak  
#13 2.766   inflating: /usr/bin/chrome-linux64/locales/gu_FEMININE.pak  
#13 2.766   inflating: /usr/bin/chrome-linux64/locales/gu_MASCULINE.pak  
#13 2.766   inflating: /usr/bin/chrome-linux64/locales/gu_NEUTER.pak  
#13 2.766   inflating: /usr/bin/chrome-linux64/locales/he.pak  
#13 2.772   inflating: /usr/bin/chrome-linux64/locales/he_FEMININE.pak  
#13 2.773   inflating: /usr/bin/chrome-linux64/locales/he_MASCULINE.pak  
#13 2.773   inflating: /usr/bin/chrome-linux64/locales/he_NEUTER.pak  
#13 2.773   inflating: /usr/bin/chrome-linux64/locales/hi.pak  
#13 2.783   inflating: /usr/bin/chrome-linux64/locales/hi_FEMININE.pak  
#13 2.783   inflating: /usr/bin/chrome-linux64/locales/hi_MASCULINE.pak  
#13 2.783   inflating: /usr/bin/chrome-linux64/locales/hi_NEUTER.pak  
#13 2.783   inflating: /usr/bin/chrome-linux64/locales/hr.pak  
#13 2.789   inflating: /usr/bin/chrome-linux64/locales/hr_FEMININE.pak  
#13 2.789   inflating: /usr/bin/chrome-linux64/locales/hr_MASCULINE.pak  
#13 2.789   inflating: /usr/bin/chrome-linux64/locales/hr_NEUTER.pak  
#13 2.789   inflating: /usr/bin/chrome-linux64/locales/hu.pak  
#13 2.795   inflating: /usr/bin/chrome-linux64/locales/hu_FEMININE.pak  
#13 2.795   inflating: /usr/bin/chrome-linux64/locales/hu_MASCULINE.pak  
#13 2.795   inflating: /usr/bin/chrome-linux64/locales/hu_NEUTER.pak  
#13 2.795   inflating: /usr/bin/chrome-linux64/locales/id.pak  
#13 2.800   inflating: /usr/bin/chrome-linux64/locales/id_FEMININE.pak  
#13 2.800   inflating: /usr/bin/chrome-linux64/locales/id_MASCULINE.pak  
#13 2.800   inflating: /usr/bin/chrome-linux64/locales/id_NEUTER.pak  
#13 2.800   inflating: /usr/bin/chrome-linux64/locales/it.pak  
#13 2.805   inflating: /usr/bin/chrome-linux64/locales/it_FEMININE.pak  
#13 2.806   inflating: /usr/bin/chrome-linux64/locales/it_MASCULINE.pak  
#13 2.806   inflating: /usr/bin/chrome-linux64/locales/it_NEUTER.pak  
#13 2.806   inflating: /usr/bin/chrome-linux64/locales/ja.pak  
#13 2.812   inflating: /usr/bin/chrome-linux64/locales/ja_FEMININE.pak  
#13 2.812   inflating: /usr/bin/chrome-linux64/locales/ja_MASCULINE.pak  
#13 2.812   inflating: /usr/bin/chrome-linux64/locales/ja_NEUTER.pak  
#13 2.812   inflating: /usr/bin/chrome-linux64/locales/kn.pak  
#13 2.823   inflating: /usr/bin/chrome-linux64/locales/kn_FEMININE.pak  
#13 2.823   inflating: /usr/bin/chrome-linux64/locales/kn_MASCULINE.pak  
#13 2.823   inflating: /usr/bin/chrome-linux64/locales/kn_NEUTER.pak  
#13 2.823   inflating: /usr/bin/chrome-linux64/locales/ko.pak  
#13 2.828   inflating: /usr/bin/chrome-linux64/locales/ko_FEMININE.pak  
#13 2.829   inflating: /usr/bin/chrome-linux64/locales/ko_MASCULINE.pak  
#13 2.829   inflating: /usr/bin/chrome-linux64/locales/ko_NEUTER.pak  
#13 2.829   inflating: /usr/bin/chrome-linux64/locales/lt.pak  
#13 2.834   inflating: /usr/bin/chrome-linux64/locales/lt_FEMININE.pak  
#13 2.835   inflating: /usr/bin/chrome-linux64/locales/lt_MASCULINE.pak  
#13 2.835   inflating: /usr/bin/chrome-linux64/locales/lt_NEUTER.pak  
#13 2.835   inflating: /usr/bin/chrome-linux64/locales/lv.pak  
#13 2.840   inflating: /usr/bin/chrome-linux64/locales/lv_FEMININE.pak  
#13 2.840   inflating: /usr/bin/chrome-linux64/locales/lv_MASCULINE.pak  
#13 2.842   inflating: /usr/bin/chrome-linux64/locales/lv_NEUTER.pak  
#13 2.842   inflating: /usr/bin/chrome-linux64/locales/ml.pak  
#13 2.853   inflating: /usr/bin/chrome-linux64/locales/ml_FEMININE.pak  
#13 2.853   inflating: /usr/bin/chrome-linux64/locales/ml_MASCULINE.pak  
#13 2.853   inflating: /usr/bin/chrome-linux64/locales/ml_NEUTER.pak  
#13 2.853   inflating: /usr/bin/chrome-linux64/locales/mr.pak  
#13 2.863   inflating: /usr/bin/chrome-linux64/locales/mr_FEMININE.pak  
#13 2.863   inflating: /usr/bin/chrome-linux64/locales/mr_MASCULINE.pak  
#13 2.863   inflating: /usr/bin/chrome-linux64/locales/mr_NEUTER.pak  
#13 2.863   inflating: /usr/bin/chrome-linux64/locales/ms.pak  
#13 2.868   inflating: /usr/bin/chrome-linux64/locales/ms_FEMININE.pak  
#13 2.868   inflating: /usr/bin/chrome-linux64/locales/ms_MASCULINE.pak  
#13 2.868   inflating: /usr/bin/chrome-linux64/locales/ms_NEUTER.pak  
#13 2.868   inflating: /usr/bin/chrome-linux64/locales/nb.pak  
#13 2.873   inflating: /usr/bin/chrome-linux64/locales/nb_FEMININE.pak  
#13 2.873   inflating: /usr/bin/chrome-linux64/locales/nb_MASCULINE.pak  
#13 2.873   inflating: /usr/bin/chrome-linux64/locales/nb_NEUTER.pak  
#13 2.874   inflating: /usr/bin/chrome-linux64/locales/nl.pak  
#13 2.879   inflating: /usr/bin/chrome-linux64/locales/nl_FEMININE.pak  
#13 2.879   inflating: /usr/bin/chrome-linux64/locales/nl_MASCULINE.pak  
#13 2.879   inflating: /usr/bin/chrome-linux64/locales/nl_NEUTER.pak  
#13 2.879   inflating: /usr/bin/chrome-linux64/locales/pl.pak  
#13 2.884   inflating: /usr/bin/chrome-linux64/locales/pl_FEMININE.pak  
#13 2.884   inflating: /usr/bin/chrome-linux64/locales/pl_MASCULINE.pak  
#13 2.885   inflating: /usr/bin/chrome-linux64/locales/pl_NEUTER.pak  
#13 2.885   inflating: /usr/bin/chrome-linux64/locales/pt-BR.pak  
#13 2.890   inflating: /usr/bin/chrome-linux64/locales/pt-BR_FEMININE.pak  
#13 2.890   inflating: /usr/bin/chrome-linux64/locales/pt-BR_MASCULINE.pak  
#13 2.891   inflating: /usr/bin/chrome-linux64/locales/pt-BR_NEUTER.pak  
#13 2.891   inflating: /usr/bin/chrome-linux64/locales/pt-PT.pak  
#13 2.896   inflating: /usr/bin/chrome-linux64/locales/pt-PT_FEMININE.pak  
#13 2.896   inflating: /usr/bin/chrome-linux64/locales/pt-PT_MASCULINE.pak  
#13 2.896   inflating: /usr/bin/chrome-linux64/locales/pt-PT_NEUTER.pak  
#13 2.896   inflating: /usr/bin/chrome-linux64/locales/ro.pak  
#13 2.902   inflating: /usr/bin/chrome-linux64/locales/ro_FEMININE.pak  
#13 2.902   inflating: /usr/bin/chrome-linux64/locales/ro_MASCULINE.pak  
#13 2.902   inflating: /usr/bin/chrome-linux64/locales/ro_NEUTER.pak  
#13 2.902   inflating: /usr/bin/chrome-linux64/locales/ru.pak  
#13 2.910   inflating: /usr/bin/chrome-linux64/locales/ru_FEMININE.pak  
#13 2.910   inflating: /usr/bin/chrome-linux64/locales/ru_MASCULINE.pak  
#13 2.910   inflating: /usr/bin/chrome-linux64/locales/ru_NEUTER.pak  
#13 2.911   inflating: /usr/bin/chrome-linux64/locales/sk.pak  
#13 2.916   inflating: /usr/bin/chrome-linux64/locales/sk_FEMININE.pak  
#13 2.916   inflating: /usr/bin/chrome-linux64/locales/sk_MASCULINE.pak  
#13 2.916   inflating: /usr/bin/chrome-linux64/locales/sk_NEUTER.pak  
#13 2.917   inflating: /usr/bin/chrome-linux64/locales/sl.pak  
#13 2.922   inflating: /usr/bin/chrome-linux64/locales/sl_FEMININE.pak  
#13 2.922   inflating: /usr/bin/chrome-linux64/locales/sl_MASCULINE.pak  
#13 2.922   inflating: /usr/bin/chrome-linux64/locales/sl_NEUTER.pak  
#13 2.922   inflating: /usr/bin/chrome-linux64/locales/sr.pak  
#13 2.930   inflating: /usr/bin/chrome-linux64/locales/sr_FEMININE.pak  
#13 2.930   inflating: /usr/bin/chrome-linux64/locales/sr_MASCULINE.pak  
#13 2.930   inflating: /usr/bin/chrome-linux64/locales/sr_NEUTER.pak  
#13 2.930   inflating: /usr/bin/chrome-linux64/locales/sv.pak  
#13 2.935   inflating: /usr/bin/chrome-linux64/locales/sv_FEMININE.pak  
#13 2.935   inflating: /usr/bin/chrome-linux64/locales/sv_MASCULINE.pak  
#13 2.935   inflating: /usr/bin/chrome-linux64/locales/sv_NEUTER.pak  
#13 2.936   inflating: /usr/bin/chrome-linux64/locales/sw.pak  
#13 2.941   inflating: /usr/bin/chrome-linux64/locales/sw_FEMININE.pak  
#13 2.941   inflating: /usr/bin/chrome-linux64/locales/sw_MASCULINE.pak  
#13 2.941   inflating: /usr/bin/chrome-linux64/locales/sw_NEUTER.pak  
#13 2.941   inflating: /usr/bin/chrome-linux64/locales/ta.pak  
#13 2.953   inflating: /usr/bin/chrome-linux64/locales/ta_FEMININE.pak  
#13 2.953   inflating: /usr/bin/chrome-linux64/locales/ta_MASCULINE.pak  
#13 2.953   inflating: /usr/bin/chrome-linux64/locales/ta_NEUTER.pak  
#13 2.953   inflating: /usr/bin/chrome-linux64/locales/te.pak  
#13 2.963   inflating: /usr/bin/chrome-linux64/locales/te_FEMININE.pak  
#13 2.964   inflating: /usr/bin/chrome-linux64/locales/te_MASCULINE.pak  
#13 2.964   inflating: /usr/bin/chrome-linux64/locales/te_NEUTER.pak  
#13 2.964   inflating: /usr/bin/chrome-linux64/locales/th.pak  
#13 2.973   inflating: /usr/bin/chrome-linux64/locales/th_FEMININE.pak  
#13 2.973   inflating: /usr/bin/chrome-linux64/locales/th_MASCULINE.pak  
#13 2.973   inflating: /usr/bin/chrome-linux64/locales/th_NEUTER.pak  
#13 2.973   inflating: /usr/bin/chrome-linux64/locales/tr.pak  
#13 2.978   inflating: /usr/bin/chrome-linux64/locales/tr_FEMININE.pak  
#13 2.978   inflating: /usr/bin/chrome-linux64/locales/tr_MASCULINE.pak  
#13 2.978   inflating: /usr/bin/chrome-linux64/locales/tr_NEUTER.pak  
#13 2.979   inflating: /usr/bin/chrome-linux64/locales/uk.pak  
#13 2.986   inflating: /usr/bin/chrome-linux64/locales/uk_FEMININE.pak  
#13 2.986   inflating: /usr/bin/chrome-linux64/locales/uk_MASCULINE.pak  
#13 2.987   inflating: /usr/bin/chrome-linux64/locales/uk_NEUTER.pak  
#13 2.987   inflating: /usr/bin/chrome-linux64/locales/ur.pak  
#13 2.994   inflating: /usr/bin/chrome-linux64/locales/ur_FEMININE.pak  
#13 2.994   inflating: /usr/bin/chrome-linux64/locales/ur_MASCULINE.pak  
#13 2.994   inflating: /usr/bin/chrome-linux64/locales/ur_NEUTER.pak  
#13 2.994   inflating: /usr/bin/chrome-linux64/locales/vi.pak  
#13 3.000   inflating: /usr/bin/chrome-linux64/locales/vi_FEMININE.pak  
#13 3.000   inflating: /usr/bin/chrome-linux64/locales/vi_MASCULINE.pak  
#13 3.000   inflating: /usr/bin/chrome-linux64/locales/vi_NEUTER.pak  
#13 3.000   inflating: /usr/bin/chrome-linux64/locales/zh-CN.pak  
#13 3.005   inflating: /usr/bin/chrome-linux64/locales/zh-CN_FEMININE.pak  
#13 3.005   inflating: /usr/bin/chrome-linux64/locales/zh-CN_MASCULINE.pak  
#13 3.005   inflating: /usr/bin/chrome-linux64/locales/zh-CN_NEUTER.pak  
#13 3.005   inflating: /usr/bin/chrome-linux64/locales/zh-TW.pak  
#13 3.010   inflating: /usr/bin/chrome-linux64/locales/zh-TW_FEMININE.pak  
#13 3.010   inflating: /usr/bin/chrome-linux64/locales/zh-TW_MASCULINE.pak  
#13 3.010   inflating: /usr/bin/chrome-linux64/locales/zh-TW_NEUTER.pak  
#13 3.010  extracting: /usr/bin/chrome-linux64/product_logo_48.png  
#13 3.010   inflating: /usr/bin/chrome-linux64/resources.pak  
#13 3.099   inflating: /usr/bin/chrome-linux64/rpm.deps  
#13 3.099   inflating: /usr/bin/chrome-linux64/v8_context_snapshot.bin  
#13 3.105   inflating: /usr/bin/chrome-linux64/vk_swiftshader_icd.json  
#13 3.105    creating: /usr/bin/chrome-linux64/resources/
#13 3.105    creating: /usr/bin/chrome-linux64/resources/inspector_overlay/
#13 3.105   inflating: /usr/bin/chrome-linux64/resources/inspector_overlay/inspector_overlay_resources.grd  
#13 3.106   inflating: /usr/bin/chrome-linux64/resources/inspector_overlay/main.js  
#13 3.106    creating: /usr/bin/chrome-linux64/resources/accessibility/
#13 3.106    creating: /usr/bin/chrome-linux64/resources/accessibility/reading_mode_gdocs_helper/
#13 3.107   inflating: /usr/bin/chrome-linux64/resources/accessibility/reading_mode_gdocs_helper/content.js  
#13 3.107   inflating: /usr/bin/chrome-linux64/resources/accessibility/reading_mode_gdocs_helper/gdocs_script.js  
#13 3.107   inflating: /usr/bin/chrome-linux64/resources/accessibility/reading_mode_gdocs_helper_manifest.json  
#13 3.107    creating: /usr/bin/chrome-linux64/hyphen-data/
#13 3.107   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-tk.hyb  
#13 3.107   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-de-1901.hyb  
#13 3.109   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-de-1996.hyb  
#13 3.110   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-mul-ethi.hyb  
#13 3.110   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-es.hyb  
#13 3.111   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-hi.hyb  
#13 3.111   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-cu.hyb  
#13 3.111   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-as.hyb  
#13 3.112   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-ta.hyb  
#13 3.112   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-pa.hyb  
#13 3.112   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-el.hyb  
#13 3.112   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-te.hyb  
#13 3.112   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-und-ethi.hyb  
#13 3.112   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-de-ch-1901.hyb  
#13 3.114   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-bg.hyb  
#13 3.114   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-gu.hyb  
#13 3.114   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-et.hyb  
#13 3.114   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-cs.hyb  
#13 3.115   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-nl.hyb  
#13 3.116   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-ru.hyb  
#13 3.117   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-hy.hyb  
#13 3.117   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-uk.hyb  
#13 3.117   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-eu.hyb  
#13 3.117   inflating: /usr/bin/chrome-linux64/hyphen-data/manifest.json  
#13 3.117   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-ga.hyb  
#13 3.118   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-sk.hyb  
#13 3.119   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-mr.hyb  
#13 3.119   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-bn.hyb  
#13 3.119   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-nb.hyb  
#13 3.121   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-en-gb.hyb  
#13 3.122   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-or.hyb  
#13 3.123   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-cy.hyb  
#13 3.123   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-hr.hyb  
#13 3.123   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-fr.hyb  
#13 3.123   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-kn.hyb  
#13 3.123   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-mn-cyrl.hyb  
#13 3.123   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-lt.hyb  
#13 3.123   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-en-us.hyb  
#13 3.124   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-ml.hyb  
#13 3.124   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-pt.hyb  
#13 3.124   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-be.hyb  
#13 3.124   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-sl.hyb  
#13 3.124   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-lv.hyb  
#13 3.125   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-sv.hyb  
#13 3.126   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-hu.hyb  
#13 3.129   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-af.hyb  
#13 3.130   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-sq.hyb  
#13 3.130   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-ka.hyb  
#13 3.131   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-it.hyb  
#13 3.131   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-gl.hyb  
#13 3.131   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-da.hyb  
#13 3.131   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-nn.hyb  
#13 3.133   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-la.hyb  
#13 DONE 3.8s

#14 [ 8/10] COPY scripts/nodejs.sh /scripts/
#14 DONE 0.0s

---
.                                                  (151/151)

======== tests/rustdoc-gui/rustdoc-toolbar.goml ========

[ERROR] rustdoc-toolbar output:
Runtime.callFunctionOn timed out. Increase the 'protocolTimeout' setting in launch/connect calls for a higher timeout if needed.
stack: ProtocolError: Runtime.callFunctionOn timed out. Increase the 'protocolTimeout' setting in launch/connect calls for a higher timeout if needed.
    at <instance_members_initializer> (file:///checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc-gui/node_modules/puppeteer-core/lib/puppeteer/common/CallbackRegistry.js:108:14)
    at new Callback (file:///checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc-gui/node_modules/puppeteer-core/lib/puppeteer/common/CallbackRegistry.js:112:16)
    at CallbackRegistry.create (file:///checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc-gui/node_modules/puppeteer-core/lib/puppeteer/common/CallbackRegistry.js:27:26)
    at Connection._rawSend (file:///checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc-gui/node_modules/puppeteer-core/lib/puppeteer/cdp/Connection.js:125:26)
    at CdpCDPSession.send (file:///checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc-gui/node_modules/puppeteer-core/lib/puppeteer/cdp/CdpSession.js:72:14)
    at #evaluate (file:///checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc-gui/node_modules/puppeteer-core/lib/puppeteer/cdp/ExecutionContext.js:374:50)
    at ExecutionContext.evaluate (file:///checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc-gui/node_modules/puppeteer-core/lib/puppeteer/cdp/ExecutionContext.js:288:36)
    at IsolatedWorld.evaluate (file:///checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc-gui/node_modules/puppeteer-core/lib/puppeteer/cdp/IsolatedWorld.js:104:30)
    at CdpFrame.evaluate (file:///checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc-gui/node_modules/puppeteer-core/lib/puppeteer/api/Frame.js:364:43)
    at CdpFrame.<anonymous> (file:///checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc-gui/node_modules/puppeteer-core/lib/puppeteer/util/decorators.js:101:27)


======== tests/rustdoc-gui/search-result-display.goml ========

[WARNING] line 38: Delta is 0 for "x", maybe try to use `compare-elements-position` instead?

@scottmcm

Copy link
Copy Markdown
Member Author

@bors r=clarfonthey

@rust-bors

rust-bors Bot commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

📌 Commit 7519f42 has been approved by clarfonthey

It is now in the queue for this repository.

@rust-bors rust-bors Bot added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Aug 30, 2026
@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Aug 30, 2026
Add intrinsics for integer minimum and maximum



I got inspired to do this when looking at `SliceOrd::compare` where I was reminded that `if a < b { a } else { b }` isn't great in MIR since it takes 4 BBs.  Looking at the codegen side, it turns out we currently emit [42 lines of LLVM-IR including 4 `alloca`s](https://rust.godbolt.org/z/ha4h4nT3r) for `u16::max` (pre-optimization), which is also unnecessarily bad†.

But both LLVM and Cranelift have dedicated things for min & max:

- https://llvm.org/docs/LangRef.html#llvm-umax-intrinsic
- https://docs.rs/cranelift-codegen/latest/cranelift_codegen/ir/trait.InstBuilder.html#method.smin

so let's just use those directly!

This actually wouldn't have been worth doing originally, but a couple of things have happened to change that:

- Back in 1.0 there was only `cmp::min` & `cmp::max`, so there was no place to actually do this at all, but in 2017 they were added to `Ord` as overridable things #25663 (comment)
- LLVM originally used icmp+select for these, not a dedicated construct, but then added one and as of 2022 the intrinsic is fully usable https://www.npopov.com/2022/12/20/This-year-in-LLVM-2022.html#integer-minmax-intrinsics
- Before we had intrinsic fallback this would have been more annoying to support everywhere -- GCC, [128-bit numbers on cg_clif](bytecodealliance/wasmtime#13790), CTFE, anything out-of-tree -- but now that we can write the obvious fallback we don't need to worry about that.
- The intrinsic would have helped less when it forced extra BBs and `alloca`s in codegen anyway, but [now](rust-lang/compiler-team#970) we can keep the result in SSA without needing to make it a primitive.

† Admittedly we could clean up the gratuitous badness there without needing an intrinsic, but I like doing the intrinsic anyway because that's the only way to avoid it always being stuck in the non-SSA path from the multi-BB assignments.  Even if we made it inlineable, GVN and such will still just give up on seeing the `x = if a < b { a } else { b }` because it's multiple assignments to the same Local, which is non-ideal for something primitive-like.
@Mark-Simulacrum

Copy link
Copy Markdown
Member

@bors yield

Yielding to #162016 to help make sure our infra stays healthy since this hasn't been running for long.

@rust-bors

rust-bors Bot commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Auto build was cancelled. Cancelled workflows:

The next pull request likely to be tested is #162016.

@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Aug 30, 2026
Add intrinsics for integer minimum and maximum



I got inspired to do this when looking at `SliceOrd::compare` where I was reminded that `if a < b { a } else { b }` isn't great in MIR since it takes 4 BBs.  Looking at the codegen side, it turns out we currently emit [42 lines of LLVM-IR including 4 `alloca`s](https://rust.godbolt.org/z/ha4h4nT3r) for `u16::max` (pre-optimization), which is also unnecessarily bad†.

But both LLVM and Cranelift have dedicated things for min & max:

- https://llvm.org/docs/LangRef.html#llvm-umax-intrinsic
- https://docs.rs/cranelift-codegen/latest/cranelift_codegen/ir/trait.InstBuilder.html#method.smin

so let's just use those directly!

This actually wouldn't have been worth doing originally, but a couple of things have happened to change that:

- Back in 1.0 there was only `cmp::min` & `cmp::max`, so there was no place to actually do this at all, but in 2017 they were added to `Ord` as overridable things #25663 (comment)
- LLVM originally used icmp+select for these, not a dedicated construct, but then added one and as of 2022 the intrinsic is fully usable https://www.npopov.com/2022/12/20/This-year-in-LLVM-2022.html#integer-minmax-intrinsics
- Before we had intrinsic fallback this would have been more annoying to support everywhere -- GCC, [128-bit numbers on cg_clif](bytecodealliance/wasmtime#13790), CTFE, anything out-of-tree -- but now that we can write the obvious fallback we don't need to worry about that.
- The intrinsic would have helped less when it forced extra BBs and `alloca`s in codegen anyway, but [now](rust-lang/compiler-team#970) we can keep the result in SSA without needing to make it a primitive.

† Admittedly we could clean up the gratuitous badness there without needing an intrinsic, but I like doing the intrinsic anyway because that's the only way to avoid it always being stuck in the non-SSA path from the multi-BB assignments.  Even if we made it inlineable, GVN and such will still just give up on seeing the `x = if a < b { a } else { b }` because it's multiple assignments to the same Local, which is non-ideal for something primitive-like.
@JonathanBrouwer

Copy link
Copy Markdown
Member

@bors yield
Doing the rollup first so I can monitor it while I'm awake

@rust-bors

rust-bors Bot commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Auto build was cancelled. Cancelled workflows:

The next pull request likely to be tested is #162028.

@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Aug 31, 2026
Add intrinsics for integer minimum and maximum



I got inspired to do this when looking at `SliceOrd::compare` where I was reminded that `if a < b { a } else { b }` isn't great in MIR since it takes 4 BBs.  Looking at the codegen side, it turns out we currently emit [42 lines of LLVM-IR including 4 `alloca`s](https://rust.godbolt.org/z/ha4h4nT3r) for `u16::max` (pre-optimization), which is also unnecessarily bad†.

But both LLVM and Cranelift have dedicated things for min & max:

- https://llvm.org/docs/LangRef.html#llvm-umax-intrinsic
- https://docs.rs/cranelift-codegen/latest/cranelift_codegen/ir/trait.InstBuilder.html#method.smin

so let's just use those directly!

This actually wouldn't have been worth doing originally, but a couple of things have happened to change that:

- Back in 1.0 there was only `cmp::min` & `cmp::max`, so there was no place to actually do this at all, but in 2017 they were added to `Ord` as overridable things #25663 (comment)
- LLVM originally used icmp+select for these, not a dedicated construct, but then added one and as of 2022 the intrinsic is fully usable https://www.npopov.com/2022/12/20/This-year-in-LLVM-2022.html#integer-minmax-intrinsics
- Before we had intrinsic fallback this would have been more annoying to support everywhere -- GCC, [128-bit numbers on cg_clif](bytecodealliance/wasmtime#13790), CTFE, anything out-of-tree -- but now that we can write the obvious fallback we don't need to worry about that.
- The intrinsic would have helped less when it forced extra BBs and `alloca`s in codegen anyway, but [now](rust-lang/compiler-team#970) we can keep the result in SSA without needing to make it a primitive.

† Admittedly we could clean up the gratuitous badness there without needing an intrinsic, but I like doing the intrinsic anyway because that's the only way to avoid it always being stuck in the non-SSA path from the multi-BB assignments.  Even if we made it inlineable, GVN and such will still just give up on seeing the `x = if a < b { a } else { b }` because it's multiple assignments to the same Local, which is non-ideal for something primitive-like.
@rust-bors rust-bors Bot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Aug 31, 2026
@rust-bors

rust-bors Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

💔 Test for b59ba1f failed: CI. Failed job:

@rdrpenguin04

Copy link
Copy Markdown

(As an observer trying to understand the Rust build system, is this kind of failure known/expected to happen sometimes? Segfaulting on installing sccache seems like a very strange way to fail)

@rust-log-analyzer

Copy link
Copy Markdown
Collaborator

A job failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)
  0      0   0      0   0      0      0      0                              0
100 19.08M 100 19.08M   0      0 147.3M      0                              0
100 19.08M 100 19.08M   0      0 147.1M      0                              0
100 19.08M 100 19.08M   0      0 146.9M      0                              0
src/ci/scripts/install-sccache.sh: line 19:  1910 Segmentation fault         curl -fo sccache/sccache.exe "${MIRRORS_BASE}/2025-02-24-sccache-v0.10.0-x86_64-pc-windows-msvc.exe"
##[error]Process completed with exit code 139.
##[group]Run echo "disk usage:"
echo "disk usage:"
df -h
shell: C:\Program Files\Git\bin\bash.EXE --noprofile --norc -e -o pipefail {0}

@clarfonthey

clarfonthey commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

There are lots of spurious issues with GitHub actions, unfortunately. Whenever they come up, we just retry the job and hope it doesn't happen again.

@clarfonthey clarfonthey removed the to-announce Announce this issue on triage meeting label Aug 31, 2026
@clarfonthey

Copy link
Copy Markdown
Contributor

@bors try jobs=x86_64-msvc-1

@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Aug 31, 2026
Add intrinsics for integer minimum and maximum


try-job: x86_64-msvc-1
@rust-bors

rust-bors Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

☀️ Try build successful (CI)
Build commit: 475f470 (475f4701ee52aacf44dbe78e603d6ce53fe49bf3)
Base parent: 4b7e3a7 (4b7e3a76d8df78960dc7c65cad43f5da1dac8ade)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. finished-final-comment-period The final comment period is finished for this PR / Issue. I-lang-radar Items that are on lang's radar and will need eventual work or consideration. perf-regression Performance regression. perf-regression-triaged The performance regression has been triaged. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-lang Relevant to the language team T-libs Relevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.