204 lines
		
	
	
	
		
			4.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			204 lines
		
	
	
	
		
			4.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* $Id$ */
 | |
| /*
 | |
|  * (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 <em_mnem.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"
 | |
| 
 | |
| 
 | |
| 
 | |
| #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;
 | |
| }
 |