/* M O D U L E F O R A C C E S S S I N G T H E L I S T * * O F A V A I L A B L E E X P R E S S I O N S */ #include "../../../h/em_mnem.h" #include "../share/types.h" #include "../share/debug.h" #include "../share/aux.h" #include "../share/lset.h" #include "../share/global.h" #include "cs.h" #include "cs_aux.h" #include "cs_debug.h" #include "cs_alloc.h" #include "cs_getent.h" avail_p avails; /* The list of available expressions. */ STATIC bool commutative(instr) int instr; { /* Is instr a commutative operator? */ switch (instr) { case op_adf: case op_adi: case op_adu: case op_and: case op_cms: case op_ior: case op_mlf: case op_mli: case op_mlu: return TRUE; default: return FALSE; } } STATIC bool same_avail(kind, avp1, avp2) byte kind; avail_p avp1, avp2; { /* Two expressions are the same if they have the same operator, * the same size, and their operand(s) have the same value. * Only if the operator is commutative, the order of the operands * does not matter. */ if (avp1->av_instr != avp2->av_instr) return FALSE; if (avp1->av_size != avp2->av_size) return FALSE; switch (kind) { default: assert(FALSE); break; case EXPENSIVE_LOAD: case UNAIR_OP: return avp1->av_operand == avp2->av_operand; case BINAIR_OP: if (commutative(avp1->av_instr & BMASK)) return avp1->av_oleft == avp2->av_oleft && avp1->av_oright == avp2->av_oright || avp1->av_oleft == avp2->av_oright && avp1->av_oright == avp2->av_oleft ; else return avp1->av_oleft == avp2->av_oleft && avp1->av_oright == avp2->av_oright; case TERNAIR_OP: return avp1->av_ofirst == avp2->av_ofirst && avp1->av_osecond == avp2->av_osecond && avp1->av_othird == avp2->av_othird; } /* NOTREACHED */ } STATIC check_local(avp) avail_p avp; { /* Check if the local in which the result of avp was stored, * still holds this result. Update if not. */ if (avp->av_saveloc == (entity_p) 0) return; /* Nothing to check. */ if (avp->av_saveloc->en_vn != avp->av_result) { OUTTRACE("save local changed value", 0); avp->av_saveloc = (entity_p) 0; } } STATIC entity_p result_local(size, l) offset size; line_p l; { /* If the result of an expression of size bytes is stored into a * local for which a registermessage was generated, return a pointer * to this local. */ line_p dummy; entity_p enp; if (l == (line_p) 0) return (entity_p) 0; if (INSTR(l)==op_stl && size==ws || INSTR(l)==op_sdl && size==2*ws) { enp = getentity(l, &dummy); if (is_regvar(enp->en_loc)) { OUTTRACE("save local found, %ld(LB)", enp->en_loc); return enp; } } return (entity_p) 0; } STATIC copy_avail(kind, src, dst) int kind; avail_p src, dst; { /* Copy some attributes from src to dst. */ dst->av_instr = src->av_instr; dst->av_size = src->av_size; switch (kind) { default: assert(FALSE); break; case EXPENSIVE_LOAD: case UNAIR_OP: dst->av_operand = src->av_operand; break; case BINAIR_OP: dst->av_oleft = src->av_oleft; dst->av_oright = src->av_oright; break; case TERNAIR_OP: dst->av_ofirst = src->av_ofirst; dst->av_osecond = src->av_osecond; dst->av_othird = src->av_othird; break; } } avail_p av_enter(avp, ocp, kind) avail_p avp; occur_p ocp; int kind; { /* Put the available expression avp in the list, * if it is not already there. * Add ocp to the set of occurrences of this expression. */ register avail_p ravp; line_p last = ocp->oc_llast; for (ravp = avails; ravp != (avail_p) 0; ravp = ravp->av_before) { if (same_avail(kind, ravp, avp)) { /* It was there. */ Ladd(ocp, &ravp->av_occurs); /* Can we still use the local in which * the result was stored? */ check_local(ravp); return ravp; } } /* A new available axpression. */ ravp = newavail(); /* Remember local, if any, that holds result. */ if (avp->av_instr != (byte) INSTR(last)) { /* Only possible when instr is the implicit AAR in * a LAR or SAR. */ ravp->av_saveloc = (entity_p) 0; } else { ravp->av_saveloc = result_local(avp->av_size, last->l_next); } ravp->av_found = last; ravp->av_result = kind == EXPENSIVE_LOAD? avp->av_operand: newvalnum(); copy_avail(kind, avp, ravp); oldoccur(ocp); ravp->av_before = avails; avails = ravp; return ravp; } clr_avails() { /* Throw away the information about the available expressions. */ register avail_p ravp, next; register Lindex i; register lset s; for (ravp = avails; ravp != (avail_p) 0; ravp = next) { next = ravp->av_before; s = ravp->av_occurs; for (i = Lfirst(s); i != (Lindex) 0; i = Lnext(i, s)) { oldoccur(occ_elem(i)); } Ldeleteset(s); oldavail(ravp); } avails = (avail_p) 0; }