File: queries.jl

package info (click to toggle)
julia 1.0.3%2Bdfsg-4
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 49,452 kB
  • sloc: lisp: 236,453; ansic: 55,579; cpp: 25,603; makefile: 1,685; pascal: 1,130; sh: 956; asm: 86; xml: 76
file content (78 lines) | stat: -rw-r--r-- 3,222 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# This file is a part of Julia. License is MIT: https://julialang.org/license

"""
Determine whether a statement is side-effect-free, i.e. may be removed if it has no uses.
"""
function stmt_effect_free(@nospecialize(stmt), @nospecialize(rt), src, spvals::SimpleVector)
    isa(stmt, Union{PiNode, PhiNode}) && return true
    isa(stmt, Union{ReturnNode, GotoNode, GotoIfNot}) && return false
    isa(stmt, GlobalRef) && return isdefined(stmt.mod, stmt.name)
    isa(stmt, Slot) && return false # Slots shouldn't occur in the IR at this point, but let's be defensive here
    if isa(stmt, Expr)
        e = stmt::Expr
        head = e.head
        if head === :static_parameter
            etyp = sparam_type(spvals[e.args[1]])
            # if we aren't certain enough about the type, it might be an UndefVarError at runtime
            return isa(etyp, Const) || issingletontype(widenconst(etyp))
        end
        ea = e.args
        if head === :call
            f = argextype(ea[1], src, spvals)
            f = isa(f, Const) ? f.val : isType(f) ? f.parameters[1] : return false
            f === return_type && return true
            contains_is(_PURE_BUILTINS, f) && return true
            contains_is(_PURE_OR_ERROR_BUILTINS, f) || return false
            rt === Bottom && return false
            return _builtin_nothrow(f, Any[argextype(ea[i], src, spvals) for i = 2:length(ea)], rt)
        elseif head === :new
            a = ea[1]
            typ = argextype(a, src, spvals)
            # `Expr(:new)` of unknown type could raise arbitrary TypeError.
            typ, isexact = instanceof_tfunc(typ)
            isexact || return false
            isconcretedispatch(typ) || return false
            typ = typ::DataType
            fieldcount(typ) >= length(ea) - 1 || return false
            for fld_idx in 1:(length(ea) - 1)
                eT = argextype(ea[fld_idx + 1], src, spvals)
                fT = fieldtype(typ, fld_idx)
                eT ⊑ fT || return false
            end
            return true
        elseif head === :isdefined || head === :the_exception || head === :copyast || head === :inbounds || head === :boundscheck
            return true
        else
            # e.g. :simdloop
            return false
        end
    end
    return true
end

function abstract_eval_ssavalue(s::SSAValue, src::IRCode)
    return types(src)[s]
end

function abstract_eval_ssavalue(s::SSAValue, src::IncrementalCompact)
    return types(src)[s]
end

function compact_exprtype(compact::IncrementalCompact, @nospecialize(value))
    if isa(value, AnySSAValue)
        return types(compact)[value]
    elseif isa(value, Argument)
        return compact.ir.argtypes[value.n]
    end
    return argextype(value, compact.ir, compact.ir.spvals)
end

is_tuple_call(ir::IRCode, @nospecialize(def)) = isa(def, Expr) && is_known_call(def, tuple, ir, ir.spvals)
is_tuple_call(compact::IncrementalCompact, @nospecialize(def)) = isa(def, Expr) && is_known_call(def, tuple, compact)
function is_known_call(e::Expr, @nospecialize(func), src::IncrementalCompact)
    if e.head !== :call
        return false
    end
    f = compact_exprtype(src, e.args[1])
    return isa(f, Const) && f.val === func
end