rust/compiler/rustc_mir_transform/src
bors a77322c16f Auto merge of #118310 - scottmcm:three-way-compare, r=davidtwco
Add `Ord::cmp` for primitives as a `BinOp` in MIR

Update: most of this OP was written months ago.  See https://github.com/rust-lang/rust/pull/118310#issuecomment-2016940014 below for where we got to recently that made it ready for review.

---

There are dozens of reasonable ways to implement `Ord::cmp` for integers using comparison, bit-ops, and branches.  Those differences are irrelevant at the rust level, however, so we can make things better by adding `BinOp::Cmp` at the MIR level:

1. Exactly how to implement it is left up to the backends, so LLVM can use whatever pattern its optimizer best recognizes and cranelift can use whichever pattern codegens the fastest.
2. By not inlining those details for every use of `cmp`, we drastically reduce the amount of MIR generated for `derive`d `PartialOrd`, while also making it more amenable to MIR-level optimizations.

Having extremely careful `if` ordering to μoptimize resource usage on broadwell (#63767) is great, but it really feels to me like libcore is the wrong place to put that logic.  Similarly, using subtraction [tricks](https://graphics.stanford.edu/~seander/bithacks.html#CopyIntegerSign) (#105840) is arguably even nicer, but depends on the optimizer understanding it (https://github.com/llvm/llvm-project/issues/73417) to be practical.  Or maybe [bitor is better than add](https://discourse.llvm.org/t/representing-in-ir/67369/2?u=scottmcm)?  But maybe only on a future version that [has `or disjoint` support](https://discourse.llvm.org/t/rfc-add-or-disjoint-flag/75036?u=scottmcm)?  And just because one of those forms happens to be good for LLVM, there's no guarantee that it'd be the same form that GCC or Cranelift would rather see -- especially given their very different optimizers.  Not to mention that if LLVM gets a spaceship intrinsic -- [which it should](https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/Suboptimal.20inlining.20in.20std.20function.20.60binary_search.60/near/404250586) -- we'll need at least a rustc intrinsic to be able to call it.

As for simplifying it in Rust, we now regularly inline `{integer}::partial_cmp`, but it's quite a large amount of IR.  The best way to see that is with 8811efa88b (diff-d134c32d028fbe2bf835fef2df9aca9d13332dd82284ff21ee7ebf717bfa4765R113) -- I added a new pre-codegen MIR test for a simple 3-tuple struct, and this PR change it from 36 locals and 26 basic blocks down to 24 locals and 8 basic blocks.  Even better, as soon as the construct-`Some`-then-match-it-in-same-BB noise is cleaned up, this'll expose the `Cmp == 0` branches clearly in MIR, so that an InstCombine (#105808) can simplify that to just a `BinOp::Eq` and thus fix some of our generated code perf issues.  (Tracking that through today's `if a < b { Less } else if a == b { Equal } else { Greater }` would be *much* harder.)

---

r? `@ghost`
But first I should check that perf is ok with this
~~...and my true nemesis, tidy.~~
2024-04-02 19:21:44 +00:00
..
coroutine Avoid an is_empty() followed by an index op in favor of a single fallible op 2024-04-02 14:13:05 +00:00
coverage Replace RemapFileNameExt::for_codegen with explicit calls 2024-03-28 18:47:26 +01:00
inline Dejargnonize subst 2024-02-12 15:46:35 +09:00
abort_unwinding_calls.rs Fix mir pass ICE in the presence of other errors 2024-02-08 14:49:27 +00:00
add_call_guards.rs remove redundant imports 2023-12-10 10:56:22 +08:00
add_moves_for_packed_drops.rs remove redundant imports 2023-12-10 10:56:22 +08:00
add_retag.rs add_retag: ensure box-to-raw-ptr casts are preserved for Miri 2024-03-18 10:32:25 +01:00
add_subtyping_projections.rs remove redundant imports 2023-12-10 10:56:22 +08:00
check_alignment.rs Eagerly convert some ctors to use their specialized ctors 2024-03-22 11:12:01 -04:00
check_const_item_mutation.rs Rename TyCtxt::emit_spanned_lint as TyCtxt::emit_node_span_lint. 2024-01-23 08:09:05 +11:00
check_packed_ref.rs Remove Session methods that duplicate DiagCtxt methods. 2023-12-24 08:05:28 +11:00
check_unsafety.rs Rename mir_const query to mir_built 2024-03-20 09:05:22 +00:00
cleanup_post_borrowck.rs Unbox and unwrap the contents of StatementKind::Coverage 2024-03-23 22:05:11 +11:00
const_debuginfo.rs Format all the let chains in compiler 2023-10-13 08:59:36 +00:00
copy_prop.rs remove redundant imports 2023-12-10 10:56:22 +08:00
coroutine.rs and more 2024-03-28 17:19:15 +03:00
cost_checker.rs Make is_intrinsic query return the intrinsic name 2024-02-12 09:33:52 +00:00
cross_crate_inline.rs Remove all checks of IntrinsicDef::must_be_overridden except for the actual overrides in codegen 2024-03-19 09:19:58 +00:00
ctfe_limit.rs Fix clippy::needless_borrow in the compiler 2023-11-21 20:13:40 +01:00
dataflow_const_prop.rs Rollup merge of #122784 - jswrenn:tag_for_variant, r=compiler-errors 2024-03-22 20:31:29 +01:00
dead_store_elimination.rs Auto merge of #116520 - Enselic:large-copy-into-fn, r=oli-obk 2024-01-16 19:33:14 +00:00
deduce_param_attrs.rs Dejargnonize subst 2024-02-12 15:46:35 +09:00
deduplicate_blocks.rs Merge dead bb pruning and unreachable bb deduplication. 2024-01-07 15:12:10 +00:00
deref_separator.rs remove redundant imports 2023-12-10 10:56:22 +08:00
dest_prop.rs Implement asm goto in MIR and MIR lowering 2024-02-24 18:50:09 +00:00
dump_mir.rs Write to stdout if - is given as output file 2023-06-06 17:53:29 -04:00
early_otherwise_branch.rs Merge dead bb pruning and unreachable bb deduplication. 2024-01-07 15:12:10 +00:00
elaborate_box_derefs.rs remove redundant imports 2023-12-10 10:56:22 +08:00
elaborate_drops.rs Convert delayed_bugs to bugs. 2024-02-21 10:20:05 +11:00
errors.rs Rename DecorateLint as LintDiagnostic. 2024-03-11 10:04:50 +11:00
ffi_unwind_calls.rs Rename mir_const query to mir_built 2024-03-20 09:05:22 +00:00
function_item_references.rs Make RawPtr take Ty and Mutbl separately 2024-03-22 11:13:29 -04:00
gvn.rs refactor check_{lang,library}_ub: use a single intrinsic, put policy into library 2024-03-23 18:45:05 +01:00
inline.rs Instance is Copy 2024-03-25 13:58:40 -04:00
instsimplify.rs Eliminate UbCheck for non-standard libraries 2024-03-27 21:02:40 +08:00
jump_threading.rs Rollup merge of #122784 - jswrenn:tag_for_variant, r=compiler-errors 2024-03-22 20:31:29 +01:00
known_panics_lint.rs refactor check_{lang,library}_ub: use a single intrinsic, put policy into library 2024-03-23 18:45:05 +01:00
large_enums.rs Fix some comments 2023-12-28 12:23:14 +08:00
lib.rs Auto merge of #122721 - oli-obk:merge_queries, r=davidtwco 2024-03-25 01:33:46 +00:00
lint.rs compiler: Lower fn call arg spans down to MIR 2024-01-15 19:07:11 +01:00
lower_intrinsics.rs Add+Use mir::BinOp::Cmp 2024-03-23 23:23:41 -07:00
lower_slice_len.rs compiler: Lower fn call arg spans down to MIR 2024-01-15 19:07:11 +01:00
match_branches.rs Merge dead bb pruning and unreachable bb deduplication. 2024-01-07 15:12:10 +00:00
mentioned_items.rs mentioned_items: avoid adding str/slice unsizing casts 2024-03-20 11:16:11 +01:00
multiple_return_terminators.rs remove redundant imports 2023-12-10 10:56:22 +08:00
normalize_array_len.rs remove redundant imports 2023-12-10 10:56:22 +08:00
nrvo.rs and more 2024-03-28 17:19:15 +03:00
pass_manager.rs Only split by-ref/by-move futures for async closures 2024-03-19 16:59:23 -04:00
prettify.rs remove redundant imports 2023-12-10 10:56:22 +08:00
promote_consts.rs Add+Use mir::BinOp::Cmp 2024-03-23 23:23:41 -07:00
ref_prop.rs Dejargnonize subst 2024-02-12 15:46:35 +09:00
remove_noop_landing_pads.rs Avoid debug logging entire MIR body 2024-02-15 15:54:28 +01:00
remove_place_mention.rs remove redundant imports 2023-12-10 10:56:22 +08:00
remove_storage_markers.rs Move condition enabling the pass to is_enabled 2024-01-23 20:58:44 +01:00
remove_uninit_drops.rs remove redundant imports 2023-12-10 10:56:22 +08:00
remove_unneeded_drops.rs Merge dead bb pruning and unreachable bb deduplication. 2024-01-07 15:12:10 +00:00
remove_zsts.rs Add CoroutineClosure to TyKind, AggregateKind, UpvarArgs 2024-02-06 02:22:58 +00:00
required_consts.rs rename mir::Constant -> mir::ConstOperand, mir::ConstKind -> mir::Const 2023-09-21 08:12:30 +02:00
reveal_all.rs remove redundant imports 2023-12-10 10:56:22 +08:00
shim.rs In ConstructCoroutineInClosureShim, pass receiver by ref, not pointer 2024-03-26 12:10:51 -04:00
simplify.rs simplify_cfg: rename some passes so that they make more sense 2024-03-17 19:59:15 +01:00
simplify_branches.rs simplify_branches: add comment 2024-03-24 12:53:03 +01:00
simplify_comparison_integral.rs rename mir::Constant -> mir::ConstOperand, mir::ConstKind -> mir::Const 2023-09-21 08:12:30 +02:00
sroa.rs remove redundant imports 2023-12-10 10:56:22 +08:00
ssa.rs Remove unused fields in some structures 2024-03-12 10:59:40 +01:00
uninhabited_enum_branching.rs Add a workaround for the TailDuplicator compile time overhead 2024-03-08 08:15:18 +08:00
unreachable_prop.rs coverage: Re-enable UnreachablePropagation for coverage builds 2024-03-26 11:46:04 +11:00