Optimize Ord trait implementation for bool

Casting the booleans to `i8`s and converting their difference
into `Ordering` generates better assembly than casting them to
`u8`s and comparing them.
This commit is contained in:
Krishna Sai Veera Reddy 2019-11-29 15:22:44 -07:00
parent d99e0c6d02
commit 4ca769ad09
3 changed files with 35 additions and 1 deletions

View file

@ -1006,6 +1006,7 @@ pub fn max_by_key<T, F: FnMut(&T) -> K, K: Ord>(v1: T, v2: T, mut f: F) -> T {
// Implementation of PartialEq, Eq, PartialOrd and Ord for primitive types
mod impls {
use crate::hint::unreachable_unchecked;
use crate::cmp::Ordering::{self, Less, Greater, Equal};
macro_rules! partial_eq_impl {
@ -1126,7 +1127,15 @@ mod impls {
impl Ord for bool {
#[inline]
fn cmp(&self, other: &bool) -> Ordering {
(*self as u8).cmp(&(*other as u8))
// Casting to i8's and converting the difference to an Ordering generates
// more optimal assembly.
// See <https://github.com/rust-lang/rust/issues/66780> for more info.
match (*self as i8) - (*other as i8) {
-1 => Less,
0 => Equal,
1 => Greater,
_ => unsafe { unreachable_unchecked() },
}
}
}

View file

@ -9,6 +9,14 @@ fn test_int_totalord() {
assert_eq!(12.cmp(&-5), Greater);
}
#[test]
fn test_bool_totalord() {
assert_eq!(true.cmp(&false), Greater);
assert_eq!(false.cmp(&true), Less);
assert_eq!(true.cmp(&true), Equal);
assert_eq!(false.cmp(&false), Equal);
}
#[test]
fn test_mut_int_totalord() {
assert_eq!((&mut 5).cmp(&&mut 10), Less);

View file

@ -0,0 +1,17 @@
// This is a test for optimal Ord trait implementation for bool.
// See <https://github.com/rust-lang/rust/issues/66780> for more info.
// compile-flags: -C opt-level=3
#![crate_type = "lib"]
use std::cmp::Ordering;
// CHECK-LABEL: @cmp_bool
#[no_mangle]
pub fn cmp_bool(a: bool, b: bool) -> Ordering {
// CHECK: zext i1
// CHECK: zext i1
// CHECK: sub nsw
a.cmp(&b)
}