Skip to content

Commit c84b99e

Browse files
committed
Optimize pow when self is a power of two
if base == 2 ** k, then (2 ** k) ** n == 2 ** (k * n) == 1 << (k * n)
1 parent 6dc9604 commit c84b99e

File tree

2 files changed

+48
-0
lines changed

2 files changed

+48
-0
lines changed

library/core/src/num/uint_macros.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3314,6 +3314,18 @@ macro_rules! uint_impl {
33143314
let mut base = self;
33153315
let mut acc = 1;
33163316

3317+
if intrinsics::is_val_statically_known(base) {
3318+
// change of base:
3319+
// if base == 2 ** k, then
3320+
// (2 ** k) ** n
3321+
// == 2 ** (k * n)
3322+
// == 1 << (k * n)
3323+
if base.is_power_of_two() {
3324+
let k = base.ilog2();
3325+
return 1 << (k * exp)
3326+
}
3327+
}
3328+
33173329
if intrinsics::is_val_statically_known(exp) {
33183330
while exp > 1 {
33193331
if (exp & 1) == 1 {
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//@ compile-flags: -Copt-level=3
2+
// Test that `pow` can use a faster implementation when `base` is a
3+
// known power of two
4+
5+
#![crate_type = "lib"]
6+
7+
// CHECK-LABEL: @pow2
8+
#[no_mangle]
9+
pub fn pow2(exp: u32) -> u32 {
10+
// CHECK: %[[SHIFT_AMOUNT:.+]] = and i32 %exp, 31
11+
// CHECK: %[[POW2:.+]] = shl nuw i32 1, %[[SHIFT_AMOUNT]]
12+
// CHECK: ret i32 %[[POW2]]
13+
2u32.pow(exp)
14+
}
15+
16+
// 4 ** n == 2 ** (2 * n) == 1 << (2 * n)
17+
// CHECK-LABEL: @pow4
18+
#[no_mangle]
19+
pub fn pow4(exp: u32) -> u32 {
20+
// CHECK: %[[EXP2:.+]] = shl i32 %exp, 1
21+
// CHECK: %[[SHIFT_AMOUNT:.+]] = and i32 %[[EXP2]], 30
22+
// CHECK: %[[POW4:.+]] = shl nuw nsw i32 1, %[[SHIFT_AMOUNT]]
23+
// CHECK: ret i32 %[[POW4]]
24+
4u32.pow(exp)
25+
}
26+
27+
// 16 ** n == 2 ** (4 * n) == 1 << (4 * n)
28+
// CHECK-LABEL: @pow16
29+
#[no_mangle]
30+
pub fn pow16(exp: u32) -> u32 {
31+
// CHECK: %[[EXP2:.+]] = shl i32 %exp, 2
32+
// CHECK: %[[SHIFT_AMOUNT:.+]] = and i32 %[[EXP2]], 28
33+
// CHECK: %[[POW16:.+]] = shl nuw nsw i32 1, %[[SHIFT_AMOUNT]]
34+
// CHECK: ret i32 %[[POW16]]
35+
16u32.pow(exp)
36+
}

0 commit comments

Comments
 (0)