scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

commit 1a31d8e1d051c04df16ab22f03f4a9354c15c05b
parent a0d19a4ca73c1c2c54f9e053f6ac9983098dfbfb
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Sat,  4 Jan 2025 15:44:57 +0100

cc2: Optimize branch over jump

A branch over jump can be optimized inverting the condition of
the branch, removing the jump and branching directly to the target
of the jump. Transforming

(0)             M4[2](0,12)     M4[3](0,12)     =4(1,0) y -> L8(0,0)
(0)     L9:     j -> L6(1,0)
(0)     L8:     q0(1,0)
(0)             M4[2](0,12)     M4[4](0,12)     !4(1,0) y -> L7(0,0)
(0)     L10:    j -> L6(1,0)
(0)     L7:     #4(0,20)        h0(1,0)

into

(0)>            M4[2](0,12)     M4[3](0,12)     !4(1,0) y -> L6(0,0)
>(0)>           M4[2](0,12)     M4[4](0,12)     =4(1,0) y -> L6(0,0)
>(0)>   L7:     #4(0,20)        h0(1,0)

Diffstat:
Msrc/cmd/scc-cc/cc2/cfg.c | 32++++++++++++++++++++++++++++++--
1 file changed, 30 insertions(+), 2 deletions(-)

diff --git a/src/cmd/scc-cc/cc2/cfg.c b/src/cmd/scc-cc/cc2/cfg.c @@ -279,22 +279,50 @@ optlabels(Node *np) return np; } +static int +negop(int op) +{ + switch (op) { + case OEQ: return ONE; + case ONE: return OEQ; + case OLT: return OGE; + case OGE: return OLT; + case OLE: return OGT; + case OGT: return OLE; + default: abort(); + } + return op; +} + static Node * optjmps(Node *np) { Symbol *label; - Node *p, *stmt, *last; + Node *p, *stmt, *next; switch (np->op) { case OBRANCH: + branch: label = np->u.sym; stmt = label->u.stmt; + next = np->next; + + /* avoid branch over jump */ + if (next->op == OJMP && next->next->label == label && + (!next->label || next->label->refcnt == 0)) { + Node *left = np->left; + np->u.sym = next->u.sym; + label->refcnt--; + left->op = negop(left->op); + delstmt(next); + goto branch; + } goto chain_jumps; case OJMP: label = np->u.sym; stmt = label->u.stmt; - /* Avoid jump over a set of NOPs */ + /* avoid jump over a set of NOPs */ for (p = np->next; p; p = p->next) { if (p == stmt) { label->refcnt--;