Skip to content

Const-prop through tuple #71

@maleadt

Description

@maleadt

The following fails to generate efficient code:

inner(::Type{Bool}, i) = nothing
outer(I...) = inner(Bool, I...)

using Cassette
Cassette.@context Ctx

f = (args...) -> Cassette.overdub(Ctx(), outer, args...)
code_warntype(f, Tuple{Int})
Body::ANY
10 1 ─ %1 = Cassette.overdub::Core.Compiler.Const(Cassette.overdub, false)
   │   %2 = (getfield)(args, 1)::Int64
   │   %3 = invoke %1($(QuoteNode(Cassette.Context{nametype(Ctx),Nothing,Cassette.NoPass,Nothing,Nothing}(nametype(Ctx)(), nothing, Cassette.NoPass(), nothing, nothing)))::Cassette.Context{nametype(Ctx),Nothing,Cassette.NoPass,Nothing,Nothing}, outer::typeof(outer), %2::Int64)::ANY
   └──      return %3

... whereas without overdubbing, we simply get:

Body::Nothing
2 1 ─     return

Checking the code for overdub reveals why we get the invoke:

code_warntype(Cassette.overdub, Tuple{typeof(Ctx()), typeof(outer), Int})
Body::ANY
2 1 ─ %1  = (Core.getfield)(##overdub_arguments#369, 2)::Int64
  │   %2  = (Core.tuple)(%1)::Tuple{Int64}
  └──       goto #3 if not true
  2 ─ %4  = Core.tuple::Core.Compiler.Const(tuple, false)
  │   %5  = Main.Bool::Core.Compiler.Const(Bool, false)
  └── %6  = (%4)(%5)::Tuple{DataType}
  3 ─ %7  = φ (#2 => %6, #1 => $(QuoteNode(Cassette.OverdubInstead())))::UNION{OVERDUBINSTEAD, TUPLE{DATATYPE}}
  │   %8  = π (%7, Core.Compiler.Const((Bool,), false))
  └──       goto #5 if not true
  4 ─ %10 = Core._apply::typeof(Core._apply)
  │   %11 = (%10)(tuple, %8, %2)::Tuple{DataType,Int64}
  │   %12 = (getfield)(%11, 1)::DATATYPE
  │   %13 = (getfield)(%11, 2)::Int64
  └── %14 = (Cassette.overdub)($(QuoteNode(Cassette.Context{nametype(Ctx),Nothing,Cassette.NoPass,Nothing,Nothing}(nametype(Ctx)(), nothing, Cassette.NoPass(), nothing, nothing))), inner, %12, %13)::ANY
  5 ─ %15 = φ (#4 => %14, #3 => $(QuoteNode(Cassette.OverdubInstead())))::ANY
  └──       return %15

Looks like a failure to const-prop the Bool argument through the argument tuple. But then again, the second element of the tuple isn't const, and I'm not sure whether that can be expressed with Compiler.Const.

This specific pattern arises with checkbounds(::Array, ::Integer) which calls to checkbounds(Bool, ...) (ie. passing a Type{Bool}), so this probably penalizes quite a lot of code as soon as it indexes arrays.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions