optimizer: more optimizations for unary operations
Previously, the optimizer simplified the application of some unary functions inside let, for example (car (let () ... (cons 1 2)) => (let () ... 1). This commit extends this to begin forms, like (car (begin ... (cons 1 2)) => (begin ... 1). Also, constant folding and some reductions were only availed in the direct case, for example (procedure? car) => #t. With this commit these reductions are extended to the expressions inside let and begin, for example (procedure? (let () (begin ... car))) => (let () (begin ... #t).
This commit is contained in:
parent
ee799eff48
commit
1f2f7a1df4
|
@ -1210,6 +1210,53 @@
|
||||||
(unsafe-cdr w)))
|
(unsafe-cdr w)))
|
||||||
#f)
|
#f)
|
||||||
|
|
||||||
|
(test-comp '(lambda (w)
|
||||||
|
(list
|
||||||
|
(car (begin (random) w))
|
||||||
|
(cdr (begin (random) w))
|
||||||
|
(pair? (begin (random) w))
|
||||||
|
(null? (begin (random) w))))
|
||||||
|
'(lambda (w)
|
||||||
|
(list
|
||||||
|
(car (begin (random) w))
|
||||||
|
(unsafe-cdr (begin (random) w))
|
||||||
|
(begin (random) #t)
|
||||||
|
(begin (random) #f))))
|
||||||
|
|
||||||
|
(test-comp '(lambda (w f)
|
||||||
|
(list
|
||||||
|
(car (let ([x (random)]) (f x x) w))
|
||||||
|
(cdr (let ([x (random)]) (f x x) w))
|
||||||
|
(pair? (let ([x (random)]) (f x x) w))
|
||||||
|
(null? (let ([x (random)]) (f x x) w))))
|
||||||
|
'(lambda (w f)
|
||||||
|
(list
|
||||||
|
(car (let ([x (random)]) (f x x) w))
|
||||||
|
(unsafe-cdr (let ([x (random)]) (f x x) w))
|
||||||
|
(let ([x (random)]) (f x x) #t)
|
||||||
|
(let ([x (random)]) (f x x) #f))))
|
||||||
|
|
||||||
|
(test-comp '(lambda ()
|
||||||
|
(car (let ([y (random)])
|
||||||
|
(list y (set! y 5)))))
|
||||||
|
'(lambda ()
|
||||||
|
(let ([y (random)])
|
||||||
|
(begin0 y (set! y 5)))))
|
||||||
|
|
||||||
|
; test for unary aplications
|
||||||
|
(test-comp -1
|
||||||
|
'(- 1))
|
||||||
|
(test-comp '(lambda (f) (begin (f) -1))
|
||||||
|
'(lambda (f) (- (begin (f) 1))))
|
||||||
|
(test-comp '(letrec ([x (lambda (t) x)]) (x x) -1)
|
||||||
|
'(- (letrec ([x (lambda (t) x)]) (x x) 1)))
|
||||||
|
(test-comp 1
|
||||||
|
'(car (cons 1 2)))
|
||||||
|
(test-comp '(lambda (f) (begin (f) 1))
|
||||||
|
'(lambda (f) (car (begin (f) (cons 1 2)))))
|
||||||
|
(test-comp '(letrec ([x (lambda (t) x)]) (x x) 1)
|
||||||
|
'(car (letrec ([x (lambda (t) x)]) (x x) (cons 1 2))))
|
||||||
|
|
||||||
(test-comp '(lambda (w z) (box? (list (cons (random w) z))))
|
(test-comp '(lambda (w z) (box? (list (cons (random w) z))))
|
||||||
'(lambda (w z) (random w) #f))
|
'(lambda (w z) (random w) #f))
|
||||||
|
|
||||||
|
@ -1499,6 +1546,26 @@
|
||||||
(values x))
|
(values x))
|
||||||
'(let ([x (+ (cons 1 2) 0)])
|
'(let ([x (+ (cons 1 2) 0)])
|
||||||
x))
|
x))
|
||||||
|
(test-comp '(lambda (x)
|
||||||
|
(begin (random) x))
|
||||||
|
'(lambda (x)
|
||||||
|
(values (begin (random) x))))
|
||||||
|
(test-comp '(lambda (x f)
|
||||||
|
(letrec ([z (lambda () z)]) (f z) x))
|
||||||
|
'(lambda (x f)
|
||||||
|
(values (letrec ([z (lambda () z)]) (f z) x))))
|
||||||
|
(test-comp '(lambda (x f)
|
||||||
|
(letrec ([z (lambda () z)]) (f z) z))
|
||||||
|
'(lambda (x f)
|
||||||
|
(values (letrec ([z (lambda () z)]) (f z) z))))
|
||||||
|
(test-comp '(lambda (f)
|
||||||
|
(let ([x (f)]) (list x x)))
|
||||||
|
'(lambda (f)
|
||||||
|
(let ([x (values (f))]) (list x x))))
|
||||||
|
(test-comp '(lambda (f)
|
||||||
|
(if (f) 0 1))
|
||||||
|
'(lambda (f)
|
||||||
|
(if (values (f)) 0 1)))
|
||||||
|
|
||||||
(test-comp '(let ([x (+ (cons 1 2) 0)])
|
(test-comp '(let ([x (+ (cons 1 2) 0)])
|
||||||
(- x 8))
|
(- x 8))
|
||||||
|
@ -1843,6 +1910,20 @@
|
||||||
88))
|
88))
|
||||||
'(let ([f (lambda (x) x)])
|
'(let ([f (lambda (x) x)])
|
||||||
(list f)))
|
(list f)))
|
||||||
|
(test-comp '(let ([f (lambda (x) x)])
|
||||||
|
(list
|
||||||
|
f
|
||||||
|
f
|
||||||
|
(procedure? f)
|
||||||
|
(procedure? (begin (random) f))
|
||||||
|
(procedure? (letrec ([x (lambda (t) x)]) (x x) f))))
|
||||||
|
'(let ([f (lambda (x) x)])
|
||||||
|
(list
|
||||||
|
f
|
||||||
|
f
|
||||||
|
#t
|
||||||
|
(begin (random) #t)
|
||||||
|
(letrec ([x (lambda (t) x)]) (x x) #t))))
|
||||||
|
|
||||||
(test-comp '(letrec ([f (case-lambda
|
(test-comp '(letrec ([f (case-lambda
|
||||||
[(x) x]
|
[(x) x]
|
||||||
|
@ -2326,6 +2407,43 @@
|
||||||
(let ([p (extfl+ n n)])
|
(let ([p (extfl+ n n)])
|
||||||
(extfl+ p p))))
|
(extfl+ p p))))
|
||||||
|
|
||||||
|
(test-comp '(lambda (n)
|
||||||
|
(let ([p (fl+ n n)])
|
||||||
|
(list
|
||||||
|
(flonum? p)
|
||||||
|
(flonum? (begin (random) p))
|
||||||
|
(flonum? (letrec ([x (lambda (t) x)]) (x x) p)))))
|
||||||
|
'(lambda (n)
|
||||||
|
(let ([p (fl+ n n)])
|
||||||
|
(list
|
||||||
|
#t
|
||||||
|
(begin (random) #t)
|
||||||
|
(letrec ([x (lambda (t) x)]) (x x) #t)))))
|
||||||
|
(test-comp '(lambda (n)
|
||||||
|
(let ([p (fx+ n n)])
|
||||||
|
(list
|
||||||
|
(fixnum? p)
|
||||||
|
(fixnum? (begin (random) p))
|
||||||
|
(fixnum? (letrec ([x (lambda (t) x)]) (x x) p)))))
|
||||||
|
'(lambda (n)
|
||||||
|
(let ([p (fx+ n n)])
|
||||||
|
(list
|
||||||
|
#t
|
||||||
|
(begin (random) #t)
|
||||||
|
(letrec ([x (lambda (t) x)]) (x x) #t)))))
|
||||||
|
(test-comp '(lambda (n)
|
||||||
|
(let ([p (extfl+ n n)])
|
||||||
|
(list
|
||||||
|
(extflonum? p)
|
||||||
|
(extflonum? (begin (random) p))
|
||||||
|
(extflonum? (letrec ([x (lambda (t) x)]) (x x) p)))))
|
||||||
|
'(lambda (n)
|
||||||
|
(let ([p (extfl+ n n)])
|
||||||
|
(list
|
||||||
|
#t
|
||||||
|
(begin (random) #t)
|
||||||
|
(letrec ([x (lambda (t) x)]) (x x) #t)))))
|
||||||
|
|
||||||
;; simple cross-module inlining
|
;; simple cross-module inlining
|
||||||
(test-comp `(module m racket/base
|
(test-comp `(module m racket/base
|
||||||
(require racket/bool)
|
(require racket/bool)
|
||||||
|
@ -2683,6 +2801,25 @@
|
||||||
`(lambda (b)
|
`(lambda (b)
|
||||||
(with-continuation-mark 'x 'y (box (box b)))))
|
(with-continuation-mark 'x 'y (box (box b)))))
|
||||||
|
|
||||||
|
(test-comp `(lambda (x y f)
|
||||||
|
(set! x 5)
|
||||||
|
(list
|
||||||
|
(#%variable-reference x)
|
||||||
|
(#%variable-reference y)
|
||||||
|
(variable-reference-constant? (#%variable-reference x))
|
||||||
|
(variable-reference-constant? (#%variable-reference y))
|
||||||
|
(variable-reference-constant? (letrec ([z (lambda () z)]) (f z) (#%variable-reference x)))
|
||||||
|
(variable-reference-constant? (letrec ([z (lambda () z)]) (f z) (#%variable-reference y)))))
|
||||||
|
`(lambda (x y f)
|
||||||
|
(set! x 5)
|
||||||
|
(list
|
||||||
|
(#%variable-reference x)
|
||||||
|
(#%variable-reference y)
|
||||||
|
#f
|
||||||
|
#t
|
||||||
|
(letrec ([z (lambda () z)]) (f z) #f)
|
||||||
|
(letrec ([z (lambda () z)]) (f z) #t))))
|
||||||
|
|
||||||
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Check splitting of definitions
|
;; Check splitting of definitions
|
||||||
(test-comp `(module m racket/base
|
(test-comp `(module m racket/base
|
||||||
|
|
|
@ -4078,6 +4078,21 @@ static int foldable_body(Scheme_Object *f)
|
||||||
return (SCHEME_TYPE(d->code) > _scheme_values_types_);
|
return (SCHEME_TYPE(d->code) > _scheme_values_types_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int scheme_is_foldable_prim(Scheme_Object *f)
|
||||||
|
{
|
||||||
|
if (SCHEME_PRIMP(f)
|
||||||
|
&& ((((Scheme_Primitive_Proc *)f)->pp.flags & SCHEME_PRIM_OPT_MASK)
|
||||||
|
== SCHEME_PRIM_OPT_FOLDING))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (SCHEME_CLSD_PRIMP(f)
|
||||||
|
&& ((((Scheme_Closed_Primitive_Proc *)f)->pp.flags & SCHEME_PRIM_OPT_MASK)
|
||||||
|
== SCHEME_PRIM_OPT_FOLDING))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
Scheme_Object *scheme_make_application(Scheme_Object *v, Optimize_Info *info)
|
Scheme_Object *scheme_make_application(Scheme_Object *v, Optimize_Info *info)
|
||||||
{
|
{
|
||||||
Scheme_Object *o;
|
Scheme_Object *o;
|
||||||
|
@ -4103,11 +4118,7 @@ Scheme_Object *scheme_make_application(Scheme_Object *v, Optimize_Info *info)
|
||||||
|
|
||||||
f = SCHEME_CAR(v);
|
f = SCHEME_CAR(v);
|
||||||
|
|
||||||
if ((SCHEME_PRIMP(f) && ((((Scheme_Primitive_Proc *)f)->pp.flags & SCHEME_PRIM_OPT_MASK)
|
if (scheme_is_foldable_prim(f)
|
||||||
== SCHEME_PRIM_OPT_FOLDING))
|
|
||||||
|| (SCHEME_CLSD_PRIMP(f)
|
|
||||||
&& ((((Scheme_Closed_Primitive_Proc *)f)->pp.flags & SCHEME_PRIM_OPT_MASK)
|
|
||||||
== SCHEME_PRIM_OPT_FOLDING))
|
|
||||||
|| (SAME_TYPE(SCHEME_TYPE(f), scheme_closure_type)
|
|| (SAME_TYPE(SCHEME_TYPE(f), scheme_closure_type)
|
||||||
&& (foldable_body(f)))) {
|
&& (foldable_body(f)))) {
|
||||||
f = scheme_try_apply(f, SCHEME_CDR(v), info);
|
f = scheme_try_apply(f, SCHEME_CDR(v), info);
|
||||||
|
|
|
@ -143,7 +143,8 @@ static Scheme_Object *optimize_shift(Scheme_Object *obj, int delta, int after_de
|
||||||
|
|
||||||
static int relevant_predicate(Scheme_Object *pred);
|
static int relevant_predicate(Scheme_Object *pred);
|
||||||
static int single_valued_noncm_expression(Scheme_Object *expr, int fuel);
|
static int single_valued_noncm_expression(Scheme_Object *expr, int fuel);
|
||||||
static Scheme_Object *optimize_ignored(Scheme_Object *e, Optimize_Info *info, int expected_vals, int maybe_omittable,
|
static Scheme_Object *optimize_ignored(Scheme_Object *e, Optimize_Info *info, int id_offset,
|
||||||
|
int expected_vals, int maybe_omittable,
|
||||||
int fuel);
|
int fuel);
|
||||||
static int movable_expression(Scheme_Object *expr, Optimize_Info *info, int delta,
|
static int movable_expression(Scheme_Object *expr, Optimize_Info *info, int delta,
|
||||||
int cross_lambda, int cross_k,
|
int cross_lambda, int cross_k,
|
||||||
|
@ -517,7 +518,8 @@ static Scheme_Object *ensure_single_value(Scheme_Object *e)
|
||||||
return (Scheme_Object *)app2;
|
return (Scheme_Object *)app2;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Scheme_Object *do_make_discarding_sequence(Scheme_Object *e1, Scheme_Object *e2, Optimize_Info *info,
|
static Scheme_Object *do_make_discarding_sequence(Scheme_Object *e1, Scheme_Object *e2,
|
||||||
|
Optimize_Info *info, int id_offset,
|
||||||
int ignored, int rev)
|
int ignored, int rev)
|
||||||
/* Evaluate `e1` then `e2` (or opposite order if rev), and each must
|
/* Evaluate `e1` then `e2` (or opposite order if rev), and each must
|
||||||
produce a single value. The result of `e1` is ignored and the
|
produce a single value. The result of `e1` is ignored and the
|
||||||
|
@ -526,23 +528,23 @@ static Scheme_Object *do_make_discarding_sequence(Scheme_Object *e1, Scheme_Obje
|
||||||
{
|
{
|
||||||
int e2_omit;
|
int e2_omit;
|
||||||
|
|
||||||
e2_omit = scheme_omittable_expr(e2, 1, 5, 0, info, NULL, 0, 0, ID_OMIT);
|
e2_omit = scheme_omittable_expr(e2, 1, 5, 0, info, NULL, 0, id_offset, ID_OMIT);
|
||||||
|
|
||||||
if (!e2_omit && !single_valued_noncm_expression(e2, 5))
|
if (!e2_omit && !single_valued_noncm_expression(e2, 5))
|
||||||
e2 = ensure_single_value(e2);
|
e2 = ensure_single_value(e2);
|
||||||
|
|
||||||
if (scheme_omittable_expr(e1, 1, 5, 0, info, NULL, 0, 0, ID_OMIT))
|
if (scheme_omittable_expr(e1, 1, 5, 0, info, NULL, 0, id_offset, ID_OMIT))
|
||||||
return e2;
|
return e2;
|
||||||
else if (single_valued_noncm_expression(e1, 5))
|
else if (single_valued_noncm_expression(e1, 5))
|
||||||
e1 = optimize_ignored(e1, info, 1, 0, 5);
|
e1 = optimize_ignored(e1, info, id_offset, 1, 0, 5);
|
||||||
else
|
else
|
||||||
e1 = ensure_single_value(optimize_ignored(e1, info, 1, 0, 5));
|
e1 = ensure_single_value(optimize_ignored(e1, info, id_offset, 1, 0, 5));
|
||||||
|
|
||||||
if (e2_omit && ignored)
|
if (e2_omit && ignored)
|
||||||
return e1;
|
return e1;
|
||||||
|
|
||||||
/* use `begin` instead of `begin0` if we can swap the order: */
|
/* use `begin` instead of `begin0` if we can swap the order: */
|
||||||
if (rev && movable_expression(e2, info, 0, 0, 0, 0, 50))
|
if (rev && movable_expression(e2, info, -id_offset, 0, 0, 0, 50))
|
||||||
rev = 0;
|
rev = 0;
|
||||||
|
|
||||||
return scheme_make_sequence_compilation(scheme_make_pair((rev ? e2 : e1),
|
return scheme_make_sequence_compilation(scheme_make_pair((rev ? e2 : e1),
|
||||||
|
@ -550,18 +552,20 @@ static Scheme_Object *do_make_discarding_sequence(Scheme_Object *e1, Scheme_Obje
|
||||||
rev ? -1 : 1);
|
rev ? -1 : 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Scheme_Object *make_discarding_sequence(Scheme_Object *e1, Scheme_Object *e2, Optimize_Info *info)
|
static Scheme_Object *make_discarding_sequence(Scheme_Object *e1, Scheme_Object *e2,
|
||||||
|
Optimize_Info *info, int id_offset)
|
||||||
{
|
{
|
||||||
return do_make_discarding_sequence(e1, e2, info, 0, 0);
|
return do_make_discarding_sequence(e1, e2, info, id_offset, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Scheme_Object *make_discarding_reverse_sequence(Scheme_Object *e1, Scheme_Object *e2, Optimize_Info *info)
|
static Scheme_Object *make_discarding_reverse_sequence(Scheme_Object *e1, Scheme_Object *e2,
|
||||||
|
Optimize_Info *info, int id_offset)
|
||||||
{
|
{
|
||||||
return do_make_discarding_sequence(e1, e2, info, 0, 1);
|
return do_make_discarding_sequence(e1, e2, info, id_offset, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Scheme_Object *make_discarding_app_sequence(Scheme_App_Rec *appr, int result_pos, Scheme_Object *result,
|
static Scheme_Object *make_discarding_app_sequence(Scheme_App_Rec *appr, int result_pos, Scheme_Object *result,
|
||||||
Optimize_Info *info)
|
Optimize_Info *info, int id_offset)
|
||||||
/* Generalize do_make_discarding_sequence() to a sequence of argument
|
/* Generalize do_make_discarding_sequence() to a sequence of argument
|
||||||
expressions, where `result_pos` is the position of the returned
|
expressions, where `result_pos` is the position of the returned
|
||||||
argument. If `result_pos` is -1, then all argument results will be
|
argument. If `result_pos` is -1, then all argument results will be
|
||||||
|
@ -581,12 +585,12 @@ static Scheme_Object *make_discarding_app_sequence(Scheme_App_Rec *appr, int res
|
||||||
/* drop if not result pos */
|
/* drop if not result pos */
|
||||||
} else if (single_valued_noncm_expression(e, 5)) {
|
} else if (single_valued_noncm_expression(e, 5)) {
|
||||||
if (i != result_pos) {
|
if (i != result_pos) {
|
||||||
l = scheme_make_pair(optimize_ignored(e, info, 1, 0, 5), l);
|
l = scheme_make_pair(optimize_ignored(e, info, id_offset, 1, 0, 5), l);
|
||||||
}
|
}
|
||||||
} else if (i == result_pos) {
|
} else if (i == result_pos) {
|
||||||
e = ensure_single_value(e);
|
e = ensure_single_value(e);
|
||||||
} else if (i != result_pos) {
|
} else if (i != result_pos) {
|
||||||
e = ensure_single_value(optimize_ignored(e, info, 1, 0, 5));
|
e = ensure_single_value(optimize_ignored(e, info, id_offset, 1, 0, 5));
|
||||||
l = scheme_make_pair(e, l);
|
l = scheme_make_pair(e, l);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -609,14 +613,15 @@ static Scheme_Object *make_discarding_app_sequence(Scheme_App_Rec *appr, int res
|
||||||
return scheme_make_sequence_compilation(l, 1);
|
return scheme_make_sequence_compilation(l, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Scheme_Object *optimize_ignored(Scheme_Object *e, Optimize_Info *info, int expected_vals, int maybe_omittable,
|
static Scheme_Object *optimize_ignored(Scheme_Object *e, Optimize_Info *info, int id_offset,
|
||||||
|
int expected_vals, int maybe_omittable,
|
||||||
int fuel)
|
int fuel)
|
||||||
/* Simplify an expression whose result will be ignored. The
|
/* Simplify an expression whose result will be ignored. The
|
||||||
`expected_vals` is 1 or -1. If `maybe_omittable`, the result can be
|
`expected_vals` is 1 or -1. If `maybe_omittable`, the result can be
|
||||||
NULL to dincate that it can be omitted. */
|
NULL to dincate that it can be omitted. */
|
||||||
{
|
{
|
||||||
if (maybe_omittable) {
|
if (maybe_omittable) {
|
||||||
if (scheme_omittable_expr(e, expected_vals, 5, 0, info, NULL, 0, 0, ID_OMIT))
|
if (scheme_omittable_expr(e, expected_vals, 5, 0, info, NULL, 0, id_offset, ID_OMIT))
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -630,7 +635,7 @@ static Scheme_Object *optimize_ignored(Scheme_Object *e, Optimize_Info *info, in
|
||||||
|
|
||||||
if (!SAME_OBJ(app->rator, scheme_values_func)) /* `values` is probably here to ensure a single result */
|
if (!SAME_OBJ(app->rator, scheme_values_func)) /* `values` is probably here to ensure a single result */
|
||||||
if (scheme_is_functional_nonfailing_primitive(app->rator, 1, expected_vals))
|
if (scheme_is_functional_nonfailing_primitive(app->rator, 1, expected_vals))
|
||||||
return do_make_discarding_sequence(app->rand, scheme_void, info, 1, 0);
|
return do_make_discarding_sequence(app->rand, scheme_void, info, id_offset, 1, 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case scheme_application3_type:
|
case scheme_application3_type:
|
||||||
|
@ -641,9 +646,9 @@ static Scheme_Object *optimize_ignored(Scheme_Object *e, Optimize_Info *info, in
|
||||||
return do_make_discarding_sequence(app->rand1,
|
return do_make_discarding_sequence(app->rand1,
|
||||||
do_make_discarding_sequence(app->rand2,
|
do_make_discarding_sequence(app->rand2,
|
||||||
scheme_void,
|
scheme_void,
|
||||||
info,
|
info, id_offset,
|
||||||
1, 0),
|
1, 0),
|
||||||
info,
|
info, id_offset,
|
||||||
1, 0);
|
1, 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -652,7 +657,7 @@ static Scheme_Object *optimize_ignored(Scheme_Object *e, Optimize_Info *info, in
|
||||||
Scheme_App_Rec *app = (Scheme_App_Rec *)e;
|
Scheme_App_Rec *app = (Scheme_App_Rec *)e;
|
||||||
|
|
||||||
if (scheme_is_functional_nonfailing_primitive(app->args[0], app->num_args, expected_vals))
|
if (scheme_is_functional_nonfailing_primitive(app->args[0], app->num_args, expected_vals))
|
||||||
return make_discarding_app_sequence(app, -1, NULL, info);
|
return make_discarding_app_sequence(app, -1, NULL, info, id_offset);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -666,11 +671,12 @@ static Scheme_Object *make_sequence_2(Scheme_Object *a, Scheme_Object *b)
|
||||||
return scheme_make_sequence_compilation(scheme_make_pair(a, scheme_make_pair(b, scheme_null)), 1);
|
return scheme_make_sequence_compilation(scheme_make_pair(a, scheme_make_pair(b, scheme_null)), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Scheme_Object *make_discarding_first_sequence(Scheme_Object *e1, Scheme_Object *e2, Optimize_Info *info)
|
static Scheme_Object *make_discarding_first_sequence(Scheme_Object *e1, Scheme_Object *e2,
|
||||||
|
Optimize_Info *info, int id_offset)
|
||||||
/* Like make_discarding_sequence(), but second expression is not constrained to
|
/* Like make_discarding_sequence(), but second expression is not constrained to
|
||||||
a single result. */
|
a single result. */
|
||||||
{
|
{
|
||||||
e1 = optimize_ignored(e1, info, 1, 1, 5);
|
e1 = optimize_ignored(e1, info, id_offset, 1, 1, 5);
|
||||||
if (!e1)
|
if (!e1)
|
||||||
return e2;
|
return e2;
|
||||||
return make_sequence_2(e1, e2);
|
return make_sequence_2(e1, e2);
|
||||||
|
@ -1157,6 +1163,7 @@ static int single_valued_noncm_expression(Scheme_Object *expr, int fuel)
|
||||||
break;
|
break;
|
||||||
case scheme_compiled_unclosed_procedure_type:
|
case scheme_compiled_unclosed_procedure_type:
|
||||||
case scheme_case_lambda_sequence_type:
|
case scheme_case_lambda_sequence_type:
|
||||||
|
case scheme_set_bang_type:
|
||||||
return 1;
|
return 1;
|
||||||
default:
|
default:
|
||||||
if (SCHEME_TYPE(expr) > _scheme_compiled_values_types_)
|
if (SCHEME_TYPE(expr) > _scheme_compiled_values_types_)
|
||||||
|
@ -1236,7 +1243,7 @@ static int movable_expression(Scheme_Object *expr, Optimize_Info *info, int delt
|
||||||
/* Ok if not mutable */
|
/* Ok if not mutable */
|
||||||
int pos = SCHEME_LOCAL_POS(expr);
|
int pos = SCHEME_LOCAL_POS(expr);
|
||||||
if (pos + delta < 0)
|
if (pos + delta < 0)
|
||||||
return 1;
|
return 0; /* assume non-movable */
|
||||||
else if (!optimize_is_mutated(info, pos + delta)) {
|
else if (!optimize_is_mutated(info, pos + delta)) {
|
||||||
if (check_space) {
|
if (check_space) {
|
||||||
if (optimize_is_local_type_valued(info, pos + delta))
|
if (optimize_is_local_type_valued(info, pos + delta))
|
||||||
|
@ -1328,43 +1335,40 @@ static Scheme_Object *finish_optimize_application(Scheme_App_Rec *app, Optimize_
|
||||||
static Scheme_Object *finish_optimize_application2(Scheme_App2_Rec *app, Optimize_Info *info, int context, int rator_flags);
|
static Scheme_Object *finish_optimize_application2(Scheme_App2_Rec *app, Optimize_Info *info, int context, int rator_flags);
|
||||||
static Scheme_Object *finish_optimize_application3(Scheme_App3_Rec *app, Optimize_Info *info, int context, int rator_flags);
|
static Scheme_Object *finish_optimize_application3(Scheme_App3_Rec *app, Optimize_Info *info, int context, int rator_flags);
|
||||||
|
|
||||||
static Scheme_Object *try_optimize_fold(Scheme_Object *f, Scheme_Object *o, Optimize_Info *info)
|
static Scheme_Object *try_optimize_fold(Scheme_Object *f, Scheme_Object *args, Scheme_Object *o, Optimize_Info *info)
|
||||||
|
/* If `args` is NULL, extract arguments from `o` */
|
||||||
{
|
{
|
||||||
if ((SCHEME_PRIMP(f)
|
if (scheme_is_foldable_prim(f)) {
|
||||||
&& ((((Scheme_Primitive_Proc *)f)->pp.flags & SCHEME_PRIM_OPT_MASK)
|
|
||||||
== SCHEME_PRIM_OPT_FOLDING))
|
|
||||||
|| (SCHEME_CLSD_PRIMP(f)
|
|
||||||
&& ((((Scheme_Closed_Primitive_Proc *)f)->pp.flags & SCHEME_PRIM_OPT_MASK)
|
|
||||||
== SCHEME_PRIM_OPT_FOLDING))) {
|
|
||||||
Scheme_Object *args;
|
|
||||||
|
|
||||||
switch (SCHEME_TYPE(o)) {
|
if (!args) {
|
||||||
case scheme_application_type:
|
switch (SCHEME_TYPE(o)) {
|
||||||
{
|
case scheme_application_type:
|
||||||
Scheme_App_Rec *app = (Scheme_App_Rec *)o;
|
{
|
||||||
int i;
|
Scheme_App_Rec *app = (Scheme_App_Rec *)o;
|
||||||
|
int i;
|
||||||
|
|
||||||
args = scheme_null;
|
args = scheme_null;
|
||||||
for (i = app->num_args; i--; ) {
|
for (i = app->num_args; i--; ) {
|
||||||
args = scheme_make_pair(app->args[i + 1], args);
|
args = scheme_make_pair(app->args[i + 1], args);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case scheme_application2_type:
|
||||||
|
{
|
||||||
|
Scheme_App2_Rec *app = (Scheme_App2_Rec *)o;
|
||||||
|
args = scheme_make_pair(app->rand, scheme_null);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case scheme_application3_type:
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
Scheme_App3_Rec *app = (Scheme_App3_Rec *)o;
|
||||||
|
args = scheme_make_pair(app->rand1,
|
||||||
|
scheme_make_pair(app->rand2,
|
||||||
|
scheme_null));
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case scheme_application2_type:
|
|
||||||
{
|
|
||||||
Scheme_App2_Rec *app = (Scheme_App2_Rec *)o;
|
|
||||||
args = scheme_make_pair(app->rand, scheme_null);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case scheme_application3_type:
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
Scheme_App3_Rec *app = (Scheme_App3_Rec *)o;
|
|
||||||
args = scheme_make_pair(app->rand1,
|
|
||||||
scheme_make_pair(app->rand2,
|
|
||||||
scheme_null));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return scheme_try_apply(f, args, info);
|
return scheme_try_apply(f, args, info);
|
||||||
|
@ -2621,10 +2625,10 @@ static Scheme_Object *finish_optimize_any_application(Scheme_Object *app, Scheme
|
||||||
{
|
{
|
||||||
if (context & OPT_CONTEXT_BOOLEAN)
|
if (context & OPT_CONTEXT_BOOLEAN)
|
||||||
if (rator_implies_predicate(rator, argc))
|
if (rator_implies_predicate(rator, argc))
|
||||||
return make_discarding_sequence(app, scheme_true, info);
|
return make_discarding_sequence(app, scheme_true, info, 0);
|
||||||
|
|
||||||
if (SAME_OBJ(rator, scheme_void_proc))
|
if (SAME_OBJ(rator, scheme_void_proc))
|
||||||
return make_discarding_sequence(app, scheme_void, info);
|
return make_discarding_sequence(app, scheme_void, info, 0);
|
||||||
|
|
||||||
return app;
|
return app;
|
||||||
}
|
}
|
||||||
|
@ -2646,7 +2650,7 @@ static Scheme_Object *finish_optimize_application(Scheme_App_Rec *app, Optimize_
|
||||||
info->kclock += 1;
|
info->kclock += 1;
|
||||||
|
|
||||||
if (all_vals) {
|
if (all_vals) {
|
||||||
le = try_optimize_fold(app->args[0], (Scheme_Object *)app, info);
|
le = try_optimize_fold(app->args[0], NULL, (Scheme_Object *)app, info);
|
||||||
if (le)
|
if (le)
|
||||||
return le;
|
return le;
|
||||||
}
|
}
|
||||||
|
@ -2670,19 +2674,22 @@ static Scheme_Object *finish_optimize_application(Scheme_App_Rec *app, Optimize_
|
||||||
info, context);
|
info, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Scheme_Object *lookup_constant_proc(Optimize_Info *info, Scheme_Object *rand)
|
static Scheme_Object *lookup_constant_proc(Optimize_Info *info, Scheme_Object *rand, int delta)
|
||||||
{
|
{
|
||||||
Scheme_Object *c = NULL;
|
Scheme_Object *c = NULL;
|
||||||
|
|
||||||
if (SAME_TYPE(scheme_compiled_unclosed_procedure_type, SCHEME_TYPE(rand)))
|
if (SAME_TYPE(scheme_compiled_unclosed_procedure_type, SCHEME_TYPE(rand)))
|
||||||
c = rand;
|
c = rand;
|
||||||
if (SAME_TYPE(SCHEME_TYPE(rand), scheme_local_type)) {
|
else if (SAME_TYPE(SCHEME_TYPE(rand), scheme_local_type)) {
|
||||||
int offset;
|
int offset, pos;
|
||||||
Scheme_Object *expr;
|
Scheme_Object *expr;
|
||||||
expr = optimize_reverse(info, SCHEME_LOCAL_POS(rand), 0, 0);
|
pos = SCHEME_LOCAL_POS(rand);
|
||||||
c = optimize_info_lookup(info, SCHEME_LOCAL_POS(expr), &offset, NULL, 0, 0, NULL, NULL);
|
if (pos >= delta) {
|
||||||
}
|
pos -= delta;
|
||||||
if (SAME_TYPE(SCHEME_TYPE(rand), scheme_compiled_toplevel_type)) {
|
expr = optimize_reverse(info, pos, 0, 0);
|
||||||
|
c = optimize_info_lookup(info, SCHEME_LOCAL_POS(expr), &offset, NULL, 0, 0, NULL, NULL);
|
||||||
|
}
|
||||||
|
} else if (SAME_TYPE(SCHEME_TYPE(rand), scheme_compiled_toplevel_type)) {
|
||||||
if (info->top_level_consts) {
|
if (info->top_level_consts) {
|
||||||
int pos;
|
int pos;
|
||||||
|
|
||||||
|
@ -2716,24 +2723,29 @@ static Scheme_Object *lookup_constant_proc(Optimize_Info *info, Scheme_Object *r
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Scheme_Object *check_known2_pred(Optimize_Info *info, Scheme_App2_Rec *app)
|
static Scheme_Object *check_known2_pred(Optimize_Info *info, Scheme_App2_Rec *app,
|
||||||
|
Scheme_Object *rand, int id_offset)
|
||||||
/* Simplify `(pred x)' where `x' is known to match a predicate */
|
/* Simplify `(pred x)' where `x' is known to match a predicate */
|
||||||
{
|
{
|
||||||
if (SAME_TYPE(SCHEME_TYPE(app->rand), scheme_local_type)) {
|
if (SAME_TYPE(SCHEME_TYPE(rand), scheme_local_type)) {
|
||||||
if (relevant_predicate(app->rator)) {
|
if (relevant_predicate(app->rator)) {
|
||||||
Scheme_Object *pred;
|
Scheme_Object *pred;
|
||||||
int pos = SCHEME_LOCAL_POS(app->rand);
|
int pos = SCHEME_LOCAL_POS(rand);
|
||||||
|
|
||||||
if (optimize_is_mutated(info, pos))
|
if (pos >= id_offset) {
|
||||||
return NULL;
|
pos -= id_offset;
|
||||||
|
|
||||||
pred = optimize_get_predicate(pos, info);
|
if (optimize_is_mutated(info, pos))
|
||||||
if (pred) {
|
return NULL;
|
||||||
if (SAME_OBJ(pred, app->rator))
|
|
||||||
return scheme_true;
|
pred = optimize_get_predicate(pos, info);
|
||||||
else {
|
if (pred) {
|
||||||
/* Relies on relevant predicates being disjoint */
|
if (SAME_OBJ(pred, app->rator))
|
||||||
return scheme_false;
|
return scheme_true;
|
||||||
|
else {
|
||||||
|
/* Relies on relevant predicates being disjoint */
|
||||||
|
return scheme_false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2742,24 +2754,28 @@ static Scheme_Object *check_known2_pred(Optimize_Info *info, Scheme_App2_Rec *ap
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void check_known2(Optimize_Info *info, Scheme_App2_Rec *app, const char *who,
|
static void check_known2(Optimize_Info *info, Scheme_App2_Rec *app,
|
||||||
Scheme_Object *expect_pred, Scheme_Object *unsafe)
|
Scheme_Object *rand, int id_offset,
|
||||||
|
const char *who, Scheme_Object *expect_pred, Scheme_Object *unsafe)
|
||||||
/* Replace the rator with an unsafe version if we know that it's ok. Alternatively,
|
/* Replace the rator with an unsafe version if we know that it's ok. Alternatively,
|
||||||
the rator implies a check, so add type information for subsequent expressions. */
|
the rator implies a check, so add type information for subsequent expressions. */
|
||||||
{
|
{
|
||||||
if (IS_NAMED_PRIM(app->rator, who)) {
|
if (IS_NAMED_PRIM(app->rator, who)) {
|
||||||
if (SAME_TYPE(SCHEME_TYPE(app->rand), scheme_local_type)) {
|
if (SAME_TYPE(SCHEME_TYPE(rand), scheme_local_type)) {
|
||||||
Scheme_Object *pred;
|
Scheme_Object *pred;
|
||||||
int pos = SCHEME_LOCAL_POS(app->rand);
|
int pos = SCHEME_LOCAL_POS(rand);
|
||||||
|
|
||||||
if (optimize_is_mutated(info, pos))
|
if (pos >= id_offset) {
|
||||||
return;
|
pos -= id_offset;
|
||||||
|
if (optimize_is_mutated(info, pos))
|
||||||
pred = optimize_get_predicate(pos, info);
|
return;
|
||||||
if (pred && SAME_OBJ(pred, expect_pred))
|
|
||||||
app->rator = unsafe;
|
pred = optimize_get_predicate(pos, info);
|
||||||
else
|
if (pred && SAME_OBJ(pred, expect_pred))
|
||||||
add_type(info, pos, expect_pred);
|
app->rator = unsafe;
|
||||||
|
else
|
||||||
|
add_type(info, pos, expect_pred);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2769,7 +2785,7 @@ static Scheme_Object *try_reduce_predicate(Scheme_Object *rator, Scheme_Object *
|
||||||
Scheme_App2_Rec *arg_app2,
|
Scheme_App2_Rec *arg_app2,
|
||||||
Scheme_App3_Rec *arg_app3,
|
Scheme_App3_Rec *arg_app3,
|
||||||
Scheme_App_Rec *arg_app,
|
Scheme_App_Rec *arg_app,
|
||||||
Optimize_Info *info)
|
Optimize_Info *info, int id_offset)
|
||||||
/* Change (pair? (list X complex-Y Z)) => (begin complex-Y #t), etc.
|
/* Change (pair? (list X complex-Y Z)) => (begin complex-Y #t), etc.
|
||||||
So much more could be done with type inference, but we're checking some
|
So much more could be done with type inference, but we're checking some
|
||||||
known predicates against the results of some known constructors, because
|
known predicates against the results of some known constructors, because
|
||||||
|
@ -2785,11 +2801,11 @@ static Scheme_Object *try_reduce_predicate(Scheme_Object *rator, Scheme_Object *
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (arg_app2)
|
if (arg_app2)
|
||||||
pred = expr_implies_predicate((Scheme_Object *)arg_app2, info, 0, 1);
|
pred = expr_implies_predicate((Scheme_Object *)arg_app2, info, id_offset, 1);
|
||||||
else if (arg_app3)
|
else if (arg_app3)
|
||||||
pred = expr_implies_predicate((Scheme_Object *)arg_app3, info, 0, 1);
|
pred = expr_implies_predicate((Scheme_Object *)arg_app3, info, id_offset, 1);
|
||||||
else
|
else
|
||||||
pred = expr_implies_predicate((Scheme_Object *)arg_app, info, 0, 1);
|
pred = expr_implies_predicate((Scheme_Object *)arg_app, info, id_offset, 1);
|
||||||
|
|
||||||
if (!pred)
|
if (!pred)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -2797,15 +2813,38 @@ static Scheme_Object *try_reduce_predicate(Scheme_Object *rator, Scheme_Object *
|
||||||
matches = SAME_OBJ(rator, pred);
|
matches = SAME_OBJ(rator, pred);
|
||||||
|
|
||||||
if (arg_app2)
|
if (arg_app2)
|
||||||
return make_discarding_sequence(arg_app2->rand, (matches ? scheme_true : scheme_false), info);
|
return make_discarding_sequence(arg_app2->rand, (matches ? scheme_true : scheme_false), info, id_offset);
|
||||||
else if (arg_app3)
|
else if (arg_app3)
|
||||||
return make_discarding_sequence(arg_app3->rand1,
|
return make_discarding_sequence(arg_app3->rand1,
|
||||||
make_discarding_sequence(arg_app3->rand2,
|
make_discarding_sequence(arg_app3->rand2,
|
||||||
(matches ? scheme_true : scheme_false),
|
(matches ? scheme_true : scheme_false),
|
||||||
info),
|
info, id_offset),
|
||||||
info);
|
info, id_offset);
|
||||||
else
|
else
|
||||||
return make_discarding_app_sequence(arg_app, -1, (matches ? scheme_true : scheme_false), info);
|
return make_discarding_app_sequence(arg_app, -1, (matches ? scheme_true : scheme_false), info, id_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Scheme_Object *replace_tail_inside(Scheme_Object *alt, Scheme_Object *inside, Scheme_Object *orig) {
|
||||||
|
if (inside) {
|
||||||
|
switch (SCHEME_TYPE(inside)) {
|
||||||
|
case scheme_sequence_type:
|
||||||
|
if (((Scheme_Sequence *)inside)->count)
|
||||||
|
((Scheme_Sequence *)inside)->array[((Scheme_Sequence *)inside)->count-1] = alt;
|
||||||
|
else
|
||||||
|
scheme_signal_error("internal error: strange inside replacement");
|
||||||
|
break;
|
||||||
|
case scheme_compiled_let_void_type:
|
||||||
|
((Scheme_Let_Header *)inside)->body = alt;
|
||||||
|
break;
|
||||||
|
case scheme_compiled_let_value_type:
|
||||||
|
((Scheme_Compiled_Let_Value *)inside)->body = alt;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
scheme_signal_error("internal error: strange inside replacement");
|
||||||
|
}
|
||||||
|
return orig;
|
||||||
|
}
|
||||||
|
return alt;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Scheme_Object *optimize_application2(Scheme_Object *o, Optimize_Info *info, int context)
|
static Scheme_Object *optimize_application2(Scheme_Object *o, Optimize_Info *info, int context)
|
||||||
|
@ -2858,54 +2897,51 @@ static Scheme_Object *optimize_application2(Scheme_Object *o, Optimize_Info *inf
|
||||||
|
|
||||||
static Scheme_Object *finish_optimize_application2(Scheme_App2_Rec *app, Optimize_Info *info, int context, int rator_flags)
|
static Scheme_Object *finish_optimize_application2(Scheme_App2_Rec *app, Optimize_Info *info, int context, int rator_flags)
|
||||||
{
|
{
|
||||||
Scheme_Object *le;
|
|
||||||
int flags;
|
int flags;
|
||||||
|
Scheme_Object *rand, *inside = NULL, *alt;
|
||||||
|
int id_offset = 0;
|
||||||
|
|
||||||
info->size += 1;
|
info->size += 1;
|
||||||
|
|
||||||
|
/* Path for direct constant folding */
|
||||||
if (SCHEME_TYPE(app->rand) > _scheme_compiled_values_types_) {
|
if (SCHEME_TYPE(app->rand) > _scheme_compiled_values_types_) {
|
||||||
le = try_optimize_fold(app->rator, (Scheme_Object *)app, info);
|
Scheme_Object *le;
|
||||||
|
le = try_optimize_fold(app->rator, NULL, (Scheme_Object *)app, info);
|
||||||
if (le)
|
if (le)
|
||||||
return le;
|
return le;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SAME_OBJ(scheme_procedure_p_proc, app->rator)) {
|
rand = app->rand;
|
||||||
if (lookup_constant_proc(info, app->rand)) {
|
|
||||||
info->preserves_marks = 1;
|
|
||||||
info->single_result = 1;
|
|
||||||
return scheme_true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SAME_OBJ(scheme_varref_const_p_proc, app->rator)) {
|
/* We can go inside a `begin' and a `let', which is useful in case
|
||||||
if (SAME_TYPE(SCHEME_TYPE(app->rand), scheme_varref_form_type)) {
|
the argument was a function call that has been inlined. */
|
||||||
Scheme_Object *var = SCHEME_PTR1_VAL(app->rand);
|
while (1) {
|
||||||
if (SAME_OBJ(var, scheme_true)) {
|
if (SAME_TYPE(SCHEME_TYPE(rand), scheme_compiled_let_void_type)) {
|
||||||
return scheme_true;
|
Scheme_Let_Header *head = (Scheme_Let_Header *)rand;
|
||||||
} else if (SAME_OBJ(var, scheme_false)) {
|
int i;
|
||||||
return scheme_false;
|
id_offset += head->count;
|
||||||
} else if (scheme_compiled_propagate_ok(var, info)) {
|
inside = rand;
|
||||||
/* can propagate => is a constant */
|
rand = head->body;
|
||||||
return scheme_true;
|
for (i = head->num_clauses; i--; ) {
|
||||||
|
inside = rand;
|
||||||
|
rand = ((Scheme_Compiled_Let_Value *)rand)->body;
|
||||||
}
|
}
|
||||||
}
|
} else if (SAME_TYPE(SCHEME_TYPE(rand), scheme_sequence_type)) {
|
||||||
|
Scheme_Sequence *seq = (Scheme_Sequence *)rand;
|
||||||
|
if (seq->count) {
|
||||||
|
inside = rand;
|
||||||
|
rand = seq->array[seq->count-1];
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
} else
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SAME_OBJ(scheme_struct_type_p_proc, app->rator)) {
|
if (SCHEME_TYPE(rand) > _scheme_compiled_values_types_) {
|
||||||
Scheme_Object *c;
|
Scheme_Object *le;
|
||||||
c = get_struct_proc_shape(app->rand, info);
|
le = try_optimize_fold(app->rator, scheme_make_pair(rand, scheme_null), NULL, info);
|
||||||
if (c && ((SCHEME_PROC_SHAPE_MODE(c) & STRUCT_PROC_SHAPE_MASK)
|
if (le)
|
||||||
== STRUCT_PROC_SHAPE_STRUCT))
|
return replace_tail_inside(le, inside, app->rand);
|
||||||
return scheme_true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((SAME_OBJ(scheme_values_func, app->rator)
|
|
||||||
|| SAME_OBJ(scheme_list_star_proc, app->rator))
|
|
||||||
&& (scheme_omittable_expr(app->rand, 1, -1, 0, info, info, 0, 0, ID_OMIT)
|
|
||||||
|| single_valued_noncm_expression(app->rand, 5))) {
|
|
||||||
info->preserves_marks = 1;
|
|
||||||
info->single_result = 1;
|
|
||||||
return app->rand;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_nonmutating_primitive(app->rator, 1))
|
if (!is_nonmutating_primitive(app->rator, 1))
|
||||||
|
@ -2920,144 +2956,182 @@ static Scheme_Object *finish_optimize_application2(Scheme_App2_Rec *app, Optimiz
|
||||||
info->single_result = -info->single_result;
|
info->single_result = -info->single_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for things like (flonum? x) on an `x' known to have a flonum value. */
|
if ((SAME_OBJ(scheme_values_func, app->rator)
|
||||||
if (SCHEME_PRIMP(app->rator)
|
|| SAME_OBJ(scheme_list_star_proc, app->rator))
|
||||||
&& (SCHEME_PRIM_PROC_OPT_FLAGS(app->rator) & SCHEME_PRIM_IS_UNARY_INLINED)
|
&& ((context & OPT_CONTEXT_SINGLED)
|
||||||
&& SAME_TYPE(SCHEME_TYPE(app->rand), scheme_local_type)) {
|
|| scheme_omittable_expr(rand, 1, -1, 0, info, info, 0, id_offset, ID_OMIT)
|
||||||
int pos = SCHEME_LOCAL_POS(app->rand);
|
|| single_valued_noncm_expression(rand, 5))) {
|
||||||
|
info->preserves_marks = 1;
|
||||||
if (!optimize_is_mutated(info, pos)) {
|
info->single_result = 1;
|
||||||
int t;
|
return replace_tail_inside(rand, inside, app->rand);
|
||||||
t = optimize_is_local_type_valued(info, pos);
|
|
||||||
|
|
||||||
if (t == SCHEME_LOCAL_TYPE_FLONUM) {
|
|
||||||
if (IS_NAMED_PRIM(app->rator, "flonum?"))
|
|
||||||
return scheme_true;
|
|
||||||
} else if (t == SCHEME_LOCAL_TYPE_FIXNUM) {
|
|
||||||
if (IS_NAMED_PRIM(app->rator, "fixnum?"))
|
|
||||||
return scheme_true;
|
|
||||||
} else if (t == SCHEME_LOCAL_TYPE_EXTFLONUM) {
|
|
||||||
if (IS_NAMED_PRIM(app->rator, "extflonum?"))
|
|
||||||
return scheme_true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for things like (cXr (cons X Y)): */
|
/* Check for things like (cXr (cons X Y)): */
|
||||||
if (SCHEME_PRIMP(app->rator)
|
if (SCHEME_PRIMP(app->rator)
|
||||||
&& (SCHEME_PRIM_PROC_OPT_FLAGS(app->rator) & SCHEME_PRIM_IS_UNARY_INLINED)) {
|
&& (SCHEME_PRIM_PROC_OPT_FLAGS(app->rator) & SCHEME_PRIM_IS_UNARY_INLINED)) {
|
||||||
Scheme_Object *rand, *inside = NULL, *alt = NULL;
|
|
||||||
|
|
||||||
rand = app->rand;
|
switch (SCHEME_TYPE(rand)) {
|
||||||
|
case scheme_application2_type:
|
||||||
/* We can go inside a `let', which is useful in case the argument
|
{
|
||||||
was a function call that has been inlined. */
|
Scheme_App2_Rec *app2 = (Scheme_App2_Rec *)rand;
|
||||||
while (SAME_TYPE(SCHEME_TYPE(rand), scheme_compiled_let_void_type)) {
|
if (SAME_OBJ(scheme_list_proc, app2->rator)) {
|
||||||
Scheme_Let_Header *head = (Scheme_Let_Header *)rand;
|
if (IS_NAMED_PRIM(app->rator, "car")) {
|
||||||
int i;
|
/* (car (list X)) */
|
||||||
inside = rand;
|
alt = make_discarding_sequence(scheme_void, app2->rand, info, id_offset);
|
||||||
rand = head->body;
|
return replace_tail_inside(alt, inside, app->rand);
|
||||||
for (i = head->num_clauses; i--; ) {
|
} else if (IS_NAMED_PRIM(app->rator, "cdr")) {
|
||||||
inside = rand;
|
/* (cdr (list X)) */
|
||||||
rand = ((Scheme_Compiled_Let_Value *)rand)->body;
|
alt = make_discarding_sequence(app2->rand, scheme_null, info, id_offset);
|
||||||
|
return replace_tail_inside(alt, inside, app->rand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
alt = try_reduce_predicate(app->rator, app2->rator, 1, app2, NULL, NULL, info, id_offset);
|
||||||
|
if (alt)
|
||||||
|
return replace_tail_inside(alt, inside, app->rand);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
case scheme_application3_type:
|
||||||
|
{
|
||||||
if (SAME_TYPE(SCHEME_TYPE(rand), scheme_application2_type)) {
|
Scheme_App3_Rec *app3 = (Scheme_App3_Rec *)rand;
|
||||||
Scheme_App2_Rec *app2 = (Scheme_App2_Rec *)rand;
|
|
||||||
if (SAME_OBJ(scheme_list_proc, app2->rator)) {
|
|
||||||
if (IS_NAMED_PRIM(app->rator, "car")) {
|
if (IS_NAMED_PRIM(app->rator, "car")) {
|
||||||
/* (car (list X)) */
|
if (SAME_OBJ(scheme_cons_proc, app3->rator)
|
||||||
alt = make_discarding_sequence(scheme_void, app2->rand, info);
|
|| SAME_OBJ(scheme_unsafe_cons_list_proc, app3->rator)
|
||||||
|
|| SAME_OBJ(scheme_list_proc, app3->rator)
|
||||||
|
|| SAME_OBJ(scheme_list_star_proc, app3->rator)) {
|
||||||
|
/* (car ({cons|list|list*} X Y)) */
|
||||||
|
alt = make_discarding_reverse_sequence(app3->rand2, app3->rand1, info, id_offset);
|
||||||
|
return replace_tail_inside(alt, inside, app->rand);
|
||||||
|
}
|
||||||
} else if (IS_NAMED_PRIM(app->rator, "cdr")) {
|
} else if (IS_NAMED_PRIM(app->rator, "cdr")) {
|
||||||
/* (cdr (list X)) */
|
if (SAME_OBJ(scheme_cons_proc, app3->rator)
|
||||||
alt = make_discarding_sequence(app2->rand, scheme_null, info);
|
|| SAME_OBJ(scheme_unsafe_cons_list_proc, app3->rator)
|
||||||
}
|
|| SAME_OBJ(scheme_list_star_proc, app3->rator)) {
|
||||||
}
|
/* (cdr ({cons|list*} X Y)) */
|
||||||
if (!alt)
|
alt = make_discarding_sequence(app3->rand1, app3->rand2, info, id_offset);
|
||||||
alt = try_reduce_predicate(app->rator, app2->rator, 1, app2, NULL, NULL, info);
|
return replace_tail_inside(alt, inside, app->rand);
|
||||||
} else if (SAME_TYPE(SCHEME_TYPE(rand), scheme_application3_type)) {
|
} else if (SAME_OBJ(scheme_list_proc, app3->rator)) {
|
||||||
Scheme_App3_Rec *app3 = (Scheme_App3_Rec *)rand;
|
/* (cdr (list X Y)) */
|
||||||
if (IS_NAMED_PRIM(app->rator, "car")) {
|
|
||||||
if (SAME_OBJ(scheme_cons_proc, app3->rator)
|
|
||||||
|| SAME_OBJ(scheme_unsafe_cons_list_proc, app3->rator)
|
|
||||||
|| SAME_OBJ(scheme_list_proc, app3->rator)
|
|
||||||
|| SAME_OBJ(scheme_list_star_proc, app3->rator)) {
|
|
||||||
/* (car ({cons|list|list*} X Y)) */
|
|
||||||
alt = make_discarding_reverse_sequence(app3->rand2, app3->rand1, info);
|
|
||||||
}
|
|
||||||
} else if (IS_NAMED_PRIM(app->rator, "cdr")) {
|
|
||||||
/* (cdr ({cons|list|list*} X Y)) */
|
|
||||||
if (SAME_OBJ(scheme_cons_proc, app3->rator)
|
|
||||||
|| SAME_OBJ(scheme_unsafe_cons_list_proc, app3->rator)
|
|
||||||
|| SAME_OBJ(scheme_list_proc, app3->rator)
|
|
||||||
|| SAME_OBJ(scheme_list_star_proc, app3->rator)) {
|
|
||||||
if (SAME_OBJ(scheme_list_proc, app3->rator)) {
|
|
||||||
alt = scheme_make_application(scheme_make_pair(scheme_list_proc,
|
alt = scheme_make_application(scheme_make_pair(scheme_list_proc,
|
||||||
scheme_make_pair(app3->rand2,
|
scheme_make_pair(app3->rand2,
|
||||||
scheme_null)),
|
scheme_null)),
|
||||||
info);
|
info);
|
||||||
SCHEME_APPN_FLAGS(((Scheme_App_Rec *)alt)) |= (APPN_FLAG_IMMED | APPN_FLAG_SFS_TAIL);
|
SCHEME_APPN_FLAGS(((Scheme_App_Rec *)alt)) |= (APPN_FLAG_IMMED | APPN_FLAG_SFS_TAIL);
|
||||||
alt = make_discarding_sequence(app3->rand1, alt, info);
|
alt = make_discarding_sequence(app3->rand1, alt, info, id_offset);
|
||||||
} else
|
return replace_tail_inside(alt, inside, app->rand);
|
||||||
alt = make_discarding_sequence(app3->rand1, app3->rand2, info);
|
}
|
||||||
}
|
} else if (IS_NAMED_PRIM(app->rator, "cadr")) {
|
||||||
} else if (IS_NAMED_PRIM(app->rator, "cadr")) {
|
if (SAME_OBJ(scheme_list_proc, app3->rator)) {
|
||||||
if (SAME_OBJ(scheme_list_proc, app3->rator)) {
|
/* (cadr (list X Y)) */
|
||||||
/* (cadr (list X Y)) */
|
alt = make_discarding_sequence(app3->rand1, app3->rand2, info, id_offset);
|
||||||
alt = make_discarding_sequence(app3->rand1, app3->rand2, info);
|
return replace_tail_inside(alt, inside, app->rand);
|
||||||
}
|
|
||||||
} else
|
|
||||||
alt = try_reduce_predicate(app->rator, app3->rator, 2, NULL, app3, NULL, info);
|
|
||||||
} else if (SAME_TYPE(SCHEME_TYPE(rand), scheme_application_type)) {
|
|
||||||
Scheme_App_Rec *appr = (Scheme_App_Rec *)rand;
|
|
||||||
Scheme_Object *r = appr->args[0];
|
|
||||||
if (IS_NAMED_PRIM(app->rator, "car")) {
|
|
||||||
if ((appr->args > 0)
|
|
||||||
&& (SAME_OBJ(scheme_list_proc, r)
|
|
||||||
|| SAME_OBJ(scheme_list_star_proc, r))) {
|
|
||||||
/* (car ({list|list*} X Y ...)) */
|
|
||||||
alt = make_discarding_app_sequence(appr, 0, NULL, info);
|
|
||||||
}
|
|
||||||
} else if (IS_NAMED_PRIM(app->rator, "cdr")) {
|
|
||||||
/* (cdr ({list|list*} X Y ...)) */
|
|
||||||
if ((appr->args > 0)
|
|
||||||
&& (SAME_OBJ(scheme_list_proc, r)
|
|
||||||
|| SAME_OBJ(scheme_list_star_proc, r))) {
|
|
||||||
Scheme_Object *al = scheme_null;
|
|
||||||
int k;
|
|
||||||
for (k = appr->num_args; k > 1; k--) {
|
|
||||||
al = scheme_make_pair(appr->args[k], al);
|
|
||||||
}
|
}
|
||||||
al = scheme_make_pair(r, al);
|
|
||||||
alt = scheme_make_application(al, info);
|
|
||||||
SCHEME_APPN_FLAGS(((Scheme_App_Rec *)alt)) |= (APPN_FLAG_IMMED | APPN_FLAG_SFS_TAIL);
|
|
||||||
alt = make_discarding_sequence(appr->args[1], alt, info);
|
|
||||||
}
|
}
|
||||||
} else
|
alt = try_reduce_predicate(app->rator, app3->rator, 2, NULL, app3, NULL, info, id_offset);
|
||||||
alt = try_reduce_predicate(app->rator, appr->args[0], appr->num_args, NULL, NULL, appr, info);
|
if (alt)
|
||||||
} else {
|
return replace_tail_inside(alt, inside, app->rand);
|
||||||
alt = check_known2_pred(info, app);
|
break;
|
||||||
if (!alt) {
|
}
|
||||||
check_known2(info, app, "car", scheme_pair_p_proc, scheme_unsafe_car_proc);
|
case scheme_application_type:
|
||||||
check_known2(info, app, "cdr", scheme_pair_p_proc, scheme_unsafe_cdr_proc);
|
{
|
||||||
check_known2(info, app, "mcar", scheme_mpair_p_proc, scheme_unsafe_mcar_proc);
|
Scheme_App_Rec *appr = (Scheme_App_Rec *)rand;
|
||||||
check_known2(info, app, "mcdr", scheme_mpair_p_proc, scheme_unsafe_mcdr_proc);
|
Scheme_Object *r = appr->args[0];
|
||||||
/* It's not clear that these are useful, since a chaperone check is needed anyway: */
|
if (IS_NAMED_PRIM(app->rator, "car")) {
|
||||||
check_known2(info, app, "unbox", scheme_box_p_proc, scheme_unsafe_unbox_proc);
|
if ((appr->args > 0)
|
||||||
check_known2(info, app, "vector-length", scheme_vector_p_proc, scheme_unsafe_vector_length_proc);
|
&& (SAME_OBJ(scheme_list_proc, r)
|
||||||
|
|| SAME_OBJ(scheme_list_star_proc, r))) {
|
||||||
|
/* (car ({list|list*} X Y ...)) */
|
||||||
|
alt = make_discarding_app_sequence(appr, 0, NULL, info, id_offset);
|
||||||
|
return replace_tail_inside(alt, inside, app->rand);
|
||||||
|
}
|
||||||
|
} else if (IS_NAMED_PRIM(app->rator, "cdr")) {
|
||||||
|
/* (cdr ({list|list*} X Y ...)) */
|
||||||
|
if ((appr->args > 0)
|
||||||
|
&& (SAME_OBJ(scheme_list_proc, r)
|
||||||
|
|| SAME_OBJ(scheme_list_star_proc, r))) {
|
||||||
|
Scheme_Object *al = scheme_null;
|
||||||
|
int k;
|
||||||
|
for (k = appr->num_args; k > 1; k--) {
|
||||||
|
al = scheme_make_pair(appr->args[k], al);
|
||||||
|
}
|
||||||
|
al = scheme_make_pair(r, al);
|
||||||
|
alt = scheme_make_application(al, info);
|
||||||
|
SCHEME_APPN_FLAGS(((Scheme_App_Rec *)alt)) |= (APPN_FLAG_IMMED | APPN_FLAG_SFS_TAIL);
|
||||||
|
alt = make_discarding_sequence(appr->args[1], alt, info, id_offset);
|
||||||
|
return replace_tail_inside(alt, inside, app->rand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
alt = try_reduce_predicate(app->rator, appr->args[0], appr->num_args, NULL, NULL, appr, info, id_offset);
|
||||||
|
if (alt)
|
||||||
|
return replace_tail_inside(alt, inside, app->rand);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
if (SAME_TYPE(SCHEME_TYPE(rand), scheme_local_type)
|
||||||
|
&& (SCHEME_LOCAL_POS(rand) >= id_offset)) {
|
||||||
|
int pos = SCHEME_LOCAL_POS(rand) - id_offset;
|
||||||
|
|
||||||
|
if (!optimize_is_mutated(info, pos)) {
|
||||||
|
int t;
|
||||||
|
t = optimize_is_local_type_valued(info, pos);
|
||||||
|
if ((t == SCHEME_LOCAL_TYPE_FLONUM && IS_NAMED_PRIM(app->rator, "flonum?"))
|
||||||
|
||(t == SCHEME_LOCAL_TYPE_FIXNUM && IS_NAMED_PRIM(app->rator, "fixnum?"))
|
||||||
|
||(t == SCHEME_LOCAL_TYPE_EXTFLONUM && IS_NAMED_PRIM(app->rator, "extflonum?"))) {
|
||||||
|
return replace_tail_inside(scheme_true, inside, app->rand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SAME_OBJ(scheme_procedure_p_proc, app->rator)) {
|
||||||
|
if (lookup_constant_proc(info, rand, id_offset)) {
|
||||||
|
info->preserves_marks = 1;
|
||||||
|
info->single_result = 1;
|
||||||
|
return replace_tail_inside(scheme_true, inside, app->rand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
alt = check_known2_pred(info, app, rand, id_offset);
|
||||||
|
if (alt)
|
||||||
|
return replace_tail_inside(alt, inside, app->rand);
|
||||||
|
|
||||||
|
check_known2(info, app, rand, id_offset, "car", scheme_pair_p_proc, scheme_unsafe_car_proc);
|
||||||
|
check_known2(info, app, rand, id_offset, "cdr", scheme_pair_p_proc, scheme_unsafe_cdr_proc);
|
||||||
|
check_known2(info, app, rand, id_offset, "mcar", scheme_mpair_p_proc, scheme_unsafe_mcar_proc);
|
||||||
|
check_known2(info, app, rand, id_offset, "mcdr", scheme_mpair_p_proc, scheme_unsafe_mcdr_proc);
|
||||||
|
/* It's not clear that these are useful, since a chaperone check is needed anyway: */
|
||||||
|
check_known2(info, app, rand, id_offset, "unbox", scheme_box_p_proc, scheme_unsafe_unbox_proc);
|
||||||
|
check_known2(info, app, rand, id_offset, "vector-length", scheme_vector_p_proc, scheme_unsafe_vector_length_proc);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (SAME_OBJ(scheme_struct_type_p_proc, app->rator)) {
|
||||||
|
Scheme_Object *c;
|
||||||
|
c = get_struct_proc_shape(rand, info);
|
||||||
|
if (c && ((SCHEME_PROC_SHAPE_MODE(c) & STRUCT_PROC_SHAPE_MASK)
|
||||||
|
== STRUCT_PROC_SHAPE_STRUCT)) {
|
||||||
|
info->preserves_marks = 1;
|
||||||
|
info->single_result = 1;
|
||||||
|
return replace_tail_inside(scheme_true, inside, app->rand);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (alt) {
|
if (SAME_OBJ(scheme_varref_const_p_proc, app->rator)
|
||||||
if (inside) {
|
&& SAME_TYPE(SCHEME_TYPE(rand), scheme_varref_form_type)) {
|
||||||
if (SAME_TYPE(SCHEME_TYPE(inside), scheme_compiled_let_void_type))
|
Scheme_Object *var = SCHEME_PTR1_VAL(rand);
|
||||||
((Scheme_Let_Header *)inside)->body = alt;
|
if (SAME_OBJ(var, scheme_true)) {
|
||||||
else
|
info->preserves_marks = 1;
|
||||||
((Scheme_Compiled_Let_Value *)inside)->body = alt;
|
info->single_result = 1;
|
||||||
return app->rand;
|
return replace_tail_inside(scheme_true, inside, app->rand);
|
||||||
|
} else if (SAME_OBJ(var, scheme_false)) {
|
||||||
|
info->preserves_marks = 1;
|
||||||
|
info->single_result = 1;
|
||||||
|
return replace_tail_inside(scheme_false, inside, app->rand);
|
||||||
|
} else {
|
||||||
|
if (var && scheme_compiled_propagate_ok(var, info)) {
|
||||||
|
/* can propagate => is a constant */
|
||||||
|
info->preserves_marks = 1;
|
||||||
|
info->single_result = 1;
|
||||||
|
return replace_tail_inside(scheme_true, inside, app->rand);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return alt;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3154,6 +3228,7 @@ static Scheme_Object *finish_optimize_application3(Scheme_App3_Rec *app, Optimiz
|
||||||
{
|
{
|
||||||
Scheme_Object *le;
|
Scheme_Object *le;
|
||||||
int all_vals = 1;
|
int all_vals = 1;
|
||||||
|
int id_offset = 0;
|
||||||
|
|
||||||
info->size += 1;
|
info->size += 1;
|
||||||
|
|
||||||
|
@ -3164,7 +3239,7 @@ static Scheme_Object *finish_optimize_application3(Scheme_App3_Rec *app, Optimiz
|
||||||
|
|
||||||
|
|
||||||
if (all_vals) {
|
if (all_vals) {
|
||||||
le = try_optimize_fold(app->rator, (Scheme_Object *)app, info);
|
le = try_optimize_fold(app->rator, NULL, (Scheme_Object *)app, info);
|
||||||
if (le)
|
if (le)
|
||||||
return le;
|
return le;
|
||||||
}
|
}
|
||||||
|
@ -3198,7 +3273,7 @@ static Scheme_Object *finish_optimize_application3(Scheme_App3_Rec *app, Optimiz
|
||||||
Scheme_Case_Lambda *cl;
|
Scheme_Case_Lambda *cl;
|
||||||
int i, cnt;
|
int i, cnt;
|
||||||
|
|
||||||
proc = lookup_constant_proc(info, app->rand1);
|
proc = lookup_constant_proc(info, app->rand1, 0);
|
||||||
if (proc) {
|
if (proc) {
|
||||||
if (SAME_TYPE(SCHEME_TYPE(proc), scheme_compiled_unclosed_procedure_type)) {
|
if (SAME_TYPE(SCHEME_TYPE(proc), scheme_compiled_unclosed_procedure_type)) {
|
||||||
cnt = 1;
|
cnt = 1;
|
||||||
|
@ -3265,9 +3340,9 @@ static Scheme_Object *finish_optimize_application3(Scheme_App3_Rec *app, Optimiz
|
||||||
if (z1 && z2)
|
if (z1 && z2)
|
||||||
return scheme_make_integer(0);
|
return scheme_make_integer(0);
|
||||||
else if (z2)
|
else if (z2)
|
||||||
return make_discarding_sequence(app->rand1, scheme_make_integer(0), info);
|
return make_discarding_sequence(app->rand1, scheme_make_integer(0), info, id_offset);
|
||||||
else
|
else
|
||||||
return make_discarding_sequence(app->rand2, scheme_make_integer(0), info);
|
return make_discarding_sequence(app->rand2, scheme_make_integer(0), info, id_offset);
|
||||||
}
|
}
|
||||||
if (SAME_OBJ(app->rand1, scheme_make_integer(1)))
|
if (SAME_OBJ(app->rand1, scheme_make_integer(1)))
|
||||||
return app->rand2;
|
return app->rand2;
|
||||||
|
@ -3275,15 +3350,15 @@ static Scheme_Object *finish_optimize_application3(Scheme_App3_Rec *app, Optimiz
|
||||||
return app->rand1;
|
return app->rand1;
|
||||||
} else if (IS_NAMED_PRIM(app->rator, "unsafe-fxquotient")) {
|
} else if (IS_NAMED_PRIM(app->rator, "unsafe-fxquotient")) {
|
||||||
if (z1)
|
if (z1)
|
||||||
return make_discarding_sequence(app->rand2, scheme_make_integer(0), info);
|
return make_discarding_sequence(app->rand2, scheme_make_integer(0), info, id_offset);
|
||||||
if (SAME_OBJ(app->rand2, scheme_make_integer(1)))
|
if (SAME_OBJ(app->rand2, scheme_make_integer(1)))
|
||||||
return app->rand1;
|
return app->rand1;
|
||||||
} else if (IS_NAMED_PRIM(app->rator, "unsafe-fxremainder")
|
} else if (IS_NAMED_PRIM(app->rator, "unsafe-fxremainder")
|
||||||
|| IS_NAMED_PRIM(app->rator, "unsafe-fxmodulo")) {
|
|| IS_NAMED_PRIM(app->rator, "unsafe-fxmodulo")) {
|
||||||
if (z1)
|
if (z1)
|
||||||
return make_discarding_sequence(app->rand2, scheme_make_integer(0), info);
|
return make_discarding_sequence(app->rand2, scheme_make_integer(0), info, id_offset);
|
||||||
if (SAME_OBJ(app->rand2, scheme_make_integer(1)))
|
if (SAME_OBJ(app->rand2, scheme_make_integer(1)))
|
||||||
return make_discarding_sequence(app->rand1, scheme_make_integer(0), info);
|
return make_discarding_sequence(app->rand1, scheme_make_integer(0), info, id_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
z1 = (SCHEME_FLOATP(app->rand1) && (SCHEME_FLOAT_VAL(app->rand1) == 0.0));
|
z1 = (SCHEME_FLOATP(app->rand1) && (SCHEME_FLOAT_VAL(app->rand1) == 0.0));
|
||||||
|
@ -3474,7 +3549,7 @@ static Scheme_Object *optimize_sequence(Scheme_Object *o, Optimize_Info *info, i
|
||||||
|
|
||||||
/* Inlining and constant propagation can expose omittable expressions. */
|
/* Inlining and constant propagation can expose omittable expressions. */
|
||||||
if (i + 1 != count)
|
if (i + 1 != count)
|
||||||
le = optimize_ignored(le, info, -1, 1, 5);
|
le = optimize_ignored(le, info, 0, -1, 1, 5);
|
||||||
|
|
||||||
if (!le) {
|
if (!le) {
|
||||||
drop++;
|
drop++;
|
||||||
|
@ -3675,7 +3750,7 @@ static Scheme_Object *optimize_branch(Scheme_Object *o, Optimize_Info *info, int
|
||||||
|
|
||||||
if (expr_implies_predicate(t, info, 0, 5)) {
|
if (expr_implies_predicate(t, info, 0, 5)) {
|
||||||
/* all predicates recognize non-#f things */
|
/* all predicates recognize non-#f things */
|
||||||
t = make_discarding_sequence(t, scheme_true, info);
|
t = make_discarding_sequence(t, scheme_true, info, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Try to lift out `let`s and `begin`s around a test: */
|
/* Try to lift out `let`s and `begin`s around a test: */
|
||||||
|
@ -3799,7 +3874,7 @@ static Scheme_Object *optimize_branch(Scheme_Object *o, Optimize_Info *info, int
|
||||||
/* Try optimize: (if <omitable-expr> v v) => v */
|
/* Try optimize: (if <omitable-expr> v v) => v */
|
||||||
if (equivalent_exprs(tb, fb)) {
|
if (equivalent_exprs(tb, fb)) {
|
||||||
info->size -= 1; /* could be more precise */
|
info->size -= 1; /* could be more precise */
|
||||||
return make_discarding_first_sequence(t, tb, info);
|
return make_discarding_first_sequence(t, tb, info, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert: (if (if M N #f) M2 K) => (if M (if N M2 K) K)
|
/* Convert: (if (if M N #f) M2 K) => (if M (if N M2 K) K)
|
||||||
|
@ -3875,7 +3950,7 @@ static Scheme_Object *optimize_wcm(Scheme_Object *o, Optimize_Info *info, int co
|
||||||
|
|
||||||
if (omittable_key(k, info)
|
if (omittable_key(k, info)
|
||||||
&& scheme_omittable_expr(b, -1, 20, 0, info, info, 0, 0, ID_OMIT))
|
&& scheme_omittable_expr(b, -1, 20, 0, info, info, 0, 0, ID_OMIT))
|
||||||
return make_discarding_first_sequence(v, b, info);
|
return make_discarding_first_sequence(v, b, info, 0);
|
||||||
|
|
||||||
/* info->single_result is already set */
|
/* info->single_result is already set */
|
||||||
info->preserves_marks = 0;
|
info->preserves_marks = 0;
|
||||||
|
@ -4224,7 +4299,7 @@ begin0_optimize(Scheme_Object *obj, Optimize_Info *info, int context)
|
||||||
|
|
||||||
/* Inlining and constant propagation can expose omittable expressions: */
|
/* Inlining and constant propagation can expose omittable expressions: */
|
||||||
if (i)
|
if (i)
|
||||||
le = optimize_ignored(le, info, -1, 1, 5);
|
le = optimize_ignored(le, info, 0, -1, 1, 5);
|
||||||
|
|
||||||
if (!le) {
|
if (!le) {
|
||||||
drop++;
|
drop++;
|
||||||
|
|
|
@ -3150,6 +3150,7 @@ int scheme_get_eval_type(Scheme_Object *obj);
|
||||||
|
|
||||||
Scheme_Object *scheme_make_application(Scheme_Object *v, Optimize_Info *info);
|
Scheme_Object *scheme_make_application(Scheme_Object *v, Optimize_Info *info);
|
||||||
Scheme_Object *scheme_try_apply(Scheme_Object *f, Scheme_Object *args, Optimize_Info *info);
|
Scheme_Object *scheme_try_apply(Scheme_Object *f, Scheme_Object *args, Optimize_Info *info);
|
||||||
|
int scheme_is_foldable_prim(Scheme_Object *f);
|
||||||
|
|
||||||
Scheme_Object *scheme_get_stop_expander(void);
|
Scheme_Object *scheme_get_stop_expander(void);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user