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

Code before:
# Transforms: Expr(:call, invoke, f, ::CodeInstance, args...)
# Into: Expr(:invoke, ::CodeInstance, f, args...)
function transform_invoke_codeinstance!(ir::IRCode, idx::Int, stmt::Expr)
    # Extract the CodeInstance from stmt.args[3]
    ci_arg = stmt.args[3]

    # Resolve to actual CodeInstance if needed
    ci::CodeInstance = if isa(ci_arg, CodeInstance)
        ci_arg
    else
        ci_type = argextype(ci_arg, ir)
        if isa(ci_type, Const) && isa(ci_type.val, CodeInstance)
            ci_type.val
        else
            return false
        end
    end
    if @atomic(ci.invoke) == C_NULL
        @ccall jl_compile_codeinst(ci::Any)::Nothing
    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

Review comment (bug):
World range comparisons seem incorrect here. The seq-cst atomic here which fails to sequence anything should have been a hint that this is dangerously unsynchronized and needs to be done more carefully elsewhere

Code after:
            mi = result.linfo
            validate_sparams(mi.sparam_vals) || return nothing
            if Union{} !== argtypes_to_type(argtypes) <: mi.def.sig
                item = resolve_todo(mi, result, info, flag, state)
                handle_single_case!(todo, ir, idx, stmt, item, true)
                return nothing
            end
        end
        item = analyze_method!(result, match, argtypes, info, flag, state; allow_typevars=false)
    end
    handle_single_case!(todo, ir, idx, stmt, item, true)
    return nothing
end

function invoke_signature(argtypes::Vector{Any})
    ft, argtyps = widenconst(argtypes[2]), instanceof_tfunc(widenconst(argtypes[3]), false)[1]
    return rewrap_unionall(Tuple{ft, unwrap_unionall(argtyps).parameters...}, argtyps)
end

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,