Skip to content

Commit

Permalink
Merge pull request #18260 from JuliaLang/yyc/typeinf/reduce
Browse files Browse the repository at this point in the history
Type inference opt passes clean up
  • Loading branch information
yuyichao authored Sep 2, 2016
2 parents 1af52d0 + 661235a commit 40c0fc6
Show file tree
Hide file tree
Showing 8 changed files with 389 additions and 130 deletions.
348 changes: 310 additions & 38 deletions base/inference.jl

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions src/alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ jl_sym_t *meta_sym; jl_sym_t *compiler_temp_sym;
jl_sym_t *inert_sym; jl_sym_t *vararg_sym;
jl_sym_t *unused_sym; jl_sym_t *static_parameter_sym;
jl_sym_t *polly_sym; jl_sym_t *inline_sym;
jl_sym_t *propagate_inbounds_sym;

typedef struct {
int64_t a;
Expand Down Expand Up @@ -349,6 +350,8 @@ static void jl_lambda_info_set_ast(jl_lambda_info_t *li, jl_expr_t *ast)
li->pure = 1;
else if (ma == (jl_value_t*)inline_sym)
li->inlineable = 1;
else if (ma == (jl_value_t*)propagate_inbounds_sym)
li->propagate_inbounds = 1;
else
jl_array_ptr_set(meta, ins++, ma);
}
Expand Down Expand Up @@ -431,6 +434,7 @@ JL_DLLEXPORT jl_lambda_info_t *jl_new_lambda_info_uninit(void)
li->constval = NULL;
li->pure = 0;
li->inlineable = 0;
li->propagate_inbounds = 0;
return li;
}

Expand Down Expand Up @@ -544,6 +548,7 @@ static jl_lambda_info_t *jl_copy_lambda(jl_lambda_info_t *linfo)
new_linfo->sparam_vals = linfo->sparam_vals;
new_linfo->pure = linfo->pure;
new_linfo->inlineable = linfo->inlineable;
new_linfo->propagate_inbounds = linfo->propagate_inbounds;
new_linfo->nargs = linfo->nargs;
new_linfo->isva = linfo->isva;
new_linfo->rettype = linfo->rettype;
Expand Down
71 changes: 11 additions & 60 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4498,18 +4498,13 @@ static std::unique_ptr<Module> emit_function(jl_lambda_info_t *lam, jl_llvm_func
DebugLoc loc;
StringRef file;
ssize_t line;
bool enabled;
bool is_inbounds;
bool loc_changed;
bool is_poploc;
};
std::vector<StmtProp> stmtprops(stmtslen);
std::vector<DbgState> DI_stack;
std::vector<bool> boundsCheck_stack{false};
std::vector<bool> inbounds_stack{false};
auto is_bounds_check_block = [&] () {
return !boundsCheck_stack.empty() && boundsCheck_stack.back();
};
auto is_inbounds = [&] () {
// inbounds rule is either of top two values on inbounds stack are true
size_t sz = inbounds_stack.size();
Expand All @@ -4518,21 +4513,22 @@ static std::unique_ptr<Module> emit_function(jl_lambda_info_t *lam, jl_llvm_func
inbounds |= inbounds_stack[sz - 2];
return inbounds;
};
StmtProp cur_prop{topdebugloc, filename, toplineno, true, false, true, false};
// this should not be necessary but it seems that meta node can cause
// an offset between the label number and the statement number
std::map<int, int> label_map;
StmtProp cur_prop{topdebugloc, filename, toplineno, false, true, false};
for (i = 0; i < stmtslen; i++) {
cur_prop.loc_changed = false;
cur_prop.is_poploc = false;
jl_value_t *stmt = jl_array_ptr_ref(stmts, i);
jl_expr_t *expr = jl_is_expr(stmt) ? (jl_expr_t*)stmt : nullptr;
#ifndef NDEBUG
if (jl_is_labelnode(stmt)) {
int lname = jl_labelnode_label(stmt);
if (lname != i + 1) {
label_map[lname] = i + 1;
jl_safe_printf("Label number mismatch.\n");
jl_(stmts);
abort();
}
}
#endif
if (jl_is_linenode(stmt) || (expr && expr->head == line_sym)) {
ssize_t lno = -1;
if (jl_is_linenode(stmt)) {
Expand Down Expand Up @@ -4627,64 +4623,26 @@ static std::unique_ptr<Module> emit_function(jl_lambda_info_t *lam, jl_llvm_func
}
if (expr) {
jl_value_t **args = (jl_value_t**)jl_array_data(expr->args);
if (expr->head == boundscheck_sym) {
if (jl_array_len(expr->args) > 0) {
jl_value_t *arg = args[0];
if (arg == jl_true) {
boundsCheck_stack.push_back(true);
}
else if (arg == jl_false) {
boundsCheck_stack.push_back(false);
}
else {
if (!boundsCheck_stack.empty()) {
boundsCheck_stack.pop_back();
}
}
}
}
else if (cur_prop.enabled && expr->head == inbounds_sym) {
if (expr->head == inbounds_sym) {
// manipulate inbounds stack
// note that when entering an inbounds context, we must also update
// the boundsCheck context to be false
if (jl_array_len(expr->args) > 0) {
jl_value_t *arg = args[0];
if (arg == jl_true) {
inbounds_stack.push_back(true);
boundsCheck_stack.push_back(false);
}
else if (arg == jl_false) {
inbounds_stack.push_back(false);
boundsCheck_stack.push_back(false);
}
else {
if (!inbounds_stack.empty())
inbounds_stack.pop_back();
if (!boundsCheck_stack.empty())
boundsCheck_stack.pop_back();
else if (!inbounds_stack.empty()) {
inbounds_stack.pop_back();
}
}
}
}
bool is_ib = is_inbounds();
if (is_ib && is_bounds_check_block() &&
jl_options.check_bounds != JL_OPTIONS_CHECK_BOUNDS_ON) {
// elide bounds check blocks in inbounds context
cur_prop.enabled = false;
}
else if (is_bounds_check_block() &&
jl_options.check_bounds == JL_OPTIONS_CHECK_BOUNDS_OFF) {
// elide bounds check blocks when turned off by options
cur_prop.enabled = false;
}
else {
cur_prop.enabled = true;
}
cur_prop.is_inbounds = is_ib;
cur_prop.is_inbounds = is_inbounds();
stmtprops[i] = cur_prop;
}
DI_stack.clear();
boundsCheck_stack.clear();
inbounds_stack.clear();

// step 12. Do codegen in control flow order
Expand Down Expand Up @@ -4718,9 +4676,6 @@ static std::unique_ptr<Module> emit_function(jl_lambda_info_t *lam, jl_llvm_func
// if `unconditional` a unconditional branch is created to the target
// label and the cursor is set to the next statement to process
auto handle_label = [&] (int lname, bool unconditional) {
auto it = label_map.find(lname);
if (it != label_map.end())
lname = it->second;
auto &bb = labels[lname];
BasicBlock *cur_bb = builder.GetInsertBlock();
// Check if we've already visited this label
Expand Down Expand Up @@ -4774,7 +4729,7 @@ static std::unique_ptr<Module> emit_function(jl_lambda_info_t *lam, jl_llvm_func
if (ctx.debug_enabled)
builder.SetCurrentDebugLocation(props.loc);
// Disable coverage for pop_loc, it doesn't start a new expression
if (do_coverage && props.enabled && !props.is_poploc) {
if (do_coverage && !props.is_poploc) {
coverageVisitLine(props.file, props.line);
}
}
Expand All @@ -4787,10 +4742,6 @@ static std::unique_ptr<Module> emit_function(jl_lambda_info_t *lam, jl_llvm_func
handle_label(lname, true);
continue;
}
if (!props.enabled) {
find_next_stmt(cursor + 1);
continue;
}
if (expr && expr->head == return_sym) {
bool retboxed = false;
Type *retty;
Expand Down
2 changes: 2 additions & 0 deletions src/dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -949,6 +949,7 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v)
jl_serialize_value(s, (jl_value_t*)li->sparam_vals);
write_int8(s->s, li->pure);
write_int8(s->s, li->inlineable);
write_int8(s->s, li->propagate_inbounds);
write_int8(s->s, li->isva);
write_int32(s->s, li->nargs);
jl_serialize_value(s, (jl_value_t*)li->def);
Expand Down Expand Up @@ -1616,6 +1617,7 @@ static jl_value_t *jl_deserialize_value_(jl_serializer_state *s, jl_value_t *vta
li->unspecialized_ducttape = NULL;
li->pure = read_int8(s->s);
li->inlineable = read_int8(s->s);
li->propagate_inbounds = read_int8(s->s);
li->isva = read_int8(s->s);
li->nargs = read_int32(s->s);
li->def = (jl_method_t*)jl_deserialize_value(s, (jl_value_t**)&li->def);
Expand Down
9 changes: 6 additions & 3 deletions src/jltypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -3880,7 +3880,7 @@ void jl_init_types(void)
jl_lambda_info_type =
jl_new_datatype(jl_symbol("LambdaInfo"),
jl_any_type, jl_emptysvec,
jl_svec(24,
jl_svec(25,
jl_symbol("rettype"),
jl_symbol("sparam_syms"),
jl_symbol("sparam_vals"),
Expand All @@ -3898,13 +3898,14 @@ void jl_init_types(void)
jl_symbol("inferred"),
jl_symbol("pure"),
jl_symbol("inlineable"),
jl_symbol("propagate_inbounds"),
jl_symbol("inInference"),
jl_symbol("inCompile"),
jl_symbol("jlcall_api"),
jl_symbol(""),
jl_symbol("fptr"),
jl_symbol(""), jl_symbol("")),
jl_svec(24,
jl_svec(25,
jl_any_type,
jl_simplevector_type,
jl_simplevector_type,
Expand All @@ -3924,6 +3925,7 @@ void jl_init_types(void)
jl_bool_type,
jl_bool_type,
jl_bool_type,
jl_bool_type,
jl_uint8_type,
jl_bool_type,
jl_any_type,
Expand Down Expand Up @@ -3991,9 +3993,9 @@ void jl_init_types(void)
jl_svecset(jl_methtable_type->types, 6, jl_int32_type); // DWORD
#endif
jl_svecset(jl_methtable_type->types, 7, jl_int32_type); // uint32_t
jl_svecset(jl_lambda_info_type->types, 21, jl_voidpointer_type);
jl_svecset(jl_lambda_info_type->types, 22, jl_voidpointer_type);
jl_svecset(jl_lambda_info_type->types, 23, jl_voidpointer_type);
jl_svecset(jl_lambda_info_type->types, 24, jl_voidpointer_type);

jl_compute_field_offsets(jl_datatype_type);
jl_compute_field_offsets(jl_typename_type);
Expand Down Expand Up @@ -4071,6 +4073,7 @@ void jl_init_types(void)
compiler_temp_sym = jl_symbol("#temp#");
polly_sym = jl_symbol("polly");
inline_sym = jl_symbol("inline");
propagate_inbounds_sym = jl_symbol("propagate_inbounds");

tttvar = jl_new_typevar(jl_symbol("T"),
(jl_value_t*)jl_bottom_type,
Expand Down
30 changes: 1 addition & 29 deletions src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ typedef struct _jl_lambda_info_t {
int8_t inferred;
int8_t pure;
int8_t inlineable;
int8_t propagate_inbounds;
int8_t inInference; // flags to tell if inference is running on this function
int8_t inCompile; // flag to tell if codegen is running on this function
int8_t jlcall_api; // the c-abi for fptr; 0 = jl_fptr_t, 1 = jl_fptr_sparam_t, 2 = constval
Expand Down Expand Up @@ -555,36 +556,7 @@ extern JL_DLLEXPORT jl_value_t *jl_false;
extern JL_DLLEXPORT jl_value_t *jl_nothing;

// some important symbols
extern jl_sym_t *call_sym; extern jl_sym_t *invoke_sym;
extern jl_sym_t *empty_sym; extern jl_sym_t *body_sym;
extern jl_sym_t *dots_sym; extern jl_sym_t *vararg_sym;
extern jl_sym_t *quote_sym; extern jl_sym_t *newvar_sym;
extern jl_sym_t *top_sym; extern jl_sym_t *dot_sym;
extern jl_sym_t *line_sym; extern jl_sym_t *toplevel_sym;
extern jl_sym_t *core_sym; extern jl_sym_t *globalref_sym;
extern JL_DLLEXPORT jl_sym_t *jl_incomplete_sym;
extern jl_sym_t *error_sym; extern jl_sym_t *amp_sym;
extern jl_sym_t *module_sym; extern jl_sym_t *colons_sym;
extern jl_sym_t *export_sym; extern jl_sym_t *import_sym;
extern jl_sym_t *importall_sym; extern jl_sym_t *using_sym;
extern jl_sym_t *goto_sym; extern jl_sym_t *goto_ifnot_sym;
extern jl_sym_t *label_sym; extern jl_sym_t *return_sym;
extern jl_sym_t *lambda_sym; extern jl_sym_t *assign_sym;
extern jl_sym_t *method_sym; extern jl_sym_t *slot_sym;
extern jl_sym_t *enter_sym; extern jl_sym_t *leave_sym;
extern jl_sym_t *exc_sym; extern jl_sym_t *new_sym;
extern jl_sym_t *compiler_temp_sym;
extern jl_sym_t *const_sym; extern jl_sym_t *thunk_sym;
extern jl_sym_t *anonymous_sym; extern jl_sym_t *underscore_sym;
extern jl_sym_t *abstracttype_sym; extern jl_sym_t *bitstype_sym;
extern jl_sym_t *compositetype_sym;
extern jl_sym_t *global_sym; extern jl_sym_t *unused_sym;
extern jl_sym_t *boundscheck_sym; extern jl_sym_t *inbounds_sym;
extern jl_sym_t *copyast_sym; extern jl_sym_t *fastmath_sym;
extern jl_sym_t *pure_sym; extern jl_sym_t *simdloop_sym;
extern jl_sym_t *meta_sym; extern jl_sym_t *list_sym;
extern jl_sym_t *inert_sym; extern jl_sym_t *static_parameter_sym;
extern jl_sym_t *polly_sym; extern jl_sym_t *inline_sym;

// gc -------------------------------------------------------------------------

Expand Down
31 changes: 31 additions & 0 deletions src/julia_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,37 @@ JL_DLLEXPORT jl_array_t *jl_array_cconvert_cstring(jl_array_t *a);

int isabspath(const char *in);

extern jl_sym_t *call_sym; extern jl_sym_t *invoke_sym;
extern jl_sym_t *empty_sym; extern jl_sym_t *body_sym;
extern jl_sym_t *dots_sym; extern jl_sym_t *vararg_sym;
extern jl_sym_t *quote_sym; extern jl_sym_t *newvar_sym;
extern jl_sym_t *top_sym; extern jl_sym_t *dot_sym;
extern jl_sym_t *line_sym; extern jl_sym_t *toplevel_sym;
extern jl_sym_t *core_sym; extern jl_sym_t *globalref_sym;
extern jl_sym_t *error_sym; extern jl_sym_t *amp_sym;
extern jl_sym_t *module_sym; extern jl_sym_t *colons_sym;
extern jl_sym_t *export_sym; extern jl_sym_t *import_sym;
extern jl_sym_t *importall_sym; extern jl_sym_t *using_sym;
extern jl_sym_t *goto_sym; extern jl_sym_t *goto_ifnot_sym;
extern jl_sym_t *label_sym; extern jl_sym_t *return_sym;
extern jl_sym_t *lambda_sym; extern jl_sym_t *assign_sym;
extern jl_sym_t *method_sym; extern jl_sym_t *slot_sym;
extern jl_sym_t *enter_sym; extern jl_sym_t *leave_sym;
extern jl_sym_t *exc_sym; extern jl_sym_t *new_sym;
extern jl_sym_t *compiler_temp_sym;
extern jl_sym_t *const_sym; extern jl_sym_t *thunk_sym;
extern jl_sym_t *anonymous_sym; extern jl_sym_t *underscore_sym;
extern jl_sym_t *abstracttype_sym; extern jl_sym_t *bitstype_sym;
extern jl_sym_t *compositetype_sym;
extern jl_sym_t *global_sym; extern jl_sym_t *unused_sym;
extern jl_sym_t *boundscheck_sym; extern jl_sym_t *inbounds_sym;
extern jl_sym_t *copyast_sym; extern jl_sym_t *fastmath_sym;
extern jl_sym_t *pure_sym; extern jl_sym_t *simdloop_sym;
extern jl_sym_t *meta_sym; extern jl_sym_t *list_sym;
extern jl_sym_t *inert_sym; extern jl_sym_t *static_parameter_sym;
extern jl_sym_t *polly_sym; extern jl_sym_t *inline_sym;
extern jl_sym_t *propagate_inbounds_sym;

#ifdef __cplusplus
}
#endif
Expand Down
23 changes: 23 additions & 0 deletions test/boundscheck_exec.jl
Original file line number Diff line number Diff line change
Expand Up @@ -151,4 +151,27 @@ end

@test B2() == 0

# Make sure type inference doesn't incorrectly optimize out
# `Expr(:inbounds, false)`
# Simply `return a[1]` doesn't work due to inlining bug
@inline function f1(a)
# This has to be an arrayget / arrayset since these currently have a
# implicit `Expr(:boundscheck)` that's not visible to type inference
x = a[1]
return x
end
# second level
@inline function g1(a)
x = f1(a)
return x
end
function k1(a)
# This `Expr(:inbounds, true)` shouldn't affect `f1`
@inbounds x = g1(a)
return x
end
if bc_opt != bc_off
@test_throws BoundsError k1(Int[])
end

end

2 comments on commit 40c0fc6

@nanosoldier
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Executing the daily benchmark build, I will reply here when finished:

@nanosoldier runbenchmarks(ALL, isdaily = true)

@nanosoldier
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. cc @jrevels

Please sign in to comment.