17bc9cdef7
Most warnings are for functions implicitly returning int. Change most
of these functions to return void. (Traditional K&R C had no void
type, but C89 has it.)
Add prototypes to most function declarations in headers. This is
easy, because ego declares most of its extern functions, and the
comments listed most parameters. There were a few outdated or missing
declarations, and a few .c files that failed to include an .h with the
declarations.
Add prototypes to a few function definitions in .c files. Most
functions still have traditional K&R definitions. Most STATIC
functions still don't have prototypes, because they have no earlier
declaration where I would have added the prototype.
Change some prototypes in util/ego/share/alloc.h. Functions newmap()
and oldmap() handle an array of pointers to something; change the
array's type from `short **` to `void **`. Callers use casts to go
between `void **` and the correct type, like `line_p *`. Function
oldtable() takes a `short *`, not a `short **`; I added the wrong type
in 5bbbaf4
.
Make a few other changes to silence warnings. There are a few places
where clang wants extra parentheses in the code.
Edit util/ego/ra/build.lua to add the missing dependency on ra*.h; I
needed this to prevent crashes from ra.
189 lines
3.8 KiB
C
189 lines
3.8 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 _ I V . C
|
|
*
|
|
*/
|
|
|
|
|
|
#include <em_mnem.h>
|
|
#include <em_pseu.h>
|
|
#include "../share/types.h"
|
|
#include "sr.h"
|
|
#include "../share/lset.h"
|
|
#include "../share/cset.h"
|
|
#include "../share/debug.h"
|
|
#include "../share/global.h"
|
|
#include "../share/alloc.h"
|
|
#include "../share/utils.h"
|
|
#include "sr_aux.h"
|
|
#include "sr_cand.h"
|
|
#include "sr_iv.h"
|
|
|
|
|
|
|
|
STATIC lset ivvars; /* set of induction variables */
|
|
|
|
STATIC short nature(lnp)
|
|
line_p lnp;
|
|
{
|
|
/* Auxiliary routine used by inc_or_dec, is_add and plus_or_min.
|
|
* Determine if lnp had INCREMENT/DECREMENT-nature (1),
|
|
* ADD-nature (2), SUBTRACT-nature (3)
|
|
* or Buddha-nature (0).
|
|
*/
|
|
|
|
bool size_ok;
|
|
|
|
assert(lnp != (line_p) 0);
|
|
size_ok = (TYPE(lnp) == OPSHORT && SHORT(lnp) == ws);
|
|
switch(INSTR(lnp)) {
|
|
case op_inc:
|
|
case op_dec:
|
|
return 1;
|
|
case op_adi:
|
|
case op_adu:
|
|
return (size_ok? 2:0);
|
|
case op_sbi:
|
|
case op_sbu:
|
|
return (size_ok? 3:0);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
#define is_add(l) (nature(l) == 2)
|
|
#define plus_or_min(l) (nature(l) > 1)
|
|
#define inc_or_dec(l) (nature(l) == 1)
|
|
|
|
|
|
STATIC bool is_same(l,lnp)
|
|
line_p l, lnp;
|
|
{
|
|
/* lnp is a STL x , where x is a candidate
|
|
* induction variable. See if l is a LOL x
|
|
* (with the same x as the store-instruction)
|
|
*/
|
|
|
|
assert(INSTR(lnp) == op_stl);
|
|
return l != (line_p) 0 && INSTR(l) == op_lol &&
|
|
off_set(l) == off_set(lnp);
|
|
}
|
|
|
|
|
|
STATIC void ivar(lnp,step)
|
|
line_p lnp;
|
|
int step;
|
|
{
|
|
/* Record the fact that we've found a new induction variable.
|
|
* lnp points to the last instruction of the code that
|
|
* increments the induction variable, i.e. a STL, DEL or INL.
|
|
*/
|
|
|
|
iv_p i;
|
|
|
|
i = newiv();
|
|
i->iv_off = (TYPE(lnp) == OPSHORT ? (offset) SHORT(lnp) : OFFSET(lnp));
|
|
i->iv_incr = lnp; /* last instruction of increment code */
|
|
i->iv_step = step; /* step value */
|
|
Ladd(i,&ivvars);
|
|
}
|
|
|
|
|
|
STATIC int sign(lnp)
|
|
line_p lnp;
|
|
{
|
|
switch(INSTR(lnp)) {
|
|
case op_inc:
|
|
case op_inl:
|
|
case op_adi:
|
|
case op_adu:
|
|
return 1;
|
|
case op_dec:
|
|
case op_del:
|
|
case op_sbi:
|
|
case op_sbu:
|
|
return (-1);
|
|
default:
|
|
assert(FALSE);
|
|
}
|
|
/* NOTREACHED */
|
|
}
|
|
|
|
|
|
STATIC void try_patterns(lnp)
|
|
line_p lnp;
|
|
{
|
|
/* lnp is a STL x; try to recognize
|
|
* one of the patterns:
|
|
* 'LOAD const; LOAD x; ADD; STORE x'
|
|
* or 'LOAD x; LOAD const; ADD or SUBTRACT;
|
|
* STORE x'
|
|
* or 'LOAD x; INCREMENT/DECREMENT; STORE x'
|
|
*/
|
|
|
|
line_p l, l2;
|
|
|
|
l = PREV(lnp); /* instruction before lnp*/
|
|
if (l == (line_p) 0) return; /* no match possible */
|
|
l2 = PREV(l);
|
|
if (inc_or_dec(l)) {
|
|
if (is_same(l2,lnp)) {
|
|
/* e.g. LOL iv ; INC ; STL iv */
|
|
ivar(lnp,sign(l));
|
|
}
|
|
return;
|
|
}
|
|
if (is_add(lnp)) {
|
|
if(is_same(l2,lnp) && is_const(PREV(l2))) {
|
|
ivar(lnp,SHORT(PREV(l2)));
|
|
return;
|
|
}
|
|
}
|
|
if (plus_or_min(l)) {
|
|
if (is_const(l2) && is_same(PREV(l2),lnp)) {
|
|
ivar(lnp,sign(l) * SHORT(l2));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void induc_vars(loop,ivar_out, vars_out)
|
|
loop_p loop;
|
|
lset *ivar_out, *vars_out;
|
|
{
|
|
/* Construct the set of induction variables. We use several
|
|
* global variables computed by 'candidates'.
|
|
*/
|
|
|
|
Lindex i;
|
|
line_p lnp;
|
|
lset cand_iv, vars;
|
|
|
|
ivvars = Lempty_set();
|
|
candidates(loop, &cand_iv, &vars);
|
|
/* Find the set of all variables that are assigned precisely
|
|
* once within the loop, within a firm block.
|
|
* Also find all remaining local variables that are changed
|
|
* within the loop.
|
|
*/
|
|
if (Lnrelems(cand_iv) > 0) {
|
|
for (i = Lfirst(cand_iv); i != (Lindex) 0; i = Lnext(i,cand_iv)) {
|
|
lnp = (line_p) Lelem(i);
|
|
if (INSTR(lnp) == op_inl || INSTR(lnp) == op_del) {
|
|
ivar(lnp,sign(lnp));
|
|
} else {
|
|
try_patterns(lnp);
|
|
}
|
|
}
|
|
}
|
|
Ljoin(cand_iv, &vars);
|
|
*ivar_out = ivvars;
|
|
*vars_out = vars;
|
|
}
|