Revert to original loop for const pow exponents · rust-lang/rust@ac88b33 (original) (raw)
`@@ -2174,54 +2174,41 @@ macro_rules! int_impl {
`
2174
2174
` #[inline]
`
2175
2175
` #[rustc_allow_const_fn_unstable(is_val_statically_known)]
`
2176
2176
`pub const fn wrapping_pow(self, mut exp: u32) -> Self {
`
``
2177
`+
if exp == 0 {
`
``
2178
`+
return 1;
`
``
2179
`+
}
`
2177
2180
`let mut base = self;
`
``
2181
`+
let mut acc: Self = 1;
`
2178
2182
``
2179
2183
`if intrinsics::is_val_statically_known(exp) {
`
2180
``
`-
// Unroll multiplications for small exponent values.
`
2181
``
`-
// This gives the optimizer a way to efficiently inline call sites
`
2182
``
`-
// for the most common use cases with constant exponents.
`
2183
``
`-
// Currently, LLVM is unable to unroll the loop below.
`
2184
``
`-
match exp {
`
2185
``
`-
0 => return 1,
`
2186
``
`-
1 => return base,
`
2187
``
`-
2 => return base.wrapping_mul(base),
`
2188
``
`-
3 => {
`
2189
``
`-
let squared = base.wrapping_mul(base);
`
2190
``
`-
return squared.wrapping_mul(base);
`
2191
``
`-
}
`
2192
``
`-
4 => {
`
2193
``
`-
let squared = base.wrapping_mul(base);
`
2194
``
`-
return squared.wrapping_mul(squared);
`
``
2184
`+
while exp > 1 {
`
``
2185
`+
if (exp & 1) == 1 {
`
``
2186
`+
acc = acc.wrapping_mul(base);
`
2195
2187
`}
`
2196
``
`-
5 => {
`
2197
``
`-
let squared = base.wrapping_mul(base);
`
2198
``
`-
return squared.wrapping_mul(squared).wrapping_mul(base);
`
2199
``
`-
}
`
2200
``
`-
6 => {
`
2201
``
`-
let cubed = base.wrapping_mul(base).wrapping_mul(base);
`
2202
``
`-
return cubed.wrapping_mul(cubed);
`
2203
``
`-
}
`
2204
``
`-
_ => {}
`
``
2188
`+
exp /= 2;
`
``
2189
`+
base = base.wrapping_mul(base);
`
2205
2190
`}
`
2206
``
`-
} else {
`
2207
``
`-
if exp == 0 {
`
2208
``
`-
return 1;
`
2209
``
`-
}
`
2210
``
`-
}
`
2211
``
`-
debug_assert!(exp != 0);
`
2212
2191
``
2213
``
`-
let mut acc: Self = 1;
`
2214
``
-
2215
``
`-
loop {
`
2216
``
`-
if (exp & 1) == 1 {
`
2217
``
`-
acc = acc.wrapping_mul(base);
`
2218
``
`-
// since exp!=0, finally the exp must be 1.
`
2219
``
`-
if exp == 1 {
`
2220
``
`-
return acc;
`
``
2192
`+
// since exp!=0, finally the exp must be 1.
`
``
2193
`+
// Deal with the final bit of the exponent separately, since
`
``
2194
`+
// squaring the base afterwards is not necessary.
`
``
2195
`+
acc.wrapping_mul(base)
`
``
2196
`+
} else {
`
``
2197
`+
// This is faster than the above when the exponent is not known
`
``
2198
`+
// at compile time. We can't use the same code for the constant
`
``
2199
`+
// exponent case because LLVM is currently unable to unroll
`
``
2200
`+
// this loop.
`
``
2201
`+
loop {
`
``
2202
`+
if (exp & 1) == 1 {
`
``
2203
`+
acc = acc.wrapping_mul(base);
`
``
2204
`+
// since exp!=0, finally the exp must be 1.
`
``
2205
`+
if exp == 1 {
`
``
2206
`+
return acc;
`
``
2207
`+
}
`
2221
2208
`}
`
``
2209
`+
exp /= 2;
`
``
2210
`+
base = base.wrapping_mul(base);
`
2222
2211
`}
`
2223
``
`-
exp /= 2;
`
2224
``
`-
base = base.wrapping_mul(base);
`
2225
2212
`}
`
2226
2213
`}
`
2227
2214
``
`@@ -2753,54 +2740,42 @@ macro_rules! int_impl {
`
2753
2740
` #[rustc_inherit_overflow_checks]
`
2754
2741
` #[rustc_allow_const_fn_unstable(is_val_statically_known)]
`
2755
2742
`pub const fn pow(self, mut exp: u32) -> Self {
`
``
2743
`+
if exp == 0 {
`
``
2744
`+
return 1;
`
``
2745
`+
}
`
2756
2746
`let mut base = self;
`
``
2747
`+
let mut acc = 1;
`
2757
2748
``
2758
2749
`if intrinsics::is_val_statically_known(exp) {
`
2759
``
`-
// Unroll multiplications for small exponent values.
`
2760
``
`-
// This gives the optimizer a way to efficiently inline call sites
`
2761
``
`-
// for the most common use cases with constant exponents.
`
2762
``
`-
// Currently, LLVM is unable to unroll the loop below.
`
2763
``
`-
match exp {
`
2764
``
`-
0 => return 1,
`
2765
``
`-
1 => return base,
`
2766
``
`-
2 => return base * base,
`
2767
``
`-
3 => {
`
2768
``
`-
let squared = base * base;
`
2769
``
`-
return squared * base;
`
2770
``
`-
}
`
2771
``
`-
4 => {
`
2772
``
`-
let squared = base * base;
`
2773
``
`-
return squared * squared;
`
``
2750
`+
while exp > 1 {
`
``
2751
`+
if (exp & 1) == 1 {
`
``
2752
`+
acc = acc * base;
`
2774
2753
`}
`
2775
``
`-
5 => {
`
2776
``
`-
let squared = base * base;
`
2777
``
`-
return squared * squared * base;
`
2778
``
`-
}
`
2779
``
`-
6 => {
`
2780
``
`-
let cubed = base * base * base;
`
2781
``
`-
return cubed * cubed;
`
2782
``
`-
}
`
2783
``
`-
_ => {}
`
``
2754
`+
exp /= 2;
`
``
2755
`+
base = base * base;
`
2784
2756
`}
`
2785
``
`-
} else {
`
2786
``
`-
if exp == 0 {
`
2787
``
`-
return 1;
`
2788
``
`-
}
`
2789
``
`-
}
`
2790
``
`-
debug_assert!(exp != 0);
`
2791
2757
``
2792
``
`-
let mut acc = 1;
`
2793
``
-
2794
``
`-
loop {
`
2795
``
`-
if (exp & 1) == 1 {
`
2796
``
`-
acc = acc * base;
`
2797
``
`-
// since exp!=0, finally the exp must be 1.
`
2798
``
`-
if exp == 1 {
`
2799
``
`-
return acc;
`
``
2758
`+
// since exp!=0, finally the exp must be 1.
`
``
2759
`+
// Deal with the final bit of the exponent separately, since
`
``
2760
`+
// squaring the base afterwards is not necessary and may cause a
`
``
2761
`+
// needless overflow.
`
``
2762
`+
acc * base
`
``
2763
`+
} else {
`
``
2764
`+
// This is faster than the above when the exponent is not known
`
``
2765
`+
// at compile time. We can't use the same code for the constant
`
``
2766
`+
// exponent case because LLVM is currently unable to unroll
`
``
2767
`+
// this loop.
`
``
2768
`+
loop {
`
``
2769
`+
if (exp & 1) == 1 {
`
``
2770
`+
acc = acc * base;
`
``
2771
`+
// since exp!=0, finally the exp must be 1.
`
``
2772
`+
if exp == 1 {
`
``
2773
`+
return acc;
`
``
2774
`+
}
`
2800
2775
`}
`
``
2776
`+
exp /= 2;
`
``
2777
`+
base = base * base;
`
2801
2778
`}
`
2802
``
`-
exp /= 2;
`
2803
``
`-
base = base * base;
`
2804
2779
`}
`
2805
2780
`}
`
2806
2781
``