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:
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--;