@@ -61,4 +61,52 @@ impl bool {
61
61
pub fn then < T , F : FnOnce ( ) -> T > ( self , f : F ) -> Option < T > {
62
62
if self { Some ( f ( ) ) } else { None }
63
63
}
64
+
65
+ /// Returns either `true_val` or `false_val` depending on the value of
66
+ /// `self`, with a hint to the compiler that `self` is unlikely
67
+ /// to be correctly predicted by a CPU’s branch predictor.
68
+ ///
69
+ /// This method is functionally equivalent to
70
+ /// ```ignore (this is just for illustrative purposes)
71
+ /// fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
72
+ /// if b { true_val } else { false_val }
73
+ /// }
74
+ /// ```
75
+ /// but might generate different assembly. In particular, on platforms with
76
+ /// a conditional move or select instruction (like `cmov` on x86 or `csel`
77
+ /// on ARM) the optimizer might use these instructions to avoid branches,
78
+ /// which can benefit performance if the branch predictor is struggling
79
+ /// with predicting `condition`, such as in an implementation of binary
80
+ /// search.
81
+ ///
82
+ /// Note however that this lowering is not guaranteed (on any platform) and
83
+ /// should not be relied upon when trying to write constant-time code. Also
84
+ /// be aware that this lowering might *decrease* performance if `condition`
85
+ /// is well-predictable. It is advisable to perform benchmarks to tell if
86
+ /// this function is useful.
87
+ ///
88
+ /// # Examples
89
+ ///
90
+ /// Distribute values evenly between two buckets:
91
+ /// ```
92
+ /// #![feature(select_unpredictable)]
93
+ ///
94
+ /// use std::hash::BuildHasher;
95
+ ///
96
+ /// fn append<H: BuildHasher>(hasher: &H, v: i32, bucket_one: &mut Vec<i32>, bucket_two: &mut Vec<i32>) {
97
+ /// let hash = hasher.hash_one(&v);
98
+ /// let bucket = (hash % 2 == 0).select_unpredictable(bucket_one, bucket_two);
99
+ /// bucket.push(v);
100
+ /// }
101
+ /// # let hasher = std::collections::hash_map::RandomState::new();
102
+ /// # let mut bucket_one = Vec::new();
103
+ /// # let mut bucket_two = Vec::new();
104
+ /// # append(&hasher, 42, &mut bucket_one, &mut bucket_two);
105
+ /// # assert_eq!(bucket_one.len() + bucket_two.len(), 1);
106
+ /// ```
107
+ #[ inline( always) ]
108
+ #[ unstable( feature = "select_unpredictable" , issue = "133962" ) ]
109
+ pub fn select_unpredictable < T > ( self , true_val : T , false_val : T ) -> T {
110
+ crate :: intrinsics:: select_unpredictable ( self , true_val, false_val)
111
+ }
64
112
}
0 commit comments