Is there a limit in the depth of a tree for constant propagation? I have seen that rather long expressions involving only constants are not completely replaced by their result:
julia> c() = log(log(log(log(2*π) + 2) + π) + tanh(3 + π))
c (generic function with 1 method)
julia> @code_llvm c()
; @ REPL[28]:1 within `c'
define double @julia_c_874() {
top:
%0 = call double @j_log_876(double 0x400EB3F8E4325F5A)
; ┌ @ promotion.jl:321 within `+' @ float.jl:326
%1 = fadd double %0, 0x400921FB54442D18
; └
%2 = call double @j_log_877(double %1)
; ┌ @ float.jl:326 within `+'
%3 = fadd double %2, 0x3FEFFFEC95BFEC1C
; └
%4 = call double @j_log_878(double %3)
ret double %4
}
Not answering your question, but with Julia v1.7 I get
julia> c() = log(log(log(log(2*π) + 2) + π) + tanh(3 + π))
c (generic function with 1 method)
julia> @code_llvm c()
; @ REPL[1]:1 within `c`
define double @julia_c_181() #0 {
top:
ret double 0x3FED55BF3C312E04
}
jw3126
December 13, 2021, 10:18am
3
Also not an answer, but with @code_warntype you can see nicely where i breaks down:
julia> c() = sin(sin(sin(sin(1)))); @code_warntype c()
MethodInstance for c()
from c() in Main at REPL[21]:1
Arguments
#self#::Core.Const(c)
Body::Float64
1 ─ %1 = Main.sin(1)::Core.Const(0.8414709848078965)
│ %2 = Main.sin(%1)::Core.Const(0.7456241416655579)
│ %3 = Main.sin(%2)::Float64
│ %4 = Main.sin(%3)::Float64
└── return %4
That’s a good suggestion, compare v1.6 vs v1.7:
# v1.6
julia> @code_warntype c()
Variables
#self#::Core.Const(c)
Body::Float64
1 ─ %1 = (2 * Main.π)::Core.Const(6.283185307179586)
│ %2 = Main.log(%1)::Float64
│ %3 = (%2 + 2)::Float64
│ %4 = Main.log(%3)::Float64
│ %5 = (%4 + Main.π)::Float64
│ %6 = Main.log(%5)::Float64
│ %7 = (3 + Main.π)::Core.Const(6.141592653589793)
│ %8 = Main.tanh(%7)::Core.Const(0.9999907421873817)
│ %9 = (%6 + %8)::Float64
│ %10 = Main.log(%9)::Float64
└── return %10
# v1.7
julia> @code_warntype c()
MethodInstance for c()
from c() in Main at REPL[1]:1
Arguments
#self#::Core.Const(c)
Body::Float64
1 ─ %1 = (2 * Main.π)::Core.Const(6.283185307179586)
│ %2 = Main.log(%1)::Core.Const(1.8378770664093453)
│ %3 = (%2 + 2)::Core.Const(3.8378770664093453)
│ %4 = Main.log(%3)::Core.Const(1.3449193664339925)
│ %5 = (%4 + Main.π)::Core.Const(4.486512020023786)
│ %6 = Main.log(%5)::Core.Const(1.5010755669062448)
│ %7 = (3 + Main.π)::Core.Const(6.141592653589793)
│ %8 = Main.tanh(%7)::Core.Const(0.9999907421873817)
│ %9 = (%6 + %8)::Core.Const(2.5010663090936265)
│ %10 = Main.log(%9)::Core.Const(0.9167171645762555)
└── return %10
So presumably this is something present in Julia 1.6 and solved already (at least up to this depth) in Julia 1.7. Another good reason to upgrade then…
lungben
December 13, 2021, 5:00pm
6
Yes, details are given here: Julia 1.7 Highlights
N5N3
December 21, 2021, 3:15am
7
For this case const propgate was blocked by sqrt:
c() = sin(sin(sin(sin(1)))); @code_typed c()
CodeInfo(
1 ─ %1 = Base.Math.sqrt_llvm(2.220446049250313e-16)::Float64
│ %2 = Base.lt_float(0.7456241416655579, %1)::Bool
└── goto #3 if not %2
2 ─ goto #4
3 ─ goto #4
4 ┄ %6 = φ (#2 => 0.7456241416655579, #3 => 0.6784304773607402)::Float64
│ %7 = invoke Main.sin(%6::Float64)::Float64
└── return %7
) => Float64
And looks like we disable it for correctness, see (https://github.com/JuliaLang/julia/blob/3a3cf028eb5e3138b0dfe5e31efce7f87f5cbfe3/base/compiler/optimize.jl#L547-L556 )