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