fixed paths

This commit is contained in:
2025-03-12 14:22:11 +03:00
parent a4c8785e66
commit 18f561925b
774 changed files with 4558 additions and 4558 deletions

View File

@@ -0,0 +1,101 @@
#######################################################################
## pC++/Sage++ Copyright (C) 1993 ##
## Indiana University University of Oregon University of Rennes ##
#######################################################################
SAGEROOT = ../../..
CONFIG_ARCH=default
LIBDIR = $(SAGEROOT)/lib/$(CONFIG_ARCH)
LIBINCLUDE = $(SAGEROOT)/lib/include
HINCLUDE = $(SAGEROOT)/h
INSTALLDEST = $(SAGEROOT)/bin/$(CONFIG_ARCH)
INSTALL = /bin/cp
#HP-ALLOCA#LDLIBS = -lPW#ENDIF#
#HP_CFLAGS#CEXTRA = -Aa#ENDIF#
CC = gcc
#USE_CC#CC=cc#ENDIF#
CXX = g++
#USE_CFRONT#CXX=CC#ENDIF#
LOADER = $(CXX)
INCLUDE = -I$(LIBINCLUDE) -I$(HINCLUDE) -I./OmegaForSage/include
CFLAGS = $(INCLUDE) -g # $(CEXTRA)
LDFLAGS =
LIBS =
#LIBS = $(LIBDIR)/libann.a $(LIBDIR)/libsage.a $(LIBDIR)/libdb.a $(LIBDIR)/libSage++.a
OMEGATEST_OBJ = OmegaForSage/add-assert.o OmegaForSage/cover.o OmegaForSage/ddomega-build.o OmegaForSage/ddomega.o OmegaForSage/kill.o OmegaForSage/affine.o OmegaForSage/sagedriver.o OmegaForSage/ddomega-use.o OmegaForSage/debug.o OmegaForSage/ip.o OmegaForSage/refine.o
HFILE = annotationDriver.h constanteSet.h depGraph.h inducVar.h set.h arrayRef.h definitionSet.h dependence.h intrinsic.h depInterface.h definesValues.h
PROGRAM = libDep.a
OBJS = set.o controlFlow.o flowAnalysis.o defUse.o constanteProp.o computeInducVar.o arrayRef.o dependence.o invariant.o depGraph.o intrinsic.o loopTransform.o annotationDriver.o depInterface.o
SRCS = set.C controlFlow.C flowAnalysis.C defUse.C constanteProp.C computeInducVar.C arrayRef.C dependence.C invariant.C depGraph.C intrinsic.C loopTransform.C annotationDriver.C depInterface.C
all: $(PROGRAM)
$(PROGRAM): $(OBJS)
/bin/rm -f libDep.a
ar qc $(PROGRAM) $(OBJS) $(LIBS) $(OMEGATEST_OBJ)
ranlib libDep.a
set.o: set.C $(HFILE)
$(CXX) $(CFLAGS) -c set.C
controlFlow.o: controlFlow.C $(HFILE)
$(CXX) $(CFLAGS) -c controlFlow.C
flowAnalysis.o: flowAnalysis.C $(HFILE)
$(CXX) $(CFLAGS) -c flowAnalysis.C
defUse.o: defUse.C $(HFILE)
$(CXX) $(CFLAGS) -c defUse.C
constanteProp.o: constanteProp.C $(HFILE)
$(CXX) $(CFLAGS) -c constanteProp.C
computeInducVar.o: computeInducVar.C $(HFILE)
$(CXX) $(CFLAGS) -c computeInducVar.C
arrayRef.o: arrayRef.C $(HFILE)
$(CXX) $(CFLAGS) -c arrayRef.C
dependence.o: dependence.C $(HFILE)
$(CXX) $(CFLAGS) -c dependence.C
invariant.o: invariant.C $(HFILE)
$(CXX) $(CFLAGS) -c invariant.C
depGraph.o: depGraph.C $(HFILE)
$(CXX) $(CFLAGS) -c depGraph.C
intrinsic.o: intrinsic.C $(HFILE)
$(CXX) $(CFLAGS) -c intrinsic.C
loopTransform.o: loopTransform.C $(HFILE)
$(CXX) $(CFLAGS) -c loopTransform.C
annotationDriver.o : annotationDriver.C $(HFILE)
$(CXX) $(CFLAGS) -c annotationDriver.C
depInterface.o : depInterface.C $(HFILE)
$(CXX) $(CFLAGS) -c depInterface.C
clean:
/bin/rm -f *.o *.dep a.out libDep.a

View File

@@ -0,0 +1,62 @@
# in maple_interface.c include vfork.h
#SUN#CEXTRA=-DSUN=1
# Directory where sigma is installed (used to find include files and libraries)
# DEFINE sigma_prefix as the path to the directory containing sigma
sigma_prefix = ../../../sage/Beta/sigma
sigma_lib = $(sigma_prefix)/lib
# Directory where tool box is installed
# DEFINE sigma_prefix as the path to the directory containing sigma toolc++
toolc++_prefix = .
# Directory in which to put toolc++ library
toolc++_libdir = .
# Directory in which include file can be found
toolc++_include = .
#
CC = gcc
INCLUDE = -I./include -I.
# -w don't issue warning now.
CFLAGS = $(INCLUDE) -g
LDFLAGS =
OMEGA_SRC = add-assert.c cover.c ddomega-build.c ddomega.c kill.c affine.c sagedriver.c ddomega-use.c debug.c ip.c refine.c
OMEGA_HDR = ./include/add-assert.h ./include/ddomega-use.h ./include/kill.h ./include/refine.h ./include/affine.h ./include/ddomega.h ./include/cover.h ./include/debug.h ./include/lang-interf.h ./include/ddomega-build.h ./include/ip.h ./include/portable.h
OMEGA_OBJ = add-assert.o cover.o ddomega-build.o ddomega.o kill.o affine.o sagedriver.o ddomega-use.o debug.o ip.o refine.o
testq: $(OMEGA_OBJ)
# $(CC) $(OMEGA_OBJ) -o testdebug -lm -lcurses -ltermcap
add-assert.o : $(OMEGA_HDR)
$(CC) $(CFLAGS) -c add-assert.c
cover.o : $(OMEGA_HDR)
$(CC) $(CFLAGS) -c cover.c
ddomega-build.o : $(OMEGA_HDR)
$(CC) $(CFLAGS) -c ddomega-build.c
ddomega.o: $(OMEGA_HDR)
$(CC) $(CFLAGS) -c ddomega.c
kill.o : $(OMEGA_HDR)
$(CC) $(CFLAGS) -c kill.c
affine.o : $(OMEGA_HDR)
$(CC) $(CFLAGS) -c affine.c
sagedriver.o : $(OMEGA_HDR) sagedriver.c
$(CC) $(CFLAGS) -c sagedriver.c
ddomega-use.o : $(OMEGA_HDR)
$(CC) $(CFLAGS) -c ddomega-use.c
debug.o: $(OMEGA_HDR)
$(CC) $(CFLAGS) -c debug.c
ip.o : $(OMEGA_HDR)
$(CC) $(CFLAGS) -c ip.c
refine.o: $(OMEGA_HDR)
$(CC) $(CFLAGS) -c refine.c
clean:
rm -rf $(OMEGA_OBJ) testdebug

View File

@@ -0,0 +1,193 @@
This is the code for the Omega Test. The interface for sage consists
in the file sagedriver.c and the include file lang-interf.h.
This is a preliminary interface, It does not use yet all the capabilities
of the omega test. More should follow.
Foloowing the original README for the tiny/omega test distribution.
********************************************************************
README file for omega/tiny distribution
README,v 1.1 1993/09/17 22:13:45 fbodin Exp
********************************************************************
This is the readme file for version 3.0.0 of the distribution of the Omega
test, which is available via anonymous ftp from ftp.cs.umd.edu (128.8.128.8)
in the directory pub/omega.
This release consists of three components:
* The Omega test: A system for performing symbolic
manipulations of conjunctions of linear constraints
over integer variables. In particular, the operations
supported include:
* Checking if integer solutions exist
* Eliminating an existential quantifier. For example,
we can transform
{ Exists b s.t. 0 <= a <= 5; b < a <= 5b}
to
{ 2 <= a <= 5}
* Checking to see if one set of constraints implies
another. For example, we can check to see if:
{0 <= x <= 3; -3 <= 2y <= 3} => {0 <= x+y, x-y <= 3}
The interface to the Omega test is described
in the file doc/omega_interface.tex
* The Omega test dependence analyzer: A system built on top
of the Omega test to analyze array data dependences. This
system builds the appropriate problems and makes the appropriate
queries of the Omega test to analyze array-based data dependences
in programs. The analyzer computes data difference/direction
vectors, recognizes reduction dependences, analyzes array kills
(which enables array expansion and array privatization),
and determines when assertions can be used to eliminate dependences.
We have attempted to define an interface that allows other users
to make use of the Omega test dependence analyzer. This interface
is described in include/lang-interf.generic and Lang-Interf3.0
(keep in touch if you plan to use this interface; we are continuing
to refine it).
* Extended tiny. We have extended Michael Wolfe's tiny tool. The
major extensions are:
* Improved user interface (scrolling, dependence browsing
windows)
* Capabilities that improve the accuracy of data dependence
analysis (induction variable recognition, forward
substitution).
* Features that demonstrate the additional information we
collect (scalar/array expansion and privatization,
interactive dependence zapping)
* An semi-automatic procedure for converting FORTRAN programs
into tiny
* A prototype implementation of a unified framework
for reordering transformations. The framework
unifies loop interchange, skewing, distribution,
fusion, reversal, statement reordering, and some
cases of access normalization, loop alignment, loop
peeling and index set splitting.
The Omega test is implemented on top of the December 1990 version of
Michael Wolfe's tiny program, as well as in a stand-alone test driver.
The Omega test computes exact data dependence information, including checks
for array kills. The Omega test data dependence analyzer is substantially
more accurate than dependence analyzers in many existing research
and commercial systems.
Tiny is a research implementation of an interactive program
restructuring tool. Tiny computes data dependence relations
and interactively performs many restructuring transformations, such
as loop interchanging, distribution, skewing, ... . Michael Wolfe
has put his tiny tool into the public domain, which allowed
us to build on top of his software. We are very grateful for Michael's
contributions.
This implementation is a research prototype and has not been subjected
to rigorous testing. In other words:
THERE ARE BUGS IN THIS SOFTWARE
We don't know of any at the moment (other that the ones listed
under KNOWN BUGS/LIMITATIONS below), but we are sure that other,
undiscovered bugs remain in the software. This software has been
put into the public domain as a public service on an "as-is"
basis, without warranty or liability.
Since this version incorporates a large number of major new features,
there will almost certain be bug fixes that will be shortly released as
version 3.0.1.
If you register with us as someone who has a copy of the Omega test,
we will send you update notices. Send email to omega@cs.umd.edu to
be added to the list of registered users.
We are committed to continued distribution and support of the Omega
test for other researchers, and a number of research groups are already
incorporating the Omega test into their compilers and programming
environments. We welcome any additional researchers. Please stay
in contact with us if you plan to make serious us of the Omega test so
that we can provide you with updates and get feedback from your use.
The implementation of the Omega test and extensions to tiny have
been done by a number of people at the University of Maryland:
William Pugh
Dave Wonnacott
Udayan Borkar
Wayne Kelly
Jerry Sobieski
Vadim Maslov
This software is public domain, and no legal restrictions of any
kind whatsoever are placed on uses of it). You may do whatever you want
with it, and no guarantees of any kind are made about its performance or
lack of errors. You can copy it, use it, incorporate it or even sell it.
We request that any research or products that make use of this software
acknowledge that use and that you keep us informed of your use.
Please send mail to omega@cs.umd.edu if you wish to be added to a mailing
list for people interesting in using this software. We will notify
people on the mail list of bug fixes and new releases.
Also send mail to omega@cs.umd.edu if you have any trouble installing
the software, bug reports or questions.
Our work on this software has been supported by NSF grants CCR-8908900 and
CCR-9157384 and by a Packard Fellowship, as well as being based on
Michael Wolfe's original implementation of tiny.
FILES
-----
The following tar files can be ftp-ed from ftp.cs.umd.edu (128.8.128.8)
from the directory pub/omega:
* README This file
* WOLFE_README The readme file that originally accompanied Michael Wolfe's
distributing of tiny
* src.tar.Z Source for the omega test and our enhanced version of tiny
* sparc_demo.tar.Z Sun Sparc executable versions of the programs that can be
made from the src files, demo files, and documentation of
of how to use our extended version of tiny.
* dec3100_demo.tar.Z Decstations 3100 executable versions of the programs that
can be made from the src files. demo files, and documentation of
of how to use our extended version of tiny.
* demo.tar.Z Test files for demos
* rt.tar.Z Regression test files
* doc.tar.Z Documentation
* techReports A directory containing postscript and dvi copies of
relevant tech reports.
Together, these tar files constitute the entire tiny system, with the
following directories:
* include header files (from src.tar.Z)
* src source code (from src.tar.Z)
* obj makefile (from src.tar.Z), generated files (from sparc_bin.tar)
* doc documentation for tiny and for other drivers for the omega test
* demo sample files documented to show features of the Omega test and
extended tiny
* f2t A FORTRAN to tiny converter based on f2c
* rt regression test sample files and expected results
* misc shell scripts used for regression testing (rt.tar and src.tar)
The executable programs are:
* "t" the tiny environment, upgraded to use the omega test and
test for refinement, killing, and covering of dependences
* "f2t" A FORTRAN to tiny converter based on f2c

View File

@@ -0,0 +1,506 @@
/* add-assert.c,v 1.1 1993/09/17 22:13:46 fbodin Exp */
#include <assert.h>
#include <string.h>
#include <stdlib.h>
/* #include "portable.h"
#include "lang-interf.h"*/
#include "include/add-assert.h"
#include "include/ddomega.h"
#include "include/ddomega-build.h"
#include "include/ip.h"
#include "include/debug.h"
#include "include/flags.h"
//#include "include/screen.h"
#include "include/Exit.h"
/*
#include "message.h"
#include "getword.h"
#include "timeTrials.h"
*/
/*
zap problem description contains information needed
to associate variable accesses in the tiny program with
variables in the integer programming problem that is
used to try determine the gist of the dependence.
zap problems are very much like delta problems,
except that there are no deltas and the symbolic constants
are protected
*/
typedef struct {
range nonloops; /* symbolic constants */
range deltas; /* deltas for common indices */
range access1s; /* index variables for access 1 */
range access2s; /* index variables for access 2 */
range steps1; /* step constraints for a1 */
range steps2; /* step constraints for a1 */
var_id vars[maxVars];
} zap_prob_desc;
#define zap_Nvars(zpd) (r_last(&(zpd)->steps2))
#if !defined NDEBUG
static int is_step_expr(var_id n)
{
return n == 0;
}
static void zap_inv(zap_prob_desc *zpd, Problem *p)
{
int v;
assert(p->getVarsN() < maxVars);
assert(p->getVarsN() >= zap_Nvars(zpd));
assert(p->_safeVars == r_length(&zpd->nonloops));
assert(r_first(&zpd->nonloops) == 1);
assert(r_last(&zpd->nonloops) + 1 == r_first(&zpd->access1s));
assert(r_last(&zpd->access1s) + 1 == r_first(&zpd->access2s));
assert(r_last(&zpd->access2s) + 1 == r_first(&zpd->steps1));
assert(r_last(&zpd->steps1) + 1 == r_first(&zpd->steps2));
for (v = 0; v < r_length(&zpd->access1s); v++) {
assert(var_id_index_p(zpd->vars[v + r_first(&zpd->access1s)]));
assert(var_ids_loop_no(zpd->vars[v + r_first(&zpd->access1s)]) == v + 1);
}
for (v = 0; v < r_length(&zpd->access2s); v++) {
assert(var_id_index_p(zpd->vars[v + r_first(&zpd->access2s)]));
assert(var_ids_loop_no(zpd->vars[v + r_first(&zpd->access2s)]) == v + 1);
}
for (v = 0; v < r_length(&zpd->nonloops); v++) {
assert(var_id_const_p(zpd->vars[v + r_first(&zpd->nonloops)]));
assert((var_ids_tag(zpd->vars[v + r_first(&zpd->nonloops)]) ==
v + r_first(&zpd->nonloops)) ||
(var_ids_tag(zpd->vars[v + r_first(&zpd->nonloops)]) == UNTAGGED));
}
for (v = 0; v < r_length(&zpd->steps1); v++) {
assert(is_step_expr(zpd->vars[v + r_first(&zpd->steps1)]));
}
for (v = 0; v < r_length(&zpd->steps2); v++) {
assert(is_step_expr(zpd->vars[v + r_first(&zpd->steps2)]));
}
for (v = 0; v < p->getNumGEqs(); v++) {
assert(p->_GEQs[v].touched);
}
}
#endif
#define MaxNameLen 254
#define MaxSuffixLen 1
static char *zap_getVarName(uint v, void *args)
{
zap_prob_desc *zpd = (zap_prob_desc*)args;
static char name[MaxNameLen + MaxSuffixLen + 1];
assert(v <= zap_Nvars(zpd));
if (zpd->vars[v] &&
(var_id_index_p(zpd->vars[v]) || var_id_const_p(zpd->vars[v])))
{
strncpy(name, var_ids_name(zpd->vars[v]), MaxNameLen);
name[MaxNameLen] = 0;
}
else {
assert(is_step_expr(zpd->vars[v]));
strcpy(name, "<trip>");
}
if (r_in(&zpd->access1s, v) || r_in(&zpd->steps1, v))
strcat(name, "1");
else if (r_in(&zpd->access2s, v) || r_in(&zpd->steps2, v))
strcat(name, "2");
return name;
}
/*
set up all fields in zap_prob_desc
copy info from a1_vars, a2_vars, and sc_vars into "omega_vars"
a1_vars and a2_vars have been set by load_bounds_and_count_steps
that is, they run from element 1 to depth+Nsteps
sc_vars have been set up by the load_constants functions
it runs from 0 to Nconsts - 1
change tags on nodes for symbolic constants to be the
indices into "vars" -- that is, the indices in the IP variable array
change order of steps to be outer loop to inner and
adjust tags accordingly (this way the common loop steps
can (and will) be aligned)
add equalities for the definitions of the deltas to p
*/
static void zap_init(zap_prob_desc *zpd, Problem *p,
uint Na1, var_id a1_vars[],
uint Na2, var_id a2_vars[],
uint Nsc, var_id sc_vars[],
uint Ns1, var_id s1_vars[],
uint Ns2, var_id s2_vars[])
{
int v;
zpd->nonloops._first = 1;
zpd->nonloops._length = Nsc;
zpd->access1s._first = 1 + Nsc;
zpd->access1s._length = Na1;
zpd->access2s._first = 1 + Nsc + Na1;
zpd->access2s._length = Na2;
zpd->steps1._first = 1 + Nsc + Na1 + Na2;
zpd->steps1._length = Ns1;
zpd->steps2._first = 1 + Nsc + Na1 + Na2 + Ns1;
zpd->steps2._length = Ns2;
if (zap_Nvars(zpd) > maxVars) {
assert(0 && "Problem too big");
fprintf(stderr, "Too many variables for omega test\n");
Exit(2);
/* We really should add all possible dependencies here */
}
zpd->vars[0] = 0;
/* a1[1..Na1] and a2[1..Na2] are valid */
for (v = 0; v < r_length(&zpd->access1s); v++) {
assert(a1_vars[v + 1] != NIL);
zpd->vars[v + r_first(&zpd->access1s)] = a1_vars[v + 1];
}
for (v = 0; v < r_length(&zpd->access2s); v++) {
assert(a2_vars[v + 1] != NIL);
zpd->vars[v + r_first(&zpd->access2s)] = a2_vars[v + 1];
}
/* sc_vars[0..Nsc-1] are valid */
for (v = 0; v < Nsc; v++) {
assert(sc_vars[v] != NIL);
zpd->vars[v + r_first(&zpd->nonloops)] = sc_vars[v];
var_ids_tag(sc_vars[v]) = v + r_first(&zpd->nonloops);
}
/* s1_vars[0..Ns1] and s2_vars[0..Ns2] hold steps
FROM INNERMOST TO OUTERMOST LOOPS */
for (v = 0; v < Ns1; v++) {
assert(s1_vars[Ns1 - 1 - v] == NIL);
zpd->vars[v + r_first(&zpd->steps1)] = s1_vars[Ns1 - 1 - v];
}
for (v = 0; v < Ns2; v++) {
assert(s2_vars[Ns2 - 1 - v] == NIL);
zpd->vars[v + r_first(&zpd->steps2)] = s2_vars[Ns2 - 1 - v];
}
init_prob(p, zap_Nvars(zpd), Nsc, zap_getVarName, zpd);
#if ! defined NDEBUG
zap_inv(zpd, p);
#endif
}
/* clear the tags for symbolic constants */
static void zap_cleanup(zap_prob_desc *zpd)
{
int v;
for (v = 0; v < r_length(&zpd->nonloops); v++) {
var_ids_tag(zpd->vars[v + r_first(&zpd->nonloops)]) = UNTAGGED;
}
}
static char *geq_as_string(Problem *p, int geq)
{
static char buf[81];
sprintEqn(buf, p, &p->_GEQs[geq], 1, 0);
return buf;
}
static int find_reds(Problem *p, int reds[])
{
int i, n_reds = 0;
for (i = 0; i < p->getNumGEqs(); i++) {
if (p->_GEQs[i].color == red) {
reds[n_reds++] = i;
}
}
return n_reds;
}
/* find, and try to get rid of a red in p */
#if 0
static bool mccarthy(Problem *p, var_id vars[])
{
WINDOW *gist_w;
int Gist_Lines, Gist_Cols, Gist_Offset;
int reds[maxGEQs]; /* only handle GEQs now */
int y, x, i;
int n_reds, zappee;
bool check;
check = hasRedEquations(p, 1);
assert(check);
n_reds = find_reds(p, reds);
assert(n_reds > 0); /* this seems the right assertion for McCarthy */
Gist_Lines = n_reds + 5;
Gist_Cols = COLS;
Gist_Offset = 0;
gist_w = newwin(Gist_Lines, Gist_Cols, Gist_Offset, 0);
if (!gist_w) {
Message_Add("couldn't create window for equations.");
screen_update();
return 0;
}
for (x = 1; x < Gist_Cols; x++) screen_waddch(gist_w, 0, x, '-');
for (x = 1; x < Gist_Cols; x++) screen_waddch(gist_w, 2, x, '-');
for (y = 1; y < Gist_Lines; y++) screen_waddch(gist_w, y, 0, '|');
for (y = 1; y < Gist_Lines; y++) screen_waddch(gist_w, y, Gist_Cols - 1, '|');
for (x = 1; x < Gist_Cols; x++) screen_waddch(gist_w, Gist_Lines - 1, x, '-');
screen_waddch(gist_w, 0, 0, '+');
screen_waddch(gist_w, 0, Gist_Cols - 1, '+');
screen_waddch(gist_w, 2, 0, '+');
screen_waddch(gist_w, 2, Gist_Cols - 1, '+');
screen_waddch(gist_w, Gist_Lines - 1, 0, '+');
screen_waddch(gist_w, Gist_Lines - 1, Gist_Cols - 1, '+');
for (i = 0; i < n_reds; i++)
negateGEQ(p, reds[i]);
screen_wprint(gist_w, 1, 1, "%s",
"Which of the following is always true (0 for none)? ");
for (i = 0; i < n_reds; i++)
{
sint j, length;
char eqn_string[80];
strcpy(eqn_string, geq_as_string(p, reds[i]));
length = strlen(eqn_string);
for (j = 1; j < length - 1; j++)
eqn_string[j - 1] = eqn_string[j];
eqn_string[length - 2] = '\0';
screen_wprint(gist_w, i + 3, 1, "%2d: %-60s\n", i + 1, eqn_string);
}
do
zappee = getint(gist_w, 1, 53);
while (zappee < 0 || zappee > n_reds);
if (zappee != 0)
add_GEQ_assertion(p, vars, reds[zappee - 1]);
delwin(gist_w);
screen_touch();
#if ! defined NOT_TINY
print_tiny(Entry, 1, 0);
#endif
return zappee != 0;
}
#endif
/*
try to build the gist problem
return 1 if it has symbolic constants and there are red equations
NOTE that reduceWithSubs must be 0
*/
static elimination_possible
build_zap_problem(dd_current dd, Problem *p, zap_prob_desc *zpd)
{
var_id consts[maxVars],
a1vars[maxVars], a2vars[maxVars],
steps1[maxVars], steps2[maxVars];
int Nconsts, Nsteps1, Nsteps2;
a_access access1 = dd_current_src(dd), access2 = dd_current_dest(dd);
uint nest1 = accesss_depth(access1), nest2 = accesss_depth(access2);
int j;
assert(!reduceWithSubs);
if (omegaPrintResult == 1) {
fprintf(debug2, "\n\nZap: Finding Gist of dependence:\n");
fprintf(debug2, "%s\n", dd_current_as_string(dd));
}
#if defined newTimeTrials
if (storeResult) zapTests++;
#endif
/* BUILD PROBLEM "p": put things we know as black equations,
and things we know only if there is a dependence as red equations */
/* PART 1: find sets of variables to be used in problem */
Nsteps1 = Nsteps2 = Nconsts = 0;
load_bounds_and_count_steps(access1, a1vars, steps1, &Nsteps1);
load_bounds_and_count_steps(access2, a2vars, steps2, &Nsteps2);
load_constants_for_bounds(access1, consts, &Nconsts);
load_constants_for_bounds(access2, consts, &Nconsts);
load_constants_for_subscripts(access1, consts, &Nconsts);
load_constants_for_subscripts(access2, consts, &Nconsts);
/* PART 2: assign columns to variables */
zap_init(zpd, p,
nest1, a1vars, nest2, a2vars, Nconsts, consts,
Nsteps1, steps1, Nsteps2, steps2);
if (Nconsts == 0)
{
assert(p->_safeVars == 0);
zap_cleanup(zpd);
if (omegaPrintResult == 1) {
fprintf(debug2, "Zap: No symbolic constants, no way to zap.\n");
}
return impossible;
}
#if ! defined NDEBUG
zap_inv(zpd, p);
#endif
/* PART 3: build problem */
/* add what we know if dd exists as red equations */
equate_subscripts(p, &zpd->access1s, &zpd->access2s, &zpd->nonloops,
red, access1, access2);
/* we don't have to bail out if there are non-affine
subscript expressions - that just gives us fewer
(possibly 0) ways to kill */
/* black equations: things that aren't interesting: */
/* we're in bounds */
bound_indices_and_conditionals(p, &zpd->access1s, &zpd->steps1, &zpd->nonloops, black, access1);
bound_indices_and_conditionals(p, &zpd->access2s, &zpd->steps2, &zpd->nonloops, black, access2);
/* we're within dddir */
for (j = 1; j <= dd_current_nest(dd); j++) {
constrain_with_convex_dddir(p, &zpd->access2s, &zpd->access1s, &dd_current_dir(dd), j, black);
}
/* PART 4: clean up */
zap_cleanup(zpd);
/* PART 5: compute gist */
if (omegaPrintResult == 1) {
fprintf(debug2, "Zap: Finding gist of problem:\n");
printProblem(p);
}
#if defined newTimeTrials
if (storeResult) realZapTests++;
#endif
if (hasRedEquations(p, 0))
{
if (printing_zap_gists)
{
fprintf(debug2, "Got red equations:\n");
printRedEquations(p);
}
if (p->getVarsN() != p->_safeVars)
{
if (omegaPrintResult == 1 || printing_zap_gists) {
fprintf(debug2, "Can't handle splintered problems yet\n");
}
return too_hard;
}
else {
#if defined newTimeTrials
if (storeResult) realZappable++;
#endif
if (omegaPrintResult == 1)
fprintf(debug2, "Zap possible\n");
return possible;
}
}
else {
if (omegaPrintResult == 1 || printing_zap_gists)
fprintf(debug2, "Zap not possible\n");
return impossible;
}
}
/*bool try_to_eliminate(dd_current dd)
{
int old_reduceWithSubs;
Problem p;
zap_prob_desc zpd;
bool result; ?!
elimination_possible ep;
old_reduceWithSubs = reduceWithSubs;
reduceWithSubs = 0
if ((ep = build_zap_problem(dd, &p, &zpd)) == possible)
{
//result = mccarthy(&p, zpd.vars);
}
else {
switch (ep) {
case too_hard:
Message_Add("The Gist of this dependence is too complicated");
if (omegaPrintResult == 1) {
fprintf(debug2, "Zap: Gist contains wild cards - give up.\n");
}
break;
case impossible:
Message_Add("No interesting assertions zap the dependence");
if (omegaPrintResult == 1) {
fprintf(debug2, "Zap: Gist = \"True\" - don't bother asking if we should negate it.\n");
}
break;
case possible:
default:
assert(0 && "Can't get here.");
}
result = 0;
}
reduceWithSubs = old_reduceWithSubs;
return result;
}*/
elimination_possible possible_to_eliminate(dd_current dd)
{
int old_reduceWithSubs;
Problem p;
zap_prob_desc zpd;
elimination_possible result;
old_reduceWithSubs = reduceWithSubs;
reduceWithSubs = 0; /* to make combining problems easier */
result = build_zap_problem(dd, &p, &zpd);
reduceWithSubs = old_reduceWithSubs;
return result;
}

View File

@@ -0,0 +1,14 @@
/* affine.c,v 1.1 1993/09/17 22:13:47 fbodin Exp */
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "include/portable.h"
#include "include/debug.h"
#include "include/ip.h"
#include "include/affine.h"
/* done in sigma */

View File

@@ -0,0 +1,427 @@
/* cover.c,v 1.1 1993/09/17 22:13:48 fbodin Exp */
/*
coverage and termination tests
Naming convention: Many of these functions and structures
refer to "read iteration" or "write iteration" as if a
test were being performed on flow dependence(s), even when
the test works for other forms of dependence.
*/
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "include/portable.h"
#include "include/debug.h"
#include "include/ip.h"
#include "include/lang-interf.h"
#include "include/ddomega-build.h"
#include "include/ddomega-use.h"
#include "include/kill.h"
#include "include/cover.h"
/*
#include "timeTrials.h"
*/
possible_reasons why_no_cover_or_terminator;
/*
test to see if a dependence covers its destination.
*/
int test_for_coverage(a_access write_acc, a_access read_acc,
uint write_nest, uint read_nest, uint common_nest,
dir_and_dist_info *dd, char *dd_as_string)
{
var_id sc_vars[maxVars], r_vars[maxVars], rs_vars[maxVars];
var_id w_vars[maxVars], ws_vars[maxVars];
int Nrs, Nws, Nsc, leading_0s;
read_prob_desc rpd; /* write1s = A[i]
write2s unused in coverage test
reads = B[j] */
Problem reads;
int j, red_complete, cover;
#if ! defined NDEBUG
int eqs, geqs;
#endif
if (access_update_p(write_acc)) {
set_reason(didnt_test);
return(0);
}
assert(write_acc == Entry || access_store_p(write_acc));
#if defined newTimeTrials
if (storeResult) coverTests++;
#endif
/* If this test is changed or removed, change ddomega-use.c
to reflect that we could have non-coverage due to some
reason other than "didnt_test" if we haven't got all 0's */
for (j = 1; j <= common_nest; j++) {
if (!dddirtest(dd->direction, ddeq, j)) {
if (omegaPrintResult) {
fprintf(debug2, "coverage unlikely, not bothering to test:\n");
fprintf(debug2, " %s\n", dd_as_string);
}
set_reason(didnt_test);
return 0;
}
}
leading_0s = leading_zeros(dd->direction, dd->nest);
/* PART 1: find sets of variables to be used in problem */
Nrs = Nws = Nsc = 0;
load_bounds_and_count_steps(read_acc, r_vars, rs_vars, &Nrs);
load_bounds_and_count_steps(write_acc, w_vars, ws_vars, &Nws);
load_constants_for_bounds(read_acc, sc_vars, &Nsc);
load_constants_for_bounds(write_acc, sc_vars, &Nsc);
load_constants_for_subscripts(read_acc, sc_vars, &Nsc);
load_constants_for_subscripts(write_acc, sc_vars, &Nsc);
/* PART 2: assign columns to variables
Protect variables representing symbolic constants and
read iteration values of loop indices, because
we wish to test if S implies T for all values of them.*/
read_init(&rpd, &reads, sc_and_r, Nsc, sc_vars,
read_nest, r_vars, Nrs, rs_vars,
write_nest, w_vars, Nws, ws_vars,
0, NIL, 0, NIL);
/* PART 3: build problem */
#if !defined NDEBUG
read_inv(&rpd, &reads);
assert(reads.getNumEqs() == 0);
assert(reads.getNumGEqs() == 0);
eqs = geqs = 0;
#endif
/* TRY TO SET UP RED "T" PROBLEM:
"i in [A] ^ A(i) << B(j) ^ A(i) sub= B(j)"
If we can't completely describe the red problem, we can't
test for cover - set red_complete to 0 to indicate this.
*/
/* i in [A] */
red_complete =
bound_inner_indices_and_conditionals(&reads, &rpd.write1s,
&rpd.w1steps, &rpd.nonloops,
leading_0s, read_acc,
red, write_acc);
if (!red_complete)
{
if (omegaPrintResult) {
fprintf(debug2, "not checking for COVER - incomplete red bounds\n");
fprintf(debug2, "of %s\n", dd_as_string);
}
read_cleanup(&rpd);
set_reason(non_affine_red_bound);
return 0;
}
#if ! defined NDEBUG
read_inv(&rpd, &reads);
#endif
/* A(i) sub= B(j) */
/* equate_sub won't be 0, or there would not be a dependence */
red_complete =
equate_subscripts(&reads, &rpd.reads, &rpd.write1s, &rpd.nonloops,
red, read_acc, write_acc) == complete;
#if ! defined NDEBUG
read_inv(&rpd, &reads);
#endif
if (!red_complete)
{
if (omegaPrintResult) {
fprintf(debug2, "not checking for COVER - incomplete red subscripts\n");
fprintf(debug2, "of %s\n", dd_as_string);
}
read_cleanup(&rpd);
set_reason(non_affine_red_sub);
return 0;
}
/* A(i) << B(j) */
constrain_with_dd(&reads, &rpd.reads, &rpd.write1s, dd, red);
#if !defined NDEBUG
read_inv(&rpd, &reads);
for (; eqs < reads.getNumEqs(); eqs++) {
assert(reads._EQs[eqs].color == red);
}
for (; geqs < reads.getNumGEqs(); geqs++) {
assert(reads._GEQs[geqs].color == red);
}
#endif
/* SET UP BLACK "S" PROBLEM: "j in [B]" */
bound_indices_and_conditionals(&reads, &rpd.reads, &rpd.rsteps,
&rpd.nonloops, black, read_acc);
#if ! defined NDEBUG
read_inv(&rpd, &reads);
for (; eqs < reads.getNumEqs(); eqs++) {
assert(reads._EQs[eqs].color == black);
}
for (; geqs < reads.getNumGEqs(); geqs++) {
assert(reads._GEQs[geqs].color == black);
}
#endif
/* PART 4: clean up */
#if ! defined NDEBUG
read_inv(&rpd, &reads);
#endif
read_cleanup(&rpd);
/* PART 5: CHECK FOR COVERAGE: Forall j, Sym, does S imply T? */
/* there must be a solution to the black equations,
since they represent only j in [B] - if this were not true,
there would be no flow dependencies at all */
if (omegaPrintResult) {
fprintf(debug2, "starting check for COVER\n");
fprintf(debug2, "of %s\n", dd_as_string);
printProblem(&reads);
}
cover = !hasRedEquations(&reads, 0);
if (omegaPrintResult) {
if (cover)
fprintf(debug2, "verified COVER:\n");
else
fprintf(debug2, "no COVER:\n");
printProblem(&reads);
}
#if defined newTimeTrials
if (storeResult) {
realCoverTests++;
if (cover) realCovers++;
}
#endif
set_reason((possible_reasons)cover);
return cover;
}
/*
test to see if dependence terminates its source
(ie an anti-dep from a read to a write termitates the read)
*/
int test_for_termination(a_access read_acc, a_access write_acc,
uint read_nest, uint write_nest, uint common_nest,
dir_and_dist_info *dd, char *dd_as_string)
{
var_id sc_vars[maxVars], r_vars[maxVars], rs_vars[maxVars];
var_id w_vars[maxVars], ws_vars[maxVars];
int Nrs, Nws, Nsc, leading_0s;
read_prob_desc rpd;
Problem reads;
int j, red_complete, termination;
#if ! defined NDEBUG
int eqs, geqs;
#endif
if (access_update_p(write_acc)) {
set_reason(didnt_test);
return(0);
}
assert(write_acc == Entry || access_store_p(write_acc));
#if defined newTimeTrials
if (storeResult) terminationTests++;
#endif
/* If this test is changed or removed, change ddomega-use.c
to reflect that we could have non-termination due to some
reason other than "didnt_test" if we haven't got all 0's */
for (j = 1; j <= common_nest; j++) {
if (!dddirtest(dd->direction, ddeq, j)) {
if (omegaPrintResult) {
fprintf(debug2,
"termination unlikely, not bothering to test:\n");
fprintf(debug2, " %s\n", dd_as_string);
}
set_reason(didnt_test);
return 0;
}
}
leading_0s = leading_zeros(dd->direction, dd->nest);
/* PART 1: find sets of variables to be used in problem */
Nrs = Nws = Nsc = 0;
load_bounds_and_count_steps(read_acc, r_vars, rs_vars, &Nrs);
load_bounds_and_count_steps(write_acc, w_vars, ws_vars, &Nws);
load_constants_for_bounds(read_acc, sc_vars, &Nsc);
load_constants_for_bounds(write_acc, sc_vars, &Nsc);
load_constants_for_subscripts(read_acc, sc_vars, &Nsc);
load_constants_for_subscripts(write_acc, sc_vars, &Nsc);
/* PART 2: assign columns to variables
Protect variables representing symbolic constants and
read iteration values of loop indices, because
we wish to test if S implies T for all values of them.*/
read_init(&rpd, &reads, sc_and_r, Nsc, sc_vars,
read_nest, r_vars, Nrs, rs_vars,
write_nest, w_vars, Nws, ws_vars,
0, NIL, 0, NIL);
/* PART 3: build problem */
#if !defined NDEBUG
read_inv(&rpd, &reads);
assert(reads.getNumEqs() == 0);
assert(reads.getNumGEqs() == 0);
eqs = geqs = 0;
#endif
/* TRY TO SET UP RED "T" PROBLEM:
"j in [B] ^ A(i) << B(j) ^ A(i) sub= B(j)"
If we can't completely describe the red problem, we can't
test for termination - set red_complete to 0 to indicate this.
*/
/* j in [B] */
red_complete =
bound_inner_indices_and_conditionals(&reads, &rpd.write1s,
&rpd.w1steps, &rpd.nonloops,
leading_0s, read_acc,
red, write_acc);
if (!red_complete)
{
if (omegaPrintResult) {
fprintf(debug2,
"not checking for TERMINATION - incomplete red bounds\n");
fprintf(debug2, "of %s\n", dd_as_string);
}
read_cleanup(&rpd);
set_reason(non_affine_red_bound);
return 0;
}
#if ! defined NDEBUG
read_inv(&rpd, &reads);
#endif
/* A(i) sub= B(j) */
/* equate_sub won't be 0, or there would not be a dependence */
red_complete =
equate_subscripts(&reads, &rpd.reads, &rpd.write1s, &rpd.nonloops,
red, read_acc, write_acc) == complete;
if (!red_complete)
{
if (omegaPrintResult) {
fprintf(debug2,
"not checking for TERMINATION - incomplete red subscript\n");
fprintf(debug2, "of %s\n", dd_as_string);
}
read_cleanup(&rpd);
set_reason(non_affine_red_sub);
return 0;
}
#if ! defined NDEBUG
read_inv(&rpd, &reads);
#endif
/* A(i) << B(j) */
constrain_with_dd(&reads, &rpd.write1s, &rpd.reads, dd, red);
#if !defined NDEBUG
read_inv(&rpd, &reads);
for (; eqs < reads.getNumEqs(); eqs++) {
assert(reads._EQs[eqs].color == red);
}
for (; geqs < reads.getNumGEqs(); geqs++) {
assert(reads._GEQs[geqs].color == red);
}
#endif
/* SET UP BLACK "S" PROBLEM: "i in [A]" */
bound_indices_and_conditionals(&reads, &rpd.reads, &rpd.rsteps,
&rpd.nonloops, black, read_acc);
#if ! defined NDEBUG
read_inv(&rpd, &reads);
for (; eqs < reads.getNumEqs(); eqs++) {
assert(reads._EQs[eqs].color == black);
}
for (; geqs < reads.getNumGEqs(); geqs++) {
assert(reads._GEQs[geqs].color == black);
}
#endif
/* PART 4: clean up */
#if ! defined NDEBUG
read_inv(&rpd, &reads);
#endif
read_cleanup(&rpd);
/* PART 5: CHECK FOR TERMINATION: Forall i, Sym, does S imply T? */
/* there must be a solution to the black equations,
since they represent only i in [A] - if this were not true,
there would be no flow dependencies at all */
if (omegaPrintResult) {
fprintf(debug2, "starting check for TERMINATION\n");
fprintf(debug2, "of %s\n", dd_as_string);
printProblem(&reads);
}
termination = !hasRedEquations(&reads, 0);
if (omegaPrintResult) {
if (termination)
fprintf(debug2, "verified TERMINATION.\n");
else
fprintf(debug2, "no TERMINATION.\n");
}
#if defined newTimeTrials
if (storeResult) {
realTerminationTests++;
if (termination) realTerminators++;
}
#endif
set_reason((possible_reasons)termination);
return termination;
}

View File

@@ -0,0 +1,784 @@
/* ddomega-build.c,v 1.1 1993/09/17 22:13:49 fbodin Exp */
/*
Functions that are used in the construction of
an omega test problem from a source program.
*/
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include "include/portable.h"
#include "include/debug.h"
/*
#include "lang-interf.h"
#include "ip.h"
*/
#include "include/affine.h"
#include "include/ddomega-build.h"
#include "include/Exit.h"
var_id *current_set_of_vars;
void init_prob(Problem *p, uint Nvars, uint Nprot,
char *(*getVarName)(unsigned int, void *),
void *getVarNameArgs)
{
initializeProblem(p);
assert(!(Nvars > maxVars));
p->setVarsN(Nvars);
p->_safeVars = Nprot;
p->setNumEqs(0);
p->setNumGEqs(0);
p->_getVarName = getVarName;
p->_getVarNameArgs = getVarNameArgs;
}
/* allocate a new _EQs with uninitialized co-efficients */
/* The touched flag only makes a difference on GEQ's */
uint prob_add_EQ(Problem *p, int color)
{
//++p->_numEQs;
p->addNumEqs(1);
assert(!(p->getNumEqs() > maxEQs));
p->_EQs[p->getNumEqs() - 1].color = color;
return p->getNumEqs() - 1;
}
/* allocate a new _EQs with all co-efficients 0 */
uint prob_add_zero_EQ(Problem *p, int color)
{
uint c;
//c = p->_numEQs++;
c = p->getNumEqs();
p->addNumEqs(1);
assert(!(p->getNumEqs() > maxEQs));
eqnnzero(&p->_EQs[c], p->getVarsN());
p->_EQs[c].color = color;
return c;
}
/* allocate a new _GEQs with uninitialized co-efficients */
uint prob_add_GEQ(Problem *p, int color)
{
p->addNumGEqs(1);
assert(!(p->getNumGEqs() > maxGEQs));
p->_GEQs[p->getNumGEqs() - 1].touched = 1;
p->_GEQs[p->getNumGEqs() - 1].color = color;
return p->getNumGEqs() - 1;
}
/* allocate a new _GEQs with all co-efficients 0 */
uint prob_add_zero_GEQ(Problem *p, int color)
{
uint c;
//c = p->_numGEQs++;
c = p->getNumGEqs();
p->addNumGEqs(1);
assert(!(p->getNumGEqs() > maxGEQs));
eqnnzero(&p->_GEQs[c], p->getVarsN());
p->_GEQs[c].touched = 1;
p->_GEQs[c].color = color;
return c;
}
/* delta = access1 - access2, so for flow dep, delta = write - read */
void set_deltas(Problem *p, int delta_color, range *deltas, range *a1, range *a2)
{
uint e, c;
assert(r_length(deltas) <= r_length(a1) && r_length(deltas) <= r_length(a2));
for (e = 0; e < r_length(deltas); e++) {
c = prob_add_zero_EQ(p, delta_color);
p->_EQs[c].coef[e + r_first(deltas)] = 1;
p->_EQs[c].coef[e + r_first(a1)] = 1;
p->_EQs[c].coef[e + r_first(a2)] = -1;
}
}
/*
Constrain a problem with the minimal constraints needed to
enforce the direction vector in dd.
Use restraint vector unless it is not convex
It is also tempting to use the or the direction vector instead
if it is "=", but that does not seem to speed things up (?)
The loss of speed is less significant if we test for eqs
in constrain_with_convex_dddir below.
*/
void constrain_with_dd(Problem *pr, range *dd_to, range *dd_from,
dir_and_dist_info *dd, int color)
{
int j;
for (j = 1; j <= dd->nest; j++) {
int thisr;
thisr = ddextract1(dd->restraint, j);
if (((thisr&ddgt) && (thisr&ddlt) && !(thisr&ddeq)) /* restr = "+-" */
|| (ddextract1(dd->direction, j) == ddeq)) /* direc = "0" */
{
constrain_with_convex_dddir(pr, dd_to, dd_from,
&dd->direction, j, color);
}
else {
constrain_with_convex_dddir(pr, dd_to, dd_from,
&dd->restraint, j, color);
}
}
}
/*
Constrain *pr with the DIRECTION vector in dd.
*/
void constrain_with_dddirs(Problem *pr, range *dd_to, range *dd_from,
dir_and_dist_info *dd, int color)
{
int j;
for (j = 1; j <= dd->nest; j++) {
constrain_with_convex_dddir(pr, dd_to, dd_from,
&dd->direction, j, color);
}
}
/*
Constrain *pr with dimension j of *dir.
Use equations of color "color".
*/
void constrain_with_convex_dddir(Problem *pr, range *dd_to, range *dd_from,
dddirection *dir, int j, int color)
{
int e;
if (ddextract1(*dir, j) == ddeq)
{
e = prob_add_zero_EQ(pr, color);
pr->_EQs[e].coef[r_first(dd_to) - 1 + j] = -1;
pr->_EQs[e].coef[r_first(dd_from) - 1 + j] = 1;
return;
}
if (!dddirtest(*dir, ddlt, j))
{
/* no +, so dd_to - dd_from <= 0 or < 0
ie, dd_from - dd_to >= 0 or > 0
ie, dd_from - dd_to >= 0 or ... -1 >= 0 */
e = prob_add_zero_GEQ(pr, color);
pr->_GEQs[e].coef[r_first(dd_to) - 1 + j] = -1;
pr->_GEQs[e].coef[r_first(dd_from) - 1 + j] = 1;
pr->_GEQs[e].coef[0] = -!dddirtest(*dir, ddeq, j);
}
if (!dddirtest(*dir, ddgt, j))
{
/* no -, so dd_to - dd_from >= 0 or > 0
ie, dd_to - dd_from >= 0 or ... -1 >= 0 */
e = prob_add_zero_GEQ(pr, color);
pr->_GEQs[e].coef[r_first(dd_to) - 1 + j] = 1;
pr->_GEQs[e].coef[r_first(dd_from) - 1 + j] = -1;
pr->_GEQs[e].coef[0] = -!dddirtest(*dir, ddeq, j);
}
}
/*
For each term in ae, add sign * its co-efficient to e.
Declarations of symbolic constants must have been tagged with
their column number already
Colunm numbers of indices are their depth + r_first(indices)
*/
static void add_coefficients(Eqn e, range *indices, int sign, affine_expr *ae)
{
int v;
assert(ae->terms[0].tiny_var == NIL);
e->coef[0] += sign * ae->terms[0].coefficient;
for (v = 1; v < ae->nterms; v++) {
if (var_id_index_p(ae->terms[v].tiny_var)) { /* index */
int loop = var_ids_loop_no(ae->terms[v].tiny_var);
e->coef[r_first(indices) - 1 + loop] +=
sign * ae->terms[v].coefficient;
}
else { /* sym. const */
assert(var_id_const_p(ae->terms[v].tiny_var));
e->coef[var_ids_tag(ae->terms[v].tiny_var)] +=
sign * ae->terms[v].coefficient;
}
}
}
/* for the lower bound, lb <= i === i - lb >= 0
for the upper bound, i <= ub === -i + ub >= 0
define bound types so that establish_one_bound works out...
*/
typedef enum { upper = 1, lower = -1 } which_bound;
/* return 1 if boundable, 0 if not affine */
static int
establish_one_bound(Problem *p, int color,
range *indices, which_bound b,
affine_expr *ae, uint depth)
{
if (!is_affine(ae))
return 0;
while (ae != NIL) {
uint c; /* new constraint */
assert(is_affine(ae));
c = prob_add_zero_GEQ(p, color);
add_coefficients(&p->_GEQs[c], indices, b, ae);
//assert(p->_GEQs[c].coef[r_first(indices) - 1 + depth] == 0);
if (p->_GEQs[c].coef[r_first(indices) - 1 + depth] != 0)
return 0;
p->_GEQs[c].coef[r_first(indices) - 1 + depth] = -b;
ae = ae->other_branch;
}
return 1;
}
/*
start_expr should point to the 1st expression taken on by the loop
return 1 if bound, 0 if not
*/
static int
handle_nonunit_increments(Problem *p, range *indices, int *which_step, int color, loop_context l, sint incr, uint depth)
{
affine_expr *start_expr = loop_start(l);
assert(incr >= 1); /* can't handle any others yet */
if (abs(incr) == 1)
return 1;
/* if lower bound is linear AND HAS NO "MAX"
add the constraint: index = lower_bound + gensym * step
otherwise, don't add any new constraints, unless color == red */
assert(start_expr != NIL);
if (is_affine(start_expr) && start_expr->other_branch == NIL)
{
int c, v, i2;
c = prob_add_zero_EQ(p, color);
add_coefficients(&p->_EQs[c], indices, 1, start_expr);
/* we now have the EQ "lower_bound = 0" */
//assert(p->_EQs[c].coef[r_first(indices) - 1 + depth] == 0);
if (p->_EQs[c].coef[r_first(indices) - 1 + depth] != 0)
return 0;
p->_EQs[c].coef[r_first(indices) - 1 + depth] = -1;
/* we now have the EQ "lower_bound - index = 0" */
/* we can reduce the co-efficients to their value mod(step),
since we're adding gensym()*step */
i2 = incr / 2;
for (v = 1; v <= p->getVarsN(); v++) {
int tmp = intMod(p->_EQs[c].coef[v], incr);
if (tmp > i2) tmp -= incr;
p->_EQs[c].coef[v] = tmp;
}
p->_EQs[c].coef[*which_step] = incr;
(*which_step)++;
return 1;
}
else {
return 0;
}
}
/* Create constraints in prob for the loop index whose dolimit
is pointed to by limits.
May add one or more(min or max) upper and lower constraints
May add an equality constraint if the increment != 0
return 1 if completely bound, 0 if we had any non-affine stuff
*/
static int bound_index(Problem *p, int color, loop_context limits, range *indices, range *non_i, int *which_step, uint depth)
{
sint incr;
bool known;
incr = 1; known = 1;
if (loop_has_step_p(limits)) {
/* there is an increment expression */
loops_step(limits, &incr, &known);
}
if (!(known && incr >= 1))
ErrAssert("DO loop step must be positive");
if (known) {
if (incr > 0) {
int l, u, i;
l = establish_one_bound(p, color, indices, lower, loop_start(limits), depth);
u = establish_one_bound(p, color, indices, upper, loop_end(limits), depth);
i = handle_nonunit_increments(p, indices, which_step, color, limits, incr, depth);
return l && u && i;
}
else if (incr < 0) {
/* assertion checking is off */
int l, u, i;
fprintf(stderr, "can't handle negative step yet\n");
Exit(2);
l = establish_one_bound(p, color, indices, lower, loop_end(limits), depth);
u = establish_one_bound(p, color, indices, upper, loop_start(limits), depth);
i = handle_nonunit_increments(p, indices, which_step, color, limits, incr, depth);
return l && u && i;
}
else {
/* assertion checking is off */
fprintf(stderr, "What do you mean by having a step of 0? What are you, stupid?\n");
Exit(1);
return 0;
}
}
else {
/* assertion checking is off */
fprintf(stderr, "can't handle unknown step\n");
Exit(2);
return 0;
}
}
/* Create constraints in problem for the conditional.
May add any number of GEQ or EQ constraints
return 1 if completely bound, 0 if we had any non-affine stuff
This initial version only works with the puny subset of conditionals
described in affine.c, and is tiny-specific.
A conservative tiny-free alternative is to just return 0.
*/
static struct {
int lhs_sign;
int rhs_sign;
int constant;
} conditionals[4] = {
{ 1, -1, -1 }, /* gt */
{ 1, -1, 0 }, /* ge */
{ -1, 1, -1 }, /* lt */
{ -1, 1, 0 } /* le */
};
#define N_ELEMENTS(ARRAY) ( sizeof(ARRAY)/sizeof(ARRAY[0]) )
static int
puny_bound_condition(Problem *p, int color, if_context cond,
range *indices, range *non_i)
{
if (if_condition_ok(cond))
{
int c, kind;
kind = if_compare_op(cond);
if (kind < 0 || kind >= N_ELEMENTS(conditionals)) {
assert(!"What the heck? How did that get to be affine?");
return 0;
}
if (if_else_branch(cond)) {
kind = N_ELEMENTS(conditionals) - kind;
}
else {
#if ! defined NOT_TINY
assert(cond->nodeop == op_then ||
cond->nodeparent->nodeop == op_assert);
#endif
}
c = prob_add_zero_GEQ(p, color);
add_coefficients(&p->_GEQs[c], indices, conditionals[kind].lhs_sign,
if_compare_left(cond));
add_coefficients(&p->_GEQs[c], indices, conditionals[kind].rhs_sign,
if_compare_right(cond));
p->_GEQs[c].coef[0] += conditionals[kind].constant;
#if ! defined NOT_TINY
assert(!cond->nodeparent->nodeaffine->other_branch->other_branch);
#endif
return 1;
}
else {
return 0;
}
}
/* Establish bounds for the loop indices and conditionals
that enclose node n.
If we come across a non-affine expression return 0.
If we successfully bound everything return 1.
Note that we finish doing all the bounds we can,
in either case, so zapping will work well.
Assume that "outer" outer loops have been taken care of
in some other way - i.e. that we are building the red
part of some problem which represents a dependence with
"outer" leading 0's, so we will take care of these
variables by setting them equal to the black loop indices.
If "skip_outer_ifs_containing_me" is non-nil, any ifs
that are within exactly "outer" loops and contain it.
This corresponds to the situation:
for1
for2
if1 then
if2a then
access a
endif
if2b then
access skip_outer_ifs_containing_me
endif
endif
endfor
endfor
in which we want to skip if1 when bounding a in the 0,0 dependence
from a to skip_outer_ifs_containing_me. Note that we don't have to
distinguish between the then & else parts, as we can't have a 0,0
if one access is is each.
*/
int
bound_inner_indices_and_conditionals(Problem *p,
range *indices, range *steps, range *non_i,
int outer, a_access skip_outer_ifs_containing_me,
int color, a_access a)
{
int result;
int which_step = r_first(steps);
context_iterator c;
if (a == Entry || a == ExitNode)
return(1);
c = cont_i_for_access(a);
result = 1;
while (!cont_i_done(c))
{
if (cont_i_cur_loop_p(c)) {
if (cont_i_cur_depth(c) <= outer)
return result;
#if ! defined NOT_TINY
assert(do_op(c->nodeparent->nodeop));
#endif
if (!bound_index(p, color, cont_i_cur_loop(c),
indices, non_i, &which_step,
cont_i_cur_depth(c)))
{
assert(which_step <= r_last(steps) + 1);
result = 0;
}
}
else {
assert(cont_i_cur_if_p(c));
#if ! defined NOT_TINY
assert(c->nodeparent->nodeop == op_if);
#endif
if (!(skip_outer_ifs_containing_me
&& cont_i_cur_depth(c) <= outer
&& access_is_in_then_or_else_of(skip_outer_ifs_containing_me, c))
&& !puny_bound_condition(p, color, cont_i_cur_if(c),
indices, non_i))
{
result = 0;
}
}
cont_i_next(c);
}
assert(which_step <= r_last(steps) + 1);
#if ! defined NOT_TINY
for (c = Assertions; c; c = c->nodelink)
{
assert(c->nodeop == op_assert);
if (!puny_bound_condition(p, color, c->nodechild, indices, non_i))
{
result = 0;
}
}
#endif
return result;
}
/* adjust the problem to include equality of subscript expressions at
nodes access1 and access2. Index variables for access1 are looked
up in range i1, and those for access2 in range i2. The non-index
variables are looked up in the range non_i.
returns 0 if subscripts could not possibly be equal.
In this case, we may not finish adding the equalities.
returns 1 if the conditions for their equality have been completely
described by the constraints added to p
returns 2 if there was a non-affine expression, in which case the
constraints added to p must be true for equality (but they
may also be true for some non-equal cases). If color==red,
we FINISH trying to bound subscripts (for zapping).
*/
equate_descr equate_subscripts(Problem *p, range *i1, range *i2, range *non_i,
int color, a_access access1, a_access access2)
{
sub_iterator sub1, sub2;
int is_complete = complete;
if (access1 == Entry || access1 == ExitNode ||
access2 == Entry || access2 == ExitNode)
return (equate_descr)1;
/* we assume children of the node are subscripts,
so scalars MUST have no nodechildren
assert(array_op(access1->nodeop) || access1->nodechild == NIL);
*/
sub1 = sub_i_for_access(access1);
sub2 = sub_i_for_access(access2);
while (!sub_i_done(sub1))
{
assert(!sub_i_done(sub2)); /* must have same # of subscripts */
assert(sub_i_cur_affine(sub1) != NIL && sub_i_cur_affine(sub2) != NIL);
if (sub_i_cur_is_affine(sub1) && sub_i_cur_is_affine(sub2)) {
uint c; /* new constraint # */
int i;
assert((sub_i_cur_affine(sub1)->other_branch == NIL) &&
(sub_i_cur_affine(sub2)->other_branch == NIL));
c = prob_add_zero_EQ(p, color);
add_coefficients(&p->_EQs[c], i1, 1, sub_i_cur_affine(sub1));
add_coefficients(&p->_EQs[c], i2, -1, sub_i_cur_affine(sub2));
for (i = p->getVarsN(); i > 0; i--)
if (p->_EQs[c].coef[i] != 0)
break;
if (i == 0) { /* linearity = 0 */
if (p->_EQs[c].coef[0] != 0)
return not_possible; /* never equal */
//p->_numEQs--; /* always equal: don't add equation */
p->addNumEqs(-1);
}
}
else {
is_complete = partial;
}
sub_i_next(sub1);
sub_i_next(sub2);
}
assert(sub_i_done(sub2)); /* must have same # of subscripts */
return (equate_descr)is_complete;
}
/* postcondition: n < maxVars */
static void NeedNVars(int n)
{
if (n >= maxVars) {
fprintf(debug2, "Out of Omega variables\n");
Exit(2);
}
}
/* set bounds[1...depth(n)] to point to the dolimits of the loops containing n
set *Nsteps to the # of loops that have step expressions
set steps[0 ... *Nsteps - 1] to NIL
*/
void load_bounds_and_count_steps(a_access a, var_id bounds[],
var_id steps[], int *Nsteps)
{
context_iterator c;
if (a == Entry || a == ExitNode)
return;
c = cont_i_for_access(a);
while (!cont_i_done(c))
{
if (cont_i_cur_loop_p(c)) {
bounds[cont_i_cur_depth(c)] = loop_var_id(cont_i_cur_loop(c));
if (loop_has_step_p(cont_i_cur_loop(c))) {
/* handle step */
NeedNVars(*Nsteps);
steps[*Nsteps] = 0;
(*Nsteps)++;
}
}
else {
assert(cont_i_cur_if_p(c));
/* handle if trivially - no new bounds or steps */
}
cont_i_next(c);
}
}
typedef struct {
var_id *consts;
int *Nconsts;
} const_stuff;
static void load_a_const(var_id v, void *args)
{
const_stuff *cs = (const_stuff *)args;
if (var_id_const_p(v)) {
/* not a loop index */
if (var_ids_tag(v) == UNTAGGED)
{
NeedNVars(*cs->Nconsts);
var_ids_tag(v) = *cs->Nconsts;
cs->consts[(*cs->Nconsts)++] = v;
}
else {
assert(cs->consts[var_ids_tag(v)] == v);
}
}
else {
assert(var_id_index_p(v));
}
}
#if 0
static void load_consts_for_expr(node *expr, var_id consts[], int *Nconsts)
{
node *nn;
for (nn = expr; nn != NIL; nn = nn->nodenext) {
assert(!array_op(nn->nodeop));
switch (nn->nodeop) {
case op_fetch:
case op_store:
if (get_nodevalue_node(nn)->nodeop == op_declare) {
/* not a loop index */
if (get_nodevalue_sym(get_nodevalue_node(nn))->symtag
== UNTAGGED)
{
NeedNVars(*Nconsts);
get_nodevalue_sym(get_nodevalue_node(nn))->symtag
= *Nconsts;
consts[(*Nconsts)++] =
get_nodevalue_sym(get_nodevalue_node(nn));
}
else {
assert(consts[get_nodevalue_sym(get_nodevalue_node(nn))
->symtag]
== get_nodevalue_sym(get_nodevalue_node(nn)));
}
}
else {
assert(get_nodevalue_node(nn)->nodeop == op_dolimit);
}
break;
default:
load_consts_for_expr(nn->nodechild, consts, Nconsts);
}
}
}
#endif
/* ensure that all symbolic constants used in affine subscript
expressions appear in consts[0..*Nconsts-1], and that they
are tagged with their indices.
If called with a scalar, do nothing
*/
void load_constants_for_subscripts(a_access a, var_id consts[], int *Nconsts)
{
const_stuff cs;
sub_iterator sub;
if (a == Entry || a == ExitNode)
return;
cs.consts = consts;
cs.Nconsts = Nconsts;
sub = sub_i_for_access(a);
while (!sub_i_done(sub)) {
sub_i_map_over_cur_vars(sub, &load_a_const, &cs);
sub_i_next(sub);
}
}
/* same for affine expressions used in loop bounds of loops surrounding n */
void load_constants_for_bounds(a_access a, var_id consts[], int *Nconsts)
{
const_stuff cs;
context_iterator c;
if (a == Entry || a == ExitNode)
return;
cs.consts = consts;
cs.Nconsts = Nconsts;
c = cont_i_for_access(a);
while (!cont_i_done(c))
{
if (cont_i_cur_loop_p(c)) {
loop_map_over_start_vars(cont_i_cur_loop(c), &load_a_const, &cs);
loop_map_over_end_vars(cont_i_cur_loop(c), &load_a_const, &cs);
}
else {
assert(cont_i_cur_if_p(c));
if_map_over_vars(cont_i_cur_if(c), &load_a_const, &cs);
}
cont_i_next(c);
}
#if ! defined NOT_TINY
for (c = Assertions; c; c = c->nodelink) {
if_map_over_vars(c->nodechild, &load_a_const, &cs);
}
#endif
}

View File

@@ -0,0 +1,865 @@
/* ddomega-use.c,v 1.1 1993/09/17 22:13:50 fbodin Exp */
/*
calls to omega test to determine data dependencies from a problem
(as defined in ddomega.c & built by the code in ddomega-build.c)
*/
#include <assert.h>
#include "include/portable.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "include/debug.h"
#include "include/lang-interf.h"
#include "include/ip.h"
#include "include/ddomega-build.h"
#include "include/ddomega-use.h"
#include "include/ddomega.h"
#include "include/omega2flags.h"
#include "include/refine.h"
#include "include/cover.h"
#include "include/missing.h"
#include "include/Exit.h"
#include "include/timeTrials.h"
/* information about nodes involved in dependence */
typedef struct {
a_access access1, access2;
ddnature oitype, iotype;
uint nest1, nest2, commonNesting;
} situation;
void out_of_memory()
{
fprintf(debug2, "Memory Allocation failed\n");
Exit(2);
}
static dddirection dd_convert[] = { ddgt, ddeq, ddlt };
/* dd_convert(i+1) is dddirection for i */
#if !defined SPEED
static char *dir_and_dist_as_str(dir_and_dist_info *d_info, ddnature type, a_access from_access, a_access to_access)
{
static char buf[TINYBUFSIZ];
char f[TINYBUFSIZ];
uint n, l, l0;
char ch;
dddirection thisdd;
strcpy(f, access_as_string(from_access));
{ char *ss;
switch (type) {
case ddflow: ss = "flow"; break;
case ddanti: ss = "anti"; break;
case ddoutput: ss = "output"; break;
case ddreduce: ss = "reduce"; break;
default: ss = ""; /* make compiler happy */
ErrAssert("dir_and_dist_as_str: wrong dependence type");
}
sprintf(buf, "%-6s %3ld: %-15.15s --> %3ld: %-15.15s ", ss,
accesss_lineno(from_access), f,
accesss_lineno(to_access), access_as_string(to_access));
}
l0 = l = strlen(buf);
ch = '(';
for (n = 1; n <= d_info->nest; ++n) {
buf[l++] = ch;
ch = ',';
thisdd = ddextract1(d_info->direction, n);
if (d_info->distanceKnown[n]) {
sprintf(&(buf[l]), "%ld", d_info->distance[n]);
l = strlen(buf);
}
else if (thisdd == ddlt + ddeq + ddgt) {
buf[l++] = '*';
}
else {
if (ddtest1(thisdd, ddeq)) buf[l++] = '0';
if (ddtest1(thisdd, ddlt)) buf[l++] = '+';
if (ddtest1(thisdd, ddgt)) buf[l++] = '-';
}
}
if (d_info->nest > 0)
buf[l++] = ')';
while (l < l0 + 18)
buf[l++] = ' ';
buf[l] = 0;
append_dd_flags(buf, d_info->direction);
return buf;
}
#endif
/*
do refinement, cover, and termination tests, set appropriate flags,
then store dependence.
*/
static void
flag_and_store_dependence(ddnature nature,
a_access from_access, a_access to_access,
dir_and_dist_info *d_info)
{
store_dependence(nature, from_access, to_access, d_info);
if (!skipping_omega2) {
#if !defined SPEED
char *str = dir_and_dist_as_str(d_info, nature, from_access, to_access);
#else
char *str = "Tiny must be compiled without -DSPEED for debug2 output";
#endif
if ((nature == ddflow || nature == ddoutput) &&
from_access != Entry && to_access != ExitNode)
{
int covers, j;
covers = test_for_coverage(from_access, to_access,
accesss_depth(from_access),
accesss_depth(to_access),
d_info->nest, d_info, str);
assert(covers < 2);
if (!covers && because(non_affine_red_bound)) {
/* see if all 0's covers */
dir_and_dist_info new_info = *d_info;
#if !defined SPEED
char *str2 = dir_and_dist_as_str(d_info, nature,
from_access, to_access);
#else
char *str2 = "Tiny must be compiled without -DSPEED for debug2 output";
#endif
new_info.nest = d_info->nest;
for (j = 1; j <= new_info.nest; j++)
{
assert(dddirtest(d_info->direction, ddeq, j));
/* otherwise we would have no cover because 'didnt_test' */
dddirsetonly(new_info.direction, ddeq, j);
dddirsetonly(new_info.restraint, ddeq, j);
new_info.distanceKnown[j] = 1;
new_info.distance[j] = 0;
}
if (test_for_coverage(from_access, to_access,
accesss_depth(from_access),
accesss_depth(to_access),
new_info.nest, &new_info, str2))
{
if (!(d_info->direction & ddrefined))
clone_dd_graph_node_for_refinement(d_info->dd_graph_node_to_be_cloned);
*d_info = new_info;
d_info->direction |= ddrefined;
covers = 2;
}
}
if (covers)
{
d_info->direction |= ddcovers;
if (covers != 2 && !skipping_all_tightening &&
(!skipping_o_a_tightening || nature == ddflow))
{
tighten_cover(from_access, to_access, d_info, str);
}
accesss_cover_depth(to_access) = MAX(accesss_cover_depth(to_access), dd_carried_by(d_info->direction, d_info->nest) - 1);
}
}
if ((nature == ddoutput || nature == ddanti) &&
from_access != ExitNode && to_access != Entry)
{
int terminates, j;
terminates = test_for_termination(from_access, to_access,
accesss_depth(from_access),
accesss_depth(to_access),
d_info->nest, d_info, str);
assert(terminates < 2);
if (!terminates && because(non_affine_red_bound)) {
/* see if all 0's terminates */
dir_and_dist_info new_info = *d_info;
#if !defined SPEED
char *str2 = dir_and_dist_as_str(d_info, nature, from_access, to_access);
#else
char *str2 = "Tiny must be compiled without -DSPEED for debug2 output";
#endif
new_info.nest = d_info->nest;
for (j = 1; j <= new_info.nest; j++)
{
assert(dddirtest(d_info->direction, ddeq, j));
/* otherwise we would have no cover because 'didnt_test' */
dddirsetonly(new_info.direction, ddeq, j);
dddirsetonly(new_info.restraint, ddeq, j);
new_info.distanceKnown[j] = 1;
new_info.distance[j] = 0;
}
if (test_for_termination(from_access, to_access,
accesss_depth(from_access),
accesss_depth(to_access),
new_info.nest, &new_info, str2))
{
if (!(d_info->direction & ddrefined))
clone_dd_graph_node_for_refinement(d_info->dd_graph_node_to_be_cloned);
*d_info = new_info;
d_info->direction |= ddrefined;
terminates = 2;
}
}
if (terminates)
{
d_info->direction |= ddterminates;
if (terminates != 2 && !skipping_o_a_tightening &&
!skipping_all_tightening)
{
tighten_terminator(from_access, to_access, d_info, str);
}
accesss_terminator_depth(from_access) = MAX(accesss_terminator_depth(from_access), dd_carried_by(d_info->direction, d_info->nest) - 1);
}
}
#if !defined NDEBUG
d_info_inv(d_info);
#endif
/* copy all the changes into the ddnode */
#if defined newTimeTrials
if (storeResult)
dir_and_dist_into_ddnode(d_info,
d_info->dd_graph_node_to_be_cloned);
#else
dir_and_dist_into_ddnode(d_info, d_info->dd_graph_node_to_be_cloned);
#endif
}
#if defined newTimeTrials
if (!storeResult)
return;
else
stores++;
#endif
}
/* split a set of flow, anti, or output dependencies into
pieces that are all forward in time
if we have a situation with an exposed 0+ followed
by an exposed -,
then filterValid will call itself recursively to split
the 0+ into 0 and + (eliminating the 0...- case)
else filterValid will store only one dependency
these dependeces are passed to flag_and_store_dependence.
*/
static void
filterValid(ddnature nature, a_access from_access, a_access to_access,
int commonNesting, dir_and_dist_info *d_info, int allEQallowed)
{
int less_at, j;
int forbidden;
/*
* For private variables: -- vadik 11/05/92
* dependencies can not be carried by loops-privatizers
*/
if (from_access != Entry && from_access != ExitNode &&
to_access != ExitNode && to_access != Entry &&
access_private_var_p(from_access))
{
int PrivLev = access_private_var_level(from_access);
assert(PrivLev <= commonNesting);
for (j = 1; j <= PrivLev; j++) {
dddirreset(d_info->direction, ddlt | ddgt, j);
if (!dddirtest(d_info->direction, ddgt | ddlt | ddeq, j))
return;
dddirreset(d_info->restraint, ddlt | ddgt, j);
d_info->distance[j] = 0;
d_info->distanceKnown[j] = 1;
}
}
#if 0
/*
* Reduction dependences aren't forward or backward in time,
* so they all are valid by default ??? -- vadik
* However, we have to ignore (0,0,...,0) reduction dependences.
*/
if (nature == ddreduce) {
for (j = 1; j <= commonNesting; ++j) {
if (dddirtest(d_info->direction, ddlt | ddgt, j))
break;
}
if (j <= commonNesting || from_access != to_access) {
flag_and_store_dependence(nature, from_access, to_access, d_info);
}
return;
}
#endif
/* remove all -'s before 1st + */
for (j = 1; j <= commonNesting; ++j) {
if (!dddirtest(d_info->direction, ddlt | ddeq, j))
return;
if (dddirtest(d_info->direction, ddgt, j)) {
dddirreset(d_info->direction, ddgt, j);
d_info_do_eq(d_info, j);
dddirreset(d_info->restraint, ddgt, j);
}
if (dddirtest(d_info->direction, ddlt, j)) break;
}
/* check for all 0's or no common Nesting */
less_at = j;
if (less_at > commonNesting) {
if (allEQallowed) {
flag_and_store_dependence(nature, from_access, to_access, d_info);
}
return;
}
/* if we start with 0+ rather than just +, check for possible all 0's */
if (dddirtest(d_info->direction, ddeq, less_at)) {
for (j = less_at + 1;
j <= commonNesting && !dddirtest(d_info->direction, ddlt | ddgt, j);
j++);
if (j <= commonNesting && !dddirtest(d_info->direction, ddlt | ddeq, j))
{
/* we have some 0's, a 0+, more 0's, then a - so, 0+ -> just + */
dddirreset(d_info->direction, ddeq, less_at);
dddirreset(d_info->restraint, ddeq, less_at);
}
else {
/* we have some 0's, a 0+, more 0's,
then either 0- or something with a + */
forbidden = !allEQallowed;
for (j = commonNesting; j >= less_at; j--) {
forbidden = dddirtest(d_info->direction, ddgt, j) ||
(dddirtest(d_info->direction, ddeq, j) && forbidden);
/* "forbidden" = some loop outside j must
force this dependence to go strictly forward in time */
}
if (forbidden) {
/* split into leading 0 vs. leading + */
dir_and_dist_info plus, zero;
plus = zero = *d_info;
dddirreset(plus.direction, ddeq, less_at);
dddirreset(plus.restraint, ddeq, less_at);
dddirreset(zero.direction, ddlt, less_at);
dddirreset(zero.restraint, ddlt, less_at);
zero.distance[less_at] = 0;
zero.distanceKnown[less_at] = 1;
filterValid(nature, from_access, to_access, commonNesting,
&plus, allEQallowed);
filterValid(nature, from_access, to_access, commonNesting,
&zero, allEQallowed);
return;
}
}
}
flag_and_store_dependence(nature, from_access, to_access, d_info);
if (omegaPrintResult == 1) {
fprintf(debug2, ">>>>>>>>>>>>>>>>>>>>>>>> (");
for (j = 1; j <= commonNesting; j++) {
if (dddirtest(d_info->restraint, ddeq, j)) fprintf(debug2, "0");
if (dddirtest(d_info->restraint, ddlt, j)) fprintf(debug2, "+");
if (dddirtest(d_info->restraint, ddgt, j)) fprintf(debug2, "-");
if (j < commonNesting) fprintf(debug2, ",");
}
fprintf(debug2, ")\n");
fprintf(debug2, "------------------------ (");
for (j = 1; j <= commonNesting; j++) {
if (dddirtest(d_info->direction, ddeq, j)) fprintf(debug2, "0");
if (dddirtest(d_info->direction, ddlt, j)) fprintf(debug2, "+");
if (dddirtest(d_info->direction, ddgt, j)) fprintf(debug2, "-");
if (j < commonNesting) fprintf(debug2, ",");
}
fprintf(debug2, ")\n");
}
}
static void dd_to_debug(dir_and_dist_info *d_info)
{
int j;
fprintf(debug2, "(");
for (j = 1; j <= d_info->nest; j++) {
if (d_info->distanceKnown[j])
fprintf(debug2, "%d", d_info->distance[j]);
else if (ddextract1(d_info->direction, j) == ddall)
fprintf(debug2, "*");
else {
if (dddirtest(d_info->direction, ddeq, j)) fprintf(debug2, "0");
if (dddirtest(d_info->direction, ddlt, j)) fprintf(debug2, "+");
if (dddirtest(d_info->direction, ddgt, j)) fprintf(debug2, "-");
}
if (j < d_info->nest) fprintf(debug2, ",");
}
fprintf(debug2, ") restraint = (");
for (j = 1; j <= d_info->nest; j++) {
if (ddextract1(d_info->restraint, j) == ddall)
fprintf(debug2, "*");
else {
if (dddirtest(d_info->restraint, ddeq, j)) fprintf(debug2, "0");
if (dddirtest(d_info->restraint, ddlt, j)) fprintf(debug2, "+");
if (dddirtest(d_info->restraint, ddgt, j)) fprintf(debug2, "-");
}
if (j < d_info->nest) fprintf(debug2, ",");
}
fprintf(debug2, ")");
}
/*
call filterValid for the dependence from access1 to access2,
and if they are distinct, for the dependence the other way.
*/
static void noteDependence(situation *sit, dir_and_dist_info *d_info)
{
dddirection deq, dgt, dlt, req, rgt, rlt;
dir_and_dist_info backward;
int j;
backward.dd_graph_node_to_be_cloned = 0;
deq = ddfilter(d_info->direction, ddeq);
dlt = ddfilter(d_info->direction, ddlt);
dgt = ddfilter(d_info->direction, ddgt);
req = ddfilter(d_info->restraint, ddeq);
rlt = ddfilter(d_info->restraint, ddlt);
rgt = ddfilter(d_info->restraint, ddgt);
if (sit->access1 != sit->access2) {
backward.direction = backward.restraint = 0;
ddsetfilter(backward.direction, deq, ddeq);
ddsetfilter(backward.direction, dlt, ddgt);
ddsetfilter(backward.direction, dgt, ddlt);
ddsetfilter(backward.restraint, req, ddeq);
ddsetfilter(backward.restraint, rlt, ddgt);
ddsetfilter(backward.restraint, rgt, ddlt);
backward.nest = d_info->nest;
for (j = 1; j <= sit->commonNesting; ++j) {
backward.distanceKnown[j] = d_info->distanceKnown[j];
if (backward.distanceKnown[j])
backward.distance[j] = -d_info->distance[j];
}
}
filterValid(sit->oitype, sit->access1, sit->access2,
sit->commonNesting, d_info,
access_lexically_preceeds(sit->access1, sit->access2));
if (omegaPrintResult == 1) {
fprintf(debug2, "%%%%%%%%%%%%%%%%%%%%%%%% ");
dd_to_debug(d_info);
fprintf(debug2, "\n");
}
if (sit->access1 != sit->access2) {
filterValid(sit->iotype, sit->access2, sit->access1,
sit->commonNesting, &backward,
access_lexically_preceeds(sit->access2, sit->access1));
if (omegaPrintResult == 1) {
fprintf(debug2, "%%%%%%%% backward %%%%%% ");
dd_to_debug(&backward);
fprintf(debug2, "\n");
}
}
} /* noteDependence */
/* info used during construction */
typedef struct {
int unknownDirection[maxCommonNest];
int unknownDirections;
} unknowns;
/*
process the omega test problem into dependence vectors
if dependencies are not coupled, just read them out.
else break into cases for each possible dependence in (+,0,-)
in each dimension by doing a recursive call
each time a dependence vector is found, call noteDependence to store it
*/
static void
findDirectionVector(Problem * prob, situation *sit,
dir_and_dist_info *d_info, unknowns *u_info)
{
int i, j;
int l, u, coupled;
int l2, u2, best, score, bestScore;
int unprotectThese[maxCommonNest];
int numToUnprotect = 0;
int simplificationNeeded = u_info->unknownDirections == 0;
int initialUnknownDirections = u_info->unknownDirections;
u2 = 2;
l2 = -2;
bestScore = 10000;
best = -1; /* keep compiler from complaining, allow later assertion */
for (i = 0; i < u_info->unknownDirections; i++) {
j = u_info->unknownDirection[i];
d_info->distanceKnown[j] = 0;
coupled = queryVariable(prob, j, &l, &u);
if (l == u) {
d_info->distanceKnown[j] = 1;
d_info->distance[j] = l;
}
else {
if (l > 1) l = 1;
else if (l < -1) l = -1;
if (u < -1) u = -1;
else if (u > 1) u = 1;
}
if (!coupled || l == u) {
dddirsetonly(d_info->direction, 0, j);
if (l < 0) dddirset(d_info->direction, ddgt, j);
if (l <= 0 && 0 <= u) dddirset(d_info->direction, ddeq, j);
if (0 < u) dddirset(d_info->direction, ddlt, j);
d_info_do_eq(d_info, j);
unprotectThese[numToUnprotect++] = j;
u_info->unknownDirection[i] =
u_info->unknownDirection[--u_info->unknownDirections];
i--;
if (coupled) simplificationNeeded = 1;
}
else if (coupled && initialUnknownDirections == 1
&& prob->getVarsN() + prob->getNumSUBs() == 2
&& prob->getNumEqs() + prob->getNumSUBs() == 1)
{
dddirsetonly(d_info->direction,
queryVariableSigns(prob, j,
ddlt, ddeq, ddgt,
negInfinity, posInfinity,
&(d_info->distanceKnown[j]),
&(d_info->distance[j])),
j);
d_info_do_eq(d_info, j);
noteDependence(sit, d_info);
return;
}
else {
score = 2 * (u - l) + j;
if (prob->getVarsN() > 1 && prob->forwardingAddress[j] > 0)
score -= 3;
if (score <= bestScore) {
u2 = u;
l2 = l;
best = j;
bestScore = score;
}
}
}
if (u_info->unknownDirections == 0) {
prob->_safeVars = 0;
prob->setNumSUBs(0);
if (!simplificationNeeded || solve(prob, UNKNOWN))
noteDependence(sit, d_info);
}
else {
for (i = 0; i < numToUnprotect; i++) {
j = unprotectThese[i];
unprotectVariable(prob, j);
}
if (simplificationNeeded ||
(u_info->unknownDirections == 1 && initialUnknownDirections > 1))
{
simplifyProblem(prob);
findDirectionVector(prob, sit, d_info, u_info);
}
else {
int s;
int oldUnknownDirections;
int oldUnknownDirection[maxCommonNest];
if (u_info->unknownDirections == 2
&& prob->getVarsN() == 1
&& prob->getNumSUBs() == 1)
{
i = u_info->unknownDirection[0];
j = u_info->unknownDirection[1];
if (prob->forwardingAddress[i] != -1) {
int t;
t = i;
i = j;
j = t;
}
if (prob->forwardingAddress[i] == -1
&& prob->forwardingAddress[j] == 1)
{
int j1, j2, j3, i1, i2, i3;
j1 = ddlt;
i1 = queryVariableSigns(prob, i,
ddlt, ddeq, ddgt, 1, posInfinity,
&(d_info->distanceKnown[i]),
&(d_info->distance[i]));
if (d_info->distanceKnown[i]) {
dddirsetonly(d_info->direction, i1, i);
dddirsetonly(d_info->direction, j1, j);
/* dddirsetonly(d_info->restraint, i1, i);not needed */
dddirsetonly(d_info->restraint, j1, j);
noteDependence(sit, d_info);
i1 = 0;
}
j2 = ddeq;
i2 = queryVariableSigns(prob, i, ddlt, ddeq, ddgt, 0, 0,
&(d_info->distanceKnown[i]),
&(d_info->distance[i]));
if (d_info->distanceKnown[i]) {
int oldDistj = d_info->distance[j];
bool oldDistKj = d_info->distanceKnown[j];
dddirsetonly(d_info->direction, i2, i);
dddirsetonly(d_info->direction, j2, j);
assert(j2 == ddeq);
d_info->distanceKnown[j] = 1;
d_info->distance[j] = 0;
/* dddirsetonly(d_info->restraint, i2, i);not needed */
dddirsetonly(d_info->restraint, j2, j);
noteDependence(sit, d_info);
i2 = 0;
d_info->distanceKnown[j] = oldDistKj;
d_info->distance[j] = oldDistj;
}
j3 = ddgt;
i3 = queryVariableSigns(prob, i,
ddlt, ddeq, ddgt, negInfinity, -1,
&(d_info->distanceKnown[i]),
&(d_info->distance[i]));
if (d_info->distanceKnown[i]) {
dddirsetonly(d_info->direction, i3, i);
dddirsetonly(d_info->direction, j3, j);
/* dddirsetonly(d_info->restraint, i3, i);not needed */
dddirsetonly(d_info->restraint, j3, j);
noteDependence(sit, d_info);
i3 = 0;
}
d_info->distanceKnown[i] = 0;
if (i3 == i2) {
j2 |= j3;
i3 = 0;
}
if (i2 == i1) {
j1 |= j2;
i2 = 0;
}
if (i3 == i1) {
j1 |= j3;
i3 = 0;
}
if (i1) {
bool oldDisti = d_info->distance[i];
bool oldDistKi = d_info->distanceKnown[i];
bool oldDistj = d_info->distance[j];
bool oldDistKj = d_info->distanceKnown[j];
dddirsetonly(d_info->direction, i1, i);
dddirsetonly(d_info->direction, j1, j);
/* dddirsetonly(d_info->restraint, i1, i);not needed */
dddirsetonly(d_info->restraint, j1, j);
d_info_do_eq(d_info, i);
d_info_do_eq(d_info, j);
noteDependence(sit, d_info);
d_info->distanceKnown[i] = oldDistKi;
if (oldDistKi) d_info->distance[i] = oldDisti;
d_info->distanceKnown[j] = oldDistKj;
if (oldDistKj) d_info->distance[j] = oldDistj;
}
if (i2) {
bool oldDisti = d_info->distance[i];
bool oldDistKi = d_info->distanceKnown[i];
bool oldDistj = d_info->distance[j];
bool oldDistKj = d_info->distanceKnown[j];
dddirsetonly(d_info->direction, i2, i);
dddirsetonly(d_info->direction, j2, j);
/* dddirsetonly(d_info->restraint, i2, i);not needed */
dddirsetonly(d_info->restraint, j2, j);
d_info_do_eq(d_info, i);
d_info_do_eq(d_info, j);
noteDependence(sit, d_info);
d_info->distanceKnown[i] = oldDistKi;
if (oldDistKi) d_info->distance[i] = oldDisti;
d_info->distanceKnown[j] = oldDistKj;
if (oldDistKj) d_info->distance[j] = oldDistj;
}
if (i3) {
bool oldDisti = d_info->distance[i];
bool oldDistKi = d_info->distanceKnown[i];
bool oldDistj = d_info->distance[j];
bool oldDistKj = d_info->distanceKnown[j];
dddirsetonly(d_info->direction, i3, i);
dddirsetonly(d_info->direction, j3, j);
/* dddirsetonly(d_info->restraint, i3, i);not needed */
dddirsetonly(d_info->restraint, j3, j);
d_info_do_eq(d_info, i);
d_info_do_eq(d_info, j);
noteDependence(sit, d_info);
d_info->distanceKnown[i] = oldDistKi;
if (oldDistKi) d_info->distance[i] = oldDisti;
d_info->distanceKnown[j] = oldDistKj;
if (oldDistKj) d_info->distance[j] = oldDistj;
}
return;
}
}
assert(best >= 0);
if (omegaPrintResult == 1)
fprintf(debug2,
"doing recursive analysis of %d..%d on var %s (#%d)\n",
l2, u2,
(*prob->_getVarName)(best, prob->_getVarNameArgs), best);
j = best;
i = 0;
while (u_info->unknownDirection[i] != j)
i++;
u_info->unknownDirection[i] =
u_info->unknownDirection[--u_info->unknownDirections];
oldUnknownDirections = u_info->unknownDirections;
for (i = 0; i < u_info->unknownDirections; i++)
oldUnknownDirection[i] = u_info->unknownDirection[i];
for (s = l2; s <= u2; s++) {
Problem tmpProblem;
dddirection oldDirection = d_info->direction;
dddirection oldRestraint = d_info->restraint;
int oldDistj = d_info->distance[j];
int oldDistKj = d_info->distanceKnown[j];
problemcpy(&tmpProblem, prob);
if (omegaPrintResult == 1)
fprintf(debug2, "considering sign = %d of %s (%d)\n", s,
(*prob->_getVarName)(best, prob->_getVarNameArgs),
best);
if (s == 0) {
d_info->distance[j] = 0;
d_info->distanceKnown[j] = 1;
}
else {
d_info->distanceKnown[j] = 0;
}
dddirsetonly(d_info->direction, dd_convert[s + 1], j);
dddirsetonly(d_info->restraint, dd_convert[s + 1], j);
d_info_inv(d_info);
if (constrainVariableSign(&tmpProblem, black, j, s))
findDirectionVector(&tmpProblem, sit, d_info, u_info);
if (s < u2) {
d_info->direction = oldDirection;
d_info->restraint = oldRestraint;
d_info->distance[j] = oldDistj;
d_info->distanceKnown[j] = oldDistKj;
d_info->dd_graph_node_to_be_cloned = 0;
u_info->unknownDirections = oldUnknownDirections;
for (i = 0; i < u_info->unknownDirections; i++)
u_info->unknownDirection[i] = oldUnknownDirection[i];
}
}
}
}
} /* findDirectionVector */
/*
calculateDDVectors just calls findDirectionVector now.
The arrays dddir[] and dddist[] need to have at least
maxnest+1 spaces allocated
*/
extern int nonConvex;
void calculateDDVectors(Problem *problemPtr, a_access access1, a_access access2,
ddnature oitype, ddnature iotype,
uint nest1, uint nest2, uint bnest, uint nonloops)
{
int i;
situation sit;
unknowns u_info;
dir_and_dist_info d_info;
d_info.dd_graph_node_to_be_cloned = 0;
d_info.nest = bnest;
u_info.unknownDirections = bnest;
for (i = 0; i < u_info.unknownDirections; i++)
u_info.unknownDirection[i] = i + 1;
#if defined newTimeTrials
if (storeResult) {
int e;
int reducable = ((problemPtr->_safeVars) == 1);
int coupledSubstitutions = 0;
int coupled = 0;
int nonUnary = 0;
for (e = problemPtr->_numSUBs - 1; e >= 0; e--)
if (problemPtr->_SUBs[e].coef[0] != 0)
reducable = 0;
for (e = problemPtr->_numGEQs - 1; e >= 0; e--) {
if (!singleVarGEQ(problemPtr->_GEQs[e], problemPtr->_nVars))
coupled = 1;
for (i = problemPtr->_nVars; i > 0; i--)
if (problemPtr->_GEQs[e].coef[i] > 1
|| problemPtr->_GEQs[e].coef[i] < -1)
nonUnary = 1;
};
for (e = problemPtr->_numSUBs - 1; e >= 0; e--) {
for (i = problemPtr->_nVars; i > 0; i--)
if (problemPtr->_SUBs[e].coef[i] != 0)
coupledSubstitutions = 1;
};
ddCategory[0] = 0;
if (reducable)
strncat(ddCategory, "r ", TINYBUFSIZ);
if (coupledSubstitutions)
strncat(ddCategory, "s ", TINYBUFSIZ);
if (coupled)
strncat(ddCategory, "c ", TINYBUFSIZ);
if (nonUnary)
strncat(ddCategory, "u ", TINYBUFSIZ);
if (nonConvex)
strncat(ddCategory, "v ", TINYBUFSIZ);
}
#endif
sit.access1 = access1;
sit.access2 = access2;
sit.oitype = oitype;
sit.iotype = iotype;
sit.nest1 = nest1;
sit.nest2 = nest2;
sit.commonNesting = bnest;
d_info.direction = 0;
d_info.restraint = -1;
/* d_info built by findDirectionVector */
findDirectionVector(problemPtr, &sit, &d_info, &u_info);
}

View File

@@ -0,0 +1,371 @@
/* ddomega.c,v 1.1 1993/09/17 22:13:51 fbodin Exp */
/*
Basic data dependence test using the omega test -
dd_omega_test determines if two array accesses might access the same element
Also, functions to manipulate the structures used to
represent various sorts of problems that we pass to the
omega test.
Naming convention: Many of these functions and structures
refer to "read iteration" or "write iteration" as if a
test were being performed on flow dependence(s), even when
the test works for other forms of dependence.
*/
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "include/flags.h"
#include "include/portable.h"
#include "include/debug.h"
#include "include/ip.h"
#include "include/lang-interf.h"
#include "include/ddomega-build.h"
#include "include/ddomega-use.h"
#include "include/ddomega.h"
#include "include/Exit.h"
#include "include/timeTrials.h"
Problem deltas; /* original problem -- needed in refine */
/*
perform the omega test on the array accesses access1 and access2
see dddriver.h for a description of arguments.
* Entry -> fetch/update dependencies.
* write/update -> ExitNode dependencies.
* Added by vadik 11/08/92.
*/
PROC void dd_omega_test(a_access access1, a_access access2, ddnature oitype, ddnature iotype, uint nest1, uint nest2, uint bnest)
{
Problem prob;
delta_prob_desc dpd; /* must have extent >= that of "prob" */
int subs_may_equal;
#if defined newTimeTrials
if (storeResult) omegaTests++;
#endif
assert(access1 == Entry || access2 == ExitNode ||
accesss_sym(access2) == accesss_sym(access1)); /* same var */
assert(!(access_fetch_p(access1) && access_store_p(access2)));
assert(oitype != ddanti);
/* if omitTopLevel, we are only interested in parallelizing loops,
and thus don't care about data dependencies between things
that don't share any common loops */
if (omitTopLevel && bnest == 0)
{
dir_and_dist_info d_info;
d_info.nest = 0;
d_info.dd_graph_node_to_be_cloned = 0;
if (access_lexically_preceeds(access1, access2))
{
store_dependence(oitype, access1, access2, &d_info);
}
else if (access_lexically_preceeds(access2, access1))
{
store_dependence(iotype, access2, access1, &d_info);
}
/* else access1 == access2 or they're in different branches of an if */
return;
}
subs_may_equal = build_delta_prob_desc(&dpd, &prob, access1, access2,
nest1, nest2, bnest);
if (omegaPrintResult == 1) {
fprintf(debug2, "\n\nconsidering dependency:\n");
fprintf(debug2, "\tfrom a %s of %s at statement %d\n",
access_store_p(access1) || access1 == Entry ? "store" :
(access_fetch_p(access1) ? "read" : "update"),
access_as_string(access1), accesss_lineno(access1));
fprintf(debug2, "\tto a %s of %s at statement %d\n",
access_store_p(access2) ? "store" :
(access_fetch_p(access2) || access2 == ExitNode ? "read" : "update"),
access_as_string(access2), accesss_lineno(access2));
printProblem(&prob);
}
if (subs_may_equal && simplifyProblem(&prob)) {
/* call omega test to add directions */
calculateDDVectors(&prob, access1, access2, oitype, iotype,
nest1, nest2, bnest, r_length(&dpd.nonloops));
}
#if defined newTimeTrials
if (storeResult) realOmegaTests++;
#endif
}/* dd_omega_test */
/* functions used to build "delta problem description" */
int build_delta_prob_desc(delta_prob_desc *dpd, Problem *prob,
a_access access1, a_access access2,
int nest1, int nest2, int bnest)
{
var_id consts[maxVars],
vars1[maxVars], vars2[maxVars],
steps1[maxVars], steps2[maxVars];
int Nconsts, Nsteps1, Nsteps2, subs_may_equal;
/* PART 1: find sets of variables to be used in problem */
Nsteps1 = Nsteps2 = Nconsts = 0;
load_bounds_and_count_steps(access1, vars1, steps1, &Nsteps1);
load_bounds_and_count_steps(access2, vars2, steps2, &Nsteps2);
load_constants_for_bounds(access1, consts, &Nconsts);
load_constants_for_bounds(access2, consts, &Nconsts);
load_constants_for_subscripts(access1, consts, &Nconsts);
load_constants_for_subscripts(access2, consts, &Nconsts);
/* PART 2: assign columns to variables */
delta_init(dpd, prob, black, bnest,
nest1, vars1, nest2, vars2, Nconsts, consts,
Nsteps1, steps1, Nsteps2, steps2);
assert(bnest == prob->_safeVars);
/* PART 3: build problem */
bound_indices_and_conditionals(prob, &dpd->access1s, &dpd->steps1,
&dpd->nonloops,
black, access1);
bound_indices_and_conditionals(prob, &dpd->access2s, &dpd->steps2,
&dpd->nonloops,
black, access2);
subs_may_equal = equate_subscripts(prob, &dpd->access1s, &dpd->access2s,
&dpd->nonloops,
black, access1, access2);
/* PART 4: clean up */
#if ! defined NDEBUG
delta_inv(dpd, prob);
#endif
delta_cleanup(dpd);
return subs_may_equal;
}
/* name information for buffers in getVarName fns */
#define MaxNameLen 254
#define MaxSuffixLen 1
#if ! defined NDEBUG
static int var_id_is_step_expr(var_id n)
{
return n == 0;
}
void delta_inv(delta_prob_desc *dpd, Problem *p)
{
int v;
assert(p->getVarsN() < maxVars);
assert(p->getVarsN() >= delta_Nvars(dpd));
assert(p->_safeVars == r_length(&dpd->deltas));
assert(r_length(&dpd->deltas) <= r_length(&dpd->access1s));
assert(r_length(&dpd->deltas) <= r_length(&dpd->access2s));
assert(r_first(&dpd->deltas) == 1);
assert(r_last(&dpd->deltas) + 1 == r_first(&dpd->access1s));
assert(r_last(&dpd->access1s) + 1 == r_first(&dpd->access2s));
assert(r_last(&dpd->access2s) + 1 == r_first(&dpd->nonloops));
assert(r_last(&dpd->nonloops) + 1 == r_first(&dpd->steps1));
assert(r_last(&dpd->steps1) + 1 == r_first(&dpd->steps2));
for (v = 0; v < r_length(&dpd->deltas); v++) {
assert(var_id_index_p(dpd->vars[v + r_first(&dpd->deltas)]));
assert(var_ids_loop_no(dpd->vars[v + r_first(&dpd->deltas)]) == v + 1);
assert(var_id_index_p(dpd->vars[v + r_first(&dpd->access1s)]));
assert(var_ids_loop_no(dpd->vars[v + r_first(&dpd->access1s)]) == v + 1);
assert(var_id_index_p(dpd->vars[v + r_first(&dpd->access2s)]));
assert(var_ids_loop_no(dpd->vars[v + r_first(&dpd->access2s)]) == v + 1);
}
for (v = r_length(&dpd->deltas); v < r_length(&dpd->access1s); v++) {
assert(var_id_index_p(dpd->vars[v + r_first(&dpd->access1s)]));
assert(var_ids_loop_no(dpd->vars[v + r_first(&dpd->access1s)]) == v + 1);
}
for (v = r_length(&dpd->deltas); v < r_length(&dpd->access2s); v++) {
assert(var_id_index_p(dpd->vars[v + r_first(&dpd->access2s)]));
assert(var_ids_loop_no(dpd->vars[v + r_first(&dpd->access2s)]) == v + 1);
}
for (v = 0; v < r_length(&dpd->nonloops); v++) {
assert(var_id_const_p(dpd->vars[v + r_first(&dpd->nonloops)]));
assert((var_ids_tag(dpd->vars[v + r_first(&dpd->nonloops)]) ==
v + r_first(&dpd->nonloops)) ||
(var_ids_tag(dpd->vars[v + r_first(&dpd->nonloops)]) == UNTAGGED));
}
for (v = 0; v < r_length(&dpd->steps1); v++) {
assert(var_id_is_step_expr(dpd->vars[v + r_first(&dpd->steps1)]));
}
for (v = 0; v < r_length(&dpd->steps2); v++) {
assert(var_id_is_step_expr(dpd->vars[v + r_first(&dpd->steps2)]));
}
for (v = 0; v < p->getNumGEqs(); v++) {
assert(p->_GEQs[v].touched);
}
}
#endif
static char *delta_getVarName(uint v, void *args)
{
delta_prob_desc *dpd = (delta_prob_desc*)args;
static char name[MaxNameLen + MaxSuffixLen + 1];
assert(v <= delta_Nvars(dpd));
if (dpd->vars[v] &&
(var_id_index_p(dpd->vars[v]) || var_id_const_p(dpd->vars[v])))
{
strncpy(name, var_ids_name(dpd->vars[v]), MaxNameLen);
name[MaxNameLen] = 0;
}
else {
assert(var_id_is_step_expr(dpd->vars[v]));
strcpy(name, "<trip>");
}
if (r_in(&dpd->deltas, v))
strcat(name, "^");
else if (r_in(&dpd->access1s, v) || r_in(&dpd->steps1, v))
strcat(name, "1");
else if (r_in(&dpd->access2s, v) || r_in(&dpd->steps2, v))
strcat(name, "2");
return name;
}
/*
set up all fields in delta_prob_desc
copy info from a1_vars, a2_vars, and sc_vars into "omega_vars"
a1_vars and a2_vars have been set by load_bounds_and_count_steps
that is, they run from element 1 to depth+Nsteps
sc_vars have been set up by the load_constants functions
it runs from 0 to Nconsts - 1
change tags on nodes for symbolic constants to be the
indices into "vars" -- that is, the indices in the IP variable array
change order of steps to be outer loop to inner and
adjust tags accordingly (this way the common loop steps
can (and will) be aligned)
add equalities for the definitions of the deltas to p
*/
void delta_init(delta_prob_desc *dpd, Problem *p,
int delta_color, uint Nd,
uint Na1, var_id a1_vars[],
uint Na2, var_id a2_vars[],
uint Nsc, var_id sc_vars[],
uint Ns1, var_id s1_vars[],
uint Ns2, var_id s2_vars[])
{
int v;
dpd->deltas._first = 1;
dpd->deltas._length = Nd;
dpd->access1s._first = 1 + Nd;
dpd->access1s._length = Na1;
dpd->access2s._first = 1 + Nd + Na1;
dpd->access2s._length = Na2;
dpd->nonloops._first = 1 + Nd + Na1 + Na2;
dpd->nonloops._length = Nsc;
dpd->steps1._first = 1 + Nd + Na1 + Na2 + Nsc;
dpd->steps1._length = Ns1;
dpd->steps2._first = 1 + Nd + Na1 + Na2 + Nsc + Ns1;
dpd->steps2._length = Ns2;
if (delta_Nvars(dpd) > maxVars) {
assert(0 && "Problem too big");
fprintf(stderr, "Too many variables for omega test\n");
Exit(2);
/* We really should add all possible dependencies here */
}
dpd->vars[0] = 0;
/* a1[1..Na1] and a2[1..Na2] are valid */
for (v = 0; v < r_length(&dpd->deltas); v++) {
assert(a1_vars[v + 1] == a2_vars[v + 1]);
assert(a1_vars[v + 1] != NIL);
dpd->vars[v + r_first(&dpd->deltas)] =
dpd->vars[v + r_first(&dpd->access1s)] =
dpd->vars[v + r_first(&dpd->access2s)] = a1_vars[v + 1];
}
for (v = r_length(&dpd->deltas); v < r_length(&dpd->access1s); v++) {
assert(a1_vars[v + 1] != NIL);
dpd->vars[v + r_first(&dpd->access1s)] = a1_vars[v + 1];
}
for (v = r_length(&dpd->deltas); v < r_length(&dpd->access2s); v++) {
assert(a2_vars[v + 1] != NIL);
dpd->vars[v + r_first(&dpd->access2s)] = a2_vars[v + 1];
}
/* sc_vars[0..Nsc-1] are valid */
for (v = 0; v < Nsc; v++) {
assert(sc_vars[v] != NIL);
dpd->vars[v + r_first(&dpd->nonloops)] = sc_vars[v];
var_ids_tag(sc_vars[v]) = v + r_first(&dpd->nonloops);
}
/* s1_vars[0..Ns1] and s2_vars[0..Ns2] hold steps
FROM INNERMOST TO OUTERMOST LOOPS */
for (v = 0; v < Ns1; v++) {
assert(s1_vars[Ns1 - 1 - v] == NIL);
dpd->vars[v + r_first(&dpd->steps1)] = s1_vars[Ns1 - 1 - v];
}
for (v = 0; v < Ns2; v++) {
assert(s2_vars[Ns2 - 1 - v] == NIL);
dpd->vars[v + r_first(&dpd->steps2)] = s2_vars[Ns2 - 1 - v];
}
init_prob(p, delta_Nvars(dpd), r_length(&dpd->deltas), delta_getVarName, dpd);
set_deltas(p, delta_color, &dpd->deltas, &dpd->access1s, &dpd->access2s);
#if ! defined NDEBUG
delta_inv(dpd, p);
#endif
}
/* clear the tags for symbolic constants */
void delta_cleanup(delta_prob_desc *dpd)
{
int v;
for (v = 0; v < r_length(&dpd->nonloops); v++) {
var_ids_tag(dpd->vars[v + r_first(&dpd->nonloops)]) = UNTAGGED;
}
}

View File

@@ -0,0 +1,16 @@
/* debug.c,v 1.1.1.2 1992/07/10 02:42:51 davew Exp */
#include "include/portable.h"
#include <stdio.h>
#include "include/debug.h"
#include "include/missing.h"
int n_strange_occurances = 0;
FILE *debug2;
void strange_occurance(char *message)
{
n_strange_occurances++;
fprintf(debug2, message);
}

View File

@@ -0,0 +1,14 @@
void Message_Add(char * str);
void Exit(int c);
void ErrAssert(char *t);
#ifdef MIN
#undef MIN
#endif
#ifdef MAX
#undef MAX
#endif
static int inline MIN(int X, int Y) { return ((X) < (Y) ? (X) : (Y)); }
static int inline MAX(int X, int Y) { return ((X) > (Y) ? (X) : (Y)); }

View File

@@ -0,0 +1,12 @@
/* add-assert.h,v 1.1 1993/09/17 22:14:04 fbodin Exp */
#ifndef Already_Included_AddAssert
#define Already_Included_AddAssert 1
#include "portable.h"
#include "lang-interf.h"
typedef enum { impossible, possible, too_hard } elimination_possible;
elimination_possible possible_to_eliminate(dd_current dd);
#endif

View File

@@ -0,0 +1,52 @@
/* affine.h,v 1.1 1993/09/17 22:14:06 fbodin Exp */
#ifndef Already_Included_Affine
#define Already_Included_Affine 1
#include "lang-interf.h"
#include "ip.h"
/* This file defines the affine_expr structure and macros & functions
that are independent of tiny - that is, code that examines existing
affine expressions. Code that builds affine expressions from the
parse tree, or part of the parse tree, is in find_affine.h, as that
code is tiny-specific.
*/
typedef struct {
var_id tiny_var; /* pointer to symbol table entry */
int coefficient; /* co-efficient */
} affine_term;
typedef struct _affine_expr {
int nterms;
affine_term terms[maxVars]; /* 1st entry var is always 0 */
struct _affine_expr *other_branch; /* if min or max */
} affine_expr;
#define is_affine(AE) ( (AE) != &not_affine )
#define node_is_affine(NODE) ( (NODE)->nodeaffine != (void *)&not_affine )
extern bool nodes_subs_are_affine(a_access A);
/* the above is needed only for one assertion - for some
array access A, return true iff all subscripts of A are affine */
#ifdef __cplusplus
extern "C" affine_expr not_affine;
#else
extern affine_expr not_affine;
#endif
/* affine_expr should point to not_affine if expression is not affine */
/* compare 2 affine exprs.
return 1 if different, 0 if same
*/
int CmpAffineExprs(affine_expr *, affine_expr *);
/* return a copy allocated with malloc */
affine_expr *CopyAffineExpr(affine_expr *);
void FreeAffineExpr(affine_expr *);
#endif

View File

@@ -0,0 +1,36 @@
/* cover.h,v 1.1 1993/09/17 22:14:07 fbodin Exp */
#ifndef Already_Included_cover
#define Already_Included_cover
/*
test to see if a dependence covers to_acc
can be used for flow or output dependences
*/
int test_for_coverage(a_access from_acc, a_access to_acc,
uint from_nest, uint to_nest, uint common_nest,
dir_and_dist_info *dd, char *dd_as_string);
/*
test to see if a dependence terminates from_acc
can be used for output or anti dependences
*/
int test_for_termination(a_access from_acc, a_access to_acc,
uint from_nest, uint to_nest, uint common_nest,
dir_and_dist_info *dd, char *dd_as_string);
typedef enum { really_not_there = 0,
really_there = 1,
didnt_test,
non_affine_red_bound,
non_affine_red_sub } possible_reasons;
extern possible_reasons why_no_cover_or_terminator;
#define set_reason(X) (why_no_cover_or_terminator = (X))
#define because(X) (why_no_cover_or_terminator == (X))
/* use: if (!cover(...))
if(because(non_affine_red)) ...
*/
#endif

View File

@@ -0,0 +1,69 @@
typedef long unsigned int dddirection;
/* directions: */
#define ddlt (dddirection)0x1
#define ddeq (dddirection)0x2
#define ddgt (dddirection)0x4
#define ddall (dddirection)0x7
#define ddrr (dddirection)0x8
#define ddne (dddirection)0xd
#define ddanydir (dddirection)0xf
/* #define ddeqeq (dddirection)0x10000000 unused */
#define ddallnone (dddirection)0
#define ddcovers (dddirection)0x80000000
#define ddterminates (dddirection)0x40000000
#define ddrefined (dddirection)0x20000000
#define ddisCovered (dddirection)0x10000000
#define ddisTerminated (dddirection)0x08000000
#define ddisRefined (dddirection)0x04000000 /* what dd was before refine */
#define ddkilled (dddirection)0x02000000
#define ddzappableWC (dddirection)0x01000000
#define ddzappable (dddirection)0x00800000
#define dddirBits (dddirection)0x00777777
/* added new flags 2/92 - 3/92 davew@cs.umd.edu */
/* test to see if a dd has been killed by a kill or cover */
#define ddisDead(d) ((d) & (ddkilled | ddisCovered | ddisTerminated| ddisRefined))
/* shift a direction 'd' to appropriate position for nest 'n' */
#define dddirnest(d,n) ((d)<<(((n)-1)*4))
/* test if direction vector 'dv' has direction 'd' set at nest 'n' */
#define dddirtest(dv,d,n) ((dv)&dddirnest(d,n))
/* test if direction vector 'dv' all-equal bit set */
#define ddeqtest(dv) ((dv)&(ddallequal))
/* return direction vector except for direction n */
#define ddallBut(dv,n) ((dv)&(dddirBits & ~dddirnest(ddall,n)))
/* set direction 'd' at nest 'dv' for nest 'n' */
#define dddirset(dv,d,n) (dv|=dddirnest(d,n))
/* reset all directions at nest 'n' in 'dv' except for 'd' */
#define dddironly(dv,d,n) (dv=(((dv)&~dddirnest(ddanydir,n))|((dv)&dddirnest(d,n))))
/* reset all directions at nest 'n' in 'dv', then set 'd' */
#define dddirsetonly(dv,d,n) (dv=(((dv)&~dddirnest(ddanydir,n))|(dddirnest(d,n))))
/* set all-equal bit in 'dv' */
#define ddeqset(dv) (dv|=(ddallequal))
/* reset direction 'd' at nest 'n' in 'dv' */
#define dddirreset(dv,d,n) (dv&=(~dddirnest(d,n)))
/* reset all-equal bit in 'dv' */
#define ddeqreset(dv) (dv&=(~(ddallequal)))
/* extract direction vector element at nest 'n' from 'dv' */
#define ddextract1(dv,n) (((dv)>>(((n)-1)*4))&0xF)
/* test direction 'd' in extracted direction vector element 'dv' */
#define ddtest1(dv,d) ((dv)&(d))
/* reset direction 'd' in extracted direction vector element 'dv' */
#define ddreset1(dv,d) (dv&=(~(d)))
/* set direction 'd' in extracted direction vector element 'dv' */
#define ddset1(dv,d) (dv|=(d))
/* filter all direction vector elements with direction 'd' set in 'dv' */
#define ddfilter(dv,d) (((dv)&((d)|(d<<4)|(d<<8)|(d<<12)|(d<<16)|(d<<20)|(d<<24)))/d)
/* set all filtered direction vector elements to direction 'd' */
#define ddsetfilter(dv,f,d) (dv|=((f)*(d)))
/* unknown distance */
#define ddunknown (dddirection)0x80000000
/* return the depth of the loop that carries dv, or the length+1 for loop ind.
dv has only the 0 bit set at levels [1 .. dd_carried_by(dv, length(dv))]
*/
extern int dd_carried_by(dddirection dv, int length);
extern int leading_zeros(dddirection dv, int length);
extern void append_dd_flags(char *, dddirection dv);
/* code for the above is currently in ddodriver.c */

View File

@@ -0,0 +1,148 @@
/* ddomega-build.h,v 1.1 1993/09/17 22:14:08 fbodin Exp */
#ifndef Already_Included_DDOmega_Build
#define Already_Included_DDOmega_Build
#include "range.h"
#include "ip.h"
/* adjust the problem to include equality of subscript expressions at
nodes access1 and access2. Index variables for access1 are looked
up in range i1, and those for access2 in range i2. The non-index
variables are looked up in the range non_i.
returns 0 if subscripts could not possibly be equal
returns 1 if the conditions for their equality have been completely
described by the constraints added to p
returns 2 if there was a non-affine expression, in which case the
constraints added to p must be true for equality (but they
may also be true for some non-equal cases). If color==red,
we stop trying to bound subscripts immediately.
*/
typedef enum { not_possible = 0, complete = 1, partial = 2 } equate_descr;
equate_descr equate_subscripts(Problem *p, range *i1, range *i2, range *non_i,
int color, a_access access1, a_access access2);
/* Establish bounds for the loop indices and conditionals
that enclose node n.
If we come across a non-affine expression return 0.
If we successfully bound everything return 1.
Note that we finish doing all the bounds we can,
in either case, so zapping will work well.
Assume that "outer" outer loops have been taken care of
in some other way - i.e. that we are building the red
part of some problem which represents a dependence with
"outer" leading 0's, so we will take care of these
variables by setting them equal to the black loop indices.
If "skip_outer_ifs_containing_me" is non-nil, any ifs
that are within exactly "outer" loops and contain it in
either the "then" or "else" code.
This corresponds to the situation:
for1
for2
if1 then
if2a then
access a
endif
if2b then
access skip_outer_ifs_containing_me
endif
endif
endfor
endfor
in which we want to skip if1 when bounding a in the 0,0 dependence
from a to skip_outer_ifs_containing_me. Note that we don't have to
distinguish between the then & else parts, as we can't have a 0,0
if one access is is each.
*/
int
bound_inner_indices_and_conditionals(Problem *p,
range *indices,range *steps,range *non_i,
int outer, a_access skip_outer_ifs_containing_me,
int color, a_access a);
#define bound_indices_and_conditionals(P,IND,ST,NONI,COL,A) \
bound_inner_indices_and_conditionals(P,IND,ST,NONI,0,NULL,COL,A)
/* in the functions below,
var_id points to op_declare for symbolic constants,
op_dolimit for index variables
or some sort of expression for iteration #'s
in 1st & 2nd cases, node's value points to S.T. entry */
/* set bounds[1...depth(n)] to point to the dolimits of the loops containing n
set *Nsteps to the # of loops that have step expressions
set steps[0 ... *Nsteps - 1] to point to these step expressions
also set the nodetag field of any step expressions to their index
into the steps array. Steps for inner loops come first in "steps".
*/
void load_bounds_and_count_steps(a_access n, var_id bounds[],
var_id steps[], int *Nsteps);
/* ensure that all symbolic constants used in affine subscript
expressions appear in consts[0..*Nconsts-1], and that they
are tagged with their indices.
*Nconsts should be set before calling this function
*/
void load_constants_for_subscripts(a_access access,
var_id consts[], int *Nconsts);
/* same for affine expressions used in loop bounds of loops surrounding n
*Nconsts should be set before calling this function
*/
void load_constants_for_bounds(a_access n, var_id consts[], int *Nconsts);
/* low-level more problem manipulation functions */
void init_prob(Problem *p, uint Nvars, uint Nprot,
char *(*getVarName)(unsigned int, void *),
void *getVarNameArgs);
uint prob_add_EQ(Problem *p, int color);
uint prob_add_zero_EQ(Problem *p, int color);
uint prob_add_GEQ(Problem *p, int color);
uint prob_add_zero_GEQ(Problem *p, int color);
/* delta = access1 - access2, so for flow dep, delta = write - read */
void set_deltas(Problem *p, int delta_color,
range *deltas, range *a1, range *a2);
/*
Constrain a problem with the minimal constraints needed to
enforce the direction vector in dd.
Use restraint vector unless it is not convex or the direction
vector is "=".
*/
void constrain_with_dd(Problem *pr, range *dd_to, range *dd_from,
dir_and_dist_info *dd, int color);
/*
Constrain *pr with the direction vector in dd.
*/
void constrain_with_dddirs(Problem *pr, range *dd_to, range *dd_from,
dir_and_dist_info *dd, int color);
/*
*dir MUST NOT BE +-
Constrain *pr with dimension j of *dir.
Use equations of color "color".
It handles 0 by adding both var[j] >= 0 and var[j] <= 0,
which is not bad, because red equalities are just converted back
to pairs of inequalities anyway. Perhaps it would be better to
add special case code for black 0's.
*/
void constrain_with_convex_dddir(Problem *pr, range *dd_to, range *dd_from,
dddirection *dir, int j, int color);
#endif

View File

@@ -0,0 +1,12 @@
/* ddomega-use.h,v 1.1 1993/09/17 22:14:09 fbodin Exp */
#ifndef Already_Included_DDOmega_Use
#define Already_Included_DDOmega_Use
/* compute DD vectors, add them to nodes */
void calculateDDVectors(Problem *problemPtr, a_access access1,a_access access2,
ddnature oitype, ddnature iotype,
uint nest1, uint nest2, uint bnest, uint nonloops);
#endif

View File

@@ -0,0 +1,77 @@
/* ddomega.h,v 1.1 1993/09/17 22:14:10 fbodin Exp */
/*
This file now contains only the main dependence test function.
see refine.h, cover.h, and kill.h for the other functions that
used to be declared here.
The structures used in these functions are now also declared here.
*/
#ifndef Already_Included_DDOmega
#define Already_Included_DDOmega
/*
perform the omega test on the array accesses access1 and access2
see dddriver.h for a description of "dd" arguments.
*/
void dd_omega_test(a_access access1, a_access access2,
ddnature oitype, ddnature iotype,
uint nest1, uint nest2, uint bnest);
#include "range.h"
#include "ip.h"
extern var_id *current_set_of_vars; /* used in getVarName fns */
/*
delta problem description contains information needed
to associate variable accesses in the tiny program with
variables in the integer programming problem.
The different ranges show which part of the array of
variables in the IP problem correspond to different
accesses in the tiny program.
*/
typedef struct {
range deltas; /* deltas for common indices */
range access1s; /* index variables for access 1 */
range access2s; /* index variables for access 2 */
range nonloops; /* symbolic constants */
range steps1; /* step constraints for a1 */
range steps2; /* step constraints for a1 */
var_id vars[maxVars];
} delta_prob_desc;
/*
build a delta_prob_desc for the dependence from access1 to access2,
return 0 if it obviously can't have solutions because
the subscripts obviously can't be equal.
Note that *dpd should be allocated at least as long as *prob,
since the _getVarNameArgs filed of *prob will point to it.
*/
int build_delta_prob_desc(delta_prob_desc *dpd, Problem *prob,
a_access access1, a_access access2,
int nest1, int nest2, int bnest);
/* the following are used by build_delta_prob_desc */
void delta_init(delta_prob_desc *dpd, Problem *p,
int delta_color, uint Nd,
uint Na1, var_id a1_vars[],
uint Na2, var_id a2_vars[],
uint Nsc, var_id sc_vars[],
uint Ns1, var_id s1_vars[],
uint Ns2, var_id s2_vars[]);
void delta_inv(delta_prob_desc *dpd, Problem *p);
void delta_cleanup(delta_prob_desc *dpd);
#define delta_Nvars(dpd) (r_last(&(dpd)->steps2))
#endif

View File

@@ -0,0 +1,5 @@
/* debug.h,v 1.1.1.2 1992/07/10 02:40:09 davew Exp */
extern int n_strange_occurances;
extern FILE *debug2;
extern void strange_occurance(char *message);

View File

@@ -0,0 +1,47 @@
/*
* Global flag variables
*/
#if !defined(GLOB)
#define GLOB extern
#endif
GLOB int quiet;
GLOB int AllowComments;
GLOB int ivr_on;
GLOB int ivr_debug;
GLOB int ivr_ElimUnused;
GLOB int ivr_DepAnalysis;
GLOB int ivr_Assert;
GLOB int ivr_RepAffine;
GLOB int ivr_DefEntryClass;
GLOB int ivr_SubstScalars;
GLOB int makeReductionOps;
GLOB int doArrayExpn;
GLOB int repeatArrayExpn;
GLOB int doPrivatization;
GLOB int arrDefInOut;
GLOB int doEEdeps;
#if defined OMIT_DDS_FOR_TOPLEVEL
#define omitScalars 1
#else
GLOB int omitScalars;
#endif
GLOB int debugLevel;
GLOB int omegaPrintResult;
GLOB int printing_zap_gists;
#if ! defined SKIP_OMEGA2
GLOB int skipping_omega2;
#endif
#if defined OMIT_DDS_FOR_TOPLEVEL
#define omitTopLevel 1
#else
GLOB int omitTopLevel;
#endif
GLOB char **Argv;
GLOB int Argc;

View File

@@ -0,0 +1,273 @@
#ifndef Already_Included_IP
#define Already_Included_IP 1
#include <stdio.h>
#include <vector>
#include <algorithm>
#define maxVars 50
#define maxGEQs 150
#define maxEQs 27
typedef int EqnKey;
typedef struct _eqn
{
/*_eqn()
{
coef.resize(maxVars + 1);
std::fill(coef.begin(), coef.end(), 0);
key = 0;
touched = 0;
color = 0;
}*/
EqnKey key;
int touched;
int color;
std::vector<int> coef;
//int coef[maxVars + 1];
} *Eqn;
#define headerWords 3
typedef struct _problem
{
private:
int _nVars;
int _numEQs, _numGEQs, _numSUBs;
void resizeEqs()
{
//printf("%d %d %d -> %d\n", _numEQs, _numGEQs, _numSUBs, _nVars + 2);
for (int z = 0; z < _numEQs; ++z)
_EQs[z].coef.resize(_nVars + 2);
for (int z = 0; z < _numGEQs; ++z)
_GEQs[z].coef.resize(_nVars + 2);
for (int z = 0; z < _numSUBs; ++z)
_SUBs[z].coef.resize(_nVars + 2);
}
public:
_problem()
{
_numEQs = _numGEQs = 0;
_numSUBs = 1;
forwardingAddress.resize(maxVars + 2);
_var.resize(maxVars + 2);
_GEQs.resize(maxGEQs);
_EQs.resize(maxEQs);
_SUBs.resize(maxVars + 1);
}
void _init()
{
forwardingAddress.resize(maxVars + 2);
_var.resize(maxVars + 2);
_GEQs.resize(maxGEQs);
_EQs.resize(maxEQs);
_SUBs.resize(maxVars + 1);
}
void _init(int eqs, int ges, int subs, int nvars)
{
_nVars = nvars;
_numEQs = eqs;
_numGEQs = ges;
_numSUBs = subs;
resizeEqs();
}
int getVarsN() const { return _nVars; }
void setVarsN(const int nvars)
{
_nVars = nvars;
resizeEqs();
}
void addToVarsN(const int nvars)
{
_nVars += nvars;
resizeEqs();
}
int getNumEqs() const { return _numEQs; }
int getNumGEqs() const { return _numGEQs; }
int getNumSUBs() const { return _numSUBs; }
void setNumEqs(const int val)
{
_numEQs = val;
//printf("EQ %d -> %d\n", _numEQs, _nVars + 2);
for (int z = 0; z < _numEQs; ++z)
_EQs[z].coef.resize(_nVars + 2);
}
void setNumGEqs(const int val)
{
_numGEQs = val;
//printf("GEQ %d -> %d\n", _numGEQs, _nVars + 2);
for (int z = 0; z < _numGEQs; ++z)
_GEQs[z].coef.resize(_nVars + 2);
}
void setNumSUBs(const int val)
{
_numSUBs = val;
//printf("SUB %d -> %d\n", _numSUBs, _nVars + 2);
for (int z = 0; z < _numSUBs; ++z)
_SUBs[z].coef.resize(_nVars + 2);
}
void addNumEqs(const int val)
{
_numEQs += val;
//printf("EQ %d -> %d\n", _numEQs, _nVars + 2);
for (int z = 0; z < _numEQs; ++z)
_EQs[z].coef.resize(_nVars + 2);
}
void addNumGEqs(const int val)
{
_numGEQs += val;
//printf("GEQ %d -> %d\n", _numGEQs, _nVars + 2);
for (int z = 0; z < _numGEQs; ++z)
_GEQs[z].coef.resize(_nVars + 2);
}
void addNumSUBs(const int val)
{
_numSUBs += val;
//printf("SUB %d -> %d\n", _numSUBs, _nVars + 2);
for (int z = 0; z < _numSUBs; ++z)
_SUBs[z].coef.resize(_nVars + 2);
}
int _safeVars;
int hashVersion;
int variablesInitialized;
int variablesFreed;
std::vector<int> _var;
//int _var[maxVars + 2];
std::vector<int> forwardingAddress;
//int forwardingAddress[maxVars + 2];
char *(*_getVarName)(unsigned int var, void *args);
void *_getVarNameArgs;
std::vector<_eqn> _GEQs;
//_eqn _GEQs [maxGEQs];
std::vector<_eqn> _EQs;
//_eqn _EQs[maxEQs];
std::vector<_eqn> _SUBs;
//_eqn _SUBs[maxVars + 1];
} Problem;
#define UNKNOWN 2
#define SIMPLIFY 3
#define posInfinity (0x7ffffff)
#define negInfinity (-0x7ffffff)
#define red 1
#define black 0
//#define eqnncpy(e1,e2,s) {int *p00,*q00,*r00; p00 = (int *)(e1); q00 = (int *)(e2); r00 = &p00[headerWords+1+s]; while(p00 < r00) *p00++ = *q00++; }
static void eqnncpy(_eqn *dst, const _eqn *src, const int s)
{
dst->color = src->color;
dst->key = src->key;
dst->touched = src->touched;
dst->coef.resize((src->coef.size() > s + 2) ? src->coef.size() : s + 2);
std::fill(dst->coef.begin(), dst->coef.end(), 0);
for (int z = 0; z < ((src->coef.size() < s + 1) ? src->coef.size() : s + 1); ++z)
dst->coef[z] = src->coef[z];
}
#define eqncpy(e1,e2) eqnncpy(e1, e2, nVars)
//#define eqnnzero(e,s) { int *p00,*r00; p00 = (int *)(e); r00 = &p00[headerWords+1+(s)]; while(p00 < r00) *p00++ = 0;}
static void eqnnzero(_eqn *dst, const int s)
{
dst->color = 0;
dst->key = 0;
dst->touched = 0;
dst->coef.resize(s + 2);
for (int z = 0; z < s + 2; ++z)
dst->coef[z] = 0;
}
#define eqnzero(e) eqnnzero(e,nVars)
#define intDiv(a,b) ((1024 * b + a)/b - 1024)
#define intMod(a,b) ((a)-(b)*intDiv(a,b))
#define singleVarGEQ(e,nV) ((e).key != 0 && -maxVars <= (e).key && (e).key <= maxVars)
extern void initializeOmega();
extern void initializeProblem(Problem *);
extern void problemcpy(Problem *, Problem *);
extern void printProblem(Problem *);
extern void printRedEquations(Problem *);
extern void prettyPrintProblem(Problem *);
extern int simplifyProblem(Problem *);
extern int simplifyApproximate(Problem *);
extern void unprotectVariable(Problem *, int var);
extern void negateGEQ(Problem *, int);
/* set extra to 0 for normal use */
extern void printEqn (Problem *p, Eqn e, int is_geq, int extra);
extern void sprintEqn (char *str, Problem *p, Eqn e, int is_geq, int extra);
/*
Return 1 if red equations constrain the set of possible solutions.
We assume that there are solutions to the black equations by themselves,
so if there is no solution to the combined problem, we return 1.
*/
extern int hasRedEquations(Problem * problemPtr, bool expensive);
extern int eliminateRedundant (Problem *problemPtr, bool expensive);
extern void eliminateRed (Problem *problemPtr, bool eliminateAll);
/* constrainVariableSign also unprotects var & simplifies the problem */
extern int
constrainVariableSign(Problem *, int color, int var, int sign);
/* constrainVariableValue adds an EQ that makes variable var have
value "value", even if variable i has been substituted out */
extern void
constrainVariableValue(Problem *problemPtr, int color, int var, int value);
extern int
queryVariable(Problem *, int var, int *lowerBound, int *upperBound);
extern int
queryVariableSigns(Problem *, int, int, int, int, int,
int,
bool *,
int*);
extern int
queryVariableBounds(Problem * problemPtr, int i, int *l, int *u);
extern int solve(Problem *problemPtr, int desiredResult);
extern void setOutputFile(FILE *file);
/* set "file" to the file to which the output of printProblem should go */
extern int reduceWithSubs;
extern int omegaPrintResult;
/* set to non-zero to have constrainVariableSign and simplifyProblem
print the resulting simplified problems */
extern int firstCheckForRedundantEquations;
extern void (*whenReduced)(Problem *problemPtr);
extern void noProcedure(Problem *problemPtr);
extern void Exit(int c);
#endif

View File

@@ -0,0 +1,79 @@
/* kill.h,v 1.1 1993/09/17 22:14:14 fbodin Exp */
#ifndef Already_Included_kill
#define Already_Included_kill
/*
Do quick but possibly indecisive kill tests to see
if dependence dd (from from_acc to to_acc) is killed.
If dd is obviously killed by an intervening write that
covers its destination or terminaties its source,
return ddisCovered or ddisTerminated.
Otherwise, return 0 (is which case dd may or may not be killed -
call accurate_test_for_kill to find out).
this_dep identifies the dependence being tested, so that we will
not try to kill a dependence with itself. this_dep will be
passed to dd_i_i_cur_is and dd_o_i_cur_is.
This function may update dd if dd is partly killed.
In this case, dd's ddrefined bit will be set.
Quick test for kill works for flow, output, or anti dependences
*/
dddirection
quick_test_for_kill(dir_and_dist_info *dd, char *dd_as_string,
a_access from_acc, a_access to_acc,
dd_current this_dep);
/*
Test to see if flow dependence dd (from from_acc to to_acc)
can be killed. If so, return ddisKilled.
This should be called if quick_test_for_kill returns 0.
Works for flow and output dependences - why not anti?
*/
dddirection
accurate_test_for_kill(dir_and_dist_info *dd, char *dd_as_string,
a_access from_acc, a_access to_acc,
dd_current this_dep);
/*
for "READS" type problems,
non-index vars and reads are protected
This type of problem is used in killing, cover & termination testing,
and in refinement
*/
typedef struct {
range nonloops;
range reads; /* index variables @ time of read */
range rsteps;
range write1s; /* index variables @ time of write #1 */
range w1steps;
range write2s; /* index variables @ time of write #2 */
range w2steps;
var_id vars[maxVars];
} read_prob_desc;
/* there is no equivalent to build_delta_prob_desc, as the various
functions that build read_prob_desc's do so in different ways. */
typedef enum { sc_and_r, sc_r_and_w1 } protect_in_read;
void read_init(read_prob_desc *rpd, Problem *p,
protect_in_read protect_which, uint Nsc, var_id sc_vars[],
uint Nr, var_id r_vars[], uint Nrs, var_id rs_vars[],
uint Nw1, var_id w1_vars[], uint Nw1s, var_id w1s_vars[],
uint Nw2, var_id w2_vars[], uint Nw2s, var_id w2s_vars[]);
void read_inv(read_prob_desc *rpd, Problem *p);
void read_cleanup(read_prob_desc *rpd);
#define read_Nvars(rpd) (r_last(&(rpd)->w2steps))
#endif

View File

@@ -0,0 +1,373 @@
/* lang-interf.generic,v 1.1 1993/09/17 22:14:15 fbodin Exp */
/*
Omega-test to programming language interface spec
To adapt the omega test to do data dependence for some language other
than tiny, use the files ip.[hc], ddomega.[hc], ddomega-use.[hc],
ddomega-build.[hc], cover.[ch], kill.[ch], refine.[ch], add-assert.[ch],
debug.[hc], and portable.h unchanged.
Modify affine.c to create affine_expr structures for each expression
that may be relevent to the omega test (loop bounds and array
subscripts). You may or may not need to modify affine.h.
Modify ddodriver.c, or provide your own code, to call the omega test
for all the array pairs where you need to test for dependence, and
call the test_for_cover, test_for_termination, quick_test_for_kill
and accurate_test_for_kill if you wish to use them. If you are
feeling bold, you may even want to try to get the "zap" functions
"possible_to_eliminate" and "try_to_eliminate" (in add-assert.c) to
work.
The flags in omega2flags.h control some of the optional behaviors
that can be obtained from the dependence killing & refining code.
They affect both ddodriver.c and the files that you do not need to
change.
If you want to have debugging output, make sure you open the debug
file and set omegaPrintResult to 1.
Create a file lang-interf.h, defining numerous macros that the
omega test needs to access the parsed program. Your lang-interf.h
can be based on this generic version, or the lang-interf.h that we
wrote for tiny, depending on whether you prefer to read my cryptic
comments here or my even more cryptic code there. In the generic
version, the macros are defined to produce a meaningless result of
the right type, so that ddomega.c, ddomega-use.c, and ddomega-build.c
can all be compiled.
In case of trouble, please feel free to contact me at:
davew@cs.umd.edu
Department of Computer Science
A. V. Williams Building
University of Maryland
College Park, Maryland 20742
Remember that it is a federal crime to send explosives or certain
other dangerous materials in the U.S. Mail.
David Wonnacott
*/
#define NOT_TINY 1
/* Note:
The omega test data dependence functions, and the macros defined
here, often require strings giving the printed representations of
data dependences or array accesses, etc. These strings are used
only for generating debugging output in trace.out. If you don't
care about debugging output, you can just make anything with the
word "string" in it = "".
*/
/* define the maximum length of a data dependence vector */
#define maxCommonNest 6 /* (32 bits - 6 used in dddir.h) / 4 bits per dd */
typedef enum { ddflow, ddanti, ddoutput, ddreduce } ddnature;
/* define the type "a_access", which identifies an array access,
and provides access to information about the access (such as
its depth, line number, the symbol accessed, and the type of
access (read or write)).
It must also be possible to extract information about the
subscript expressions used in the access, with "sub_i_for_access",
information about the "context" of an access (the enclosing reads
& writes), with "cont_i_for_access", and information about the
dependences to or from an access, as per the stuff later in this file.
accesss_cover_depth and accesss_terminator_depth must be lvalues
where we can store the depth at which the access is covered or
terminated. These should both be initialized to -1.
accesss_shared_depth must give the number of loops contianing both
A1 and A2.
Two a_accesses must be equal in a self-dependence test
If there is no existing structure that provides all this information,
you may need to create an aggregate with pointers to the different
structures you use.
*/
typedef void *a_access;
#define access_as_string(A) ("a[i]") /* only used in debugging output */
#define accesss_sym(A) (void *)0 /* currently only used in 1 assertion */
#define accesss_lineno(A) 42 /* currently only in debugging output */
#define accesss_cover_depth(A) ( *((int *) 0) )
#define accesss_terminator_depth(A) ( *((int *) 0) )
#define accesss_depth(A) 7
#define accesss_shared_depth(A1,A2) 6
/* does A access a private var - if so, at what level is it private? */
#define access_private_var_p(A) 0
#define access_private_var_level(A) 3
#define access_fetch_p(A) 1
#define access_store_p(A) 1
#define access_update_p(A) 1
/* Are A1 and A2 updates of the same kind (ie both += or both *=) */
#define access_same_update_type_p(A1, A2) 1
/* can we execute A1 and then A2 without going to another iteration */
#define access_lexically_preceeds(A1, A2) 1
/* pointers to Entry and Exit node for testing for dependence to
points before or after the routine being analyzed. It must
be possible to compare these to a variable of type a_access */
#define Entry ((a_access)0)
#define ExitNode ((a_access)0)
/* define the type "sub_iterator" - an iterator over the
subscripts of an array access. We need to test these
subscripts to see if they are affine expressions of the
loop index variables and symbolic constants, and if so,
find the associated affine_expr structure.
We also need to have access to all the variables used in
the expression (for the purpose of building the set of
variables used), via the function sub_i_map_over_cur_vars,
which calls F(V,ARGS) for each variable V in the expression.
*/
typedef void *sub_iterator;
#define sub_i_for_access(A) ((sub_iterator *) 0)
#define sub_i_next(SUBI)
#define sub_i_done(SUBI) (1)
#define sub_i_cur_is_affine(SUBI) (1)
#define sub_i_cur_affine(SUBI) ((affine_expr *) 0)
#define sub_i_map_over_cur_vars(SUBI,F,ARGS)
/* define the type "sub_iterator" - an iterator over the
enclosing contexts of an array access. Each cont_i_next
operation must select the next enclosing loop or if.
We must be able to tell which we have selected, and
get a "loop_context" or "if_context" object from it.
*/
typedef void *context_iterator;
extern context_iterator cont_i_for_access(a_access a);
#define cont_i_next(C)
#define cont_i_done(C) 1
#define cont_i_cur_loop_p(C) 1
#define cont_i_cur_if_p(C) 0
#define cont_i_cur_if(C) (C)
#define cont_i_cur_loop(C) (C)
#define cont_i_cur_depth(C) 7
/* cur_depth valid for loops - # of loops around stmts in this loop */
/* cur_depth is also needed for ifs as of release 3.0 */
#define access_is_in_then_or_else_of(A,C) 0
/* access A is in the then or the else part of C,
where cont_i_cur_if_p must be true of C */
#define cont_i_cur_lineno(C) 42
/* a "loop_context" provides information about a loop.
We need to be able to find affine_exprs for the start
and end bounds (if a bound is not affine, we should
get a result for which "is_affine" is false).
We also need to know if there is a step expression,
and whether it is known at compile time, and if so,
what it is. These last two must be answered by the
function "loops_step(LOOP,S,KNOWN)", which sets *KNOWN
to true if the step is known at compile time, and sets
*S to the step if it is known.
We must also be able to map a function over all the
variables used in the start and end bounds (as we did
for the variables used in the step expressions).
*/
typedef void *loop_context;
#define loop_var_id(LOOP) ((var_id *) 0)
#define loop_start(LOOP) ((affine_expr *) 0)
#define loop_end(LOOP) ((affine_expr *) 0)
#define loop_has_step_p(LOOP) 1
#define loops_step(LOOP,S,KNOWN) { *S = 2; *KNOWN = 1; }
#define loop_map_over_start_vars(LOOP,F,ARGS)
#define loop_map_over_end_vars(LOOP,F,ARGS)
/* an "if context" provides information about the conditions
surrounding an array access.
The current code can handle ifs with single >, >=, <, or <= conditions.
Note that it is not OK to just leave this out - it will prevent the
refinement, cover, termination, and kill tests from determining whether
or not they have exact information.
If, for some reason, you can not supply this information,
make sure that the context iterator for an array access in an if
yeilds one if_context for which if_condition_ok is false
*/
typedef void *if_context;
typedef enum { greater = 0, greater_eq = 1, less = 2, less_eq = 3 }
if_compare_operators;
#define if_condition_ok(IC) (0)
#define if_compare_op(IC) (greater) /* one of if_compare_operators */
#define if_compare_left(IC) ((affine_expr *) 0) /* lhs of compare op */
#define if_compare_right(IC) ((affine_expr *) 0) /* rhs of compare op */
#define if_else_branch(IC) (0) /* true in body of "else" clause */
#define if_map_over_vars(IC,F,ARGS)
/* define the type used to identify a variable (typically
a pointer into the symbol table or some such).
It must be possible to tell the difference between a loop
index and a symbolic constant, and for a loop index, we must
be able to find the depth of the loop.
We must also be able to associate a integer "tag" with each
variable - all tags must start out with the value UNTAGGED.
*/
typedef void *var_id;
#define var_id_const_p(AE_VAR) (1)
#define var_id_index_p(AE_VAR) (1)
#define var_ids_loop_no(AE_VAR) (7 /* depth of associated loop */ )
#define var_ids_tag(AE_VAR) (*(int *)0)
#define var_ids_name(AE_VAR) ("a variable name") /* only for debug */
#define UNTAGGED -1
/* representations of Data Dependences follow -
You probably should not change these, but simply convert from
this format into whatever you use, and vice versa, when getting
information from/to the omega test
*/
/* information about dd direction vectors.
works only if unsigned long int has at least 32 bits */
#include "dddir.h"
/*
A dir_and_dist_info structure contains information about a dependence
This is the form in which some of the omega test functions expect
dependence information.
*/
typedef struct {
uint nest;
dddirection direction;
dddirection restraint;
bool distanceKnown[maxCommonNest];
int distance[maxCommonNest];
void * dd_graph_node_to_be_cloned;
/* dd_graph_node_to_be_cloned points to the structure
that must be duplicated when we need to make a copy
of an existing entry in the dependence graph using
the function clone_dd_graph_node_for_refinement */
} dir_and_dist_info;
/* Duplicate the dd graph node, setting "isRefined" in the copy.
This bit will hopefully get cleaner in the next release */
void clone_dd_graph_node_for_refinement(void *dd_graph_node_to_be_cloned);
#define d_info_do_eq(D_INFO, J) \
if (ddextract1((D_INFO)->direction,(J)) == ddeq) \
{ \
(D_INFO)->distanceKnown[(J)] = 1; \
(D_INFO)->distance[(J)] = 0; \
}
#if ! defined NDEBUG
#define d_info_inv(D_INFO) \
{ \
int i; \
for (i=1; i<=(D_INFO)->nest; i++) { \
if (ddextract1((D_INFO)->direction,i) == ddeq) { \
assert((D_INFO)->distanceKnown[i] && \
(D_INFO)->distance[i] == 0); \
} \
} \
}
#else
#define d_info_inv(X)
#endif
/*
odd_iterators are now obsolete.
they have been replaced.
*/
/* dd_in_iterators and dd_out_iterators allow iteration thru all the
dependences into a given access or out of a given access.
We may need to find the source or destination node of the current
dependence, or find out whether it is a flow or output dependence,
and whether it covers or terminates.
We must also be able to identify a dependence, so that we don't
test it against itself in certain circumstances
For either type, we must be able to select the current dependence,
which we identify with the type dd_current.
From this current element, we may determine the nesting level, or
information about the dependence distances or directions or the
restraint vector.
*/
typedef void *dd_in_iterator; /* iterate thru dds in to an access */
typedef void *dd_out_iterator; /* iterate thru dds out from an access */
typedef void *dd_current; /* point to the dd the iterator is on */
#define dd_current_nest(DDC) (3)
#define dd_current_dist(DDC) ((int *)0) /* distance array */
#define dd_current_dist_known(DDC,j) 1 /* dd_current_dist(DDC)[j] meaningful?*/
#define dd_current_dir(DDC) (*((dddirection *)0)) /* direction */
#define dd_current_restr(DDC) (*((dddirection *)0)) /* restraint */
#define dd_current_as_string(DDC) "a dependence"
#define dd_current_src(DDC) ((a_access) 0)
#define dd_current_dest(DDC) ((a_access) 0)
#define dd_i_i_for_access(ACC) ((dd_in_iterator) 0)
#define dd_i_i_done(DD_I_I) (1)
#define dd_i_i_next(DD_I_I)
#define dd_i_i_current(DD_I_I) ((dd_current) 0)
#define dd_i_i_cur_src(DD_I_I) ((a_access) 0)
#define dd_i_i_cur_dest(DD_I_I) ((a_access) 0)
#define dd_i_i_cur_flow_p(DD_I_I) 0
#define dd_i_i_cur_output_p(DD_I_I) 0
#define dd_i_i_cur_cover_p(DD_I_I) 0
#define dd_i_i_cur_is(DD_I_I, DEP) (dd_i_i_current(DD_I_I) == (DEP))
#define dd_o_i_for_access(ACC) ((dd_out_iterator) 0)
#define dd_o_i_done(DD_O_I) 1
#define dd_o_i_next(DD_O_I)
#define dd_o_i_current(DD_O_I) ((dd_current) 0)
#define dd_o_i_cur_src(DD_O_I) ((a_access) 0)
#define dd_o_i_cur_dest(DD_O_I) ((a_access) 0)
#define dd_o_i_cur_output_p(DD_O_I) 0
#define dd_o_i_cur_terminate_p(DD_O_I) 0
#define dd_o_i_cur_is(DD_O_I, DEP) (dd_o_i_current(DD_O_I) == (DEP))
/* the function "store_dependence" will be called when the omega test
has detected a data dependence. It should convert from the
dir_and_dist_info into whatever form is used by the rest of the system */
void store_dependence(ddnature nature, a_access from_access,
a_access to_access, dir_and_dist_info *d_info);
/* convert dd nodes into stuff our functions can handle */
void ddnode_to_dir_and_dist(dd_current, dir_and_dist_info *);
/* copy info from a dir_and_dist_info into an existing dd node */
void dir_and_dist_into_ddnode(const dir_and_dist_info *ddi, dd_current);
/* take inequality number GEQ, and turn it into an assertion */
#define add_GEQ_assertion(P, VARS, GEQ) ;

View File

@@ -0,0 +1,503 @@
/* lang-interf.h,v 1.2 1994/07/05 15:34:09 fbodin Exp */
#ifndef Already_Included_Lang_Interf
#define Already_Included_Lang_Interf 1
/*
Omega-test to programming language interface spec
To adapt the omega test to do data dependence for some language other
than tiny, use the files ip.[hc], ddomega.[hc], ddomega-use.[hc],
ddomega-build.[hc], cover.[ch], kill.[ch], refine.[ch], add-assert.[ch],
debug.[hc], and portable.h unchanged.
Modify affine.c to create affine_expr structures for each expression
that may be relevent to the omega test (loop bounds and array
subscripts). You may or may not need to modify affine.h.
Modify ddodriver.c, or provide your own code, to call the omega test
for all the array pairs where you need to test for dependence, and
call the test_for_cover, test_for_termination, quick_test_for_kill
and accurate_test_for_kill if you wish to use them. If you are
feeling bold, you may even want to try to get the "zap" functions
"possible_to_eliminate" and "try_to_eliminate" (in add-assert.c) to
work.
The flags in omega2flags.h control some of the optional behaviors
that can be obtained from the dependence killing & refining code.
They affect both ddodriver.c and the files that you do not need to
change.
If you want to have debugging output, make sure you open the debug
file and set omegaPrintResult to 1.
Create a file lang-interf.h, defining numerous macros that the
omega test needs to access the parsed program. Your lang-interf.h
can be based on this generic version, or the lang-interf.h that we
wrote for tiny, depending on whether you prefer to read my cryptic
comments here or my even more cryptic code there. In the generic
version, the macros are defined to produce a meaningless result of
the right type, so that ddomega.c, ddomega-use.c, and ddomega-build.c
can all be compiled.
In case of trouble, please feel free to contact me at:
davew@cs.umd.edu
Department of Computer Science
A. V. Williams Building
University of Maryland
College Park, Maryland 20742
Remember that it is a federal crime to send explosives or certain
other dangerous materials in the U.S. Mail.
David Wonnacott
*/
#define NOT_TINY 1
/* include for the sage macro */
/* #include "macro.h"*/
struct _affine_expr; /* define later in affine.h */
struct omegaIterator ; /* define later in this file */
struct omegaLoop; /* define later in this file */
struct omegaIf; /* define later in this file */
struct omegaVar; /* define later in this file */
struct omegaContIter;
/* Note:
The omega test data dependence functions, and the macros defined
here, often require strings giving the printed representations of
data dependences or array accesses, etc. These strings are used
only for generating debugging output in trace.out. If you don't
care about debugging output, you can just make anything with the
word "string" in it = "".
*/
/* define the maximum length of a data dependence vector */
#define maxCommonNest 10 /* (32 bits - 6 used in dddir.h) / 4 bits per dd */
typedef enum { ddflow, ddanti, ddoutput, ddreduce, dd_unknown, ddnovalue } ddnature;
/* define the type "a_access", which identifies an array access,
and provides access to information about the access (such as
its depth, line number, the symbol accessed, and the type of
access (read or write)).
It must also be possible to extract information about the
subscript expressions used in the access, with "sub_i_for_access",
information about the "context" of an access (the enclosing reads
& writes), with "cont_i_for_access", and information about the
dependences to or from an access, as per the stuff later in this file.
accesss_cover_depth and accesss_terminator_depth must be lvalues
where we can store the depth at which the access is covered or
terminated. These should both be initialized to -1.
accesss_shared_depth must give the number of loops contianing both
A1 and A2.
Two a_accesses must be equal in a self-dependence test
If there is no existing structure that provides all this information,
you may need to create an aggregate with pointers to the different
structures you use.
*/
struct omegaAccess {
char *str;
struct omegaVar *symb;
struct omegaIterator *subiter;
struct omegaContIter *context;
int inIfStmt;
int line,cdepth,tdepth;
int depth;
int idforsage;
int shareddepth;
int pri;
int level;
int fetch;
int store;
int update;
int lexord;
};
typedef struct omegaAccess *a_access;
#define access_as_string(A) (A->str) /* only used in debugging output */
#define accesss_sym(A) (A->symb) /* currently only used in 1 assertion */
#define accesss_lineno(A) (A->line) /* currently only in debugging output */
#define accesss_cover_depth(A) (A->cdepth)
#define accesss_terminator_depth(A) (A->tdepth)
#define accesss_depth(A) (A->depth)
#define accesss_shared_depth(A1,A2) (A1->shareddepth)
/* this is wrong
#define accesss_shared_depth(A1,A2) ((A1->depth > A2->depth)?(A1->depth - A2->depth):(A2->depth > A1->depth))
*/
/* does A access a private var - if so, at what level is it private? */
#define access_private_var_p(A) (A->pri)
#define access_private_var_level(A) (A->level)
#define access_fetch_p(A) (A->fetch)
#define access_store_p(A) (A->store)
#define access_update_p(A) (A->update)
/* Are A1 and A2 updates of the same kind (ie both += or both *=) */
#define access_same_update_type_p(A1, A2) 0
/* can we execute A1 and then A2 without going to another iteration */
#define access_lexically_preceeds(A1, A2) (A1->lexord > A2->lexord)
/* pointers to Entry and Exit node for testing for dependence to
points before or after the routine being analyzed. It must
be possible to compare these to a variable of type a_access */
#define Entry ((a_access)0)
#define ExitNode ((a_access)0)
/* define the type "sub_iterator" - an iterator over the
subscripts of an array access. We need to test these
subscripts to see if they are affine expressions of the
loop index variables and symbolic constants, and if so,
find the associated affine_expr structure.
We also need to have access to all the variables used in
the expression (for the purpose of building the set of
variables used), via the function sub_i_map_over_cur_vars,
which calls F(V,ARGS) for each variable V in the expression.
*/
struct omegaIterator {
struct omegaIterator *next;
int isaffine;
struct _affine_expr *affine;
struct omegaVar *constante;
int cstvalue;
} ;
typedef struct omegaIterator *sub_iterator;
#define sub_i_for_access(A) ((A)->subiter)
#define sub_i_next(SUBI) (SUBI = SUBI->next)
#define sub_i_done(SUBI) (SUBI == NULL)
#define sub_i_cur_is_affine(SUBI) (SUBI->isaffine)
#define sub_i_cur_affine(SUBI) (SUBI->affine)
/*
#define sub_i_map_over_cur_vars(SUBI,F,ARGS) {(F)(SUBI->constante,ARGS);}
*/
#define sub_i_map_over_cur_vars(SUBI,F,ARGS)
/* define the type "sub_iterator" - an iterator over the
enclosing contexts of an array access. Each cont_i_next
operation must select the next enclosing loop or if.
We must be able to tell which we have selected, and
get a "loop_context" or "if_context" object from it.
*/
struct omegaContIter {
struct omegaContIter *next;
int depth;
int line;
struct omegaLoop *loop;
struct omegaIf *ifstmt;
int loopiter;
};
typedef struct omegaContIter *context_iterator;
/*extern context_iterator cont_i_for_access(a_access a);*/
#define cont_i_for_access(A) (A->context)
#define cont_i_next(C) (C = C->next)
#define cont_i_done(C) (C == NULL)
#define cont_i_cur_loop_p(C) (C->loopiter)
#define cont_i_cur_if_p(C) (!(C->loopiter))
#define cont_i_cur_if(C) (C->ifstmt)
#define cont_i_cur_loop(C) (C->loop)
#define cont_i_cur_depth(C) (C->depth)
/* cur_depth valid for loops - # of loops around stmts in this loop */
/* cur_depth is also needed for ifs as of release 3.0 */
/* #define access_is_in_then_or_else_of(A,C) ((A)->inIfStmt)*/
extern int access_is_in_then_or_else_of(a_access A,context_iterator C);
/* access A is in the then or the else part of C,
where cont_i_cur_if_p must be true of C */
#define cont_i_cur_lineno(C) (C->line)
/* a "loop_context" provides information about a loop.
We need to be able to find affine_exprs for the start
and end bounds (if a bound is not affine, we should
get a result for which "is_affine" is false).
We also need to know if there is a step expression,
and whether it is known at compile time, and if so,
what it is. These last two must be answered by the
function "loops_step(LOOP,S,KNOWN)", which sets *KNOWN
to true if the step is known at compile time, and sets
*S to the step if it is known.
We must also be able to map a function over all the
variables used in the start and end bounds (as we did
for the variables used in the step expressions).
*/
struct omegaLoop {
struct omegaVar *symb;
struct _affine_expr *startl;
struct _affine_expr *endl;
int hasstep;
int stepl;
int knownstep;
struct omegaVar *constantestart;
int cstvaluestart;
struct omegaVar *constanteend;
int cstvaluesend;
};
typedef struct omegaLoop *loop_context;
#define loop_var_id(LOOP) (LOOP->symb)
#define loop_start(LOOP) (LOOP->startl)
#define loop_end(LOOP) (LOOP->endl)
#define loop_has_step_p(LOOP) (LOOP->hasstep)
#define loops_step(LOOP,S,KNOWN) { *S = LOOP->stepl; *KNOWN = LOOP->knownstep; }
/*
#define loop_map_over_start_vars(LOOP,F,ARGS) {(F)(LOOP->constantestart,ARGS);}
#define loop_map_over_end_vars(LOOP,F,ARGS) {(F)(LOOP->constanteend,ARGS);}
*/
#define loop_map_over_start_vars(LOOP,F,ARGS)
#define loop_map_over_end_vars(LOOP,F,ARGS)
/* an "if context" provides information about the conditions
surrounding an array access.
The current code can handle ifs with single >, >=, <, or <= conditions.
Note that it is not OK to just leave this out - it will prevent the
refinement, cover, termination, and kill tests from determining whether
or not they have exact information.
If, for some reason, you can not supply this information,
make sure that the context iterator for an array access in an if
yeilds one if_context for which if_condition_ok is false
*/
typedef enum { greater = 0, greater_eq = 1, less = 2, less_eq = 3 }
if_compare_operators;
struct omegaIf {
int condOK;
int ident;
if_compare_operators oper;
struct _affine_expr *left;
struct _affine_expr *right;
int partelse;
};
typedef struct omegaIf *if_context;
#define if_condition_ok(IC) (IC->condOK)
#define if_compare_op(IC) (IC->oper) /* one of if_compare_operators */
#define if_compare_left(IC) (IC->left) /* lhs of compare op */
#define if_compare_right(IC) (IC->right) /* rhs of compare op */
#define if_else_branch(IC) (IC->partelse) /* true in body of "else" clause */
#define if_map_over_vars(IC,F,ARGS)
/* define the type used to identify a variable (typically
a pointer into the symbol table or some such).
It must be possible to tell the difference between a loop
index and a symbolic constant, and for a loop index, we must
be able to find the depth of the loop.
We must also be able to associate a integer "tag" with each
variable - all tags must start out with the value UNTAGGED.
*/
struct omegaVar {
int loop;
int constp;
int indexp;
int tag;
char *name;
};
typedef struct omegaVar *var_id;
#define var_id_const_p(AE_VAR) (AE_VAR->constp)
#define var_id_index_p(AE_VAR) (AE_VAR->indexp)
#define var_ids_loop_no(AE_VAR) (AE_VAR->loop)
#define var_ids_tag(AE_VAR) (AE_VAR->tag)
#define var_ids_name(AE_VAR) (AE_VAR->name) /* only for debug */
#define UNTAGGED -1
/* representations of Data Dependences follow -
You probably should not change these, but simply convert from
this format into whatever you use, and vice versa, when getting
information from/to the omega test
*/
/* information about dd direction vectors.
works only if unsigned long int has at least 32 bits */
#include "dddir.h"
/*
A dir_and_dist_info structure contains information about a dependence
This is the form in which some of the omega test functions expect
dependence information.
*/
#include "portable.h"
typedef struct DD_info {
uint nest;
dddirection direction;
dddirection restraint;
bool distanceKnown[maxCommonNest];
int distance[maxCommonNest];
void * dd_graph_node_to_be_cloned;
/* dd_graph_node_to_be_cloned points to the structure
that must be duplicated when we need to make a copy
of an existing entry in the dependence graph using
the function clone_dd_graph_node_for_refinement */
DD_info()
{
nest = 0;
direction = 0;
restraint = 0;
for (int z = 0; z < maxCommonNest; ++z)
{
distanceKnown[z] = false;
distance[z] = 0;
}
dd_graph_node_to_be_cloned = NULL;
}
} dir_and_dist_info;
/* Duplicate the dd graph node, setting "isRefined" in the copy.
This bit will hopefully get cleaner in the next release */
void clone_dd_graph_node_for_refinement(void *dd_graph_node_to_be_cloned);
#define d_info_do_eq(D_INFO, J) \
if (ddextract1((D_INFO)->direction,(J)) == ddeq) \
{ \
(D_INFO)->distanceKnown[(J)] = 1; \
(D_INFO)->distance[(J)] = 0; \
}
#if ! defined NDEBUG
#define d_info_inv(D_INFO) \
{ \
int i; \
for (i=1; i<=(D_INFO)->nest; i++) { \
if (ddextract1((D_INFO)->direction,i) == ddeq) { \
if (!((D_INFO)->distanceKnown[i] && (D_INFO)->distance[i] == 0))\
{\
printf("%lld %lld %lld\n", (D_INFO)->nest, (D_INFO)->direction, (D_INFO)->restraint);\
for (int z = 0; z < maxCommonNest; ++z)\
printf("[%d]: %d %d\n", z, (D_INFO)->distanceKnown[z], (D_INFO)->distance[z]);\
}\
assert((D_INFO)->distanceKnown[i] && (D_INFO)->distance[i] == 0); \
} \
} \
}
#else
#define d_info_inv(X)
#endif
/*
odd_iterators are now obsolete.
they have been replaced.
*/
/* dd_in_iterators and dd_out_iterators allow iteration thru all the
dependences into a given access or out of a given access.
We may need to find the source or destination node of the current
dependence, or find out whether it is a flow or output dependence,
and whether it covers or terminates.
We must also be able to identify a dependence, so that we don't
test it against itself in certain circumstances
For either type, we must be able to select the current dependence,
which we identify with the type dd_current.
From this current element, we may determine the nesting level, or
information about the dependence distances or directions or the
restraint vector.
*/
typedef void *dd_in_iterator; /* iterate thru dds in to an access */
typedef void *dd_out_iterator; /* iterate thru dds out from an access */
typedef void *dd_current; /* point to the dd the iterator is on */
#define dd_current_nest(DDC) (3)
#define dd_current_dist(DDC) ((int *)0) /* distance array */
#define dd_current_dist_known(DDC,j) 1 /* dd_current_dist(DDC)[j] meaningful?*/
#define dd_current_dir(DDC) (*((dddirection *)0)) /* direction */
#define dd_current_restr(DDC) (*((dddirection *)0)) /* restraint */
#define dd_current_as_string(DDC) "a dependence"
#define dd_current_src(DDC) ((a_access) 0)
#define dd_current_dest(DDC) ((a_access) 0)
#define dd_i_i_for_access(ACC) ((dd_in_iterator) 0)
#define dd_i_i_done(DD_I_I) (1)
#define dd_i_i_next(DD_I_I)
#define dd_i_i_current(DD_I_I) ((dd_current) 0)
#define dd_i_i_cur_src(DD_I_I) ((a_access) 0)
#define dd_i_i_cur_dest(DD_I_I) ((a_access) 0)
#define dd_i_i_cur_flow_p(DD_I_I) 0
#define dd_i_i_cur_output_p(DD_I_I) 0
#define dd_i_i_cur_cover_p(DD_I_I) 0
#define dd_i_i_cur_is(DD_I_I, DEP) (dd_i_i_current(DD_I_I) == (DEP))
#define dd_o_i_for_access(ACC) ((dd_out_iterator) 0)
#define dd_o_i_done(DD_O_I) 1
#define dd_o_i_next(DD_O_I)
#define dd_o_i_current(DD_O_I) ((dd_current) 0)
#define dd_o_i_cur_src(DD_O_I) ((a_access) 0)
#define dd_o_i_cur_dest(DD_O_I) ((a_access) 0)
#define dd_o_i_cur_output_p(DD_O_I) 0
#define dd_o_i_cur_terminate_p(DD_O_I) 0
#define dd_o_i_cur_is(DD_O_I, DEP) (dd_o_i_current(DD_O_I) == (DEP))
/* the function "store_dependence" will be called when the omega test
has detected a data dependence. It should convert from the
dir_and_dist_info into whatever form is used by the rest of the system */
void store_dependence(ddnature nature, a_access from_access,
a_access to_access, dir_and_dist_info *d_info);
/* convert dd nodes into stuff our functions can handle */
void ddnode_to_dir_and_dist(dd_current, dir_and_dist_info *);
/* copy info from a dir_and_dist_info into an existing dd node */
void dir_and_dist_into_ddnode(const dir_and_dist_info *ddi, dd_current);
/* take inequality number GEQ, and turn it into an assertion */
#define add_GEQ_assertion(P, VARS, GEQ) ;
#endif

View File

@@ -0,0 +1,37 @@
/* missing.h,v 1.1.1.2 1992/07/10 02:40:55 davew Exp */
#ifndef Already_Included_Missing
#define Already_Included_Missing
/* You may need to comment these out */
extern int delwin();
extern int touchwin();
extern int waddch();
extern int waddstr();
extern int wclear();
extern int wclrtoeol();
extern int wdeleteln();
extern int wgetch();
extern int wgetstr();
extern int winsch();
extern int winsertln();
extern int wmove();
extern int wrefresh();
extern int wstandend();
extern int wstandout();
extern int printw();
extern int wprintw();
extern int mvwprintw();
extern int endwin();
extern int stty();
extern char *getwd();
extern int wait3();
extern int mkdir();
extern int getrusage();
#endif

View File

@@ -0,0 +1,50 @@
/* omega2flags.h,v 1.1 1993/09/17 22:14:18 fbodin Exp */
/* compile time and run time flags that control the behavior of the
code that eliminates dead dependences */
#ifndef Already_Included_Omega2flags
#define Already_Included_Omega2flags
#if defined SKIP_OMEGA2
#define skipping_omega2 1
#else
extern int skipping_omega2;
#endif
#if defined SKIP_ZAPPABLE
#define skipping_zappable 1
#else
#define skipping_zappable 0
#endif
#if defined ONLY_CHANGE_FLOW_LEVEL
#define skipping_plus_refinement 1
#define skipping_o_a_tightening 1
#else
#define skipping_plus_refinement 0
#define skipping_o_a_tightening 0
#endif
#if ! defined skipping_all_tightening
#define skipping_all_tightening 0
#endif
#if ! defined skipping_bailout
#define skipping_bailout 0
#endif
#if defined EXTRAVAGANT
#define doing_all_accurate_kills 1
/* do refinement of all kinds of dds: "skipping_plus_refinement" still works */
#define doing_all_refines 1
#else
#define doing_all_accurate_kills 0
/* do refinement of all kinds of dds: "skipping_plus_refinement" still works */
#define doing_all_refines 0
#endif
#endif

View File

@@ -0,0 +1,57 @@
/* portable.h,v 1.1 1993/09/17 22:14:20 fbodin Exp */
#ifndef Already_Included_Portable
#define Already_Included_Portable
/* define integer type names for portability */
/* use 'sint' and 'uint' unless space is at a premium */
typedef long int sint;
typedef char sint8;
typedef short int sint16;
typedef long int sint32;
typedef unsigned char uint8;
typedef unsigned short int uint16;
typedef unsigned long int uint32;
#ifndef __cplusplus
typedef unsigned char bool;
#endif
/* tiny uses arrays of characters to buffer I/O at various points.
These really should be dynamically sized strings, but since that
is a pain in C, we just make arrays of the following size.
In many cases, the size is not tested, so, for example, running
tiny on a file with a really long name can cause a core dump.
This ought to be at least 256, as thats the largest constant that
we replaced with TINYBUFSIZ. This is in portable.h for irony */
#define TINYBUFSIZ 256
#ifndef __TURBOC__
#include <sys/types.h>
#endif
#define uint unsigned int
#ifndef NIL
#define NIL 0L
#endif
#define ANSI_libraries
#define TYPEPROCPTR typedef
#define EXPROC extern
#define PROC
#define SWAP(TYPE, V1, V2) \
{ TYPE TMP; \
TMP = V1; \
V1 = V2; \
V2 = TMP; \
}
/*
#define MIN(X,Y) ((X)<(Y)?(X):(Y))
#define MAX(X,Y) ((X)>(Y)?(X):(Y))
*/
#endif

View File

@@ -0,0 +1,53 @@
/* portable.h.origine,v 1.1 1993/09/17 22:14:21 fbodin Exp */
#ifndef Already_Included_Portable
#define Already_Included_Portable
/* define integer type names for portability */
/* use 'sint' and 'uint' unless space is at a premium */
typedef long int sint;
typedef char sint8;
typedef short int sint16;
typedef long int sint32;
typedef unsigned char uint8;
typedef unsigned short int uint16;
typedef unsigned long int uint32;
typedef unsigned char bool;
/* tiny uses arrays of characters to buffer I/O at various points.
These really should be dynamically sized strings, but since that
is a pain in C, we just make arrays of the following size.
In many cases, the size is not tested, so, for example, running
tiny on a file with a really long name can cause a core dump.
This ought to be at least 256, as thats the largest constant that
we replaced with TINYBUFSIZ. This is in portable.h for irony */
#define TINYBUFSIZ 256
#ifndef __TURBOC__
#include <sys/types.h>
#endif
#define uint unsigned int
#ifndef NIL
#define NIL 0L
#endif
#define ANSI_libraries
#define TYPEPROCPTR typedef
#define EXPROC extern
#define PROC
#define SWAP(TYPE, V1, V2) \
{ TYPE TMP; \
TMP = V1; \
V1 = V2; \
V2 = TMP; \
}
#define MIN(X,Y) ((X)<(Y)?(X):(Y))
#define MAX(X,Y) ((X)>(Y)?(X):(Y))
#endif

View File

@@ -0,0 +1,19 @@
/* range.h,v 1.1.1.1 1992/07/10 02:41:06 davew Exp */
#ifndef Already_Included_Range
#define Already_Included_Range
typedef struct {
uint _first;
uint _length;
} range;
#define r_first(r) ((r)->_first)
#define r_last(r) ((r)->_first + (r)->_length - 1)
#define r_length(r) ((r)->_length)
#define r_in(r, i) ((i) >= r_first(r) && (i) <= r_last(r))
/* #define r_grow(r) (++(r)->_length)
grow is no longer allowed, as variables after the last region are
used for iteration number counts */
#endif

View File

@@ -0,0 +1,37 @@
/* refine.h,v 1.1 1993/09/17 22:14:23 fbodin Exp */
#ifndef Already_Included_refine
#define Already_Included_refine
/*
if from_acc is a write, try to refine the source
if to_acc is a write, try to refine the destination
(If both are writes, I think we could get a bit more refinement
by having a refine_both, which tries to refine either the source
or the destination at each loop nest. I also think this would be
so rare that its not worth writing the code.)
*d_info will be updated if refinement is successful
can be used for flow, output, or anti dependences
*/
void refine_dependence(a_access from, a_access to,
dir_and_dist_info *d_info);
/*
try to refine a covers leading 0+'s into 0's.
can be used for output or flow dependences
*/
void tighten_cover(a_access from_acc, a_access to_acc,
dir_and_dist_info *d_info,
char *dd_as_string);
/*
try to refine a terminators leading 0+'s into 0's.
can be used for output or anti dependences
*/
void tighten_terminator(a_access from_acc, a_access to_acc,
dir_and_dist_info *d_info,
char *dd_as_string);
#endif

View File

@@ -0,0 +1,124 @@
/* screen.h,v 1.1.1.2 1992/07/10 02:41:20 davew Exp */
#ifndef Already_Included_Screen
#define Already_Included_Screen
/* Define 6 screen primitives:
screen_init() what to call to initialize the graphics system.
screen_print like 'printf' to write to the virtual screen
screen_move(line,col) to move to an (line,col) position on the virtual screen
screen_where(line,col) get the current (line,col) position
screen_highlight() print with reverse video
screen_lowlight() end reverse-video printing
screen_getchar(ch,line,col) get the char at position (line,col)
[may move cursor]
screen_clear() how to clear the screen
screen_clrline(line) move to the start of line 'line' and clear it
screen_clreol() clear to end of this line from current pos
screen_clrrest() clear to end of screen from this line
screen_update() after _print, how to update the actual screen
screen_fini() what to call when done with graphics.
two variables:
COLS : number of columns on screen
LINES: number of lines on screen
0 <= line < LINES
0 <= col < COLS
*/
#ifdef __TURBOC__
/* no good way to use Turbo C to detect number of lines/cols on screen */
#define LINES 25
#define COLS 80
#include <conio.h>
/* #define screen_init() textattr((BLUE<<4)+LIGHTGRAY) */
#define screen_init() textattr((BLACK<<4)+LIGHTGRAY), 1
/* added ,1 to make it return TRUE. 3.21.91 davew@panache.cs.umd.edu */
#define screen_print cprintf
#define screen_move(line,col) gotoxy(col+1,line+1)
#define screen_where(line,col) line=wherey()-1;col=wherex()-1
/* #define screen_highlight() textattr((LIGHTGRAY<<4)+BLUE) */
/* #define screen_lowlight() textattr((BLUE<<4)+LIGHTGRAY) */
#define screen_highlight() textattr((LIGHTGRAY<<4)+BLACK)
#define screen_lowlight() textattr((BLACK<<4)+LIGHTGRAY)
#define screen_getchar(ch,line,col) \
{ char c[2];\
gettext(col+1,line+1,col+1,line+1,c);\
ch = c[2]; }
#define screen_clear() clrscr()
#define screen_clrline(line) gotoxy(1,line+1);clreol()
#define screen_clreol() clreol()
#define screen_clrrest() { uint l;\
for(l=wherey();l<=LINES-2;++l){\
gotoxy(1,l);\
clreol();\
}\
}
#define screen_update()
#define screen_fini()
#else
#include <curses.h>
#include "missing.h"
#undef bool
/* #define screen_init() initscr();refresh() */
/* Three new functions for use with scrolling */
#define screen_putchar mvaddch
#define screen_waddch mvwaddch
#define screen_insertln insertln
#define screen_deleteln deleteln
#define screen_print printw
#define screen_wprint mvwprintw
#define screen_move(line,col) move(line,col)
#define screen_where(line,col) getyx(stdscr,line,col)
#define screen_highlight() standout()
#define screen_lowlight() standend()
#define screen_dhighlight() wstandout(depend)
#define screen_dlowlight() wstandend(depend)
#define screen_touch() touchwin(stdscr)
#define screen_dtouch() touchwin(depend)
#define screen_dclose() delwin(depend)
/* get the character directly from the curses data structure so that the */
/* attribute bit is not stripped off */
#define screen_getchar(ch,line,col) ch=stdscr->_y[line][col]
#define screen_clear() { clear();\
if (depend_shown)\
wclear(depend);\
}
#define screen_clrline(line) {move(line,0);clrtoeol();}
#define screen_clreol() clrtoeol()
#define screen_clrrest() { uint l,c;\
getyx(stdscr,l,c);\
for(l=l;l<LINES-2;++l){\
move(l,0);\
clrtoeol();\
}\
}
#define screen_update() { refresh();\
if (depend_shown){\
wrefresh(depend);\
}\
}
#define screen_touch_and_update() { touchwin(stdscr); refresh();\
if (depend_shown){\
touchwin(depend); wrefresh(depend);\
}\
}
extern int screen_init();
extern void screen_fini();
/* changed to functions for better results from curses
3/20/91 davew@panache.cs.umd.edu */
#endif
WINDOW *depend;
int depend_shown;
#endif

View File

@@ -0,0 +1 @@

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,730 @@
/* kill.c,v 1.1 1993/09/17 22:13:59 fbodin Exp */
/*
Dependence kill tests ("quick" and "accurate")
Naming convention: Many of these functions and structures
refer to "read iteration" or "write iteration" as if a
test were being performed on flow dependence(s), even when
the test works for other forms of dependence.
*/
#include <assert.h>
#include <string.h>
#include "include/portable.h"
#include <stdio.h>
#include <stdlib.h>
#include "include/debug.h"
#include "include/ip.h"
#include "include/lang-interf.h"
#include "include/ddomega-build.h"
#include "include/ddomega-use.h"
#include "include/kill.h"
#include "include/missing.h"
#include "include/timeTrials.h"
#include "include/Exit.h"
/* The following table shows the possible results
of combining two direction vectors:
! + 0 0+ - +- 0- *
! ! ! ! ! ! ! ! !
+ ! + + + * * * *
0 ! + 0 0+ - +- 0- *
0+ ! + 0+ 0+ * * * *
- ! * - * - * - *
+- ! * +- * * * * *
0- ! * 0- * - * 0- *
* ! * * * * * * *
*/
static int ddCombine[8][8] =
{ 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 1, 1, 7, 7, 7, 7,
0, 1, 2, 3, 4, 5, 6, 7,
0, 1, 3, 3, 7, 7, 7, 7,
0, 7, 4, 7, 4, 7, 4, 7,
0, 7, 5, 7, 7, 7, 7, 7,
0, 7, 6, 7, 4, 7, 6, 7,
0, 7, 7, 7, 7, 7, 7, 7 };
/*
Test to see if flow dependence f (from middle_acc to to_acc) kills
the flow dependence dd (from from_acc to to_acc)
via the output dependence o (from from_acc to middle_acc).
*/
static dddirection
do_test_for_kill_via(dir_and_dist_info *dd, char *dd_as_string,
a_access from_acc, a_access middle_acc, a_access to_acc,
dd_current f, dd_current o,
int commonDepth)
{
read_prob_desc rpd; /* write1s = A[i]
write2s = B[j]
reads = C[k]
we project onto i and k, so it doesn't
matter that either A or C or neither
could be the read */
Problem reads;
dir_and_dist_info tmp_ddi;
var_id sc_vars[maxVars], r_vars[maxVars], rs_vars[maxVars];
var_id w1_vars[maxVars], w1s_vars[maxVars];
var_id w2_vars[maxVars], w2s_vars[maxVars];
int from_depth, middle_depth, to_depth;
int Nrs, Nw1s, Nw2s, Nsc;
int j, red_complete;
#if ! defined NDEBUG
int eqs, geqs;
#endif
assert(access_store_p(middle_acc) || access_update_p(middle_acc));
from_depth = accesss_depth(from_acc);
middle_depth = accesss_depth(middle_acc);
to_depth = accesss_depth(to_acc);
#if defined newTimeTrials
if (storeResult) killTests++;
#endif
#ifndef SPEED
if (omegaPrintResult) {
fprintf(debug2, "continuing check for KILL\n");
fprintf(debug2, "Does %s\n", dd_current_as_string(f));
fprintf(debug2, "Kill %s\n", dd_as_string);
fprintf(debug2, "via %s\n", dd_current_as_string(o));
}
#endif
/* Quick check to see if direction vectors are feasible */
assert(commonDepth <= dd_current_nest(o));
for (j = 1; j <= commonDepth; j++) {
if (dd->distanceKnown[j] &&
dd_current_dist_known(f, j) &&
dd_current_dist_known(o, j))
{
if (dd_current_dist(f)[j] + dd_current_dist(o)[j] !=
dd->distance[j])
break;
}
else {
int m = ddCombine[ddextract1(dd_current_dir(f), j)]
[ddextract1(dd_current_dir(o), j)];
int t = ddextract1(dd->direction, j);
if ((m & t) != t) break;
}
}
if (j <= commonDepth) { /* break occured */
if (omegaPrintResult) {
fprintf(debug2,
"kill not feasible because of dddir at level %d\n",
j);
}
return 0;
}
/* PART 1: find sets of variables to be used in problem */
Nrs = Nw1s = Nw2s = Nsc = 0;
load_bounds_and_count_steps(to_acc, r_vars, rs_vars, &Nrs);
load_bounds_and_count_steps(from_acc, w1_vars, w1s_vars, &Nw1s);
load_bounds_and_count_steps(middle_acc, w2_vars, w2s_vars, &Nw2s);
load_constants_for_bounds(to_acc, sc_vars, &Nsc);
load_constants_for_bounds(from_acc, sc_vars, &Nsc);
load_constants_for_bounds(middle_acc, sc_vars, &Nsc);
load_constants_for_subscripts(to_acc, sc_vars, &Nsc);
load_constants_for_subscripts(from_acc, sc_vars, &Nsc);
load_constants_for_subscripts(middle_acc, sc_vars, &Nsc);
/* PART 2: assign columns to variables
Protect variables representing symbolic constants,
read iteration and 1st write values of loop indices,
because we wish to test if S implies T
for all values of them. */
read_init(&rpd, &reads, sc_r_and_w1, Nsc, sc_vars,
to_depth, r_vars, Nrs, rs_vars,
from_depth, w1_vars, Nw1s, w1s_vars,
middle_depth, w2_vars, Nw2s, w2s_vars);
/* PART 3: build problem */
#if !defined NDEBUG
read_inv(&rpd, &reads);
assert(reads.getNumEqs() == 0);
assert(reads.getNumGEqs() == 0);
eqs = geqs = 0;
#endif
/* TRY TO SET UP RED "T" PROBLEM:
"j in [B] ^ A(i) << B(j) << C(k) ^ A(i) sub= B(j) sub= C(k)"
If C is not exit, we can omit A(i) sub= B(j), as it is
redundant with B(j) sub= C(k) and A(i) sub= C(k)
IF WE CAN'T ESTABLISH COMPLETE RED BOUNDS, DON'T KILL */
/* j in [B] */
red_complete =
bound_indices_and_conditionals(&reads, &rpd.write2s,
&rpd.w2steps, &rpd.nonloops,
red, middle_acc);
if (to_acc != ExitNode) {
/* B(j) sub= C(k) */
/* equate_subs can't return 0 */
red_complete = red_complete &&
equate_subscripts(&reads, &rpd.reads, &rpd.write2s,
&rpd.nonloops,
red, to_acc, middle_acc) == complete;
}
else {
/* B(j) sub= A(i) */
/* equate_subs can't return 0 */
red_complete = red_complete &&
equate_subscripts(&reads, &rpd.write1s, &rpd.write2s,
&rpd.nonloops,
red, from_acc, middle_acc) == complete;
}
if (!red_complete)
{
if (omegaPrintResult) {
fprintf(debug2, "not checking KILL - incomplete red bounds \n");
}
read_cleanup(&rpd);
return 0;
}
/* B(j) << C(k) */
ddnode_to_dir_and_dist(f, &tmp_ddi);
constrain_with_dd(&reads, &rpd.reads, &rpd.write2s, &tmp_ddi, red);
/* A(i) << B(j) */
ddnode_to_dir_and_dist(o, &tmp_ddi);
constrain_with_dd(&reads, &rpd.write2s, &rpd.write1s, &tmp_ddi, red);
#if !defined NDEBUG
read_inv(&rpd, &reads);
for ( /* eqs as it is */; eqs < reads.getNumEqs(); eqs++)
{
assert(reads._EQs[eqs].color == red);
}
for ( /* geqs as it is */; geqs < reads.getNumGEqs(); geqs++)
{
assert(reads._GEQs[geqs].color == red);
}
#endif
/* SET UP BLACK "S" PROBLEM:
"i in [A] ^ k in [C] ^ A(i) << C(k) ^ A(i) sub= C(k)" */
/* i in [A] */
bound_indices_and_conditionals(&reads, &rpd.write1s, &rpd.w1steps,
&rpd.nonloops, black, from_acc);
/* k in [C] */
bound_indices_and_conditionals(&reads, &rpd.reads, &rpd.rsteps,
&rpd.nonloops, black, to_acc);
/* A(i) sub= C(k) */
/* this must be possible, or there would not be a dependence */
equate_subscripts(&reads, &rpd.reads, &rpd.write1s, &rpd.nonloops,
black, to_acc, from_acc);
/* A(i) << C(k) */
constrain_with_dd(&reads, &rpd.reads, &rpd.write1s, dd, black);
#if !defined NDEBUG
for (/* eqs as it is */; eqs < reads.getNumEqs(); eqs++) {
assert(reads._EQs[eqs].color == black);
}
for (/* geqs as it is */; geqs < reads.getNumGEqs(); geqs++) {
assert(reads._GEQs[geqs].color == black);
}
#endif
/* PART 4: clean up */
#if ! defined NDEBUG
read_inv(&rpd, &reads);
#endif
read_cleanup(&rpd);
/* PART 5: CHECK FOR KILL: Forall i,k,Sym, does S imply T? */
if (omegaPrintResult) {
fprintf(debug2, "checking for KILL in: \n");
printProblem(&reads);
}
#if defined newTimeTrials
if (storeResult) realKillTests++;
#endif
/* There must be a solution to the black equations,
because they describe a flow dependence from A to C */
if (!hasRedEquations(&reads, 0)) {
if (omegaPrintResult) {
fprintf(debug2, "verified KILL:\n");
printProblem(&reads);
}
#if defined newTimeTrials
if (storeResult) realKills++;
#endif
return ddkilled;
}
else {
if (omegaPrintResult) {
fprintf(debug2, "no KILL:\n");
printProblem(&reads);
}
return 0;
}
}
/*
Test to see if flow dependence dd2 (from write_acc2 to read_acc) kills
the flow dependence dd1 (frow write_acc1 to read_acc).
This should be called if quick_test_for_kill returns 0.
*/
dddirection
accurate_test_for_kill(dir_and_dist_info *dd, char *dd_as_string,
a_access from_acc, a_access to_acc,
dd_current this_dep)
{
dd_in_iterator potential_killers;
#ifndef SPEED
if (omegaPrintResult) {
fprintf(debug2, "starting check for KILL of dependence:\n");
fprintf(debug2, "%s\n", dd_as_string);
}
#endif
potential_killers = dd_i_i_for_access(to_acc);
while (!dd_i_i_done(potential_killers))
{
/* search for intervening writes or different updates */
if ((access_store_p(dd_i_i_cur_src(potential_killers)) ||
(access_update_p(dd_i_i_cur_src(potential_killers)) &&
!access_same_update_type_p(dd_i_i_cur_src(potential_killers),
to_acc) &&
!access_same_update_type_p(dd_i_i_cur_src(potential_killers),
from_acc))) &&
!dd_i_i_cur_is(potential_killers, this_dep))
{
dd_out_iterator o;
int commonDepth;
commonDepth = MIN(dd->nest, dd_current_nest(dd_i_i_current(potential_killers)));
o = dd_o_i_for_access(from_acc);
while (!dd_o_i_done(o))
{
if (dd_i_i_cur_src(potential_killers) == dd_o_i_cur_dest(o))
{
/* test for kill with output dep "o" */
dddirection d;
d = do_test_for_kill_via(dd, dd_as_string,
from_acc, dd_o_i_cur_dest(o),
to_acc,
dd_i_i_current(potential_killers),
dd_o_i_current(o), commonDepth);
if (d)
return d;
}
dd_o_i_next(o);
}
}
dd_i_i_next(potential_killers);
}
return 0;
}
/* The following table shows whether dd1 is strictly < dd2,
strictly <= dd2,
or possibly > dd2.
It is used in dd_is_shorter
If + in dd1, dd1 p> dd2
else if 0 in dd1, if - in dd2, dd1 p> dd2
else if dd2 == +, dd1 < dd2
else (0 or 0+) dd1 <= dd2
else (dd1 == -) if - in dd2, dd1 p> dd2
else dd1 < dd2
*/
typedef enum { pg = 0, le, lt } ddComparison;
/* compare[dd1][dd2] */
ddComparison ddCompare[8][8] =
{
/* DD2 + 0 0+ - +- 0- * */
/* DD1 */
/* */ { pg, pg, pg, pg, pg, pg, pg, pg },
/* + */ { pg, pg, pg, pg, pg, pg, pg, pg },
/* 0 */ { pg, lt, le, le, pg, pg, pg, pg },
/* 0+ */ { pg, pg, pg, pg, pg, pg, pg, pg },
/* - */ { pg, lt, lt, lt, pg, pg, pg, pg },
/* +- */ { pg, pg, pg, pg, pg, pg, pg, pg },
/* 0- */ { pg, lt, le, le, pg, pg, pg, pg },
/* * */ { pg, pg, pg, pg, pg, pg, pg, pg }
};
/* if possibly_shorter is strictly shorter than possibly_longer, return true
if possibly_shorter might be scum than possibly_longer, return false
if possibly_shorter is shorter or of equal length, return what_if_equal
possibly_shorter is assumed to be a covering dependence to the
same destination as possibly_longer, and thus possibly_longer
may be "partially refined".
*/
static int
dd_is_shorter(dd_current possibly_shorter,
dir_and_dist_info *possibly_longer,
int what_if_equal)
{
ddComparison c;
int j;
int minLength = MIN(possibly_longer->nest, dd_current_nest(possibly_shorter));
for (j = 1; j <= minLength; j++)
{
if (dd_current_dist_known(possibly_shorter, j) &&
possibly_longer->distanceKnown[j])
{
c = dd_current_dist(possibly_shorter)[j] < possibly_longer->distance[j] ? lt :
(dd_current_dist(possibly_shorter)[j] == possibly_longer->distance[j] ? le : pg);
}
else {
c = ddCompare[ddextract1(dd_current_dir(possibly_shorter), j)]
[ddextract1(possibly_longer->direction, j)];
}
switch (c) {
case lt:
return 1;
case pg:
return 0;
break;
case le:
if (!dddirtest(dd_current_dir(possibly_shorter), ddlt, j)) {
if (dddirtest(possibly_longer->direction, ddlt, j)) {
if (!(possibly_longer->direction & ddrefined))
{
clone_dd_graph_node_for_refinement(possibly_longer->dd_graph_node_to_be_cloned);
possibly_longer->direction |= ddrefined;
}
dddirreset(possibly_longer->direction, ddlt, j);
d_info_do_eq(possibly_longer, j);
};
if (!dddirtest(dd_current_dir(possibly_shorter), ddeq, j)
&& dddirtest(possibly_longer->direction, ddeq, j))
{
if (!(possibly_longer->direction & ddrefined))
{
clone_dd_graph_node_for_refinement(possibly_longer->dd_graph_node_to_be_cloned);
possibly_longer->direction |= ddrefined;
}
dddirreset(possibly_longer->direction, ddeq, j);
};
};
break;
}
}
/* le in all directions if we get here. */
return what_if_equal;
}
/*
Do quick but possibly indecisive kill tests to see
if dependence dd (from write_acc2 to read_acc) kills
the flow dependence dd1 (frow write_acc1 to read_acc).
If dd1 is obviously killed by dd2, this function will return
either ddiscovered or ddisterminated.
Otherwise, this function returns 0 (is which case dd2 may
or may not be killed - call accurate_test_for_kill to find out).
This function may update dd1 if dd1 is partly killed by dd2.
In this case, dd1's ddrefined bit will be set.
*/
dddirection
quick_test_for_kill(dir_and_dist_info *dd, char *dd_as_string,
a_access from_acc, a_access to_acc,
dd_current this_dep)
{
dd_in_iterator covers_dest; /* search for a dd that covers to_acc */
dd_out_iterator terms_src; /* search for a dd that terminates from_acc */
dddirection oldDirection = dd->direction;
assert(!ddisDead(dd->direction));
#ifndef SPEED
if (omegaPrintResult) {
fprintf(debug2, "starting quick kill check for:\n");
fprintf(debug2, "%s\n", dd_as_string);
}
#endif
covers_dest = dd_i_i_for_access(to_acc);
while (!dd_i_i_done(covers_dest))
{
a_access cur_src = dd_i_i_cur_src(covers_dest);
#if ! defined NOT_TINY
assert(covers_dest->ddsucc == to_acc);
#endif
if (!dd_i_i_cur_is(covers_dest, this_dep) &&
dd_i_i_cur_cover_p(covers_dest) &&
dd_is_shorter(dd_i_i_current(covers_dest), dd,
(accesss_shared_depth(from_acc, cur_src)
== dd->nest) &&
access_lexically_preceeds(from_acc, cur_src)))
{
if (omegaPrintResult) {
fprintf(debug2,
"Yes: there is a closer cover of the destination:\n");
fprintf(debug2, "%s\n",
dd_current_as_string(dd_i_i_current(covers_dest)));
}
return ddisCovered;
}
dd_i_i_next(covers_dest);
}
terms_src = dd_o_i_for_access(from_acc);
while (!dd_i_i_done(terms_src))
{
a_access cur_dest = dd_o_i_cur_dest(terms_src);
#if ! defined NOT_TINY
assert(terms_src->ddpred == from_acc);
#endif
if (!dd_o_i_cur_is(terms_src, this_dep) &&
dd_o_i_cur_terminate_p(terms_src) &&
dd_is_shorter(dd_o_i_current(terms_src), dd,
(accesss_shared_depth(to_acc, cur_dest)
== dd->nest) &&
access_lexically_preceeds(cur_dest, to_acc)))
{
if (omegaPrintResult) {
fprintf(debug2,
"Yes: there is a closer terminator of the source:\n");
fprintf(debug2, "%s\n",
dd_current_as_string(dd_i_i_current(terms_src)));
}
return ddisTerminated;
}
dd_o_i_next(terms_src);
}
if (omegaPrintResult) {
if (oldDirection != dd->direction)
fprintf(debug2, "direction vector refined but not killed\n");
else fprintf(debug2, "quick kill check indecisive\n");
}
return 0;
}
/* functions for manipulating "read problem descriptions" */
/* name information for buffers in getVarName fns */
#define MaxNameLen 254
#define MaxSuffixLen 1
#if !defined NDEBUG
static int var_id_is_step_expr(var_id n)
{
return n == 0;
}
void read_inv(read_prob_desc *rpd, Problem *p)
{
int v;
assert(p->getVarsN() < maxVars);
assert(p->getVarsN() >= read_Nvars(rpd));
assert(r_first(&rpd->nonloops) == 1);
assert(r_last(&rpd->nonloops) + 1 == r_first(&rpd->reads));
assert(r_last(&rpd->reads) + 1 == r_first(&rpd->rsteps));
assert(r_last(&rpd->rsteps) + 1 == r_first(&rpd->write1s));
assert(r_last(&rpd->write1s) + 1 == r_first(&rpd->w1steps));
assert(r_last(&rpd->w1steps) + 1 == r_first(&rpd->write2s));
assert(r_last(&rpd->write2s) + 1 == r_first(&rpd->w2steps));
for (v = 0; v < r_length(&rpd->nonloops); v++) {
assert(rpd->vars[v + r_first(&rpd->nonloops)] != NIL);
assert(var_id_const_p(rpd->vars[v + 1]));
assert(var_ids_tag(rpd->vars[v + 1]) == v + 1);
}
for (v = 0; v < r_length(&rpd->reads); v++) {
assert(rpd->vars[v + r_first(&rpd->reads)] != NIL);
assert(var_id_index_p(rpd->vars[v + r_first(&rpd->reads)]));
assert(var_ids_loop_no(rpd->vars[v + r_first(&rpd->reads)]) == v + 1);
}
for (v = 0; v < r_length(&rpd->rsteps); v++) {
assert(var_id_is_step_expr(rpd->vars[v + r_first(&rpd->rsteps)]));
}
for (v = 0; v < r_length(&rpd->write1s); v++) {
assert(rpd->vars[v + r_first(&rpd->write1s)] != NIL);
assert(var_id_index_p(rpd->vars[v + r_first(&rpd->write1s)]));
assert(var_ids_loop_no(rpd->vars[v + r_first(&rpd->write1s)]) == v + 1);
}
for (v = 0; v < r_length(&rpd->w1steps); v++) {
assert(var_id_is_step_expr(rpd->vars[v + r_first(&rpd->w1steps)]));
}
for (v = 0; v < r_length(&rpd->write2s); v++) {
assert(rpd->vars[v + r_first(&rpd->write2s)] != NIL);
assert(var_id_index_p(rpd->vars[v + r_first(&rpd->write2s)]));
assert(var_ids_loop_no(rpd->vars[v + r_first(&rpd->write2s)]) == v + 1);
}
for (v = 0; v < r_length(&rpd->w2steps); v++) {
assert(var_id_is_step_expr(rpd->vars[v + r_first(&rpd->w2steps)]));
}
for (v = 0; v < p->getNumGEqs(); v++) {
assert(p->_GEQs[v].touched);
}
}
#endif
static char *read_getVarName(uint v, void *args)
{
read_prob_desc *rpd = (read_prob_desc*)args;
static char name[MaxNameLen + MaxSuffixLen + 1];
assert(v <= read_Nvars(rpd));
if (rpd->vars[v] &&
(var_id_const_p(rpd->vars[v]) || var_id_index_p(rpd->vars[v]))) {
strncpy(name, var_ids_name(rpd->vars[v]), MaxNameLen);
name[MaxNameLen] = 0;
}
else {
assert(var_id_is_step_expr(rpd->vars[v]));
strcpy(name, "<trip>");
}
if (r_in(&rpd->reads, v) || r_in(&rpd->rsteps, v))
strcat(name, "0");
else if (r_in(&rpd->write1s, v) || r_in(&rpd->w1steps, v))
strcat(name, "1");
else if (r_in(&rpd->write2s, v) || r_in(&rpd->w2steps, v))
strcat(name, "2");
return name;
}
void read_init(read_prob_desc *rpd, Problem *p,
protect_in_read protect_which, uint Nsc, var_id sc_vars[],
uint Nr, var_id r_vars[], uint Nrs, var_id rs_vars[],
uint Nw1, var_id w1_vars[], uint Nw1s, var_id w1s_vars[],
uint Nw2, var_id w2_vars[], uint Nw2s, var_id w2s_vars[])
{
int v;
rpd->nonloops._first = 1;
rpd->nonloops._length = Nsc;
rpd->reads._first = 1 + Nsc;
rpd->reads._length = Nr;
rpd->rsteps._first = 1 + Nsc + Nr;
rpd->rsteps._length = Nrs;
rpd->write1s._first = 1 + Nsc + Nr + Nrs;
rpd->write1s._length = Nw1;
rpd->w1steps._first = 1 + Nsc + Nr + Nrs + Nw1;
rpd->w1steps._length = Nw1s;
rpd->write2s._first = 1 + Nsc + Nr + Nrs + Nw1 + Nw1s;
rpd->write2s._length = Nw2;
rpd->w2steps._first = 1 + Nsc + Nr + Nrs + Nw1 + Nw1s + Nw2;
rpd->w2steps._length = Nw2s;
if (read_Nvars(rpd) > maxVars) {
assert(0 && "Problem too big");
fprintf(stderr, "Too many variables for omega test\n");
Exit(2);
/* Could we handle this by not doing r/k/c? */
}
rpd->vars[0] = 0;
/* sc_vars[0..Nsc-1] are valid */
for (v = 0; v < Nsc; v++) {
assert(sc_vars[v] != NIL);
rpd->vars[v + r_first(&rpd->nonloops)] = sc_vars[v];
var_ids_tag(sc_vars[v]) = v + r_first(&rpd->nonloops);
}
/* r_vars[1..Nr] are valid */
for (v = 0; v < r_length(&rpd->reads); v++) {
assert(r_vars[v + 1] != NIL);
rpd->vars[v + r_first(&rpd->reads)] = r_vars[v + 1];
}
for (v = 0; v < r_length(&rpd->write1s); v++) {
assert(w1_vars[v + 1] != NIL);
rpd->vars[v + r_first(&rpd->write1s)] = w1_vars[v + 1];
}
for (v = 0; v < r_length(&rpd->write2s); v++) {
assert(w2_vars[v + 1] != NIL);
rpd->vars[v + r_first(&rpd->write2s)] = w2_vars[v + 1];
}
/* rs_vars[0..Nrs] hold steps FROM INNERMOST TO OUTERMOST LOOPS */
for (v = 0; v < Nrs; v++) {
assert(rs_vars[Nrs - 1 - v] == NIL);
rpd->vars[v + r_first(&rpd->rsteps)] = rs_vars[Nrs - 1 - v];
}
for (v = 0; v < Nw1s; v++) {
assert(w1s_vars[Nw1s - 1 - v] == NIL);
rpd->vars[v + r_first(&rpd->w1steps)] = w1s_vars[Nw1s - 1 - v];
}
for (v = 0; v < Nw2s; v++) {
assert(w2s_vars[Nw2s - 1 - v] == NIL);
rpd->vars[v + r_first(&rpd->w2steps)] = w2s_vars[Nw2s - 1 - v];
}
init_prob(p, read_Nvars(rpd),
protect_which == sc_and_r ? Nsc + Nr + Nrs : Nsc + Nr + Nrs + Nw1 + Nw1s,
read_getVarName, rpd);
}
/* clear the tags for symbolic constants */
void read_cleanup(read_prob_desc *rpd)
{
int v;
for (v = 0; v < r_length(&rpd->nonloops); v++) {
var_ids_tag(rpd->vars[v + r_first(&rpd->nonloops)]) = UNTAGGED;
}
}

View File

@@ -0,0 +1,604 @@
/* refine.c,v 1.1 1993/09/17 22:14:00 fbodin Exp */
/*
Refinement tests
Naming convention: Many of these functions and structures
refer to "read iteration" or "write iteration" as if a
test were being performed on flow dependence(s), even when
the test works for other forms of dependence.
*/
#include <assert.h>
#include <string.h>
#include "include/portable.h"
#include <stdio.h>
#include <stdlib.h>
#include "include/debug.h"
#include "include/ip.h"
#include "include/lang-interf.h"
#include "include/ddomega-build.h"
#include "include/ddomega-use.h"
#include "include/ddomega.h"
#include "include/omega2flags.h"
#include "include/kill.h"
#include "include/cover.h"
#include "include/refine.h"
#include "include/missing.h"
#include "include/timeTrials.h"
/*
check to see if a data dependence can be refined at the source,
and change d_info if so
*/
typedef enum { source, dest } which_end;
static void refine_end(a_access access_A, a_access access_B, which_end which,
dir_and_dist_info *d_info)
{
uint access_B_nest = accesss_depth(access_B),
access_A_nest = accesss_depth(access_A);
read_prob_desc rpd; /* write1s = A[i]
write2s = A[j] (or B[j] if which == dest)
reads = B[k] */
delta_prob_desc dpd; /* original dependence: A[i] --> B[k] */
Problem reads, new_deltas;
bool red_complete;
var_id sc_vars[maxVars], B_indices[maxVars], B_steps[maxVars];
var_id A_indices[maxVars], A_steps[maxVars];
int NBsteps, NAsteps, Nsc;
int l, u, j;
dd_in_iterator o;
int anyRefinementPossible = 0;
int refinementPossible[maxCommonNest];
#if ! defined NDEBUG
bool possible_dependence, simplified;
#endif
#if defined newTimeTrials
if (storeResult) refineTests++;
#endif
assert(!(which == source) || !access_fetch_p(access_A));
assert(!(which == dest) || !access_fetch_p(access_B));
if (omegaPrintResult) {
fprintf(debug2, "attempting refinement of %s of dependence\n",
which == source ? "source" : "destination");
fprintf(debug2, "\tfrom a store of %s at statement %d\n",
access_as_string(access_A), accesss_lineno(access_A));
fprintf(debug2, "\tto a read of %s at statement %d\n",
access_as_string(access_B), accesss_lineno(access_B));
fprintf(debug2, "\tdddir = %x, ", d_info->direction);
fprintf(debug2, "\trestraint = %x\n", d_info->restraint);
}
/* First, verify that the dependence isn't constant */
for (j = 1; j <= d_info->nest; j++)
if (!d_info->distanceKnown[j]) break;
/* if all constant or d_info->nest == 0, no need to refine */
if (j > d_info->nest) {
if (omegaPrintResult) {
fprintf(debug2, "no non-constant distances to refine\n");
}
return;
}
/* Check which dimensions refinement is feasible in */
for (j = 1; j <= d_info->nest; j++)
refinementPossible[j] = 0;
o = dd_i_i_for_access((which == source) ? access_A : access_B);
while (!dd_i_i_done(o))
{
if (dd_i_i_cur_src(o) == ((which == source) ? access_A : access_B))
{
/* self output/reduction dependence to end we're refining */
assert(dd_i_i_cur_dest(o) == dd_i_i_cur_src(o));
for (j = 1; j <= d_info->nest; j++) {
if (!d_info->distanceKnown[j] &&
dddirtest(dd_current_dir(dd_i_i_current(o)),
ddlt | ddgt, j))
{
refinementPossible[j] = 1;
anyRefinementPossible = 1;
}
}
}
dd_i_i_next(o);
}
if (!anyRefinementPossible) {
if (omegaPrintResult)
fprintf(debug2, "Fast break out of refinement\n");
return;
}
/* BUILD BLACK PROBLEM IN "new_deltas" :
i in [A] ^ k in [B] ^ A(i) << B(k) ^ A(i) sub= B(k) */
#if ! defined NDEBUG
possible_dependence =
#endif
build_delta_prob_desc(&dpd, &new_deltas, access_A, access_B,
access_A_nest, access_B_nest, d_info->nest);
assert(possible_dependence);
/* The A(i) << B(k) part */
constrain_with_dd(&new_deltas, &dpd.access2s, &dpd.access1s, d_info, black);
/* PART 1: find sets of variables to be used in problem */
NBsteps = NAsteps = Nsc = 0;
load_bounds_and_count_steps(access_B, B_indices, B_steps, &NBsteps);
load_bounds_and_count_steps(access_A, A_indices, A_steps, &NAsteps);
load_constants_for_bounds(access_B, sc_vars, &Nsc);
load_constants_for_bounds(access_A, sc_vars, &Nsc);
load_constants_for_subscripts(access_B, sc_vars, &Nsc);
load_constants_for_subscripts(access_A, sc_vars, &Nsc);
if (which == source)
{
/* PART 2: assign columns to variables */
read_init(&rpd, &reads, sc_and_r, Nsc, sc_vars,
access_B_nest, B_indices, NBsteps, B_steps,
access_A_nest, A_indices, NAsteps, A_steps,
access_A_nest, A_indices, NAsteps, A_steps);
#if ! defined NDEBUG
read_inv(&rpd, &reads);
#endif
/* PART 3: set up equations in "reads" */
/* SET UP BLACK PROBLEM IN "reads", IDENTICAL TO THAT IN "new_deltas":
i in [A] ^ k in [B] ^ A(i) << B(k) ^ A(i) sub= B(k) */
/* SET UP i in [A] */
bound_indices_and_conditionals(&reads, &rpd.write1s, &rpd.w1steps,
&rpd.nonloops, black, access_A);
/* SET UP k in [B] */
bound_indices_and_conditionals(&reads, &rpd.reads, &rpd.rsteps,
&rpd.nonloops, black, access_B);
/* SET UP A(i) sub= B(k) (this can not return 0) */
#if ! defined NDEBUG
possible_dependence =
#endif
equate_subscripts(&reads, &rpd.write1s, &rpd.reads, &rpd.nonloops,
black, access_A, access_B);
assert(possible_dependence);
constrain_with_dd(&reads, &rpd.reads, &rpd.write1s, d_info, black);
/* TRY TO SET UP RED PROBLEM IN "reads", EXCEPT REFINEMENT VECTOR PART.
IF WE CAN'T ESTABLISH COMPLETE RED BOUNDS, DON'T REFINE
IF which == source, RED PROBLEM = j in [A] ^ A(j) sub= B(k)
*/
red_complete = /* j in [A] ^ A(j) sub= B(k) */
((equate_subscripts(&reads, &rpd.reads, &rpd.write2s, &rpd.nonloops,
red, access_B, access_A) == complete) &&
(bound_inner_indices_and_conditionals(&reads, &rpd.write2s,
&rpd.w2steps, &rpd.nonloops,
leading_zeros(d_info->direction,
d_info->nest),
access_B,
red, access_A)));
}
else {
/* PART 2: assign columns to variables */
read_init(&rpd, &reads, sc_and_r, Nsc, sc_vars,
access_A_nest, A_indices, NBsteps, A_steps,
access_B_nest, B_indices, NBsteps, B_steps,
access_B_nest, B_indices, NBsteps, B_steps);
#if ! defined NDEBUG
read_inv(&rpd, &reads);
#endif
/* PART 3: set up equations in "reads" */
/* SET UP BLACK PROBLEM IN "reads", IDENTICAL TO THAT IN "new_deltas":
i in [A] ^ k in [B] ^ A(i) << B(k) ^ A(i) sub= B(k) */
/* SET UP i in [A] */
bound_indices_and_conditionals(&reads, &rpd.reads, &rpd.rsteps,
&rpd.nonloops, black, access_A);
/* SET UP k in [B] */
bound_indices_and_conditionals(&reads, &rpd.write2s, &rpd.w2steps,
&rpd.nonloops, black, access_B);
/* SET UP A(i) sub= B(k) (this can not return 0) */
#if ! defined NDEBUG
possible_dependence =
#endif
equate_subscripts(&reads, &rpd.reads, &rpd.write2s, &rpd.nonloops,
black, access_A, access_B);
assert(possible_dependence);
constrain_with_dd(&reads, &rpd.write2s, &rpd.reads, d_info, black);
/* TRY TO SET UP RED PROBLEM IN "reads", EXCEPT REFINEMENT VECTOR PART.
IF WE CAN'T ESTABLISH COMPLETE RED BOUNDS, DON'T REFINE
IF which == dest, RED PROBLEM = j in [B] ^ A(i) sub= B(j)
*/
red_complete = /* j in [B] ^ A(i) sub= B(j) */
((equate_subscripts(&reads, &rpd.write1s, &rpd.write2s, &rpd.nonloops,
red, access_B, access_A) == complete) &&
(bound_inner_indices_and_conditionals(&reads, &rpd.write2s,
&rpd.w2steps, &rpd.nonloops,
leading_zeros(d_info->direction,
d_info->nest),
access_A,
red, access_B)));
}
if (!red_complete)
{
if (omegaPrintResult) {
fprintf(debug2,
"not checking for refinement - incomplete red bounds\n");
}
read_cleanup(&rpd);
return;
}
/* START WITH REFINEMENT VECTOR = DEPENDENCE VECTOR,
THEN IN REFINEMENT, WE'LL SHORTEN IT */
if (which == source) {
/* SET UP A(j) << B(k) */
constrain_with_dd(&reads, &rpd.reads, &rpd.write2s, d_info, red);
}
else {
/* SET UP A(i) << B(j) */
constrain_with_dd(&reads, &rpd.write1s, &rpd.reads, d_info, red);
}
/* PART 4: clean up */
#if ! defined NDEBUG
read_inv(&rpd, &reads);
#endif
read_cleanup(&rpd);
/* PART 5: TRY TO REFINE DEPENDENCE */
#if ! defined NDEBUG
simplified =
#endif
simplifyProblem(&new_deltas);
assert(simplified && "new_deltas can be simplified"); /* ferd */
#if defined newTimeTrials
if (storeResult) semiRealRefineTests++;
#endif
/* go from outer to inner loops, trying to change + to its minimum */
for (j = 1; j <= d_info->nest; j++) {
uint e;
/* if dddist is unknown, try to refine:
see if min distance will cancel out all others */
if (!d_info->distanceKnown[j]) {
int fiendish;
if (!refinementPossible[j]) break;
fiendish = queryVariableBounds(&new_deltas,
r_first(&dpd.deltas) - 1 + j,
&l, &u);
if (fiendish)
if (ddextract1(d_info->direction, j) == (ddeq | ddlt)) {
l = 0;
u = posInfinity;
}
else
{
int k;
Problem new_new_deltas;
problemcpy(&new_new_deltas, &new_deltas);
for (k = 1; k <= d_info->nest; k++) {
if (k != j) {
unprotectVariable(&new_new_deltas,
r_first(&dpd.deltas) - 1 + k);
}
}
#if ! defined NDEBUG
simplified =
#endif
simplifyProblem(&new_new_deltas);
assert(simplified && "new_new_deltas can be simplified"); /*ferd*/
fiendish = queryVariableBounds(&new_new_deltas,
r_first(&dpd.deltas) - 1 + j,
&l, &u);
if (fiendish) {
eliminateRedundant(&new_new_deltas, 0);
simplifyProblem(&new_new_deltas);
fiendish = queryVariableBounds(&new_new_deltas,
r_first(&dpd.deltas) - 1 + j,
&l, &u);
};
if (fiendish) {
eliminateRedundant(&new_new_deltas, 1);
simplifyProblem(&new_new_deltas);
fiendish = queryVariableBounds(&new_new_deltas,
r_first(&dpd.deltas) - 1 + j,
&l, &u);
};
if (fiendish) {
#if defined newTimeTrials
if (storeResult) {
#endif
strange_occurance("Problem still fiendish in refine:\n");
/* debug2 and outputFile should always be the same */
printProblem(&new_new_deltas);
#if defined newTimeTrials
}
#endif
break; /* just stop refining */
}
}
if (l == u) { /* no need to refine, distance is known */
if (l == 0) {
dddironly(d_info->direction, ddeq, j);
d_info_do_eq(d_info, j)
}
else if (l > 0) {
dddironly(d_info->direction, ddlt, j);
}
else {
dddironly(d_info->direction, ddgt, j);
}
d_info->distanceKnown[j] = 1;
d_info->distance[j] = l;
}
else if (l != negInfinity && !(skipping_plus_refinement && l > 0))
{
int result;
Problem tmpProb;
problemcpy(&tmpProb, &reads);
/* Try to constrain delta index variable #j to exactly l
in red equations
That is, try to strengthen D in "A(j) <<D B(k)"
(or, if refining dest, in "A(i) <<D B(j)") */
if (which == source) {
int varj, vark; /* variable[k] - variable[j] = l */
vark = r_first(&rpd.reads) - 1 + j;
varj = r_first(&rpd.write2s) - 1 + j;
e = prob_add_zero_EQ(&tmpProb, red);
tmpProb._EQs[e].coef[varj] = -1;
tmpProb._EQs[e].coef[vark] = 1;
tmpProb._EQs[e].coef[0] = -l;
}
else {
int vari, varj; /* variable[j] - variable[i] = l */
vari = r_first(&rpd.reads) - 1 + j;
varj = r_first(&rpd.write1s) - 1 + j;
e = prob_add_zero_EQ(&tmpProb, red);
tmpProb._EQs[e].coef[vari] = -1;
tmpProb._EQs[e].coef[varj] = 1;
tmpProb._EQs[e].coef[0] = -l;
}
/* if there are remaining red equations,
then ! (black problem in red problem), and
we can't refine delta j to u, so stop refining */
/* the black equations represent the write1 - read
flow dependence, so they must have a solution,
(if the dep. has not been refined, we wouldn't
be here unless there were a dependence. And
refinement can't eliminate all the solutions,
since we only restrict the black equations to
values that don't constrain the solutions.)
Thus, it is ok to call hasRedEquations here. */
result = hasRedEquations(&tmpProb, 0);
#if defined newTimeTrials
if (storeResult) realRefineTests++;
#endif
if (omegaPrintResult) {
if (result && !refinementPossible[j])
fprintf(debug2, "fast test could have saved refinement check\n");
if (!result && !refinementPossible[j])
fprintf(debug2, "fast test didn't think refinement was possible\n");
}
if (result) break;
#if defined newTimeTrials
if (storeResult) realRefines++;
#endif
/* else, refine delta j to u in delta and read */
/* deltas must be constrained in terms of deltas:
read - write = l --> delta = -l --> delta + l = 0 */
constrainVariableValue(&new_deltas, black,
r_first(&dpd.deltas) - 1 + j,
l);
if (which == source)
{
/* reads must be constrained in terms of read & write */
e = prob_add_zero_EQ(&reads, black);
reads._EQs[e].coef[r_first(&rpd.reads) - 1 + j] = 1;
reads._EQs[e].coef[r_first(&rpd.write1s) - 1 + j] = -1;
reads._EQs[e].coef[0] = -l;
e = prob_add_zero_EQ(&reads, red);
reads._EQs[e].coef[r_first(&rpd.reads) - 1 + j] = 1;
reads._EQs[e].coef[r_first(&rpd.write2s) - 1 + j] = -1;
reads._EQs[e].coef[0] = -l;
}
else {
/* reads must be constrained in terms of read & write */
e = prob_add_zero_EQ(&reads, black);
reads._EQs[e].coef[r_first(&rpd.write2s) - 1 + j] = 1;
reads._EQs[e].coef[r_first(&rpd.reads) - 1 + j] = -1;
reads._EQs[e].coef[0] = -l;
e = prob_add_zero_EQ(&reads, red);
reads._EQs[e].coef[r_first(&rpd.write1s) - 1 + j] = 1;
reads._EQs[e].coef[r_first(&rpd.reads) - 1 + j] = -1;
reads._EQs[e].coef[0] = -l;
}
if (!(d_info->direction & ddrefined))
{
clone_dd_graph_node_for_refinement(d_info->dd_graph_node_to_be_cloned);
d_info->direction |= ddrefined;
}
if (l == 0) {
dddironly(d_info->direction, ddeq, j);
d_info_do_eq(d_info, j);
}
else if (l > 0) {
dddironly(d_info->direction, ddlt, j);
}
else {
dddironly(d_info->direction, ddgt, j);
}
d_info->distanceKnown[j] = 1;
d_info->distance[j] = l;
}
else break; /* minimum distance in loop is neg Infinity */
}
}
}
/*
if from_acc is a write, call refine_source
if to_acc is a write, call refine_dest
(If both are writes, I think we could get a bit more refinement
by having a refine_both, which tries to refine either the source
or the destination at each loop nest. I also think this would be
so rare that its not worth writing the code.)
*d_info will be updated if refinement is successful
*/
void refine_dependence(a_access from, a_access to,
dir_and_dist_info *d_info)
{
/* Read accesses, update operations of the same type as
one end of the dependence, and the Entry & Exit nodes
can not kill dependences. Thus, avoid refining with them. */
if (!access_fetch_p(from) && !access_update_p(from) && from != Entry)
{
assert(access_store_p(from));
refine_end(from, to, source, d_info);
}
if (!access_fetch_p(to) && !access_update_p(to) && to != ExitNode)
{
assert(access_store_p(to));
refine_end(from, to, dest, d_info);
}
}
/*
try to refine a cover or terminator's leading 0+'s into 0's.
*/
typedef int(*test_for_one)(a_access, a_access,
uint, uint, uint, dir_and_dist_info *,
char *);
static void tighten_cover_or_terminator(a_access from_acc, a_access to_acc,
dir_and_dist_info *d_info,
char *dd_as_string,
test_for_one which_test)
{
int i;
#if ! defined SPEED
char str[TINYBUFSIZ + sizeof("tightening of ")];
strcpy(str, "tightening of ");
strcat(str, dd_as_string);
#else
char *str = "Tiny must be compiled without -DSPEED for debugging info";
#endif
assert((*which_test)(from_acc, to_acc,
accesss_depth(from_acc),
accesss_depth(to_acc),
accesss_shared_depth(from_acc, to_acc),
d_info, dd_as_string));
#if defined newTimeTrials
if (storeResult) tightenTests++;
#endif
/* prototype version - build & solve problem again and again
profiling suggests that we don't waste significant time here. */
/* go from outer loops to inner, changing 0+ to 0 */
for (i = 1; i <= d_info->nest; i++)
{
if (ddextract1(d_info->direction, i) == (ddeq | ddlt))
{
/* we have a 0+ */
dir_and_dist_info new_info = *d_info;
dddirreset(new_info.direction, ddlt, i);
dddirreset(new_info.restraint, ddlt, i);
#if defined newTimeTrials
if (storeResult) realTightenTests++;
#endif
if ((*which_test)(from_acc, to_acc,
accesss_depth(from_acc),
accesss_depth(to_acc),
accesss_shared_depth(from_acc, to_acc),
&new_info, str))
{
if (!(d_info->direction & ddrefined)) {
clone_dd_graph_node_for_refinement(d_info->dd_graph_node_to_be_cloned);
}
d_info->direction = new_info.direction | ddrefined;
d_info->restraint = new_info.restraint;
d_info->distanceKnown[i] = 1;
d_info->distance[i] = 0;
}
}
if (ddextract1(d_info->direction, i) != ddeq)
break;
}
}
void tighten_cover(a_access from_acc, a_access to_acc,
dir_and_dist_info *d_info,
char *dd_as_string)
{
assert(d_info->direction & ddcovers);
tighten_cover_or_terminator(from_acc, to_acc, d_info, dd_as_string,
test_for_coverage);
}
void tighten_terminator(a_access from_acc, a_access to_acc,
dir_and_dist_info *d_info,
char *dd_as_string)
{
assert(d_info->direction & ddterminates);
tighten_cover_or_terminator(from_acc, to_acc, d_info, dd_as_string,
test_for_termination);
}

View File

@@ -0,0 +1,285 @@
/* sagedriver.c,v 1.2 1994/07/05 15:34:07 fbodin Exp */
/*
Driver routine for dependence testing with the omega test.
A different driver is used for several reasons:
- we use coverage information to decide whether or not to check for
a flow dependence
- we don't want the funky values for the loop nesting
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#define DEBUG 0
#include "include/portable.h"
#include "include/ip.h"
#include "include/affine.h" /* for an assertion about node_is_affine */
#include "include/lang-interf.h"
#define GLOB
#include "include/flags.h"
/* to be define later */
affine_expr not_affine = { -1, { 0 }, 0 };
extern int toBeCalledByOmegaTest(int tdep, int kdep, int *dist, int *kdist, int le, int from, int to);
/*
* Do closing procedures
*/
extern void ExitFromOmegaTest(const int c);
void Exit(int c)
{
switch (c) {
case 0:
break;
case 1:
fprintf(stderr, "Exit apparently due to user error (exit code 1)\n");
break;
case 2:
case -2:
fprintf(stderr, "Exit apparently due to system limitation or error (exit code %d)\n", c);
break;
default:
fprintf(stderr, "Something really bad happened (exit code %d)\n", c);
break;
}
ExitFromOmegaTest(c);
}
/*
* Assertion failed
*/
void ErrAssert(char *t) {
if (Argv)
fprintf(stderr, "\n%s: %s\n", &Argv[0][0], t);
else
fprintf(stderr, " %s\n", t);
Exit(-2);
}
int dd_carried_by(dddirection dv, int length)
{
int depth;
for (depth = 1; (depth <= length && ddextract1(dv, depth) == ddeq); depth++)
;
/* dd dirs [1..depth-1] are 0 */
return depth;
}
int leading_zeros(dddirection dv, int length)
{
int depth;
for (depth = 1; (depth <= length && ddextract1(dv, depth) == ddeq); depth++)
;
/* dd dirs [1..depth-1] are 0 */
return depth - 1;
}
void append_dd_flags(char *line, dddirection dv)
{
if (dv & ddkilled ||
dv & ddisCovered || dv & ddisTerminated || dv & ddisRefined ||
dv & ddrefined || dv & ddcovers || dv & ddterminates ||
dv & ddzappable || dv & ddzappableWC)
{
strcat(line, " [");
if (dv & ddcovers) strcat(line, "C");
if (dv & ddterminates) strcat(line, "T");
if (dv & ddrefined) strcat(line, "R");
if (!(dv & ddcovers) &&
!(dv & ddterminates) &&
!(dv & ddrefined)) strcat(line, " ");
if (dv & ddkilled) strcat(line, "k");
if (dv & ddisCovered) strcat(line, "c");
if (dv & ddisTerminated) strcat(line, "t");
if (dv & ddisRefined) strcat(line, "r");
if (dv & ddzappable) strcat(line, "Z");
if (dv & ddzappableWC) strcat(line, "?");
strcat(line, "]");
}
}
/* some temporary definition of functions, to be modified later */
void ddnode_to_dir_and_dist(dd_current a, dir_and_dist_info *b)
{
printf(" Calling ddnode_to_dir_and_dist\n");
}
/* coming from the sage part */
#define MAXNESTEDLOOP 100
#define DEPZERO 1
#define DEPGREATER 2
#define DEPLESS 4
#define WRONGDEP 0
#define ARRAYDEP 1
#define PRIVATEDEP 2
#define REDUCTIONDEP 3
#define SCALARDEP 4
void store_dependence(ddnature nature, a_access from_access, a_access to_access, dir_and_dist_info *d_info)
{
int i;
int tdep;
int kdep;
int dist[MAXNESTEDLOOP];
int kdist[MAXNESTEDLOOP];
tdep = ARRAYDEP;
if (d_info)
{
switch (nature)
{
case ddflow:
if (DEBUG)
printf("Omega test found a FLOW dependence: (");
kdep = ddflow;
break;
case ddanti:
if (DEBUG)
printf("Omega test found a ANTI dependence: (");
kdep = ddanti;
break;
case ddoutput:
if (DEBUG)
printf("Omega test found a OUTPUT dependence: (");
kdep = ddoutput;
break;
case ddreduce:
if (DEBUG)
printf("Omega test found a REDUCE dependence: (");
kdep = ddreduce;
break;
default:
printf("Omega test found an UNKNOWN dependence: (");
kdep = ddflow;
tdep = WRONGDEP;
break;
}
for (i = 1; i <= d_info->nest; i++)
{
if (d_info->distanceKnown[i])
{
if (DEBUG)
printf("%d", d_info->distance[i]);
kdist[i] = DEPZERO;
dist[i] = d_info->distance[i];
}
else
{
kdist[i] = 0;
dist[i] = 0;
if (dddirtest(d_info->direction, ddeq, i))
{
dist[i] = dist[i] + 1; /* temporary */
if (DEBUG)
printf("0");
}
if (dddirtest(d_info->direction, ddlt, i))
{
dist[i] = dist[i] + DEPGREATER; /* temporary */
if (DEBUG)
printf("+");
}
if (dddirtest(d_info->direction, ddgt, i))
{
dist[i] = dist[i] + DEPLESS; /* temporary */
if (DEBUG)
printf("-");
}
}
if (i < d_info->nest)
if (DEBUG)
printf(", ");
}
if (DEBUG)
printf(")\n"); /* if (from_access->lexord > to_access->lexord)*/
toBeCalledByOmegaTest(tdep, kdep, dist, kdist, d_info->nest, from_access->idforsage, to_access->idforsage);
/*else
toBeCalledByOmegaTest(tdep,kdep,dist,kdist,d_info->nest,-1);*/
}
else
{
if (DEBUG)
printf("Omega Test Found no Dependence\n");
}
}
void dir_and_dist_into_ddnode(const dir_and_dist_info *ddi, dd_current b)
{
/* printf(" Calling dir_and_dist_into_ddnode\n");*/
}
void Message_Add(char *str)
{
printf("Message_Add %s\n", str);
}
void clone_dd_graph_node_for_refinement(void *dd_graph_node_to_be_cloned)
{
/* printf(" Calling clone_dd_graph_node_for_refinement\n");*/
}
void SetOmegaDebug()
{
extern FILE *debug2;
debugLevel = 3;
setOutputFile(stdout);
omegaPrintResult = 1;
debug2 = stdout;
}
void SetSTuff()
{
extern FILE *debug2;
/* debugLevel = 3;
setOutputFile(stdout);
omegaPrintResult = 1;
debug2 = stdout; */
initializeOmega();
}
int access_is_in_then_or_else_of(a_access A, context_iterator C)
{
context_iterator it1, it2;
if (!C || !A)
return 0;
it1 = A->context;
it2 = C;
if (!cont_i_cur_loop_p(it2))
return 0;
while (!cont_i_done(it1))
{
if (!cont_i_cur_loop_p(it1))
{
if (cont_i_cur_if(it1)->ident == cont_i_cur_if(it2)->ident)
return 1;
}
cont_i_next(it1);
}
return 0;
}

View File

@@ -0,0 +1,52 @@
***************************** PRELIMINARY ***************************
This file contains PRELIMINARY extensions to the basic sage system.
It mainly consists in an interface with the Omega test.
A demo program using the functionnalities of this library is given in
DemoDataDep. Documentation for this library is not yet available.
This directory contains the following files:
Makefile : just do make: create the library libDep.a
OmegaForSage : directory containing the Omega test src code
annotationDriver.C/.h : Interface in sage with the annotation system
arrayRef.C/.h : routine to create sets of array references (no yet completed)
give the index in affine form when possible
computeInducVar.C : Induction variable computation (no yet completed)
inducVar.h : structure for Induction variables
constanteProp.C : constante propagation routine (no yet completed)
constanteSet.h : constante data structure
controlFlow.C : routine to get the control flow in program (no yet completed)
defUse.C : compute for each statement the set of variables defined and used
(no yet completed)
definitionSet.h : for defUse.C
depGraph.C : data dependence graph (no yet completed)
depGraph.h : class declaration of the data dep graph
dependence.C : Interface with the omega test (no yet completed).
dependence.h :
flowAnalysis.C : support for data flow analysis (no yet completed)
intrinsic.C : list of intrinsic functions (no yet completed)
intrinsic.h :
invariant.C : (no yet completed)
loopTransform.C : simple loop transformations for sage (no yet completed)
set.C : basic class for dealing with object sets.
set.h :

View File

@@ -0,0 +1,329 @@
#include <stdio.h>
#include <string.h>
#include "sage++user.h"
#include "annotationDriver.h"
//////////////////////////////////////////////////////////////
// set of functions in the library
//////////////////////////////////////////////////////////////
#ifdef __SPF
extern "C" void addToCollection(const int line, const char *file, void *pointer, int type);
extern "C" void removeFromCollection(void *pointer);
#endif
extern "C" {
int initAnnotation();
PTR_LLND Get_Define_Field(...);
char *Get_Define_Label_Field(...);
char *Get_Label_Field(...);
PTR_LLND Get_ApplyTo_Field(...);
PTR_LLND Get_ApplyToIf_Field(...);
PTR_LLND Get_LocalVar_Field(...);
PTR_LLND Get_Annotation_Field(...);
char *Get_Annotation_Field_Label(...);
char *Unparse_Annotation(...);
char *Does_Annotation_Defines(...);
int Get_Annotation_With_Label(...);
int Get_Scope_Of_Annotation(...);
PTR_LLND Does_Annotation_Apply(...);
PTR_LLND Get_Annotation_Field_List_For_Stmt(...);
PTR_LLND Get_Annotation_List_For_Stmt(...);
int Get_Number_of_Annotation();
PTR_BFND Get_Annotation_Bif(...);
PTR_LLND Get_Annotation_Expr(...);
char *Get_String_of_Annotation(...);
PTR_CMNT Get_Annotation_Comment(...);
int Is_Annotation_Defined(...);
char *Annotation_Defines_string(...);
int Annotation_Defines_string_Value(...);
int isItInSection(...);
}
extern "C" int TRACEANN;
//////////////////////////////////////////////////////////////
// Link with the Sage: maps it in sage space.
//////////////////////////////////////////////////////////////
extern SgExpression * LlndMapping(PTR_LLND pt);
extern SgStatement *BfndMapping(PTR_BFND st);
//////////////////////////////////////////////////////////////
// The interface. method of class annotations
//////////////////////////////////////////////////////////////
SgAnnotation::SgAnnotation(int ident)
{
PTR_BFND first, last;
SgFunctionCallExp *cal;
if ((ident < 0) || (ident >= Get_Number_of_Annotation()))
{
Message("Invalid annotation", 0);
return;
}
// the id of the annotation;
id = ident;
theannotation = LlndMapping(Get_Annotation_Expr(id));
//the statement it is attached on;
stmt = BfndMapping(Get_Annotation_Bif(id));
Get_Scope_Of_Annotation(id, &first, &last);
scopebegin = BfndMapping(first);
scopeend = BfndMapping(last);
defined = Is_Annotation_Defined(id);
thedirective = LlndMapping(Get_Annotation_Field(Get_Annotation_Expr(id)));
directiveName = Get_Annotation_Field_Label(Get_Annotation_Expr(id));
directiveFields = NULL;
nbDirectiveFields = 0;
if (cal = isSgFunctionCallExp(thedirective))
{
int i;
nbDirectiveFields = cal->numberOfArgs();
if (nbDirectiveFields)
{
directiveFields = new SgExpression *[nbDirectiveFields];
#ifdef __SPF
addToCollection(__LINE__, __FILE__, directiveFields, 2);
#endif
for (i = 0; i < nbDirectiveFields; i++)
{
directiveFields[i] = cal->arg(i);
}
}
}
else
{
Message("Fail to recognize annotation format", 0);
}
next = NULL;
}
SgAnnotation::~SgAnnotation()
{
if (directiveFields)
{
#ifdef __SPF
removeFromCollection(directiveFields);
#endif
delete[] directiveFields;
}
}
char * SgAnnotation::unparse()
{
return Unparse_Annotation(Get_Annotation_Expr(id));
}
int SgAnnotation::applyToStatement(SgStatement *stat)
{
SgStatement *temp;
if (!stat)
return 0;
for (temp = scopebegin; temp; temp = temp->lexNext())
{
if (temp == stat)
return 1;
if (temp == scopeend)
break;
}
return 0;
}
////////////////////////////////////////////////////////////////////////
// non method functions to get the annotation
///////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
// create the list of annotations that applies to a statements
// only the defined one
/////////////////////////////////////////////////////////////
SgAnnotation *
getTheAnnotationThatApply(SgStatement *stmt, char *kind)
{
int i;
PTR_BFND first, last;
SgAnnotation *listann = NULL;
SgAnnotation *lastann = NULL;
PTR_BFND bif;
if (!stmt)
return NULL;
bif = stmt->thebif;
for (i = 0; i < Get_Number_of_Annotation(); i++)
{
if (Is_Annotation_Defined(i))
{
if (kind)
{
if (Get_Annotation_Field_Label(Get_Annotation_Expr(i)) &&
(strcmp(Get_Annotation_Field_Label(Get_Annotation_Expr(i)), kind) == 0))
{
if (Get_Scope_Of_Annotation(i, &first, &last))
{
if (isItInSection(first, last, bif))
{
if (!listann)
{
listann = new SgAnnotation(i);
#ifdef __SPF
addToCollection(__LINE__, __FILE__, listann, 1);
#endif
lastann = listann;
}
else
{
lastann->next = new SgAnnotation(i);
#ifdef __SPF
addToCollection(__LINE__, __FILE__, listann->next, 1);
#endif
lastann = lastann->next;
}
}
}
}
}
else
{
if (Get_Scope_Of_Annotation(i, &first, &last))
{
if (isItInSection(first, last, bif))
{
if (!listann)
{
listann = new SgAnnotation(i);
#ifdef __SPF
addToCollection(__LINE__, __FILE__, listann, 1);
#endif
lastann = listann;
}
else
{
lastann->next = new SgAnnotation(i);
#ifdef __SPF
addToCollection(__LINE__, __FILE__, listann->next, 1);
#endif
lastann = lastann->next;
}
}
}
}
}
}
return listann;
}
SgAnnotation *
getTheAnnotationWithString(char *kind)
{
int i;
PTR_BFND first, last;
SgAnnotation *listann = NULL;
SgAnnotation *lastann = NULL;
PTR_BFND bif;
for (i = 0; i < Get_Number_of_Annotation(); i++)
{
if (Is_Annotation_Defined(i))
{
if (kind)
{
if (Get_Annotation_Field_Label(Get_Annotation_Expr(i)) &&
(strncmp(Get_Annotation_Field_Label(Get_Annotation_Expr(i)),
kind, strlen(kind)) == 0))
if (!listann)
{
listann = new SgAnnotation(i);
#ifdef __SPF
addToCollection(__LINE__, __FILE__, listann, 1);
#endif
lastann = listann;
}
else
{
lastann->next = new SgAnnotation(i);
#ifdef __SPF
addToCollection(__LINE__, __FILE__, listann->next, 1);
#endif
lastann = lastann->next;
}
}
}
}
return listann;
}
int
isAnnotationWithString(SgStatement *stmt, char *kind, int len)
{
int i;
PTR_BFND first, last;
SgAnnotation *listann = NULL;
SgAnnotation *lastann = NULL;
PTR_BFND bif;
if (!stmt)
return 0;
bif = stmt->thebif;
for (i = 0; i < Get_Number_of_Annotation(); i++)
{
if (Is_Annotation_Defined(i))
{
if (kind)
{
if (Get_Annotation_Field_Label(Get_Annotation_Expr(i)) &&
(strncmp(Get_Annotation_Field_Label(Get_Annotation_Expr(i)),
kind, len) == 0))
{
if (Get_Scope_Of_Annotation(i, &first, &last))
{
if (isItInSection(first, last, bif))
return 1;
}
}
}
}
}
return 0;
}
void initAnnotationSystem(int printann)
{
int i;
SgExpression *exp;
SgStatement *stmt;
if (printann)
{
TRACEANN = 1;
}
initAnnotation();
// add also the annotation expression for the garbage collection attributes;
for (i = 0; i < Get_Number_of_Annotation(); i++)
{
exp = LlndMapping(Get_Annotation_Expr(i));
stmt = BfndMapping(Get_Annotation_Bif(i));
if (stmt && exp)
{
stmt->addAttribute(ANNOTATION_EXPR_ATTRIBUTE, (void *)exp, 0);
}
}
}

View File

@@ -0,0 +1,31 @@
#pragma once
///////////////////////////////////////////////////////////////////
// interface to the annotations
///////////////////////////////////////////////////////////////////
class SgAnnotation
{
public:
// the id of the annotation;
int id;
// the annotation itself;
SgExpression *theannotation;
//the statement it is attached on;
SgStatement *stmt;
SgStatement *scopebegin;
SgStatement *scopeend;
int defined;
SgExpression *thedirective;
char *directiveName;
// pointer to the next annotation for a statement;
SgAnnotation *next;
SgAnnotation(int id);
~SgAnnotation();
char * unparse();
int applyToStatement(SgStatement *stat);
SgExpression **directiveFields;
int nbDirectiveFields;
};

View File

@@ -0,0 +1,726 @@
#include <stdio.h>
#include <set>
#include <string>
#include "sage++user.h"
#include "definesValues.h"
#include "set.h"
#include "definitionSet.h"
#include "inducVar.h"
#include "arrayRef.h"
#ifdef __SPF
extern "C" void addToCollection(const int line, const char *file, void *pointer, int type);
extern "C" void removeFromCollection(void *pointer);
#endif
int NbLinearRef = 0;
int NbNonLinearRef = 0;
extern Set *genSet[MAXNODE];
extern Set *killSet[MAXNODE];
extern Set *inSet[MAXNODE];
extern Set *outSet[MAXNODE];
extern Set* getAllInductionVar(SgStatement *func, SgStatement *stmt, int level, int *num, int include);
using std::set;
using std::string;
//
// for an array ref build the linear representation
// return 0 if failed
//
int linearRepArray(SgExpression *ex1, SgSymbol **symb, int size, int linear[MAXDIMARRAY][MAXNESTEDLOOP], int *cst, int isLinear[MAXDIMARRAY])
{
SgArrayRefExp *ar;
SgExpression *lin;
int i;
int returnVal;
if (!ex1 || !symb || !cst)
return 0;
if (!(ar = isSgArrayRefExp(ex1)))
return 0;
returnVal = 1;
for (i = 0; i < ar->numberOfSubscripts(); i++)
{
lin = ar->subscript(i);
isLinear[i] = 1;
if (!lin)
{
returnVal = 0;
isLinear[i] = 0;
}
else
if (!lin->linearRepresentation(linear[i], symb, &cst[i], size))
{
returnVal = 0;
isLinear[i] = 0;
}
}
return returnVal;
}
//
// Set Operations
//
int arrayEqual(void *e1, void *e2)
{
SgExpression *ex1, *ex2;
SgSymbol *s1, *s2;
PT_ACCESSARRAY el1, el2;
int i;
if (!e1 && !e2)
return 1;
if (!e1 || !e2)
return 0;
el1 = (PT_ACCESSARRAY)e1;
el2 = (PT_ACCESSARRAY)e2;
ex1 = el1->var;
ex2 = el2->var;
if (el1->type != el2->type)
return 0;
if (ex1 && ex2 && (s1 = ex1->symbol()) && (s2 = ex2->symbol()))
{
if (s1 != s2)
return 0;
// need to check more, at which condition, two sections are equal;
// pattern matching should be ok;
}
return 1;
}
void arrayPrint(void *e1)
{
SgExpression *ex1;
PT_ACCESSARRAY el1;
int i, j;
if (!e1)
return;
el1 = (PT_ACCESSARRAY)e1;
ex1 = el1->var;
printf("%d :", el1->level);
ex1->unparsestdout();
printf("\n");
if (el1->scalar)
printf("scalar variable\n");
if (el1->rw)
printf("written\n");
else
printf("read\n");
if (el1->type)
printf("Linear\n");
for (i = 0; i < MAXDIMARRAY; i++)
{
if (el1->isLinear[i])
{
printf("Linear (%d) :", i);
for (j = 0; j < el1->size; j++)
printf("%d ", el1->linear[i][j]);
printf(" cst = %d", el1->cst[i]);
printf("\n");
}
else
printf("NonLinear (%d) \n", i);
}
printf("\n");
}
// this function should be extended to handle non loop statement...
Set *loopArrayAccessAnalysis(SgStatement *func, SgStatement *stmt, SgSymbol **tsymb, Set **induc, const set<string> &privVars)
{
Set *inducvar, *cstset, *tpt, *arset;
SgStatement *temp1, *temp2, *last;
SgExpression *def1, *def2, *use1, *use2;
SgExpression *ex1, *ex2, *r1, *r2;
int linear1[MAXDIMARRAY][MAXNESTEDLOOP];
int i, j, size, res1, res2, cst1[MAXDIMARRAY];
int level, ptstack = 0, LevStack[MAXNESTEDLOOP], nbloop;
PT_INDUCVAR ind;
PT_ACCESSARRAY el;
int numloop = 0;
int isLinear[MAXDIMARRAY];
if (!isSgForStmt(stmt) || !func)
return NULL;
last = stmt->lastNodeOfStmt();
// get induction variables;
inducvar = getAllInductionVar(func, stmt, 1, &numloop, -1);
// add the constante to the induction set variable;
// cstset = computeConstanteInStmt(func,stmt);
// if (cstset)
// cstset->printSet();
// inducvar->unionSet(cstset);
// delete cstset;
if (!inducvar)
{
Message("no induction variables", stmt->lineNumber());
return NULL;
}
// load the array of symbol with induction var;
if (inducvar->size() >= MAXNESTEDLOOP)
{
Message("Too many induction variables\n", stmt->lineNumber());
return NULL;
}
tpt = inducvar;
inducvar = inducvar->compact();
#ifdef __SPF
removeFromCollection(tpt);
#endif
delete tpt;
*induc = inducvar;
arset = new Set(arrayEqual, NULL, arrayPrint);
#ifdef __SPF
addToCollection(__LINE__, __FILE__, arset, 1);
#endif
size = inducvar->size();
for (i = 0; i < inducvar->size(); i++)
{
ind = (PT_INDUCVAR)inducvar->getElement(i);
if (ex2 = ind->var)
{
tsymb[i] = ex2->symbol();
}
}
// get all array references, there are contained in the Defined Used set;
level = 0;
nbloop = 0;
for (temp1 = stmt; temp1 && (temp1 != last); temp1 = temp1->lexNext())
{
if (isSgForStmt(temp1))
{
nbloop++;
ptstack++;
if (ptstack >= MAXNESTEDLOOP)
Message("Stack out of bound in loopArrayAccessAnalysis", 0);
LevStack[ptstack] = nbloop;
level = nbloop;
}
if (isSgControlEndStmt(temp1) || isSgContinueStmt(temp1))
{
if (temp1->controlParent() && (temp1->controlParent()->variant() == FOR_NODE) && (temp1->controlParent()->lastNodeOfStmt() == temp1))
{
ptstack--;
if (ptstack <= 0)
Message("Stack out of bound in loopArrayAccessAnalysis", 0);
level = LevStack[ptstack];
}
}
for (def1 = (SgExpression *)temp1->attributeValue(0, DEFINEDLIST_ATTRIBUTE); def1; def1 = def1->rhs())
//Defined[temp1->id()]; def1; def1 = def1->rhs())
{
for (i = 0; i < MAXDIMARRAY; i++)
{
cst1[i] = 0;
isLinear[i] = 1;
for (j = 0; j < MAXNESTEDLOOP; j++)
linear1[i][j] = 0;
}
ex1 = def1->lhs();
if (isSgArrayRefExp(ex1))
{
if (privVars.find(ex1->symbol()->identifier()) == privVars.end())
{
res1 = linearRepArray(ex1, tsymb, size, linear1, cst1, isLinear);
el = new struct arrayAccess;
#ifdef __SPF
addToCollection(__LINE__, __FILE__, el, 1);
#endif
for (i = 0; i < MAXDIMARRAY; i++)
{
el->isLinear[i] = isLinear[i];
for (j = 0; j < MAXNESTEDLOOP; j++)
el->linear[i][j] = linear1[i][j];
el->cst[i] = cst1[i];
}
// add the ref;
el->stmt = temp1;
el->nbdim = MAXDIMARRAY;
el->var = ex1;
el->type = res1;
if (res1)
NbLinearRef++;
else
NbNonLinearRef++;
el->size = size;
el->rw = 1; // this is a write;
el->scalar = 0; // not a scalar var;
el->level = level;
arset->addElement((void *)el);
}
}
else
{
SgSymbol *ssy;
int l, trouve;
// if non induction var ;
if (!isSgTypeExp(ex1))
{
ssy = ex1->symbol();
trouve = 0;
for (l = 0; l < size; l++)
{
if (ssy == tsymb[l])
{
trouve = 1;
break;
}
}
}
else
trouve = 1;
if (!trouve)
{
el = new struct arrayAccess;
#ifdef __SPF
addToCollection(__LINE__, __FILE__, el, 1);
#endif
// add the ref;
el->stmt = temp1;
el->var = ex1;
el->nbdim = 0;
el->type = 0;
el->size = 0;
el->rw = 1; // this is a write;
el->level = level;
el->scalar = 1; // not a scalar var;
arset->addElement((void *)el);
}
}
}
for (use1 = (SgExpression *)temp1->attributeValue(0, USEDLIST_ATTRIBUTE); use1; use1 = use1->rhs())
// Used[temp1->id()]; use1; use1 = use1->rhs())
{
for (i = 0; i < MAXDIMARRAY; i++)
{
cst1[i] = 0;
isLinear[i] = 1;
for (j = 0; j < MAXNESTEDLOOP; j++)
linear1[i][j] = 0;
}
ex1 = use1->lhs();
if (isSgArrayRefExp(ex1))
{
if (privVars.find(ex1->symbol()->identifier()) == privVars.end())
{
res1 = linearRepArray(ex1, tsymb, size, linear1, cst1, isLinear);
el = new struct arrayAccess;
#ifdef __SPF
addToCollection(__LINE__, __FILE__, el, 1);
#endif
for (i = 0; i < MAXDIMARRAY; i++)
{
el->isLinear[i] = isLinear[i];
for (j = 0; j < MAXNESTEDLOOP; j++)
el->linear[i][j] = linear1[i][j];
el->cst[i] = cst1[i];
}
// add the ref;
el->stmt = temp1;
el->var = ex1;
el->nbdim = MAXDIMARRAY;
el->type = res1;
if (res1)
NbLinearRef++;
else
NbNonLinearRef++;
el->size = size;
el->rw = 0; // this is a read;
el->scalar = 0; // not a scalar var;
el->level = level;
arset->addElement((void *)el);
}
}
else
{
SgSymbol *ssy;
int l, trouve;
if (!isSgTypeExp(ex1))
{
// if non induction var ;
ssy = ex1->symbol();
trouve = 0;
for (l = 0; l < size; l++)
{
if (ssy == tsymb[l])
{
trouve = 1;
break;
}
}
}
else
trouve = 1;
if (!trouve)
{
el = new struct arrayAccess;
#ifdef __SPF
addToCollection(__LINE__, __FILE__, el, 1);
#endif
// add the ref;
el->stmt = temp1;
el->var = ex1;
el->nbdim = 0;
el->type = 0;
el->size = 0;
el->level = level;
el->rw = 0; // this is a read;
el->scalar = 1; // not a scalar var;
arset->addElement((void *)el);
}
}
}
}
return arset;
}
int
projectoPermut(PT_ACCESSARRAY el1)
{
SgSymbol *inducsy;
int i, j, k;
PT_INDUCVAR ind, cur;
int temp;
if (!el1)
return 0;
if (!el1->type)
return 0; // non linear;
for (j = 0; j < el1->size; j++)
{
temp = 0;
for (k = 0; k < MAXDIMARRAY; k++)
{
if (el1->linear[k][j] != 0)
{
if (temp)
return 0;
temp = 1;
}
}
}
for (k = 0; k < MAXDIMARRAY; k++)
{
temp = 0;
for (j = 0; j < el1->size; j++)
{
if (el1->linear[k][j] != 0)
{
if (temp)
return 0;
temp = 1;
}
}
}
return 1;
}
//
// Between two references is there temporal locality. Limited to permutation o projection
//
int
temporalLocality(PT_ACCESSARRAY el1, SgSymbol **tsymb, Set *induc)
{
SgSymbol *inducsy;
int j, k;
PT_INDUCVAR ind, cur;
int loopnum;
int temporal, temp;
if (!el1 || !induc || !tsymb)
return 0;
inducsy = NULL;
loopnum = el1->level;
for (j = 0; j < induc->size(); j++)
{
ind = (PT_INDUCVAR)induc->getElement(j);
if (ind && (ind->loopnum == loopnum))
{
inducsy = ind->var->symbol();
cur = ind;
break;
}
}
temporal = 0;
// this is the induction var of the loop.
if (inducsy)
{
while (cur)
{
for (j = 0; j < el1->size; j++)
{
if (tsymb[j] == inducsy)
break;
} // we have the symbol;
if (j < el1->size)
{
temp = 1;
for (k = 0; k < MAXDIMARRAY; k++)
{
if (el1->linear[k][j] != 0)
{
temp = 0;
}
}
if (temp)
temporal = 1;
}
if (cur->include == -1)
break;
// compute the next one;
for (j = 0; j < induc->size(); j++)
{
ind = (PT_INDUCVAR)induc->getElement(j);
if (ind && (ind->loopnum == cur->include))
{
inducsy = ind->var->symbol();
cur = ind;
break;
}
}
}
}
return temporal;
}
int
spatialLocality(PT_ACCESSARRAY el1, SgSymbol **tsymb, Set *induc, int CacheLIneSize)
{
SgSymbol *inducsy;
int j, k;
PT_INDUCVAR ind, cur;
int loopnum;
int spatial, temp;
if (!el1 || !induc || !tsymb)
return 0;
inducsy = NULL;
loopnum = el1->level;
for (j = 0; j < induc->size(); j++)
{
ind = (PT_INDUCVAR)induc->getElement(j);
if (ind && (ind->loopnum == loopnum))
{
inducsy = ind->var->symbol();
cur = ind;
break;
}
}
spatial = 0;
// this is the induction var of the loop.
if (inducsy)
{
// look at in the dimension where the variable appear;
spatial = 1;
// the first dimension is fine where is the column of the symbole;
for (j = 0; j < el1->size; j++)
{
if (tsymb[j] == inducsy)
break;
}
if (j < el1->size)
{
for (k = 1; k < MAXDIMARRAY; k++)
{
if (el1->linear[k][j] != 0)
{
spatial = 0;
break;
}
}
if (el1->linear[0][j] > CacheLIneSize)
spatial = 0;
}
else
{
spatial = 0;
}
}
return spatial;
}
int
spatialNonSelfLocality(PT_ACCESSARRAY el1, PT_ACCESSARRAY el2, SgSymbol **tsymb, Set *induc, int CacheLIneSize)
{
SgSymbol *inducsy;
int j, k;
PT_INDUCVAR ind, cur;
int loopnum;
int spatial, temp;
if (!el1 || !el2 || !induc || !tsymb)
return 0;
inducsy = NULL;
if (el1->level != el2->level)
return 0;
if (!el1->var || !el2->var)
return 0;
if (el1->var->symbol() != el2->var->symbol())
return 0;
// do they have the same function
for (k = 0; k < MAXDIMARRAY; k++)
{
for (j = 0; j < el1->size; j++)
{
if (el1->linear[k][j] != el2->linear[k][j])
{
return 0;
}
}
}
for (k = 1; k < MAXDIMARRAY; k++)
{
if (el1->cst[k] != el2->cst[k])
{
return 0;
}
}
spatial = el1->cst[0] - el2->cst[0];
if (spatial < 0)
spatial = -spatial;
if (spatial >= CacheLIneSize)
return 0;
return 1;
}
int
TemporalNonSelfLocality(PT_ACCESSARRAY el1, PT_ACCESSARRAY el2, SgSymbol **tsymb, Set *induc)
{
SgSymbol *inducsy;
int j, k;
PT_INDUCVAR ind, cur;
int loopnum;
int spatial, temp;
int flag;
if (!el1 || !el2 || !induc || !tsymb)
return 0;
inducsy = NULL;
if (el1->level != el2->level)
return 0;
if (!el1->var || !el2->var)
return 0;
if (el1->var->symbol() != el2->var->symbol())
return 0;
// do they have the same function
for (k = 0; k < MAXDIMARRAY; k++)
{
for (j = 0; j < el1->size; j++)
{
if (el1->linear[k][j] != el2->linear[k][j])
{
return 0;
}
}
}
// is there one reference with only one constant different
flag = 0;
for (k = 0; k < MAXDIMARRAY; k++)
{
if (el1->cst[k] != el2->cst[k])
{
if (flag)
return 0;
flag = k + 1;
}
}
if (flag)
{
// check first that the coefficient is not NULL;
for (j = 0; j < el1->size; j++)
{
if (el1->linear[flag - 1][j] != 0)
return 1;
}
return 0;
}
else
return 0; // that case is considered elsewhere
}
int
isLinearEqual(int size1, int size2, int linear1[MAXDIMARRAY][MAXNESTEDLOOP], int *cst1, int linear2[MAXDIMARRAY][MAXNESTEDLOOP], int *cst2)
{
int i, j;
if (!linear1 || !linear2 || !cst1 || !cst2)
return 0;
if (size1 != size2)
return 0;
for (i = 0; i < MAXDIMARRAY; i++)
{
if (cst1[i] != cst2[i])
return 0;
for (j = 0; j < size1; j++)
{
if (linear1[i][j] != linear2[i][j])
return 0;
}
}
return 1;
}
int
isLinearEqualNoCst(int size1, int size2, int linear1[MAXDIMARRAY][MAXNESTEDLOOP], int linear2[MAXDIMARRAY][MAXNESTEDLOOP])
{
int i, j;
if (!linear1 || !linear2)
return 0;
if (size1 != size2)
return 0;
for (i = 0; i < MAXDIMARRAY; i++)
{
for (j = 0; j < size1; j++)
{
if (linear1[i][j] != linear2[i][j])
return 0;
}
}
return 1;
}
int
isNull(int size, int linear[MAXNESTEDLOOP])
{
int i;
if (!linear)
return 1;
for (i = 0; i < size; i++)
{
if (linear[i] != 0)
return 0;
}
return 1;
}

View File

@@ -0,0 +1,18 @@
#pragma once
struct arrayAccess {
SgStatement *stmt;
SgExpression *var; // this is var;
int linear[MAXDIMARRAY][MAXNESTEDLOOP];
int isLinear[MAXDIMARRAY];
int cst[MAXNESTEDLOOP];
int nbdim;
int size;
int type;
int rw;
int scalar;
int level; // give the loop number
};
typedef struct arrayAccess *PT_ACCESSARRAY;

View File

@@ -0,0 +1,365 @@
#include <stdio.h>
#include "sage++user.h"
#include "definesValues.h"
#include "set.h"
#include "definitionSet.h"
#include "inducVar.h"
extern Set *genSet[MAXNODE];
extern Set *killSet[MAXNODE];
extern Set *inSet[MAXNODE];
extern Set *outSet[MAXNODE];
#ifdef __SPF
extern "C" void addToCollection(const int line, const char *file, void *pointer, int type);
extern "C" void removeFromCollection(void *pointer);
#endif
//
// Here we compute the induction variables for a loop
// this use the result of recheing analysis and invariant computation in loop.
// we use as element of sets the following structure.
//
//
// Set Operation
//
int inducVarEqual(void *e1, void *e2)
{
SgExpression *ex1, *ex2;
SgSymbol *s1, *s2;
PT_INDUCVAR el1, el2;
if (!e1 && !e2)
return 1;
if (!e1 || !e2)
return 0;
el1 = (PT_INDUCVAR)e1;
el2 = (PT_INDUCVAR)e2;
if (el1->level != el2->level)
return 0;
if (el1->include != el2->include)
return 0;
if (el1->loopnum != el2->loopnum)
return 0;
if (el1->constante != el2->constante)
return 0;
ex1 = el1->var;
ex2 = el2->var;
if ((s1 = ex1->symbol()) && (s2 = ex2->symbol()))
{
if (s1 == s2)
return 1;
else
return 0;
}
else
return 0;
}
void inducVarPrint(void *e1)
{
SgExpression *ex1;
PT_INDUCVAR el1;
if (!e1)
return;
el1 = (PT_INDUCVAR)e1;
ex1 = el1->var;
if (el1->constante)
printf("Constante ");
if (ex1->symbol())
printf("%s (%d-%d-%d)", ex1->symbol()->identifier(), el1->level, el1->loopnum, el1->include);
else
ex1->unparsestdout();
printf(" = ");
ex1 = el1->lbound;
if (ex1)
ex1->unparsestdout();
printf(",");
ex1 = el1->ubound;
if (ex1)
ex1->unparsestdout();
printf(",");
ex1 = el1->stride;
if (ex1)
ex1->unparsestdout();
printf("\n");
}
//
// Indicate if a variable is subject to modification in a stmt
// Based on the Definition for each statement....
// defvar is a varref;
//
int definitionInStmt(SgStatement *func, SgStatement *stmtin, SgExpression *defvar)
{
SgStatement *last, *stmt;
SgExpression *def, *expr;
if (!stmtin || !func)
return FALSE;
last = stmtin->lastNodeOfStmt();
for (stmt = stmtin; stmt; stmt = stmt->lexNext())
{
def = (SgExpression *)stmt->attributeValue(0, DEFINEDLIST_ATTRIBUTE);
//Defined[stmt->id()];
while (def)
{
expr = def->lhs();
if (expr && expr->symbol() && defvar->symbol() &&
(expr->symbol() == defvar->symbol()))
{
return TRUE;
}
def = def->rhs();
}
if (stmt == last)
break;
}
return FALSE;
}
//same as before but avoid the first statement (for instance the loop header)
// so can be used fo checking the basic induction variable;
int definitionOnlyInsideStmt(SgStatement *func, SgStatement *stmtin, SgExpression *defvar)
{
SgStatement *last, *stmt;
SgExpression *def, *expr;
if (!stmtin || !func)
return FALSE;
last = stmtin->lastNodeOfStmt();
for (stmt = stmtin->lexNext(); stmt; stmt = stmt->lexNext())
{
def = (SgExpression *)stmt->attributeValue(0, DEFINEDLIST_ATTRIBUTE);
// Defined[stmt->id()];
while (def)
{
expr = def->lhs();
if (expr && expr->symbol() && defvar->symbol() &&
(expr->symbol() == defvar->symbol()))
{
return TRUE;
}
def = def->rhs();
}
if (stmt == last)
break;
}
return FALSE;
}
//
// For a statement create an induction var set that contains the SCALAR constante
// based on the use set which have to be defined later
//
Set* computeConstanteInStmt(SgStatement *func, SgStatement *stmtin)
{
SgStatement *last, *stmt;
SgExpression *use, *expr;
Set *constante;
PT_INDUCVAR elin;
int cst;
if (!stmtin || !func)
return NULL;
last = stmtin->lastNodeOfStmt();
constante = new Set(inducVarEqual, NULL, inducVarPrint);
#ifdef __SPF
addToCollection(__LINE__, __FILE__, constante, 1);
#endif
for (stmt = stmtin; stmt; stmt = stmt->lexNext())
{
use = (SgExpression *)stmt->attributeValue(0, USEDLIST_ATTRIBUTE);
// Used[stmt->id()];
while (use)
{
expr = use->lhs();
if (definitionInStmt(func, stmtin, expr))
cst = 0;
else
cst = 1;
if (cst)
{
elin = new struct inducvar;
#ifdef __SPF
addToCollection(__LINE__, __FILE__, elin, 1);
#endif
elin->constante = TRUE;
elin->stmt = stmtin;
elin->var = use->lhs();
elin->lbound = NULL;
elin->ubound = NULL;
elin->stride = NULL;
elin->level = 0;
elin->loopnum = 0;
constante->addElement((void *)elin);
}
use = use->rhs();
}
if (stmt == last)
break;
}
if (constante)
constante->compact();
return constante;
}
//
// compute effectively induction variables (limited to basic induction variable for now)
//
Set* computeInductionVariables(SgStatement *func, SgStatement *stmt)
{
SgStatement *last, *first, *defreach, *temp, *cp;
SgForStmt *loop;
Set *induc, *reachdef;
SgExpression *use, *def, *pt, *defvar, *expr;
int change, id, inloop, inv, step;
PT_ELSET el;
PT_INDUCVAR elin;
int i, inducF;
if (!stmt || !func)
return NULL;
if (!(loop = isSgForStmt(stmt)))
return NULL;
induc = new Set(inducVarEqual, NULL, inducVarPrint);
#ifdef __SPF
addToCollection(__LINE__, __FILE__, induc, 1);
#endif
def = (SgExpression *)stmt->attributeValue(0, DEFINEDLIST_ATTRIBUTE);
// Defined[stmt->id()];
if (def)
{ // basic induction var;
defvar = def->lhs(); // the loop modify the induction var only;
// check if it is constant;
if (!definitionOnlyInsideStmt(func, loop, defvar))
inducF = 1;
else
{
inducF = 1;
Message("Induction variable may be defined", stmt->lineNumber());
}
if (inducF)
{
elin = new struct inducvar;
#ifdef __SPF
addToCollection(__LINE__, __FILE__, elin, 1);
#endif
elin->constante = FALSE;
elin->stmt = stmt;
elin->var = def->lhs();
elin->lbound = loop->start();
elin->ubound = loop->end();
elin->stride = loop->step();
elin->level = 0;
elin->loopnum = 0;
induc->addElement((void *)elin);
}
else
Message("Basic Induction Var not Found: dependence Test will abort", loop->lineNumber());
// limited to basic induction variable for the moment...;
}
return induc;
}
//Get all induction var;
Set* getAllInductionVar(SgStatement *func, SgStatement *stmt, int level, int *num, int include)
{
SgStatement *temp, *child;
int i, newlevel;
Set *induc, *tpt;
PT_INDUCVAR el;
int tmpincl;
if (!stmt)
return NULL;
induc = NULL;
if (isSgForStmt(stmt))
{
*num = *num + 1;
tmpincl = *num;
induc = computeInductionVariables(func, stmt);
if (induc)
{
for (i = 0; i < induc->size(); i++)
{
el = (PT_INDUCVAR)induc->getElement(i);
if (el)
{
el->level = level;
el->loopnum = *num;
el->include = include;
}
}
}
}
else
tmpincl = include;
i = 1;
temp = stmt;
child = temp->childList1(0);
while (child)
{
if (isSgForStmt(child))
newlevel = level + 1;
else
newlevel = level;
if (induc)
{
induc->unionSet(tpt = getAllInductionVar(func, child, newlevel, num, tmpincl));
if (tpt)
{
#ifdef __SPF
removeFromCollection(tpt);
#endif
delete tpt;
}
}
else
induc = getAllInductionVar(func, child, newlevel, num, tmpincl);
child = temp->childList1(i);
i++;
}
i = 1;
temp = stmt;
child = temp->childList2(0);
while (child)
{
if (isSgForStmt(child))
newlevel = level + 1;
else
newlevel = level;
if (induc)
{
induc->unionSet(tpt = getAllInductionVar(func, child, newlevel, num, tmpincl));
if (tpt)
{
#ifdef __SPF
removeFromCollection(tpt);
#endif
delete tpt;
}
}
else
induc = getAllInductionVar(func, child, newlevel, num, tmpincl);
child = temp->childList2(i);
i++;
}
return induc;
}

View File

@@ -0,0 +1,279 @@
#include <stdio.h>
#include <stdlib.h>
#include "sage++user.h"
#include "definesValues.h"
#include "set.h"
#include "definitionSet.h"
#include "constanteSet.h"
#ifdef __SPF
extern "C" void addToCollection(const int line, const char *file, void *pointer, int type);
#endif
//
// Program part for constant propagation.
//
//
// Set Operation
//
int constPropEqual(void *e1, void *e2)
{
SgExpression *ex1, *ex2;
SgSymbol *s1, *s2;
PT_CONSTPROP el1, el2;
if (!e1 && !e2)
return 1;
if (!e1 || !e2)
return 0;
el1 = (PT_CONSTPROP)e1;
el2 = (PT_CONSTPROP)e2;
ex1 = el1->var;
ex2 = el2->var;
if ((s1 = ex1->symbol()) && (s2 = ex2->symbol()))
{
if ((s1 == s2) && (el1->flag == el2->flag) && (el1->value == el2->value))
return 1;
else
return 0;
}
else
return 0;
}
void constPropPrint(void *e1)
{
SgExpression *ex1;
PT_CONSTPROP el1;
if (!e1)
return;
el1 = (PT_CONSTPROP)e1;
ex1 = el1->var;
if (ex1->symbol())
{
printf("%s (from stmt %d):", ex1->symbol()->identifier(), el1->stmt->lineNumber());
switch (el1->flag)
{
case UNDEFFLAG:
printf("undefined\n");
break;
case NONCONSTFLAG:
printf("non constant\n");
break;
case CONSTFLAG:
printf("%d\n", el1->value);
break;
}
}
else
printf("Bizarre\n");
}
//
// Here we need th combine operation, combine two elements
// return NULL if combine possible
//
void *
constPropCombine(void *e1, void *e2)
{
SgExpression *ex1, *ex2;
SgSymbol *s1, *s2;
PT_CONSTPROP el1, el2;
if (!e1)
return e2;
if (!e2)
return e1;
el1 = (PT_CONSTPROP)e1;
el2 = (PT_CONSTPROP)e2;
ex1 = el1->var;
ex2 = el2->var;
if ((s1 = ex1->symbol()) && (s2 = ex2->symbol()))
{
if (s1 == s2)
{
if (el1->flag == UNDEFFLAG)
return e1;
if (el2->flag == UNDEFFLAG)
return e2;
if (el1->flag == NONCONSTFLAG)
return e1;
if (el2->flag == NONCONSTFLAG)
return e2;
if (el1->value == el2->value)
return e1;
else
{
el1->flag = NONCONSTFLAG;
return e1;
}
}
else
return NULL;
}
else
return NULL;
}
//
// this function evaluate the value of the
//
// some functions from the low_level are used for that function so that Evaluate Expression can use
// the value of some variables
//
// extern "C" void resetPresetEvaluate();
// extern "C" void addElementEvaluate(...);
Set *transConstante(SgStatement *func, SgStatement *stmt, Set *setin)
{
Set *outset;
SgExpression *def, *defvar, *expr;
SgSymbol *symb;
int val;
int i;
PT_CONSTPROP el = NULL;
PT_CONSTPROP el1 = NULL;
if (!func || !stmt)
{
Message("transConstante some parameters are null", 0);
return NULL;
}
if (isSgCallStmt(stmt) || isSgInputOutputStmt(stmt))
{
if (!setin)
return NULL;
else
{
outset = new Set(constPropEqual, constPropCombine, constPropPrint);
#ifdef __SPF
addToCollection(__LINE__, __FILE__, outset, 1);
#endif
for (i = 0; i < setin->size(); i++)
{
el = (PT_CONSTPROP)setin->getElement(i);
if (el)
{ // create new one otherwise side effect can appear;
el1 = new struct constprop;
#ifdef __SPF
addToCollection(__LINE__, __FILE__, el1, 1);
#endif
el1->flag = UNDEFFLAG;
el1->var = el->var;
el1->value = 0;
el1->stmt = el->stmt;
el1->expr = el->expr;
outset->addElement((void *)el1);
}
}
// should add the parameter list with undefined;
// this has been completly copied so allow to deallocate element too;
// setin->setDealllocateElem(); other element need also to be copied
return outset;
}
}
if (!isSgAssignStmt(stmt))
{
if (!setin)
return NULL;
else
return setin->copy();
}
if (setin)
outset = setin->copy();
else
{
outset = new Set(constPropEqual, constPropCombine, constPropPrint);
#ifdef __SPF
addToCollection(__LINE__, __FILE__, outset, 1);
#endif
}
// before evaluating the expression set the Value set ;
if (setin)
{
for (i = 0; i < setin->size(); i++)
{
el = (PT_CONSTPROP)setin->getElement(i);
if (el)
{
if ((el->flag == CONSTFLAG) &&
el->var &&
el->var->symbol())
{
addElementEvaluate(el->var->symbol()->thesymb, el->value);
}
}
}
}
// just call Evaluate Expression ;
def = (SgExpression *)stmt->attributeValue(0, DEFINEDLIST_ATTRIBUTE);
//Defined[stmt->id()];
if (def)
{
defvar = def->lhs();
if (isSgVarRefExp(defvar))
{
symb = defvar->symbol();
if (symb && symb->type() && (symb->type()->variant() == T_INT))
{
if (setin)
{
// remove all definition to the symbol;
for (i = 0; i < outset->size(); i++)
{
el = (PT_CONSTPROP)outset->getElement(i);
if (el)
{
if (el->var->symbol() == symb)
outset->rmElement(i);
}
}
}
expr = stmt->expr(1);
el = new struct constprop;
#ifdef __SPF
addToCollection(__LINE__, __FILE__, el, 1);
#endif
if (!el)
{
Message("No more Memory", 0);
exit(1);
}
if (expr && expr->isInteger())
{
val = expr->valueInteger();
el->flag = CONSTFLAG;
el->var = defvar;
el->value = val;
el->stmt = stmt;
el->expr = expr;
outset->addElement((void *)el);
}
else
{
el->flag = UNDEFFLAG;
el->var = defvar;
el->value = 0;
el->stmt = stmt;
el->expr = expr;
outset->addElement((void *)el);
}
}
}
}
resetPresetEvaluate();
// printf("intermediate print line %d\n", stmt->lineNumber());
// outset->printSet();
return outset;
}

View File

@@ -0,0 +1,19 @@
#pragma once
//
// Here we compute the induction variables for a loop
// this use the result of recheing analysis and invariant computation in loop.
// we use as element of sets the following structure.
//
struct constprop
{
int flag; // can be UNDEFFLAG, NONCONSTFLAG, CONSTFLAG
SgExpression *var; // this is a var ref;
int value;
SgStatement *stmt;
SgExpression *expr;
};
typedef struct constprop *PT_CONSTPROP;

View File

@@ -0,0 +1,237 @@
#include <stdio.h>
#include "sage++user.h"
#include "definesValues.h"
//
// Control Flow functions -------> should become a method of the statement class
// return an array of successor and predecessor
// the function compute the control flow.
// this is assumed to be applied on a function.
// func is the function we are in
//
void
controlFlow(SgStatement *stmt, SgStatement *func, SgStatement **pred, SgStatement **suc, int *predin, int *sucint)
{
SgLabel *lab, *labtemp;
SgStatement *last, *cp, *temp;
SgGotoStmt *gt;
SgLabelListStmt *gtl;
SgExpression *expr, *te;
SgLabelRefExp *le;
int nbpred, nbsuc;
if (!stmt || !func)
return;
nbpred = 0;
nbsuc = 0;
if (lab = stmt->label())
{ // there is a label, look at the goto on it;
last = func->lastNodeOfStmt();
// look at the goto statement going to the statement;
for (temp = func; temp && (temp != last); temp = temp->lexNext())
{
if (gt = isSgGotoStmt(temp))
{
labtemp = gt->label();
if (labtemp && (labtemp->id() == lab->id()))
{
pred[nbpred] = temp;
nbpred++;
}
}
else
{
if (gtl = isSgLabelListStmt(temp))
{
expr = gtl->labelList();
for (te = expr; te; te = te->rhs())
{
if (le = isSgLabelRefExp(te->lhs()))
{
labtemp = le->label();
if (labtemp && (labtemp->id() == lab->id()))
{
pred[nbpred] = temp;
nbpred++;
break;
}
}
}
}
}
}
}
// there is no label;
// depending on the statement we compute the predecessors;
// and the successor;
// here we use a big case;
switch (stmt->variant())
{
case CONT_STAT:
case CONTROL_END:
cp = stmt->controlParent();
if (cp)
{
switch (cp->variant())
{
case WHILE_NODE:
case FOR_NODE:
pred[nbpred] = stmt->nodeBefore();
nbpred++;
suc[nbsuc] = stmt->lexNext();
nbsuc++;
suc[nbsuc] = cp;
nbsuc++;
break;
default:
pred[nbpred] = stmt->nodeBefore();
suc[nbsuc] = stmt->lexNext();
nbpred++;
nbsuc++;
}
}
else
{
pred[nbpred] = stmt->nodeBefore();
suc[nbsuc] = stmt->lexNext();
nbpred++;
nbsuc++;
}
break;
case IF_NODE:
suc[nbsuc] = stmt->childList1(0);
nbsuc++;
if (stmt->childList2(0))
{
suc[nbsuc] = stmt->childList2(0);
nbsuc++;
}
else
{
suc[nbsuc] = stmt->lastNodeOfStmt()->lexNext();
nbsuc++;
}
pred[nbpred] = stmt->nodeBefore();
nbpred++;
break;
case WHILE_NODE:
case FOR_NODE:
pred[nbpred] = stmt->nodeBefore();
nbpred++;
pred[nbpred] = stmt->lastNodeOfStmt();
nbpred++;
suc[nbsuc] = stmt->lexNext();
nbsuc++;
suc[nbsuc] = stmt->lastNodeOfStmt()->lexNext();
nbsuc++;
break;
case DO_WHILE_NODE:
pred[nbpred] = stmt->nodeBefore();
nbpred++;
pred[nbpred] = stmt->lastNodeOfStmt();
nbpred++;
suc[nbsuc] = stmt->lexNext();
nbsuc++;
break;
case GOTO_NODE:
if (gt = isSgGotoStmt(stmt))
{
if (lab = gt->label())
{ // there is a label, look at the goto on it;
last = func->lastNodeOfStmt();
// look at the goto statement going to the statement;
for (temp = func; temp && (temp != last); temp = temp->lexNext())
{
labtemp = temp->label();
if (labtemp && (labtemp->id() == lab->id()))
{
suc[nbsuc] = temp;
nbsuc++;
}
}
}
}
break;
case LOGIF_NODE:
suc[nbsuc] = stmt->childList1(0);
nbsuc++;
suc[nbsuc] = stmt->lastNodeOfStmt()->lexNext();
nbsuc++;
pred[nbpred] = stmt->nodeBefore();
nbpred++;
break;
case STOP_STAT:
case RETURN_STAT:
case RETURN_NODE:
pred[nbpred] = stmt->nodeBefore();
nbpred++;
suc[nbsuc] = func->lastNodeOfStmt();
nbsuc++;
break;
case ELSEIF_NODE:
// case ARITHIF_NODE:
case WHERE_NODE:
case WHERE_BLOCK_STMT:
case SWITCH_NODE:
case CASE_NODE:
case BREAK_NODE:
case EXIT_STMT:
case ASSGOTO_NODE:
case COMGOTO_NODE:
printf("Statement line %d not implemented for control flow\n", stmt->lineNumber());
break;
default:
// cas du if a voir ici...
cp = stmt->controlParent();
if (cp)
{
switch (cp->variant())
{
case IF_NODE:
if (cp->childList1(0) == stmt)
{
pred[nbpred] = cp;
nbpred++;
suc[nbsuc] = stmt->lexNext();
nbsuc++;
}
else
if (cp->childList2(0) == stmt)
{
pred[nbpred] = cp;
nbpred++;
suc[nbsuc] = stmt->lexNext();
nbsuc++;
}
else
{
pred[nbpred] = stmt->nodeBefore();
suc[nbsuc] = stmt->lexNext();
nbpred++;
nbsuc++;
}
break;
// for node should also be taken into account
default:
pred[nbpred] = stmt->nodeBefore();
suc[nbsuc] = stmt->lexNext();
nbpred++;
nbsuc++;
}
}
else
{
pred[nbpred] = stmt->nodeBefore();
suc[nbsuc] = stmt->lexNext();
nbpred++;
nbsuc++;
}
}
*predin = nbpred;
*sucint = nbsuc;
}

View File

@@ -0,0 +1,789 @@
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <map>
#include <string>
#include "../GraphCall/graph_calls.h"
#include "../Utils/errors.h"
#include "../Utils/utils.h"
#include "sage++user.h"
#include "definesValues.h"
#include "set.h"
#include "definitionSet.h"
using std::map;
using std::string;
using std::vector;
using std::wstring;
#ifdef __SPF
extern "C" void addToCollection(const int line, const char *file, void *pointer, int type);
extern "C" void removeFromCollection(void *pointer);
#endif
//
// Global table to store the use and def
//
// Not used anymore, replaced by attributes;
// SgExpression *Used[MAXNODE];
// SgExpression *Defined[MAXNODE];
//
// declaration for the data flow framework
//
extern Set *genSet[MAXNODE];
extern Set *killSet[MAXNODE];
extern Set *inSet[MAXNODE];
extern Set *outSet[MAXNODE];
extern void iterativeForwardFlowAnalysis(SgFile *file,
SgStatement *func,
Set *(*giveGenSet)(SgStatement *func, SgStatement *stmt),
Set *(*giveKillSet)(SgStatement *func, SgStatement *stmt),
int(*feq)(void *e1, void *e2),
void *(*fcomb)(void *e1, void *e2),
void(*fp)(void *e1));
extern void generalIterativeFlowAnalysis(SgFile *file,
SgStatement *func,
Set *(*transfertSet)(SgStatement *func, SgStatement *stmt, Set *setin),
int(*feq)(void *e1, void *e2),
void* (*fcomb)(void *e1, void *e2),
void(*fp)(void *e1));
/////////////////////////////////////////////////////////////////////
// from the intrinsic.C file
/////////////////////////////////////////////////////////////////////
extern int isSymbolIntrinsic(SgSymbol *symb);
/////////////////////////////////////////////////////////////////////
// computes the definition for each file;
/////////////////////////////////////////////////////////////////////
static inline bool isVarRef(SgExpression *ex)
{
const int var = ex->variant();
return (var == ARRAY_REF || var == VAR_REF || var == ARRAY_OP);
}
static void fillDef(SgExpression *ex, vector<SgExpression*> &useL, vector<SgExpression*> &defL,
const map<string, FuncInfo*> &funcs, vector<Messages> &messagesForFile, const int currLine);
static void fillUse(SgExpression *ex, vector<SgExpression*> &useL, vector<SgExpression*> &defL,
const map<string, FuncInfo*> &funcs, vector<Messages> &messagesForFile, const int currLine)
{
if (ex)
{
if (isVarRef(ex))
{
useL.push_back(ex);
fillUse(ex->lhs(), useL, defL, funcs, messagesForFile, currLine);
fillUse(ex->rhs(), useL, defL, funcs, messagesForFile, currLine);
}
else if (ex->variant() == FUNC_CALL)
fillDef(ex, useL, defL, funcs, messagesForFile, currLine);
else
{
fillUse(ex->lhs(), useL, defL, funcs, messagesForFile, currLine);
fillUse(ex->rhs(), useL, defL, funcs, messagesForFile, currLine);
}
}
}
static void fillDef(SgExpression *ex, vector<SgExpression*> &useL, vector<SgExpression*> &defL,
const map<string, FuncInfo*> &funcs, vector<Messages> &messagesForFile, const int currLine)
{
if (ex)
{
if (ex->variant() == FUNC_CALL)
{
bool isIntrinsic = isSymbolIntrinsic(ex->symbol());
SgFunctionCallExp *call = (SgFunctionCallExp*)ex;
FuncInfo *currInfo = NULL;
auto it = funcs.find(call->funName()->identifier());
if (funcs.end() != it)
{
currInfo = it->second;
if (currInfo->funcParams.countOfPars != call->numberOfArgs())
{
wstring bufE, bufR;
__spf_printToLongBuf(bufE, L"Count of formal and actual parameters are not equal for function call '%s'", to_wstring(currInfo->funcName).c_str());
__spf_printToLongBuf(bufR, R82, to_wstring(currInfo->funcName).c_str());
messagesForFile.push_back(Messages(ERROR, currLine, bufR, bufE, 1046));
throw -991;
}
}
for (int z = 0; z < call->numberOfArgs(); ++z)
{
SgExpression *arg = call->arg(z);
if (isVarRef(arg))
{
if (currInfo)
{
if (currInfo->funcParams.isArgOut(z))
defL.push_back(arg);
}
else
{
if (!isIntrinsic)
defL.push_back(arg);
}
useL.push_back(arg);
}
fillUse(arg->lhs(), useL, defL, funcs, messagesForFile, currLine);
fillUse(arg->rhs(), useL, defL, funcs, messagesForFile, currLine);
}
}
else
{
fillUse(ex->lhs(), useL, defL, funcs, messagesForFile, currLine);
fillUse(ex->rhs(), useL, defL, funcs, messagesForFile, currLine);
}
}
}
SgExpression* makeList(const std::vector<SgExpression*> &vec)
{
if (vec.size() == 0)
return NULL;
SgExpression *list = new SgExpression(EXPR_LIST);
SgExpression *r_list = list;
for (int i = 0; i < vec.size(); ++i)
{
list->setLhs(vec[i]);
if (i != vec.size() - 1)
{
list->setRhs(new SgExpression(EXPR_LIST));
list = list->rhs();
}
}
return r_list;
}
static void defUseVar(SgStatement *stmt, SgStatement *func, SgExpression **def, SgExpression **use,
const map<string, FuncInfo*> &allFuncs, vector<Messages> &messagesForFile)
{
SgExpression *expr1, *expr2;
SgExpression *temp, *pt, *pt1;
SgArrayRefExp *aref;
SgExprListExp *exprli;
SgFunctionCallExp *fc;
SgInputOutputStmt *iostmt;
SgCallStmt *callStat;
if (!stmt || !func)
return;
*def = NULL;
*use = NULL;
switch (stmt->variant())
{
case ASSIGN_STAT:
expr1 = stmt->expr(0);
expr2 = stmt->expr(1);
// need to be recursively applied later;
if (expr1)
*def = expr1->symbRefs();
else
*def = NULL;
if (expr2)
*use = expr2->symbRefs();
else
*use = NULL;
for (temp = *def; temp; temp = temp->rhs())
{
if (aref = isSgArrayRefExp(temp->lhs()))
{
pt = aref->subscripts();
if (pt)
{
pt1 = pt->symbRefs();
// we add it to the end of use;
if (*use)
{
if (pt1 && (exprli = isSgExprListExp(*use)))
{
exprli->linkToEnd(*pt1);
}
}
else
*use = pt1;
}
}
}
for (temp = *use; temp; temp = temp->rhs())
{
if (aref = isSgArrayRefExp(temp->lhs()))
{
pt = aref->subscripts();
if (pt)
{
pt1 = pt->symbRefs();
// we add it to the end of use;
if (pt1 && (exprli = isSgExprListExp(*use)))
{
exprli->linkToEnd(*pt1);
}
}
}
if (fc = isSgFunctionCallExp(temp->lhs()))
{
FuncInfo *currInfo = NULL;
auto it = allFuncs.find(fc->funName()->identifier());
if (allFuncs.end() != it)
{
currInfo = it->second;
if (currInfo->funcParams.countOfPars != fc->numberOfArgs())
{
wstring bufE, bufR;
__spf_printToLongBuf(bufE, L"Count of formal and actual parameters are not equal for function call '%s'", to_wstring(currInfo->funcName).c_str());
__spf_printToLongBuf(bufR, R83, to_wstring(currInfo->funcName).c_str());
messagesForFile.push_back(Messages(ERROR, stmt->lineNumber(), bufR, bufE, 1046));
throw -991;
}
}
pt = fc->args();
if (pt)
{
pt1 = pt->symbRefs();
// we add it to the end of use;
if (pt1 && (exprli = isSgExprListExp(*use)))
{
exprli->linkToEnd(*pt1);
}
//new algo
if (currInfo)
{
vector<SgExpression*> defL;
vector<SgExpression*> useL;
fillDef(fc, useL, defL, allFuncs, messagesForFile, stmt->lineNumber());
if (defL.size())
{
SgExpression *list = makeList(defL);
if (exprli = isSgExprListExp(*def))
exprli->linkToEnd(*list);
else
*def = list;
}
} //old algo
else
{
// if not an intrinsic, needs to be added to the def list;
if (!isSymbolIntrinsic(fc->funName()))
{
pt1 = pt->symbRefs();
if (pt1 && (exprli = isSgExprListExp(*def)))
{
exprli->linkToEnd(*pt1);
}
else
*def = pt1;
}
}
}
}
}
break;
case FOR_NODE:
{
SgExprListExp *el;
SgVarRefExp *vr;
if (stmt->symbol())
{
vr = new SgVarRefExp(*(stmt->symbol()));
*def = new SgExprListExp(*vr);
*use = new SgExprListExp(*vr);
}
else
{
*use = NULL;
*def = NULL;
}
// Borne inf and sup are also sunject to use;
expr1 = stmt->expr(0);
expr2 = stmt->expr(1);
// need to be recursively applied later;
if (expr1)
{
pt1 = expr1->symbRefs();
if (*use)
{
if (pt1 && (exprli = isSgExprListExp(*use)))
{
exprli->linkToEnd(*pt1);
}
}
else
*use = pt1;
}
if (expr2)
{
pt1 = expr2->symbRefs();
if (*use)
{
if (pt1 && (exprli = isSgExprListExp(*use)))
{
exprli->linkToEnd(*pt1);
}
}
else
*use = pt1;
}
for (temp = *use; temp; temp = temp->rhs())
{
if (aref = isSgArrayRefExp(temp->lhs()))
{
pt = aref->subscripts();
if (pt)
{
pt1 = pt->symbRefs();
// we add it to the end of use;
if (pt1 && (exprli = isSgExprListExp(*use)))
{
exprli->linkToEnd(*pt1);
}
}
}
if (fc = isSgFunctionCallExp(temp->lhs()))
{
pt = fc->args();
if (pt)
{
pt1 = pt->symbRefs();
// we add it to the end of use;
if (pt1 && (exprli = isSgExprListExp(*use)))
{
exprli->linkToEnd(*pt1);
}
// if not an intrinsic, needs to be added to the def list;
if (!isSymbolIntrinsic(fc->funName()))
{
pt1 = pt->symbRefs();
if (pt1 && (exprli = isSgExprListExp(*def)))
{
exprli->linkToEnd(*pt1);
}
else
*def = pt1;
}
}
}
}
}
break;
case LOGIF_NODE:
case CONT_STAT:
case CONTROL_END: // here we should check if loop...
case IF_NODE:
case WHILE_NODE:
case DO_WHILE_NODE:
expr2 = stmt->expr(0);
// need to be recursively applied later;
if (expr2)
*use = expr2->symbRefs();
else
*use = NULL;
*def = NULL;
for (temp = *use; temp; temp = temp->rhs())
{
if (aref = isSgArrayRefExp(temp->lhs()))
{
pt = aref->subscripts();
if (pt)
{
pt1 = pt->symbRefs();
// we add it to the end of use;
if (pt1 && (exprli = isSgExprListExp(*use)))
{
exprli->linkToEnd(*pt1);
}
}
}
if (fc = isSgFunctionCallExp(temp->lhs()))
{
pt = fc->args();
if (pt)
{
pt1 = pt->symbRefs();
// we add it to the end of use;
if (pt1 && (exprli = isSgExprListExp(*use)))
{
exprli->linkToEnd(*pt1);
}
// if not an intrinsic, needs to be added to the def list;
if (!isSymbolIntrinsic(fc->funName()))
{
pt1 = pt->symbRefs();
if (pt1 && (exprli = isSgExprListExp(*def)))
{
exprli->linkToEnd(*pt1);
}
else
*def = pt1;
}
}
}
}
break;
case READ_STAT:
iostmt = isSgInputOutputStmt(stmt);
if (iostmt)
{
if (iostmt->itemList())
*def = iostmt->itemList()->symbRefs();
else
*def = NULL;
*use = NULL;
}
else
Message("internal error : IO statements not found\n", 0);
break;
case WRITE_STAT:
case PRINT_STAT:
iostmt = isSgInputOutputStmt(stmt);
if (iostmt)
{
if (iostmt->itemList())
*use = iostmt->itemList()->symbRefs();
else
*use = NULL;
*def = NULL;
}
else
Message("internal error : IO statements not found\n", 0);
break;
case PROC_STAT:
callStat = (SgCallStmt*)stmt;
pt = callStat->expr(0);
if (pt)
{
/**use = pt->symbRefs();
// if not an intrinsic, needs to be added to the def list;
if (!isSymbolIntrinsic(callStat->name()))
*def = pt->symbRefs();
printf("old use:\n");
recExpressionPrint(*use);
printf("old def:\n");
recExpressionPrint(*def);*/
vector<SgExpression*> defL;
vector<SgExpression*> useL;
FuncInfo *currInfo = NULL;
auto it = allFuncs.find(callStat->name()->identifier());
if (allFuncs.end() != it)
{
currInfo = it->second;
if (currInfo->funcParams.countOfPars != callStat->numberOfArgs())
{
wstring bufE, bufR;
__spf_printToLongBuf(bufE, L"Count of formal and actual parameters are not equal for function call '%s'", to_wstring(currInfo->funcName).c_str());
__spf_printToLongBuf(bufR, R84, to_wstring(currInfo->funcName).c_str());
messagesForFile.push_back(Messages(ERROR, stmt->lineNumber(), bufR, bufE, 1046));
throw -991;
}
}
for (int z = 0; z < callStat->numberOfArgs(); ++z)
{
SgExpression *arg = callStat->arg(z);
if (isVarRef(arg))
{
if (currInfo)
{
if (currInfo->funcParams.isArgOut(z))
defL.push_back(arg);
}
else
defL.push_back(arg);
useL.push_back(arg);
}
fillUse(arg->lhs(), useL, defL, allFuncs, messagesForFile, callStat->lineNumber());
fillUse(arg->rhs(), useL, defL, allFuncs, messagesForFile, callStat->lineNumber());
}
*use = makeList(useL);
*def = makeList(defL);
/*printf("new use:\n");
recExpressionPrint(*use);
printf("new def:\n");
recExpressionPrint(*def);
printf("");*/
}
else
{
*def = NULL;
*use = NULL;
}
break;
case GOTO_NODE:
case STOP_STAT:
case RETURN_STAT:
case RETURN_NODE:
case ELSEIF_NODE:
case ARITHIF_NODE:
case WHERE_NODE:
case WHERE_BLOCK_STMT:
case SWITCH_NODE:
case CASE_NODE:
case BREAK_NODE:
case EXIT_STMT:
case ASSGOTO_NODE:
case COMGOTO_NODE:
default:
*def = NULL;
*use = NULL;
break;
}
}
void initDefUseTable(SgStatement *func, const map<string, FuncInfo*> &allFuncs, vector<Messages> &messagesForFile)
{
SgStatement *last, *first, *lastfunc, *temp;
SgExpression *def, *use, *pt;
int i;
int nbatt, typeat, j;
if (!func)
return;
lastfunc = func->lastNodeOfStmt();
for (temp = func; temp; temp = temp->lexNext())
{
if (isSgExecutableStatement(temp))
{
nbatt = temp->numberOfAttributes();
for (j = 0; j < nbatt; j++)
{
typeat = temp->attributeType(j);
if ((typeat == USEDLIST_ATTRIBUTE) ||
(typeat == DEFINEDLIST_ATTRIBUTE))
{
temp->deleteAttribute(j);
j--;
}
}
}
if (temp == lastfunc)
break;
}
for (temp = func; temp; temp = temp->lexNext())
{
if (isSgExecutableStatement(temp))
{
defUseVar(temp, func, &def, &use, allFuncs, messagesForFile);
temp->addAttribute(USEDLIST_ATTRIBUTE, (void*)use, 0);
temp->addAttribute(DEFINEDLIST_ATTRIBUTE, (void*)def, 0);
}
if (temp == lastfunc)
break;
}
}
//
// Example of functions for flow analysis
//
int symbRefEqual(void *e1, void *e2)
{
SgExpression *ex1, *ex2;
SgSymbol *s1, *s2;
PT_ELSET el1, el2;
if (!e1 && !e2)
return 1;
if (!e1 || !e2)
return 0;
el1 = (PT_ELSET)e1;
el2 = (PT_ELSET)e2;
ex1 = el1->expr;
ex2 = el2->expr;
if ((s1 = ex1->symbol()) && (s2 = ex2->symbol()))
{
if (s1 == s2)
{
if (el1->stmt == el2->stmt)
return 1;
else
return 0;
}
else
return 0;
}
else
return 0;
}
void myPrint(void *e1)
{
SgExpression *ex1;
PT_ELSET el1;
if (!e1)
return;
el1 = (PT_ELSET)e1;
ex1 = el1->expr;
if (el1->stmt)
printf("(id = %d, line = %d, ", el1->stmt->id(), el1->stmt->lineNumber());
else
printf("(id = -, line = -, ");
if (ex1->symbol())
printf("%s", ex1->symbol()->identifier());
else
ex1->unparsestdout();
printf(")");
printf(",");
}
//
// Example of function to compute gen and kill sets for Reaching Definition.
// NOARRAYREF indicate if we want array ref in
Set *makeGenSet(SgStatement *func, SgStatement *stmt)
{
SgExpression *def, *use, *pt;
PT_ELSET el;
Set *defset, *pts;
if (!func || !stmt)
return NULL;
def = (SgExpression *)stmt->attributeValue(0, DEFINEDLIST_ATTRIBUTE);
// Defined[stmt->id()];
defset = new Set(symbRefEqual, NULL, myPrint);
#ifdef __SPF
addToCollection(__LINE__, __FILE__, defset, 1);
#endif
if (def)
{
for (pt = def; pt; pt = pt->rhs())
{
if (!isSgTypeExp(pt->lhs()))
{
if (!NOARRAYREF || !isSgArrayRefExp(pt->lhs()))
{
el = new struct elset;
#ifdef __SPF
addToCollection(__LINE__, __FILE__, el, 1);
#endif
el->stmt = stmt;
el->expr = pt->lhs();
defset->addElement((void *)el);
}
}
}
}
pts = defset;
// printf("Printing defset:\n");
// defset->printSet();
defset = defset->compact();
if (pts)
{
#ifdef __SPF
removeFromCollection(pts);
#endif
delete pts;
}
// defset->printSet();
return defset;
}
Set *makeKillSet(SgStatement *func, SgStatement *stmt)
{
SgExpression *def, *use, *pt, *defstmt, *expr1, *pt1;
PT_ELSET el;
Set *killset, *pts;
SgStatement *last, *first, *lastfunc, *temp;
int trouve;
if (!func || !stmt)
return NULL;
killset = new Set(symbRefEqual, NULL, myPrint);
#ifdef __SPF
addToCollection(__LINE__, __FILE__, killset, 1);
#endif
last = func->lastNodeOfStmt();
defstmt = (SgExpression *)stmt->attributeValue(0, DEFINEDLIST_ATTRIBUTE);
//Defined[stmt->id()];
if (defstmt)
{
for (pt1 = defstmt; pt1; pt1 = pt1->rhs())
{
expr1 = pt1->lhs();
if (!isSgArrayRefExp(expr1) && !isSgTypeExp(expr1))
{ // cannot kill an array ref;
for (temp = func; temp; temp = temp->lexNext())
{
if (temp != stmt)
{
if (def = (SgExpression *)temp->attributeValue(0, DEFINEDLIST_ATTRIBUTE))
//Defined[temp->id()])
{
for (pt = def; pt; pt = pt->rhs())
{
if (pt->lhs())
{
if (pt->lhs()->symbol() == expr1->symbol())
{
el = new struct elset;
#ifdef __SPF
addToCollection(__LINE__, __FILE__, el, 1);
#endif
el->stmt = temp;
el->expr = pt->lhs();
killset->addElement((void *)el);
}
}
}
}
}
if (temp == last)
break;
}
}
}
}
pts = killset;
// printf("Printing killset:\n");
// killset->printSet();
killset = killset->compact();
// killset->printSet();
if (pts)
{
#ifdef __SPF
removeFromCollection(pts);
#endif
delete pts;
}
return killset;
}

View File

@@ -0,0 +1,66 @@
// set of the defined values used for the data dependence analsysis;
// for most of the files
#define MAXITDATAFLOW 100
// needs to be bigger than real loop, symbols may appear twice.
#define MAXNESTEDLOOP 40
#define MAXDIMARRAY 7
#define MAXP 100
#define MAXNODE 10000
#define NOARRAYREF 0
#define NO_STEP 10000
//constanteSet.C
#define UNDEFFLAG 1
#define NONCONSTFLAG 2
#define CONSTFLAG 3
//depGraph.C
#define WRONGDEP 0
#define ARRAYDEP 1
#define PRIVATEDEP 2
#define REDUCTIONDEP 3
#define SCALARDEP 4
#define DEPZERO 1
#define DEPGREATER 2
#define DEPLESS 4
//dependence.C
#define OUTDEP 1
#define FLOWDEP 2
#define ANTIDEP 3
#define UNKNOWNDEP 4
//reductionCode.C
#define UNKNOWREDUCTION 0
//SUM
#define SADDREDUCTION 2
#define DADDREDUCTION 3
#define IADDREDUCTION 4
//MULT
#define SMULREDUCTION 5
#define DMULREDUCTION 6
#define IMULREDUCTION 7
//DIV
#define SDIVREDUCTION 8
#define DDIVREDUCTION 9
#define IDIVREDUCTION 10
//MAX
#define SMAXREDUCTION 11
#define DMAXREDUCTION 12
#define IMAXREDUCTION 13
//MIN
#define SMINREDUCTION 14
#define DMINREDUCTION 15
#define IMINREDUCTION 16
//LOGICAL
#define ANDREDUCTION 17
#define ORREDUCTION 18
#define EQVREDUCTION 19
#define NEQVREDUCTION 20
// set.C
#define MAXELEMENT 10000000
#define ALLOCATECHUNKSET 10000

View File

@@ -0,0 +1,10 @@
#pragma once
struct elset
{
SgStatement *stmt;
SgExpression *expr;
};
typedef struct elset *PT_ELSET;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,73 @@
#pragma once
#include <vector>
#include <set>
#include <string>
#include "set.h"
////////////////////////////////////////////////////////////
// to deal with data dep, scalar are considered apart
// but included as special nodes in the dep grap...
////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
// class dep graph used for restructuring
// two classes, the graph and the graph node
//////////////////////////////////////////////////////////////
class depNode {
public:
SgStatement *stmtin;
SgStatement *stmtout;
SgExpression *varin; // this is var;
SgExpression *varout; // this is var;
int typedep; // WRONGDEP something wrong happend, ARRAYDEP array dependence, > 1 SCALAR DEP
int kinddep; // ddflow, ddanti, ddoutput
int lenghtvect;
std::vector<signed short> distance;
std::vector<signed short> knowndist;
depNode(SgStatement *sin,SgStatement *sout, SgExpression *vin, SgExpression *vout, int tdep, int kdep, int *dist, int *kdist, int le);
~depNode();
void displayDep(bool onlyDifferentLines) const;
std::string displayDepToStr() const;
std::pair<std::string, std::string> createDepMessagebetweenArrays() const;
};
//////////////////////////////////////////////////////////////
// The graph is represented by
//////////////////////////////////////////////////////////////
class depGraph {
std::vector<depNode*> nodes;
public:
const std::set<std::string> privVars;
SgFile *file;
Set *arrayRef;
Set *induc;
SgSymbol *tsymb[40/*MAXNESTEDLOOP*/];
int loopnum;
SgStatement *func;
SgStatement *loop;
int perfectNestedLevel;
int nbstmt;
SgStatement **tabstat;
int *tabtag;
depGraph(SgFile *fi, SgStatement *f, SgStatement *l, const std::set<std::string> &privVars);
~depGraph();
void addAnEdge(SgStatement *sin, SgStatement *sout, SgExpression *vin, SgExpression *vout, int tdep, int kdep, int *dist, int *kdist, int le);
void display(bool onlyDifferentLines = false);
void scalarRefAnalysis(SgStatement *loop);
void redoScalarRefAnalysis(SgStatement *loop);
depNode *firstNode();
int isLoopCarryingTheDep(SgStatement *loop, depNode *node);
depNode *isThereAnEdge(SgStatement *s1, SgStatement *s2);
int isThereAnEdgeSCC(SgStatement *s1, SgStatement *s2, SgStatement *doloop);
void depthTraversal(int stmtid, SgStatement *doloop);
int getHigherMark();
int getZeroMark();
int computeSCC(SgStatement *stmtin);
const std::vector<depNode*>& getNodes() const;
// ... much more here
};

View File

@@ -0,0 +1,291 @@
////////////////////////////////////////////////////////////////////////////////////////
/////// Interface for data dependence analysis using the attributes mechanisn///////////
///// FB. July 94 Indiana University ///////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <set>
#include <string>
#include "sage++user.h"
#include "depInterfaceExt.h"
//////////////////////////////////// A set of routines for interfacing the dep analysis //////////////////////////////////
static int initializeTheAnnotationSystem = 1;
void initAnnotationsSysExt(const int printannotation)
{
if (initializeTheAnnotationSystem)
{
if (printannotation)
initAnnotationSystem(1);
else
initAnnotationSystem(0);
initializeTheAnnotationSystem = 0;
}
}
void doDependenceAnalysisOnTheFullFile(SgFile *file, int printdep, int printannotation, int verbose)
{
SgForStmt *doloop;
int i, j, nbfunc;
SgStatement *func, *temp, *last;
depGraph *depg;
depNode *datadep;
int nbatt, typeat;
if (!file)
return;
initAnnotationsSysExt(printannotation);
// delete the attributes first;
nbfunc = file->numberOfFunctions();
for (i = 0; i < nbfunc; i++)
{
func = file->functions(i);
if (func)
{
last = func->lastNodeOfStmt();
for (temp = func; temp && (temp != last); temp = temp->lexNext())
{
nbatt = temp->numberOfAttributes();
for (j = 0; j < nbatt; j++)
{
typeat = temp->attributeType(j);
if ((typeat == DEPGRAPH_ATTRIBUTE) ||
(typeat == INDUCTION_ATTRIBUTE) ||
(typeat == ACCESS_ATTRIBUTE) ||
(typeat == DEPENDENCE_ATTRIBUTE))
{
temp->deleteAttribute(j);
j--;
}
}
}
}
}
nbfunc = file->numberOfFunctions();
for (i = 0; i < nbfunc; i++)
{
func = file->functions(i);
doDependenceAnalysisForAFunction(file, func, printdep, printannotation, verbose);
}
}
void doDependenceAnalysisForAFunction(SgFile *file, SgStatement *func, int printdep, int printannotation, int verbose)
{
SgForStmt *doloop;
int i, j, nbfunc;
SgStatement *temp, *last;
depGraph *depg;
depNode *datadep;
int nbatt, typeat;
if (!file || !func)
return;
initAnnotationsSysExt(printannotation);
last = func->lastNodeOfStmt();
for (temp = func; temp && (temp != last); temp = temp->lexNext())
{
nbatt = temp->numberOfAttributes();
for (j = 0; j < nbatt; j++)
{
typeat = temp->attributeType(j);
if ((typeat == DEPGRAPH_ATTRIBUTE) ||
(typeat == INDUCTION_ATTRIBUTE) ||
(typeat == ACCESS_ATTRIBUTE) ||
(typeat == DEPENDENCE_ATTRIBUTE))
{
temp->deleteAttribute(j);
j--;
}
}
}
if (verbose)
printf(" -init dependence for function %s\n", func->symbol()->identifier());
//!!!!!!
//TODO: add allFuncs if needed, now it does not work!
throw(-991);
//initializeDepAnalysisForFunction(file, func);
//!!!!!!
// now compute the dependence graph for each loop;
last = func->lastNodeOfStmt();
for (temp = func; temp && (temp != last); temp = temp->lexNext())
{
if (doloop = isSgForStmt(temp))
{
depg = new depGraph(file, func, temp, std::set<std::string>());
if (depg)
{
if (printdep)
depg->display();
const std::vector<depNode*> &nodes = depg->getNodes();
//printf("data dep for loop on line %d is = %d\n", doloop->lineNumber(), nodes.size());
// add the attributes here;
/*doloop->addAttribute(DEPGRAPH_ATTRIBUTE, (void *)depg, 0);
doloop->addAttribute(INDUCTION_ATTRIBUTE, (void *)depg->induc, 0);
doloop->addAttribute(ACCESS_ATTRIBUTE, (void *)depg->arrayRef, 0);
const std::vector<depNode*> &nodes = depg->getNodes();
for (int i = 0; i < nodes.size(); ++i)
{
datadep = nodes[i];
doloop->addAttribute(DEPENDENCE_ATTRIBUTE, (void *)datadep, 0);
}*/
//TODO: save needed info
delete depg;
}
else
if (verbose)
Message("no data dependence graph found", temp->lineNumber());
// skip the loop;
temp = doloop->lastNodeOfStmt();
}
}
}
//
// Look in the subroutine if there is equivalence statement (drop it if yes for now)
//
int isThereEquivalenceStatement(SgStatement *func)
{
SgStatement *temp, *last;
if (!func)
return FALSE;
last = func->lastNodeOfStmt();
for (temp = func; temp && (temp != last); temp = temp->lexNext())
{
if (EQUI_STAT == temp->variant())
return TRUE;
}
return FALSE;
}
int isWriteToSymbolInStatement(SgSymbol *symb, SgStatement *loop, depGraph *depg)
{
int i;
PT_ACCESSARRAY access1;
for (i = 0; i < depg->arrayRef->size(); i++)
{
access1 = (PT_ACCESSARRAY)depg->arrayRef->getElement(i);
if (loop->isIncludedInStmt(*(access1->stmt)))
{
if (access1 && access1->scalar && access1->rw)
{
if (access1->var->symbol() == symb)
{
return 1;
}
}
}
}
return 0;
}
//
// take a data dep and return the first dimension with a non zero distance
//
int leadingDimension(depNode *datadep, int entryLevel)
{
int i, j;
int carried;
if (!datadep)
return 0;
if (datadep->typedep == ARRAYDEP)
{
if (entryLevel)
{ // check that the dependence is not carried by the outer loops first
for (i = 1; (i <= datadep->lenghtvect) && (i <= entryLevel); i++)
{
if (datadep->knowndist[i])
{
if (datadep->distance[i] != 0)
{
return datadep->lenghtvect;
}
}
else
{
if (!(datadep->distance[i] & DEPZERO))
{
return datadep->lenghtvect;
}
}
}
}
for (i = 1 + entryLevel; i <= datadep->lenghtvect; i++)
{
if (datadep->knowndist[i])
{
if (datadep->distance[i] != 0)
{
return i - 1;
}
}
else
{
if ((datadep->distance[i] & DEPGREATER) ||
(datadep->distance[i] & DEPLESS))
{
return i - 1;
}
}
}
return datadep->lenghtvect;
}
else
return 0;
}
int numberOfOuterParallelLoops(SgStatement *loop, depGraph *depg, int entryLevel)
{
depNode *datadep;
int Min, t;
if (!loop)
return 0;
Min = MAXNESTEDLOOP;
const std::vector<depNode*> &nodes = depg->getNodes();
for (int i = 0; i < nodes.size(); ++i)
{
datadep = nodes[i];
if (datadep->typedep == ARRAYDEP)
{
// source and sink must be included in the loop;
if (datadep->stmtin && datadep->stmtout &&
loop->isIncludedInStmt(*(datadep->stmtin)) &&
loop->isIncludedInStmt(*(datadep->stmtout)))
{
t = leadingDimension(datadep, entryLevel);
if (t < Min)
Min = t;
}
}
}
return Min - entryLevel;
}

View File

@@ -0,0 +1,134 @@
////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////// includes for data dep information ////////////////////////
////// FB July 94 Indiana University ///////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////
// the set class
#include "set.h"
#include "definesValues.h"
//////////////////////////////////////////////////////////////////////////////////
// external for the anotation system
//////////////////////////////////////////////////////////////////////////////////
#include "annotationDriver.h"
extern SgAnnotation *getTheAnnotationThatApply(SgStatement *stmt, char *kind);
extern SgAnnotation * getTheAnnotationWithString(char *kind);
extern int isAnnotationWithString(SgStatement *stmt, char *kind, int len);
extern void initAnnotationSystem(int printann);
//////////////////////////////////////////////////////////////////////////////////
// some external from loop transformations
//////////////////////////////////////////////////////////////////////////////////
extern int tileLoops(SgStatement *func, SgStatement *b, int *size, int nb);
extern int distributeLoopSCC(SgStatement *b, int *sccTable, int leadingdim, int numSCC);
extern int loopFusion(SgStatement *loop1,SgStatement *loop2);
///////////////////////////////////////////////////////////////////////////////////////
// Control FLOW part of declaration
///////////////////////////////////////////////////////////////////////////////////////
extern void controlFlow(SgStatement *stmt, SgStatement *func,
SgStatement **pred, SgStatement **suc,
int *predin,int *sucint);
///////////////////////////////////////////////////////////////////////////////////////
// declaration for the data flow framework
///////////////////////////////////////////////////////////////////////////////////////
extern Set *genSet[MAXNODE];
extern Set *killSet[MAXNODE];
extern Set *inSet[MAXNODE];
extern Set *outSet[MAXNODE];
extern void iterativeForwardFlowAnalysis(SgFile *file,
SgStatement *func,
Set *(*giveGenSet)(SgStatement *func,SgStatement *stmt),
Set *(*giveKillSet)(SgStatement *func,SgStatement *stmt),
int (*feq)(void *e1, void *e2),
void *(*fcomb)(void *e1, void *e2),
void (*fp)(void *e1));
extern void generalIterativeFlowAnalysis(SgFile *file,
SgStatement *func,
Set *(*transfertSet)(SgStatement *func,SgStatement *stmt, Set *setin),
int (*feq)(void *e1, void *e2),
void* (*fcomb)(void *e1, void *e2),
void (*fp)(void *e1));
///////////////////////////////////////////////////////////////////////////////////////
// declaration for defuse and reaching definition
///////////////////////////////////////////////////////////////////////////////////////
#include "definitionSet.h"
extern Set *makeGenSet(SgStatement *func,SgStatement *stmt);
extern Set *makeKillSet(SgStatement *func,SgStatement *stmt);
extern int symbRefEqual(void *e1, void *e2);
extern void myPrint(void *e1);
///////////////////////////////////////////////////////////////////////////////////////
// Part for constante propagation.....
///////////////////////////////////////////////////////////////////////////////////////
#include "constanteSet.h"
extern int constPropEqual(void *e1, void *e2);
extern void constPropPrint(void *e1);
extern void * constPropCombine(void *e1, void *e2);
extern Set *transConstante(SgStatement *func,SgStatement *stmt, Set *setin);
///////////////////////////////////////////////////////////////////////////////////////
// Part for induction variable
///////////////////////////////////////////////////////////////////////////////////////
#include "inducVar.h"
extern int inducVarEqual(void *e1, void *e2);
extern void inducVarPrint(void *e1);
extern int definitionInStmt(SgStatement *func,SgStatement *stmtin, SgExpression *defvar);
extern Set *computeConstanteInStmt(SgStatement *func,SgStatement *stmtin);
extern Set *computeInductionVariables(SgStatement *func,SgStatement *stmt);
extern Set *getAllInductionVar(SgStatement *func,
SgStatement *stmt,int level, int *num,int include);
///////////////////////////////////////////////////////////////////////////////////////
// Part for computing array reference
///////////////////////////////////////////////////////////////////////////////////////
#include "arrayRef.h"
extern int NbLinearRef;
extern int NbNonLinearRef;
extern int linearRepArray(SgExpression *ex1, SgSymbol **symb,
int size,
int linear[MAXDIMARRAY][MAXNESTEDLOOP],
int *cst);
extern int arrayEqual(void *e1, void *e2);
extern void arrayPrint(void *e1);
extern Set *loopArrayAccessAnalysis(SgStatement *func,SgStatement *stmt,
SgSymbol **tsymb, Set **induc);
///////////////////////////////////////////////////////////////////////////////////////
// for data dependence computation (uses omega Test)
///////////////////////////////////////////////////////////////////////////////////////
#include "dependence.h"
extern Set *computeLoopDependencies(SgStatement *func,Set *inset, SgSymbol **tsymb, Set *induc);
extern "C" void SetOmegaDebug();
///////////////////////////////////////////////////////////////////////////////////////
// for data dependence computation (uses omega Test)
///////////////////////////////////////////////////////////////////////////////////////
#include "depGraph.h"
///////////////////////////////////////////////////////////////////////////////////////
// from intrinsic.C
///////////////////////////////////////////////////////////////////////////////////////
extern int isStmtCallToFuncNotIntrinsic(SgStatement *stmt);
extern int isSymbolIntrinsic(SgSymbol *symb);
extern int isExprCallToFuncNotIntrinsic(SgExpression *exp);

View File

@@ -0,0 +1,14 @@
/////////////////// TO BE INCLUDED FOR USING DATA DEPENDENCE ///////////////////////
#include "depInterface.h"
// initialize for a full file;
extern void doDependenceAnalysisOnTheFullFile(SgFile *file, int printdep, int printannotation, int verbose);
extern void doDependenceAnalysisForAFunction(SgFile *file, SgStatement *func, int printdep, int printannotation, int verbose);
extern int isThereEquivalenceStatement(SgStatement *func);
extern int isWriteToSymbolInStatement(SgSymbol *symb, SgStatement *loop, depGraph *depg);
extern int leadingDimension(depNode *datadep,int entryLevel);
extern int numberOfOuterParallelLoops(SgStatement *loop, depGraph *depg,int entryLevel);
extern void initAnnotationsSysExt(const int printannotation);

View File

@@ -0,0 +1,758 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __SPF
extern "C" void addToCollection(const int line, const char *file, void *pointer, int type);
extern "C" void removeFromCollection(void *pointer);
#endif
#if __SPF && NDEBUG && __BOOST
#include <boost/thread.hpp>
#endif
extern int passDone;
#include "sage++user.h"
#include "definesValues.h"
#include "set.h"
#include "definitionSet.h"
#include "inducVar.h"
#include "arrayRef.h"
#include "dependence.h"
/* to link with the omega Test */
#include "OmegaForSage/include/portable.h"
#include "OmegaForSage/include/affine.h"
extern void SetSTuff();
extern "C" void SetOmegaDebug();
extern "C" void initAnnotation();
extern "C" void Look_For_Align_Declaration();
extern void dd_omega_test(a_access access1, a_access access2, ddnature oitype, ddnature iotype, uint nest1, uint nest2, uint bnest);
///////////////////////////////////////////////////////////////////////////
// Some global declaration
///////////////////////////////////////////////////////////////////////////
SgStatement *currentStmtIn = NULL;
SgStatement *currentStmtOut = NULL;
SgExpression *currentVarIn = NULL;
SgExpression *currentVarOut = NULL;
int WarningOutForNegativeStep = 0;
int TurnIfConstructionOf = 0;
// Kolganov A.S. 31.07.2017
// try to process loop with negative step: inverse the iteration space
#define PROCESS_LOOPS_WITH_NEG_STEP 1
// Needs to provide dummy function
int dummyEqual(void *e1, void *e2)
{
return (e1 == e2);
}
void dummyPrint(void *e1)
{
printf("Dummy print\n");
}
///////////////////////////////////////////////////////////////////////////
// comming from depGraph.c
///////////////////////////////////////////////////////////////////////////
#include "depGraph.h"
#include "../VisualizerCalls/get_information.h"
extern depGraph *currentDepGraph;
///////////////////////////////////////////////////////////////////////////
// here we call the omega test routine.... First some routine to do the job
// compute the data dependencies using the Omega Test....
///////////////////////////////////////////////////////////////////////////
affine_expr *makeOmegaAffine(int size, var_id *induc, int *linear, int cst, int notaffine, Set *setForDealocatingMemory)
{
int i, finalsize;
affine_expr *ptaff, *init;
if (!induc || !linear)
return &not_affine;
if (!notaffine)
return &not_affine;
if (WarningOutForNegativeStep)
return &not_affine;
ptaff = new affine_expr;
#ifdef __SPF
addToCollection(__LINE__, __FILE__, ptaff, 1);
#endif
setForDealocatingMemory->addElement((void *)ptaff);
ptaff->nterms = size + 1;
ptaff->other_branch = NULL;
(ptaff->terms[0]).tiny_var = NULL;
(ptaff->terms[0]).coefficient = cst;
if (size >= maxVars)
{
Message("Too many variable in makeOmegaAffine\n");
return NULL;
}
finalsize = 0;
for (i = 1; i <= size; i++)
{
if (linear[i - 1] != 0)
{
finalsize++;
(ptaff->terms[finalsize]).tiny_var = induc[i - 1];
(ptaff->terms[finalsize]).coefficient = linear[i - 1];
}
}
ptaff->nterms = finalsize + 1;
return ptaff;
}
int fillOmegaAccess(PT_ACCESSARRAY el1, a_access access1, const Set *induc, var_id *inducom,
context_iterator firstcontiter, char *name, int inif, Set *setForDealocatingMemory)
{
int i, j;
sub_iterator itern = NULL;
sub_iterator firstiter;
PT_INDUCVAR ind, cur;
firstiter = NULL;
for (j = 0; j < el1->nbdim; j++)
{
if (firstiter)
{
itern->next = new struct omegaIterator;
#ifdef __SPF
addToCollection(__LINE__, __FILE__, itern->next, 1);
#endif
setForDealocatingMemory->addElement((void *)itern->next);
itern = itern->next;
itern->next = NULL;
}
else
{
itern = new struct omegaIterator;
#ifdef __SPF
addToCollection(__LINE__, __FILE__, itern, 1);
#endif
setForDealocatingMemory->addElement((void *)itern);
firstiter = itern;
itern->next = NULL;
}
if (el1->isLinear[j] && !el1->scalar)
{
itern->isaffine = TRUE;
itern->affine = makeOmegaAffine(induc->size(), inducom, el1->linear[j], el1->cst[j], el1->isLinear[j], setForDealocatingMemory);
}
else
{
itern->isaffine = FALSE;
itern->affine = &not_affine;
}
itern->cstvalue = 0;
itern->constante = NULL;
}
//
access1->str = new char[256];
#ifdef __SPF
addToCollection(__LINE__, __FILE__, access1->str, 2);
#endif
setForDealocatingMemory->addElement((void *)access1->str);
strcpy(access1->str, name);
access1->symb = NULL;
access1->subiter = firstiter;
access1->context = firstcontiter;
access1->line = el1->stmt->lineNumber();
access1->cdepth = -1;
access1->tdepth = -1;
access1->idforsage = el1->var->id();
access1->inIfStmt = inif;
// look at for the level;
cur = NULL;
for (j = 0; j < induc->size(); j++)
{
ind = (PT_INDUCVAR)induc->getElement(j);
if (ind && (ind->loopnum == el1->level))
{
cur = ind;
break;
}
}
if (cur)
{
access1->depth = cur->level;
}
else
access1->depth = 0;
access1->pri = 0;
access1->level = el1->level; // temporary setting;
if (el1->rw)
{
access1->fetch = FALSE;
access1->store = TRUE;
}
else
{
access1->fetch = TRUE;
access1->store = FALSE;
}
access1->update = 0;
access1->lexord = 1; // temporary setting;
return access1->depth;
}
// answer yes if el1 >> el2; to be optimize by checking procedure control_end
int lexOrder(PT_ACCESSARRAY el1, PT_ACCESSARRAY el2)
{
SgStatement *stmt;
if (!el1 || !el2)
return FALSE;
if (el1->stmt == el2->stmt)
return FALSE;
if (!el1->stmt || !el2->stmt)
return FALSE;
stmt = el1->stmt;
while (stmt)
{
if (stmt == el2->stmt)
return TRUE;
stmt = stmt->lexNext();
}
return FALSE;
}
context_iterator makeOmegaIf(int depth, SgStatement *stmt, context_iterator next, int brelse, Set *setForDealocatingMemory)
{
if_context ifstat;
context_iterator contiter;
if (!stmt)
return NULL;
// dealing with the conditions later...
contiter = new struct omegaContIter;
#ifdef __SPF
addToCollection(__LINE__, __FILE__, contiter, 1);
#endif
setForDealocatingMemory->addElement((void *)contiter);
contiter->next = next;
contiter->depth = depth;
contiter->loopiter = FALSE;
contiter->line = stmt->lineNumber();
contiter->loop = NULL;
ifstat = new struct omegaIf;
#ifdef __SPF
addToCollection(__LINE__, __FILE__, ifstat, 1);
#endif
setForDealocatingMemory->addElement((void *)ifstat);
ifstat->oper = greater_eq;
ifstat->ident = stmt->id();
ifstat->left = &not_affine;
ifstat->right = &not_affine;
ifstat->condOK = FALSE;
ifstat->partelse = brelse;
contiter->ifstmt = ifstat;
return contiter;
}
// try to manage non nested loops;;;
context_iterator fillOmegaLoop(PT_ACCESSARRAY el1, const Set *induc, var_id *inducom, SgSymbol **tsymb, int *inif, Set *setForDealocatingMemory)
{
int i, j, inbrelse, k;
PT_INDUCVAR ind, cur;
context_iterator contiter, firstcontiter;
loop_context loop;
if_context ifstat;
int linear[MAXNESTEDLOOP];
int cst, loopnum, curnum;
var_id tempvar;
SgExpression *step;
SgForStmt *stloop;
SgStatement *currentstmt, *cp, *tmp;
if (!el1 || !induc || !tsymb)
return NULL;
// look for the induction variable corresponding to the loop...;
// examine for duplicate symbols first so the linear loop bounds are set right;
loopnum = el1->level;
while (loopnum != -1)
{
cur = NULL;
for (j = 0; j < induc->size(); j++)
{
ind = (PT_INDUCVAR)induc->getElement(j);
if (ind && (!ind->constante) && (ind->loopnum == loopnum))
{
cur = ind;
// check if there is multiple uses of the same variable;
// to set curnum to the righ symbol;
// the first one has to be taken;
// this is related to the linear expression;
for (k = 0; k < j; k++)
{
ind = (PT_INDUCVAR)induc->getElement(k);
if (ind->var->symbol() == cur->var->symbol())
{
// switch the position in inducom so the;
// linear expression for the loops bound are right;
tempvar = inducom[k];
inducom[k] = inducom[j];
inducom[j] = tempvar;
break;
}
}
break;
}
}
if (!cur)
break;
loopnum = cur->include;
}
loopnum = el1->level;
firstcontiter = NULL;
contiter = NULL;
curnum = -1;
currentstmt = el1->stmt;
*inif = FALSE;
while (loopnum != -1)
{
cur = NULL;
for (j = 0; j < induc->size(); j++)
{
ind = (PT_INDUCVAR)induc->getElement(j);
if (ind && (!ind->constante) && (ind->loopnum == loopnum))
{
cur = ind;
curnum = j;
// check if there is multiple uses of the same variable;
// to set curnum to the righ symbol;
// the first one has to be taken;
// this is related to the linear expression;
for (k = 0; k < j; k++)
{
ind = (PT_INDUCVAR)induc->getElement(k);
if (ind->var->symbol() == cur->var->symbol())
{
curnum = k; // position has been switch before;
break;
}
}
break;
}
}
if (cur)
{
if (TurnIfConstructionOf)
{
// is in IF Statement; problems with the ELSE IF STUFF;
if (currentstmt && currentstmt->controlParent() &&
((currentstmt->controlParent()->variant() == IF_NODE) ||
(currentstmt->controlParent()->variant() == ELSEIF_NODE)))
{
// which branch of the IF???;
cp = currentstmt->controlParent();
inbrelse = TRUE;
if (!(currentstmt->controlParent()->variant() == ELSEIF_NODE))
{
for (i = 0; i < cp->numberOfChildrenList1(); i++)
{
tmp = cp->childList1(i);
if (tmp == currentstmt)
{
inbrelse = FALSE;
break;
}
}
*inif = TRUE;
firstcontiter = makeOmegaIf(cur->level, currentstmt->controlParent(), firstcontiter, inbrelse, setForDealocatingMemory);
}
}
// end of if statement;
}
contiter = new struct omegaContIter;
#ifdef __SPF
addToCollection(__LINE__, __FILE__, contiter, 1);
#endif
setForDealocatingMemory->addElement((void *)contiter);
contiter->next = firstcontiter;
firstcontiter = contiter;
contiter->depth = cur->level;
contiter->loopiter = TRUE;
contiter->line = cur->stmt->lineNumber();
currentstmt = cur->stmt;
contiter->loop = new struct omegaLoop;
#ifdef __SPF
addToCollection(__LINE__, __FILE__, contiter->loop, 1);
#endif
setForDealocatingMemory->addElement((void *)contiter->loop);
loop = contiter->loop;
// for different non perfectly nested loop
// the index variable must be the same, so there is a pb here;
loop->symb = inducom[curnum];
// build the linear rep ;
cst = 0;
for (i = 0; i < MAXNESTEDLOOP; i++)
linear[i] = 0;
if (cur->lbound->linearRepresentation(linear, tsymb, &cst, induc->size()))
{
loop->startl = makeOmegaAffine(induc->size(), inducom, linear, cst, 1, setForDealocatingMemory);
}
else
{
loop->startl = &not_affine;
// if (VeryVerbose)
// Message("Non Linear Starting Bound of Loop",cur->stmt->lineNumber());
}
loop->cstvaluestart = 0;
loop->constantestart = NULL;
cst = 0;
for (i = 0; i < MAXNESTEDLOOP; i++)
linear[i] = 0;
if (cur->ubound->linearRepresentation(linear, tsymb, &cst, induc->size()))
{
loop->endl = makeOmegaAffine(induc->size(), inducom, linear, cst, 1, setForDealocatingMemory);
}
else
{
loop->endl = &not_affine;
// if (VeryVerbose)
// Message("Non Linear Ending Bound of Loop",cur->stmt->lineNumber());
}
loop->cstvaluesend = 0;
loop->constanteend = NULL;
// deal with the step of the loop;
if (stloop = isSgForStmt(cur->stmt))
{
if (step = stloop->step())
{
if (step->isInteger())
{
loop->hasstep = TRUE;
loop->stepl = step->valueInteger();
loop->knownstep = TRUE;
if (loop->stepl < 0)
{
#if PROCESS_LOOPS_WITH_NEG_STEP
loop->stepl = -loop->stepl;
std::swap(loop->startl, loop->endl);
#else
loop->hasstep = FALSE;
loop->stepl = 1;
loop->knownstep = FALSE;
loop->startl = &not_affine;
loop->endl = &not_affine;
if (!WarningOutForNegativeStep)
{
Message("Negative Steps found: Ignored loop bounds", stloop->lineNumber());
WarningOutForNegativeStep = 1;
}
#endif
}
}
else
{
loop->hasstep = FALSE;
loop->stepl = 1;
loop->knownstep = FALSE;
}
}
else
{
loop->hasstep = FALSE;
loop->stepl = 1;
loop->knownstep = TRUE;
}
}
else
{
loop->hasstep = FALSE;
loop->stepl = 1;
loop->knownstep = FALSE;
}
}
else
break;
loopnum = cur->include;
}
return firstcontiter;
}
int commonDepth(context_iterator iti1, context_iterator iti2)
{
context_iterator it1, it2;
it1 = iti1;
it2 = iti2;
int depth = 0;
while (!cont_i_done(it1) && !cont_i_done(it2))
{
if (cont_i_cur_loop_p(it1) && cont_i_cur_loop_p(it2))
{
if (loop_var_id(cont_i_cur_loop(it1)) != loop_var_id(cont_i_cur_loop(it2)))
return depth;
depth++;
}
// common depth does not go in If (I guess);
// else
// {
// if (cont_i_cur_if_p(it1) && cont_i_cur_if_p(it2))
// {
// if (cont_i_cur_if(it1)->ident != cont_i_cur_if(it2)->ident)
// return depth;
// depth++;
// }
// }
cont_i_next(it1);
cont_i_next(it2);
}
return depth;
}
//from dep_analyzer.cpp
extern bool isRemovableDependence(const depNode *toCheck, const std::set<std::string> &privVars);
static int isDependent(PT_ACCESSARRAY el1, PT_ACCESSARRAY el2, const Set *induc, int &countOfNodes)
{
///////////////////////////////////////////////////////////////////////////
// deallocation Set
///////////////////////////////////////////////////////////////////////////
// in that set we store everything that must be deallocated at some
// point in the program
Set *setForDealocatingMemory = NULL;
int i, j;
PT_INDUCVAR ind;
SgExpression *ex2;
SgSymbol *tsymb[MAXNESTEDLOOP];
a_access access1, access2, access3;
ddnature oitype, iotype;
uint nest1, nest2, nest3, bnest;
context_iterator firstcontiter, firstcontiter1;
var_id inducom1[MAXNESTEDLOOP];
var_id inducom2[MAXNESTEDLOOP];
var_id ptvar;
int inif;
if (!el1 || !el2)
return -2;
// do not accept scalar variables here
if (el1->scalar || el2->scalar)
{
// not treated here but in depGraph.C
// if (!currentDepGraph)
// {
// Message("No current Dep Graph",0);
// return -2;
// }
// currentDepGraph->addAnEdge(el1->stmt,el2->stmt,
// el1->var,el2->var,
// SCALARDEP,0,NULL,NULL,0);
return 0;
}
// create the set for deallocation of memory;
setForDealocatingMemory = new Set(dummyEqual, NULL, dummyPrint);
#ifdef __SPF
addToCollection(__LINE__, __FILE__, setForDealocatingMemory, 1);
#endif
setForDealocatingMemory->setDealllocateElem();
// we have to prepare the data structure for the omega test
SetSTuff(); // initialize the omega test
// format the variable for the omega test;
for (j = 0; j < induc->size(); j++)
{
ind = (PT_INDUCVAR)induc->getElement(j);
ptvar = (omegaVar*)malloc(sizeof(omegaVar));
#ifdef __SPF
addToCollection(__LINE__, __FILE__, ptvar, 0);
#endif
setForDealocatingMemory->addElement((void *)ptvar);
inducom1[j] = ptvar;
inducom2[j] = ptvar;
// ptvar->loop = ind->loopnum;
ptvar->loop = ind->level; // seems to be more correct...
if (ind->constante)
{
ptvar->indexp = FALSE; // constante variable;
ptvar->constp = TRUE;
}
else
{
ptvar->indexp = TRUE; // index variable;
ptvar->constp = FALSE;
}
ptvar->tag = UNTAGGED;
ptvar->name = ind->var->symbol()->identifier();
}
inducom1[induc->size()] = NULL;
inducom2[induc->size()] = NULL;
for (i = 0; i < induc->size(); i++)
{
ind = (PT_INDUCVAR)induc->getElement(i);
if (ex2 = ind->var)
{
tsymb[i] = ex2->symbol();
}
}
access1 = (omegaAccess*)malloc(sizeof(omegaAccess));
setForDealocatingMemory->addElement((void *)access1);
access2 = (omegaAccess*)malloc(sizeof(omegaAccess));
setForDealocatingMemory->addElement((void *)access2);
#ifdef __SPF
addToCollection(__LINE__, __FILE__, access1, 0);
addToCollection(__LINE__, __FILE__, access2, 0);
#endif
firstcontiter = fillOmegaLoop(el1, induc, inducom1, tsymb, &inif, setForDealocatingMemory);
firstcontiter1 = firstcontiter;
nest1 = fillOmegaAccess(el1, access1, induc, inducom1, firstcontiter, "Access1", inif, setForDealocatingMemory);
firstcontiter = fillOmegaLoop(el2, induc, inducom2, tsymb, &inif, setForDealocatingMemory);
nest2 = fillOmegaAccess(el2, access2, induc, inducom2, firstcontiter, "Access2", inif, setForDealocatingMemory);
access1->lexord = 2;
access2->lexord = 1;
if (!lexOrder(el1, el2))
{
access1->lexord = 1;
access2->lexord = 2;
}
if (!el1->rw)
{ // swapp the reference;
int ts;
access3 = access1;
access1 = access2;
access2 = access3;
nest3 = nest1;
nest1 = nest2;
nest2 = nest3;
}
bnest = commonDepth(firstcontiter1, firstcontiter); // should be the common nests see ddnests;
access1->shareddepth = bnest;
access2->shareddepth = bnest;
if (el1->rw && el2->rw)
{
oitype = ddoutput;
iotype = ddoutput;
}
else
{
oitype = ddflow;
iotype = ddanti;
}
// printf("Testing dependence Using Omega Test between ");
// el1->var->unparsestdout();
// printf(" line %d and ", el1->stmt->lineNumber());
// el2->var->unparsestdout();
// printf(" line %d \n", el2->stmt->lineNumber());
currentStmtIn = el1->stmt;
currentStmtOut = el2->stmt;
currentVarIn = el1->var;
currentVarOut = el2->var;
dd_omega_test(access1, access2, oitype, iotype, nest1, nest2, bnest);
//check if dependensices is known;
int result = 0;
const std::vector<depNode*> &nodes = currentDepGraph->getNodes();
for (int z = countOfNodes; z < nodes.size(); ++z)
{
if (isRemovableDependence(nodes[z], currentDepGraph->privVars) == false)
{
result = 5;
break;
}
}
countOfNodes = nodes.size();
// should delete all allocated space;
#ifdef __SPF
removeFromCollection(setForDealocatingMemory);
#endif
delete setForDealocatingMemory;
return result;
}
//
// indicates if a statement is before in a loop body stmt1 is assumed to be the first one
//
int beforeInText(SgStatement *func, SgStatement *stmt1, SgStatement *stmt2)
{
SgStatement *temp, *last;
if (!func || !stmt1 || !stmt2)
return -1;
last = func->lastNodeOfStmt();
for (temp = func; temp && (temp != last); temp = temp->lexNext())
{
if (temp == stmt1)
return 1;
if (temp == stmt2)
return 0;
}
Message("None of the statement where found in beforeInText", 0);
return -1;
}
Set *computeLoopDependencies(SgStatement *func, Set *inset, SgSymbol **tsymb, Set *induc)
{
PT_INDUCVAR ind;
PT_ACCESSARRAY el1, el2;
int i, j, k;
int found;
int loopnum;
PT_DEPENDENCE el;
Set *depset;
int datadep;
int typedep;
if (!inset || !tsymb || !induc)
return NULL;
// not needed anymore
// depset = new Set(dependenceEqual, NULL, dependencePrint);
WarningOutForNegativeStep = 0;
int countOfNodes = currentDepGraph->getNodes().size();
for (i = 0; i < inset->size(); i++)
{
createNeededException();
el1 = (PT_ACCESSARRAY)inset->getElement(i);
if (el1)
{
for (j = i; j < inset->size(); j++)
{
datadep = 0;
el2 = (PT_ACCESSARRAY)inset->getElement(j);
if (el2)
{
if (el1->var && el2->var &&
(el1->rw || el2->rw) &&
(el1->var->symbol() == el2->var->symbol()))
{
int res = isDependent(el1, el2, induc, countOfNodes);
if (res == 5)
{
printf("Sapfor: return from computeLoopDependencies with 5 status with %d graph\n", countOfNodes);
return NULL;
}
}
}
}
}
}
if (countOfNodes > 1000)
printf("Sapfor: return from computeLoopDependencies with %d graph\n", countOfNodes);
return NULL;
}

View File

@@ -0,0 +1,19 @@
#pragma once
//
// for computing loop dependencies
//
struct datadep
{
SgStatement *loop;
int loopnum;
SgStatement *stmtin;
SgStatement *stmtout;
SgExpression *varin; // this is var;
SgExpression *varout; // this is var;
int typedep;
int kinddep;
int distance[MAXNESTEDLOOP];
};
typedef struct datadep *PT_DEPENDENCE;

View File

@@ -0,0 +1,280 @@
#include <stdio.h>
#include <stdlib.h>
#include "sage++user.h"
#include "definesValues.h"
#include "set.h"
#ifdef __SPF
extern "C" void addToCollection(const int line, const char *file, void *pointer, int type);
extern "C" void removeFromCollection(void *pointer);
#endif
//
// Control FLOW part of declaration
//
extern void controlFlow(SgStatement *stmt, SgStatement *func,
SgStatement **pred, SgStatement **suc,
int *predin, int *sucint);
Set *genSet[MAXNODE];
Set *killSet[MAXNODE];
Set *inSet[MAXNODE];
Set *outSet[MAXNODE];
//
// Main function for data flow analysis, take some functions as a parameter
//
void iterativeForwardFlowAnalysis(SgFile *file,
SgStatement *func,
Set *(*giveGenSet)(SgStatement *func, SgStatement *stmt),
Set *(*giveKillSet)(SgStatement *func, SgStatement *stmt),
int(*feq)(void *e1, void *e2),
void *(*fcomb)(void *e1, void *e2),
void(*fp)(void *e1))
{
SgStatement *last, *first, *lastfunc, *temp;
SgStatement *pred[MAXP], *suc[MAXP];
int nbpred, nbsuc;
int size, i, j;
Set *tps, *oldout, *tpt, *pt1, *pt2, *comb;
int change, step;
int cid;
if (!file || !func || !giveGenSet || !giveKillSet)
{
Message("iterativeForwardFlowAnalysis: Some Argument are NULL", 0);
return;
}
lastfunc = func->lastNodeOfStmt();
// should use the max id instead;
for (i = 0; i < MAXNODE; i++)
{
genSet[i] = NULL;
killSet[i] = NULL;
outSet[i] = NULL;
inSet[i] = NULL;
}
// initialize the gen and kill set;
for (temp = func; temp; temp = temp->lexNext())
{
if (temp->id() > MAXNODE)
{
Message("Too many nodes in program: Fatal", 0);
exit(1);
}
genSet[temp->id()] = (*giveGenSet)(func, temp);
killSet[temp->id()] = (*giveKillSet)(func, temp);
if (temp == lastfunc)
break;
}
// initialize the out set;
for (temp = func; temp; temp = temp->lexNext())
{
if (genSet[temp->id()])
{
pt2 = genSet[temp->id()];
outSet[temp->id()] = pt2->copy();
}
else
outSet[temp->id()] = NULL;
inSet[temp->id()] = NULL;
if (temp == lastfunc)
break;
}
change = 1;
step = 0;
while (change)
{
step++;
change = 0;
for (temp = func; temp; temp = temp->lexNext())
{
cid = temp->id();
controlFlow(temp, func, pred, suc, &nbpred, &nbsuc);
if (inSet[cid])
{
#ifdef __SPF
removeFromCollection(inSet[cid]);
#endif
delete inSet[cid];
}
tps = new Set(feq, fcomb, fp);
#ifdef __SPF
addToCollection(__LINE__, __FILE__, tps, 1);
#endif
for (i = 0; i < nbpred; i++)
{
tps->unionSet(outSet[pred[i]->id()]);
}
inSet[cid] = tps;
oldout = outSet[cid];
outSet[cid] = new Set(feq, fcomb, fp);
tpt = new Set(feq, fcomb, fp);
#ifdef __SPF
addToCollection(__LINE__, __FILE__, outSet[cid], 1);
addToCollection(__LINE__, __FILE__, tpt, 1);
#endif
tpt->diffSet(inSet[cid], killSet[cid]);
outSet[cid]->unionSet(genSet[cid]);
outSet[cid]->unionSet(tpt);
pt1 = outSet[cid];
outSet[cid] = pt1->compact();
#ifdef __SPF
removeFromCollection(pt1);
#endif
delete pt1;
if (!oldout && outSet[cid])
change = 1;
else
if (!oldout->equalSet(outSet[cid]))
change = 1;
if (oldout)
{
#ifdef __SPF
removeFromCollection(oldout);
#endif
delete oldout;
}
if (tpt)
{
#ifdef __SPF
removeFromCollection(tpt);
#endif
delete tpt;
}
if (temp == lastfunc)
break;
}
if (step > MAXITDATAFLOW)
{
Message("data flow analysis not converging", 0);
return;
}
printf("Data flow analysis at step %d\n", step);
}
}
//
// Iterative Algorithme for General Frameworks page 690 Aho Ullman
// out is initialise to transfertSet(NULL). in is initialized to NULL (this is T).
// combineSet() is the meet operator (take as input the union or output...)
//
void generalIterativeFlowAnalysis(SgFile *file,
SgStatement *func,
Set *(*transfertSet)(SgStatement *func, SgStatement *stmt, Set *setin),
int(*feq)(void *e1, void *e2),
void* (*fcomb)(void *e1, void *e2),
void(*fp)(void *e1))
{
SgStatement *last, *first, *lastfunc, *temp;
SgStatement *pred[MAXP], *suc[MAXP];
int nbpred, nbsuc;
int size, i, j;
Set *tps, *oldout, *tpt, *pt1, *pt2, *comb;
int change, step;
int cid;
if (!file || !func || !transfertSet)
{
Message("generalIterativeFlowAnalysis: Some Arguments are NULL", 0);
return;
}
lastfunc = func->lastNodeOfStmt();
// should use the max id instead;
for (i = 0; i < MAXNODE; i++)
{
genSet[i] = NULL;
killSet[i] = NULL;
outSet[i] = NULL;
inSet[i] = NULL;
}
// initialize the out Set
for (temp = func; temp; temp = temp->lexNext())
{
if (temp->id() > MAXNODE)
{
Message("Too many nodes in program: Fatal", 0);
exit(1);
}
outSet[temp->id()] = (*transfertSet)(func, temp, NULL);
if (temp == lastfunc)
break;
}
change = 1;
step = 0;
while (change)
{
step++;
change = 0;
for (temp = func; temp; temp = temp->lexNext())
{
cid = temp->id();
controlFlow(temp, func, pred, suc, &nbpred, &nbsuc);
if (inSet[cid])
{
#ifdef __SPF
removeFromCollection(inSet[cid]);
#endif
delete inSet[cid];
}
tps = new Set(feq, fcomb, fp);
#ifdef __SPF
addToCollection(__LINE__, __FILE__, tps, 1);
#endif
for (i = 0; i < nbpred; i++)
{
tps->unionSet(outSet[pred[i]->id()]);
}
tpt = tps;
tps = tps->combineSet();
inSet[cid] = tps;
if (tpt)
{
#ifdef __SPF
removeFromCollection(tpt);
#endif
delete tpt;
}
oldout = outSet[cid];
outSet[cid] = (*transfertSet)(func, temp, inSet[cid]);
if (!oldout && outSet[cid])
{
change = 1;
// printf ("old out is NULL (line %d)\n", temp->lineNumber());
}
else
if (!oldout->equalSet(outSet[cid]))
{
// printf ("-------debug ouput (line %d)-----------: \n", temp->lineNumber());
// printf ("oldout: \n");
// oldout->printSet();
// printf ("out: \n");
// if (outSet[cid])
// outSet[cid]->printSet();
change = 1;
}
if (oldout)
{
#ifdef __SPF
removeFromCollection(oldout);
#endif
delete oldout;
}
if (temp == lastfunc)
break;
}
if (step > MAXITDATAFLOW)
{
Message("data flow analysis not converging", 0);
return;
}
printf("Data flow analysis at step %d\n", step);
}
}

View File

@@ -0,0 +1,18 @@
#pragma once
struct inducvar
{
int constante; // indicate if constante or induction
SgStatement *stmt;
SgExpression *var; // this is a var ref;
SgExpression *stride;
SgExpression *lbound;
SgExpression *ubound;
Set *reachdef;
int level;
int loopnum;
int include;
};
typedef struct inducvar *PT_INDUCVAR;

View File

@@ -0,0 +1,92 @@
//////////////////////////////////////////////////////////////////////////
// To deals with the intrinsics function call
//////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <string.h>
#include "sage++user.h"
#include "definesValues.h"
#include "intrinsic.h"
#include <string>
#include <set>
extern std::set<std::string> intrinsicF;
extern void initIntrinsicFunctionNames();
// return TRUE if OK and FALSE otherwise
int isSymbolIntrinsic(SgSymbol *symb)
{
initIntrinsicFunctionNames();
SgFunctionSymb *fs;
char *ident;
if (fs = isSgFunctionSymb(symb))
{
ident = fs->identifier();
if (!ident)
return FALSE;
if (intrinsicF.find(ident) == intrinsicF.end())
return FALSE;
else
return TRUE;
}
return FALSE;
}
int isExprCallToFuncNotIntrinsic(SgExpression *exp)
{
SgFunctionCallExp *fc;
if (!exp)
return FALSE;
if (fc = isSgFunctionCallExp(exp))
{
if (!isSymbolIntrinsic(fc->funName()))
return TRUE;
}
if (isExprCallToFuncNotIntrinsic(exp->lhs()))
return TRUE;
if (isExprCallToFuncNotIntrinsic(exp->rhs()))
return TRUE;
return FALSE;
}
int isStmtCallToFuncNotIntrinsic(SgStatement *stmt)
{
int i;
SgStatement *child;
if (!stmt)
return FALSE;
if (isExprCallToFuncNotIntrinsic(stmt->expr(0)))
return TRUE;
if (isExprCallToFuncNotIntrinsic(stmt->expr(1)))
return TRUE;
if (isExprCallToFuncNotIntrinsic(stmt->expr(2)))
return TRUE;
i = 1;
child = stmt->childList1(0);
while (child)
{
if (isStmtCallToFuncNotIntrinsic(child))
return TRUE;
child = stmt->childList1(i);
i++;
}
i = 1;
child = stmt->childList2(0);
while (child)
{
if (isStmtCallToFuncNotIntrinsic(child))
return TRUE;
child = stmt->childList2(i);
i++;
}
return FALSE;
}

View File

@@ -0,0 +1,26 @@
//////////////////////////////////////////////////////////////////////////
//
// To deals with the intrisics function call
// Declare the sets of function considered as intrinsic
// in fortran 77
// indicate also if side effect
//
//////////////////////////////////////////////////////////////////////////
// see definesValues.h files

View File

@@ -0,0 +1,169 @@
#include <stdio.h>
#include "sage++user.h"
#include "definesValues.h"
#include "set.h"
#include "definitionSet.h"
#ifdef __SPF
extern "C" void addToCollection(const int line, const char *file, void *pointer, int type);
#endif
extern Set *genSet[MAXNODE];
extern Set *killSet[MAXNODE];
extern Set *inSet[MAXNODE];
extern Set *outSet[MAXNODE];
//
// used in compute loop invariant
//
int stmtEqual(void *e1, void *e2)
{
SgStatement *ex1, *ex2;
if (!e1 && !e2)
return 1;
if (!e1 || !e2)
return 0;
ex1 = (SgStatement *)e1;
ex2 = (SgStatement *)e2;
if (ex1 != ex2)
return 0;
else
return 1;
}
void stmtPrint(void *e1)
{
SgStatement *ex1;
if (!e1)
return;
ex1 = (SgStatement *)e1;
printf("statement at line %d:\n", ex1->lineNumber());
ex1->unparsestdout();
}
void exprPrint(void *e1)
{
SgExpression *ex1;
if (!e1)
return;
ex1 = (SgExpression *)e1;
ex1->unparsestdout();
printf("\n");
}
//
//function to Compute Loop Invariant Computation
// assume Reaching definition has been done
// and also the used and defined for each statment has also been computed
//
Set *loopInvariantStmt(SgStatement *func, SgStatement *stmt)
{
SgStatement *last, *first, *defreach, *temp, *cp;
SgForStmt *loop;
Set *invariant, *reachdef;
SgExpression *use, *pt, *usevar, *expr;
int change, id, inloop, inv, step;
PT_ELSET el;
int i;
if (!stmt || !func)
return NULL;
if (!(loop = isSgForStmt(stmt)))
return NULL;
last = stmt->lastNodeOfStmt();
invariant = new Set(stmtEqual, NULL, stmtPrint);
#ifdef __SPF
addToCollection(__LINE__, __FILE__, invariant, 1);
#endif
change = 1;
step = 0;
while (change)
{
change = 0;
step++;
for (temp = stmt->lexNext(); temp; temp = temp->lexNext())
{
// only if assgn_stat...;
if (!isSgAssignStmt(temp))
{
if (temp == last)
break;
else
continue;
}
id = temp->id();
use = (SgExpression *)temp->attributeValue(0, USEDLIST_ATTRIBUTE);
//Used[id];
reachdef = inSet[id];
// look at all the use of ;
inv = 1;
for (pt = use; pt && (inv == 1); pt = pt->rhs())
{
usevar = pt->lhs();
if (usevar)
{// look at if the definition is the reaching set;
for (i = 0; i < reachdef->size(); i++)
{
el = (PT_ELSET)reachdef->getElement(i);
if (el)
{
defreach = el->stmt;
expr = el->expr;
if (expr)
{
if (expr->symbol() && usevar->symbol() &&
(expr->symbol() == usevar->symbol()))
{
// we have a definition of the variable;
if (!invariant->isInSet((void *)defreach))
{
// look at if in the loop body;
inloop = 0;
cp = defreach;
while (cp)
{
if (cp == stmt)
{
inloop = 1;
break;
}
if ((cp->variant() == GLOBAL) || (cp == func))
{
inloop = 0;
break;
}
cp = cp->controlParent();
}
if (inloop)
{
inv = 0;
}
}
}
}
}
}
}
}
if (inv && !invariant->isInSet((void *)temp) && (step < MAXITDATAFLOW))
{
invariant->addElement((void *)temp);
change = 1;
}
if (step >= MAXITDATAFLOW)
Message("invariant computation is Looping", 0);
if (temp == last)
break;
}
}
return invariant;
}

View File

@@ -0,0 +1,412 @@
#include <stdio.h>
#include "sage++user.h"
#include "definesValues.h"
#include "set.h"
#include "definitionSet.h"
#include "inducVar.h"
#include "depGraph.h"
#ifdef __SPF
extern "C" void addToCollection(const int line, const char *file, void *pointer, int type);
extern "C" void removeFromCollection(void *pointer);
#endif
extern int countPerfectLoopNest(SgStatement*);
///////////////////////////////////////////////////////////////////////////////////////
// some global declarations
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
// Loop Transformation Sets. (the validity checkings for the transformations
// are in the depGraph method.
///////////////////////////////////////////////////////////////////////////////////////
//
// b is the outer loopm
// permut specify the loop permutations
// the n outermost loops must be perfectly nested
// permut start at 0; Example
// do i = 0
// do j = 8
// do k = 1
// ....
// permut = [2,1,0]
// gives
// do k = 1
// do j = 8
// do i = 0
// ....
//
int loopInterchange(SgStatement *b, int *permut, int n)
{
SgSymbol *tab_symb[MAXNESTEDLOOP];
SgExpression *tab_bf[MAXNESTEDLOOP];
SgExpression * tab_bi[MAXNESTEDLOOP];
SgExpression * tab_step[MAXNESTEDLOOP];
SgForStmt *loop, *tloop;
int i;
if (!(loop = isSgForStmt(b)))
return 0;
if (n > countPerfectLoopNest(loop))
{
Message("Interchange loop error, loops are not perfectly nested", loop->lineNumber());
return 0;
}
tloop = loop;
for (i = 0; (i < n); i++)
{
tab_symb[i] = tloop->symbol();
tab_bf[i] = tloop->start();
tab_bi[i] = tloop->end();
tab_step[i] = tloop->step();
tloop = isSgForStmt(tloop->getNextLoop());
}
tloop = loop;
for (i = 0; (i < n); i++)
{
if (tab_symb[permut[i]])
tloop->setSymbol(*tab_symb[permut[i]]);
if (tab_bf[permut[i]])
tloop->setStart(*tab_bf[permut[i]]);
if (tab_bi[permut[i]])
tloop->setEnd(*tab_bi[permut[i]]);
if (tab_step[permut[i]])
tloop->setStep(*tab_step[permut[i]]);
tloop = isSgForStmt(tloop->getNextLoop());
}
return 1;
}
//
// Tile a loop.
// assumed to be perfectly nested.
// size is NO_STEP we do not want it to be tiled
//
int tileLoops(SgStatement *func, SgStatement *b, int *size, int nb)
{
int i, j;
SgSymbol *tab_symb[MAXNESTEDLOOP];
SgStatement *body, *ptstmt;
SgForStmt *internal_loop, *temp, *last_loop;
SgForStmt *loop, *temloo;
SgExpression *borne_inf[MAXNESTEDLOOP];
SgExpression *borne_sup[MAXNESTEDLOOP];
SgExpression *step[MAXNESTEDLOOP];
SgType *typint;
SgSymbol *min_fonc;
char strfoname[256];
if (!(loop = isSgForStmt(b)) || !func)
return 0;
if (nb > countPerfectLoopNest(loop))
{
Message("loop Tilling error, loops are not perfectly nested", loop->lineNumber());
return 0;
}
if (nb == 0) return 0;
if (nb >= MAXNESTEDLOOP)
{
Message("Too many nested level", b->lineNumber());
return 0;
}
for (i = 0; i < MAXNESTEDLOOP; i++)
{
tab_symb[i] = NULL;
borne_inf[i] = NULL;
borne_sup[i] = NULL;
step[i] = NULL;
}
last_loop = loop;
for (i = 0; i < nb; i++)
{
if (size[i] != NO_STEP)
{
if (last_loop->step())
{
Message("Cannot tile loop, there is already a step", last_loop->lineNumber());
return 0;
}
}
last_loop = isSgForStmt(last_loop->getNextLoop());
}
// Get integer type;
typint = SgTypeInt();
// get the indexes of the loops;
temloo = loop;
for (i = 0; i < nb; i++)
{
tab_symb[i] = temloo->symbol();
internal_loop = temloo;
temloo = isSgForStmt(temloo->getNextLoop());
}
if (!internal_loop)
{
Message("Internal loop not found", loop->lineNumber());
return 0;
}
// generate the new symbol and declare them
for (i = 0; i < nb; i++)
{
sprintf(strfoname, "iT%d_%d", loop->id(), i);
tab_symb[i + nb] = new SgVariableSymb(strfoname);
#ifdef __SPF
addToCollection(__LINE__, __FILE__, tab_symb[i + nb], 1);
#endif
tab_symb[i + nb]->declareTheSymbol(*func);
}
last_loop = loop;
for (i = 0; i < nb; i++)
{
if (size[i] != NO_STEP)
{
SgValueExp *tmp = (new SgValueExp(size[i] + 1));
last_loop->setStep(*tmp);
#ifdef __SPF
addToCollection(__LINE__, __FILE__, tmp, 1);
#endif
}
last_loop = isSgForStmt(last_loop->getNextLoop());
}
// create a min function;
min_fonc = new SgSymbol(FUNCTION_NAME, "min", *typint, *(loop->controlParent()));
#ifdef __SPF
addToCollection(__LINE__, __FILE__, min_fonc, 1);
#endif
// creation of the bound expressions;
last_loop = loop;
for (i = 0; i < nb; i++)
{
if (size[i] != NO_STEP)
{
SgFunctionCallExp *cexp;
borne_inf[i + nb] = new SgValueExp(0);
cexp = new SgFunctionCallExp(*min_fonc);
borne_sup[i + nb] = cexp;
SgValueExp *tmp = (new SgValueExp(size[i]));
SgVarRefExp *tmp1 = (new SgVarRefExp(*tab_symb[i]));
cexp->addArg(((last_loop->end())->copy()) - *tmp1);
cexp->addArg(*tmp);
#ifdef __SPF
addToCollection(__LINE__, __FILE__, borne_inf[i + nb], 1);
addToCollection(__LINE__, __FILE__, cexp, 1);
addToCollection(__LINE__, __FILE__, tmp, 1);
addToCollection(__LINE__, __FILE__, tmp1, 1);
#endif
}
else
{
borne_inf[i + nb] = new SgValueExp(1);
borne_sup[i + nb] = &((last_loop->end())->copy());
#ifdef __SPF
addToCollection(__LINE__, __FILE__, borne_inf[i + nb], 1);
#endif
}
step[i + nb] = NULL;
last_loop = isSgForStmt(last_loop->getNextLoop());
}
// remove the loop body;
// update the steps;
body = internal_loop->extractStmtBody();
// upper bound for NO_STEP loops
last_loop = loop;
for (i = 0; i < nb; i++)
{
if (size[i] == NO_STEP)
{
SgValueExp *tmp = (new SgValueExp(1));
last_loop->setEnd(*tmp);
#ifdef __SPF
addToCollection(__LINE__, __FILE__, tmp, 1);
#endif
}
last_loop = isSgForStmt(last_loop->getNextLoop());
}
// create the new loop;
last_loop = internal_loop;
for (i = 0; i < nb; i++)
{
loop = new SgForStmt(tab_symb[i + nb], borne_inf[i + nb], borne_sup[i + nb], step[i + nb], NULL);
#ifdef __SPF
addToCollection(__LINE__, __FILE__, loop, 1);
#endif
last_loop->insertStmtAfter(*loop, *last_loop);
last_loop = loop;
}
// update the loop body;
if (!body || !last_loop)
{
Message("The loop may not have a body or internal error", 0);
return 0;
}
last_loop->insertStmtAfter(*body, *last_loop);
for (j = 0; j < last_loop->numberOfChildrenList1(); j++)
{
ptstmt = last_loop->childList1(j);
if (ptstmt)
{
for (i = 0; i < nb; i++)
{
if (size[i] != NO_STEP)
{
SgVarRefExp *tmp = (new SgVarRefExp(*tab_symb[i]));
SgVarRefExp *tmp1 = (new SgVarRefExp(*tab_symb[i + nb]));
ptstmt->replaceSymbByExp(*tab_symb[i], *tmp + *tmp1);
#ifdef __SPF
addToCollection(__LINE__, __FILE__, tmp, 1);
addToCollection(__LINE__, __FILE__, tmp1, 1);
#endif
}
else
{
SgVarRefExp *tmp = (new SgVarRefExp(*tab_symb[i]));
ptstmt->replaceSymbByExp(*tab_symb[i], *tmp);
#ifdef __SPF
addToCollection(__LINE__, __FILE__, tmp, 1);
#endif
}
}
}
}
return 1;
}
//
// distribute the loops according to the
// table of SCC.
// for instance consider the following loop
//
// do i= 1,100
//[1] x = 2
//[2] do j= 1,100
// D(j+i) = A(i,j)
// D(j+i) = A(i,j)
// enddo
//[3] x = 2
// enddo
// and the following content of the
// [[1,3],2] scc table index
//
int distributeLoopSCC(SgStatement *b, int *sccTable, int leadingdim, int numSCC)
{
int i, j;
SgStatement *last, **sccloop, **sccextracted, *ptstm;
SgStatement *previous, *cp, *copl;
SgForStmt *loop;
int nbstat;
if (!(loop = isSgForStmt(b)) || !sccTable)
return 0;
nbstat = loop->numberOfChildrenList1() - 1; // does not remove the controlend;
sccloop = new SgStatement *[numSCC];
sccextracted = new SgStatement *[nbstat];
#ifdef __SPF
addToCollection(__LINE__, __FILE__, sccloop, 2);
addToCollection(__LINE__, __FILE__, sccextracted, 2);
#endif
for (j = 0; j < nbstat; j++)
{
ptstm = loop->childList1(j);
sccextracted[j] = ptstm;
}
for (j = 0; j < nbstat; j++)
{
if (sccextracted[j])
sccextracted[j]->extractStmt();
}
// now creates the loop;
previous = loop->nodeBefore();
cp = loop->controlParent();
loop->extractStmt();
copl = &(loop->copy());
previous->insertStmtAfter(*loop, *cp);
sccloop[0] = loop;
last = loop->lastNodeOfStmt();
// need to extractloop before doing the copy;
for (j = 1; j < numSCC; j++)
{
if (j == numSCC - 1)
sccloop[j] = copl;
else
sccloop[j] = &(copl->copy());
last->insertStmtAfter(*(sccloop[j]), *cp);
last = sccloop[j]->lastNodeOfStmt();
}
for (j = 0; j < numSCC; j++)
{
for (i = leadingdim - 1; i >= 0; i--)
{
// insert in the right body the statement;
// go revserse order; simpler;
if (sccTable[j*leadingdim + i])
if (sccextracted[sccTable[j*leadingdim + i] - 1])
sccloop[j]->insertStmtAfter(*sccextracted[sccTable[j*leadingdim + i] - 1], *sccloop[j]);
}
}
#ifdef __SPF
removeFromCollection(sccloop);
removeFromCollection(sccextracted);
#endif
delete []sccloop;
delete []sccextracted;
return 1;
}
//
// Takes two loops and fusion the bodies
//
int loopFusion(SgStatement *loop1, SgStatement *loop2)
{
SgForStmt *doloop1;
SgForStmt *doloop2;
SgStatement *body, *last;
if (!(doloop1 = isSgForStmt(loop1)))
return 0;
if (!(doloop2 = isSgForStmt(loop2)))
return 0;
if (!doloop1->symbol())
return 0;
SgVarRefExp *tmp = (new SgVarRefExp(*doloop1->symbol()));
doloop2->replaceSymbByExp(*doloop2->symbol(), *tmp);
#ifdef __SPF
addToCollection(__LINE__, __FILE__, tmp, 1);
#endif
body = doloop2->extractStmtBody();
if (!body)
return 0;
last = doloop1->lastNodeOfStmt();
if (!last)
return 0;
last = last->nodeBefore();
if (!last)
return 0;
last->insertStmtAfter(*body, *doloop1);
doloop2->extractStmt();
return 1;
}

View File

@@ -0,0 +1,8 @@
////////////////////////////////////////////////////////////////////
// code for reduction recogniction
////////////////////////////////////////////////////////////////////
// see definesValues.h files

View File

@@ -0,0 +1,425 @@
#include <stdio.h>
#include "sage++user.h"
#include "definesValues.h"
#include "set.h"
#ifdef __SPF
extern "C" void addToCollection(const int line, const char *file, void *pointer, int type);
extern "C" void removeFromCollection(void *pointer);
#endif
Set::Set(int(*feq)(void *e1, void *e2),
void *(*fcomb)(void *e1, void *e2),
void(*fp)(void *e1))
{
data = NULL;
nbelement = 0;
nballocated = 0;
equal = feq;
combine = fcomb;
printEl = fp;
deallocelem = 0;
}
void Set::printSet()
{
int i;
if (!printEl)
{
Message("Function printEl not given", 0);
return;
}
if (!this->size())
printf("Empty set\n");
else
{
for (i = 0; i < this->size(); i++)
{
(*printEl)(getElement(i));
}
printf("\n");
}
}
void Set::interSet(Set *s1, Set *s2)
{
int i, j;
int trouve;
void *e1, *e2;
if (!equal)
return;
if (!s1 || !s2)
return;
if (!equal)
{
Message("Function Equal not given", 0);
return;
}
for (i = 0; i < s1->size(); i++)
{
e1 = s1->getElement(i);
if (e1)
{
trouve = 0;
for (j = 0; j < s2->size(); j++)
{
e2 = s2->getElement(j);
if ((*equal)(e1, e2))
{
trouve = 1;
break;
}
}
if (trouve)
this->addElement(e1);
}
}
}
void Set::unionSet(Set *s1)
{
int i, j;
int trouve;
void *e1, *e2;
int initsize;
int initsize2;
if (!s1)
{
return;
}
if (!equal)
{
Message("Function Equal not given", 0);
return;
}
initsize = s1->size();
initsize2 = this->size();
for (i = 0; i < initsize; i++)
{
e1 = s1->getElement(i);
if (e1)
{
trouve = 0;
for (j = 0; j < initsize2; j++)
{
e2 = this->getElement(j);
if ((*equal)(e1, e2))
{
trouve = 1;
break;
}
}
if (!trouve)
this->addElement(e1);
}
}
}
int Set::equalSet(Set *s1)
{
int i, j;
int trouve;
void *e1, *e2;
if (!s1)
return 0;
if (!equal)
{
Message("Function Equal not given", 0);
return 0;
}
if (this->size() != s1->size())
return 0;
for (i = 0; i < size(); i++)
{
e1 = getElement(i);
if (e1)
{
trouve = 0;
for (j = 0; j < s1->size(); j++)
{
e2 = s1->getElement(j);
if ((*equal)(e1, e2))
{
trouve = 1;
break;
}
}
if (!trouve)
return 0;
}
}
return 1;
}
int Set::isInSet(void *e1)
{
int i, j;
int trouve;
void *e2;
if (!e1)
return 0;
if (!equal)
{
Message("Function Equal not given", 0);
return 0;
}
for (i = 0; i < size(); i++)
{
e2 = getElement(i);
if (e1)
{
if ((*equal)(e1, e2))
{
return 1;
}
}
}
return 0;
}
void Set::diffSet(Set *s1, Set *s2)
{
int i, j;
int trouve;
void *e1, *e2;
int initsize;
if (!s2)
{
if (s1)
{
for (i = 1; i < s1->size(); i++)
{
e1 = s1->getElement(i);
this->addElement(e1);
}
}
return;
}
if (!equal)
{
Message("Function Equal not given", 0);
return;
}
initsize = s1->size();
for (i = 0; i < initsize; i++)
{
e1 = s1->getElement(i);
if (e1)
{
trouve = 0;
for (j = 1; j < s2->size(); j++)
{
e2 = s2->getElement(j);
if ((*equal)(e1, e2))
{
trouve = 1;
break;
}
}
if (!trouve)
this->addElement(e1);
}
}
}
void Set::Reallocatedata()
{
int i;
void **pt;
pt = new void *[nballocated + ALLOCATECHUNKSET];
#ifdef __SPF
addToCollection(__LINE__, __FILE__, pt, 2);
#endif
for (i = 0; i < nballocated + ALLOCATECHUNKSET; i++)
pt[i] = NULL;
for (i = 0; i < nballocated; i++)
pt[i] = data[i];
if (nballocated)
{
#ifdef __SPF
removeFromCollection(data);
#endif
delete[] data;
}
data = pt;
nballocated = nballocated + ALLOCATECHUNKSET;
}
void Set::addElement(void *el)
{
if (!el)
return;
// should check if already here
if (nbelement >= MAXELEMENT)
{
Message("Too many element in set", 0);
return;
}
while (nballocated <= (nbelement + 1))
{
Reallocatedata();
}
data[nbelement] = el;
nbelement++;
}
Set *Set::compact()
{
int i, k;
int trouve;
Set *newset;
if (!equal)
{
Message("Function Equal not given", 0);
return NULL;
}
// look at duplicate elements, and combine (to see later) if necessary
newset = new Set(equal, combine, printEl);
#ifdef __SPF
addToCollection(__LINE__, __FILE__, newset, 1);
#endif
for (i = 0; i < this->size(); i++)
{
trouve = 0;
for (k = 0; k < newset->size(); k++)
{
if ((*equal)(data[i], newset->data[k]))
{
trouve = 1;
break;
}
}
if (!trouve && data[i])
{
newset->addElement(data[i]);
}
}
return newset;
}
Set *Set::combineSet()
{
int i, j, inisize;
int change;
Set *newset, *temp;
void *pt;
int step = 0;
if (!combine)
{
Message("Function Combine not given", 0);
return NULL;
}
temp = this->copy();
change = 1;
while (change)
{
step++;
change = 0;
inisize = temp->size();
for (i = 0; i < inisize; i++)
{
for (j = i + 1; j < inisize; j++)
{
if (temp->getElement(i) && temp->getElement(j))
{
pt = combine(temp->getElement(i), temp->getElement(j));
if (pt)
{
temp->addElement(pt);
change = 1;
temp->rmElement(j);
temp->rmElement(i);
}
else
temp->addElement(pt);
}
}
}
if (step > MAXITDATAFLOW)
{
Message("Combine set is Looping", 0);
break;
}
}
///////////////////////////////
// PAS DE DESALLOCATION //
///////////////////////////////
// newset = temp;
// temp = temp->compact();
// if (newset)
// delete newset;
return temp;
}
Set *Set::copy()
{
int i, k;
Set *newset;
newset = new Set(equal, combine, printEl);
#ifdef __SPF
addToCollection(__LINE__, __FILE__, newset, 1);
#endif
for (i = 0; i < this->size(); i++)
{
if (data[i])
newset->addElement(data[i]);
}
return newset;
}
void *Set::getElement(int i) const
{
void *pt;
if ((i < 0) || (i >= nbelement))
return NULL;
pt = data[i];
return pt;
}
void *Set::rmElement(int i)
{
void *pt;
if ((i < 0) || (i >= nbelement))
return NULL;
pt = data[i];
data[i] = NULL;
return pt;
}
Set::~Set()
{
int i;
if (data)
{
if (deallocelem)
{
for (i = 0; i < nbelement; i++)
{
#ifdef __SPF
removeFromCollection(data[i]);
#endif
delete [](char*)data[i];
}
}
#ifdef __SPF
removeFromCollection(data);
#endif
delete []data;
}
}

View File

@@ -0,0 +1,47 @@
#pragma once
#include <stdio.h>
#include <sage++user.h>
//
// class Set used for data flow analysis...
//
class Set {
void **data;
int nbelement;
int nballocated;
int deallocelem;
SgStatement *stmt;
// used to compare two elements
int(*equal)(void *e1, void *e2);
void *(*combine)(void *e1, void *e2);
void(*printEl)(void *e1);
public:
Set(int(*feq)(void *e1, void *e2),
void *(*fcomb)(void *e1, void *e2),
void(*fp)(void *e1))
/* end of fp */;
~Set();
void interSet(Set *s1, Set *s2);
void unionSet(Set *s1);
Set *combineSet();
void diffSet(Set *s1, Set *s2);
int equalSet(Set *s1);
int isInSet(void *e1);
void setDealllocateElem() { deallocelem = 1; }
void resetDealllocateElem() { deallocelem = 0; }
void printSet();
int size() const { return nbelement; }
void addElement(void *el);
void *rmElement(int i);
void* getElement(int i) const;
Set *compact();
Set *copy();
void setStmt(SgStatement *s) { stmt = s; }
SgStatement* getStmt() const { return stmt; }
// add a chunk to the size ;
void Reallocatedata();
};