@@ -60,4 +60,50 @@ impl bool {
60
60
pub fn then < T , F : FnOnce ( ) -> T > ( self , f : F ) -> Option < T > {
61
61
if self { Some ( f ( ) ) } else { None }
62
62
}
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
+ }
63
109
}
0 commit comments