@@ -1187,6 +1187,52 @@ macro_rules! uint_impl {
1187
1187
self % rhs
1188
1188
}
1189
1189
1190
+ /// Same value as
1191
+ #[ doc = concat!( "`<" , stringify!( $SelfT) , " as BitOr>::bitor(self, other)`" ) ]
1192
+ /// but UB if any bit position is set in both inputs.
1193
+ ///
1194
+ /// This is a situational μoptimization for places where you'd rather use
1195
+ /// addition on some platforms and bitwise or on other platforms, based on
1196
+ /// exactly which instructions combine better with whatever else you're
1197
+ /// doing. Note that there's no reason to bother using this for places
1198
+ /// where it's clear from the operations involved that they can't overlap.
1199
+ /// For example, if you're combining `u16`s into a `u32` with
1200
+ /// `((a as u32) << 16) | (b as u32)`, that's fine, as the backend will
1201
+ /// know those sides of the `|` are disjoint without needing help.
1202
+ ///
1203
+ /// # Examples
1204
+ ///
1205
+ /// ```
1206
+ /// #![feature(disjoint_bitor)]
1207
+ ///
1208
+ /// // SAFETY: `1` and `4` have no bits in common.
1209
+ /// unsafe {
1210
+ #[ doc = concat!( " assert_eq!(1_" , stringify!( $SelfT) , ".unchecked_disjoint_bitor(4), 5);" ) ]
1211
+ /// }
1212
+ /// ```
1213
+ ///
1214
+ /// # Safety
1215
+ ///
1216
+ /// Requires that `(self | other) == 0`, otherwise it's immediate UB.
1217
+ ///
1218
+ /// Equivalently, requires that `(self | other) == (self + other)`.
1219
+ #[ unstable( feature = "disjoint_bitor" , issue = "135758" ) ]
1220
+ #[ rustc_const_unstable( feature = "disjoint_bitor" , issue = "135758" ) ]
1221
+ #[ inline]
1222
+ pub const unsafe fn unchecked_disjoint_bitor( self , other: Self ) -> Self {
1223
+ assert_unsafe_precondition!(
1224
+ check_language_ub,
1225
+ concat!( stringify!( $SelfT) , "::unchecked_disjoint_bitor cannot have overlapping bits" ) ,
1226
+ (
1227
+ lhs: $SelfT = self ,
1228
+ rhs: $SelfT = other,
1229
+ ) => ( lhs & rhs) == 0 ,
1230
+ ) ;
1231
+
1232
+ // SAFETY: Same precondition
1233
+ unsafe { intrinsics:: disjoint_bitor( self , other) }
1234
+ }
1235
+
1190
1236
/// Returns the logarithm of the number with respect to an arbitrary base,
1191
1237
/// rounded down.
1192
1238
///
@@ -2346,15 +2392,22 @@ macro_rules! uint_impl {
2346
2392
/// assert_eq!((sum1, sum0), (9, 6));
2347
2393
/// ```
2348
2394
#[ unstable( feature = "bigint_helper_methods" , issue = "85532" ) ]
2395
+ #[ rustc_const_unstable( feature = "bigint_helper_methods" , issue = "85532" ) ]
2349
2396
#[ must_use = "this returns the result of the operation, \
2350
2397
without modifying the original"]
2351
2398
#[ inline]
2352
2399
pub const fn carrying_add( self , rhs: Self , carry: bool ) -> ( Self , bool ) {
2353
2400
// note: longer-term this should be done via an intrinsic, but this has been shown
2354
2401
// to generate optimal code for now, and LLVM doesn't have an equivalent intrinsic
2355
- let ( a, b) = self . overflowing_add( rhs) ;
2356
- let ( c, d) = a. overflowing_add( carry as $SelfT) ;
2357
- ( c, b | d)
2402
+ let ( a, c1) = self . overflowing_add( rhs) ;
2403
+ let ( b, c2) = a. overflowing_add( carry as $SelfT) ;
2404
+ // Ideally LLVM would know this is disjoint without us telling them,
2405
+ // but it doesn't <https://github.com/llvm/llvm-project/issues/118162>
2406
+ // SAFETY: Only one of `c1` and `c2` can be set.
2407
+ // For c1 to be set we need to have overflowed, but if we did then
2408
+ // `a` is at most `MAX-1`, which means that `c2` cannot possibly
2409
+ // overflow because it's adding at most `1` (since it came from `bool`)
2410
+ ( b, unsafe { intrinsics:: disjoint_bitor( c1, c2) } )
2358
2411
}
2359
2412
2360
2413
/// Calculates `self` + `rhs` with a signed `rhs`.
0 commit comments