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.
193 lines
4 KiB
C
193 lines
4 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 _ C A N D . C
|
|
*/
|
|
|
|
|
|
#include <em_mnem.h>
|
|
#include <em_pseu.h>
|
|
#include "../share/types.h"
|
|
#include "../share/lset.h"
|
|
#include "../share/cset.h"
|
|
#include "../share/debug.h"
|
|
#include "../share/global.h"
|
|
#include "../share/map.h"
|
|
#include "../share/utils.h"
|
|
#include "sr.h"
|
|
#include "sr_aux.h"
|
|
#include "sr_cand.h"
|
|
|
|
|
|
/* A candidate induction variable of a loop (hereafter called candidate) is a
|
|
* local variable (of the current procedure) that is assigned a value
|
|
* precisely once within the loop. Furthermore, this assignment must
|
|
* take place in a firm block of the loop.
|
|
* We determine those locals that are assigned precisely once, within
|
|
* a firm block;
|
|
*
|
|
* We represent a local variable via an instruction that references it,
|
|
* e.g. LOL -6 represents the local variable at offset -6 with size=wordsize.
|
|
* We keep track of two sets:
|
|
* cand - the set of all candidate variables
|
|
* dismiss - a set of variables that may not be made a candidate
|
|
* (because they are assigned more than once, or because
|
|
* they are assigned outside a firm block).
|
|
* Only local variables for which a register message is given are considered.
|
|
*/
|
|
|
|
|
|
STATIC lset cand, /* set of candidates */
|
|
dism; /* set of dismissed variables */
|
|
|
|
|
|
#define ALL_LINES(lnp,list) lnp = list; lnp != (line_p) 0; lnp = lnp->l_next
|
|
|
|
|
|
|
|
STATIC void un_cand(lnp)
|
|
line_p lnp;
|
|
{
|
|
/* remove the variable stored into by lnp from the list of
|
|
* candidates (if it was there anyway).
|
|
*/
|
|
|
|
Lindex i, next;
|
|
|
|
for (i = Lfirst(cand); i != (Lindex) 0; i = next) {
|
|
next = Lnext(i,cand);
|
|
if (same_local(lnp,Lelem(i))) {
|
|
OUTTRACE("remove candidate",0);
|
|
Lremove(Lelem(i), &cand);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
STATIC bool is_cand(lnp)
|
|
line_p lnp;
|
|
{
|
|
/* see if the variable stored into by lnp is a candate */
|
|
|
|
Lindex i;
|
|
|
|
for (i = Lfirst(cand); i != (Lindex) 0; i = Lnext(i,cand)) {
|
|
if (same_local(lnp,Lelem(i))) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
STATIC void make_cand(lnp)
|
|
line_p lnp;
|
|
{
|
|
/* make the variable stored into by lnp a candidate */
|
|
|
|
|
|
OUTTRACE("add a new candidate",0);
|
|
Ladd(lnp,&cand);
|
|
}
|
|
|
|
|
|
|
|
STATIC void do_dismiss(lnp)
|
|
line_p lnp;
|
|
{
|
|
Ladd(lnp,&dism);
|
|
}
|
|
|
|
|
|
STATIC void dismiss(lnp)
|
|
line_p lnp;
|
|
{
|
|
/* The variable referenced by lnp is turned definitely into
|
|
* a non-candidate.
|
|
*/
|
|
|
|
un_cand(lnp); /* remove it from the candidate set,
|
|
* if it was there in the first place.
|
|
*/
|
|
do_dismiss(lnp); /* add it to the set of dismissed variables */
|
|
}
|
|
|
|
|
|
STATIC bool not_dismissed(lnp)
|
|
line_p lnp;
|
|
{
|
|
Lindex i;
|
|
|
|
for (i = Lfirst(dism); i != (Lindex) 0; i = Lnext(i,dism)) {
|
|
if (same_local(Lelem(i),lnp)) {
|
|
return FALSE; /* variable was dismissed */
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
STATIC void try_cand(lnp,b)
|
|
line_p lnp;
|
|
bblock_p b;
|
|
{
|
|
/* If the variable stored into by lnp was not already a candidate
|
|
* and was not dismissed, then it is made a candidate
|
|
* (unless the assignment takes places in a block that is not firm).
|
|
*/
|
|
|
|
if (!is_regvar(off_set(lnp))) return;
|
|
if (is_cand(lnp) || !IS_FIRM(b)) {
|
|
dismiss(lnp);
|
|
} else {
|
|
if (not_dismissed(lnp)) {
|
|
make_cand(lnp);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void candidates(lp,cand_out,vars_out)
|
|
loop_p lp;
|
|
lset *cand_out, *vars_out;
|
|
{
|
|
/* Find the candidate induction variables.
|
|
*/
|
|
|
|
bblock_p b;
|
|
line_p lnp;
|
|
Lindex i;
|
|
|
|
OUTTRACE("find candidates of loop %d",lp->lp_id);
|
|
cand = Lempty_set();
|
|
dism = Lempty_set();
|
|
|
|
for (i = Lfirst(lp->LP_BLOCKS); i != (Lindex) 0;
|
|
i = Lnext(i,lp->LP_BLOCKS)) {
|
|
b = (bblock_p) Lelem(i);
|
|
for ( ALL_LINES(lnp, b->b_start)) {
|
|
OUTTRACE("inspect instruction %d",INSTR(lnp));
|
|
switch(INSTR(lnp)) {
|
|
case op_stl:
|
|
case op_inl:
|
|
case op_del:
|
|
OUTTRACE("it's a store local",0);
|
|
try_cand(lnp,b);
|
|
break;
|
|
case op_zrl:
|
|
OUTTRACE("it's a destroy local",0);
|
|
if (is_regvar(off_set(lnp))) {
|
|
dismiss(lnp);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
*cand_out = cand;
|
|
*vars_out = dism;
|
|
}
|