finalyze moving
This commit is contained in:
371
src/SageAnalysisTool/OmegaForSage/ddomega.cpp
Normal file
371
src/SageAnalysisTool/OmegaForSage/ddomega.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user