/* $Header$ */ /* * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * See the copyright notice in the ACK home directory, in the file "Copyright". */ /* S T R E N G T H R E D U C T I O N * * S R _ E X P R . C * */ #include #include "../share/types.h" #include "sr.h" #include "../share/debug.h" #include "../share/global.h" #include "../share/aux.h" #include "sr_aux.h" #include "../share/lset.h" #include "sr_iv.h" #include "../../../h/em_mnem.h" #define ME_NONE 0 #define ME_UNAIR 1 #define ME_BINAIR 2 #define ME_LOOPCONST 3 #define ME_IV 4 STATIC iv_p last_iv; STATIC int iv_sign; STATIC lset ivars, loopvars; STATIC bool is_loadiv(lnp) line_p lnp; { /* See if lnp is a LOL iv instruction, where iv is an * induction variable of the set ivars. If so, set the * the global variable last_iv to its descriptor. */ Lindex i; iv_p iv; offset off; if (INSTR(lnp) == op_lol) { off = off_set(lnp); for (i = Lfirst(ivars); i != (Lindex) 0; i = Lnext(i,ivars)) { iv = (iv_p) Lelem(i); if (iv->iv_off == off) { last_iv = iv; return TRUE; } } } return FALSE; } #define size_ok(l) (TYPE(l) == OPSHORT && SHORT(l) == ws) STATIC int me_kind(l,sign_in,sign_out) line_p l; int sign_in, *sign_out; { if (l != (line_p) 0) { switch(INSTR(l)) { case op_adi: case op_adu: if (size_ok(l)) { *sign_out = sign_in; return ME_BINAIR; } break; case op_sbi: case op_sbu: if (size_ok(l)) { *sign_out = - sign_in; return ME_BINAIR; } break; case op_ngi: if (size_ok(l)) { *sign_out = - sign_in; return ME_UNAIR; } break; case op_inc: case op_dec: *sign_out = sign_in; return ME_UNAIR; case op_loc: return ME_LOOPCONST; case op_lol: if (is_loadiv(l)) { iv_sign = sign_in; return ME_IV; } if (is_loopconst(l,loopvars)) return ME_LOOPCONST; } } return ME_NONE; } STATIC bool match_expr(l,iv_allowed,lbegin,iv_seen,sign) line_p l,*lbegin; bool iv_allowed, *iv_seen; int sign; { /* This routine is a top down parser for simple * EM expressions. It recognizes expressions that * have as operators + and - (unary - is also allowed) * and that have as operands a number of loop constants * (either a constant or a variable that is not * changed within the loop) and at most one induction * variable. * The parameter iv_allowed is propagated downwards * in the expression tree, indicating whether the * subexpression may use an induction variable as * operand. The parameter iv_seen is propagated * upwards, indicating if the subexpression has used * an induction variable. The parameter sign is * propagated downwards; it indicates the sign of * the subexpression. lbegin will point to the * beginning of the recognized subexpression * (it is an out parameter). Note that we scan the * EM text from right to left (i.e. top down). */ line_p l1; bool iv_insubexpr; int sign2; switch(me_kind(l,sign,&sign2)) { case ME_UNAIR: /* unairy operator, match one subexpression */ if (match_expr(PREV(l),iv_allowed,&l1,&iv_insubexpr,sign2)) { *lbegin = l1; *iv_seen = iv_insubexpr; return TRUE; } return FALSE; case ME_BINAIR: /* binairy operator, match two subexpressions */ if (match_expr(PREV(l), iv_allowed, &l1, &iv_insubexpr,sign2)) { l = PREV(l1); iv_allowed = iv_allowed && !iv_insubexpr; if (match_expr(l,iv_allowed,&l1, &iv_insubexpr,sign)) { *lbegin = l1; *iv_seen = !iv_allowed || iv_insubexpr; return TRUE; } } return FALSE; /* subexpression not recognized */ case ME_LOOPCONST: *lbegin = l; /* expression is a loop constant */ *iv_seen = FALSE; return TRUE; case ME_IV: if (iv_allowed) { *iv_seen = TRUE; *lbegin = l; return TRUE; } /* fall through ... */ default: return FALSE; } } bool is_ivexpr(l,ivs,vars,lbegin_out,iv_out,sign_out) line_p l, *lbegin_out; lset ivs,vars; iv_p *iv_out; int *sign_out; { line_p l2; bool iv_seen; loopvars = vars; ivars = ivs; if (match_expr(l,TRUE,&l2,&iv_seen,1)) { if (iv_seen) { /* recognized a correct expression */ *lbegin_out = l2; *iv_out = last_iv; *sign_out = iv_sign; return TRUE; } } return FALSE; }