diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2021-02-05 06:48:23 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2021-02-05 06:48:23 -0800 |
commit | 4cddc02c7c2993ef7f942c200a6ec5408947cddb (patch) | |
tree | 40ca5e4a153c1dce0c4da07ab735e9fe8d13e1d2 | |
parent | 21c8ee30e7fc4d252698e39c99eeacf31dd5847c (diff) | |
download | txr-4cddc02c7c2993ef7f942c200a6ec5408947cddb.tar.gz txr-4cddc02c7c2993ef7f942c200a6ec5408947cddb.tar.bz2 txr-4cddc02c7c2993ef7f942c200a6ec5408947cddb.zip |
compiler: new jump threading optimization case.
This opportunity now exists due to the previous commit which
eliminates discarded register moves.
The idea is to recognize code like
if Txxx label0
jmp label1 ;; jump if Txx is not nil
label1:
if Txxx ... ;; Txxx is not nil
jmp label2 ;; jump taken
and rewrite the jmp in the first block to:
if Txxx label0
jmp label2
The leading if Txx label0 is then susceptible to further
threading via label0, as before.
Before the previous compiler commit, there were dead register
moves between the if and jmp that would be too complicated to
analyze in the peephole.
The motivation is that this pattern occurs in match-case
and lambda-match due to the way the cases update a matched-p
variable which is used to skip subsequent cases:
case0
(unless matched-p
case1) ;; sets matched-p if it matches
(unless matched-p)
case2) ;; sets matched-p if it matches
...
and so on. Those successive matched-p tests now thread; if matched-p
is true, the control flow will short-circuit past the
subsequent tests.
* share/txr/stdlib/optimize.tl (basic-blocks peephole): Add
new case for recognizing aforementioned pattern.
-rw-r--r-- | share/txr/stdlib/optimize.tl | 9 |
1 files changed, 9 insertions, 0 deletions
diff --git a/share/txr/stdlib/optimize.tl b/share/txr/stdlib/optimize.tl index 7a6b9dbb..a8a329de 100644 --- a/share/txr/stdlib/optimize.tl +++ b/share/txr/stdlib/optimize.tl @@ -65,6 +65,15 @@ (jmp @(require @jjlabel (neq jjlabel jlabel))) . @nil) ^((jmp ,jjlabel) ,*rest)) (@jelse insns)))) + (((if @reg @jlabel0) + (jmp @jlabel1) . @rest) + (let ((jinsns [bb.hash jlabel1])) + (if-match (@(op eq jlabel1) + (if @(op eq reg) @nil) + (jmp @jlabel3) . @nil) + jinsns + ^(,(car insns) (jmp ,jlabel3) ,*rest) + insns))) (((if @reg @jlabel) . @rest) (let ((jinsns [bb.hash jlabel])) (match-case jinsns |