-
Notifications
You must be signed in to change notification settings - Fork 36
Closed
Description
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.
jrevels
Metadata
Metadata
Assignees
Labels
No labels