204 lines
4.2 KiB
C
204 lines
4.2 KiB
C
/*
|
|
* (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 <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;
|
|
}
|