Julia: Integer powers do not alway constant fold

Created on 12 Nov 2019  ยท  2Comments  ยท  Source: JuliaLang/julia

@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

Most helpful comment

Ok I feel less guilty about not openning an issue.

All 2 comments

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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

arshpreetsingh picture arshpreetsingh  ยท  3Comments

iamed2 picture iamed2  ยท  3Comments

omus picture omus  ยท  3Comments

yurivish picture yurivish  ยท  3Comments

StefanKarpinski picture StefanKarpinski  ยท  3Comments