Add chaining versions of lt/le/gt/ge and use them in tuple PartialOrd
This commit is contained in:
parent
b54ca0e433
commit
35248c6830
5 changed files with 174 additions and 329 deletions
|
@ -29,6 +29,7 @@ mod bytewise;
|
|||
pub(crate) use bytewise::BytewiseEq;
|
||||
|
||||
use self::Ordering::*;
|
||||
use crate::ops::ControlFlow::{self, Break, Continue};
|
||||
|
||||
/// Trait for comparisons using the equality operator.
|
||||
///
|
||||
|
@ -1446,6 +1447,54 @@ pub macro PartialOrd($item:item) {
|
|||
/* compiler built-in */
|
||||
}
|
||||
|
||||
/// Helpers for chaining together field PartialOrds into the full type's ordering.
|
||||
///
|
||||
/// If the two values are equal, returns `ControlFlow::Continue`.
|
||||
/// If the two values are not equal, returns `ControlFlow::Break(self OP other)`.
|
||||
///
|
||||
/// This allows simple types like `i32` and `f64` to just emit two comparisons
|
||||
/// directly, instead of needing to optimize the 3-way comparison.
|
||||
///
|
||||
/// Currently this is done using specialization, but it doesn't need that:
|
||||
/// it could be provided methods on `PartialOrd` instead and work fine.
|
||||
pub(crate) trait SpecChainingPartialOrd<Rhs>: PartialOrd<Rhs> {
|
||||
fn spec_chain_lt(&self, other: &Rhs) -> ControlFlow<bool>;
|
||||
fn spec_chain_le(&self, other: &Rhs) -> ControlFlow<bool>;
|
||||
fn spec_chain_gt(&self, other: &Rhs) -> ControlFlow<bool>;
|
||||
fn spec_chain_ge(&self, other: &Rhs) -> ControlFlow<bool>;
|
||||
}
|
||||
|
||||
impl<T: PartialOrd<U>, U> SpecChainingPartialOrd<U> for T {
|
||||
#[inline]
|
||||
default fn spec_chain_lt(&self, other: &U) -> ControlFlow<bool> {
|
||||
match PartialOrd::partial_cmp(self, other) {
|
||||
Some(Equal) => Continue(()),
|
||||
c => Break(c.is_some_and(Ordering::is_lt)),
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
default fn spec_chain_le(&self, other: &U) -> ControlFlow<bool> {
|
||||
match PartialOrd::partial_cmp(self, other) {
|
||||
Some(Equal) => Continue(()),
|
||||
c => Break(c.is_some_and(Ordering::is_le)),
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
default fn spec_chain_gt(&self, other: &U) -> ControlFlow<bool> {
|
||||
match PartialOrd::partial_cmp(self, other) {
|
||||
Some(Equal) => Continue(()),
|
||||
c => Break(c.is_some_and(Ordering::is_gt)),
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
default fn spec_chain_ge(&self, other: &U) -> ControlFlow<bool> {
|
||||
match PartialOrd::partial_cmp(self, other) {
|
||||
Some(Equal) => Continue(()),
|
||||
c => Break(c.is_some_and(Ordering::is_ge)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Compares and returns the minimum of two values.
|
||||
///
|
||||
/// Returns the first argument if the comparison determines them to be equal.
|
||||
|
@ -1741,6 +1790,7 @@ where
|
|||
mod impls {
|
||||
use crate::cmp::Ordering::{self, Equal, Greater, Less};
|
||||
use crate::hint::unreachable_unchecked;
|
||||
use crate::ops::ControlFlow::{self, Break, Continue};
|
||||
|
||||
macro_rules! partial_eq_impl {
|
||||
($($t:ty)*) => ($(
|
||||
|
@ -1779,6 +1829,36 @@ mod impls {
|
|||
|
||||
eq_impl! { () bool char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
|
||||
|
||||
macro_rules! chaining_impl {
|
||||
($t:ty) => {
|
||||
// These implementations are the same for `Ord` or `PartialOrd` types
|
||||
// because if either is NAN the `==` test will fail so we end up in
|
||||
// the `Break` case and the comparison will correctly return `false`.
|
||||
impl super::SpecChainingPartialOrd<$t> for $t {
|
||||
#[inline]
|
||||
fn spec_chain_lt(&self, other: &Self) -> ControlFlow<bool> {
|
||||
let (lhs, rhs) = (*self, *other);
|
||||
if lhs == rhs { Continue(()) } else { Break(lhs < rhs) }
|
||||
}
|
||||
#[inline]
|
||||
fn spec_chain_le(&self, other: &Self) -> ControlFlow<bool> {
|
||||
let (lhs, rhs) = (*self, *other);
|
||||
if lhs == rhs { Continue(()) } else { Break(lhs <= rhs) }
|
||||
}
|
||||
#[inline]
|
||||
fn spec_chain_gt(&self, other: &Self) -> ControlFlow<bool> {
|
||||
let (lhs, rhs) = (*self, *other);
|
||||
if lhs == rhs { Continue(()) } else { Break(lhs > rhs) }
|
||||
}
|
||||
#[inline]
|
||||
fn spec_chain_ge(&self, other: &Self) -> ControlFlow<bool> {
|
||||
let (lhs, rhs) = (*self, *other);
|
||||
if lhs == rhs { Continue(()) } else { Break(lhs >= rhs) }
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! partial_ord_impl {
|
||||
($($t:ty)*) => ($(
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -1801,6 +1881,8 @@ mod impls {
|
|||
#[inline(always)]
|
||||
fn gt(&self, other: &$t) -> bool { (*self) > (*other) }
|
||||
}
|
||||
|
||||
chaining_impl!($t);
|
||||
)*)
|
||||
}
|
||||
|
||||
|
@ -1840,6 +1922,8 @@ mod impls {
|
|||
fn gt(&self, other: &$t) -> bool { (*self) > (*other) }
|
||||
}
|
||||
|
||||
chaining_impl!($t);
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Ord for $t {
|
||||
#[inline]
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
// See core/src/primitive_docs.rs for documentation.
|
||||
|
||||
use crate::cmp::Ordering::{self, *};
|
||||
use crate::cmp::SpecChainingPartialOrd;
|
||||
use crate::marker::{ConstParamTy_, StructuralPartialEq, UnsizedConstParamTy};
|
||||
use crate::ops::ControlFlow::{Break, Continue};
|
||||
|
||||
// Recursive macro for implementing n-ary tuple functions and operations
|
||||
//
|
||||
|
@ -80,19 +82,19 @@ macro_rules! tuple_impls {
|
|||
}
|
||||
#[inline]
|
||||
fn lt(&self, other: &($($T,)+)) -> bool {
|
||||
lexical_ord!(lt, Less, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
|
||||
lexical_ord!(lt, spec_chain_lt, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
|
||||
}
|
||||
#[inline]
|
||||
fn le(&self, other: &($($T,)+)) -> bool {
|
||||
lexical_ord!(le, Less, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
|
||||
lexical_ord!(le, spec_chain_le, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
|
||||
}
|
||||
#[inline]
|
||||
fn ge(&self, other: &($($T,)+)) -> bool {
|
||||
lexical_ord!(ge, Greater, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
|
||||
lexical_ord!(ge, spec_chain_ge, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
|
||||
}
|
||||
#[inline]
|
||||
fn gt(&self, other: &($($T,)+)) -> bool {
|
||||
lexical_ord!(gt, Greater, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
|
||||
lexical_ord!(gt, spec_chain_gt, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -171,15 +173,16 @@ macro_rules! maybe_tuple_doc {
|
|||
// `(a1, a2, a3) < (b1, b2, b3)` would be `lexical_ord!(lt, opt_is_lt, a1, b1,
|
||||
// a2, b2, a3, b3)` (and similarly for `lexical_cmp`)
|
||||
//
|
||||
// `$ne_rel` is only used to determine the result after checking that they're
|
||||
// not equal, so `lt` and `le` can both just use `Less`.
|
||||
// `$chain_rel` is the method from `SpecChainingPartialOrd` to use for all but the
|
||||
// final value, to produce better results for simple primitives.
|
||||
macro_rules! lexical_ord {
|
||||
($rel: ident, $ne_rel: ident, $a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {{
|
||||
let c = PartialOrd::partial_cmp(&$a, &$b);
|
||||
if c != Some(Equal) { c == Some($ne_rel) }
|
||||
else { lexical_ord!($rel, $ne_rel, $($rest_a, $rest_b),+) }
|
||||
($rel: ident, $chain_rel: ident, $a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {{
|
||||
match SpecChainingPartialOrd::$chain_rel(&$a, &$b) {
|
||||
Break(val) => val,
|
||||
Continue(()) => lexical_ord!($rel, $chain_rel, $($rest_a, $rest_b),+),
|
||||
}
|
||||
}};
|
||||
($rel: ident, $ne_rel: ident, $a:expr, $b:expr) => {
|
||||
($rel: ident, $chain_rel: ident, $a:expr, $b:expr) => {
|
||||
// Use the specific method for the last element
|
||||
PartialOrd::$rel(&$a, &$b)
|
||||
};
|
||||
|
|
|
@ -4,234 +4,67 @@ fn demo_ge_partial(_1: &(f32, f32), _2: &(f32, f32)) -> bool {
|
|||
debug a => _1;
|
||||
debug b => _2;
|
||||
let mut _0: bool;
|
||||
scope 1 (inlined std::cmp::impls::<impl PartialOrd for &(f32, f32)>::le) {
|
||||
scope 2 (inlined core::tuple::<impl PartialOrd for (f32, f32)>::le) {
|
||||
let mut _12: bool;
|
||||
let _15: std::option::Option<std::cmp::Ordering>;
|
||||
let _19: &f32;
|
||||
let _20: &f32;
|
||||
scope 1 (inlined std::cmp::impls::<impl PartialOrd for &(f32, f32)>::ge) {
|
||||
scope 2 (inlined core::tuple::<impl PartialOrd for (f32, f32)>::ge) {
|
||||
let mut _7: std::ops::ControlFlow<bool>;
|
||||
let _8: bool;
|
||||
scope 3 {
|
||||
let mut _9: &std::option::Option<std::cmp::Ordering>;
|
||||
let mut _13: &std::option::Option<std::cmp::Ordering>;
|
||||
scope 4 (inlined <Option<std::cmp::Ordering> as PartialEq>::ne) {
|
||||
let mut _11: bool;
|
||||
scope 5 (inlined <Option<std::cmp::Ordering> as PartialEq>::eq) {
|
||||
let mut _10: isize;
|
||||
let mut _16: isize;
|
||||
scope 6 {
|
||||
scope 7 (inlined <std::cmp::Ordering as PartialEq>::eq) {
|
||||
let _17: i8;
|
||||
scope 8 {
|
||||
let _18: i8;
|
||||
scope 9 {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
scope 10 (inlined <Option<std::cmp::Ordering> as PartialEq>::eq) {
|
||||
let mut _14: isize;
|
||||
let mut _21: isize;
|
||||
scope 11 {
|
||||
scope 12 (inlined <std::cmp::Ordering as PartialEq>::eq) {
|
||||
let _22: i8;
|
||||
scope 13 {
|
||||
let _23: i8;
|
||||
scope 14 {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
scope 15 (inlined std::cmp::impls::<impl PartialOrd for f32>::partial_cmp) {
|
||||
scope 4 (inlined std::cmp::impls::<impl std::cmp::SpecChainingPartialOrd<f32> for f32>::spec_chain_ge) {
|
||||
let mut _3: f32;
|
||||
let mut _4: f32;
|
||||
let mut _5: bool;
|
||||
let mut _6: f32;
|
||||
let mut _7: f32;
|
||||
let mut _8: bool;
|
||||
let mut _6: bool;
|
||||
scope 5 {
|
||||
}
|
||||
}
|
||||
scope 6 (inlined std::cmp::impls::<impl PartialOrd for f32>::ge) {
|
||||
let mut _9: f32;
|
||||
let mut _10: f32;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_19);
|
||||
StorageLive(_20);
|
||||
StorageLive(_13);
|
||||
StorageLive(_9);
|
||||
StorageLive(_15);
|
||||
StorageLive(_5);
|
||||
StorageLive(_8);
|
||||
StorageLive(_3);
|
||||
_3 = copy ((*_1).0: f32);
|
||||
StorageLive(_4);
|
||||
_4 = copy ((*_2).0: f32);
|
||||
_5 = Le(move _3, move _4);
|
||||
StorageDead(_4);
|
||||
StorageDead(_3);
|
||||
StorageLive(_6);
|
||||
_6 = copy ((*_1).0: f32);
|
||||
StorageLive(_7);
|
||||
_7 = copy ((*_2).0: f32);
|
||||
_8 = Ge(move _6, move _7);
|
||||
StorageDead(_7);
|
||||
StorageDead(_6);
|
||||
switchInt(copy _5) -> [0: bb1, otherwise: bb5];
|
||||
StorageLive(_3);
|
||||
StorageLive(_4);
|
||||
_3 = copy ((*_1).0: f32);
|
||||
_4 = copy ((*_2).0: f32);
|
||||
StorageLive(_5);
|
||||
_5 = Eq(copy _3, copy _4);
|
||||
switchInt(move _5) -> [0: bb1, otherwise: bb2];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
switchInt(copy _8) -> [0: bb2, otherwise: bb4];
|
||||
StorageLive(_6);
|
||||
_6 = Ge(copy _3, copy _4);
|
||||
_7 = ControlFlow::<bool>::Break(move _6);
|
||||
StorageDead(_6);
|
||||
StorageDead(_5);
|
||||
StorageDead(_4);
|
||||
StorageDead(_3);
|
||||
_8 = copy ((_7 as Break).0: bool);
|
||||
_0 = copy _8;
|
||||
goto -> bb3;
|
||||
}
|
||||
|
||||
bb2: {
|
||||
StorageDead(_8);
|
||||
StorageDead(_5);
|
||||
StorageLive(_12);
|
||||
_9 = const core::tuple::<impl std::cmp::PartialOrd for (f32, f32)>::le::promoted[1];
|
||||
StorageLive(_11);
|
||||
StorageLive(_16);
|
||||
StorageDead(_4);
|
||||
StorageDead(_3);
|
||||
StorageLive(_9);
|
||||
_9 = copy ((*_1).1: f32);
|
||||
StorageLive(_10);
|
||||
_10 = discriminant((*_9));
|
||||
_11 = Eq(copy _10, const 0_isize);
|
||||
_10 = copy ((*_2).1: f32);
|
||||
_0 = Ge(move _9, move _10);
|
||||
StorageDead(_10);
|
||||
StorageDead(_16);
|
||||
_12 = Not(move _11);
|
||||
StorageDead(_11);
|
||||
switchInt(move _12) -> [0: bb11, otherwise: bb3];
|
||||
StorageDead(_9);
|
||||
goto -> bb3;
|
||||
}
|
||||
|
||||
bb3: {
|
||||
_13 = const core::tuple::<impl std::cmp::PartialOrd for (f32, f32)>::le::promoted[0];
|
||||
StorageLive(_21);
|
||||
StorageLive(_14);
|
||||
_14 = discriminant((*_13));
|
||||
_0 = Eq(copy _14, const 0_isize);
|
||||
goto -> bb16;
|
||||
}
|
||||
|
||||
bb4: {
|
||||
_15 = const Option::<std::cmp::Ordering>::Some(Greater);
|
||||
StorageDead(_8);
|
||||
StorageDead(_5);
|
||||
StorageLive(_12);
|
||||
_9 = const core::tuple::<impl std::cmp::PartialOrd for (f32, f32)>::le::promoted[1];
|
||||
StorageLive(_11);
|
||||
StorageLive(_16);
|
||||
StorageLive(_10);
|
||||
goto -> bb8;
|
||||
}
|
||||
|
||||
bb5: {
|
||||
switchInt(copy _8) -> [0: bb6, otherwise: bb7];
|
||||
}
|
||||
|
||||
bb6: {
|
||||
_15 = const Option::<std::cmp::Ordering>::Some(Less);
|
||||
StorageDead(_8);
|
||||
StorageDead(_5);
|
||||
StorageLive(_12);
|
||||
_9 = const core::tuple::<impl std::cmp::PartialOrd for (f32, f32)>::le::promoted[1];
|
||||
StorageLive(_11);
|
||||
StorageLive(_16);
|
||||
StorageLive(_10);
|
||||
goto -> bb8;
|
||||
}
|
||||
|
||||
bb7: {
|
||||
_15 = const Option::<std::cmp::Ordering>::Some(Equal);
|
||||
StorageDead(_8);
|
||||
StorageDead(_5);
|
||||
StorageLive(_12);
|
||||
_9 = const core::tuple::<impl std::cmp::PartialOrd for (f32, f32)>::le::promoted[1];
|
||||
StorageLive(_11);
|
||||
StorageLive(_16);
|
||||
StorageLive(_10);
|
||||
goto -> bb8;
|
||||
}
|
||||
|
||||
bb8: {
|
||||
_16 = discriminant((*_9));
|
||||
switchInt(move _16) -> [0: bb9, 1: bb10, otherwise: bb18];
|
||||
}
|
||||
|
||||
bb9: {
|
||||
StorageDead(_10);
|
||||
StorageDead(_16);
|
||||
StorageDead(_11);
|
||||
_13 = const core::tuple::<impl std::cmp::PartialOrd for (f32, f32)>::le::promoted[0];
|
||||
StorageLive(_21);
|
||||
StorageLive(_14);
|
||||
goto -> bb13;
|
||||
}
|
||||
|
||||
bb10: {
|
||||
StorageLive(_17);
|
||||
StorageLive(_18);
|
||||
_17 = discriminant(((_15 as Some).0: std::cmp::Ordering));
|
||||
_18 = discriminant((((*_9) as Some).0: std::cmp::Ordering));
|
||||
_11 = Eq(copy _17, copy _18);
|
||||
StorageDead(_18);
|
||||
StorageDead(_17);
|
||||
StorageDead(_10);
|
||||
StorageDead(_16);
|
||||
_12 = Not(move _11);
|
||||
StorageDead(_11);
|
||||
switchInt(move _12) -> [0: bb11, otherwise: bb12];
|
||||
}
|
||||
|
||||
bb11: {
|
||||
_19 = &((*_1).1: f32);
|
||||
_20 = &((*_2).1: f32);
|
||||
_0 = <f32 as PartialOrd>::le(move _19, move _20) -> [return: bb17, unwind continue];
|
||||
}
|
||||
|
||||
bb12: {
|
||||
_13 = const core::tuple::<impl std::cmp::PartialOrd for (f32, f32)>::le::promoted[0];
|
||||
StorageLive(_21);
|
||||
StorageLive(_14);
|
||||
goto -> bb13;
|
||||
}
|
||||
|
||||
bb13: {
|
||||
_21 = discriminant((*_13));
|
||||
switchInt(move _21) -> [0: bb14, 1: bb15, otherwise: bb18];
|
||||
}
|
||||
|
||||
bb14: {
|
||||
_0 = const false;
|
||||
goto -> bb16;
|
||||
}
|
||||
|
||||
bb15: {
|
||||
StorageLive(_22);
|
||||
StorageLive(_23);
|
||||
_22 = discriminant(((_15 as Some).0: std::cmp::Ordering));
|
||||
_23 = discriminant((((*_13) as Some).0: std::cmp::Ordering));
|
||||
_0 = Eq(copy _22, copy _23);
|
||||
StorageDead(_23);
|
||||
StorageDead(_22);
|
||||
goto -> bb16;
|
||||
}
|
||||
|
||||
bb16: {
|
||||
StorageDead(_14);
|
||||
StorageDead(_21);
|
||||
goto -> bb17;
|
||||
}
|
||||
|
||||
bb17: {
|
||||
StorageDead(_12);
|
||||
StorageDead(_15);
|
||||
StorageDead(_9);
|
||||
StorageDead(_13);
|
||||
StorageDead(_20);
|
||||
StorageDead(_19);
|
||||
StorageDead(_7);
|
||||
return;
|
||||
}
|
||||
|
||||
bb18: {
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,140 +6,65 @@ fn demo_le_total(_1: &(u16, i16), _2: &(u16, i16)) -> bool {
|
|||
let mut _0: bool;
|
||||
scope 1 (inlined std::cmp::impls::<impl PartialOrd for &(u16, i16)>::le) {
|
||||
scope 2 (inlined core::tuple::<impl PartialOrd for (u16, i16)>::le) {
|
||||
let mut _12: bool;
|
||||
let _13: &i16;
|
||||
let _14: &i16;
|
||||
let mut _7: std::ops::ControlFlow<bool>;
|
||||
let _8: bool;
|
||||
scope 3 {
|
||||
let mut _6: &std::option::Option<std::cmp::Ordering>;
|
||||
let mut _8: &std::option::Option<std::cmp::Ordering>;
|
||||
scope 4 (inlined <Option<std::cmp::Ordering> as PartialEq>::ne) {
|
||||
let mut _11: bool;
|
||||
scope 5 (inlined <Option<std::cmp::Ordering> as PartialEq>::eq) {
|
||||
let mut _7: isize;
|
||||
scope 6 {
|
||||
scope 7 (inlined <std::cmp::Ordering as PartialEq>::eq) {
|
||||
let _9: i8;
|
||||
scope 8 {
|
||||
let _10: i8;
|
||||
scope 9 {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
scope 10 (inlined <Option<std::cmp::Ordering> as PartialEq>::eq) {
|
||||
let mut _15: isize;
|
||||
scope 11 {
|
||||
scope 12 (inlined <std::cmp::Ordering as PartialEq>::eq) {
|
||||
let _16: i8;
|
||||
scope 13 {
|
||||
let _17: i8;
|
||||
scope 14 {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
scope 15 (inlined std::cmp::impls::<impl PartialOrd for u16>::partial_cmp) {
|
||||
scope 4 (inlined std::cmp::impls::<impl std::cmp::SpecChainingPartialOrd<u16> for u16>::spec_chain_le) {
|
||||
let mut _3: u16;
|
||||
let mut _4: u16;
|
||||
let mut _5: std::cmp::Ordering;
|
||||
let mut _5: bool;
|
||||
let mut _6: bool;
|
||||
scope 5 {
|
||||
}
|
||||
}
|
||||
scope 6 (inlined std::cmp::impls::<impl PartialOrd for i16>::le) {
|
||||
let mut _9: i16;
|
||||
let mut _10: i16;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_13);
|
||||
StorageLive(_14);
|
||||
StorageLive(_8);
|
||||
StorageLive(_6);
|
||||
StorageLive(_3);
|
||||
_3 = copy ((*_1).0: u16);
|
||||
StorageLive(_4);
|
||||
_4 = copy ((*_2).0: u16);
|
||||
_5 = Cmp(move _3, move _4);
|
||||
StorageDead(_4);
|
||||
StorageDead(_3);
|
||||
StorageLive(_12);
|
||||
_6 = const core::tuple::<impl std::cmp::PartialOrd for (u16, i16)>::le::promoted[1];
|
||||
StorageLive(_11);
|
||||
StorageLive(_7);
|
||||
_7 = discriminant((*_6));
|
||||
switchInt(move _7) -> [0: bb1, 1: bb2, otherwise: bb10];
|
||||
StorageLive(_3);
|
||||
StorageLive(_4);
|
||||
_3 = copy ((*_1).0: u16);
|
||||
_4 = copy ((*_2).0: u16);
|
||||
StorageLive(_5);
|
||||
_5 = Eq(copy _3, copy _4);
|
||||
switchInt(move _5) -> [0: bb1, otherwise: bb2];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
StorageDead(_7);
|
||||
StorageDead(_11);
|
||||
_8 = const core::tuple::<impl std::cmp::PartialOrd for (u16, i16)>::le::promoted[0];
|
||||
StorageLive(_15);
|
||||
goto -> bb5;
|
||||
StorageLive(_6);
|
||||
_6 = Le(copy _3, copy _4);
|
||||
_7 = ControlFlow::<bool>::Break(move _6);
|
||||
StorageDead(_6);
|
||||
StorageDead(_5);
|
||||
StorageDead(_4);
|
||||
StorageDead(_3);
|
||||
_8 = copy ((_7 as Break).0: bool);
|
||||
_0 = copy _8;
|
||||
goto -> bb3;
|
||||
}
|
||||
|
||||
bb2: {
|
||||
StorageDead(_5);
|
||||
StorageDead(_4);
|
||||
StorageDead(_3);
|
||||
StorageLive(_9);
|
||||
_9 = copy ((*_1).1: i16);
|
||||
StorageLive(_10);
|
||||
_9 = discriminant(_5);
|
||||
_10 = discriminant((((*_6) as Some).0: std::cmp::Ordering));
|
||||
_11 = Eq(copy _9, copy _10);
|
||||
_10 = copy ((*_2).1: i16);
|
||||
_0 = Le(move _9, move _10);
|
||||
StorageDead(_10);
|
||||
StorageDead(_9);
|
||||
StorageDead(_7);
|
||||
_12 = Not(move _11);
|
||||
StorageDead(_11);
|
||||
switchInt(move _12) -> [0: bb3, otherwise: bb4];
|
||||
goto -> bb3;
|
||||
}
|
||||
|
||||
bb3: {
|
||||
_13 = &((*_1).1: i16);
|
||||
_14 = &((*_2).1: i16);
|
||||
_0 = <i16 as PartialOrd>::le(move _13, move _14) -> [return: bb9, unwind continue];
|
||||
}
|
||||
|
||||
bb4: {
|
||||
_8 = const core::tuple::<impl std::cmp::PartialOrd for (u16, i16)>::le::promoted[0];
|
||||
StorageLive(_15);
|
||||
goto -> bb5;
|
||||
}
|
||||
|
||||
bb5: {
|
||||
_15 = discriminant((*_8));
|
||||
switchInt(move _15) -> [0: bb6, 1: bb7, otherwise: bb10];
|
||||
}
|
||||
|
||||
bb6: {
|
||||
_0 = const false;
|
||||
goto -> bb8;
|
||||
}
|
||||
|
||||
bb7: {
|
||||
StorageLive(_16);
|
||||
StorageLive(_17);
|
||||
_16 = discriminant(_5);
|
||||
_17 = discriminant((((*_8) as Some).0: std::cmp::Ordering));
|
||||
_0 = Eq(copy _16, copy _17);
|
||||
StorageDead(_17);
|
||||
StorageDead(_16);
|
||||
goto -> bb8;
|
||||
}
|
||||
|
||||
bb8: {
|
||||
StorageDead(_15);
|
||||
goto -> bb9;
|
||||
}
|
||||
|
||||
bb9: {
|
||||
StorageDead(_12);
|
||||
StorageDead(_6);
|
||||
StorageDead(_8);
|
||||
StorageDead(_14);
|
||||
StorageDead(_13);
|
||||
StorageDead(_7);
|
||||
return;
|
||||
}
|
||||
|
||||
bb10: {
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//@ compile-flags: -O -Zmir-opt-level=2 -Cdebuginfo=0 -Z inline-mir-hint-threshold=9999
|
||||
//@ compile-flags: -O -Zmir-opt-level=2 -Cdebuginfo=0
|
||||
//@ needs-unwind
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
@ -12,5 +12,5 @@ pub fn demo_le_total(a: &(u16, i16), b: &(u16, i16)) -> bool {
|
|||
// EMIT_MIR tuple_ord.demo_ge_partial.PreCodegen.after.mir
|
||||
pub fn demo_ge_partial(a: &(f32, f32), b: &(f32, f32)) -> bool {
|
||||
// CHECK-LABEL: demo_ge_partial
|
||||
a <= b
|
||||
a >= b
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue