Skip to content

Commit a77322c

Browse files
committed
Auto merge of rust-lang#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 rust-lang#118310 (comment) 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 (rust-lang#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) (rust-lang#105840) is arguably even nicer, but depends on the optimizer understanding it (llvm/llvm-project#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 rust-lang@8811efa#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 (rust-lang#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.~~
2 parents 029cb1b + c59e93c commit a77322c

36 files changed

+601
-13
lines changed

compiler/rustc_codegen_cranelift/src/codegen_i128.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ pub(crate) fn maybe_codegen<'tcx>(
6868
Some(CValue::by_val(ret_val, lhs.layout()))
6969
}
7070
}
71-
BinOp::Lt | BinOp::Le | BinOp::Eq | BinOp::Ge | BinOp::Gt | BinOp::Ne => None,
71+
BinOp::Lt | BinOp::Le | BinOp::Eq | BinOp::Ge | BinOp::Gt | BinOp::Ne | BinOp::Cmp => None,
7272
BinOp::Shl | BinOp::ShlUnchecked | BinOp::Shr | BinOp::ShrUnchecked => None,
7373
}
7474
}
@@ -134,6 +134,7 @@ pub(crate) fn maybe_codegen_checked<'tcx>(
134134
BinOp::AddUnchecked | BinOp::SubUnchecked | BinOp::MulUnchecked => unreachable!(),
135135
BinOp::Offset => unreachable!("offset should only be used on pointers, not 128bit ints"),
136136
BinOp::Div | BinOp::Rem => unreachable!(),
137+
BinOp::Cmp => unreachable!(),
137138
BinOp::Lt | BinOp::Le | BinOp::Eq | BinOp::Ge | BinOp::Gt | BinOp::Ne => unreachable!(),
138139
BinOp::Shl | BinOp::ShlUnchecked | BinOp::Shr | BinOp::ShrUnchecked => unreachable!(),
139140
}

compiler/rustc_codegen_cranelift/src/num.rs

+22-2
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,33 @@ pub(crate) fn bin_op_to_intcc(bin_op: BinOp, signed: bool) -> Option<IntCC> {
4040
})
4141
}
4242

43+
fn codegen_three_way_compare<'tcx>(
44+
fx: &mut FunctionCx<'_, '_, 'tcx>,
45+
signed: bool,
46+
lhs: Value,
47+
rhs: Value,
48+
) -> CValue<'tcx> {
49+
// This emits `(lhs > rhs) - (lhs < rhs)`, which is cranelift's preferred form per
50+
// <https://github.com/bytecodealliance/wasmtime/blob/8052bb9e3b792503b225f2a5b2ba3bc023bff462/cranelift/codegen/src/prelude_opt.isle#L41-L47>
51+
let gt_cc = crate::num::bin_op_to_intcc(BinOp::Gt, signed).unwrap();
52+
let lt_cc = crate::num::bin_op_to_intcc(BinOp::Lt, signed).unwrap();
53+
let gt = fx.bcx.ins().icmp(gt_cc, lhs, rhs);
54+
let lt = fx.bcx.ins().icmp(lt_cc, lhs, rhs);
55+
let val = fx.bcx.ins().isub(gt, lt);
56+
CValue::by_val(val, fx.layout_of(fx.tcx.ty_ordering_enum(Some(fx.mir.span))))
57+
}
58+
4359
fn codegen_compare_bin_op<'tcx>(
4460
fx: &mut FunctionCx<'_, '_, 'tcx>,
4561
bin_op: BinOp,
4662
signed: bool,
4763
lhs: Value,
4864
rhs: Value,
4965
) -> CValue<'tcx> {
66+
if bin_op == BinOp::Cmp {
67+
return codegen_three_way_compare(fx, signed, lhs, rhs);
68+
}
69+
5070
let intcc = crate::num::bin_op_to_intcc(bin_op, signed).unwrap();
5171
let val = fx.bcx.ins().icmp(intcc, lhs, rhs);
5272
CValue::by_val(val, fx.layout_of(fx.tcx.types.bool))
@@ -59,7 +79,7 @@ pub(crate) fn codegen_binop<'tcx>(
5979
in_rhs: CValue<'tcx>,
6080
) -> CValue<'tcx> {
6181
match bin_op {
62-
BinOp::Eq | BinOp::Lt | BinOp::Le | BinOp::Ne | BinOp::Ge | BinOp::Gt => {
82+
BinOp::Eq | BinOp::Lt | BinOp::Le | BinOp::Ne | BinOp::Ge | BinOp::Gt | BinOp::Cmp => {
6383
match in_lhs.layout().ty.kind() {
6484
ty::Bool | ty::Uint(_) | ty::Int(_) | ty::Char => {
6585
let signed = type_sign(in_lhs.layout().ty);
@@ -160,7 +180,7 @@ pub(crate) fn codegen_int_binop<'tcx>(
160180
}
161181
BinOp::Offset => unreachable!("Offset is not an integer operation"),
162182
// Compare binops handles by `codegen_binop`.
163-
BinOp::Eq | BinOp::Ne | BinOp::Lt | BinOp::Le | BinOp::Gt | BinOp::Ge => {
183+
BinOp::Eq | BinOp::Ne | BinOp::Lt | BinOp::Le | BinOp::Gt | BinOp::Ge | BinOp::Cmp => {
164184
unreachable!("{:?}({:?}, {:?})", bin_op, in_lhs.layout().ty, in_rhs.layout().ty);
165185
}
166186
};

compiler/rustc_codegen_gcc/src/common.rs

+4
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,10 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
9494
self.const_int(self.type_i32(), i as i64)
9595
}
9696

97+
fn const_i8(&self, i: i8) -> RValue<'gcc> {
98+
self.const_int(self.type_i8(), i as i64)
99+
}
100+
97101
fn const_u32(&self, i: u32) -> RValue<'gcc> {
98102
self.const_uint(self.type_u32(), i as u64)
99103
}

compiler/rustc_codegen_llvm/src/common.rs

+4
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,10 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
160160
self.const_int(self.type_i32(), i as i64)
161161
}
162162

163+
fn const_i8(&self, i: i8) -> &'ll Value {
164+
self.const_int(self.type_i8(), i as i64)
165+
}
166+
163167
fn const_u32(&self, i: u32) -> &'ll Value {
164168
self.const_uint(self.type_i32(), i as u64)
165169
}

compiler/rustc_codegen_ssa/src/mir/rvalue.rs

+30
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use crate::common::{self, IntPredicate};
77
use crate::traits::*;
88
use crate::MemFlags;
99

10+
use rustc_hir as hir;
1011
use rustc_middle::mir;
1112
use rustc_middle::mir::Operand;
1213
use rustc_middle::ty::cast::{CastTy, IntTy};
@@ -882,6 +883,35 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
882883
bx.icmp(base::bin_op_to_icmp_predicate(op.to_hir_binop(), is_signed), lhs, rhs)
883884
}
884885
}
886+
mir::BinOp::Cmp => {
887+
use std::cmp::Ordering;
888+
debug_assert!(!is_float);
889+
let pred = |op| base::bin_op_to_icmp_predicate(op, is_signed);
890+
if bx.cx().tcx().sess.opts.optimize == OptLevel::No {
891+
// FIXME: This actually generates tighter assembly, and is a classic trick
892+
// <https://graphics.stanford.edu/~seander/bithacks.html#CopyIntegerSign>
893+
// However, as of 2023-11 it optimizes worse in things like derived
894+
// `PartialOrd`, so only use it in debug for now. Once LLVM can handle it
895+
// better (see <https://github.com/llvm/llvm-project/issues/73417>), it'll
896+
// be worth trying it in optimized builds as well.
897+
let is_gt = bx.icmp(pred(hir::BinOpKind::Gt), lhs, rhs);
898+
let gtext = bx.zext(is_gt, bx.type_i8());
899+
let is_lt = bx.icmp(pred(hir::BinOpKind::Lt), lhs, rhs);
900+
let ltext = bx.zext(is_lt, bx.type_i8());
901+
bx.unchecked_ssub(gtext, ltext)
902+
} else {
903+
// These operations are those expected by `tests/codegen/integer-cmp.rs`,
904+
// from <https://github.com/rust-lang/rust/pull/63767>.
905+
let is_lt = bx.icmp(pred(hir::BinOpKind::Lt), lhs, rhs);
906+
let is_ne = bx.icmp(pred(hir::BinOpKind::Ne), lhs, rhs);
907+
let ge = bx.select(
908+
is_ne,
909+
bx.cx().const_i8(Ordering::Greater as i8),
910+
bx.cx().const_i8(Ordering::Equal as i8),
911+
);
912+
bx.select(is_lt, bx.cx().const_i8(Ordering::Less as i8), ge)
913+
}
914+
}
885915
}
886916
}
887917

compiler/rustc_codegen_ssa/src/traits/consts.rs

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pub trait ConstMethods<'tcx>: BackendTypes {
1919
fn const_bool(&self, val: bool) -> Self::Value;
2020
fn const_i16(&self, i: i16) -> Self::Value;
2121
fn const_i32(&self, i: i32) -> Self::Value;
22+
fn const_i8(&self, i: i8) -> Self::Value;
2223
fn const_u32(&self, i: u32) -> Self::Value;
2324
fn const_u64(&self, i: u64) -> Self::Value;
2425
fn const_u128(&self, i: u128) -> Self::Value;

compiler/rustc_const_eval/src/interpret/operand.rs

+7
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,13 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
235235
Self::from_scalar(Scalar::from_bool(b), layout)
236236
}
237237

238+
#[inline]
239+
pub fn from_ordering(c: std::cmp::Ordering, tcx: TyCtxt<'tcx>) -> Self {
240+
let ty = tcx.ty_ordering_enum(None);
241+
let layout = tcx.layout_of(ty::ParamEnv::reveal_all().and(ty)).unwrap();
242+
Self::from_scalar(Scalar::from_i8(c as i8), layout)
243+
}
244+
238245
#[inline]
239246
pub fn to_const_int(self) -> ConstInt {
240247
assert!(self.layout.ty.is_integral());

compiler/rustc_const_eval/src/interpret/operator.rs

+18
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
6161
}
6262

6363
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
64+
fn three_way_compare<T: Ord>(&self, lhs: T, rhs: T) -> (ImmTy<'tcx, M::Provenance>, bool) {
65+
let res = Ord::cmp(&lhs, &rhs);
66+
return (ImmTy::from_ordering(res, *self.tcx), false);
67+
}
68+
6469
fn binary_char_op(
6570
&self,
6671
bin_op: mir::BinOp,
@@ -69,6 +74,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
6974
) -> (ImmTy<'tcx, M::Provenance>, bool) {
7075
use rustc_middle::mir::BinOp::*;
7176

77+
if bin_op == Cmp {
78+
return self.three_way_compare(l, r);
79+
}
80+
7281
let res = match bin_op {
7382
Eq => l == r,
7483
Ne => l != r,
@@ -231,6 +240,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
231240
let r = self.sign_extend(r, right_layout) as i128;
232241
return Ok((ImmTy::from_bool(op(&l, &r), *self.tcx), false));
233242
}
243+
if bin_op == Cmp {
244+
let l = self.sign_extend(l, left_layout) as i128;
245+
let r = self.sign_extend(r, right_layout) as i128;
246+
return Ok(self.three_way_compare(l, r));
247+
}
234248
let op: Option<fn(i128, i128) -> (i128, bool)> = match bin_op {
235249
Div if r == 0 => throw_ub!(DivisionByZero),
236250
Rem if r == 0 => throw_ub!(RemainderByZero),
@@ -270,6 +284,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
270284
}
271285
}
272286

287+
if bin_op == Cmp {
288+
return Ok(self.three_way_compare(l, r));
289+
}
290+
273291
let val = match bin_op {
274292
Eq => ImmTy::from_bool(l == r, *self.tcx),
275293
Ne => ImmTy::from_bool(l != r, *self.tcx),

compiler/rustc_const_eval/src/transform/validate.rs

+9
Original file line numberDiff line numberDiff line change
@@ -986,6 +986,15 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
986986
)
987987
}
988988
}
989+
Cmp => {
990+
for x in [a, b] {
991+
check_kinds!(
992+
x,
993+
"Cannot three-way compare non-integer type {:?}",
994+
ty::Char | ty::Uint(..) | ty::Int(..)
995+
)
996+
}
997+
}
989998
AddUnchecked | SubUnchecked | MulUnchecked | Shl | ShlUnchecked | Shr
990999
| ShrUnchecked => {
9911000
for x in [a, b] {

compiler/rustc_const_eval/src/util/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub fn binop_left_homogeneous(op: mir::BinOp) -> bool {
1919
match op {
2020
Add | AddUnchecked | Sub | SubUnchecked | Mul | MulUnchecked | Div | Rem | BitXor
2121
| BitAnd | BitOr | Offset | Shl | ShlUnchecked | Shr | ShrUnchecked => true,
22-
Eq | Ne | Lt | Le | Gt | Ge => false,
22+
Eq | Ne | Lt | Le | Gt | Ge | Cmp => false,
2323
}
2424
}
2525

@@ -30,7 +30,7 @@ pub fn binop_right_homogeneous(op: mir::BinOp) -> bool {
3030
use rustc_middle::mir::BinOp::*;
3131
match op {
3232
Add | AddUnchecked | Sub | SubUnchecked | Mul | MulUnchecked | Div | Rem | BitXor
33-
| BitAnd | BitOr | Eq | Ne | Lt | Le | Gt | Ge => true,
33+
| BitAnd | BitOr | Eq | Ne | Lt | Le | Gt | Ge | Cmp => true,
3434
Offset | Shl | ShlUnchecked | Shr | ShrUnchecked => false,
3535
}
3636
}

compiler/rustc_hir/src/lang_items.rs

+1
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ language_item_table! {
226226
Unpin, sym::unpin, unpin_trait, Target::Trait, GenericRequirement::None;
227227
Pin, sym::pin, pin_type, Target::Struct, GenericRequirement::None;
228228

229+
OrderingEnum, sym::Ordering, ordering_enum, Target::Enum, GenericRequirement::Exact(0);
229230
PartialEq, sym::eq, eq_trait, Target::Trait, GenericRequirement::Exact(1);
230231
PartialOrd, sym::partial_ord, partial_ord_trait, Target::Trait, GenericRequirement::Exact(1);
231232
CVoid, sym::c_void, c_void, Target::Enum, GenericRequirement::None;

compiler/rustc_hir_analysis/src/check/intrinsic.rs

+5
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -
107107
| sym::cttz
108108
| sym::bswap
109109
| sym::bitreverse
110+
| sym::three_way_compare
110111
| sym::discriminant_value
111112
| sym::type_id
112113
| sym::likely
@@ -418,6 +419,10 @@ pub fn check_intrinsic_type(
418419
| sym::bswap
419420
| sym::bitreverse => (1, 0, vec![param(0)], param(0)),
420421

422+
sym::three_way_compare => {
423+
(1, 0, vec![param(0), param(0)], tcx.ty_ordering_enum(Some(span)))
424+
}
425+
421426
sym::add_with_overflow | sym::sub_with_overflow | sym::mul_with_overflow => {
422427
(1, 0, vec![param(0), param(0)], Ty::new_tup(tcx, &[param(0), tcx.types.bool]))
423428
}

compiler/rustc_middle/src/mir/syntax.rs

+10
Original file line numberDiff line numberDiff line change
@@ -1438,6 +1438,16 @@ pub enum BinOp {
14381438
Ge,
14391439
/// The `>` operator (greater than)
14401440
Gt,
1441+
/// The `<=>` operator (three-way comparison, like `Ord::cmp`)
1442+
///
1443+
/// This is supported only on the integer types and `char`, always returning
1444+
/// [`rustc_hir::LangItem::OrderingEnum`] (aka [`std::cmp::Ordering`]).
1445+
///
1446+
/// [`Rvalue::BinaryOp`]`(BinOp::Cmp, A, B)` returns
1447+
/// - `Ordering::Less` (`-1_i8`, as a Scalar) if `A < B`
1448+
/// - `Ordering::Equal` (`0_i8`, as a Scalar) if `A == B`
1449+
/// - `Ordering::Greater` (`+1_i8`, as a Scalar) if `A > B`
1450+
Cmp,
14411451
/// The `ptr.offset` operator
14421452
Offset,
14431453
}

compiler/rustc_middle/src/mir/tcx.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,11 @@ impl<'tcx> BinOp {
276276
&BinOp::Eq | &BinOp::Lt | &BinOp::Le | &BinOp::Ne | &BinOp::Ge | &BinOp::Gt => {
277277
tcx.types.bool
278278
}
279+
&BinOp::Cmp => {
280+
// these should be integer-like types of the same size.
281+
assert_eq!(lhs_ty, rhs_ty);
282+
tcx.ty_ordering_enum(None)
283+
}
279284
}
280285
}
281286
}
@@ -312,7 +317,8 @@ impl BinOp {
312317
BinOp::Gt => hir::BinOpKind::Gt,
313318
BinOp::Le => hir::BinOpKind::Le,
314319
BinOp::Ge => hir::BinOpKind::Ge,
315-
BinOp::AddUnchecked
320+
BinOp::Cmp
321+
| BinOp::AddUnchecked
316322
| BinOp::SubUnchecked
317323
| BinOp::MulUnchecked
318324
| BinOp::ShlUnchecked

compiler/rustc_middle/src/ty/context.rs

+7
Original file line numberDiff line numberDiff line change
@@ -956,6 +956,13 @@ impl<'tcx> TyCtxt<'tcx> {
956956
self.get_lang_items(())
957957
}
958958

959+
/// Gets a `Ty` representing the [`LangItem::OrderingEnum`]
960+
#[track_caller]
961+
pub fn ty_ordering_enum(self, span: Option<Span>) -> Ty<'tcx> {
962+
let ordering_enum = self.require_lang_item(hir::LangItem::OrderingEnum, span);
963+
self.type_of(ordering_enum).no_bound_vars().unwrap()
964+
}
965+
959966
/// Obtain the given diagnostic item's `DefId`. Use `is_diagnostic_item` if you just want to
960967
/// compare against another `DefId`, since `is_diagnostic_item` is cheaper.
961968
pub fn get_diagnostic_item(self, name: Symbol) -> Option<DefId> {

compiler/rustc_mir_transform/src/lower_intrinsics.rs

+2
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
9090
sym::wrapping_add
9191
| sym::wrapping_sub
9292
| sym::wrapping_mul
93+
| sym::three_way_compare
9394
| sym::unchecked_add
9495
| sym::unchecked_sub
9596
| sym::unchecked_mul
@@ -109,6 +110,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
109110
sym::wrapping_add => BinOp::Add,
110111
sym::wrapping_sub => BinOp::Sub,
111112
sym::wrapping_mul => BinOp::Mul,
113+
sym::three_way_compare => BinOp::Cmp,
112114
sym::unchecked_add => BinOp::AddUnchecked,
113115
sym::unchecked_sub => BinOp::SubUnchecked,
114116
sym::unchecked_mul => BinOp::MulUnchecked,

compiler/rustc_mir_transform/src/promote_consts.rs

+1
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,7 @@ impl<'tcx> Validator<'_, 'tcx> {
525525
| BinOp::Lt
526526
| BinOp::Ge
527527
| BinOp::Gt
528+
| BinOp::Cmp
528529
| BinOp::Offset
529530
| BinOp::Add
530531
| BinOp::AddUnchecked

compiler/rustc_smir/src/rustc_smir/convert/mir.rs

+1
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,7 @@ impl<'tcx> Stable<'tcx> for mir::BinOp {
493493
BinOp::Ne => stable_mir::mir::BinOp::Ne,
494494
BinOp::Ge => stable_mir::mir::BinOp::Ge,
495495
BinOp::Gt => stable_mir::mir::BinOp::Gt,
496+
BinOp::Cmp => stable_mir::mir::BinOp::Cmp,
496497
BinOp::Offset => stable_mir::mir::BinOp::Offset,
497498
}
498499
}

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1813,6 +1813,7 @@ symbols! {
18131813
thread,
18141814
thread_local,
18151815
thread_local_macro,
1816+
three_way_compare,
18161817
thumb2,
18171818
thumb_mode: "thumb-mode",
18181819
tmm_reg,

compiler/rustc_ty_utils/src/consts.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ fn check_binop(op: mir::BinOp) -> bool {
8282
match op {
8383
Add | AddUnchecked | Sub | SubUnchecked | Mul | MulUnchecked | Div | Rem | BitXor
8484
| BitAnd | BitOr | Shl | ShlUnchecked | Shr | ShrUnchecked | Eq | Lt | Le | Ne | Ge
85-
| Gt => true,
85+
| Gt | Cmp => true,
8686
Offset => false,
8787
}
8888
}

compiler/stable_mir/src/mir/body.rs

+4
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ pub enum BinOp {
329329
Ne,
330330
Ge,
331331
Gt,
332+
Cmp,
332333
Offset,
333334
}
334335

@@ -368,6 +369,9 @@ impl BinOp {
368369
assert!(lhs_kind.is_primitive() || lhs_kind.is_raw_ptr() || lhs_kind.is_fn_ptr());
369370
Ty::bool_ty()
370371
}
372+
BinOp::Cmp => {
373+
unimplemented!("Should cmp::Ordering be a RigidTy?");
374+
}
371375
}
372376
}
373377
}

0 commit comments

Comments
 (0)