diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2023-01-28 05:20:15 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-01-28 05:20:15 +0100 |
| commit | 7b78b6a78d2caf20f6e6c76523719ec6fe039c19 (patch) | |
| tree | 27203a72b46068e3a6eb79dc34493f81b9acf697 /library/core/src | |
| parent | 6cd6bad51fb34a0d89e97c27814041fe4d0838b5 (diff) | |
| parent | 3e9d1e40cb2a4dc1e1d303e9d9fa382c34106277 (diff) | |
| download | rust-7b78b6a78d2caf20f6e6c76523719ec6fe039c19.tar.gz rust-7b78b6a78d2caf20f6e6c76523719ec6fe039c19.zip | |
Rollup merge of #107022 - scottmcm:ordering-option-eq, r=m-ou-se
Implement `SpecOptionPartialEq` for `cmp::Ordering`
Noticed as I continue to explore options for having code using `partial_cmp` optimize better.
Before:
```llvm
; Function Attrs: mustprogress nofree nosync nounwind willreturn uwtable
define noundef zeroext i1 `@ordering_eq(i8` noundef %0, i8 noundef %1) unnamed_addr #0 {
start:
%2 = icmp eq i8 %0, 2
br i1 %2, label %bb1.i, label %bb3.i
bb1.i: ; preds = %start
%3 = icmp eq i8 %1, 2
br label %"_ZN55_$LT$T$u20$as$u20$core..option..SpecOptionPartialEq$GT$2eq17hb7e7beacecde585fE.exit"
bb3.i: ; preds = %start
%.not.i = icmp ne i8 %1, 2
%4 = icmp eq i8 %0, %1
%spec.select.i = and i1 %.not.i, %4
br label %"_ZN55_$LT$T$u20$as$u20$core..option..SpecOptionPartialEq$GT$2eq17hb7e7beacecde585fE.exit"
"_ZN55_$LT$T$u20$as$u20$core..option..SpecOptionPartialEq$GT$2eq17hb7e7beacecde585fE.exit": ; preds = %bb1.i, %bb3.i
%.0.i = phi i1 [ %3, %bb1.i ], [ %spec.select.i, %bb3.i ]
ret i1 %.0.i
}
```
After:
```llvm
; Function Attrs: mustprogress nofree norecurse nosync nounwind readnone willreturn uwtable
define noundef zeroext i1 `@ordering_eq(i8` noundef %0, i8 noundef %1) unnamed_addr #1 {
start:
%2 = icmp eq i8 %0, %1
ret i1 %2
}
```
(Which <https://alive2.llvm.org/ce/z/-rop5r> says LLVM *could* just do itself, but there's probably an issue already open for that problem from when this was originally looked at for `Option<NonZeroU8>` and friends.)
Diffstat (limited to 'library/core/src')
| -rw-r--r-- | library/core/src/option.rs | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 7cc00e3f8d1..c43b728022d 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -551,7 +551,7 @@ use crate::marker::Destruct; use crate::panicking::{panic, panic_str}; use crate::pin::Pin; use crate::{ - convert, hint, mem, + cmp, convert, hint, mem, ops::{self, ControlFlow, Deref, DerefMut}, }; @@ -2090,6 +2090,12 @@ impl<T: PartialEq> PartialEq for Option<T> { } } +/// This specialization trait is a workaround for LLVM not currently (2023-01) +/// being able to optimize this itself, even though Alive confirms that it would +/// be legal to do so: <https://github.com/llvm/llvm-project/issues/52622> +/// +/// Once that's fixed, `Option` should go back to deriving `PartialEq`, as +/// it used to do before <https://github.com/rust-lang/rust/pull/103556>. #[unstable(feature = "spec_option_partial_eq", issue = "none", reason = "exposed only for rustc")] #[doc(hidden)] pub trait SpecOptionPartialEq: Sized { @@ -2146,6 +2152,14 @@ impl<T> SpecOptionPartialEq for crate::ptr::NonNull<T> { } } +#[stable(feature = "rust1", since = "1.0.0")] +impl SpecOptionPartialEq for cmp::Ordering { + #[inline] + fn eq(l: &Option<Self>, r: &Option<Self>) -> bool { + l.map_or(2, |x| x as i8) == r.map_or(2, |x| x as i8) + } +} + ///////////////////////////////////////////////////////////////////////////// // The Option Iterators ///////////////////////////////////////////////////////////////////////////// |
