Skip to content

Commit

Permalink
Add a macro to opt into aggressive constprop
Browse files Browse the repository at this point in the history
Right now aggressive constprop is essentially tied to the inlining
threshold (or to their name being `getproperty` or `setproperty!`
respectively, which can be both somewhat brittle if the inlining cost
changes and insufficient when you do really know that const prop
would be beneficial even if the function is not inlineable. This
adds a simple macro that can be used to manually annotate methods
to force aggressive constprop on them.
  • Loading branch information
Keno committed Oct 17, 2020
1 parent d9d8fd3 commit 11fcf8b
Show file tree
Hide file tree
Showing 10 changed files with 50 additions and 9 deletions.
2 changes: 1 addition & 1 deletion base/compiler/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ function abstract_call_method_with_const_args(interp::AbstractInterpreter, @nosp
istopfunction(f, :<<) || istopfunction(f, :>>))
return Any
end
force_inference = allconst || InferenceParams(interp).aggressive_constant_propagation
force_inference = allconst || method.aggressive_constprop || InferenceParams(interp).aggressive_constant_propagation
if istopfunction(f, :getproperty) || istopfunction(f, :setproperty!)
force_inference = true
end
Expand Down
13 changes: 13 additions & 0 deletions base/expr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,19 @@ macro pure(ex)
esc(isa(ex, Expr) ? pushmeta!(ex, :pure) : ex)
end

"""
@aggressive_constprop ex
@aggressive_constprop(ex)
`@aggressive_constprop` requests more aggressive interprocedural constant
propagation for the annotated function. For function where the return type
depends on the value of the arguments, this can yield improved inference results
at the cost of additional compile time.
"""
macro aggressive_constprop(ex)
esc(isa(ex, Expr) ? pushmeta!(ex, :aggressive_constprop) : ex)
end

"""
@propagate_inbounds
Expand Down
2 changes: 2 additions & 0 deletions src/ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ jl_sym_t *static_parameter_sym; jl_sym_t *inline_sym;
jl_sym_t *noinline_sym; jl_sym_t *generated_sym;
jl_sym_t *generated_only_sym; jl_sym_t *isdefined_sym;
jl_sym_t *propagate_inbounds_sym; jl_sym_t *specialize_sym;
jl_sym_t *aggressive_constprop_sym;
jl_sym_t *nospecialize_sym; jl_sym_t *macrocall_sym;
jl_sym_t *colon_sym; jl_sym_t *hygienicscope_sym;
jl_sym_t *throw_undef_if_not_sym; jl_sym_t *getfield_undefref_sym;
Expand Down Expand Up @@ -381,6 +382,7 @@ void jl_init_common_symbols(void)
noinline_sym = jl_symbol("noinline");
polly_sym = jl_symbol("polly");
propagate_inbounds_sym = jl_symbol("propagate_inbounds");
aggressive_constprop_sym = jl_symbol("aggressive_constprop");
isdefined_sym = jl_symbol("isdefined");
nospecialize_sym = jl_symbol("nospecialize");
specialize_sym = jl_symbol("specialize");
Expand Down
2 changes: 2 additions & 0 deletions src/dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,7 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li
write_int32(s->s, m->nkw);
write_int8(s->s, m->isva);
write_int8(s->s, m->pure);
write_int8(s->s, m->aggressive_constprop);
jl_serialize_value(s, (jl_value_t*)m->slot_syms);
jl_serialize_value(s, (jl_value_t*)m->roots);
jl_serialize_value(s, (jl_value_t*)m->ccallable);
Expand Down Expand Up @@ -1410,6 +1411,7 @@ static jl_value_t *jl_deserialize_value_method(jl_serializer_state *s, jl_value_
m->nkw = read_int32(s->s);
m->isva = read_int8(s->s);
m->pure = read_int8(s->s);
m->aggressive_constprop = read_int8(s->s);
m->slot_syms = jl_deserialize_value(s, (jl_value_t**)&m->slot_syms);
jl_gc_wb(m, m->slot_syms);
m->roots = (jl_array_t*)jl_deserialize_value(s, (jl_value_t**)&m->roots);
Expand Down
4 changes: 3 additions & 1 deletion src/ircode.c
Original file line number Diff line number Diff line change
Expand Up @@ -702,7 +702,8 @@ JL_DLLEXPORT jl_array_t *jl_compress_ir(jl_method_t *m, jl_code_info_t *code)
jl_get_ptls_states()
};

uint8_t flags = (code->inferred << 3)
uint8_t flags = (code->aggressive_constprop << 4)
| (code->inferred << 3)
| (code->inlineable << 2)
| (code->propagate_inbounds << 1)
| (code->pure << 0);
Expand Down Expand Up @@ -787,6 +788,7 @@ JL_DLLEXPORT jl_code_info_t *jl_uncompress_ir(jl_method_t *m, jl_code_instance_t

jl_code_info_t *code = jl_new_code_info_uninit();
uint8_t flags = read_uint8(s.s);
code->aggressive_constprop = !!(flags & (1 << 4));
code->inferred = !!(flags & (1 << 3));
code->inlineable = !!(flags & (1 << 2));
code->propagate_inbounds = !!(flags & (1 << 1));
Expand Down
18 changes: 11 additions & 7 deletions src/jltypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -2239,7 +2239,7 @@ void jl_init_types(void) JL_GC_DISABLED
jl_code_info_type =
jl_new_datatype(jl_symbol("CodeInfo"), core,
jl_any_type, jl_emptysvec,
jl_perm_symsvec(18,
jl_perm_symsvec(19,
"code",
"codelocs",
"ssavaluetypes",
Expand All @@ -2257,8 +2257,9 @@ void jl_init_types(void) JL_GC_DISABLED
"inferred",
"inlineable",
"propagate_inbounds",
"pure"),
jl_svec(18,
"pure",
"aggressive_constprop"),
jl_svec(19,
jl_array_any_type,
jl_array_int32_type,
jl_any_type,
Expand All @@ -2276,13 +2277,14 @@ void jl_init_types(void) JL_GC_DISABLED
jl_bool_type,
jl_bool_type,
jl_bool_type,
jl_bool_type,
jl_bool_type),
0, 1, 18);
0, 1, 19);

jl_method_type =
jl_new_datatype(jl_symbol("Method"), core,
jl_any_type, jl_emptysvec,
jl_perm_symsvec(22,
jl_perm_symsvec(23,
"name",
"module",
"file",
Expand All @@ -2304,8 +2306,9 @@ void jl_init_types(void) JL_GC_DISABLED
"nospecialize",
"nkw",
"isva",
"pure"),
jl_svec(22,
"pure",
"aggressive_constprop"),
jl_svec(23,
jl_symbol_type,
jl_module_type,
jl_symbol_type,
Expand All @@ -2327,6 +2330,7 @@ void jl_init_types(void) JL_GC_DISABLED
jl_int32_type,
jl_int32_type,
jl_bool_type,
jl_bool_type,
jl_bool_type),
0, 1, 10);

Expand Down
2 changes: 2 additions & 0 deletions src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@ typedef struct _jl_code_info_t {
uint8_t inlineable;
uint8_t propagate_inbounds;
uint8_t pure;
uint8_t aggressive_constprop;
} jl_code_info_t;

// This type describes a single method definition, and stores data
Expand Down Expand Up @@ -327,6 +328,7 @@ typedef struct _jl_method_t {
// of another method.
uint8_t isva;
uint8_t pure;
uint8_t aggressive_constprop;

// hidden fields:
// lock for modifications to the method
Expand Down
1 change: 1 addition & 0 deletions src/julia_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -1256,6 +1256,7 @@ extern jl_sym_t *static_parameter_sym; extern jl_sym_t *inline_sym;
extern jl_sym_t *noinline_sym; extern jl_sym_t *generated_sym;
extern jl_sym_t *generated_only_sym; extern jl_sym_t *isdefined_sym;
extern jl_sym_t *propagate_inbounds_sym; extern jl_sym_t *specialize_sym;
extern jl_sym_t *aggressive_constprop_sym;
extern jl_sym_t *nospecialize_sym; extern jl_sym_t *macrocall_sym;
extern jl_sym_t *colon_sym; extern jl_sym_t *hygienicscope_sym;
extern jl_sym_t *throw_undef_if_not_sym; extern jl_sym_t *getfield_undefref_sym;
Expand Down
3 changes: 3 additions & 0 deletions src/method.c
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,8 @@ static void jl_code_info_set_ir(jl_code_info_t *li, jl_expr_t *ir)
li->inlineable = 1;
else if (ma == (jl_value_t*)propagate_inbounds_sym)
li->propagate_inbounds = 1;
else if (ma == (jl_value_t*)aggressive_constprop_sym)
li->aggressive_constprop = 1;
else
jl_array_ptr_set(meta, ins++, ma);
}
Expand Down Expand Up @@ -512,6 +514,7 @@ static void jl_method_set_source(jl_method_t *m, jl_code_info_t *src)
}
m->called = called;
m->pure = src->pure;
m->aggressive_constprop = src->aggressive_constprop;
jl_add_function_name_to_lineinfo(src, (jl_value_t*)m->name);

jl_array_t *copy = NULL;
Expand Down
12 changes: 12 additions & 0 deletions test/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7508,3 +7508,15 @@ let array = Int[]
end
@test compare_union37557(Ref{Union{Int,Vector{Int}}}(1),
Ref{Union{Int,Vector{Int}}}(1))

# @aggressive_constprop ======
g_nonaggressive(y, x) = (for i = 1:100; end; Val{x}())
@Base.aggressive_constprop g_aggressive(y, x) = (for i = 1:100; end; Val{x}())

f_nonaggressive(x) = g_nonaggressive(x, 1)
f_aggressive(x) = g_aggressive(x, 1)

# The first test just makes sure that improvements to the compiler don't
# render the annotation effectless.
@test Base.return_types(f_nonaggressive, Tuple{Int})[1] == Val
@test Base.return_types(f_aggressive, Tuple{Int})[1] == Val{1}

0 comments on commit 11fcf8b

Please sign in to comment.