9037d137f5
This uncovers a problem in il/il_aux.c: it passes 3 arguments to getlines(), but the function expects 4 arguments. I add FALSE as the 4th argument. TRUE would fill in the list of mesregs. IL uses mesregs during phase 1, but this call to getlines() is in phase 2. TRUE would leak memory unless I added a call to Ldeleteset(mesregs). So I pass FALSE. Functions passed to go() now have a `void *` parameter because no_action() now takes a `void *`.
243 lines
4.9 KiB
C
243 lines
4.9 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 */
|
|
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "../share/types.h"
|
|
#include "sr.h"
|
|
#include "../share/debug.h"
|
|
#include "../share/global.h"
|
|
#include "../share/files.h"
|
|
#include "../share/get.h"
|
|
#include "../share/put.h"
|
|
#include "../share/lset.h"
|
|
#include "../share/map.h"
|
|
#include "../share/alloc.h"
|
|
#include "../share/go.h"
|
|
#include "../share/aux.h"
|
|
#include "sr_aux.h"
|
|
#include "sr_iv.h"
|
|
|
|
/* Strength reduction tries to change expensive operators occurring
|
|
* in a loop into cheaper operators. The expensive operators considered
|
|
* are multiplication, left-shift and array referencing.
|
|
* The transformations can be expressed in C as:
|
|
*
|
|
* [1]: for (i = e1; i <= e2; i++)
|
|
* print(118*i);
|
|
* becomes:
|
|
* for (i = e1, t = 118*e1; i <= e2; i++, t += 118)
|
|
* print(t);
|
|
*
|
|
* [2]: for (i = e1; i <= e2; i++)
|
|
* print(a[i]);
|
|
* becomes:
|
|
* for (i = e1, p = &a[i]; i <= e2; i++, p++)
|
|
* print(*p);
|
|
* The latter optimization is suppressed if array bound checking
|
|
* is required.
|
|
*/
|
|
|
|
/* Machine and/or language dependent parameters: */
|
|
|
|
int ovfl_harmful;
|
|
int arrbound_harmful;
|
|
int sli_threshold;
|
|
|
|
int Ssr; /* #optimizations found */
|
|
|
|
void sr_machinit(void *vp)
|
|
{
|
|
/* Read target machine dependent information */
|
|
FILE *f = vp;
|
|
char s[100];
|
|
|
|
|
|
for (;;) {
|
|
while(getc(f) != '\n');
|
|
fscanf(f,"%s",s);
|
|
if (strcmp(s,"%%SR") == 0)break;
|
|
}
|
|
fscanf(f,"%d",&ovfl_harmful);
|
|
fscanf(f,"%d",&arrbound_harmful);
|
|
fscanf(f,"%d",&sli_threshold);
|
|
}
|
|
|
|
STATIC del_ivs(ivs)
|
|
lset ivs;
|
|
{
|
|
/* Delete the set of iv structs */
|
|
|
|
Lindex i;
|
|
|
|
for (i = Lfirst(ivs); i != (Lindex) 0; i = Lnext(i,ivs)) {
|
|
oldiv(Lelem(i));
|
|
}
|
|
Ldeleteset(ivs);
|
|
}
|
|
|
|
|
|
STATIC do_loop(loop)
|
|
loop_p loop;
|
|
{
|
|
lset ivs, vars;
|
|
|
|
OUTTRACE("going to process loop %d",loop->lp_id);
|
|
induc_vars(loop,&ivs, &vars);
|
|
/* Build a set of iv_structs, one for every induction
|
|
* variable of the loop, i.e. a variable i that
|
|
* is changed only by i := i + c, where c is a loop constant.
|
|
* Also detects variables that are changed (including induction
|
|
* variables!).
|
|
*/
|
|
OUTTRACE("loop has %d induction variables",Lnrelems(ivs));
|
|
if (Lnrelems(ivs) > 0) {
|
|
strength_reduction(loop,ivs,vars);
|
|
/* Perform strength reduction. Reduce:
|
|
* iv * c to addition
|
|
* a[iv] to indirection (*p)
|
|
* (unless array bound checking is required)
|
|
*/
|
|
}
|
|
del_ivs(ivs);
|
|
Ldeleteset(vars);
|
|
}
|
|
|
|
|
|
|
|
STATIC loopblocks(p)
|
|
proc_p p;
|
|
{
|
|
/* Compute the LP_BLOCKS sets for all loops of p */
|
|
|
|
register bblock_p b;
|
|
register Lindex i;
|
|
|
|
for (b = p->p_start; b != (bblock_p) 0; b = b->b_next) {
|
|
for (i = Lfirst(b->b_loops); i != (Lindex) 0;
|
|
i = Lnext(i,b->b_loops)) {
|
|
Ladd(b,&(((loop_p) Lelem(i))->LP_BLOCKS));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
STATIC opt_proc(p)
|
|
proc_p p;
|
|
{
|
|
/* Optimize all loops of one procedure. We first do all
|
|
* outer loops at the lowest nesting level and proceed
|
|
* in the inwards direction.
|
|
*/
|
|
|
|
Lindex i;
|
|
loop_p lp,outermost;
|
|
int min_level;
|
|
|
|
for (;;) {
|
|
min_level = 1000;
|
|
outermost = 0;
|
|
for (i = Lfirst(p->p_loops); i != (Lindex) 0;
|
|
i = Lnext(i,p->p_loops)) {
|
|
lp = (loop_p) Lelem(i);
|
|
if (!lp->LP_DONE && lp->lp_level < min_level) {
|
|
min_level = lp->lp_level;
|
|
outermost = lp;
|
|
}
|
|
}
|
|
if (! outermost) break;
|
|
do_loop(outermost);
|
|
outermost->LP_DONE = TRUE;
|
|
OUTTRACE("loop %d processed",outermost->lp_id);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
STATIC bblock_p header(lp)
|
|
loop_p lp;
|
|
{
|
|
/* Try to determine the 'header' block of loop lp.
|
|
* If 'e' is the entry block of loop L, then block 'b' is
|
|
* called the header block of L, iff:
|
|
* SUCC(b) = {e} & b dominates e.
|
|
* If lp has no header block, 0 is returned.
|
|
*/
|
|
|
|
bblock_p x = lp->lp_entry->b_idom;
|
|
|
|
if (x != (bblock_p) 0 && Lnrelems(x->b_succ) == 1 &&
|
|
(bblock_p) Lelem(Lfirst(x->b_succ)) == lp->lp_entry) {
|
|
return x;
|
|
}
|
|
return (bblock_p) 0;
|
|
}
|
|
|
|
|
|
|
|
STATIC sr_extproc(p)
|
|
proc_p p;
|
|
{
|
|
/* Allocate the extended data structures for procedure p */
|
|
|
|
register loop_p lp;
|
|
register Lindex pi;
|
|
|
|
for (pi = Lfirst(p->p_loops); pi != (Lindex) 0;
|
|
pi = Lnext(pi,p->p_loops)) {
|
|
lp = (loop_p) Lelem(pi);
|
|
lp->lp_extend = newsrlpx();
|
|
lp->LP_HEADER = header(lp);
|
|
if (lp->LP_HEADER) {
|
|
lp->LP_INSTR = last_instr(lp->LP_HEADER);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
STATIC sr_cleanproc(p)
|
|
proc_p p;
|
|
{
|
|
/* Remove the extended data structures for procedure p */
|
|
|
|
register loop_p lp;
|
|
register Lindex pi;
|
|
|
|
|
|
for (pi = Lfirst(p->p_loops); pi != (Lindex) 0;
|
|
pi = Lnext(pi,p->p_loops)) {
|
|
lp = (loop_p) Lelem(pi);
|
|
oldsrlpx(lp->lp_extend);
|
|
}
|
|
}
|
|
|
|
|
|
void sr_optimize(void *vp)
|
|
{
|
|
proc_p p = vp;
|
|
|
|
if (IS_ENTERED_WITH_GTO(p)) return;
|
|
sr_extproc(p);
|
|
loopblocks(p);
|
|
opt_proc(p);
|
|
sr_cleanproc(p);
|
|
}
|
|
|
|
|
|
|
|
main(argc,argv)
|
|
int argc;
|
|
char *argv[];
|
|
{
|
|
go(argc,argv,no_action,sr_optimize,sr_machinit,no_action);
|
|
report("strength reductions",Ssr);
|
|
exit(0);
|
|
}
|