/* * Compare two trees; return 1 if equal and 0 if not. */ int treecmp(NODE *p1, NODE *p2) { if (p1->n_op != p2->n_op) return 0; switch (p1->n_op) { case SCONV: case UMUL: return treecmp(p1->n_left, p2->n_left); case OREG: if (getlval(p1) != getlval(p2) || p1->n_rval != p2->n_rval) return 0; break; case NAME: case ICON: if (strcmp(p1->n_name, p2->n_name)) return 0; /* FALLTHROUGH */ if (getlval(p1) != getlval(p2)) return 0; break; case TEMP: #ifdef notyet /* SSA will put assignment in separate register */ /* Help out by accepting different regs here */ if (xssa) break; #endif case REG: if (p1->n_rval != p2->n_rval) return 0; break; case LS: case RS: case PLUS: case MINUS: case MUL: case DIV: if (treecmp(p1->n_left, p2->n_left) == 0 || treecmp(p1->n_right, p2->n_right) == 0) return 0; break; default: return 0; } return 1; }
static int inctree(NODE *p) { if (p->n_op == MINUS && p->n_left->n_op == ASSIGN && p->n_left->n_right->n_op == PLUS && treecmp(p->n_left->n_left, p->n_left->n_right->n_left) && p->n_right->n_op == ICON && p->n_right->n_lval == 1 && p->n_left->n_right->n_right->n_op == ICON && p->n_left->n_right->n_right->n_lval == 1) { /* post-increment by 1; (r0)+ */ if (isreg(p->n_left->n_left)) /* Ignore if index not in reg */ return 1; } return 0; }
long treestack_push(Dataptr matrix, Treestack *sp, const Branch *const barray, const long root) { long i; /* loop counter */ Branch *stacktree = NULL; /* current tree on stack */ long stackroot; /* root of current tree */ /* return before push if not a new topology */ /* check backwards as similar trees may be discovered together */ for (i = sp->next - 1; i >= 0; i--) { stacktree = sp->stack[i].tree; stackroot = sp->stack[i].root; if (treecmp(matrix, stacktree, stackroot, barray, root) == 0) return 0; } /* topology is new so must be pushed */ dopush(matrix, sp, barray, root); return 1; } /* end treestack_push() */
/* * Try to find constructs like "a = a + 1;" and match them together * with instructions like "incl a" or "addl $1,a". * * Level assignment for priority: * left right prio * - - - * direct direct 1 * direct REG 2 * direct OREG 3 * OREG direct 4 * OREG REG 5 * OREG OREG 6 */ int findmops(NODE *p, int cookie) { extern int *qtable[]; struct optab *q; int i, sh, shl, shr, lvl = 10; NODE *l, *r; int *ixp; struct optab *qq = NULL; /* XXX gcc */ int idx = 0, gol = 0, gor = 0; shl = shr = 0; F2DEBUG(("findmops tree: %s\n", prcook(cookie))); F2WALK(p); l = getlr(p, 'L'); r = getlr(p, 'R'); /* See if this is a usable tree to work with */ /* Currently only check for leaves */ if (optype(r->n_op) != BITYPE || treecmp(l, r->n_left) == 0) return FFAIL; F2DEBUG(("findmops is useable\n")); /* We can try to find a match. Use right op */ ixp = qtable[r->n_op]; l = getlr(r, 'L'); r = getlr(r, 'R'); for (i = 0; ixp[i] >= 0; i++) { q = &table[ixp[i]]; F2DEBUG(("findmops: ixp %d\n", ixp[i])); if (!acceptable(q)) /* target-dependent filter */ continue; if (ttype(l->n_type, q->ltype) == 0 || ttype(r->n_type, q->rtype) == 0) continue; /* Types must be correct */ F2DEBUG(("findmops got types\n")); switch (cookie) { case FOREFF: if ((q->visit & FOREFF) == 0) continue; /* Not only for side effects */ break; case FORCC: if ((q->visit & FORCC) == 0) continue; /* Not only for side effects */ break; default: if ((cookie & q->visit) == 0) continue; /* Won't match requested shape */ if (((cookie & INREGS & q->lshape) == 0) || !isreg(l)) continue; /* Bad return register */ break; } F2DEBUG(("findmops cookie\n")); /* * left shape must match left node. */ if ((shl = tshape(l, q->lshape)) != SRDIR && (shl != SROREG)) continue; F2DEBUG(("findmops lshape %s\n", srtyp[shl])); F2WALK(l); if ((shr = chcheck(r, q->rshape, 0)) == SRNOPE) continue; F2DEBUG(("findmops rshape %s\n", srtyp[shr])); /* * Only allow RLEFT. XXX */ if ((q->rewrite & (RLEFT|RRIGHT)) != RLEFT) continue; F2DEBUG(("rewrite OK\n")); F2WALK(r); if (q->needs & REWRITE) break; /* Done here */ if (lvl <= (shl + shr)) continue; lvl = shl + shr; qq = q; idx = ixp[i]; gol = shl; gor = shr; } if (lvl == 10) return FFAIL; F2DEBUG(("findmops entry %d(%s,%s)\n", idx, srtyp[gol], srtyp[gor])); /* * Now we're here and have a match. left is semi-direct and * right may be anything. */ sh = -1; sh = shswitch(sh, p->n_left, qq->lshape, cookie, qq->rewrite & RLEFT, gol); sh = shswitch(sh, r, qq->rshape, cookie, 0, gor); if (sh == -1) { if (cookie & (FOREFF|FORCC)) sh = 0; else sh = ffs(cookie & qq->visit & INREGS)-1; } F2DEBUG(("findmops done: node %p class %d\n", p, sh)); /* Trickery: Set table index on assign to op instead */ /* gencode() will remove useless nodes */ p->n_su = MKIDX(idx, 0); p->n_su |= ISMOPS; /* XXX tell gencode to reduce the right tree */ SCLASS(p->n_su, sh); return sh; }