@@ -1187,6 +1187,52 @@ macro_rules! uint_impl {
11871187 self % rhs
11881188 }
11891189
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+
11901236 /// Returns the logarithm of the number with respect to an arbitrary base,
11911237 /// rounded down.
11921238 ///
@@ -2346,15 +2392,22 @@ macro_rules! uint_impl {
23462392 /// assert_eq!((sum1, sum0), (9, 6));
23472393 /// ```
23482394 #[ unstable( feature = "bigint_helper_methods" , issue = "85532" ) ]
2395+ #[ rustc_const_unstable( feature = "bigint_helper_methods" , issue = "85532" ) ]
23492396 #[ must_use = "this returns the result of the operation, \
23502397 without modifying the original"]
23512398 #[ inline]
23522399 pub const fn carrying_add( self , rhs: Self , carry: bool ) -> ( Self , bool ) {
23532400 // note: longer-term this should be done via an intrinsic, but this has been shown
23542401 // 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) } )
23582411 }
23592412
23602413 /// Calculates `self` + `rhs` with a signed `rhs`.
0 commit comments