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