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