Repository: JuliaLang/julia
File: Compiler/src/ssair/inlining.jl (Julia)

Code before:
    end
    if @atomic(ci.invoke) == C_NULL
        # if invoke is still null after trying to compile the codeinstance, we just fall back
        # to the interpreter, which will handle errors, or falling back to the methodinstance.
        return false
    end
    if ir.valid_worlds.min_world < @atomic(ci.min_world) ||  @atomic(ci.max_world) < ir.valid_worlds.max_world
        # If the code instance has a world range that's inappropriate for our IR, fall
        # back to the interpreter which will raise an appropriate error
        return false
    end
    # Rebuild as: Expr(:invoke, CodeInstance, f, args...)
    stmt.head = :invoke
    stmt.args = Any[ci, stmt.args[2], stmt.args[4:end]...]
    return true
end

function handle_invoke_call!(todo::Vector{Pair{Int,Any}},
    ir::IRCode, idx::Int, stmt::Expr, @nospecialize(info), flag::UInt32,
    sig::Signature, state::InliningState)

    # Check for invoke with CodeInstance pattern and transform it
    # This allows invoke calls with CodeInstance to be resolved at compile time
    # Pattern: Expr(:call, invoke, f, ::CodeInstance, args...)
    # Transformed into: Expr(:invoke, ::CodeInstance, f, args...)
    if sig.f === Core.invoke && is_invoke_with_codeinstance(stmt, ir)
        if transform_invoke_codeinstance!(ir, idx, stmt)
            # Successfully transformed to :invoke, now handle it as such
            handle_invoke_expr!(todo, ir, idx, stmt, info, flag, sig, state)
            return nothing
        end
       # If transformation failed, fall through to normal invoke handling
    end

    nspl = nsplit(info)
    nspl == 0 && return nothing # e.g. InvokeCICallInfo
    @assert nspl == 1
    mresult = getsplit(info, 1)
    match = mresult.matches[1]
    if !match.fully_covers
        # TODO: We could union split out the signature check and continue on
        return nothing
    end
    result = getresult(info, 1)
    if isa(result, ConcreteResult)
        item = concrete_result_item(result, info, state)
    elseif isa(result, SemiConcreteResult)
        item = semiconcrete_result_item(result, info, flag, state)
    else
        argtypes = invoke_rewrite(sig.argtypes)
        if isa(result, InferenceResult)

Review comment (suggestion):
Note my comments in https://github.com/JuliaLang/julia/pull/60442#discussion_r2708095815 you should check that you have a `InvokeCICallInfo` and act on that

Code after:
function narrow_opaque_closure!(ir::IRCode, stmt::Expr, @nospecialize(info::CallInfo), state::InliningState)
    if isa(info, OpaqueClosureCreateInfo)
        lbt = argextype(stmt.args[2], ir)
        lb, exact = instanceof_tfunc(lbt)
        exact || return
        ubt = argextype(stmt.args[3], ir)
        ub, exact = instanceof_tfunc(ubt)
        exact || return
        # Narrow opaque closure type
        𝕃ₒ = optimizer_lattice(state.interp)
        newT = widenconst(tmeet(𝕃ₒ, tmerge(𝕃ₒ, lb, info.unspec.rt), ub))
        if newT != ub
            # N.B.: Narrowing the ub requires a backedge on the mi whose type
            # information we're using, since a change in that function may
            # invalidate ub result.
            stmt.args[3] = newT
        end
    end
end

# As a matter of convenience, this pass also computes effect-freenes.
# For primitives, we do that right here. For proper calls, we will
# discover this when we consult the caches.
add_inst_flag!(inst::Instruction, ir::IRCode, state::InliningState) =
    add_inst_flag!(inst, ir, optimizer_lattice(state.interp))
function add_inst_flag!(inst::Instruction, ir::IRCode, 𝕃ₒ::AbstractLattice)
    flags = recompute_effects_flags(𝕃ₒ, inst[:stmt], inst[:type], ir)
    add_flag!(inst, flags)
    return !iszero(flags & IR_FLAGS_REMOVABLE)
end

# Handles all analysis and inlining of intrinsics and builtins. In particular,
# this method does not access the method table or otherwise process generic
# functions.
function process_simple!(todo::Vector{Pair{Int,Any}}, ir::IRCode, idx::Int, flag::UInt32,
                         state::InliningState)
    inst = ir[SSAValue(idx)]
    stmt = inst[:stmt]
    if !(stmt isa Expr)
        add_inst_flag!(inst, ir, state)
        return nothing
    end
    rt = inst[:type]
    head = stmt.head
    if head !== :call
        if head === :splatnew
            inline_splatnew!(ir, idx, stmt, rt, state)
        elseif head === :new_opaque_closure
            narrow_opaque_closure!(ir, stmt, inst[:info], state)
        elseif head === :invoke
            sig = call_sig(ir, stmt)