2519 lines
61 KiB
C
2519 lines
61 KiB
C
|
|
/*********************************************************************/
|
||
|
|
/* pC++/Sage++ Copyright (C) 1993 */
|
||
|
|
/* Indiana University University of Oregon University of Rennes */
|
||
|
|
/*********************************************************************/
|
||
|
|
|
||
|
|
|
||
|
|
/* file: setutils.c */
|
||
|
|
#include <stdlib.h>
|
||
|
|
#include "db.h"
|
||
|
|
|
||
|
|
#ifdef __SPF
|
||
|
|
extern void addToCollection(const int line, const char *file, void *pointer, int type);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
extern PCF UnparseBfnd[];
|
||
|
|
extern PCF UnparseLlnd[];
|
||
|
|
|
||
|
|
PTR_SYMB induct_list[MAX_NEST_DEPTH];
|
||
|
|
int stride[MAX_NEST_DEPTH];
|
||
|
|
int is_forall[MAX_NEST_DEPTH];
|
||
|
|
|
||
|
|
/* variable default value structure. */
|
||
|
|
struct dflts {
|
||
|
|
PTR_SYMB name;
|
||
|
|
int value;
|
||
|
|
struct dflts *next;
|
||
|
|
};
|
||
|
|
|
||
|
|
typedef struct dflts *PTR_DFLT;
|
||
|
|
PTR_DFLT glob_dflts = NULL;
|
||
|
|
PTR_SETS free_sets = NULL;
|
||
|
|
PTR_REFL free_refl = NULL;
|
||
|
|
PTR_DEP free_dep = NULL;
|
||
|
|
/*char *malloc();*/
|
||
|
|
|
||
|
|
extern PTR_FILE cur_file;
|
||
|
|
extern int language;
|
||
|
|
|
||
|
|
/* Forward declarations */
|
||
|
|
int is_not_loc();
|
||
|
|
void disp_refl();
|
||
|
|
int make_range();
|
||
|
|
void disp_refl();
|
||
|
|
int make_induct_list();
|
||
|
|
|
||
|
|
extern int identical();
|
||
|
|
extern int integer_difference();
|
||
|
|
|
||
|
|
int get_dflt(df, s)
|
||
|
|
int *df;
|
||
|
|
PTR_SYMB s;
|
||
|
|
{
|
||
|
|
PTR_DFLT p;
|
||
|
|
int v;
|
||
|
|
|
||
|
|
p = glob_dflts;
|
||
|
|
*df = 1;
|
||
|
|
while (p != NULL) {
|
||
|
|
if (p->name == s)
|
||
|
|
return (p->value);
|
||
|
|
p = p->next;
|
||
|
|
}
|
||
|
|
p = (PTR_DFLT) malloc(sizeof(struct dflts));
|
||
|
|
#ifdef __SPF
|
||
|
|
addToCollection(__LINE__, __FILE__,p, 0);
|
||
|
|
#endif
|
||
|
|
p->next = glob_dflts;
|
||
|
|
glob_dflts = p;
|
||
|
|
p->name = s;
|
||
|
|
*df = 1;
|
||
|
|
v = 100;
|
||
|
|
p->value = v;
|
||
|
|
return (v);
|
||
|
|
}
|
||
|
|
|
||
|
|
PTR_SETS alloc_sets()
|
||
|
|
{
|
||
|
|
PTR_SETS s;
|
||
|
|
|
||
|
|
s = (PTR_SETS) malloc(sizeof(struct sets));
|
||
|
|
#ifdef __SPF
|
||
|
|
addToCollection(__LINE__, __FILE__,s, 0);
|
||
|
|
#endif
|
||
|
|
if (s == NULL)
|
||
|
|
fprintf(stderr, "! out of space for sets!!\n");
|
||
|
|
s->use = NULL;
|
||
|
|
s->gen = NULL;
|
||
|
|
s->in_use = NULL;
|
||
|
|
s->in_def = NULL;
|
||
|
|
s->out_use = NULL;
|
||
|
|
s->out_def = NULL;
|
||
|
|
s->arefl = NULL;
|
||
|
|
return (s);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*********************************************************************/
|
||
|
|
/* is_not_local() is used to find out if a reference is to a global */
|
||
|
|
/* variable. The way it works is that it traverses the biffnd tree */
|
||
|
|
/* up to the level of a procedure or function checking for local */
|
||
|
|
/* declarations. It understands the static scoping of C. */
|
||
|
|
/*********************************************************************/
|
||
|
|
static int search_for_dec(b, s)
|
||
|
|
PTR_BFND b;
|
||
|
|
PTR_SYMB s;
|
||
|
|
{
|
||
|
|
PTR_BFND par;
|
||
|
|
PTR_BLOB p;
|
||
|
|
PTR_LLND ll, def;
|
||
|
|
|
||
|
|
par = b->control_parent;
|
||
|
|
p = par->entry.Template.bl_ptr1;
|
||
|
|
while (p != NULL && p->ref != b) {
|
||
|
|
switch (p->ref->variant) {
|
||
|
|
case VAR_DECL:
|
||
|
|
case STRUCT_DECL:
|
||
|
|
ll = p->ref->entry.Template.ll_ptr1;
|
||
|
|
while (ll != NULL) {
|
||
|
|
def = ll->entry.Template.ll_ptr1;
|
||
|
|
while (def != NULL && def->variant == DEREF_OP)
|
||
|
|
def = def->entry.Template.ll_ptr1;
|
||
|
|
|
||
|
|
if ((def != NULL) &&
|
||
|
|
(def->variant == VAR_REF || def->variant == ARRAY_REF)
|
||
|
|
&& (s == def->entry.Template.symbol))
|
||
|
|
return (0);
|
||
|
|
ll = ll->entry.Template.ll_ptr2;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
p = p->next;
|
||
|
|
}
|
||
|
|
if (par->variant == GLOBAL || par->variant == FUNC_HEDR)
|
||
|
|
return (1);
|
||
|
|
else
|
||
|
|
return (search_for_dec(par, s));
|
||
|
|
}
|
||
|
|
|
||
|
|
int non_exec_statement(fBF)
|
||
|
|
PTR_BFND fBF;
|
||
|
|
{
|
||
|
|
switch (fBF->variant) {
|
||
|
|
case PROS_COMM:
|
||
|
|
case COMM_STAT:
|
||
|
|
case EXTERN_STAT:
|
||
|
|
case INTRIN_STAT:
|
||
|
|
case EQUI_STAT:
|
||
|
|
case STMTFN_STAT:
|
||
|
|
case ATTR_DECL:
|
||
|
|
case DIM_STAT:
|
||
|
|
case VAR_DECL:
|
||
|
|
case PARAM_DECL:
|
||
|
|
case IMPL_DECL:
|
||
|
|
case DATA_DECL:
|
||
|
|
case SAVE_DECL:
|
||
|
|
case BLOCK_DATA:
|
||
|
|
case COMMENT_STAT:
|
||
|
|
case ENTRY_STAT:
|
||
|
|
case CONTROL_END:
|
||
|
|
return (1);
|
||
|
|
default:
|
||
|
|
return (0);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
int search_for_common_decl(b, s)
|
||
|
|
PTR_BFND b;
|
||
|
|
PTR_SYMB s;
|
||
|
|
{
|
||
|
|
PTR_BFND par;
|
||
|
|
PTR_BLOB p;
|
||
|
|
PTR_LLND ll, def;
|
||
|
|
|
||
|
|
par = b;
|
||
|
|
while (par != NULL && par->variant != PROG_HEDR &&
|
||
|
|
par->variant != PROC_HEDR &&
|
||
|
|
par->variant != FUNC_HEDR)
|
||
|
|
par = par->control_parent;
|
||
|
|
if (par == NULL)
|
||
|
|
return (0);
|
||
|
|
|
||
|
|
p = par->entry.Template.bl_ptr1;
|
||
|
|
while (p != NULL && non_exec_statement(p->ref)) {
|
||
|
|
if (p->ref->variant == COMM_STAT) {
|
||
|
|
ll = p->ref->entry.Template.ll_ptr1; /* COMM_LIST */
|
||
|
|
ll = ll->entry.Template.ll_ptr1; /* EXPR_LIST */
|
||
|
|
while (ll != NULL) {
|
||
|
|
def = ll->entry.Template.ll_ptr1;
|
||
|
|
if ((def != NULL) &&
|
||
|
|
(def->variant == VAR_REF || def->variant == ARRAY_REF) &&
|
||
|
|
(s == def->entry.Template.symbol))
|
||
|
|
return (1);
|
||
|
|
ll = ll->entry.Template.ll_ptr2;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
p = p->next;
|
||
|
|
}
|
||
|
|
return (0);
|
||
|
|
}
|
||
|
|
|
||
|
|
int is_not_local(r)
|
||
|
|
struct ref *r;
|
||
|
|
{
|
||
|
|
PTR_BFND b;
|
||
|
|
PTR_LLND ll;
|
||
|
|
|
||
|
|
b = r->stmt;
|
||
|
|
ll = r->refer;
|
||
|
|
return (is_not_loc(b, ll));
|
||
|
|
}
|
||
|
|
|
||
|
|
int is_not_loc(b, ll)
|
||
|
|
PTR_BFND b;
|
||
|
|
PTR_LLND ll;
|
||
|
|
{
|
||
|
|
PTR_BFND curfun;
|
||
|
|
PTR_SYMB s, params;
|
||
|
|
PTR_LLND q;
|
||
|
|
int i;
|
||
|
|
|
||
|
|
curfun = b;
|
||
|
|
while (curfun != NULL && curfun->variant != GLOBAL &&
|
||
|
|
curfun->variant != FUNC_HEDR && curfun->variant != PROC_HEDR)
|
||
|
|
curfun = curfun->control_parent;
|
||
|
|
if (curfun->variant == FUNC_HEDR || curfun->variant == PROC_HEDR) {
|
||
|
|
params = curfun->entry.Template.symbol;
|
||
|
|
params = params->entry.proc_decl.in_list;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
params = NULL;
|
||
|
|
|
||
|
|
switch (ll->variant) {
|
||
|
|
case VAR_REF:
|
||
|
|
case ARRAY_REF:
|
||
|
|
s = ll->entry.Template.symbol;
|
||
|
|
break;
|
||
|
|
case POINTST_OP:
|
||
|
|
q = ll;
|
||
|
|
while (q != NULL && q->variant != VAR_REF)
|
||
|
|
q = q->entry.Template.ll_ptr1;
|
||
|
|
if (q == NULL)
|
||
|
|
return (1);
|
||
|
|
else {
|
||
|
|
s = q->entry.Template.symbol;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
s = NULL;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
while (s != NULL && params != NULL) {
|
||
|
|
if (params == s)
|
||
|
|
return (1);
|
||
|
|
params = params->entry.var_decl.next_in;
|
||
|
|
}
|
||
|
|
if (language == ForSrc) {
|
||
|
|
if (search_for_common_decl(b, s))
|
||
|
|
return (1);
|
||
|
|
if (s->attr == 1)
|
||
|
|
return (1); /* attribute is global */
|
||
|
|
return (0);
|
||
|
|
}
|
||
|
|
if (s != NULL) {
|
||
|
|
if ((i = search_for_dec(b, s)) == 0) {
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
}
|
||
|
|
return (i);
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
return (1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
PTR_REFL remove_locals_from_list(rl)
|
||
|
|
PTR_REFL rl;
|
||
|
|
{
|
||
|
|
PTR_REFL t, local, global;
|
||
|
|
|
||
|
|
local = NULL;
|
||
|
|
global = NULL;
|
||
|
|
while (rl != NULL) {
|
||
|
|
if (is_not_local(rl->node)) {
|
||
|
|
t = rl;
|
||
|
|
rl = rl->next;
|
||
|
|
t->next = global;
|
||
|
|
global = t;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
t = rl;
|
||
|
|
rl = rl->next;
|
||
|
|
t->next = local;
|
||
|
|
local = t;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
disp_refl(local);
|
||
|
|
return (global);
|
||
|
|
}
|
||
|
|
|
||
|
|
int subsumed(p, q)
|
||
|
|
PTR_LLND p,q;
|
||
|
|
{
|
||
|
|
PTR_LLND pind[10], qind[10], newpind[10], t;
|
||
|
|
int pdim, qdim, i, same, not_same[10], k,ns ;
|
||
|
|
|
||
|
|
if (p->variant != ARRAY_REF)
|
||
|
|
return (0);
|
||
|
|
if (q->variant != ARRAY_REF)
|
||
|
|
return (0);
|
||
|
|
if (p->entry.Template.symbol != q->entry.Template.symbol)
|
||
|
|
return (0);
|
||
|
|
|
||
|
|
pdim = 0;
|
||
|
|
t = p->entry.Template.ll_ptr1;
|
||
|
|
while(t && (t->variant == EXPR_LIST) && pdim < 10){
|
||
|
|
pind[pdim++] = t;
|
||
|
|
t = t->entry.Template.ll_ptr2;
|
||
|
|
/* printf("pind[%d] = %s",pdim-1,(UnparseLlnd[cur_file->lang])(pind[pdim-1]));*/
|
||
|
|
}
|
||
|
|
qdim = 0;
|
||
|
|
t = q->entry.Template.ll_ptr1;
|
||
|
|
while(t && (t->variant == EXPR_LIST) && qdim < 10){
|
||
|
|
qind[qdim++] = t;
|
||
|
|
t = t->entry.Template.ll_ptr2;
|
||
|
|
/* printf("qind[%d] = %s",qdim-1,(UnparseLlnd[cur_file->lang])(qind[qdim-1]));*/
|
||
|
|
}
|
||
|
|
|
||
|
|
if(pdim != qdim) return 0;
|
||
|
|
if(pdim == 0) return 1;
|
||
|
|
|
||
|
|
ns = 0;
|
||
|
|
for(i = 0; i < pdim; i++){
|
||
|
|
same = identical(pind[i]->entry.Template.ll_ptr1,
|
||
|
|
qind[i]->entry.Template.ll_ptr1);
|
||
|
|
if (same == 0){ ns = 1; not_same[i] = 1;}
|
||
|
|
else not_same[i] = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
if(ns == 0) return 1;
|
||
|
|
/* if(not_same > 1) return 0; */
|
||
|
|
|
||
|
|
for(k = 0; k < pdim; k++)
|
||
|
|
if(not_same[k] &&
|
||
|
|
(make_range(pind[k]->entry.Template.ll_ptr1,
|
||
|
|
qind[k]->entry.Template.ll_ptr1, &(newpind[k])) == 0)) return 0;
|
||
|
|
|
||
|
|
for(k = 0; k < pdim; k++)
|
||
|
|
if(not_same[k]){
|
||
|
|
if( k == 0)
|
||
|
|
p->entry.Template.ll_ptr1->entry.Template.ll_ptr1 = newpind[k];
|
||
|
|
else
|
||
|
|
pind[k]->entry.Template.ll_ptr1 = newpind[k];
|
||
|
|
}
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
int make_range(p,q, newp)
|
||
|
|
PTR_LLND p,q, *newp;
|
||
|
|
{
|
||
|
|
PTR_LLND plow, phi, qlow, qhi, newlow, newhi,d1,d2;
|
||
|
|
PTR_LLND make_llnd();
|
||
|
|
int diff, pconst, qconst;
|
||
|
|
|
||
|
|
if(p == NULL) {*newp = NULL; return 1;}
|
||
|
|
if(q == NULL) {*newp = NULL; return 1;}
|
||
|
|
if(p->variant == STAR_RANGE){ *newp = p; return 1; }
|
||
|
|
if(q->variant == STAR_RANGE){ *newp = q; return 1; }
|
||
|
|
|
||
|
|
pconst = qconst = 0;
|
||
|
|
if(p->variant == DDOT){
|
||
|
|
plow = p->entry.Template.ll_ptr1;
|
||
|
|
phi = p->entry.Template.ll_ptr2;
|
||
|
|
if(plow == NULL || phi == NULL){
|
||
|
|
*newp = make_llnd(cur_file, STAR_RANGE, NULL, NULL);
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
if(phi->variant == DDOT) phi = p->entry.Template.ll_ptr1;
|
||
|
|
}
|
||
|
|
else {plow = phi = p; pconst = 1;}
|
||
|
|
if(q->variant == DDOT){
|
||
|
|
qlow = q->entry.Template.ll_ptr1;
|
||
|
|
qhi = q->entry.Template.ll_ptr2;
|
||
|
|
if(qlow == NULL || qhi == NULL){
|
||
|
|
*newp = make_llnd(cur_file, STAR_RANGE, NULL, NULL);
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
if(qhi->variant == DDOT) qhi = q->entry.Template.ll_ptr1;
|
||
|
|
}
|
||
|
|
else {qlow = qhi = q; qconst = 1;}
|
||
|
|
if(pconst && qconst == 0){
|
||
|
|
if(integer_difference(p,qlow, &diff, &d1) && (diff >= -1)){
|
||
|
|
if(diff == 1 || diff == 0){
|
||
|
|
/* we have qlow < p ? qhi. we need to know the range of qhi */
|
||
|
|
*newp = q;
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
else if (diff == -1){
|
||
|
|
/* we hve p = qlow-1 < qhi o */
|
||
|
|
*newp = make_llnd(cur_file, DDOT, p, qhi, NULL);
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if(integer_difference(p,qhi, &diff, &d1) && (diff <= 1)){
|
||
|
|
if(diff == -1 || diff == 0){
|
||
|
|
/* we have qlow < qhi = p+1 */
|
||
|
|
*newp = q;
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
else if(diff == 1){
|
||
|
|
/* we hve qlow < qhi = p-1 < p */
|
||
|
|
*newp = make_llnd(cur_file, DDOT, qlow, p, NULL);
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
if(pconst == 0 && qconst){
|
||
|
|
if(integer_difference(plow,q, &diff, &d1) && (diff <= 1)){
|
||
|
|
if(diff == -1 || diff == 0){
|
||
|
|
/* we have plow < q ? phi. we need to know the range of phi */
|
||
|
|
*newp = p;
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
else if(diff == 1){
|
||
|
|
/* we hve q = plow-1<plow < phi */
|
||
|
|
*newp = make_llnd(cur_file, DDOT, q, phi, NULL);
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if(integer_difference(phi,q, &diff, &d1) && (diff >= -1)){
|
||
|
|
if(diff == 1 || diff == 0){
|
||
|
|
/* we have qlow ? p < qhi */
|
||
|
|
*newp = p;
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
else if(diff == -1){
|
||
|
|
/* we hve plow < phi = q-1<q */
|
||
|
|
*newp = make_llnd(cur_file, DDOT, plow, q, NULL);
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
if(pconst && qconst){
|
||
|
|
if(integer_difference(p,q,&diff,&d1)){
|
||
|
|
if (diff == 1){
|
||
|
|
*newp = make_llnd(cur_file, DDOT, q,p,NULL);
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
else if (diff ==1){
|
||
|
|
*newp = make_llnd(cur_file, DDOT, p,q,NULL);
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
else return 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if(integer_difference(plow,qlow,&diff, &d1) == 0){
|
||
|
|
/* printf("lo diff is %s", (UnparseLlnd[cur_file->lang])(d1)); */
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
if(diff <= 0) newlow = plow; else newlow = qlow;
|
||
|
|
if(integer_difference(phi, qhi, &diff,&d2) == 0){
|
||
|
|
/* printf("hi diff is %s", (UnparseLlnd[cur_file->lang])(d2)); */
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
if(diff <= 0) newhi = qhi; else newhi = phi;
|
||
|
|
*newp = make_llnd(cur_file, DDOT, newlow, newhi, NULL);
|
||
|
|
/* printf("new ref is%s",(UnparseLlnd[cur_file->lang])(*newp)); */
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
PTR_LLND merge_ll_array_list(rl)
|
||
|
|
PTR_LLND rl;
|
||
|
|
{
|
||
|
|
PTR_LLND t, newlist, junk;
|
||
|
|
int stop;
|
||
|
|
|
||
|
|
newlist = NULL;
|
||
|
|
junk = NULL;
|
||
|
|
while (rl != NULL) {
|
||
|
|
if (rl->variant != EXPR_LIST) {
|
||
|
|
fprintf(stderr, "problem in merge_ll_array_list, not exprlist\n%s\n",
|
||
|
|
(UnparseLlnd[cur_file->lang])(rl));
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
t = newlist;
|
||
|
|
stop = 0;
|
||
|
|
while (t != NULL) {
|
||
|
|
if (subsumed(t->entry.Template.ll_ptr1,
|
||
|
|
rl->entry.Template.ll_ptr1)) {
|
||
|
|
stop = 1;
|
||
|
|
}
|
||
|
|
t = t->entry.Template.ll_ptr2;
|
||
|
|
}
|
||
|
|
if (stop == 0) {
|
||
|
|
t = rl;
|
||
|
|
rl = rl->entry.Template.ll_ptr2;
|
||
|
|
t->entry.Template.ll_ptr2 = newlist;
|
||
|
|
newlist = t;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
t = rl;
|
||
|
|
rl = rl->entry.Template.ll_ptr2;
|
||
|
|
t->entry.Template.ll_ptr2 = junk;
|
||
|
|
junk = t;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return (newlist);
|
||
|
|
}
|
||
|
|
|
||
|
|
PTR_REFL merge_array_refs(rl)
|
||
|
|
PTR_REFL rl;
|
||
|
|
{
|
||
|
|
|
||
|
|
PTR_REFL t, newlist, junk;
|
||
|
|
int stop;
|
||
|
|
|
||
|
|
newlist = NULL;
|
||
|
|
junk = NULL;
|
||
|
|
while (rl != NULL) {
|
||
|
|
t = newlist;
|
||
|
|
stop = 0;
|
||
|
|
while (t != NULL) {
|
||
|
|
if (subsumed(t->node->refer, rl->node->refer)) {
|
||
|
|
stop = 1;
|
||
|
|
}
|
||
|
|
t = t->next;
|
||
|
|
}
|
||
|
|
if (stop == 0) {
|
||
|
|
t = rl;
|
||
|
|
rl = rl->next;
|
||
|
|
t->next = newlist;
|
||
|
|
newlist = t;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
t = rl;
|
||
|
|
rl = rl->next;
|
||
|
|
t->next = junk;
|
||
|
|
junk = t;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
disp_refl(junk);
|
||
|
|
return (newlist);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
PTR_REFL alloc_ref(bif, ll)
|
||
|
|
PTR_BFND bif;
|
||
|
|
PTR_LLND ll;
|
||
|
|
{
|
||
|
|
struct ref *p;
|
||
|
|
PTR_REFL q;
|
||
|
|
if ((bif == NULL) || (ll == NULL))
|
||
|
|
return (NULL);
|
||
|
|
|
||
|
|
if ((ll->variant == VAR_REF) || (ll->variant == ARRAY_REF) ||
|
||
|
|
(ll->variant == RECORD_REF) || (ll->variant == POINTST_OP)) {
|
||
|
|
p = (struct ref *) malloc(sizeof(struct ref));
|
||
|
|
#ifdef __SPF
|
||
|
|
addToCollection(__LINE__, __FILE__,p, 0);
|
||
|
|
#endif
|
||
|
|
if (p == NULL)
|
||
|
|
fprintf(stderr, "! out of space for references !!\n");
|
||
|
|
p->stmt = bif;
|
||
|
|
p->refer = ll;
|
||
|
|
if (free_refl != NULL) {
|
||
|
|
q = free_refl;
|
||
|
|
free_refl = free_refl->next;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
q = (PTR_REFL)malloc(sizeof(struct refl));
|
||
|
|
#ifdef __SPF
|
||
|
|
addToCollection(__LINE__, __FILE__,q, 0);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
if (q == NULL)
|
||
|
|
fprintf(stderr, "out of space for reference lists !!\n");
|
||
|
|
q->next = NULL;
|
||
|
|
if (ll->variant == RECORD_REF || ll->variant == POINTST_OP)
|
||
|
|
q->id = NULL;
|
||
|
|
else
|
||
|
|
q->id = p->refer->entry.Template.symbol;
|
||
|
|
q->node = p;
|
||
|
|
return (q);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
return (NULL);
|
||
|
|
}
|
||
|
|
|
||
|
|
void disp_refl(p)
|
||
|
|
PTR_REFL p;
|
||
|
|
{
|
||
|
|
PTR_REFL q;
|
||
|
|
|
||
|
|
while (p != NULL) {
|
||
|
|
q = p->next;
|
||
|
|
p->node = NULL;
|
||
|
|
p->id = NULL;
|
||
|
|
p->next = free_refl;
|
||
|
|
free_refl = p;
|
||
|
|
p = q;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
PTR_REFL copy_refl(p)
|
||
|
|
PTR_REFL p;
|
||
|
|
{
|
||
|
|
PTR_REFL q;
|
||
|
|
PTR_REFL tail, neo_q;
|
||
|
|
|
||
|
|
if (p == NULL)
|
||
|
|
return (NULL);
|
||
|
|
q = NULL;
|
||
|
|
tail = q;
|
||
|
|
|
||
|
|
if (free_refl == NULL)
|
||
|
|
{
|
||
|
|
q = (PTR_REFL)malloc(sizeof(struct refl));
|
||
|
|
#ifdef __SPF
|
||
|
|
addToCollection(__LINE__, __FILE__,q, 0);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
q = free_refl;
|
||
|
|
free_refl = free_refl->next;
|
||
|
|
}
|
||
|
|
if (q == NULL) {
|
||
|
|
fprintf(stderr, "!! out of space for reference lists !\n");
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
q->node = p->node;
|
||
|
|
q->id = p->id;
|
||
|
|
q->next = NULL;
|
||
|
|
/* now copy the rest of p */
|
||
|
|
tail = q;
|
||
|
|
p = p->next;
|
||
|
|
while (p) {
|
||
|
|
if (free_refl == NULL)
|
||
|
|
{
|
||
|
|
neo_q = (PTR_REFL)malloc(sizeof(struct refl));
|
||
|
|
#ifdef __SPF
|
||
|
|
addToCollection(__LINE__, __FILE__,neo_q, 0);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
neo_q = free_refl;
|
||
|
|
free_refl = free_refl->next;
|
||
|
|
}
|
||
|
|
if (neo_q == NULL) {
|
||
|
|
fprintf(stderr, "!! out of space for reference lists !\n");
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
neo_q->node = p->node;
|
||
|
|
neo_q->id = p->id;
|
||
|
|
neo_q->next = NULL;
|
||
|
|
tail->next = neo_q;
|
||
|
|
tail = neo_q;
|
||
|
|
p = p->next;
|
||
|
|
}
|
||
|
|
return q;
|
||
|
|
}
|
||
|
|
/* create a new reference list that is the interesction of two others */
|
||
|
|
/* the intersection is based on names and the actual reference comes */
|
||
|
|
/* from the second argument of the pair. */
|
||
|
|
/* in the case of a pair p p->a we include p->a in the intersection */
|
||
|
|
PTR_REFL intersect_refl(p, q)
|
||
|
|
PTR_REFL p, q;
|
||
|
|
{
|
||
|
|
PTR_REFL s, t, inter;
|
||
|
|
PTR_SYMB id;
|
||
|
|
PTR_LLND z;
|
||
|
|
int match_found;
|
||
|
|
|
||
|
|
inter = NULL;
|
||
|
|
s = q;
|
||
|
|
while (p != NULL) {
|
||
|
|
id = p->id;
|
||
|
|
if (id == NULL) { /* this is a ref to a p->a sub struct */
|
||
|
|
z = p->node->refer;
|
||
|
|
while (z != NULL && z->variant != VAR_REF)
|
||
|
|
z = z->entry.Template.ll_ptr1;
|
||
|
|
if (z == NULL)
|
||
|
|
id = NULL;
|
||
|
|
else
|
||
|
|
id = z->entry.Template.symbol;
|
||
|
|
}
|
||
|
|
match_found = 0;
|
||
|
|
while (s != NULL && (match_found == 0)) {
|
||
|
|
if (s->id == NULL) { /* a ref to a p->a sub struct */
|
||
|
|
z = s->node->refer;
|
||
|
|
while (z != NULL && z->variant != VAR_REF)
|
||
|
|
z = z->entry.Template.ll_ptr1;
|
||
|
|
if (z == NULL)
|
||
|
|
s = s->next;
|
||
|
|
else if (z->entry.Template.symbol == id)
|
||
|
|
match_found = 1;
|
||
|
|
else
|
||
|
|
s = s->next;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
if (s->id == id)
|
||
|
|
match_found = 1;
|
||
|
|
else
|
||
|
|
s = s->next;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (match_found && id != NULL) {
|
||
|
|
if (free_refl == NULL)
|
||
|
|
{
|
||
|
|
t = (PTR_REFL)malloc(sizeof(struct refl));
|
||
|
|
#ifdef __SPF
|
||
|
|
addToCollection(__LINE__, __FILE__,t, 0);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
t = free_refl;
|
||
|
|
free_refl = free_refl->next;
|
||
|
|
}
|
||
|
|
if (t == NULL)
|
||
|
|
fprintf(stderr, "!!! out of space for reference lists\n");
|
||
|
|
if (p->node != NULL &&
|
||
|
|
(p->node->refer->variant == POINTST_OP ||
|
||
|
|
p->node->refer->variant == RECORD_REF)) {
|
||
|
|
t->node = p->node;
|
||
|
|
t->id = NULL;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
t->node = s->node;
|
||
|
|
t->id = s->id;
|
||
|
|
}
|
||
|
|
t->next = inter;
|
||
|
|
inter = t;
|
||
|
|
s = s->next;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
p = p->next;
|
||
|
|
s = q;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return (inter);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* make name list makes a reference list based on a list of symbol */
|
||
|
|
/* table names. The node field is null. This is used for making */
|
||
|
|
/* a dummy list for arguments to procedures. */
|
||
|
|
PTR_REFL make_name_list(p)
|
||
|
|
PTR_SYMB p;
|
||
|
|
{
|
||
|
|
PTR_REFL list, t;
|
||
|
|
|
||
|
|
list = NULL;
|
||
|
|
while (p != NULL) {
|
||
|
|
if (free_refl == NULL)
|
||
|
|
{
|
||
|
|
t = (PTR_REFL)malloc(sizeof(struct refl));
|
||
|
|
#ifdef __SPF
|
||
|
|
addToCollection(__LINE__, __FILE__,t, 0);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
t = free_refl;
|
||
|
|
free_refl = free_refl->next;
|
||
|
|
}
|
||
|
|
if (t == NULL)
|
||
|
|
fprintf(stderr, "!!! out of space for reference lists\n");
|
||
|
|
t->node = NULL;
|
||
|
|
t->id = p;
|
||
|
|
t->next = list;
|
||
|
|
list = t;
|
||
|
|
p = p->entry.var_decl.next_in;
|
||
|
|
}
|
||
|
|
return (list);
|
||
|
|
}
|
||
|
|
|
||
|
|
void append_refl(s, p) /* and remove dups */
|
||
|
|
PTR_REFL *s, p;
|
||
|
|
{
|
||
|
|
PTR_REFL t;
|
||
|
|
struct ref *n;
|
||
|
|
|
||
|
|
while (p != NULL) {
|
||
|
|
n = p->node;
|
||
|
|
t = *s;
|
||
|
|
while ((t != NULL) && (t->node != n))
|
||
|
|
t = t->next;
|
||
|
|
if (t == NULL) {
|
||
|
|
if (free_refl == NULL)
|
||
|
|
{
|
||
|
|
t = (PTR_REFL)malloc(sizeof(struct refl));
|
||
|
|
#ifdef __SPF
|
||
|
|
addToCollection(__LINE__, __FILE__,t, 0);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
t = free_refl;
|
||
|
|
free_refl = free_refl->next;
|
||
|
|
}
|
||
|
|
if (t == NULL)
|
||
|
|
fprintf(stderr, "!!! out of space for reference lists\n");
|
||
|
|
t->node = p->node;
|
||
|
|
t->id = p->id;
|
||
|
|
t->next = *s;
|
||
|
|
*s = t;
|
||
|
|
}
|
||
|
|
p = p->next;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
PTR_REFL union_refl(p, q)
|
||
|
|
PTR_REFL p, q;
|
||
|
|
{
|
||
|
|
PTR_REFL s, t;
|
||
|
|
struct ref *n;
|
||
|
|
|
||
|
|
s = copy_refl(q);
|
||
|
|
while (p != NULL) {
|
||
|
|
n = p->node;
|
||
|
|
t = q;
|
||
|
|
while ((t != NULL) && (t->node != n))
|
||
|
|
t = t->next;
|
||
|
|
if (t == NULL) {
|
||
|
|
if (free_refl == NULL)
|
||
|
|
{
|
||
|
|
t = (PTR_REFL)malloc(sizeof(struct refl));
|
||
|
|
#ifdef __SPF
|
||
|
|
addToCollection(__LINE__, __FILE__,t, 0);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
t = free_refl;
|
||
|
|
free_refl = free_refl->next;
|
||
|
|
}
|
||
|
|
if (t == NULL) {
|
||
|
|
fprintf(stderr, "!!! out of space for reference lists\n");
|
||
|
|
exit(0);
|
||
|
|
}
|
||
|
|
t->node = p->node;
|
||
|
|
t->id = p->id;
|
||
|
|
t->next = s;
|
||
|
|
s = t;
|
||
|
|
}
|
||
|
|
p = p->next;
|
||
|
|
}
|
||
|
|
return (s);
|
||
|
|
}
|
||
|
|
|
||
|
|
void assign(to, from)
|
||
|
|
PTR_REFL *to;
|
||
|
|
PTR_REFL from;
|
||
|
|
{
|
||
|
|
disp_refl(*to);
|
||
|
|
*to = from;
|
||
|
|
}
|
||
|
|
|
||
|
|
void print_refl(p)
|
||
|
|
PTR_REFL p;
|
||
|
|
{
|
||
|
|
int i;
|
||
|
|
PTR_LLND z;
|
||
|
|
|
||
|
|
fprintf(stderr, " ref list :");
|
||
|
|
i = 0;
|
||
|
|
while (p != NULL) {
|
||
|
|
if (p->id != NULL)
|
||
|
|
fprintf(stderr, " %s", p->id->ident);
|
||
|
|
else {
|
||
|
|
fprintf(stderr, " pointer de-ref");
|
||
|
|
z = p->node->refer;
|
||
|
|
while (z != NULL && z->variant != VAR_REF)
|
||
|
|
z = z->entry.Template.ll_ptr1;
|
||
|
|
if (z == NULL)
|
||
|
|
fprintf(stderr, "-unknown");
|
||
|
|
else
|
||
|
|
fprintf(stderr, " %s", z->entry.Template.symbol->ident);
|
||
|
|
}
|
||
|
|
p = p->next;
|
||
|
|
i++;
|
||
|
|
if (i > 10) {
|
||
|
|
i = 0;
|
||
|
|
fprintf(stderr, "\n");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
fprintf(stderr, "\n");
|
||
|
|
}
|
||
|
|
|
||
|
|
int is_param(plist, s)
|
||
|
|
PTR_REFL plist;
|
||
|
|
PTR_SYMB s;
|
||
|
|
{
|
||
|
|
while (plist != NULL) {
|
||
|
|
if (plist->id == s)
|
||
|
|
return (1);
|
||
|
|
plist = plist->next;
|
||
|
|
}
|
||
|
|
return (0);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/********************************************************************/
|
||
|
|
/* function equiv_ll_exp(p,q) returns 1 if p and q are equivalent */
|
||
|
|
/* algebraic expressions. both are low level experessions */
|
||
|
|
/********************************************************************/
|
||
|
|
|
||
|
|
int equiv_ll_exp(p, q)
|
||
|
|
PTR_LLND p, q;
|
||
|
|
{
|
||
|
|
if (p == NULL && q == NULL)
|
||
|
|
return (1);
|
||
|
|
if (p == NULL || q == NULL)
|
||
|
|
return (0);
|
||
|
|
return (0);
|
||
|
|
}
|
||
|
|
|
||
|
|
int flat_check(p, q)
|
||
|
|
PTR_LLND p, q;
|
||
|
|
{
|
||
|
|
if (p == NULL && q == NULL)
|
||
|
|
return (1);
|
||
|
|
if (p == NULL || q == NULL)
|
||
|
|
return (0);
|
||
|
|
if (p->variant != q->variant)
|
||
|
|
return (0);
|
||
|
|
if (p->variant == VAR_REF || p->variant == ARRAY_REF) {
|
||
|
|
if (p->entry.var_ref.symbol != q->entry.var_ref.symbol)
|
||
|
|
return (0);
|
||
|
|
}
|
||
|
|
if (flat_check(p->entry.Template.ll_ptr1, q->entry.Template.ll_ptr1) == 0)
|
||
|
|
return (0);
|
||
|
|
if (flat_check(p->entry.Template.ll_ptr2, q->entry.Template.ll_ptr2) == 0)
|
||
|
|
return (0);
|
||
|
|
return (1);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/********************************************************************/
|
||
|
|
/* function reduce_ll_exp(p,newp) takes a low level pointer and */
|
||
|
|
/* returns a new expression (or the same old one) that is a an */
|
||
|
|
/* simple algebraic expression in terms of constants and parameter */
|
||
|
|
/* common references. the function returns 1 if sucessfull and 0 */
|
||
|
|
/* if it failed. if a 2 is returned then an integer value has been*/
|
||
|
|
/* generated and its value is return in the value newv. */
|
||
|
|
/* newp is the pointer to the new expression. */
|
||
|
|
/********************************************************************/
|
||
|
|
int reduce_ll_exp(b, plist, induct_list, p, newp, newv)
|
||
|
|
PTR_BFND b; /* bif node of expression (needed for
|
||
|
|
* context) */
|
||
|
|
PTR_REFL plist; /* list of parameters and commons in
|
||
|
|
* enclosing scope */
|
||
|
|
PTR_SYMB induct_list[]; /* induction variable list for current scope */
|
||
|
|
PTR_LLND p, *newp;
|
||
|
|
int *newv;
|
||
|
|
{
|
||
|
|
int lf, rf, lv, rv;
|
||
|
|
PTR_LLND lp, rp, make_llnd();
|
||
|
|
|
||
|
|
lv = 0;
|
||
|
|
rv = 0;
|
||
|
|
lf = 0;
|
||
|
|
rf = 0;
|
||
|
|
if (p == NULL) {
|
||
|
|
*newp = NULL;
|
||
|
|
return (1);
|
||
|
|
}
|
||
|
|
if ((p->variant == EXPR_LIST || p->variant == RANGE_LIST)
|
||
|
|
&& p->entry.Template.ll_ptr2 == NULL)
|
||
|
|
p = p->entry.Template.ll_ptr1;
|
||
|
|
if (p->variant == VAR_REF) {
|
||
|
|
/* first check for scalar propogation possibility */
|
||
|
|
if (p->entry.Template.ll_ptr1 != NULL) {
|
||
|
|
lf = reduce_ll_exp(b, plist, induct_list,
|
||
|
|
p->entry.Template.ll_ptr1, newp, newv);
|
||
|
|
return (lf);
|
||
|
|
}
|
||
|
|
/* second check to see if this is a parameter or global */
|
||
|
|
else if (is_param(plist, p->entry.Template.symbol) ||
|
||
|
|
is_not_loc(b, p)) {
|
||
|
|
*newp = p;
|
||
|
|
return (1);
|
||
|
|
}
|
||
|
|
/* this is some other variable and no propogation */
|
||
|
|
/* can reduce it to a simple expression. give up */
|
||
|
|
else {
|
||
|
|
*newp = p;
|
||
|
|
return (0);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if (p->variant == CONST_REF) {
|
||
|
|
*newp = p->entry.Template.symbol->entry.const_value;
|
||
|
|
if ((*newp)->variant == INT_VAL) {
|
||
|
|
*newv = (*newp)->entry.ival;
|
||
|
|
return (2);
|
||
|
|
}
|
||
|
|
return (1);
|
||
|
|
}
|
||
|
|
else if (p->variant == INT_VAL) {
|
||
|
|
*newv = p->entry.ival;
|
||
|
|
*newp = p;
|
||
|
|
return (2);
|
||
|
|
}
|
||
|
|
else if (p->variant != ADD_OP && p->variant != SUBT_OP &&
|
||
|
|
p->variant != MULT_OP && p->variant != DIV_OP &&
|
||
|
|
p->variant != MINUS_OP) {
|
||
|
|
*newp = p;
|
||
|
|
return (0);
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
lf = reduce_ll_exp(b, plist, induct_list,
|
||
|
|
p->entry.Template.ll_ptr1, &lp, &lv);
|
||
|
|
rf = reduce_ll_exp(b, plist, induct_list,
|
||
|
|
p->entry.Template.ll_ptr2, &rp, &rv);
|
||
|
|
if (lf == 2 && rf == 2) {
|
||
|
|
*newp = make_llnd(cur_file, INT_VAL, NULL, NULL, NULL);
|
||
|
|
switch (p->variant) {
|
||
|
|
case ADD_OP:
|
||
|
|
(*newp)->entry.ival = lv + rv;
|
||
|
|
break;
|
||
|
|
case SUBT_OP:
|
||
|
|
(*newp)->entry.ival = lv - rv;
|
||
|
|
break;
|
||
|
|
case MULT_OP:
|
||
|
|
(*newp)->entry.ival = lv * rv;
|
||
|
|
break;
|
||
|
|
case MINUS_OP:
|
||
|
|
(*newp)->entry.ival = -lv; /* not sure */
|
||
|
|
break;
|
||
|
|
case DIV_OP:
|
||
|
|
if (rv != 0)
|
||
|
|
(*newp)->entry.ival = lv / rv;
|
||
|
|
else
|
||
|
|
return (0);
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
*newp = p;
|
||
|
|
*newv = 0;
|
||
|
|
return (0);
|
||
|
|
}
|
||
|
|
(*newp)->type = cur_file->head_type;
|
||
|
|
*newv = (*newp)->entry.ival;
|
||
|
|
return (2);
|
||
|
|
}
|
||
|
|
else { /* both not integer case */
|
||
|
|
if (lf == 2 && lv == 1 && p->variant == MULT_OP) {
|
||
|
|
*newp = rp;
|
||
|
|
return (rf);
|
||
|
|
}
|
||
|
|
if ((lf == 2) && (lv < 0)) {
|
||
|
|
switch (p->variant) {
|
||
|
|
case ADD_OP:
|
||
|
|
*newp = make_llnd(cur_file, INT_VAL, NULL, NULL, NULL);
|
||
|
|
(*newp)->entry.ival = -lv;
|
||
|
|
*newp = make_llnd(cur_file, SUBT_OP, rp, *newp, NULL);
|
||
|
|
return (rf);
|
||
|
|
|
||
|
|
case SUBT_OP:
|
||
|
|
*newp = make_llnd(cur_file, INT_VAL, NULL, NULL, NULL);
|
||
|
|
(*newp)->entry.ival = -lv;
|
||
|
|
*newp = make_llnd(cur_file, ADD_OP, rp, *newp, NULL);
|
||
|
|
return (rf);
|
||
|
|
|
||
|
|
case MULT_OP:
|
||
|
|
if (lv == -1) {
|
||
|
|
if (rp->variant == MINUS_OP) {
|
||
|
|
*newp = rp->entry.Template.ll_ptr1;
|
||
|
|
*newv = rv;
|
||
|
|
return (rf);
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
*newp = make_llnd(cur_file, MINUS_OP, rp, NULL, NULL);
|
||
|
|
return (rf);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case MINUS_OP:
|
||
|
|
case DIV_OP:
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
} /* end if lf == 2 && lv < 0 */
|
||
|
|
|
||
|
|
if (rf == 2 && rv == 1 && p->variant == MULT_OP) {
|
||
|
|
*newp = lp;
|
||
|
|
return (lf);
|
||
|
|
}
|
||
|
|
if (rf == 2 && (rv < 0)) {
|
||
|
|
switch (p->variant) {
|
||
|
|
case ADD_OP:
|
||
|
|
*newp = make_llnd(cur_file, INT_VAL, NULL, NULL, NULL);
|
||
|
|
(*newp)->entry.ival = -rv;
|
||
|
|
*newp = make_llnd(cur_file, SUBT_OP, lp, *newp, NULL);
|
||
|
|
return (lf);
|
||
|
|
|
||
|
|
case SUBT_OP:
|
||
|
|
*newp = make_llnd(cur_file, INT_VAL, NULL, NULL, NULL);
|
||
|
|
(*newp)->entry.ival = -rv;
|
||
|
|
*newp = make_llnd(cur_file, ADD_OP, lp, *newp, NULL);
|
||
|
|
return (lf);
|
||
|
|
|
||
|
|
case MULT_OP:
|
||
|
|
if (rv == -1) {
|
||
|
|
if (rp->variant == MINUS_OP) {
|
||
|
|
*newp = lp->entry.Template.ll_ptr1;
|
||
|
|
*newv = lv;
|
||
|
|
return (lf);
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
*newp = make_llnd(cur_file, MINUS_OP, lp, NULL, NULL);
|
||
|
|
return (lf);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case MINUS_OP:
|
||
|
|
case DIV_OP:
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
} /* end if rf == 2 && rv < 0 */
|
||
|
|
if (p->variant == ADD_OP) {
|
||
|
|
if (rp->variant == MINUS_OP) {
|
||
|
|
*newp = make_llnd(cur_file, SUBT_OP, lp,
|
||
|
|
rp->entry.Template.ll_ptr1, NULL);
|
||
|
|
return (lf * rf);
|
||
|
|
}
|
||
|
|
if (lp->variant == MINUS_OP) {
|
||
|
|
*newp = make_llnd(cur_file, SUBT_OP, rp,
|
||
|
|
lp->entry.Template.ll_ptr1, NULL);
|
||
|
|
return (lf * rf);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
*newp = make_llnd(cur_file, p->variant,lp,rp,p->entry.Template.symbol);
|
||
|
|
if (lf == 0 || rf == 0) {
|
||
|
|
*newp = p;
|
||
|
|
return (0);
|
||
|
|
}
|
||
|
|
if (lf == 1 || rf == 1) {
|
||
|
|
lf = 1;
|
||
|
|
rf = 1;
|
||
|
|
}
|
||
|
|
return (lf * rf);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/********************************************************************/
|
||
|
|
/* comp_offset computes the constant term in a low level expression */
|
||
|
|
/* the value is in coef and a 1 is returned. If a 0 is returned */
|
||
|
|
/* this means that no integer order zero term was computable. */
|
||
|
|
/* if a 2 is returned then a ddot was found ".." coef contains the */
|
||
|
|
/* lower value and extra_coef contains the upper value. Note: we */
|
||
|
|
/* assume that the .. is at the root of the tree. */
|
||
|
|
/* if a 3 is returned then this is not a normal algebraic expression*/
|
||
|
|
/* if a 4 is returned then this is an algebraic expression using */
|
||
|
|
/* procedure parameters and vexp points to a ll tree representing */
|
||
|
|
/* the symbolic part of the constant. */
|
||
|
|
/* if a 5 is returned then it is a ddot with parameters. */
|
||
|
|
/* chkdflts = 1 means that the user should be prompted for defautls */
|
||
|
|
/* if a variable with no default value is found then a 3 will be */
|
||
|
|
/* returned. note: this needs more thought! */
|
||
|
|
/********************************************************************/
|
||
|
|
int extra_coef = 0;
|
||
|
|
int comp_offset(plist, induct_list, chkdflts, ll, coef, vexp)
|
||
|
|
PTR_REFL plist; /* list of parameters and commons in
|
||
|
|
* enclosing scope */
|
||
|
|
PTR_SYMB induct_list[]; /* induction variable list for current scope */
|
||
|
|
int chkdflts;
|
||
|
|
PTR_LLND ll;
|
||
|
|
int *coef;
|
||
|
|
PTR_LLND *vexp;
|
||
|
|
{
|
||
|
|
int i, lf, rf, lcoef, rcoef, tmp;
|
||
|
|
PTR_LLND lltmp, lexp, rexp;
|
||
|
|
PTR_LLND make_llnd(), copy_llnd();
|
||
|
|
|
||
|
|
tmp = 0;
|
||
|
|
*coef = 0;
|
||
|
|
*vexp = NULL;
|
||
|
|
if (ll == NULL)
|
||
|
|
return (0);
|
||
|
|
else if (ll->variant == VAR_REF) {
|
||
|
|
/* first check to see if this an induction variable */
|
||
|
|
for (i = 0; i < MAX_NEST_DEPTH; i++) {
|
||
|
|
if (ll->entry.Template.symbol == induct_list[i])
|
||
|
|
return (0);
|
||
|
|
}
|
||
|
|
/* second check for scalar propogation possibility */
|
||
|
|
if (ll->entry.Template.ll_ptr1 != NULL) {
|
||
|
|
return (comp_offset(plist, induct_list, chkdflts,
|
||
|
|
ll->entry.Template.ll_ptr1, coef, vexp)
|
||
|
|
);
|
||
|
|
}
|
||
|
|
/* third check to see if this is a scalar parameter */
|
||
|
|
/* in this modified version the induction test was */
|
||
|
|
/* put at the top and all unknown expressions are */
|
||
|
|
/* returned as type 4. */
|
||
|
|
else {
|
||
|
|
*vexp = copy_llnd(ll);
|
||
|
|
return (4);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if (ll->variant == CONST_REF) {
|
||
|
|
lltmp = ll->entry.Template.symbol->entry.const_value;
|
||
|
|
if (lltmp->variant == INT_VAL) {
|
||
|
|
*coef = lltmp->entry.ival;
|
||
|
|
*vexp = copy_llnd(ll);
|
||
|
|
return (1);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
return (0);
|
||
|
|
}
|
||
|
|
else if (ll->variant == INT_VAL) {
|
||
|
|
*coef = ll->entry.ival;
|
||
|
|
*vexp = copy_llnd(ll);
|
||
|
|
return (1);
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
lf = comp_offset(plist, induct_list, chkdflts,
|
||
|
|
ll->entry.Template.ll_ptr1, &lcoef, &lexp);
|
||
|
|
rf = comp_offset(plist, induct_list, chkdflts,
|
||
|
|
ll->entry.Template.ll_ptr2, &rcoef, &rexp);
|
||
|
|
if (lf == 3 || rf == 3)
|
||
|
|
return (3);
|
||
|
|
if (lf == 5 || rf == 5)
|
||
|
|
return (5);
|
||
|
|
switch (ll->variant) {
|
||
|
|
case DDOT:
|
||
|
|
if (lf == 1)
|
||
|
|
*coef = lcoef;
|
||
|
|
else
|
||
|
|
*coef = 0;
|
||
|
|
if (rf == 1)
|
||
|
|
extra_coef = rcoef;
|
||
|
|
else
|
||
|
|
extra_coef = 0;
|
||
|
|
if ((lf == 1) || (rf == 1))
|
||
|
|
return (2);
|
||
|
|
if (lf == 4 || rf == 4)
|
||
|
|
return (5);
|
||
|
|
else
|
||
|
|
return (0);
|
||
|
|
case ADD_OP:
|
||
|
|
tmp = 0;
|
||
|
|
if (lf == 4 && rf == 0) {
|
||
|
|
*vexp = lexp;
|
||
|
|
return (4);
|
||
|
|
}
|
||
|
|
if (rf == 4 && lf == 0) {
|
||
|
|
*vexp = rexp;
|
||
|
|
return (4);
|
||
|
|
}
|
||
|
|
if (lf == 4 || rf == 4) {
|
||
|
|
if (rexp->variant == MINUS_OP)
|
||
|
|
*vexp = make_llnd(cur_file, SUBT_OP, lexp,
|
||
|
|
rexp->entry.Template.ll_ptr1, NULL);
|
||
|
|
else
|
||
|
|
*vexp = make_llnd(cur_file, ADD_OP, lexp, rexp, NULL);
|
||
|
|
return (4);
|
||
|
|
}
|
||
|
|
if (lf == 1)
|
||
|
|
tmp = lcoef;
|
||
|
|
if (rf == 1)
|
||
|
|
tmp = tmp + rcoef;
|
||
|
|
if ((lf == 1) || (rf == 1)) {
|
||
|
|
*coef = tmp;
|
||
|
|
*vexp = make_llnd(cur_file, INT_VAL, NULL, NULL, NULL);
|
||
|
|
(*vexp)->entry.ival = tmp;
|
||
|
|
return (1);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
return (0);
|
||
|
|
case SUBT_OP:
|
||
|
|
tmp = 0;
|
||
|
|
if (lf == 4 && rf == 0) {
|
||
|
|
*vexp = lexp;
|
||
|
|
return (4);
|
||
|
|
}
|
||
|
|
if (rf == 4 && lf == 0) {
|
||
|
|
if (rexp->variant == INT_VAL) {
|
||
|
|
rexp->entry.ival = -(rexp->entry.ival);
|
||
|
|
*vexp = rexp;
|
||
|
|
return (4);
|
||
|
|
}
|
||
|
|
if (rexp->variant != MINUS_OP)
|
||
|
|
*vexp = make_llnd(cur_file, MINUS_OP, rexp, NULL, NULL);
|
||
|
|
else
|
||
|
|
*vexp = rexp->entry.Template.ll_ptr1;
|
||
|
|
return (4);
|
||
|
|
}
|
||
|
|
if (lf == 4 || rf == 4) {
|
||
|
|
if (rexp->variant == MINUS_OP)
|
||
|
|
*vexp = make_llnd(cur_file, ADD_OP, lexp,
|
||
|
|
rexp->entry.Template.ll_ptr1, NULL);
|
||
|
|
else
|
||
|
|
*vexp = make_llnd(cur_file, SUBT_OP, lexp, rexp, NULL);
|
||
|
|
return (4);
|
||
|
|
}
|
||
|
|
if (lf == 1)
|
||
|
|
tmp = lcoef;
|
||
|
|
if (rf == 1)
|
||
|
|
tmp = tmp - rcoef;
|
||
|
|
if ((lf == 1) || (rf == 1)) {
|
||
|
|
*coef = tmp;
|
||
|
|
*vexp = make_llnd(cur_file, INT_VAL, NULL, NULL, NULL);
|
||
|
|
(*vexp)->entry.ival = tmp;
|
||
|
|
return (1);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
return (0);
|
||
|
|
case MULT_OP:
|
||
|
|
if (lf == 4 && rf == 0)
|
||
|
|
return (0);
|
||
|
|
if (rf == 4 && lf == 0)
|
||
|
|
return (0);
|
||
|
|
if (lf == 4 || rf == 4) {
|
||
|
|
if (rexp->variant == MULT_OP) { /* left associate terms */
|
||
|
|
lltmp = rexp->entry.Template.ll_ptr1;
|
||
|
|
lltmp = make_llnd(cur_file, MULT_OP, lexp, lltmp, NULL);
|
||
|
|
*vexp = make_llnd(cur_file, MULT_OP, lltmp,
|
||
|
|
rexp->entry.Template.ll_ptr2, NULL);
|
||
|
|
return (4);
|
||
|
|
}
|
||
|
|
if (rf == 1) {
|
||
|
|
*vexp = make_llnd(cur_file, MULT_OP, rexp, lexp, NULL);
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
*vexp = make_llnd(cur_file, MULT_OP, lexp, rexp, NULL);
|
||
|
|
}
|
||
|
|
return (4);
|
||
|
|
}
|
||
|
|
if ((lf == 1) && (rf == 1)) {
|
||
|
|
*coef = lcoef * rcoef;
|
||
|
|
*vexp = make_llnd(cur_file, INT_VAL, NULL, NULL, NULL);
|
||
|
|
(*vexp)->entry.ival = *coef;
|
||
|
|
return (1);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
return (0);
|
||
|
|
case MINUS_OP:
|
||
|
|
if (lf == 4) {
|
||
|
|
if (lexp->variant == MINUS_OP)
|
||
|
|
*vexp = lexp->entry.Template.ll_ptr1;
|
||
|
|
else
|
||
|
|
*vexp = make_llnd(cur_file, MINUS_OP, lexp, NULL, NULL);
|
||
|
|
}
|
||
|
|
else if (lf == 1) {
|
||
|
|
*vexp = make_llnd(cur_file, INT_VAL, NULL, NULL, NULL);
|
||
|
|
*coef = -lcoef;
|
||
|
|
(*vexp)->entry.ival = *coef;
|
||
|
|
}
|
||
|
|
return (lf);
|
||
|
|
case DIV_OP:
|
||
|
|
if (lf == 4 && rf == 0)
|
||
|
|
return (0);
|
||
|
|
if (rf == 4 && lf == 0)
|
||
|
|
return (0);
|
||
|
|
if (lf == 4 || rf == 4) {
|
||
|
|
*vexp = make_llnd(cur_file, DIV_OP, lexp, rexp, NULL);
|
||
|
|
return (4);
|
||
|
|
}
|
||
|
|
if ((rcoef != 0) && (lf == 1) && (rf == 1)) {
|
||
|
|
*coef = lcoef / rcoef;
|
||
|
|
*vexp = make_llnd(cur_file, INT_VAL, NULL, NULL, NULL);
|
||
|
|
(*vexp)->entry.ival = *coef;
|
||
|
|
return (1);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
return (0);
|
||
|
|
case EXPR_LIST:
|
||
|
|
if (ll->entry.Template.ll_ptr2 == NULL) {
|
||
|
|
*vexp = lexp;
|
||
|
|
*coef = lcoef;
|
||
|
|
return (lf);
|
||
|
|
}
|
||
|
|
default:
|
||
|
|
*coef = 0;
|
||
|
|
return (3); /* not normal */
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************/
|
||
|
|
/* search symb searches a ll tree returns 0 if a const. is found */
|
||
|
|
/* a -2 if another symbol is found as a multiplicative factor */
|
||
|
|
/* for example, searching for i in 2*i*(5+j) returns -2 */
|
||
|
|
/* a -1 if it is found but not in a linear combination. */
|
||
|
|
/* and a 1 if it is and coef has the value of the coefecient */
|
||
|
|
/* In the case that a ddot ".." is found a 2 is returned and */
|
||
|
|
/* coef has the value of the low bound term and extra_coef has */
|
||
|
|
/* the high value. Note this implies that .. is at the root of */
|
||
|
|
/* the tree. */
|
||
|
|
/* chkdflts=1 means that the usr should be prompted for defautls */
|
||
|
|
/*****************************************************************/
|
||
|
|
|
||
|
|
/* returns 1 if constant coef and *coef is set. */
|
||
|
|
/* returns -2 if non-constant coef and *exp is set */
|
||
|
|
/* returns 0 if constant but not coef and *coef is set */
|
||
|
|
/* returns 2 if non-constant non-coef is found. *exp set*/
|
||
|
|
/* returns -1 for non-linear expressions in s */
|
||
|
|
|
||
|
|
int new_search_symb(s, induct_list, ll, coef, exp)
|
||
|
|
PTR_SYMB s;
|
||
|
|
PTR_SYMB induct_list[];
|
||
|
|
PTR_LLND ll, *exp;
|
||
|
|
int *coef;
|
||
|
|
{
|
||
|
|
int lval, rval;
|
||
|
|
PTR_LLND lexp, rexp, nll, make_llnd(), copy_llnd();
|
||
|
|
int lcoef, rcoef;
|
||
|
|
|
||
|
|
if (ll == NULL) {
|
||
|
|
*coef = 0;
|
||
|
|
return (0);
|
||
|
|
}
|
||
|
|
lexp = NULL;
|
||
|
|
rexp = NULL;
|
||
|
|
if (ll->variant == VAR_REF) {
|
||
|
|
if (ll->entry.Template.symbol == s) {
|
||
|
|
*coef = 1;
|
||
|
|
*exp = NULL;
|
||
|
|
return (1);
|
||
|
|
}
|
||
|
|
if (ll->entry.Template.ll_ptr1 != NULL) {
|
||
|
|
return (
|
||
|
|
new_search_symb(s, induct_list, ll->entry.Template.ll_ptr1, coef, exp)
|
||
|
|
);
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
*exp = ll;
|
||
|
|
return (2);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if (ll->variant == INT_VAL) {
|
||
|
|
*coef = ll->entry.ival;
|
||
|
|
*exp = NULL;
|
||
|
|
return (0);
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
lval=new_search_symb(s,induct_list,ll->entry.Template.ll_ptr1,&lcoef,&lexp);
|
||
|
|
rval=new_search_symb(s,induct_list,ll->entry.Template.ll_ptr2,&rcoef,&rexp);
|
||
|
|
switch (ll->variant) {
|
||
|
|
case MINUS_OP:
|
||
|
|
if (lval == 1 || lval == 0) {
|
||
|
|
*coef = -lcoef;
|
||
|
|
return (lval);
|
||
|
|
}
|
||
|
|
else if (lval == -2 || lval == 2) {
|
||
|
|
if (lexp->variant == MINUS_OP)
|
||
|
|
*exp = lexp->entry.Template.ll_ptr1;
|
||
|
|
else
|
||
|
|
*exp = make_llnd(cur_file, MINUS_OP, lexp, NULL, NULL);
|
||
|
|
return (lval);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
return (-1);
|
||
|
|
case MULT_OP:
|
||
|
|
case DIV_OP:
|
||
|
|
if (rval == 1) { /* right side is const coef of s */
|
||
|
|
switch (lval) {
|
||
|
|
case 0:
|
||
|
|
if (ll->variant == MULT_OP) {
|
||
|
|
*coef = lcoef * rcoef;
|
||
|
|
return (1);
|
||
|
|
}
|
||
|
|
else if (rcoef != 0) {
|
||
|
|
*coef = lcoef / rcoef;
|
||
|
|
return (1);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
return (-1);
|
||
|
|
case -2:
|
||
|
|
case -1:
|
||
|
|
case 1:
|
||
|
|
return (-1);
|
||
|
|
case 2:
|
||
|
|
if (rcoef == 1)
|
||
|
|
*exp = lexp;
|
||
|
|
else {
|
||
|
|
if (ll->variant == DIV_OP && rcoef == 0)
|
||
|
|
return (-1);
|
||
|
|
nll = make_llnd(cur_file, INT_VAL, NULL, NULL, rcoef);
|
||
|
|
nll = make_llnd(cur_file, ll->variant, lexp, nll, NULL);
|
||
|
|
*exp = nll;
|
||
|
|
}
|
||
|
|
return (-2);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if (rval == 0) { /* right side is just a constant */
|
||
|
|
switch (lval) {
|
||
|
|
case 0:
|
||
|
|
if (ll->variant == MULT_OP) {
|
||
|
|
*coef = lcoef * rcoef;
|
||
|
|
return (0);
|
||
|
|
}
|
||
|
|
else if (rcoef != 0) {
|
||
|
|
*coef = lcoef / rcoef;
|
||
|
|
return (0);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
return (-1);
|
||
|
|
case -2: /* left side is non-const coef of s */
|
||
|
|
case 2: /* or non-const non-coef */
|
||
|
|
if (rcoef == 1)
|
||
|
|
*exp = lexp;
|
||
|
|
else {
|
||
|
|
nll = make_llnd(cur_file, INT_VAL, NULL, NULL, rcoef);
|
||
|
|
nll = make_llnd(cur_file, ll->variant, lexp, nll, NULL);
|
||
|
|
*exp = nll;
|
||
|
|
}
|
||
|
|
return (lval);
|
||
|
|
case 1:
|
||
|
|
if (ll->variant == MULT_OP) {
|
||
|
|
*coef = lcoef * rcoef;
|
||
|
|
return (1);
|
||
|
|
}
|
||
|
|
else if (rcoef != 0) {
|
||
|
|
*coef = lcoef / rcoef;
|
||
|
|
return (1);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
return (-1);
|
||
|
|
case -1:
|
||
|
|
return (-1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if (rval == 2) { /* right side is a non-constant non coef */
|
||
|
|
switch (lval) {
|
||
|
|
case 1:
|
||
|
|
case 0:
|
||
|
|
if (lcoef == 1)
|
||
|
|
*exp = rexp;
|
||
|
|
else {
|
||
|
|
nll = make_llnd(cur_file, INT_VAL, NULL, NULL, lcoef);
|
||
|
|
nll = make_llnd(cur_file, MULT_OP, nll, rexp, NULL);
|
||
|
|
*exp = nll;
|
||
|
|
}
|
||
|
|
if (lval == 0)
|
||
|
|
return (2);
|
||
|
|
else
|
||
|
|
return (-2);
|
||
|
|
case 2:
|
||
|
|
*exp = ll;
|
||
|
|
return (2);
|
||
|
|
case -2:
|
||
|
|
*exp = make_llnd(cur_file, MULT_OP, lexp, rexp, NULL);
|
||
|
|
return (-2);
|
||
|
|
case -1:
|
||
|
|
return (-1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if (rval == -2) { /* right side is a coef of s but not const */
|
||
|
|
switch (lval) {
|
||
|
|
case 1:
|
||
|
|
case -2:
|
||
|
|
case -1:
|
||
|
|
return (-1);
|
||
|
|
case 0:
|
||
|
|
if (lcoef == 1)
|
||
|
|
*exp = rexp;
|
||
|
|
else {
|
||
|
|
nll = make_llnd(cur_file, INT_VAL, NULL, NULL, lcoef);
|
||
|
|
nll = make_llnd(cur_file, MULT_OP, nll, rexp, NULL);
|
||
|
|
*exp = nll;
|
||
|
|
}
|
||
|
|
return (-2);
|
||
|
|
case 2:
|
||
|
|
*exp = make_llnd(cur_file, MULT_OP, lexp, rexp, NULL);
|
||
|
|
return (-2);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else /* rval == -1 */
|
||
|
|
return (-1);
|
||
|
|
case ADD_OP:
|
||
|
|
case SUBT_OP:
|
||
|
|
if (rval == 1) { /* right side is const times s */
|
||
|
|
switch (lval) {
|
||
|
|
case 1: /* lhs is const coef */
|
||
|
|
if (ll->variant == ADD_OP)
|
||
|
|
*coef = lcoef + rcoef;
|
||
|
|
else
|
||
|
|
*coef = lcoef - rcoef;
|
||
|
|
return (1);
|
||
|
|
case -2: /* lhs is non-const coef */
|
||
|
|
nll = make_llnd(cur_file, INT_VAL, NULL, NULL, NULL);
|
||
|
|
if (ll->variant == ADD_OP)
|
||
|
|
nll->entry.ival = rcoef;
|
||
|
|
else
|
||
|
|
nll->entry.ival = -rcoef;
|
||
|
|
if (lexp->variant == MINUS_OP) {
|
||
|
|
lexp = lexp->entry.Template.ll_ptr1;
|
||
|
|
*exp = make_llnd(cur_file, SUBT_OP, nll, lexp, NULL);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
*exp = make_llnd(cur_file, ADD_OP, lexp, nll, NULL);
|
||
|
|
return (-2);
|
||
|
|
case -1:
|
||
|
|
return (-1);
|
||
|
|
case 0: /* lhs is const */
|
||
|
|
case 2: /* lhs is non const */
|
||
|
|
if (ll->variant == ADD_OP)
|
||
|
|
*coef = rcoef;
|
||
|
|
else
|
||
|
|
*coef = -rcoef;
|
||
|
|
return (1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if (rval == -2) { /* right side is non-const times s */
|
||
|
|
switch (lval) {
|
||
|
|
case 1: /* lhs is const coef */
|
||
|
|
lexp = make_llnd(cur_file, INT_VAL, NULL, NULL, NULL);
|
||
|
|
if (lexp->variant == ADD_OP)
|
||
|
|
lexp->entry.ival = lcoef;
|
||
|
|
else
|
||
|
|
lexp->entry.ival = -lcoef;
|
||
|
|
case -2: /* lhs is non-const coef */
|
||
|
|
*exp = make_llnd(cur_file, ll->variant, lexp, rexp, NULL);
|
||
|
|
return (-2);
|
||
|
|
case -1:
|
||
|
|
return (-1);
|
||
|
|
case 0: /* lhs is const */
|
||
|
|
case 2: /* lhs is non const */
|
||
|
|
if (ll->variant == SUBT_OP) {
|
||
|
|
rexp = make_llnd(cur_file, MINUS_OP, rexp, NULL, NULL);
|
||
|
|
}
|
||
|
|
*exp = rexp;
|
||
|
|
return (-2);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if (rval == 0) { /* right side is just constant */
|
||
|
|
switch (lval) {
|
||
|
|
case 1: /* lhs is const coef */
|
||
|
|
*coef = lcoef;
|
||
|
|
return (1);
|
||
|
|
case -2: /* lhs is non-const coef */
|
||
|
|
*exp = lexp;
|
||
|
|
return (-2);
|
||
|
|
case -1:
|
||
|
|
return (-1);
|
||
|
|
case 0: /* lhs is const */
|
||
|
|
if (ll->variant == ADD_OP)
|
||
|
|
*coef = lcoef + rcoef;
|
||
|
|
else
|
||
|
|
*coef = lcoef - rcoef;
|
||
|
|
return (0);
|
||
|
|
case 2: /* lhs is non const */
|
||
|
|
nll = make_llnd(cur_file, INT_VAL, NULL, NULL, NULL);
|
||
|
|
nll->entry.ival = rcoef;
|
||
|
|
*exp = make_llnd(cur_file, ll->variant, lexp, nll, NULL);
|
||
|
|
return (2);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if (rval == 2) { /* right side in non-const non coef */
|
||
|
|
switch (lval) {
|
||
|
|
case 1: /* lhs is const coef */
|
||
|
|
*coef = lcoef;
|
||
|
|
return (1);
|
||
|
|
case -2: /* lhs is non-const coef */
|
||
|
|
*exp = lexp;
|
||
|
|
return (-2);
|
||
|
|
case -1:
|
||
|
|
return (-1);
|
||
|
|
case 0: /* lhs is const */
|
||
|
|
lexp = make_llnd(cur_file, INT_VAL, NULL, NULL, NULL);
|
||
|
|
lexp->entry.ival = lcoef;
|
||
|
|
case 2: /* lhs is non const */
|
||
|
|
*exp = make_llnd(cur_file, ll->variant, lexp, rexp, NULL);
|
||
|
|
return (2);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else /* if(rval == -1) */
|
||
|
|
return (-1);
|
||
|
|
case DDOT:
|
||
|
|
case ARRAY_REF:
|
||
|
|
case FUNC_CALL:
|
||
|
|
return (-1);
|
||
|
|
default:
|
||
|
|
return (-1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
int search_symb(chkdflts, s, ll, coef)
|
||
|
|
int chkdflts;
|
||
|
|
PTR_SYMB s;
|
||
|
|
PTR_LLND ll;
|
||
|
|
int *coef;
|
||
|
|
{
|
||
|
|
int i, lf, rf, lcoef, rcoef, tmp;
|
||
|
|
PTR_LLND lltmp;
|
||
|
|
|
||
|
|
tmp = 0;
|
||
|
|
*coef = 0;
|
||
|
|
if (ll == NULL)
|
||
|
|
return (0);
|
||
|
|
else if (ll->variant == VAR_REF) {
|
||
|
|
if (ll->entry.Template.symbol == s) {
|
||
|
|
*coef = 1;
|
||
|
|
return (1);
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
/* first try a variable propogation to find s */
|
||
|
|
if (ll->entry.Template.ll_ptr1 != NULL) {
|
||
|
|
return (
|
||
|
|
search_symb(chkdflts, s, ll->entry.Template.ll_ptr1, coef)
|
||
|
|
);
|
||
|
|
}
|
||
|
|
else if (chkdflts) {
|
||
|
|
for (i = 0; i < MAX_NEST_DEPTH; i++) {
|
||
|
|
if (ll->entry.Template.symbol == induct_list[i])
|
||
|
|
return (-3);
|
||
|
|
}
|
||
|
|
return (0);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
return (-3);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if (ll->variant == CONST_REF) {
|
||
|
|
lltmp = ll->entry.Template.symbol->entry.const_value;
|
||
|
|
if (lltmp->variant == INT_VAL) {
|
||
|
|
*coef = lltmp->entry.ival;
|
||
|
|
return (0);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
return (-3);
|
||
|
|
}
|
||
|
|
else if (ll->variant == INT_VAL) {
|
||
|
|
*coef = ll->entry.ival;
|
||
|
|
return (0);
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
lf = search_symb(chkdflts, s, ll->entry.Template.ll_ptr1, &lcoef);
|
||
|
|
rf = search_symb(chkdflts, s, ll->entry.Template.ll_ptr2, &rcoef);
|
||
|
|
switch (ll->variant) {
|
||
|
|
case DDOT:
|
||
|
|
if (lf == 1)
|
||
|
|
*coef = lcoef;
|
||
|
|
else
|
||
|
|
*coef = 0;
|
||
|
|
if (rf == 1)
|
||
|
|
extra_coef = rcoef;
|
||
|
|
else
|
||
|
|
extra_coef = 0;
|
||
|
|
if ((lf == 1) || (rf == 1))
|
||
|
|
return (2);
|
||
|
|
else {
|
||
|
|
if (lf * rf == 0)
|
||
|
|
return (0);
|
||
|
|
else
|
||
|
|
return ((lf <= rf) ? rf : lf);
|
||
|
|
}
|
||
|
|
case ADD_OP:
|
||
|
|
if (lf == 1)
|
||
|
|
tmp = lcoef;
|
||
|
|
if (rf == 1)
|
||
|
|
tmp = tmp + rcoef;
|
||
|
|
if ((lf == 1) || (rf == 1)) {
|
||
|
|
*coef = tmp;
|
||
|
|
return (1);
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
*coef = rcoef + lcoef;
|
||
|
|
if (lf * rf == 0)
|
||
|
|
return (0);
|
||
|
|
else
|
||
|
|
return ((lf <= rf) ? rf : lf);
|
||
|
|
}
|
||
|
|
case SUBT_OP:
|
||
|
|
if (lf == 1)
|
||
|
|
tmp = lcoef;
|
||
|
|
if (rf == 1)
|
||
|
|
tmp = tmp - rcoef;
|
||
|
|
if ((lf == 1) || (rf == 1)) {
|
||
|
|
*coef = tmp;
|
||
|
|
return (1);
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
*coef = lcoef - rcoef;
|
||
|
|
if (lf * rf == 0)
|
||
|
|
return (0);
|
||
|
|
else
|
||
|
|
return ((lf <= rf) ? rf : lf);
|
||
|
|
}
|
||
|
|
case MULT_OP:
|
||
|
|
tmp = 1;
|
||
|
|
if ((lf == 1) || (lf == 0))
|
||
|
|
tmp = lcoef;
|
||
|
|
if ((rf == 1) || (rf == 0))
|
||
|
|
tmp = tmp * rcoef;
|
||
|
|
if ((lf * rf) == 0) {
|
||
|
|
*coef = tmp;
|
||
|
|
return (lf + rf);
|
||
|
|
}
|
||
|
|
else if ((lf == 1) && (rf == 1)) {
|
||
|
|
*coef = 1;
|
||
|
|
return (-1);
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
*coef = 1;
|
||
|
|
return (-2);
|
||
|
|
}
|
||
|
|
case MINUS_OP:
|
||
|
|
*coef = -lcoef;
|
||
|
|
return (lf);
|
||
|
|
default:
|
||
|
|
*coef = 999;
|
||
|
|
return (-2);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void print_subscr(r, arr, induct_list)
|
||
|
|
PTR_SYMB induct_list[];
|
||
|
|
struct ref *r;
|
||
|
|
struct subscript arr[];
|
||
|
|
{
|
||
|
|
int i, j;
|
||
|
|
PTR_LLND ll;
|
||
|
|
char *s;
|
||
|
|
|
||
|
|
ll = r->refer;
|
||
|
|
if (induct_list[0] == NULL)
|
||
|
|
return;
|
||
|
|
for (j = 0; j < 2; j++) {
|
||
|
|
fprintf(stderr, "______________________________________________________\n");
|
||
|
|
fprintf(stderr, "| ID | decidable | offset | %s | %s | %s | parm_exp \n",
|
||
|
|
induct_list[0]->ident,
|
||
|
|
(induct_list[1] == NULL) ? "-" : induct_list[1]->ident,
|
||
|
|
(induct_list[2] == NULL) ? "-" : induct_list[2]->ident);
|
||
|
|
fprintf(stderr, "|-----------------------------------------------------|\n");
|
||
|
|
if (arr[j].parm_exp != NULL)
|
||
|
|
s = (UnparseLlnd[cur_file->lang])(arr[j].parm_exp);
|
||
|
|
else
|
||
|
|
s = "";
|
||
|
|
fprintf(stderr, "| %s | %d | %d | %d | %d | %d |%s\n",
|
||
|
|
ll->entry.array_ref.symbol->ident,
|
||
|
|
arr[j].decidable, arr[j].offset,
|
||
|
|
arr[j].coefs[0], arr[j].coefs[1], arr[j].coefs[2], s
|
||
|
|
);
|
||
|
|
fprintf(stderr, "|-----------------------------------------------------|\n");
|
||
|
|
for (i = 0; i < 2; i++) {
|
||
|
|
if (arr[j].coefs_symb[i] != NULL)
|
||
|
|
fprintf(stderr, " arr[%d].coefs_symb[%d] = %s\n", j, i,
|
||
|
|
(UnparseLlnd[cur_file->lang])(arr[j].coefs_symb[i]));
|
||
|
|
}
|
||
|
|
fprintf(stderr, "|-----------------------------------------------------|\n");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* structure equiv. takes two low level pointers to expressions and test */
|
||
|
|
/* them for equivalence as expressions. if equif returns 1 else 0 */
|
||
|
|
/* this version checks only syntatic equiv. algebraic equiv will be needed */
|
||
|
|
int sequiv(sub1, sub2)
|
||
|
|
PTR_LLND sub1, sub2;
|
||
|
|
{
|
||
|
|
if ((sub1 == NULL) && (sub2 == NULL))
|
||
|
|
return (1);
|
||
|
|
if (((sub1 == NULL) && (sub2 != NULL)) ||
|
||
|
|
((sub1 != NULL) && (sub2 == NULL)))
|
||
|
|
return (0);
|
||
|
|
/* both not null */
|
||
|
|
if (sub1->variant != sub2->variant)
|
||
|
|
return (0);
|
||
|
|
else {
|
||
|
|
if (sub1->variant == VAR_REF) {
|
||
|
|
if (sub1->entry.Template.symbol ==
|
||
|
|
sub2->entry.Template.symbol)
|
||
|
|
return (1);
|
||
|
|
else
|
||
|
|
return (0);
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
if (sequiv(sub1->entry.Template.ll_ptr1,
|
||
|
|
sub2->entry.Template.ll_ptr1) &&
|
||
|
|
sequiv(sub1->entry.Template.ll_ptr2,
|
||
|
|
sub2->entry.Template.ll_ptr2)
|
||
|
|
)
|
||
|
|
return (1);
|
||
|
|
else
|
||
|
|
return (0);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* make_subscr(r,arr) creates the subscript array for the reference r */
|
||
|
|
void make_subscr(r, arr)
|
||
|
|
struct ref *r;
|
||
|
|
struct subscript arr[];
|
||
|
|
{
|
||
|
|
int i, j;
|
||
|
|
PTR_BFND b, fun;
|
||
|
|
PTR_REFL plist;
|
||
|
|
PTR_LLND ll, tl, index_exper, parexp, exp;
|
||
|
|
struct subscript il_lo[MAX_NEST_DEPTH];
|
||
|
|
struct subscript il_hi[MAX_NEST_DEPTH];
|
||
|
|
int depth, found, coef;
|
||
|
|
|
||
|
|
b = r->stmt;
|
||
|
|
ll = r->refer;
|
||
|
|
for (j = 0; j < AR_DIM_MAX; j++) {
|
||
|
|
arr[j].decidable = -1;
|
||
|
|
arr[j].parm_exp = NULL;
|
||
|
|
arr[j].offset = 0;
|
||
|
|
arr[j].vector = NULL;
|
||
|
|
for (i = 0; i < MAX_NEST_DEPTH; i++) {
|
||
|
|
arr[j].coefs[i] = 0;
|
||
|
|
arr[j].coefs_symb[i] = NULL;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* now make build the set of valid induction variables */
|
||
|
|
depth = make_induct_list(b, induct_list, il_lo, il_hi);
|
||
|
|
/* now find the parameters and common vars for this scope */
|
||
|
|
fun = b;
|
||
|
|
while (fun != NULL && (fun->variant != PROG_HEDR) &&
|
||
|
|
(fun->variant != FUNC_HEDR) &&
|
||
|
|
(fun->variant != PROC_HEDR))
|
||
|
|
fun = fun->control_parent;
|
||
|
|
if (fun == NULL)
|
||
|
|
return;
|
||
|
|
if(fun->entry.Template.sets == NULL) plist = NULL;
|
||
|
|
else plist = fun->entry.Template.sets->in_def;
|
||
|
|
|
||
|
|
/* now for each array index position build the vector of coefs. */
|
||
|
|
/* start with the left most position numbered by i */
|
||
|
|
i = 0;
|
||
|
|
if (ll->variant == ARRAY_REF) {
|
||
|
|
tl = ll->entry.array_ref.index;
|
||
|
|
while (tl != NULL) {
|
||
|
|
if ((tl->variant == VAR_LIST) ||
|
||
|
|
(tl->variant == EXPR_LIST) ||
|
||
|
|
(tl->variant == RANGE_LIST)) {
|
||
|
|
index_exper = tl->entry.Template.ll_ptr1;
|
||
|
|
if (index_exper == NULL ||
|
||
|
|
index_exper->variant == STAR_RANGE) {
|
||
|
|
arr[i].vector = index_exper;
|
||
|
|
arr[i].decidable = 0;
|
||
|
|
arr[i].coefs[depth] = 0;
|
||
|
|
}
|
||
|
|
else if (index_exper->variant == DDOT) {
|
||
|
|
/* we have a vector */
|
||
|
|
/* set the decidable flag to 2 */
|
||
|
|
/* and save a pointr to the vector */
|
||
|
|
/* bounds for later use */
|
||
|
|
/* we set the coef in position */
|
||
|
|
/* depth to be 1 so this is */
|
||
|
|
/* a pseudo loop. the bounds of the */
|
||
|
|
/* loops will be set */
|
||
|
|
/* as inequalities. NOTE: for stride */
|
||
|
|
/* vectors we will */
|
||
|
|
/* set the coef to be equal to thestride */
|
||
|
|
arr[i].vector = index_exper;
|
||
|
|
arr[i].decidable = 2;
|
||
|
|
arr[i].coefs[depth] = 1;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
/* this is just a standard scalar expression */
|
||
|
|
arr[i].decidable = 1;
|
||
|
|
parexp = NULL;
|
||
|
|
found = comp_offset(plist, induct_list, 1,
|
||
|
|
index_exper, &coef, &parexp);
|
||
|
|
if (found == 1)
|
||
|
|
arr[i].offset = coef;
|
||
|
|
if (found == 4) {
|
||
|
|
arr[i].offset = 0;
|
||
|
|
arr[i].parm_exp = parexp;
|
||
|
|
}
|
||
|
|
for (j = 0; j < depth; j++) {
|
||
|
|
found=new_search_symb(induct_list[j],
|
||
|
|
induct_list,index_exper, &coef, &exp);
|
||
|
|
switch (found) {
|
||
|
|
case 1: /* constant coef */
|
||
|
|
arr[i].coefs[j] = coef;
|
||
|
|
break;
|
||
|
|
case -2: /* variable coef */
|
||
|
|
arr[i].coefs_symb[j] = exp;
|
||
|
|
break;
|
||
|
|
case -1:
|
||
|
|
arr[i].decidable = 0;
|
||
|
|
case 0:
|
||
|
|
case 2:
|
||
|
|
arr[i].coefs[j] = 0;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
for (j = depth; j < MAX_NEST_DEPTH; j++)
|
||
|
|
arr[i].coefs[j] = 0;
|
||
|
|
if (arr[i].decidable == -1)
|
||
|
|
arr[i].decidable = 3;
|
||
|
|
}
|
||
|
|
tl = tl->entry.Template.ll_ptr2;
|
||
|
|
i++;
|
||
|
|
}
|
||
|
|
else { /* must be a simple 1 Dim. subscript */
|
||
|
|
arr[i].decidable = 1;
|
||
|
|
parexp = NULL;
|
||
|
|
found = comp_offset(plist, induct_list, 1, tl, &coef, &parexp);
|
||
|
|
if (found != 0)
|
||
|
|
arr[i].offset = coef;
|
||
|
|
if (found == 4) {
|
||
|
|
arr[i].offset = 0;
|
||
|
|
arr[i].parm_exp = parexp;
|
||
|
|
}
|
||
|
|
for (j = 0; j < depth; j++) {
|
||
|
|
found = new_search_symb(induct_list[j], induct_list, tl,&coef,&exp);
|
||
|
|
switch (found) {
|
||
|
|
case 1: /* constant coef */
|
||
|
|
arr[i].coefs[j] = coef;
|
||
|
|
break;
|
||
|
|
case -2: /* variable coef */
|
||
|
|
arr[i].coefs_symb[j] = exp;
|
||
|
|
break;
|
||
|
|
case -1:
|
||
|
|
arr[i].decidable = 0;
|
||
|
|
case 0:
|
||
|
|
case 2:
|
||
|
|
arr[i].coefs[j] = 0;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
for (j = depth; j < MAX_NEST_DEPTH; j++)
|
||
|
|
arr[i].coefs[j] = 0;
|
||
|
|
tl = NULL;
|
||
|
|
}
|
||
|
|
} /* end while */
|
||
|
|
} /* end if array_ref */
|
||
|
|
}
|
||
|
|
|
||
|
|
/********************************************************************/
|
||
|
|
/* search_inc_scalar(b) looks for a scalar variable in the condition*/
|
||
|
|
/* that is modified in the body of the loop. */
|
||
|
|
/* this is returned and used as an induction varialble in the */
|
||
|
|
/* routine below. There are two utility routines which recursively*/
|
||
|
|
/* search the condition tree and the body of the loop */
|
||
|
|
/********************************************************************/
|
||
|
|
int ll_search(ll, s)
|
||
|
|
PTR_LLND ll;
|
||
|
|
PTR_SYMB s;
|
||
|
|
{
|
||
|
|
if (ll == NULL)
|
||
|
|
return (0);
|
||
|
|
else {
|
||
|
|
switch (ll->variant) {
|
||
|
|
case VAR_REF:
|
||
|
|
if (ll->entry.var_ref.symbol == s)
|
||
|
|
return (1);
|
||
|
|
else
|
||
|
|
return (0);
|
||
|
|
case ARRAY_REF:
|
||
|
|
return (ll_search(ll->entry.array_ref.index, s));
|
||
|
|
case CONST_REF:
|
||
|
|
return (0);
|
||
|
|
default:
|
||
|
|
if (ll_search(ll->entry.Template.ll_ptr1, s))
|
||
|
|
return (1);
|
||
|
|
else
|
||
|
|
return (ll_search(ll->entry.Template.ll_ptr2, s));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
int body_search(b, s)
|
||
|
|
PTR_BFND b;
|
||
|
|
PTR_SYMB s;
|
||
|
|
{
|
||
|
|
PTR_BLOB x;
|
||
|
|
|
||
|
|
if (b == NULL)
|
||
|
|
return (0);
|
||
|
|
else {
|
||
|
|
switch (b->variant) {
|
||
|
|
case ASSIGN_STAT:
|
||
|
|
case M_ASSIGN_STAT:
|
||
|
|
case SUM_ACC:
|
||
|
|
case MULT_ACC:
|
||
|
|
case MAX_ACC:
|
||
|
|
case MIN_ACC:
|
||
|
|
case CAT_ACC:
|
||
|
|
case OR_ACC:
|
||
|
|
case AND_ACC:
|
||
|
|
return (ll_search(b->entry.Template.ll_ptr1, s));
|
||
|
|
case FOR_NODE:
|
||
|
|
case FORALL_NODE:
|
||
|
|
case WHILE_NODE:
|
||
|
|
x = b->entry.Template.bl_ptr1;
|
||
|
|
while (x != NULL && x->ref != b) {
|
||
|
|
if (body_search(x->ref, s))
|
||
|
|
return (1);
|
||
|
|
x = x->next;
|
||
|
|
}
|
||
|
|
return (0);
|
||
|
|
case IF_NODE:
|
||
|
|
x = b->entry.if_node.control_true;
|
||
|
|
while (x != NULL) {
|
||
|
|
if (body_search(x->ref, s))
|
||
|
|
return (1);
|
||
|
|
x = x->next;
|
||
|
|
}
|
||
|
|
x = b->entry.if_node.control_false;;
|
||
|
|
while (x != NULL) {
|
||
|
|
if (body_search(x->ref, s))
|
||
|
|
return (1);
|
||
|
|
x = x->next;
|
||
|
|
}
|
||
|
|
return (0);
|
||
|
|
default:
|
||
|
|
return (0);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
PTR_SYMB induc_search(b, ll)
|
||
|
|
PTR_BFND b;
|
||
|
|
PTR_LLND ll;
|
||
|
|
{
|
||
|
|
PTR_SYMB s;
|
||
|
|
|
||
|
|
if (ll == NULL)
|
||
|
|
return (NULL);
|
||
|
|
else {
|
||
|
|
switch (ll->variant) {
|
||
|
|
case VAR_REF:
|
||
|
|
if (body_search(b, ll->entry.var_ref.symbol))
|
||
|
|
return (ll->entry.var_ref.symbol);
|
||
|
|
else
|
||
|
|
return (NULL);
|
||
|
|
case ARRAY_REF:
|
||
|
|
return (induc_search(b, ll->entry.array_ref.index));
|
||
|
|
case CONST_REF:
|
||
|
|
return (NULL);
|
||
|
|
default:
|
||
|
|
if ((s = induc_search(b, ll->entry.Template.ll_ptr1))
|
||
|
|
!= NULL)
|
||
|
|
return (s);
|
||
|
|
else
|
||
|
|
return (induc_search(b, ll->entry.Template.ll_ptr2));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
PTR_SYMB search_inc_scalar(b)
|
||
|
|
PTR_BFND b;
|
||
|
|
{
|
||
|
|
PTR_LLND v;
|
||
|
|
|
||
|
|
v = b->entry.while_node.condition;
|
||
|
|
return (induc_search(b, v));
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/********************************************************************/
|
||
|
|
/* Make_induct_list(b,induct_list ) creates the induction list as */
|
||
|
|
/* seen from this point in the graph. the function returns the nest*/
|
||
|
|
/* level and it also side effects four other arrays: il_lo, il_hi */
|
||
|
|
/* which describe the low and hi bounds for the list and the vectors*/
|
||
|
|
/* stride and is_forall. In the case of a stride component that is */
|
||
|
|
/* not one, we normalize the induction list arrays as follows. */
|
||
|
|
/* if the stride is not a constant il_lo and il_hi is set undecidble*/
|
||
|
|
/* otherwise il_lo is set to 0 and il_hi becomes (il_hi-il_lo)/str */
|
||
|
|
/* The way this works: it goes up the tree and fills in the loop */
|
||
|
|
/* index variables from the top down to this point. */
|
||
|
|
/* In the case of WHILE loops and C for loops as well as while loops*/
|
||
|
|
/* we must try to identify an induction */
|
||
|
|
/* variable. We will do this by searching the test condition for */
|
||
|
|
/* first scalar variable. This is not accurate. What we should do */
|
||
|
|
/* is search for a scalar variable that changes value in the body of*/
|
||
|
|
/* the iteration, but that is not done yet. I will do it later. */
|
||
|
|
/********************************************************************/
|
||
|
|
int make_induct_list(b, induct_list, il_lo, il_hi)
|
||
|
|
PTR_BFND b;
|
||
|
|
PTR_SYMB induct_list[];
|
||
|
|
struct subscript il_lo[];
|
||
|
|
struct subscript il_hi[];
|
||
|
|
{
|
||
|
|
int i, j, found, coef;
|
||
|
|
PTR_LLND p, lv, rv, q, pexp;
|
||
|
|
PTR_REFL plist;
|
||
|
|
PTR_BFND proc;
|
||
|
|
|
||
|
|
if ((b == NULL) || (b->variant == GLOBAL)) {
|
||
|
|
return (0);
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
for (j = 0; j < MAX_NEST_DEPTH; j++) {
|
||
|
|
il_lo[j].decidable = -1;
|
||
|
|
il_lo[j].parm_exp = NULL;
|
||
|
|
il_lo[j].offset = 0;
|
||
|
|
il_lo[j].vector = NULL;
|
||
|
|
for (i = 0; i < MAX_NEST_DEPTH; i++) {
|
||
|
|
il_lo[j].coefs[i] = 0;
|
||
|
|
il_lo[j].coefs_symb[i] = NULL;
|
||
|
|
}
|
||
|
|
il_hi[j].decidable = -1;
|
||
|
|
il_hi[j].parm_exp = NULL;
|
||
|
|
il_hi[j].offset = 0;
|
||
|
|
il_hi[j].vector = NULL;
|
||
|
|
for (i = 0; i < MAX_NEST_DEPTH; i++) {
|
||
|
|
il_hi[j].coefs[i] = 0;
|
||
|
|
il_hi[j].coefs_symb[i] = NULL;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
/* first generate the list of parameters of the function */
|
||
|
|
proc = b;
|
||
|
|
while (proc != NULL && (proc->variant != PROC_HEDR) &&
|
||
|
|
(proc->variant != FUNC_HEDR) &&
|
||
|
|
(proc->variant != PROG_HEDR))
|
||
|
|
proc = proc->control_parent;
|
||
|
|
if (proc == NULL)
|
||
|
|
return 0;
|
||
|
|
if (proc->entry.Template.sets == NULL)
|
||
|
|
plist = NULL;
|
||
|
|
else
|
||
|
|
plist = proc->entry.Template.sets->out_use;
|
||
|
|
|
||
|
|
/* now recursive apply procedure */
|
||
|
|
i = make_induct_list(b->control_parent, induct_list, il_lo, il_hi);
|
||
|
|
if ((b->variant == FOR_NODE) ||
|
||
|
|
(b->variant == FORALL_NODE)) {
|
||
|
|
if (i > MAX_NEST_DEPTH) {
|
||
|
|
fprintf(stderr, " nest too deep ! \n");
|
||
|
|
return (0);
|
||
|
|
}
|
||
|
|
if (b->entry.for_node.control_var == NULL) {
|
||
|
|
/* must be a C for loop */
|
||
|
|
lv = b->entry.Template.ll_ptr1; /* exp list */
|
||
|
|
if (lv == NULL) {
|
||
|
|
/* try to go for the increment exp */
|
||
|
|
lv = b->entry.Template.ll_ptr3;
|
||
|
|
rv = lv->entry.Template.ll_ptr1; /* op */
|
||
|
|
lv = rv->entry.Template.ll_ptr1;
|
||
|
|
induct_list[i] =
|
||
|
|
lv->entry.Template.symbol;
|
||
|
|
lv = NULL;
|
||
|
|
il_lo[i].decidable = 0;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
rv = lv->entry.Template.ll_ptr1; /* asign op */
|
||
|
|
lv = rv->entry.Template.ll_ptr1; /* var ref */
|
||
|
|
il_lo[i].decidable = 1;
|
||
|
|
induct_list[i] = lv->entry.Template.symbol;
|
||
|
|
lv = rv->entry.Template.ll_ptr2; /* start val */
|
||
|
|
}
|
||
|
|
is_forall[i] = 0;
|
||
|
|
/* now do hi bound for C case */
|
||
|
|
rv = b->entry.Template.ll_ptr2; /* 2nd expr */
|
||
|
|
rv = rv->entry.Template.ll_ptr1;
|
||
|
|
rv = rv->entry.Template.ll_ptr2;
|
||
|
|
stride[i] = 1; /* these two lines are bogus */
|
||
|
|
il_hi[i].decidable = 1;
|
||
|
|
}
|
||
|
|
else { /* fortran case */
|
||
|
|
induct_list[i] = b->entry.for_node.control_var;
|
||
|
|
if (b->variant == FORALL_NODE)
|
||
|
|
is_forall[i] = 1;
|
||
|
|
else
|
||
|
|
is_forall[i] = 0;
|
||
|
|
/* now create low and hi bounds */
|
||
|
|
p = b->entry.for_node.range;
|
||
|
|
if (p->variant != DDOT)
|
||
|
|
fprintf(stderr, "bad range node\n");
|
||
|
|
lv = p->entry.Template.ll_ptr1;
|
||
|
|
rv = p->entry.Template.ll_ptr2;
|
||
|
|
il_lo[i].decidable = 1;
|
||
|
|
il_hi[i].decidable = 1;
|
||
|
|
stride[i] = 1;
|
||
|
|
if ((lv->variant == DDOT) ||
|
||
|
|
(b->entry.for_node.increment != NULL)) {
|
||
|
|
/* we have a stride term! */
|
||
|
|
if (b->entry.for_node.increment != NULL)
|
||
|
|
q = b->entry.for_node.increment;
|
||
|
|
else {
|
||
|
|
q = rv;
|
||
|
|
rv = lv->entry.Template.ll_ptr2;
|
||
|
|
lv = lv->entry.Template.ll_ptr1;
|
||
|
|
}
|
||
|
|
/* we currently only support constant strides */
|
||
|
|
/* this can be improved to general expressions */
|
||
|
|
found = comp_offset(plist, induct_list, 1, q, &coef, &pexp);
|
||
|
|
if (found != 3)
|
||
|
|
stride[i] = coef;
|
||
|
|
if ((found == 4) || (found == 3) || (stride[i] == 0)) {
|
||
|
|
il_lo[i].decidable = 0;
|
||
|
|
il_hi[i].decidable = 0;
|
||
|
|
stride[i] = 1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
} /* end fortran case */
|
||
|
|
pexp = NULL;
|
||
|
|
found = comp_offset(plist, induct_list, 1, lv, &coef, &pexp);
|
||
|
|
if (found >= 3)
|
||
|
|
il_lo[i].decidable = 0;
|
||
|
|
if (found == 4)
|
||
|
|
il_lo[i].parm_exp = pexp;
|
||
|
|
else
|
||
|
|
il_lo[i].parm_exp = NULL;
|
||
|
|
if (found != 0)
|
||
|
|
il_lo[i].offset = coef;
|
||
|
|
pexp = NULL;
|
||
|
|
found = comp_offset(plist, induct_list, 1, rv, &coef, &pexp);
|
||
|
|
if (found >= 3)
|
||
|
|
il_hi[i].decidable = 0;
|
||
|
|
if (found == 4)
|
||
|
|
il_hi[i].parm_exp = pexp;
|
||
|
|
else
|
||
|
|
il_hi[i].parm_exp = NULL;
|
||
|
|
if (found != 0)
|
||
|
|
il_hi[i].offset = coef;
|
||
|
|
for (j = 0; j < i; j++) {
|
||
|
|
found = search_symb(0, induct_list[j], lv, &coef);
|
||
|
|
if (found >= 1)
|
||
|
|
il_lo[i].coefs[j] = coef;
|
||
|
|
else if (found == 0)
|
||
|
|
il_lo[i].coefs[j] = 0;
|
||
|
|
else if ((found == -1) ||
|
||
|
|
(found == -2))
|
||
|
|
il_lo[i].decidable = 0;
|
||
|
|
|
||
|
|
found = search_symb(0, induct_list[j], rv, &coef);
|
||
|
|
if (found >= 1)
|
||
|
|
il_hi[i].coefs[j] = coef;
|
||
|
|
else if (found == 0)
|
||
|
|
il_hi[i].coefs[j] = 0;
|
||
|
|
else if ((found == -1) ||
|
||
|
|
(found == -2))
|
||
|
|
il_hi[i].decidable = 0;
|
||
|
|
}
|
||
|
|
/* now normalize for stride */
|
||
|
|
if (stride[i] != 1) {
|
||
|
|
il_hi[i].offset =
|
||
|
|
(il_hi[i].offset - il_lo[i].offset) / stride[i];
|
||
|
|
il_lo[i].offset = 0;
|
||
|
|
for (j = 0; j < i; j++) {
|
||
|
|
il_hi[i].coefs[j] =
|
||
|
|
(il_hi[i].coefs[j] - il_lo[i].coefs[j]) / stride[i];
|
||
|
|
il_lo[i].coefs[j] = 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return (i + 1);
|
||
|
|
}
|
||
|
|
else if (b->variant == WHILE_NODE) {
|
||
|
|
if (i > MAX_NEST_DEPTH) {
|
||
|
|
fprintf(stderr, " nest too deep ! \n");
|
||
|
|
return (0);
|
||
|
|
}
|
||
|
|
induct_list[i] = search_inc_scalar(b);;
|
||
|
|
/* now create low and hi bounds */
|
||
|
|
il_lo[i].decidable = 0;
|
||
|
|
il_hi[i].decidable = 0;
|
||
|
|
for (j = 0; j < i; j++) {
|
||
|
|
il_lo[i].coefs[j] = 0;
|
||
|
|
il_hi[i].coefs[j] = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
return (i + 1);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
return (i);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
/* make_vect_range takes a pointer to a .. node */
|
||
|
|
/* for a vector reference and builds two */
|
||
|
|
/* subscript records. One for the lo end the */
|
||
|
|
/* other for the hi end. induct_list is */
|
||
|
|
/* the current active induction list. */
|
||
|
|
void make_vect_range(depth, p, induct_list, lo, hi)
|
||
|
|
PTR_LLND p;
|
||
|
|
PTR_SYMB induct_list[];
|
||
|
|
struct subscript *lo;
|
||
|
|
struct subscript *hi;
|
||
|
|
int depth;
|
||
|
|
{
|
||
|
|
int i, j, found, coef;
|
||
|
|
PTR_LLND lv, rv, plv, prv;
|
||
|
|
PTR_REFL plist; /* this is a dummy. need to add this as
|
||
|
|
* parameter */
|
||
|
|
if (p->variant != DDOT)
|
||
|
|
fprintf(stderr, "bad range node in vector\n");
|
||
|
|
for (i = 0; i < MAX_NEST_DEPTH; i++) {
|
||
|
|
lo->coefs[i] = 0;
|
||
|
|
hi->coefs[i] = 0;
|
||
|
|
}
|
||
|
|
lo->offset = 0;
|
||
|
|
hi->offset = 0;
|
||
|
|
lv = p->entry.Template.ll_ptr1;
|
||
|
|
rv = p->entry.Template.ll_ptr2;
|
||
|
|
lo->decidable = 1;
|
||
|
|
plist = NULL; /* ignore parametes in vector range for now */
|
||
|
|
found = comp_offset(plist, induct_list, 1, lv, &coef, &plv);
|
||
|
|
if (found >= 3)
|
||
|
|
lo->decidable = 0;
|
||
|
|
if (found != 0)
|
||
|
|
lo->offset = coef;
|
||
|
|
hi->decidable = 1;
|
||
|
|
found = comp_offset(plist, induct_list, 1, rv, &coef, &prv);
|
||
|
|
if (found >= 3)
|
||
|
|
hi->decidable = 0;
|
||
|
|
if (found != 0)
|
||
|
|
hi->offset = coef;
|
||
|
|
for (j = 0; j < i; j++) {
|
||
|
|
found = search_symb(0, induct_list[j], lv, &coef);
|
||
|
|
if (found >= 1)
|
||
|
|
lo->coefs[j] = coef;
|
||
|
|
else if (found == 0)
|
||
|
|
lo->coefs[j] = 0;
|
||
|
|
else if ((found == -1) ||
|
||
|
|
(found == -2))
|
||
|
|
lo->decidable = 0;
|
||
|
|
|
||
|
|
found = search_symb(0, induct_list[j], rv, &coef);
|
||
|
|
if (found >= 1)
|
||
|
|
hi->coefs[j] = coef;
|
||
|
|
else if (found == 0)
|
||
|
|
hi->coefs[j] = 0;
|
||
|
|
else if ((found == -1) ||
|
||
|
|
(found == -2))
|
||
|
|
hi->decidable = 0;
|
||
|
|
}
|
||
|
|
lo->offset = -lo->offset;
|
||
|
|
for (i = 0; i < MAX_NEST_DEPTH; i++) {
|
||
|
|
lo->coefs[i] = -lo->coefs[i];
|
||
|
|
}
|
||
|
|
lo->coefs[depth] = 1; /* perhaps repalce by stride ? */
|
||
|
|
hi->coefs[depth] = -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
/************************************************/
|
||
|
|
/* standard gcd routines: gcd of two vectors. */
|
||
|
|
/* zeros are not counted. */
|
||
|
|
/************************************************/
|
||
|
|
int sgcd(a, b)
|
||
|
|
int a, b;
|
||
|
|
{
|
||
|
|
int tmp;
|
||
|
|
|
||
|
|
if (a < 0)
|
||
|
|
a = -a;
|
||
|
|
if (b < 0)
|
||
|
|
b = -b;
|
||
|
|
if (a > b) {
|
||
|
|
tmp = b;
|
||
|
|
b = a;
|
||
|
|
a = tmp;
|
||
|
|
}
|
||
|
|
if (a == 0)
|
||
|
|
return (b);
|
||
|
|
else
|
||
|
|
return (sgcd(a, b % a));
|
||
|
|
}
|
||
|
|
|
||
|
|
int gcd(d, x)
|
||
|
|
int d;
|
||
|
|
int x[];
|
||
|
|
{
|
||
|
|
int i, g;
|
||
|
|
g = 0;
|
||
|
|
for (i = 0; i < d; i++) {
|
||
|
|
g = sgcd(g, x[i]);
|
||
|
|
}
|
||
|
|
return (g);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
void clean_loops(b)
|
||
|
|
PTR_BFND b;
|
||
|
|
{
|
||
|
|
PTR_BLOB x;
|
||
|
|
|
||
|
|
if (b == NULL)
|
||
|
|
return ;
|
||
|
|
else {
|
||
|
|
switch (b->variant) {
|
||
|
|
case GLOBAL:
|
||
|
|
case PROG_HEDR:
|
||
|
|
case PROC_HEDR:
|
||
|
|
case FUNC_HEDR:
|
||
|
|
case FOR_NODE:
|
||
|
|
case FORALL_NODE:
|
||
|
|
case WHILE_NODE:
|
||
|
|
x = b->entry.Template.bl_ptr1;
|
||
|
|
while (x != NULL && x->ref != b) {
|
||
|
|
clean_loops(x->ref);
|
||
|
|
if (x->next != NULL &&
|
||
|
|
x->next->ref == b)
|
||
|
|
x->next = NULL;
|
||
|
|
x = x->next;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case IF_NODE:
|
||
|
|
x = b->entry.if_node.control_true;
|
||
|
|
while (x != NULL) {
|
||
|
|
clean_loops(x->ref);
|
||
|
|
if (x->next != NULL &&
|
||
|
|
x->next->ref == b)
|
||
|
|
x->next = NULL;
|
||
|
|
x = x->next;
|
||
|
|
}
|
||
|
|
x = b->entry.if_node.control_false;;
|
||
|
|
while (x != NULL) {
|
||
|
|
clean_loops(x->ref);
|
||
|
|
if (x->next != NULL &&
|
||
|
|
x->next->ref == b)
|
||
|
|
x->next = NULL;
|
||
|
|
x = x->next;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|