Skip to content

LICM for pure functions #29285

@SimonDanisch

Description

@SimonDanisch

Julia 1.0:

I just realized, that this is a gotcha one easily runs into, especially when using the @. macro:

a = rand(1000, 1000)
c = 1.0
out = similar(a)
julia> @btime $(out) .= $a .- sin.($c);
  5.695 ms (0 allocations: 0 bytes)
julia> @btime $(out) .= $a .- sin($c);
  495.669 μs (0 allocations: 0 bytes)

This likely happens because the compiler can't infer that sin is pure.
I realize, with having access to the call tree in the new lazy broadcast, we could solve this for a predefined set of functions.

First trick could be to just overload broadcasted for known signatures:

Base.Broadcast.broadcasted(::typeof(sin), x::Number) = sin(x)
@btime $out .= $a .+ sin.($c)

this solves the problem for a chosen set of functions.
We could also consider, if we introduce a purity trait to make this easier for multiple argument functions:

broadcasted(f, args...) = broadcasted(IsPure(f), f, args...)
broadcasted(::Pure{true}, f, args...) = f(args...) # should probably not get applied to arrays
broadcasted(::Pure{false}, f, args...) = Broadcasted(f, args...)

I guess this has been discussed before, but I couldn't really find an issue about it...

Metadata

Metadata

Assignees

No one assigned

    Labels

    compiler:optimizerOptimization passes (mostly in base/compiler/ssair/)featureIndicates new feature / enhancement requests

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions