Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Constant folding/propagation of functions #11159

Closed
yuyichao opened this issue May 6, 2015 · 5 comments
Closed

Constant folding/propagation of functions #11159

yuyichao opened this issue May 6, 2015 · 5 comments

Comments

@yuyichao
Copy link
Contributor

yuyichao commented May 6, 2015

Not sure if there's already an issue for this or if this is covered by #3440 somehow. I brought it up here because this break type inference once I made invoke a generic function. This also affect other functions that take a function as a parameter (e.g. map). I can understand why it is impossible to do type inference on such a function as parameter, but maybe it can be done better when the function is inlined.

The constant folding doesn't even happen for user defined local variables (i.e. assign a generic function to a local variable) and for once a constant global is better than a local variable..... (This kind of code probably won't happen in user written code but it can probably be introduced in macros to avoid multiple evaluation of an argument)

@inline wrapper(f, args...) = f(args...)

f(args...) = args

g() = wrapper(f, 1, 2, 3)

const f2 = f
function h()
    f2(1, 2, 3)
end

function k()
    m = f
    m(1, 2, 3)
end

function l()
    f(1, 2, 3)
end

@code_warntype g()
println()
@code_warntype h()
println()
@code_warntype k()
println()
@code_warntype l()

Output

Variables:

Body:
  begin  # /home/yuyichao/tmp/julia/invoke-wrap.jl, line 7:
      GenSym(0) = f
      return (GenSym(0))(1,2,3)::ANY
  end::ANY

Variables:

Body:
  begin  # /home/yuyichao/tmp/julia/invoke-wrap.jl, line 11:
      return $(Expr(:call1, :(top(tuple)), 1, 2, 3))
  end::Tuple{Int64,Int64,Int64}

Variables:
  m::F

Body:
  begin  # /home/yuyichao/tmp/julia/invoke-wrap.jl, line 15:
      m = f # line 16:
      return (m::F)(1,2,3)::ANY
  end::ANY

Variables:

Body:
  begin  # /home/yuyichao/tmp/julia/invoke-wrap.jl, line 20:
      return $(Expr(:call1, :(top(tuple)), 1, 2, 3))
  end::Tuple{Int64,Int64,Int64}
@vtjnash
Copy link
Member

vtjnash commented May 6, 2015

const global is actually almost always better than a local, by nature of it being constant

yes, this is covered by #3440: "handle more constant conditions in inference"

@vtjnash vtjnash closed this as completed May 6, 2015
@yuyichao
Copy link
Contributor Author

yuyichao commented May 6, 2015

@vtjnash I was under the impression from #5148 that local constant is not necessary from the compiler point of view because it is smart enough to figure it out....

I guess having enough information to figure that out doesn't mean it is doing that....

@carnaval
Copy link
Contributor

carnaval commented May 6, 2015

The case of a single assigment local where the assignment is to a toplevel const is probably easy to hack into the compiler right now. If you want to do it, look for various kinds of static_eval in inference and codegen. The fact that a local is SA is already noted somewhere in the varinfo flags so it's just a matter of finding the assignment and static_evaling it.

It's only a special case though.

@yuyichao
Copy link
Contributor Author

yuyichao commented May 6, 2015

Thanks for the info and I might have a look at it when I want to do sth for fun =).

The fact that a local is SA is already noted somewhere in the varinfo flags

Does this mean a static checking version of #5148 should be almost trivial to implement?

@bramtayl
Copy link
Contributor

test(x) = if first((true, true, false))
    x
else
    "a"
end

@code_warntype test(1)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants