@@ -1187,6 +1187,50 @@ macro_rules! uint_impl {
11871187 self % rhs
11881188 }
11891189
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+
11901234 /// Returns the logarithm of the number with respect to an arbitrary base,
11911235 /// rounded down.
11921236 ///
@@ -2346,15 +2390,22 @@ macro_rules! uint_impl {
23462390 /// assert_eq!((sum1, sum0), (9, 6));
23472391 /// ```
23482392 #[ unstable( feature = "bigint_helper_methods" , issue = "85532" ) ]
2393+ #[ rustc_const_unstable( feature = "bigint_helper_methods" , issue = "85532" ) ]
23492394 #[ must_use = "this returns the result of the operation, \
23502395 without modifying the original"]
23512396 #[ inline]
23522397 pub const fn carrying_add( self , rhs: Self , carry: bool ) -> ( Self , bool ) {
23532398 // note: longer-term this should be done via an intrinsic, but this has been shown
23542399 // 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) } )
23582409 }
23592410
23602411 /// Calculates `self` + `rhs` with a signed `rhs`.
0 commit comments