Use a sub_info to optimize branches

Create a new sub_info for each branch to hold the type information of the local variables, instead of handling the types manually.
This commit is contained in:
Gustavo Massaccesi 2015-09-22 15:48:16 -03:00
parent 5031897c51
commit 3f246dd857

View File

@ -4218,19 +4218,21 @@ static void merge_types(Optimize_Info *src_info, Optimize_Info *info, int delta)
} }
} }
Scheme_Hash_Tree *intersect_and_merge_types(Scheme_Hash_Tree *t_types, Scheme_Hash_Tree *f_types, static void intersect_and_merge_types(Optimize_Info *t_info, Optimize_Info *f_info,
Scheme_Hash_Tree *base_types) Optimize_Info *base_info)
/* return (union (intersetion t_type f_types) base_types) /* return (union (intersetion t_type f_types) base_types)
in case a key is already in base_type, the value is not modified*/ in case a key is already in base_type, the value is not modified*/
{ {
Scheme_Hash_Tree *t_types = t_info->types, *f_types = f_info->types,
*base_types = base_info->types;
Scheme_Object *pos, *t_pred, *f_pred, *base_pred; Scheme_Object *pos, *t_pred, *f_pred, *base_pred;
intptr_t i; intptr_t i;
if (!t_types || !f_types) if (!t_types || !f_types)
return base_types; return;
if (base_types && (SAME_OBJ(f_types, base_types) || SAME_OBJ(t_types, base_types))) if (base_types && (SAME_OBJ(f_types, base_types) || SAME_OBJ(t_types, base_types)))
return base_types; return;
if (f_types->count > t_types->count) { if (f_types->count > t_types->count) {
Scheme_Hash_Tree *swap = f_types; Scheme_Hash_Tree *swap = f_types;
@ -4256,7 +4258,7 @@ Scheme_Hash_Tree *intersect_and_merge_types(Scheme_Hash_Tree *t_types, Scheme_Ha
} }
i = scheme_hash_tree_next(f_types, i); i = scheme_hash_tree_next(f_types, i);
} }
return base_types; base_info->types = base_types;
} }
static int relevant_predicate(Scheme_Object *pred) static int relevant_predicate(Scheme_Object *pred)
@ -4373,10 +4375,8 @@ static Scheme_Object *optimize_branch(Scheme_Object *o, Optimize_Info *info, int
{ {
Scheme_Branch_Rec *b; Scheme_Branch_Rec *b;
Scheme_Object *t, *tb, *fb; Scheme_Object *t, *tb, *fb;
Scheme_Hash_Tree *init_types, *then_types;
int init_vclock, init_aclock, init_kclock, init_sclock; int init_vclock, init_aclock, init_kclock, init_sclock;
int then_escapes, then_preserves_marks, then_single_result; Optimize_Info *then_info, *else_info;
int then_vclock, then_aclock, then_kclock, then_sclock;
Optimize_Info_Sequence info_seq; Optimize_Info_Sequence info_seq;
Scheme_Object *pred; Scheme_Object *pred;
@ -4492,22 +4492,13 @@ static Scheme_Object *optimize_branch(Scheme_Object *o, Optimize_Info *info, int
init_aclock = info->aclock; init_aclock = info->aclock;
init_kclock = info->kclock; init_kclock = info->kclock;
init_sclock = info->sclock; init_sclock = info->sclock;
init_types = info->types;
add_types_for_t_branch(t, info, 5); then_info = optimize_info_add_frame(info, 0, 0, 0);
add_types_for_t_branch(t, then_info, 5);
tb = scheme_optimize_expr(tb, then_info, scheme_optimize_tail_context(context));
optimize_info_done(then_info, NULL);
tb = scheme_optimize_expr(tb, info, scheme_optimize_tail_context(context)); info->escapes = 0;
then_types = info->types;
then_preserves_marks = info->preserves_marks;
then_single_result = info->single_result;
then_escapes = info->escapes;
then_vclock = info->vclock;
then_aclock = info->aclock;
then_kclock = info->kclock;
then_sclock = info->sclock;
info->types = init_types;
info->vclock = init_vclock; info->vclock = init_vclock;
info->aclock = init_aclock; info->aclock = init_aclock;
info->kclock = init_kclock; info->kclock = init_kclock;
@ -4515,44 +4506,48 @@ static Scheme_Object *optimize_branch(Scheme_Object *o, Optimize_Info *info, int
optimize_info_seq_step(info, &info_seq); optimize_info_seq_step(info, &info_seq);
add_types_for_f_branch(t, info, 5); else_info = optimize_info_add_frame(info, 0, 0, 0);
add_types_for_f_branch(t, else_info, 5);
fb = scheme_optimize_expr(fb, else_info, scheme_optimize_tail_context(context));
optimize_info_done(else_info, NULL);
fb = scheme_optimize_expr(fb, info, scheme_optimize_tail_context(context)); if (then_info->escapes && else_info->escapes) {
if (info->escapes && then_escapes) {
/* both branches escaped */ /* both branches escaped */
info->preserves_marks = 1; info->preserves_marks = 1;
info->single_result = 1; info->single_result = 1;
info->kclock = init_kclock; info->kclock = init_kclock;
info->types = init_types; /* not sure if this is necesary */
} else if (info->escapes) { } else if (info->escapes) {
info->preserves_marks = then_preserves_marks; info->preserves_marks = then_info->preserves_marks;
info->single_result = then_single_result; info->single_result = then_info->single_result;
info->kclock = then_kclock; info->kclock = then_info->kclock;
info->types = then_types; merge_types(then_info, info, 0);
info->escapes = 0; info->escapes = 0;
} else if (then_escapes) { } else if (then_info->escapes) {
info->escapes = 0; info->preserves_marks = else_info->preserves_marks;
info->single_result = else_info->single_result;
merge_types(else_info, info, 0);
info->escapes = 0;
} else { } else {
then_preserves_marks = or_tentative(then_preserves_marks, info->preserves_marks); int new_preserves_marks, new_single_result;
info->preserves_marks = then_preserves_marks;
then_single_result = or_tentative(then_single_result, info->single_result); new_preserves_marks = or_tentative(then_info->preserves_marks, else_info->preserves_marks);
info->single_result = then_single_result; info->preserves_marks = new_preserves_marks;
if (then_kclock > info->kclock) new_single_result = or_tentative(then_info->single_result, else_info->single_result);
info->kclock = then_kclock; info->single_result = new_single_result;
init_types = intersect_and_merge_types(then_types, info->types, init_types); if (then_info->kclock > info->kclock)
info->types = init_types; info->kclock = then_info->kclock;
intersect_and_merge_types(then_info, else_info, info);
} }
if (then_sclock > info->sclock) if (then_info->sclock > info->sclock)
info->sclock = then_sclock; info->sclock = then_info->sclock;
if (then_aclock > info->aclock) if (then_info->aclock > info->aclock)
info->aclock = then_aclock; info->aclock = then_info->aclock;
if ((init_vclock == then_vclock) && (init_vclock == info->vclock)) { if ((init_vclock == then_info->vclock) && (init_vclock == info->vclock)) {
/* we can rewind the vclock to just after the test, because the /* we can rewind the vclock to just after the test, because the
`if` as a whole has no effect */ `if` as a whole has no effect */
info->vclock--; info->vclock--;