Julia: Allow splicing constants into `@code_warntype` to represent constant propagation

Created on 28 Dec 2017  Â·  9Comments  Â·  Source: JuliaLang/julia

Ref: https://github.com/JuliaLang/julia/pull/24362

Hi all, the above Ref is was to merge IPO constant propagation, but this still doesn't
seem to be working. The following code compiles conditionally with Val{B}

function myFun(::Type{Val{B}}, x::Int) where {B}
  if B
    println("B is true")
  else
    println("B is false")
  end
  return x
end

@code_warntype myFun(Val{true}, 2)
Variables:
  x::Int64

Body:
  begin
      #= line 3 =#
      $(Expr(:invoke, MethodInstance for println(::String), :(Main.println), "B is true"))::Nothing
      goto 5
      #= line 5 =#
      5: 
      #= line 7 =#
      return x::Int64
  end::Int64

But not conditionally with B::Bool

function myFun(B::Bool, x::Int)
  if B
    println("B is true")
  else
    println("B is false")
  end
  return x
end

# Should optimise over B = true but does not.
@code_warntype myFun(true, 2)
Variables:
  B::Bool
  x::Int64

Body:
  begin
      unless B::Bool goto 5
      #= line 3 =#
      $(Expr(:invoke, MethodInstance for println(::String), :(Main.println), "B is true"))::Nothing
      goto 8
      5: 
      #= line 5 =#
      $(Expr(:invoke, MethodInstance for println(::String), :(Main.println), "B is false"))::Nothing
      8: 
      #= line 7 =#
      return x::Int64
  end::Int64

I used it with Julia 0.7.0-dev downloaded today, so its the latest compiler.

Thank you.

Most helpful comment

Speaking with @keno in the Slack, it would make sense if @code_warntype myFun($true, $2) handled the constants correctly. Could someone check if it does, and if it doesn't, I think that's a worthwhile feature request.

All 9 comments

That’s just the code_warntype behavior, IPO (inter-procedural) requires that you actually have an outer proceedure to infer between.

How do we verify that it is working?

Here's a test case showing the difference between 0.6.2 and 0.7.

julia> function test(x)
              x ? 1 : 2
              end
test (generic function with 1 method)

julia> function test2()
              y = true
              test(y)
              end
test2 (generic function with 1 method)

julia> test2()
1

On 0.6, you get this:

julia> @code_warntype test2()
Variables:
  #self# <optimized out>
  y::Bool
  #temp#::Int64

Body:
  begin 
      y::Bool = true # line 3:
      $(Expr(:inbounds, false))
      # meta: location REPL[1] test 2
      unless y::Bool goto 8
      #temp#::Int64 = 1
      goto 10
      8: 
      #temp#::Int64 = 2
      10: 
      # meta: pop location
      $(Expr(:inbounds, :pop))
      return #temp#::Int64
  end::Int64

However, on 0.7 the constant is propagated into test.

julia> @code_warntype test2()
Variables:

Body:
  begin
      return 1
  end::Int64

I believe this is the IPO, but I'm not an expert.

Thanks @aaowens, I'm certainly no IPO expert either. Does this then not raise the need for some kind of const identifier for function arguments to make full use of this feature?

Not necessarily. You know it’s working the same way you know any other optimization is working: trust, but verify, with @profile.

Speaking with @keno in the Slack, it would make sense if @code_warntype myFun($true, $2) handled the constants correctly. Could someone check if it does, and if it doesn't, I think that's a worthwhile feature request.

Reopen to implement the splicing syntax here.

As proposed here, this would introduce a bit of a strange disconnect with @benchmark — it'd mean exactly the opposite thing. Not sure I have any good ideas here, but figured I'd update the title to represent the proposed action-item.

Not into @code_warntype but at least in a replacement of Test.@inferred:
https://discourse.julialang.org/t/pre-ann-rfc-testextras-jl/46487

Was this page helpful?
0 / 5 - 0 ratings