@@ -1496,18 +1496,17 @@ macro_rules! int_impl {
14961496 let mut base = self ;
14971497 let mut acc: Self = 1 ;
14981498
1499- while exp > 1 {
1499+ loop {
15001500 if ( exp & 1 ) == 1 {
15011501 acc = try_opt!( acc. checked_mul( base) ) ;
1502+ // since exp!=0, finally the exp must be 1.
1503+ if exp == 1 {
1504+ return Some ( acc) ;
1505+ }
15021506 }
15031507 exp /= 2 ;
15041508 base = try_opt!( base. checked_mul( base) ) ;
15051509 }
1506- // since exp!=0, finally the exp must be 1.
1507- // Deal with the final bit of the exponent separately, since
1508- // squaring the base afterwards is not necessary and may cause a
1509- // needless overflow.
1510- acc. checked_mul( base)
15111510 }
15121511
15131512 /// Strict exponentiation. Computes `self.pow(exp)`, panicking if
@@ -1547,18 +1546,17 @@ macro_rules! int_impl {
15471546 let mut base = self ;
15481547 let mut acc: Self = 1 ;
15491548
1550- while exp > 1 {
1549+ loop {
15511550 if ( exp & 1 ) == 1 {
15521551 acc = acc. strict_mul( base) ;
1552+ // since exp!=0, finally the exp must be 1.
1553+ if exp == 1 {
1554+ return acc;
1555+ }
15531556 }
15541557 exp /= 2 ;
15551558 base = base. strict_mul( base) ;
15561559 }
1557- // since exp!=0, finally the exp must be 1.
1558- // Deal with the final bit of the exponent separately, since
1559- // squaring the base afterwards is not necessary and may cause a
1560- // needless overflow.
1561- acc. strict_mul( base)
15621560 }
15631561
15641562 /// Returns the square root of the number, rounded down.
@@ -2175,26 +2173,44 @@ macro_rules! int_impl {
21752173 #[ must_use = "this returns the result of the operation, \
21762174 without modifying the original"]
21772175 #[ inline]
2176+ #[ rustc_allow_const_fn_unstable( is_val_statically_known) ]
21782177 pub const fn wrapping_pow( self , mut exp: u32 ) -> Self {
21792178 if exp == 0 {
21802179 return 1 ;
21812180 }
21822181 let mut base = self ;
21832182 let mut acc: Self = 1 ;
21842183
2185- while exp > 1 {
2186- if ( exp & 1 ) == 1 {
2187- acc = acc. wrapping_mul( base) ;
2184+ if intrinsics:: is_val_statically_known( exp) {
2185+ while exp > 1 {
2186+ if ( exp & 1 ) == 1 {
2187+ acc = acc. wrapping_mul( base) ;
2188+ }
2189+ exp /= 2 ;
2190+ base = base. wrapping_mul( base) ;
21882191 }
2189- exp /= 2 ;
2190- base = base. wrapping_mul( base) ;
2191- }
21922192
2193- // since exp!=0, finally the exp must be 1.
2194- // Deal with the final bit of the exponent separately, since
2195- // squaring the base afterwards is not necessary and may cause a
2196- // needless overflow.
2197- acc. wrapping_mul( base)
2193+ // since exp!=0, finally the exp must be 1.
2194+ // Deal with the final bit of the exponent separately, since
2195+ // squaring the base afterwards is not necessary.
2196+ acc. wrapping_mul( base)
2197+ } else {
2198+ // This is faster than the above when the exponent is not known
2199+ // at compile time. We can't use the same code for the constant
2200+ // exponent case because LLVM is currently unable to unroll
2201+ // this loop.
2202+ loop {
2203+ if ( exp & 1 ) == 1 {
2204+ acc = acc. wrapping_mul( base) ;
2205+ // since exp!=0, finally the exp must be 1.
2206+ if exp == 1 {
2207+ return acc;
2208+ }
2209+ }
2210+ exp /= 2 ;
2211+ base = base. wrapping_mul( base) ;
2212+ }
2213+ }
21982214 }
21992215
22002216 /// Calculates `self` + `rhs`.
@@ -2690,9 +2706,14 @@ macro_rules! int_impl {
26902706 // Scratch space for storing results of overflowing_mul.
26912707 let mut r;
26922708
2693- while exp > 1 {
2709+ loop {
26942710 if ( exp & 1 ) == 1 {
26952711 r = acc. overflowing_mul( base) ;
2712+ // since exp!=0, finally the exp must be 1.
2713+ if exp == 1 {
2714+ r. 1 |= overflown;
2715+ return r;
2716+ }
26962717 acc = r. 0 ;
26972718 overflown |= r. 1 ;
26982719 }
@@ -2701,14 +2722,6 @@ macro_rules! int_impl {
27012722 base = r. 0 ;
27022723 overflown |= r. 1 ;
27032724 }
2704-
2705- // since exp!=0, finally the exp must be 1.
2706- // Deal with the final bit of the exponent separately, since
2707- // squaring the base afterwards is not necessary and may cause a
2708- // needless overflow.
2709- r = acc. overflowing_mul( base) ;
2710- r. 1 |= overflown;
2711- r
27122725 }
27132726
27142727 /// Raises self to the power of `exp`, using exponentiation by squaring.
@@ -2728,26 +2741,45 @@ macro_rules! int_impl {
27282741 without modifying the original"]
27292742 #[ inline]
27302743 #[ rustc_inherit_overflow_checks]
2744+ #[ rustc_allow_const_fn_unstable( is_val_statically_known) ]
27312745 pub const fn pow( self , mut exp: u32 ) -> Self {
27322746 if exp == 0 {
27332747 return 1 ;
27342748 }
27352749 let mut base = self ;
27362750 let mut acc = 1 ;
27372751
2738- while exp > 1 {
2739- if ( exp & 1 ) == 1 {
2740- acc = acc * base;
2752+ if intrinsics:: is_val_statically_known( exp) {
2753+ while exp > 1 {
2754+ if ( exp & 1 ) == 1 {
2755+ acc = acc * base;
2756+ }
2757+ exp /= 2 ;
2758+ base = base * base;
27412759 }
2742- exp /= 2 ;
2743- base = base * base;
2744- }
27452760
2746- // since exp!=0, finally the exp must be 1.
2747- // Deal with the final bit of the exponent separately, since
2748- // squaring the base afterwards is not necessary and may cause a
2749- // needless overflow.
2750- acc * base
2761+ // since exp!=0, finally the exp must be 1.
2762+ // Deal with the final bit of the exponent separately, since
2763+ // squaring the base afterwards is not necessary and may cause a
2764+ // needless overflow.
2765+ acc * base
2766+ } else {
2767+ // This is faster than the above when the exponent is not known
2768+ // at compile time. We can't use the same code for the constant
2769+ // exponent case because LLVM is currently unable to unroll
2770+ // this loop.
2771+ loop {
2772+ if ( exp & 1 ) == 1 {
2773+ acc = acc * base;
2774+ // since exp!=0, finally the exp must be 1.
2775+ if exp == 1 {
2776+ return acc;
2777+ }
2778+ }
2779+ exp /= 2 ;
2780+ base = base * base;
2781+ }
2782+ }
27512783 }
27522784
27532785 /// Returns the square root of the number, rounded down.
0 commit comments