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
}
1 Like
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
}
3 Likes
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
2 Likes
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
4 Likes
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
1 Like
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 )
2 Likes