From 4ca769ad091ef0018f5a20effaf4b4f428a034d7 Mon Sep 17 00:00:00 2001 From: Krishna Sai Veera Reddy Date: Fri, 29 Nov 2019 15:22:44 -0700 Subject: [PATCH 1/3] 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. --- src/libcore/cmp.rs | 11 ++++++++++- src/libcore/tests/cmp.rs | 8 ++++++++ src/test/codegen/bool-cmp.rs | 17 +++++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 src/test/codegen/bool-cmp.rs diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index eea3dc39d345e..e72b6117ba862 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -1006,6 +1006,7 @@ pub fn max_by_key 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 for more info. + match (*self as i8) - (*other as i8) { + -1 => Less, + 0 => Equal, + 1 => Greater, + _ => unsafe { unreachable_unchecked() }, + } } } diff --git a/src/libcore/tests/cmp.rs b/src/libcore/tests/cmp.rs index 5e6778e222a29..56a2f4acf6eaa 100644 --- a/src/libcore/tests/cmp.rs +++ b/src/libcore/tests/cmp.rs @@ -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); diff --git a/src/test/codegen/bool-cmp.rs b/src/test/codegen/bool-cmp.rs new file mode 100644 index 0000000000000..8769a4cb5e189 --- /dev/null +++ b/src/test/codegen/bool-cmp.rs @@ -0,0 +1,17 @@ +// This is a test for optimal Ord trait implementation for bool. +// See 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) +} From a30ee8e7636d2cf26eba89a8402cdfefebf9845e Mon Sep 17 00:00:00 2001 From: Krishna Sai Veera Reddy Date: Mon, 2 Dec 2019 08:45:35 -0700 Subject: [PATCH 2/3] Document usage of unsafe block --- src/libcore/cmp.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index e72b6117ba862..e16a428feb645 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -1134,6 +1134,7 @@ mod impls { -1 => Less, 0 => Equal, 1 => Greater, + // SAFETY: Unreachable code _ => unsafe { unreachable_unchecked() }, } } From 1f07aa582a41e6fc253139909d3bf9bfd04a9d6d Mon Sep 17 00:00:00 2001 From: Krishna Sai Veera Reddy Date: Tue, 10 Dec 2019 14:30:06 -0700 Subject: [PATCH 3/3] Add better documentation for unsafe block --- src/libcore/cmp.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index e16a428feb645..87a407c5e9f7b 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -1134,7 +1134,7 @@ mod impls { -1 => Less, 0 => Equal, 1 => Greater, - // SAFETY: Unreachable code + // SAFETY: bool as i8 returns 0 or 1, so the difference can't be anything else _ => unsafe { unreachable_unchecked() }, } }