Skip to content

Commit

Permalink
inference: define InterConditional within Core.Compiler
Browse files Browse the repository at this point in the history
When I introduced this new lattice within #38905, I defined this in
`Core` for some performance reason, but now I'm sure it is really
necessary. Rather, it is easier to develop Julia-level inference routine
in pure Julia, so this commit moves the definition of `InterConditional`
to `Core.Compiler`.
  • Loading branch information
aviatesk committed May 30, 2022
1 parent 18bdbbf commit 29beb84
Show file tree
Hide file tree
Showing 8 changed files with 21 additions and 32 deletions.
1 change: 0 additions & 1 deletion base/boot.jl
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,6 @@ eval(Core, quote
Const(@nospecialize(v)) = $(Expr(:new, :Const, :v))
PartialStruct(typ::DataType, fields::Array{Any, 1}) = $(Expr(:new, :PartialStruct, :typ, :fields))
PartialOpaque(@nospecialize(typ), @nospecialize(env), parent::MethodInstance, source::Method) = $(Expr(:new, :PartialOpaque, :typ, :env, :parent, :source))
InterConditional(slot::Int, @nospecialize(vtype), @nospecialize(elsetype)) = $(Expr(:new, :InterConditional, :slot, :vtype, :elsetype))
MethodMatch(@nospecialize(spec_types), sparams::SimpleVector, method::Method, fully_covers::Bool) = $(Expr(:new, :MethodMatch, :spec_types, :sparams, :method, :fully_covers))
end)

Expand Down
24 changes: 13 additions & 11 deletions base/compiler/typelattice.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# structs/constants #
#####################

# N.B.: Const/PartialStruct/InterConditional are defined in Core, to allow them to be used
# N.B.: Const/PartialStruct are defined in Core, to allow them to be used
# inside the global code cache.
#
# # The type of a value might be constant
Expand Down Expand Up @@ -44,16 +44,18 @@ struct Conditional
end
end

# # Similar to `Conditional`, but conveys inter-procedural constraints imposed on call arguments.
# # This is separate from `Conditional` to catch logic errors: the lattice element name is InterConditional
# # while processing a call, then Conditional everywhere else. Thus InterConditional does not appear in
# # CompilerTypes—these type's usages are disjoint—though we define the lattice for InterConditional.
# struct InterConditional
# slot::Int
# vtype
# elsetype
# end
import Core: InterConditional
# Similar to `Conditional`, but conveys inter-procedural constraints imposed on call arguments.
# This is separate from `Conditional` to catch logic errors: the lattice element name is InterConditional
# while processing a call, then Conditional everywhere else. Thus InterConditional does not appear in
# CompilerTypes—these type's usages are disjoint—though we define the lattice for InterConditional.
struct InterConditional
slot::Int
vtype
elsetype
InterConditional(slot::Int, @nospecialize(vtype), @nospecialize(elsetype)) =
new(slot, vtype, elsetype)
end

const AnyConditional = Union{Conditional,InterConditional}

struct PartialTypeVar
Expand Down
1 change: 0 additions & 1 deletion src/builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -2010,7 +2010,6 @@ void jl_init_primitives(void) JL_GC_DISABLED
add_builtin("Const", (jl_value_t*)jl_const_type);
add_builtin("PartialStruct", (jl_value_t*)jl_partial_struct_type);
add_builtin("PartialOpaque", (jl_value_t*)jl_partial_opaque_type);
add_builtin("InterConditional", (jl_value_t*)jl_interconditional_type);
add_builtin("MethodMatch", (jl_value_t*)jl_method_match_type);
add_builtin("IntrinsicFunction", (jl_value_t*)jl_intrinsic_type);
add_builtin("Function", (jl_value_t*)jl_function_type);
Expand Down
1 change: 0 additions & 1 deletion src/jl_exported_data.inc
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@
XX(jl_int32_type) \
XX(jl_int64_type) \
XX(jl_int8_type) \
XX(jl_interconditional_type) \
XX(jl_interrupt_exception) \
XX(jl_intrinsic_type) \
XX(jl_lineinfonode_type) \
Expand Down
5 changes: 0 additions & 5 deletions src/jltypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -2576,11 +2576,6 @@ void jl_init_types(void) JL_GC_DISABLED
jl_svec2(jl_datatype_type, jl_array_any_type),
jl_emptysvec, 0, 0, 2);

jl_interconditional_type = jl_new_datatype(jl_symbol("InterConditional"), core, jl_any_type, jl_emptysvec,
jl_perm_symsvec(3, "slot", "vtype", "elsetype"),
jl_svec(3, jl_long_type, jl_any_type, jl_any_type),
jl_emptysvec, 0, 0, 3);

jl_method_match_type = jl_new_datatype(jl_symbol("MethodMatch"), core, jl_any_type, jl_emptysvec,
jl_perm_symsvec(4, "spec_types", "sparams", "method", "fully_covers"),
jl_svec(4, jl_type_type, jl_simplevector_type, jl_method_type, jl_bool_type),
Expand Down
1 change: 0 additions & 1 deletion src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -684,7 +684,6 @@ extern JL_DLLIMPORT jl_datatype_t *jl_argument_type JL_GLOBALLY_ROOTED;
extern JL_DLLIMPORT jl_datatype_t *jl_const_type JL_GLOBALLY_ROOTED;
extern JL_DLLIMPORT jl_datatype_t *jl_partial_struct_type JL_GLOBALLY_ROOTED;
extern JL_DLLIMPORT jl_datatype_t *jl_partial_opaque_type JL_GLOBALLY_ROOTED;
extern JL_DLLIMPORT jl_datatype_t *jl_interconditional_type JL_GLOBALLY_ROOTED;
extern JL_DLLIMPORT jl_datatype_t *jl_method_match_type JL_GLOBALLY_ROOTED;
extern JL_DLLIMPORT jl_datatype_t *jl_simplevector_type JL_GLOBALLY_ROOTED;
extern JL_DLLIMPORT jl_typename_t *jl_tuple_typename JL_GLOBALLY_ROOTED;
Expand Down
3 changes: 1 addition & 2 deletions src/staticdata.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ extern "C" {
// TODO: put WeakRefs on the weak_refs list during deserialization
// TODO: handle finalizers

#define NUM_TAGS 155
#define NUM_TAGS 154

// An array of references that need to be restored from the sysimg
// This is a manually constructed dual of the gvars array, which would be produced by codegen for Julia code, for C.
Expand Down Expand Up @@ -119,7 +119,6 @@ jl_value_t **const*const get_tags(void) {
INSERT_TAG(jl_const_type);
INSERT_TAG(jl_partial_struct_type);
INSERT_TAG(jl_partial_opaque_type);
INSERT_TAG(jl_interconditional_type);
INSERT_TAG(jl_method_match_type);
INSERT_TAG(jl_pinode_type);
INSERT_TAG(jl_phinode_type);
Expand Down
17 changes: 7 additions & 10 deletions test/compiler/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2034,17 +2034,14 @@ end
return nothing
end == Any[Union{Nothing,Expr}]

# handle the edge case
let ts = @eval Module() begin
edgecase(_) = $(Core.Compiler.InterConditional(2, Int, Any))
# create cache
Base.return_types(edgecase, (Any,))
Base.return_types((Any,)) do x
edgecase(x) ? x : nothing # ::Any
end
# handle edge case
@test (@eval Module() begin
edgecase(_) = $(Core.Compiler.InterConditional(2, Int, Any))
Base.return_types(edgecase, (Any,)) # create cache
Base.return_types((Any,)) do x
edgecase(x)
end
@test ts == Any[Any]
end
end) == Any[Core.Compiler.InterConditional]

# a tricky case: if constant inference derives `Const` while non-constant inference has
# derived `InterConditional`, we should not discard that constant information
Expand Down

0 comments on commit 29beb84

Please sign in to comment.