fix optimization related to with-continuation-mark
Fix mistake intoduced in 5904acc69a adding `with-continuation-mark` to single_valued_noncm_expression().
This commit is contained in:
parent
2bfb851ccc
commit
79ad86d891
|
@ -122,8 +122,10 @@ static void add_type(Optimize_Info *info, Scheme_Object *var, Scheme_Object *pre
|
|||
static void merge_types(Optimize_Info *src_info, Optimize_Info *info, Scheme_Hash_Tree *skip_vars);
|
||||
static Scheme_Object *lookup_constant_proc(Optimize_Info *info, Scheme_Object *rand);
|
||||
|
||||
static Scheme_Object *expr_implies_predicate(Scheme_Object *expr, Optimize_Info *info,
|
||||
int *_involves_k_cross, int fuel);
|
||||
static Scheme_Object *expr_implies_predicate(Scheme_Object *expr, Optimize_Info *info);
|
||||
static Scheme_Object *do_expr_implies_predicate(Scheme_Object *expr, Optimize_Info *info,
|
||||
int *_involves_k_cross, int fuel,
|
||||
Scheme_Hash_Tree *ignore_vars);
|
||||
static int produces_local_type(Scheme_Object *rator, int argc);
|
||||
static int optimize_any_uses(Optimize_Info *info, Scheme_IR_Let_Value *at_irlv, int n);
|
||||
static void propagate_used_variables(Optimize_Info *info);
|
||||
|
@ -1372,8 +1374,9 @@ Scheme_Object *scheme_make_struct_proc_shape(intptr_t k)
|
|||
return ps;
|
||||
}
|
||||
|
||||
static int single_valued_noncm_expression(Scheme_Object *expr, int fuel)
|
||||
/* Not necessarily omittable or copyable, but single-valued expressions that are not sensitive
|
||||
static int single_valued_expression(Scheme_Object *expr, int fuel, int non_cm)
|
||||
/* Not necessarily omittable or copyable, but single-valued expressions.
|
||||
If `non_cm`, the expression must not be sensitive
|
||||
to being in tail position. */
|
||||
{
|
||||
Scheme_Object *rator = NULL;
|
||||
|
@ -1403,20 +1406,25 @@ static int single_valued_noncm_expression(Scheme_Object *expr, int fuel)
|
|||
case scheme_branch_type:
|
||||
if (fuel > 0) {
|
||||
Scheme_Branch_Rec *b = (Scheme_Branch_Rec *)expr;
|
||||
return (single_valued_noncm_expression(b->tbranch, fuel - 1)
|
||||
&& single_valued_noncm_expression(b->fbranch, fuel - 1));
|
||||
return (single_valued_expression(b->tbranch, fuel - 1, non_cm)
|
||||
&& single_valued_expression(b->fbranch, fuel - 1, non_cm));
|
||||
}
|
||||
break;
|
||||
case scheme_begin0_sequence_type:
|
||||
if (fuel > 0) {
|
||||
Scheme_Sequence *seq = (Scheme_Sequence *)expr;
|
||||
return single_valued_noncm_expression(seq->array[0], fuel - 1);
|
||||
return single_valued_expression(seq->array[0], fuel - 1, 0);
|
||||
}
|
||||
break;
|
||||
case scheme_with_cont_mark_type:
|
||||
{
|
||||
Scheme_With_Continuation_Mark * wcm = (Scheme_With_Continuation_Mark *)expr;
|
||||
return single_valued_noncm_expression(wcm->body, fuel - 1);
|
||||
if (non_cm) {
|
||||
/* To avoid being sensitive to tail position, the body must not inspect
|
||||
the continuation at all. */
|
||||
return scheme_omittable_expr(wcm->body, 1, fuel, 0, NULL, NULL);
|
||||
} else
|
||||
return single_valued_expression(wcm->body, fuel - 1, 0);
|
||||
}
|
||||
break;
|
||||
case scheme_ir_lambda_type:
|
||||
|
@ -1433,7 +1441,7 @@ static int single_valued_noncm_expression(Scheme_Object *expr, int fuel)
|
|||
Scheme_Object *tail = expr, *inside = NULL;
|
||||
extract_tail_inside(&tail, &inside);
|
||||
if (inside)
|
||||
return single_valued_noncm_expression(tail, fuel - 1);
|
||||
return single_valued_expression(tail, fuel - 1, non_cm);
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -1453,6 +1461,11 @@ static int single_valued_noncm_expression(Scheme_Object *expr, int fuel)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int single_valued_noncm_expression(Scheme_Object *expr, int fuel)
|
||||
{
|
||||
return single_valued_expression(expr, fuel, 1);
|
||||
}
|
||||
|
||||
static int is_movable_prim(Scheme_Object *rator, int n, int cross_lambda, int cross_k, Optimize_Info *info)
|
||||
/* Can we move a call to `rator` relative to other function calls?
|
||||
A -1 return means that the arguments must be movable without
|
||||
|
@ -2236,7 +2249,7 @@ Scheme_Object *optimize_for_inline(Optimize_Info *info, Scheme_Object *le, int a
|
|||
static int is_local_type_expression(Scheme_Object *expr, Optimize_Info *info)
|
||||
/* Get an unboxing type (e.g., flonum) for `expr` */
|
||||
{
|
||||
return scheme_predicate_to_local_type(expr_implies_predicate(expr, info, NULL, 5));
|
||||
return scheme_predicate_to_local_type(expr_implies_predicate(expr, info));
|
||||
}
|
||||
|
||||
static void register_local_argument_types(Scheme_App_Rec *app, Scheme_App2_Rec *app2, Scheme_App3_Rec *app3,
|
||||
|
@ -2300,7 +2313,7 @@ static void register_local_argument_types(Scheme_App_Rec *app, Scheme_App2_Rec *
|
|||
|| !lam->ir_info->arg_type_contributors[i]) {
|
||||
int widen_to_top = 0;
|
||||
|
||||
pred = expr_implies_predicate(rand, info, NULL, 5);
|
||||
pred = expr_implies_predicate(rand, info);
|
||||
|
||||
if (pred) {
|
||||
if (!lam->ir_info->arg_type_contributors[i]) {
|
||||
|
@ -2534,7 +2547,8 @@ int scheme_predicate_to_local_type(Scheme_Object *pred)
|
|||
int scheme_expr_produces_local_type(Scheme_Object *expr, int *_involves_k_cross)
|
||||
{
|
||||
if (_involves_k_cross) *_involves_k_cross = 0;
|
||||
return scheme_predicate_to_local_type(expr_implies_predicate(expr, NULL, _involves_k_cross, 10));
|
||||
return scheme_predicate_to_local_type(do_expr_implies_predicate(expr, NULL, _involves_k_cross,
|
||||
10, empty_eq_hash_tree));
|
||||
}
|
||||
|
||||
static Scheme_Object *rator_implies_predicate(Scheme_Object *rator, int argc)
|
||||
|
@ -2582,8 +2596,9 @@ static Scheme_Object *rator_implies_predicate(Scheme_Object *rator, int argc)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static Scheme_Object *expr_implies_predicate(Scheme_Object *expr, Optimize_Info *info,
|
||||
int *_involves_k_cross, int fuel)
|
||||
static Scheme_Object *do_expr_implies_predicate(Scheme_Object *expr, Optimize_Info *info,
|
||||
int *_involves_k_cross, int fuel,
|
||||
Scheme_Hash_Tree *ignore_vars)
|
||||
/* can be called by the JIT with info = NULL;
|
||||
in that case, beware that the validator must be
|
||||
able to reconstruct the result in a shallow way, so don't
|
||||
|
@ -2595,6 +2610,9 @@ static Scheme_Object *expr_implies_predicate(Scheme_Object *expr, Optimize_Info
|
|||
switch (SCHEME_TYPE(expr)) {
|
||||
case scheme_ir_local_type:
|
||||
{
|
||||
if (scheme_hash_tree_get(ignore_vars, expr))
|
||||
return NULL;
|
||||
|
||||
if (!SCHEME_VAR(expr)->mutated) {
|
||||
Scheme_Object *p;
|
||||
|
||||
|
@ -2614,7 +2632,8 @@ static Scheme_Object *expr_implies_predicate(Scheme_Object *expr, Optimize_Info
|
|||
|
||||
if ((SCHEME_VAR(expr)->mode == SCHEME_VAR_MODE_OPTIMIZE)
|
||||
&& SCHEME_VAR(expr)->optimize.known_val)
|
||||
return expr_implies_predicate(SCHEME_VAR(expr)->optimize.known_val, info, _involves_k_cross, fuel-1);
|
||||
return do_expr_implies_predicate(SCHEME_VAR(expr)->optimize.known_val, info, _involves_k_cross,
|
||||
fuel-1, ignore_vars);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -2625,7 +2644,7 @@ static Scheme_Object *expr_implies_predicate(Scheme_Object *expr, Optimize_Info
|
|||
if (SCHEME_PRIMP(app->rator)
|
||||
&& SCHEME_PRIM_PROC_OPT_FLAGS(app->rator) & SCHEME_PRIM_CLOSED_ON_REALS) {
|
||||
Scheme_Object *p;
|
||||
p = expr_implies_predicate(app->rand, info, NULL, fuel-1);
|
||||
p = do_expr_implies_predicate(app->rand, info, NULL, fuel-1, ignore_vars);
|
||||
if (p && predicate_implies(p, scheme_real_p_proc))
|
||||
return scheme_real_p_proc;
|
||||
}
|
||||
|
@ -2652,9 +2671,9 @@ static Scheme_Object *expr_implies_predicate(Scheme_Object *expr, Optimize_Info
|
|||
if (SCHEME_PRIMP(app->rator)
|
||||
&& SCHEME_PRIM_PROC_OPT_FLAGS(app->rator) & SCHEME_PRIM_CLOSED_ON_REALS) {
|
||||
Scheme_Object *p;
|
||||
p = expr_implies_predicate(app->rand1, info, NULL, fuel-1);
|
||||
p = do_expr_implies_predicate(app->rand1, info, NULL, fuel-1, ignore_vars);
|
||||
if (p && predicate_implies(p, scheme_real_p_proc)) {
|
||||
p = expr_implies_predicate(app->rand2, info, NULL, fuel-1);
|
||||
p = do_expr_implies_predicate(app->rand2, info, NULL, fuel-1, ignore_vars);
|
||||
if (p && predicate_implies(p, scheme_real_p_proc)) {
|
||||
return scheme_real_p_proc;
|
||||
}
|
||||
|
@ -2673,7 +2692,7 @@ static Scheme_Object *expr_implies_predicate(Scheme_Object *expr, Optimize_Info
|
|||
Scheme_Object *p;
|
||||
int i;
|
||||
for (i = 0; i < app->num_args; i++) {
|
||||
p = expr_implies_predicate(app->args[i+1], info, NULL, fuel-1);
|
||||
p = do_expr_implies_predicate(app->args[i+1], info, NULL, fuel-1, ignore_vars);
|
||||
if (!p || !predicate_implies(p, scheme_real_p_proc))
|
||||
break;
|
||||
}
|
||||
|
@ -2697,11 +2716,15 @@ static Scheme_Object *expr_implies_predicate(Scheme_Object *expr, Optimize_Info
|
|||
{
|
||||
Scheme_Object *l, *r;
|
||||
Scheme_Branch_Rec *b = (Scheme_Branch_Rec *)expr;
|
||||
l = expr_implies_predicate(b->tbranch, info, _involves_k_cross, fuel-1);
|
||||
l = do_expr_implies_predicate(b->tbranch, info, _involves_k_cross, fuel-1, ignore_vars);
|
||||
if (l) {
|
||||
r = expr_implies_predicate(b->fbranch, info, _involves_k_cross, fuel-1);
|
||||
if (SAME_OBJ(l, r))
|
||||
r = do_expr_implies_predicate(b->fbranch, info, _involves_k_cross, fuel-1, ignore_vars);
|
||||
if (predicate_implies(l, r))
|
||||
return r;
|
||||
else if (predicate_implies(r, l))
|
||||
return l;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -2709,30 +2732,36 @@ static Scheme_Object *expr_implies_predicate(Scheme_Object *expr, Optimize_Info
|
|||
{
|
||||
Scheme_Sequence *seq = (Scheme_Sequence *)expr;
|
||||
|
||||
return expr_implies_predicate(seq->array[seq->count-1], info, _involves_k_cross, fuel-1);
|
||||
return do_expr_implies_predicate(seq->array[seq->count-1], info, _involves_k_cross, fuel-1, ignore_vars);
|
||||
}
|
||||
case scheme_with_cont_mark_type:
|
||||
{
|
||||
Scheme_With_Continuation_Mark *wcm = (Scheme_With_Continuation_Mark *)expr;
|
||||
|
||||
return expr_implies_predicate(wcm->body, info, _involves_k_cross, fuel-1);
|
||||
return do_expr_implies_predicate(wcm->body, info, _involves_k_cross, fuel-1, ignore_vars);
|
||||
}
|
||||
case scheme_ir_let_header_type:
|
||||
{
|
||||
Scheme_IR_Let_Header *lh = (Scheme_IR_Let_Header *)expr;
|
||||
int i;
|
||||
Scheme_IR_Let_Value *irlv;
|
||||
int i, j;
|
||||
expr = lh->body;
|
||||
for (i = 0; i < lh->num_clauses; i++) {
|
||||
expr = ((Scheme_IR_Let_Value *)expr)->body;
|
||||
irlv = (Scheme_IR_Let_Value *)expr;
|
||||
for (j = 0; j < irlv->count; j++) {
|
||||
ignore_vars = scheme_hash_tree_set(ignore_vars, (Scheme_Object *)irlv->vars[j],
|
||||
scheme_true);
|
||||
}
|
||||
expr = irlv->body;
|
||||
}
|
||||
return expr_implies_predicate(expr, info, _involves_k_cross, fuel-1);
|
||||
return do_expr_implies_predicate(expr, info, _involves_k_cross, fuel-1, ignore_vars);
|
||||
}
|
||||
break;
|
||||
case scheme_begin0_sequence_type:
|
||||
{
|
||||
Scheme_Sequence *seq = (Scheme_Sequence *)expr;
|
||||
|
||||
return expr_implies_predicate(seq->array[0], info, _involves_k_cross, fuel-1);
|
||||
return do_expr_implies_predicate(seq->array[0], info, _involves_k_cross, fuel-1, ignore_vars);
|
||||
}
|
||||
case scheme_pair_type:
|
||||
return scheme_pair_p_proc;
|
||||
|
@ -2789,6 +2818,11 @@ static Scheme_Object *expr_implies_predicate(Scheme_Object *expr, Optimize_Info
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static Scheme_Object *expr_implies_predicate(Scheme_Object *expr, Optimize_Info *info)
|
||||
{
|
||||
return do_expr_implies_predicate(expr, info, NULL, 5, empty_eq_hash_tree);
|
||||
}
|
||||
|
||||
static Scheme_Object *finish_optimize_app(Scheme_Object *o, Optimize_Info *info, int context, int rator_flags)
|
||||
{
|
||||
switch(SCHEME_TYPE(o)) {
|
||||
|
@ -3064,7 +3098,7 @@ static int check_known_variant(Optimize_Info *info, Scheme_Object *app,
|
|||
if (SCHEME_PRIMP(rator) && (!who || IS_NAMED_PRIM(rator, who))) {
|
||||
Scheme_Object *pred;
|
||||
|
||||
pred = expr_implies_predicate(rand, info, NULL, 5);
|
||||
pred = expr_implies_predicate(rand, info);
|
||||
if (pred) {
|
||||
if (predicate_implies(pred, expect_pred)) {
|
||||
if (unsafe) {
|
||||
|
@ -3101,7 +3135,7 @@ static void check_known_rator(Optimize_Info *info, Scheme_Object *rator)
|
|||
{
|
||||
Scheme_Object *pred;
|
||||
|
||||
pred = expr_implies_predicate(rator, info, NULL, 5);
|
||||
pred = expr_implies_predicate(rator, info);
|
||||
if (pred) {
|
||||
if (predicate_implies_not(pred, scheme_procedure_p_proc))
|
||||
info->escapes = 1;
|
||||
|
@ -3122,9 +3156,9 @@ static void check_known_both_try(Optimize_Info *info, Scheme_Object *app,
|
|||
if (SCHEME_PRIMP(rator) && (!who || IS_NAMED_PRIM(rator, who))) {
|
||||
Scheme_Object *pred1, *pred2;
|
||||
|
||||
pred1 = expr_implies_predicate(rand1, info, NULL, 5);
|
||||
pred1 = expr_implies_predicate(rand1, info);
|
||||
if (pred1 && SAME_OBJ(pred1, expect_pred)) {
|
||||
pred2 = expr_implies_predicate(rand2, info, NULL, 5);
|
||||
pred2 = expr_implies_predicate(rand2, info);
|
||||
if (pred2 && SAME_OBJ(pred2, expect_pred)) {
|
||||
reset_rator(app, unsafe);
|
||||
}
|
||||
|
@ -3336,7 +3370,7 @@ static Scheme_Object *try_reduce_predicate(Scheme_Object *rator, Scheme_Object *
|
|||
if (!relevant_predicate(rator))
|
||||
return NULL;
|
||||
|
||||
pred = expr_implies_predicate(rand, info, NULL, 5);
|
||||
pred = expr_implies_predicate(rand, info);
|
||||
|
||||
if (!pred)
|
||||
return NULL;
|
||||
|
@ -3647,7 +3681,7 @@ static Scheme_Object *finish_optimize_application2(Scheme_App2_Rec *app, Optimiz
|
|||
Scheme_Object* pred;
|
||||
Scheme_App3_Rec *new;
|
||||
|
||||
pred = expr_implies_predicate(rand, info, NULL, 5);
|
||||
pred = expr_implies_predicate(rand, info);
|
||||
if (pred && SAME_OBJ(pred, scheme_fixnum_p_proc)) {
|
||||
new = (Scheme_App3_Rec *)make_application_3(scheme_unsafe_fx_eq_proc, app->rand, scheme_make_integer(0), info);
|
||||
SCHEME_APPN_FLAGS(new) |= (APPN_FLAG_IMMED | APPN_FLAG_SFS_TAIL);
|
||||
|
@ -3951,9 +3985,9 @@ static Scheme_Object *finish_optimize_application3(Scheme_App3_Rec *app, Optimiz
|
|||
|
||||
if (SAME_OBJ(app->rator, scheme_eq_proc)) {
|
||||
Scheme_Object *pred1, *pred2;
|
||||
pred1 = expr_implies_predicate(app->rand1, info, NULL, 5);
|
||||
pred1 = expr_implies_predicate(app->rand1, info);
|
||||
if (pred1) {
|
||||
pred2 = expr_implies_predicate(app->rand2, info, NULL, 5);
|
||||
pred2 = expr_implies_predicate(app->rand2, info);
|
||||
if (pred2) {
|
||||
if (predicate_implies_not(pred1, pred2) || predicate_implies_not(pred2, pred1)) {
|
||||
info->preserves_marks = 1;
|
||||
|
@ -4396,7 +4430,7 @@ static Scheme_Object *collapse_local(Scheme_Object *var, Optimize_Info *info, in
|
|||
if (!SCHEME_VAR(var)->mutated) {
|
||||
Scheme_Object *pred;
|
||||
|
||||
pred = expr_implies_predicate(var, info, NULL, 5);
|
||||
pred = expr_implies_predicate(var, info);
|
||||
if (pred) {
|
||||
if (predicate_implies(pred, scheme_not_proc))
|
||||
return scheme_false;
|
||||
|
@ -4614,18 +4648,18 @@ static void add_types_for_t_branch(Scheme_Object *t, Optimize_Info *info, int fu
|
|||
if (SAME_OBJ(app->rator, scheme_eq_proc)) {
|
||||
if (SAME_TYPE(SCHEME_TYPE(app->rand1), scheme_ir_local_type)
|
||||
&& !SCHEME_VAR(app->rand1)->mutated) {
|
||||
pred1 = expr_implies_predicate(app->rand1, info, NULL, 5);
|
||||
pred1 = expr_implies_predicate(app->rand1, info);
|
||||
if (!pred1) {
|
||||
pred2 = expr_implies_predicate(app->rand2, info, NULL, 5);
|
||||
pred2 = expr_implies_predicate(app->rand2, info);
|
||||
if (pred2)
|
||||
add_type(info, app->rand1, pred2);
|
||||
}
|
||||
}
|
||||
if (SAME_TYPE(SCHEME_TYPE(app->rand2), scheme_ir_local_type)
|
||||
&& !SCHEME_VAR(app->rand2)->mutated) {
|
||||
pred2 = expr_implies_predicate(app->rand2, info, NULL, 5);
|
||||
pred2 = expr_implies_predicate(app->rand2, info);
|
||||
if (!pred2) {
|
||||
pred1 = expr_implies_predicate(app->rand1, info, NULL, 5);
|
||||
pred1 = expr_implies_predicate(app->rand1, info);
|
||||
if (pred1)
|
||||
add_type(info, app->rand2, pred1);
|
||||
}
|
||||
|
@ -4742,7 +4776,7 @@ static Scheme_Object *optimize_branch(Scheme_Object *o, Optimize_Info *info, int
|
|||
but don't expand (if (let (...) (begin x K)) a b) */
|
||||
Scheme_Object *pred;
|
||||
|
||||
pred = expr_implies_predicate(t2, info, NULL, 5);
|
||||
pred = expr_implies_predicate(t2, info);
|
||||
if (pred) {
|
||||
Scheme_Object *test_val = SAME_OBJ(pred, scheme_not_proc) ? scheme_false : scheme_true;
|
||||
|
||||
|
@ -6249,7 +6283,7 @@ static Scheme_Object *optimize_lets(Scheme_Object *form, Optimize_Info *info, in
|
|||
seq->count = 2;
|
||||
|
||||
value = irlv->value;
|
||||
if (!single_valued_noncm_expression(value, 5))
|
||||
if (!single_valued_expression(value, 5, 0))
|
||||
value = ensure_single_value(value);
|
||||
|
||||
seq->array[0] = value;
|
||||
|
@ -6619,7 +6653,7 @@ static Scheme_Object *optimize_lets(Scheme_Object *form, Optimize_Info *info, in
|
|||
local is in unoptimized coordinates */
|
||||
pred = NULL;
|
||||
} else
|
||||
pred = expr_implies_predicate(value, rhs_info, NULL, 5);
|
||||
pred = expr_implies_predicate(value, rhs_info);
|
||||
|
||||
if (pred)
|
||||
add_type(body_info, (Scheme_Object *)pre_body->vars[0], pred);
|
||||
|
@ -6877,7 +6911,17 @@ static Scheme_Object *optimize_lets(Scheme_Object *form, Optimize_Info *info, in
|
|||
int used = 0, j;
|
||||
|
||||
pre_body = (Scheme_IR_Let_Value *)body;
|
||||
|
||||
|
||||
if (pre_body->count == 1) {
|
||||
/* If the right-hand side is a function, make sure all use sites
|
||||
are accounted for toward type inference of arguments. */
|
||||
if (pre_body->vars[0]->optimize.known_val
|
||||
&& SAME_TYPE(SCHEME_TYPE(pre_body->vars[0]->optimize.known_val), scheme_lambda_type)) {
|
||||
check_lambda_arg_types_registered((Scheme_Lambda *)pre_body->vars[0]->optimize.known_val,
|
||||
pre_body->vars[0]->use_count);
|
||||
}
|
||||
}
|
||||
|
||||
for (j = pre_body->count; j--; ) {
|
||||
if (pre_body->vars[j]->optimize_used) {
|
||||
used = 1;
|
||||
|
|
Loading…
Reference in New Issue
Block a user