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,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);
}