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