|
| 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 | +// 2 ** n == 2 ** (1 * n) == 1 << (1 * n) |
| 8 | +// CHECK-LABEL: @pow2 |
| 9 | +#[no_mangle] |
| 10 | +pub fn pow2(exp: u32) -> u32 { |
| 11 | + // CHECK: %[[OVERFLOW:.+]] = icmp ult i32 %exp, 32 |
| 12 | + // CHECK: %[[POW:.+]] = shl nuw i32 1, %exp |
| 13 | + // CHECK: %[[RET:.+]] = select i1 %[[OVERFLOW]], i32 %[[POW]], i32 0 |
| 14 | + // CHECK: ret i32 %[[RET]] |
| 15 | + 2u32.pow(exp) |
| 16 | +} |
| 17 | + |
| 18 | +// 4 ** n == 2 ** (2 * n) == 1 << (2 * n) |
| 19 | +// CHECK-LABEL: @pow4 |
| 20 | +#[no_mangle] |
| 21 | +pub fn pow4(exp: u32) -> u32 { |
| 22 | + // CHECK: %[[ICMP1:.+]] = icmp slt i32 %exp, 0 |
| 23 | + // CHECK: %[[SHIFT_AMOUNT:.+]] = shl i32 %exp, 1 |
| 24 | + // CHECK: %[[ICMP2:.+]] = icmp ult i32 %[[SHIFT_AMOUNT]], 32 |
| 25 | + // CHECK: %[[POW:.+]] = shl nuw i32 1, %[[SHIFT_AMOUNT]] |
| 26 | + // CHECK: %[[SEL:.+]] = select i1 %[[ICMP2]], i32 %[[POW]], i32 0 |
| 27 | + // CHECK: %[[RET:.+]] = select i1 %[[ICMP1]], i32 0, i32 %[[SEL]] |
| 28 | + // CHECK: ret i32 %[[RET]] |
| 29 | + 4u32.pow(exp) |
| 30 | +} |
| 31 | + |
| 32 | +// 16 ** n == 2 ** (4 * n) == 1 << (4 * n) |
| 33 | +// CHECK-LABEL: @pow16 |
| 34 | +#[no_mangle] |
| 35 | +pub fn pow16(exp: u32) -> u32 { |
| 36 | + // CHECK: %[[ICMP1:.+]] = icmp ugt i32 %exp, 1073741823 |
| 37 | + // CHECK: %[[SHIFT_AMOUNT:.+]] = shl i32 %exp, 2 |
| 38 | + // CHECK: %[[ICMP2:.+]] = icmp ult i32 %[[SHIFT_AMOUNT]], 32 |
| 39 | + // CHECK: %[[POW:.+]] = shl nuw i32 1, %[[SHIFT_AMOUNT]] |
| 40 | + // CHECK: %[[SEL:.+]] = select i1 %[[ICMP2]], i32 %[[POW]], i32 0 |
| 41 | + // CHECK: %[[RET:.+]] = select i1 %[[ICMP1]], i32 0, i32 %[[SEL]] |
| 42 | + // CHECK: ret i32 %[[RET]] |
| 43 | + 16u32.pow(exp) |
| 44 | +} |
| 45 | + |
| 46 | +// (-2) ** n == (-2) ** (1 * n) == 1 << (1 * n) |
| 47 | +// CHECK-LABEL: @pow_minus_2 |
| 48 | +#[no_mangle] |
| 49 | +pub fn pow_minus_2(exp: u32) -> i32 { |
| 50 | + // CHECK: %[[OVERFLOW:.+]] = icmp ult i32 %exp, 32 |
| 51 | + // CHECK: %[[POW:.+]] = shl nuw i32 1, %exp |
| 52 | + // CHECK: %[[MAGNITUDE:.+]] = select i1 %[[OVERFLOW]], i32 %[[POW]], i32 0 |
| 53 | + // CHECK: %[[IS_ODD:.+]] = and i32 %exp, 1 |
| 54 | + // CHECK: %[[IS_EVEN:.+]] = icmp eq i32 %[[IS_ODD]], 0 |
| 55 | + // CHECK: %[[NEG:.+]] = sub i32 0, %[[MAGNITUDE]] |
| 56 | + // CHECK: %[[RET:.+]] = select i1 %[[IS_EVEN]], i32 %[[MAGNITUDE]], i32 %[[NEG]] |
| 57 | + // CHECK: ret i32 %[[RET]] |
| 58 | + (-2i32).pow(exp) |
| 59 | +} |
0 commit comments