optimizer: reduce ignored ifs

The optimizer tries to reduce the `if` assuming that the result will be used.
In case it later detects that the result will be ignored, it can try to
apply some additional reductions to the branches and to the whole expression.
This commit is contained in:
Gustavo Massaccesi 2016-06-30 00:37:20 -03:00
parent 9a5aa89fb5
commit f8b3ba8253
2 changed files with 39 additions and 0 deletions

View File

@ -1956,6 +1956,26 @@
(test-comp '(lambda (x) (not (if (null? x) #t x))) (test-comp '(lambda (x) (not (if (null? x) #t x)))
'(lambda (x) (not x))) '(lambda (x) (not x)))
;reduce ignored `if`s
(test-comp '(lambda (x) (void (if x 1 2)))
'(lambda (x) (void)))
(test-comp '(lambda (f) (void (if (f) 1 2)))
'(lambda (f) (void (values (f)))))
(test-comp '(lambda () (void (if (eq? (random 2) 0) 1 2)))
'(lambda () (void (random 2))))
(test-comp '(lambda (x) (void (if (eq? (random 2) 0) (box x) (list x))))
'(lambda (x) (void (random 2))))
(test-comp '(lambda (x) (void (if x (random) 1)))
'(lambda (x) (void (if x (random) 2))))
(test-comp '(lambda (x) (void (if x 1 (random))))
'(lambda (x) (void (if x 2 (random)))))
(test-comp '(lambda (x) (void (if x (random) 1)))
'(lambda (x) (void))
#f)
(test-comp '(lambda (x) (void (if x 1 (random))))
'(lambda (x) (void))
#f)
(test-comp '(lambda (x) (let ([n (list 1)]) (test-comp '(lambda (x) (let ([n (list 1)])
(list n n (not (if x #t n))))) (list n n (not (if x #t n)))))
'(lambda (x) (let ([n (list 1)]) '(lambda (x) (let ([n (list 1)])

View File

@ -808,6 +808,25 @@ static Scheme_Object *optimize_ignored(Scheme_Object *e, Optimize_Info *info,
return make_discarding_app_sequence(app, -1, NULL, info); return make_discarding_app_sequence(app, -1, NULL, info);
} }
break; break;
case scheme_branch_type:
{
Scheme_Branch_Rec *b = (Scheme_Branch_Rec *)e;
Scheme_Object *tb, *fb;
tb = optimize_ignored(b->tbranch, info, expected_vals, 1, fuel - 1);
fb = optimize_ignored(b->fbranch, info, expected_vals, 1, fuel - 1);
if (tb || fb) {
b->tbranch = tb ? tb : scheme_false;
b->fbranch = fb ? fb : scheme_false;
return (Scheme_Object*)b;
} else {
Scheme_Object *val;
val = ensure_single_value(b->test);
return optimize_ignored(val, info, 1, maybe_omittable, 5);
}
}
break;
} }
} }