optimizer: fix calculation of used local variables (again)

Mostly reverts a52a08146a, then repairs the problem in a way
that does not add variables unnecessarily to nested closures.
This commit is contained in:
Matthew Flatt 2016-02-20 15:31:07 -07:00
parent 01458e22fa
commit 537292ef45
3 changed files with 40 additions and 59 deletions

View File

@ -17,7 +17,6 @@ static int mark_optimize_info_MARK(void *p, struct NewGC *gc) {
gcMARK2(i->cp, gc);
gcMARK2(i->top_level_consts, gc);
gcMARK2(i->transitive_use_var, gc);
gcMARK2(i->transitive_uses_to, gc);
gcMARK2(i->context, gc);
gcMARK2(i->logger, gc);
gcMARK2(i->types, gc);
@ -41,7 +40,6 @@ static int mark_optimize_info_FIXUP(void *p, struct NewGC *gc) {
gcFIXUP2(i->cp, gc);
gcFIXUP2(i->top_level_consts, gc);
gcFIXUP2(i->transitive_use_var, gc);
gcFIXUP2(i->transitive_uses_to, gc);
gcFIXUP2(i->context, gc);
gcFIXUP2(i->logger, gc);
gcFIXUP2(i->types, gc);

View File

@ -1411,7 +1411,6 @@ mark_optimize_info {
gcMARK2(i->cp, gc);
gcMARK2(i->top_level_consts, gc);
gcMARK2(i->transitive_use_var, gc);
gcMARK2(i->transitive_uses_to, gc);
gcMARK2(i->context, gc);
gcMARK2(i->logger, gc);
gcMARK2(i->types, gc);

View File

@ -92,7 +92,6 @@ struct Optimize_Info
Scheme_IR_Local *transitive_use_var; /* set when optimizing a letrec-bound procedure
to record variables that were added to `uses` */
struct Optimize_Info *transitive_uses_to; /* points to frame with relevant `transitive_use_var` */
Scheme_Object *context; /* for logging */
Scheme_Logger *logger;
@ -137,6 +136,8 @@ static void increment_use_count(Scheme_IR_Local *var, int as_rator);
static Optimize_Info *optimize_info_add_frame(Optimize_Info *info, int orig, int current, int flags);
static void optimize_info_done(Optimize_Info *info, Optimize_Info *parent);
static void register_transitive_uses(Scheme_IR_Local *var, Optimize_Info *info);
static void optimize_info_seq_init(Optimize_Info *info, Optimize_Info_Sequence *info_seq);
static void optimize_info_seq_step(Optimize_Info *info, Optimize_Info_Sequence *info_seq);
static void optimize_info_seq_done(Optimize_Info *info, Optimize_Info_Sequence *info_seq);
@ -5828,7 +5829,6 @@ static void start_transitive_use_record(Optimize_Info *to_info, Optimize_Info *i
return;
info->transitive_use_var = var;
info->transitive_uses_to = to_info;
/* Restore use flags, if any, saved from before: */
if (var->optimize.transitive_uses)
@ -5842,7 +5842,6 @@ static void end_transitive_use_record(Optimize_Info *info)
if (var != info->next->transitive_use_var) {
info->transitive_use_var = info->next->transitive_use_var;
info->transitive_uses_to = info->next->transitive_uses_to;
if (var->optimize.transitive_uses)
flip_transitive(var->optimize.transitive_uses, 0);
@ -6469,6 +6468,26 @@ scheme_optimize_lets(Scheme_Object *form, Optimize_Info *info, int for_inline, i
else
head->body = body;
/* Propagate any use from formerly tentative uses: */
while (1) {
int changed = 0;
body = head->body;
for (i = head->num_clauses; i--; ) {
pre_body = (Scheme_IR_Let_Value *)body;
for (j = pre_body->count; j--; ) {
if (pre_body->vars[j]->optimize_used
&& pre_body->vars[j]->optimize.transitive_uses) {
register_transitive_uses(pre_body->vars[j], body_info);
changed = 1;
pre_body->vars[j]->optimize.transitive_uses = NULL;
}
}
body = pre_body->body;
}
if (!changed)
break;
}
info->single_result = body_info->single_result;
info->preserves_marks = body_info->preserves_marks;
info->vclock = body_info->vclock;
@ -8122,53 +8141,6 @@ void scheme_optimize_info_never_inline(Optimize_Info *oi)
oi->inline_fuel = -1;
}
static void register_transitive(Scheme_IR_Local *var, Optimize_Info *info);
static void register_use_at(Scheme_IR_Local *var, Optimize_Info *info);
static Scheme_Object *transitive_k(void)
{
Scheme_Thread *p = scheme_current_thread;
Scheme_IR_Local *var = SCHEME_VAR(p->ku.k.p1);
Optimize_Info *info = (Optimize_Info *)p->ku.k.p2;
p->ku.k.p1 = NULL;
p->ku.k.p2 = NULL;
register_transitive(var, info);
return scheme_false;
}
static void register_transitive(Scheme_IR_Local *var, Optimize_Info *info)
{
Scheme_Hash_Table *ht;
Scheme_IR_Local *tvar;
int j;
#ifdef DO_STACK_CHECK
# include "mzstkchk.h"
{
Scheme_Thread *p = scheme_current_thread;
p->ku.k.p1 = (void *)var;
p->ku.k.p2 = (void *)info;
scheme_handle_stack_overflow(transitive_k);
return;
}
#endif
ht = var->optimize.transitive_uses;
for (j = 0; j < ht->size; j++) {
if (ht->vals[j]) {
tvar = SCHEME_VAR(ht->keys[j]);
register_use_at(tvar, info);
}
}
}
static void propagate_used_variables(Optimize_Info *info)
{
Scheme_Hash_Table *ht;
@ -8261,7 +8233,7 @@ static int optimize_any_uses(Optimize_Info *info, Scheme_IR_Let_Value *at_irlv,
return 0;
}
static void register_use_at(Scheme_IR_Local *var, Optimize_Info *info)
static void register_use(Scheme_IR_Local *var, Optimize_Info *info)
{
if (var->optimize.lambda_depth < info->lambda_depth)
scheme_hash_set(info->uses, (Scheme_Object *)var, scheme_true);
@ -8271,7 +8243,7 @@ static void register_use_at(Scheme_IR_Local *var, Optimize_Info *info)
if (info->transitive_use_var
&& (var->optimize.lambda_depth
<= info->transitive_uses_to->lambda_depth)) {
<= info->transitive_use_var->optimize.lambda_depth)) {
Scheme_Hash_Table *ht = info->transitive_use_var->optimize.transitive_uses;
if (!ht) {
@ -8280,9 +8252,22 @@ static void register_use_at(Scheme_IR_Local *var, Optimize_Info *info)
}
scheme_hash_set(ht, (Scheme_Object *)var, scheme_true);
}
}
}
if (var->optimize.transitive_uses)
register_transitive(var, info);
static void register_transitive_uses(Scheme_IR_Local *var, Optimize_Info *info)
{
Scheme_Hash_Table *ht;
Scheme_IR_Local *tvar;
int j;
ht = var->optimize.transitive_uses;
for (j = 0; j < ht->size; j++) {
if (ht->vals[j]) {
tvar = SCHEME_VAR(ht->keys[j]);
register_use(tvar, info);
}
}
}
@ -8357,7 +8342,7 @@ static Scheme_Object *optimize_info_lookup(Optimize_Info *info, Scheme_Object *v
}
if (!closure_ok)
register_use_at(SCHEME_VAR(var), info);
register_use(SCHEME_VAR(var), info);
return NULL;
}
@ -8413,7 +8398,6 @@ static Optimize_Info *optimize_info_add_frame(Optimize_Info *info, int orig, int
naya->lambda_depth = info->lambda_depth + ((flags & SCHEME_LAMBDA_FRAME) ? 1 : 0);
naya->uses = info->uses;
naya->transitive_use_var = info->transitive_use_var;
naya->transitive_uses_to = info->transitive_uses_to;
return naya;
}