This commit is contained in:
2025-03-12 12:37:19 +03:00
parent 1c851baa7e
commit 6a4040be3e
426 changed files with 0 additions and 0 deletions

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