ack/util/ego/sr/sr_cand.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 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 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 do_dismiss(lnp)
line_p lnp;
{
Ladd(lnp,&dism);
}
STATIC 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);
}
}
}
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;
}