Files
SAPFOR/Sapfor/_src/SageAnalysisTool/OmegaForSage/ddomega.cpp
2025-03-12 12:37:19 +03:00

372 lines
12 KiB
C++

/* 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;
}
}