fix optimizer bug for inlining procedures under 'let' in rator position
svn: r18622
This commit is contained in:
parent
99ee6c468f
commit
72db535760
|
@ -1148,6 +1148,42 @@
|
||||||
(err/rt-test (cwv-2-5-f (lambda () 1) (lambda (y z) (+ y 2))) exn:fail:contract:arity?)
|
(err/rt-test (cwv-2-5-f (lambda () 1) (lambda (y z) (+ y 2))) exn:fail:contract:arity?)
|
||||||
(err/rt-test (cwv-2-5-f (lambda () (values 1 2 3)) (lambda (y z) (+ y 2))) exn:fail:contract:arity?)
|
(err/rt-test (cwv-2-5-f (lambda () (values 1 2 3)) (lambda (y z) (+ y 2))) exn:fail:contract:arity?)
|
||||||
|
|
||||||
|
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Inlining with higher-order functions:
|
||||||
|
|
||||||
|
(test 0 'ho1 (let ([x (random 1)])
|
||||||
|
((let ([fn (add1 (random 1))])
|
||||||
|
(lambda (c) c))
|
||||||
|
x)))
|
||||||
|
(test 0 'ho2 (let ([x (random 1)]
|
||||||
|
[id (lambda (c) c)])
|
||||||
|
((let ([fn (add1 (random 1))])
|
||||||
|
id)
|
||||||
|
x)))
|
||||||
|
(test 0 'ho3 (let ([proc (lambda (q)
|
||||||
|
(let ([fn (add1 (random 1))])
|
||||||
|
(lambda (c) c)))])
|
||||||
|
(let ([x (random 1)])
|
||||||
|
((proc 99) x))))
|
||||||
|
(test '(2 0) 'ho4 (let ([y (+ 2 (random 1))])
|
||||||
|
(let ([x (random 1)])
|
||||||
|
((let ([fn (add1 (random 1))])
|
||||||
|
(lambda (c) (list y c)))
|
||||||
|
x))))
|
||||||
|
(test '(2 0) 'ho5 (let ([y (+ 2 (random 1))])
|
||||||
|
(let ([x (random 1)]
|
||||||
|
[id (lambda (c) (list y c))])
|
||||||
|
((let ([fn (add1 (random 1))])
|
||||||
|
id)
|
||||||
|
x))))
|
||||||
|
(test '(2 0) 'ho6 (let ([y (+ 2 (random 1))])
|
||||||
|
(let ([proc (lambda (q)
|
||||||
|
(let ([fn (add1 (random 1))])
|
||||||
|
(lambda (c) (list y c))))])
|
||||||
|
(let ([x (random 1)])
|
||||||
|
((proc 98)
|
||||||
|
x)))))
|
||||||
|
|
||||||
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
(report-errs)
|
(report-errs)
|
||||||
|
|
|
@ -2436,19 +2436,18 @@ static Scheme_Object *apply_inlined(Scheme_Object *p, Scheme_Closure_Data *data,
|
||||||
{
|
{
|
||||||
Scheme_Let_Header *lh;
|
Scheme_Let_Header *lh;
|
||||||
Scheme_Compiled_Let_Value *lv, *prev = NULL;
|
Scheme_Compiled_Let_Value *lv, *prev = NULL;
|
||||||
|
Scheme_Object *val;
|
||||||
int i, expected;
|
int i, expected;
|
||||||
int *flags, flag;
|
int *flags, flag;
|
||||||
|
|
||||||
expected = data->num_params;
|
expected = data->num_params;
|
||||||
|
|
||||||
if (!expected) {
|
if (!expected) {
|
||||||
info = scheme_optimize_info_add_frame(info, nested_count, nested_count, 0);
|
info = scheme_optimize_info_add_frame(info, 0, 0, 0);
|
||||||
info->inline_fuel >>= 1;
|
info->inline_fuel >>= 1;
|
||||||
if (nested_count) info->vclock++;
|
|
||||||
p = scheme_optimize_expr(p, info, context);
|
p = scheme_optimize_expr(p, info, context);
|
||||||
info->next->single_result = info->single_result;
|
info->next->single_result = info->single_result;
|
||||||
if (!nested_count)
|
info->next->preserves_marks = info->preserves_marks;
|
||||||
info->next->preserves_marks = info->preserves_marks;
|
|
||||||
scheme_optimize_info_done(info);
|
scheme_optimize_info_done(info);
|
||||||
|
|
||||||
if (le_prev) {
|
if (le_prev) {
|
||||||
|
@ -2472,7 +2471,7 @@ static Scheme_Object *apply_inlined(Scheme_Object *p, Scheme_Closure_Data *data,
|
||||||
if ((i == expected - 1)
|
if ((i == expected - 1)
|
||||||
&& (SCHEME_CLOSURE_DATA_FLAGS(data) & CLOS_HAS_REST)) {
|
&& (SCHEME_CLOSURE_DATA_FLAGS(data) & CLOS_HAS_REST)) {
|
||||||
int j;
|
int j;
|
||||||
Scheme_Object *l = scheme_null, *val;
|
Scheme_Object *l = scheme_null;
|
||||||
|
|
||||||
for (j = argc; j-- > i; ) {
|
for (j = argc; j-- > i; ) {
|
||||||
if (app)
|
if (app)
|
||||||
|
@ -2488,14 +2487,16 @@ static Scheme_Object *apply_inlined(Scheme_Object *p, Scheme_Closure_Data *data,
|
||||||
}
|
}
|
||||||
l = cons(scheme_list_proc, l);
|
l = cons(scheme_list_proc, l);
|
||||||
val = make_application(l);
|
val = make_application(l);
|
||||||
|
|
||||||
lv->value = val;
|
|
||||||
} else if (app)
|
} else if (app)
|
||||||
lv->value = app->args[i + 1];
|
val = app->args[i + 1];
|
||||||
else if (app3)
|
else if (app3)
|
||||||
lv->value = (i ? app3->rand2 : app3->rand1);
|
val = (i ? app3->rand2 : app3->rand1);
|
||||||
else if (app2)
|
else
|
||||||
lv->value = app2->rand;
|
val = app2->rand;
|
||||||
|
|
||||||
|
if (nested_count)
|
||||||
|
val = scheme_optimize_shift(val, nested_count, 0);
|
||||||
|
lv->value = val;
|
||||||
|
|
||||||
flag = scheme_closure_argument_flags(data, i);
|
flag = scheme_closure_argument_flags(data, i);
|
||||||
flags = (int *)scheme_malloc_atomic(sizeof(int));
|
flags = (int *)scheme_malloc_atomic(sizeof(int));
|
||||||
|
@ -2514,7 +2515,7 @@ static Scheme_Object *apply_inlined(Scheme_Object *p, Scheme_Closure_Data *data,
|
||||||
else
|
else
|
||||||
lh->body = p;
|
lh->body = p;
|
||||||
|
|
||||||
p = scheme_optimize_lets((Scheme_Object *)lh, info, 1 + nested_count, context);
|
p = scheme_optimize_lets((Scheme_Object *)lh, info, 1, context);
|
||||||
|
|
||||||
if (le_prev) {
|
if (le_prev) {
|
||||||
*((Scheme_Object **)(((char *)le_prev) + prev_offset)) = p;
|
*((Scheme_Object **)(((char *)le_prev) + prev_offset)) = p;
|
||||||
|
@ -2538,7 +2539,7 @@ Scheme_Object *optimize_for_inline(Optimize_Info *info, Scheme_Object *le, int a
|
||||||
int offset = 0, single_use = 0, psize = 0;
|
int offset = 0, single_use = 0, psize = 0;
|
||||||
Scheme_Object *bad_app = NULL, *prev = NULL, *orig_le = le;
|
Scheme_Object *bad_app = NULL, *prev = NULL, *orig_le = le;
|
||||||
long prev_offset = 0;
|
long prev_offset = 0;
|
||||||
int nested_count = 0;
|
int nested_count = 0, outside_nested = 0;
|
||||||
|
|
||||||
if (info->inline_fuel < 0)
|
if (info->inline_fuel < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -2568,9 +2569,10 @@ Scheme_Object *optimize_for_inline(Optimize_Info *info, Scheme_Object *le, int a
|
||||||
|
|
||||||
if (!optimized_rator && SAME_TYPE(SCHEME_TYPE(le), scheme_local_type)) {
|
if (!optimized_rator && SAME_TYPE(SCHEME_TYPE(le), scheme_local_type)) {
|
||||||
/* Check for inlining: */
|
/* Check for inlining: */
|
||||||
if (SCHEME_LOCAL_POS(le) >= nested_count)
|
if (SCHEME_LOCAL_POS(le) >= nested_count) {
|
||||||
le = scheme_optimize_info_lookup(info, SCHEME_LOCAL_POS(le) - nested_count, &offset, &single_use, 0, 0, &psize);
|
le = scheme_optimize_info_lookup(info, SCHEME_LOCAL_POS(le) - nested_count, &offset, &single_use, 0, 0, &psize);
|
||||||
else
|
outside_nested = 1;
|
||||||
|
} else
|
||||||
info->has_nonleaf = 1;
|
info->has_nonleaf = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2587,6 +2589,7 @@ Scheme_Object *optimize_for_inline(Optimize_Info *info, Scheme_Object *le, int a
|
||||||
}
|
}
|
||||||
if (!le)
|
if (!le)
|
||||||
break;
|
break;
|
||||||
|
outside_nested = 1;
|
||||||
} else
|
} else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2616,16 +2619,25 @@ Scheme_Object *optimize_for_inline(Optimize_Info *info, Scheme_Object *le, int a
|
||||||
|
|
||||||
if ((sz >= 0) && (single_use || (sz <= threshold))) {
|
if ((sz >= 0) && (single_use || (sz <= threshold))) {
|
||||||
Optimize_Info *sub_info;
|
Optimize_Info *sub_info;
|
||||||
if (nested_count)
|
if (nested_count) {
|
||||||
sub_info = scheme_optimize_info_add_frame(info, nested_count, nested_count, 0);
|
sub_info = scheme_optimize_info_add_frame(info, nested_count, nested_count, nested_count);
|
||||||
else
|
sub_info->vclock++;
|
||||||
|
/* We could propagate bound values in sub_info , but relevant inlining
|
||||||
|
and propagatation has probably already happened when the rator was
|
||||||
|
optimized. */
|
||||||
|
} else
|
||||||
sub_info = info;
|
sub_info = info;
|
||||||
le = scheme_optimize_clone(0, data->code, sub_info, offset, data->num_params);
|
le = scheme_optimize_clone(0, data->code, sub_info,
|
||||||
|
offset + (outside_nested ? nested_count : 0),
|
||||||
|
data->num_params);
|
||||||
if (le) {
|
if (le) {
|
||||||
LOG_INLINE(fprintf(stderr, "Inline %d[%d]<=%d@%d %d %s\n", sz, is_leaf, threshold, info->inline_fuel,
|
LOG_INLINE(fprintf(stderr, "Inline %d[%d]<=%d@%d %d %s\n", sz, is_leaf, threshold, info->inline_fuel,
|
||||||
single_use, data->name ? scheme_write_to_string(data->name, NULL) : "???"));
|
single_use, data->name ? scheme_write_to_string(data->name, NULL) : "???"));
|
||||||
return apply_inlined(le, data, info, argc, app, app2, app3, context,
|
le = apply_inlined(le, data, sub_info, argc, app, app2, app3, context,
|
||||||
nested_count, orig_le, prev, prev_offset);
|
nested_count, orig_le, prev, prev_offset);
|
||||||
|
if (nested_count)
|
||||||
|
scheme_optimize_info_done(sub_info);
|
||||||
|
return le;
|
||||||
} else {
|
} else {
|
||||||
LOG_INLINE(fprintf(stderr, "No inline %s\n", data->name ? scheme_write_to_string(data->name, NULL) : "???"));
|
LOG_INLINE(fprintf(stderr, "No inline %s\n", data->name ? scheme_write_to_string(data->name, NULL) : "???"));
|
||||||
info->has_nonleaf = 1;
|
info->has_nonleaf = 1;
|
||||||
|
@ -2857,33 +2869,30 @@ static void reset_rator(Scheme_Object *app, Scheme_Object *a)
|
||||||
static Scheme_Object *check_app_let_rator(Scheme_Object *app, Scheme_Object *rator, Optimize_Info *info,
|
static Scheme_Object *check_app_let_rator(Scheme_Object *app, Scheme_Object *rator, Optimize_Info *info,
|
||||||
int argc, int context)
|
int argc, int context)
|
||||||
{
|
{
|
||||||
|
/* Convert ((let (....) E) arg ...) to (let (....) (E arg ...)), in case
|
||||||
|
the `let' is immediately apparent. We check for this pattern again
|
||||||
|
in optimize_for_inline() after optimizing a rator. */
|
||||||
if (SAME_TYPE(SCHEME_TYPE(rator), scheme_compiled_let_void_type)) {
|
if (SAME_TYPE(SCHEME_TYPE(rator), scheme_compiled_let_void_type)) {
|
||||||
Scheme_Let_Header *head = (Scheme_Let_Header *)rator;
|
Scheme_Let_Header *head = (Scheme_Let_Header *)rator;
|
||||||
|
Scheme_Compiled_Let_Value *clv = NULL;
|
||||||
|
int i;
|
||||||
|
|
||||||
if ((head->count == 1) && (head->num_clauses == 1)) {
|
rator = head->body;
|
||||||
Scheme_Object *body;
|
for (i = head->num_clauses; i--; ) {
|
||||||
Scheme_Compiled_Let_Value *clv;
|
clv = (Scheme_Compiled_Let_Value *)rator;
|
||||||
|
rator = clv->body;
|
||||||
clv = (Scheme_Compiled_Let_Value *)head->body;
|
|
||||||
body = clv->body;
|
|
||||||
if (SAME_TYPE(SCHEME_TYPE(body), scheme_local_type)
|
|
||||||
&& (SCHEME_LOCAL_POS(body) == 0)
|
|
||||||
&& scheme_is_compiled_procedure(clv->value, 1, 1)) {
|
|
||||||
|
|
||||||
reset_rator(app, scheme_false);
|
|
||||||
app = scheme_optimize_shift(app, 1, 0);
|
|
||||||
reset_rator(app, scheme_make_local(scheme_local_type, 0, 0));
|
|
||||||
|
|
||||||
clv->body = app;
|
|
||||||
|
|
||||||
if (clv->flags[0] & SCHEME_WAS_APPLIED_EXCEPT_ONCE) {
|
|
||||||
clv->flags[0] -= SCHEME_WAS_APPLIED_EXCEPT_ONCE;
|
|
||||||
clv->flags[0] |= SCHEME_WAS_ONLY_APPLIED;
|
|
||||||
}
|
|
||||||
|
|
||||||
return scheme_optimize_expr(rator, info, context);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reset_rator(app, scheme_false);
|
||||||
|
app = scheme_optimize_shift(app, head->count, 0);
|
||||||
|
reset_rator(app, rator);
|
||||||
|
|
||||||
|
if (clv)
|
||||||
|
clv->body = app;
|
||||||
|
else
|
||||||
|
head->body = app;
|
||||||
|
|
||||||
|
return scheme_optimize_expr((Scheme_Object *)head, info, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -3098,15 +3098,9 @@ scheme_optimize_lets(Scheme_Object *form, Optimize_Info *info, int for_inline, i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (for_inline > 1) {
|
body_info = scheme_optimize_info_add_frame(info, head->count, head->count, 0);
|
||||||
info->vclock++;
|
|
||||||
sub_info = scheme_optimize_info_add_frame(info, for_inline - 1, for_inline - 1, 0);
|
|
||||||
} else
|
|
||||||
sub_info = info;
|
|
||||||
|
|
||||||
body_info = scheme_optimize_info_add_frame(sub_info, head->count, head->count, 0);
|
|
||||||
if (for_inline) {
|
if (for_inline) {
|
||||||
rhs_info = scheme_optimize_info_add_frame(info, 0, head->count + (for_inline - 1), 0);
|
rhs_info = scheme_optimize_info_add_frame(info, 0, head->count, 0);
|
||||||
body_info->inline_fuel >>= 1;
|
body_info->inline_fuel >>= 1;
|
||||||
} else
|
} else
|
||||||
rhs_info = body_info;
|
rhs_info = body_info;
|
||||||
|
@ -3562,7 +3556,6 @@ scheme_optimize_lets(Scheme_Object *form, Optimize_Info *info, int for_inline, i
|
||||||
/* Optimized away all clauses? */
|
/* Optimized away all clauses? */
|
||||||
if (!head->num_clauses) {
|
if (!head->num_clauses) {
|
||||||
scheme_optimize_info_done(body_info);
|
scheme_optimize_info_done(body_info);
|
||||||
if (for_inline > 1) scheme_optimize_info_done(sub_info);
|
|
||||||
return head->body;
|
return head->body;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3616,20 +3609,18 @@ scheme_optimize_lets(Scheme_Object *form, Optimize_Info *info, int for_inline, i
|
||||||
value = scheme_optimize_clone(1, value, rhs_info, 0, 0);
|
value = scheme_optimize_clone(1, value, rhs_info, 0, 0);
|
||||||
|
|
||||||
if (value) {
|
if (value) {
|
||||||
info = scheme_optimize_info_add_frame(sub_info, extract_depth, 0, 0);
|
sub_info = scheme_optimize_info_add_frame(info, extract_depth, 0, 0);
|
||||||
info->inline_fuel = 0;
|
sub_info->inline_fuel = 0;
|
||||||
value = scheme_optimize_expr(value, info, context);
|
value = scheme_optimize_expr(value, sub_info, context);
|
||||||
sub_info->single_result = info->single_result;
|
info->single_result = sub_info->single_result;
|
||||||
sub_info->preserves_marks = info->preserves_marks;
|
info->preserves_marks = sub_info->preserves_marks;
|
||||||
scheme_optimize_info_done(info);
|
scheme_optimize_info_done(sub_info);
|
||||||
if (for_inline > 1) scheme_optimize_info_done(sub_info);
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
scheme_optimize_info_done(body_info);
|
scheme_optimize_info_done(body_info);
|
||||||
if (for_inline > 1) scheme_optimize_info_done(sub_info);
|
|
||||||
|
|
||||||
return form;
|
return form;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user