Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integer powers do not alway constant fold #33822

Closed
oxinabox opened this issue Nov 12, 2019 · 2 comments
Closed

Integer powers do not alway constant fold #33822

oxinabox opened this issue Nov 12, 2019 · 2 comments

Comments

@oxinabox
Copy link
Contributor

oxinabox commented Nov 12, 2019

@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

@jakobnissen
Copy link
Contributor

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.

@oxinabox
Copy link
Contributor Author

Ok I feel less guilty about not openning an issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants