bytecode optimizer: fix inlining bug
When a single-use function is inlined late enough in the optimization process, and when the body has the only use of some variable computed by an expression that can be move in place of the use in the inlined function (but not in the non-inlined function), then it's a problem if the function binding isn't pruned away early enough. Make sure the binding to the function is marked as unused after the function is inlined. This bug was exposed by a recent change to the "dssl2" package.
This commit is contained in:
parent
66b624e8ca
commit
cd9071cb9b
|
@ -6359,6 +6359,16 @@
|
|||
(set! m m)
|
||||
m)))
|
||||
|
||||
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Regresssion test for an optimizer bug
|
||||
|
||||
(define (late-inline-with-single-use-that-turns-out-to-be-movable g)
|
||||
(let ([x (g)])
|
||||
(let ([proc (lambda (y) (list x y))])
|
||||
(let ([only (lambda () ((car (list proc)) '(5)))])
|
||||
(let ([also-only only])
|
||||
(also-only))))))
|
||||
|
||||
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(report-errs)
|
||||
|
|
|
@ -2658,7 +2658,8 @@ int check_potential_size(Scheme_Object *var)
|
|||
}
|
||||
|
||||
Scheme_Object *do_lookup_constant_proc(Optimize_Info *info, Scheme_Object *le,
|
||||
int argc, int for_inline, int for_props, int *_single_use)
|
||||
int argc, int for_inline, int for_props,
|
||||
int *_single_use, Scheme_Object **_single_use_var)
|
||||
/* Return a known procedure, if any.
|
||||
When argc == -1, the result may be a case-lambda or `scheme_constant_key`;
|
||||
otherwise, unless `for_props`, the arity is used to split a case-lambda to extact
|
||||
|
@ -2687,6 +2688,8 @@ Scheme_Object *do_lookup_constant_proc(Optimize_Info *info, Scheme_Object *le,
|
|||
int tmp;
|
||||
tmp = check_single_use(le);
|
||||
*_single_use = tmp;
|
||||
if (tmp)
|
||||
*_single_use_var = le;
|
||||
if ((SCHEME_VAR(le)->mode != SCHEME_VAR_MODE_OPTIMIZE)) {
|
||||
/* We got a local that is bound in a let that is not yet optimized. */
|
||||
return NULL;
|
||||
|
@ -2832,7 +2835,8 @@ Scheme_Object *do_lookup_constant_proc(Optimize_Info *info, Scheme_Object *le,
|
|||
Scheme_Object *lookup_constant_proc(Optimize_Info *info, Scheme_Object *le, int argc)
|
||||
{
|
||||
int single_use = 0;
|
||||
return do_lookup_constant_proc(info, le, argc, 0, 0, &single_use);
|
||||
Scheme_Object *single_use_var;
|
||||
return do_lookup_constant_proc(info, le, argc, 0, 0, &single_use, &single_use_var);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
@ -2850,7 +2854,7 @@ Scheme_Object *optimize_for_inline(Optimize_Info *info, Scheme_Object *le, int a
|
|||
application with two arguments. */
|
||||
{
|
||||
int single_use = 0, psize = 0;
|
||||
Scheme_Object *prev = NULL, *orig_le = le, *le2;
|
||||
Scheme_Object *prev = NULL, *orig_le = le, *le2, *single_use_var = NULL;
|
||||
int already_opt = optimized_rator;
|
||||
|
||||
if ((info->inline_fuel < 0) && info->has_nonleaf)
|
||||
|
@ -2871,7 +2875,7 @@ Scheme_Object *optimize_for_inline(Optimize_Info *info, Scheme_Object *le, int a
|
|||
}
|
||||
|
||||
le2 = le;
|
||||
le = do_lookup_constant_proc(info, le, argc, 1, 0, &single_use);
|
||||
le = do_lookup_constant_proc(info, le, argc, 1, 0, &single_use, &single_use_var);
|
||||
|
||||
if (!le) {
|
||||
info->has_nonleaf = 1;
|
||||
|
@ -2894,7 +2898,7 @@ Scheme_Object *optimize_for_inline(Optimize_Info *info, Scheme_Object *le, int a
|
|||
int len;
|
||||
const char *pname = NULL, *context;
|
||||
info->escapes = 1;
|
||||
le2 = do_lookup_constant_proc(info, le2, argc, 1, 1, &single_use);
|
||||
le2 = do_lookup_constant_proc(info, le2, argc, 1, 1, &single_use, &single_use_var);
|
||||
if (!SAME_TYPE(SCHEME_TYPE(le2), scheme_struct_proc_shape_type)
|
||||
&& !SAME_TYPE(SCHEME_TYPE(le2), scheme_struct_prop_proc_shape_type)){
|
||||
pname = scheme_get_proc_name(le2, &len, 0);
|
||||
|
@ -2942,6 +2946,8 @@ Scheme_Object *optimize_for_inline(Optimize_Info *info, Scheme_Object *le, int a
|
|||
sz,
|
||||
threshold,
|
||||
scheme_optimize_context_to_string(info->context));
|
||||
if (single_use_var)
|
||||
SCHEME_VAR(single_use_var)->optimize_used = 0; /* just in case tentatively used */
|
||||
le = apply_inlined((Scheme_Lambda *)le, sub_info, argc, app, app2, app3, context,
|
||||
orig_le, prev, single_use);
|
||||
return le;
|
||||
|
|
Loading…
Reference in New Issue
Block a user