I’m researching SSA-IR, and I found that most types of Julia functions are determined by compile-time, as they’re converted to invoke
type from call
type with a MethodInstance
in code_typed
. But there are still some call
left there. Some of them are Core.Builtin
, so I guess it’s unnecessary to “optimize” them, as they’re not even generic functions. And others come with some throw
statements. The following code demonstrates it:
julia> function g()
println(string(1, "2"))
throw(string(2, "3"))
println(string(3, "4"))
end
g (generic function with 1 method)
julia> @code_typed g()
CodeInfo(
1 ─ %1 = Main.string(1, "2")::Any
│ Main.println(%1)::Any
│ %3 = Main.string(2, "3")::Any
│ Main.throw(%3)::Union{}
└── unreachable
) => Union{}
julia> function gg()
println(string(1, "2"))
println(string(3, "4"))
end
gg (generic function with 1 method)
julia> @code_typed gg()
CodeInfo(
1 ─ %1 = invoke Base.print_to_string(1::Int64, "2"::Vararg{Any})::String
│ invoke Main.println(%1::String)::Any
│ %3 = invoke Base.print_to_string(3::Int64, "4"::Vararg{Any})::String
│ %4 = invoke Main.println(%3::String)::Nothing
└── return %4
) => Nothing
julia> @code_typed optimize=false g()
CodeInfo(
1 ─ %1 = Main.string(1, "2")::Any
│ Main.println(%1)::Any
│ %3 = Main.string(2, "3")::Any
│ Main.throw(%3)::Union{}
│ Core.Const(:(Main.string(3, "4")))::Union{}
│ Core.Const(:(Main.println(%5)))::Union{}
└── Core.Const(:(return %6))::Union{}
) => Union{}
julia> @code_typed optimize=false gg()
CodeInfo(
1 ─ %1 = Main.string(1, "2")::String
│ Main.println(%1)::Any
│ %3 = Main.string(3, "4")::String
│ %4 = Main.println(%3)::Core.Const(nothing)
└── return %4
) => Nothing
I see no reason why the first string
call in the g
is not specialized like what happened in the gg
call. Maybe Julia considers it “unnecessary” as well since there’s an ensured throw
?