Revision a121721f975fc4105ed24ebd0ad1020d08d07a38 authored by Shuhei Kadowaki on 01 November 2021, 10:49:07 UTC, committed by GitHub on 01 November 2021, 10:49:07 UTC
* inference: form `PartialStruct` for extra type information propagation

This commit forms `PartialStruct` whenever there is any type-level
refinement available about a field, even if it's not "constant" information.

In Julia "definitions" are allowed to be abstract whereas "usages"
(i.e. callsites) are often concrete. The basic idea is to allow inference
to make more use of such precise callsite type information by encoding it
as `PartialStruct`.

This may increase optimization possibilities of "unidiomatic" Julia code,
which may contain poorly-typed definitions, like this very contrived example:
```julia
struct Problem
    n; s; c; t
end

function main(args...)
    prob = Problem(args...)
    s = 0
    for i in 1:prob.n
        m = mod(i, 3)
        s += m == 0 ? sin(prob.s) : m == 1 ? cos(prob.c) : tan(prob.t)
    end
    return prob, s
end

main(10000, 1, 2, 3)
```

One of the obvious limitation is that this extra type information can be
propagated inter-procedurally only as a const-propagation.
I'm not sure this kind of "just a type-level" refinement can often make
constant-prop' successful (i.e. shape-up a method body and allow it to
be inlined, encoding the extra type information into the generated code),
thus I didn't not modify any part of const-prop' heuristics.

So the improvements from this change might not be very useful for general
inter-procedural analysis currently, but they should definitely improve the
accuracy of local analysis and very simple inter-procedural analysis.
1 parent 6c274ed
Raw File
options.jl
# This file is a part of Julia. License is MIT: https://julialang.org/license

# NOTE: This type needs to be kept in sync with jl_options in src/julia.h
struct JLOptions
    quiet::Int8
    banner::Int8
    julia_bindir::Ptr{UInt8}
    julia_bin::Ptr{UInt8}
    commands::Ptr{Ptr{UInt8}} # (e)eval, (E)print, (L)load
    image_file::Ptr{UInt8}
    cpu_target::Ptr{UInt8}
    nthreads::Int32
    nprocs::Int32
    machine_file::Ptr{UInt8}
    project::Ptr{UInt8}
    isinteractive::Int8
    color::Int8
    historyfile::Int8
    startupfile::Int8
    compile_enabled::Int8
    code_coverage::Int8
    malloc_log::Int8
    opt_level::Int8
    opt_level_min::Int8
    debug_level::Int8
    check_bounds::Int8
    depwarn::Int8
    warn_overwrite::Int8
    can_inline::Int8
    polly::Int8
    trace_compile::Ptr{UInt8}
    fast_math::Int8
    worker::Int8
    cookie::Ptr{UInt8}
    handle_signals::Int8
    use_sysimage_native_code::Int8
    use_compiled_modules::Int8
    bindto::Ptr{UInt8}
    outputbc::Ptr{UInt8}
    outputunoptbc::Ptr{UInt8}
    outputo::Ptr{UInt8}
    outputasm::Ptr{UInt8}
    outputji::Ptr{UInt8}
    output_code_coverage::Ptr{UInt8}
    incremental::Int8
    image_file_specified::Int8
    warn_scope::Int8
    image_codegen::Int8
    rr_detach::Int8
end

# This runs early in the sysimage != is not defined yet
if sizeof(JLOptions) === ccall(:jl_sizeof_jl_options, Int, ())
else
    ccall(:jl_throw, Cvoid, (Any,), "Option structure mismatch")
end

JLOptions() = unsafe_load(cglobal(:jl_options, JLOptions))

function show(io::IO, opt::JLOptions)
    print(io, "JLOptions(")
    fields = fieldnames(JLOptions)
    nfields = length(fields)
    for (i, f) in enumerate(fields)
        v = getfield(opt, i)
        if isa(v, Ptr{UInt8})
            v = (v != C_NULL) ? unsafe_string(v) : ""
        elseif isa(v, Ptr{Ptr{UInt8}})
            v = unsafe_load_commands(v)
        end
        print(io, f, " = ", repr(v), i < nfields ? ", " : "")
    end
    print(io, ")")
end

function unsafe_load_commands(v::Ptr{Ptr{UInt8}})
    cmds = Pair{Char, String}[]
    v == C_NULL && return cmds
    i = 1
    while true
        s = unsafe_load(v, i)
        s == C_NULL && break
        e = Char(unsafe_load(s))
        push!(cmds, e => unsafe_string(s + 1))
        i += 1
    end
    return cmds
end
back to top