What might have happened to *my* @code_warntype?

I run this command many times before and it used to print hundreds of lines, now it just print this (same for other @code_warntype calls to other functions)

julia> @code_warntype plot([0 0; 1 1]);
Variables
  #self#::Core.Const(GMT.plot)
  arg1::Matrix{Int64}

Body::Any
1 ─ %1 = Core.NamedTuple()::Core.Const(NamedTuple())
│   %2 = Base.pairs(%1)::Core.Const(Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}())
│   %3 = GMT.:(var"#plot#228")(true, %2, #self#, arg1)::Any
└──      return %3

Hopefully someone who knows more can help with this, but I’ve seen this happen when the functions I’m using @code_warntype on have keyword arguments:

function f1(a; b=2,c=3)
    a*b
    d = zeros(b, c*4)
end
julia> @code_warntype f1(1)
Variables
  #self#::Core.Compiler.Const(f1, false)
  a::Int64

Body::Array{Float64,2}
1 ─ %1 = Main.:(var"#f1#10")(2, 3, #self#, a)::Array{Float64,2}
└──      return %1

If I add the kwargs when using @code_warntype I get more output:

julia> @code_warntype f1(1;b=2,c=3)
Variables
  #unused#::Core.Compiler.Const(var"#f1##kw"(), false)
  @_2::NamedTuple{(:b, :c),Tuple{Int64,Int64}}
  @_3::Core.Compiler.Const(f1, false)
  a::Int64
  b::Int64
  c::Int64
  @_7::Int64
  @_8::Int64

Body::Array{Float64,2}
1 ─ %1  = Base.haskey(@_2, :b)::Core.Compiler.Const(true, false)
│         %1
│         (@_7 = Base.getindex(@_2, :b))
└──       goto #3
2 ─       Core.Compiler.Const(:(@_7 = 2), false)
3 ┄       (b = @_7)
│   %7  = Base.haskey(@_2, :c)::Core.Compiler.Const(true, false)
│         %7
│         (@_8 = Base.getindex(@_2, :c))
└──       goto #5
4 ─       Core.Compiler.Const(:(@_8 = 3), false)
5 ┄       (c = @_8)
│   %13 = (:b, :c)::Core.Compiler.Const((:b, :c), false)
│   %14 = Core.apply_type(Core.NamedTuple, %13)::Core.Compiler.Const(NamedTuple{(:b, :c),T} where T<:Tuple, false)
│   %15 = Base.structdiff(@_2, %14)::Core.Compiler.Const(NamedTuple(), false)
│   %16 = Base.pairs(%15)::Core.Compiler.Const(Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}(), false)
│   %17 = Base.isempty(%16)::Core.Compiler.Const(true, false)
│         %17
└──       goto #7
6 ─       Core.Compiler.Const(:(Base.kwerr(@_2, @_3, a)), false)
7 ┄ %21 = Main.:(var"#f1#10")(b, c, @_3, a)::Array{Float64,2}
└──       return %21
1 Like

To supplement what @mmiller said, if you define a function with keyword arguments, this gets ‘translated’ into an outer function dealing with the keyword arguments (the one you see), and some internal function which basically contains the body of your original function. In your example the function call you would want to see is

  %3 = GMT.:(var"#plot#228")(true, %2, #self#, arg1)::Any

To do @code_warntype on this, I recommend the use of GitHub - JuliaDebug/Cthulhu.jl: The slow descent into madness, which allows you to easily navigate to the function you really care about (once you are inside @descend, type w to toggle colors for warnings and o to toggle optimizations).

2 Likes

Thanks, you’re right. Consulting my repl_history.jl I found that the (very) long output is obtained when I call the function that does the work

@code_warntype GMT.common_plot_xyz("", [0.0 0.0; 1.0 1.0], "", true, false)

I have tried to use Cthulhu before, but for this example I just fall into a dead-end and cannot get inside the function of interests

# If I enter in %3 (which what I want)
Actions: [E]dit source code, [R]evise and redisplay
Advanced: dump [P]arams cache.
   %1  = NamedTuple()::Core.Const(NamedTuple())
   %2  = pairs(::NamedTuple{(), Tuple{}})::Core.Const(Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}())
 • %3  = #plot#228(::Bool,::Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}},::typeof(plot),::Matrix{Int64})::Any

I land in

Show: [S]ource code, [A]ST, [L]LVM IR, [N]ative code
Actions: [E]dit source code, [R]evise and redisplay
Advanced: dump [P]arams cache.
 • %2  = cat_1_arg(::Matrix{Int64})::Matrix{Int64}

from which I can’t do nothing but come back to previous step

Select a call to descend into or ↩ to ascend. [q]uit. [b]ookmark.
Toggles: [o]ptimize, [w]arn, [v]erbose printing for warntype code, [d]ebuginfo, [s]yntax highlight for Source/LLVM/Native.
Show: [S]ource code, [A]ST, [L]LVM IR, [N]ative code
Actions: [E]dit source code, [R]evise and redisplay
Advanced: dump [P]arams cache.

On a side note to this. I can’t understand how the return type of the length or string functions can by a Any

163 ─ %728  = GMT.string(val)::Any
or
%207  = GMT.length(gval)::Any

I can reproduce it. Might be a good idea to open an issue.

Ok, but let’s bother (sorry) @tim.holy first. He may have an explanation saying Sorry, that’s how it works