@NHDaly and I found this the day before juliacon, but forgot to open an issue.
I think @Keno's theory was that the literal_pow stuff broke this.
Basically constant folding stops for exponents greater than 4.
julia> @code_typed (()->10^4)()
CodeInfo(
1 โ nothing::Nothing
2 โ %2 = ฯ (#1 => 10, #3 => %7)::Int64
โ %3 = ฯ (#1 => 3, #3 => %4)::Int64
โ %4 = Base.sub_int(%3, 1)::Int64
โ %5 = Base.slt_int(0, %4)::Bool
โโโ goto #4 if not %5
3 โ %7 = Base.mul_int(%2, %2)::Int64
โโโ goto #2
4 โ goto #5
5 โ goto #6
6 โ goto #7
7 โ return %2
) => Int64
julia> @code_typed (()->10^3)()
CodeInfo(
1 โ return 1000
) => Int64
julia> @code_typed (()->10^2)()
CodeInfo(
1 โ return 100
) => Int64
julia> @code_typed (()->10^1)()
CodeInfo(
1 โ return 10
) => Int64
julia> @code_typed (()->10^0)()
CodeInfo(
1 โ return 1
) => Int64
julia> @code_typed (()->10^-1)()
CodeInfo(
1 โ return 0.1
) => Float64
julia> @code_typed (()->10^-2)()
CodeInfo(
1 โ return 0.010000000000000002
) => Float64
julia> @code_typed (()->10^-3)()
CodeInfo(
1 โ return 0.0010000000000000002
) => Float64
julia> @code_typed (()->10^-4)()
CodeInfo(
1 โ %1 = $(Expr(:foreigncall, "llvm.pow.f64", Float64, svec(Float64, Float64), 0, :(:llvmcall), 0.1, 4.0, 4.0, 0.1))::Float64
โโโ return %1
) => Float64
LLVM actually has our back here though.
It will constant fold for all negative integer powers I think.
julia> @code_llvm (()->10^-4)()
; @ REPL[15]:1 within `#35'
define double @"julia_#35_16849"() {
top:
ret double 0x3F1A36E2EB1C432E
}
julia> @code_llvm (()->10^-100)()
; @ REPL[19]:1 within `#43'
define double @"julia_#43_16854"() {
top:
ret double 0x2B2BFF2EE48E055C
}
But for positive powers it only does 1 extra: 10^4
julia> @code_llvm (()->10^4)()
; @ REPL[16]:1 within `#37'
define i64 @"julia_#37_16850"() {
top:
ret i64 10000
}
julia> @code_llvm (()->10^5)()
; @ REPL[17]:1 within `#39'
define i64 @"julia_#39_16851"() {
L21.lr.ph:
; โ @ none within `literal_pow'
; โโ @ none within `macro expansion'
; โโโ @ intfuncs.jl:221 within `^'
; โโโโ @ intfuncs.jl:208 within `power_by_squaring'
br label %L21
L21: ; preds = %L21.lr.ph, %L21
%0 = phi i64 [ 1, %L21.lr.ph ], [ %2, %L21 ]
%value_phi35 = phi i64 [ 10, %L21.lr.ph ], [ %1, %L21 ]
; โโโโ @ intfuncs.jl:209 within `power_by_squaring'
; โโโโโ @ int.jl:54 within `*'
%1 = mul i64 %value_phi35, %value_phi35
; โโโโโ
; โโโโ @ intfuncs.jl:208 within `power_by_squaring'
; โโโโโ @ int.jl:52 within `-'
%2 = add nsw i64 %0, -1
; โโโโโ
; โโโโโ @ operators.jl:341 within `>='
; โโโโโโ @ int.jl:410 within `<='
%3 = icmp slt i64 %0, 1
; โโโโโโ
br i1 %3, label %L23, label %L21
L23: ; preds = %L21
%phitmp = mul i64 %1, 10
; โโโโ
ret i64 %phitmp
}
Was reminded when this came up in https://discourse.julialang.org/t/no-constant-expression-elimination-for-e-g-2-24-1/30964/8
Duplicate of #30126. Also, if it helps you figure out why it does this, it's only a problems with integers, and it does constant fold if the exponent is a power of two. So, the problem must be somewhere inpower_by_squaring.
Ok I feel less guilty about not openning an issue.
Most helpful comment
Ok I feel less guilty about not openning an issue.