ack/util/ego/sr/sr_expr.c
1984-11-26 14:51:59 +00:00

200 lines
4.1 KiB
C

/* 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 <stdio.h>
#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;
}