/*********************************************************************/ /* pC++/Sage++ Copyright (C) 1993 */ /* Indiana University University of Oregon University of Rennes */ /*********************************************************************/ #include #include #include "db.h" #include "compatible.h" #ifdef SYS5 #include #else #include #endif #ifdef __SPF extern void addToCollection(const int line, const char *file, void *pointer, int type); #endif static PTR_BFND current_par_loop = NULL; static char *depstrs[] = { "flow","anti","output","huh??","got me?"}; static char *dirstrs[] = { " ", "= ", "- ", "0-", "+ ", "0+", ". ", "+-"}; extern PCF UnparseBfnd[]; extern PCF UnparseLlnd[]; extern PTR_FILE cur_file; /* Forward definitions */ static PTR_BLOB1 Nsearch_deps(); static void subtract_list(); static int same_loop(); void search_and_replace_call(); extern void normal_form(); extern int identical(); PTR_LLND search_call(ll, s) PTR_LLND ll; PTR_SYMB *s; { PTR_LLND t; *s = NULL; if(ll == NULL) return(NULL); if(ll->variant == FUNC_CALL){ *s = ll->entry.Template.symbol; return(ll->entry.Template.ll_ptr1); } else{ t = search_call(ll->entry.Template.ll_ptr1,s); if(t != NULL) return(t); return(search_call(ll->entry.Template.ll_ptr2,s)); } } PTR_REFL build_refl(b,s) PTR_BFND b; PTR_LLND s; { PTR_REFL p,h,l,alloc_ref(); h = NULL; l = NULL; while(s!= NULL){ p = alloc_ref(b,s->entry.Template.ll_ptr1); if(p != NULL){ if(h == NULL){ h = p;} if(l != NULL) l->next = p; l = p; } s = s->entry.Template.ll_ptr2; } return(h); } /* find loop bounds takes a bif pointer b and addresses of */ /* three other pointers low, hi, inc and computes loop bounds */ /* and returns 1 if it succeds in finding these in terms of */ /* constants, parameters and external varaibles and returns */ /* 0 if it failed. */ int find_loop_bounds(b,low,hi,inc) PTR_BFND b; PTR_LLND *low, *hi, *inc; {return (0);} /* bind call site info will take a pointer to a call statement and */ /* return a expression list of the used and modified sets in terms */ /* of the actual parameters. */ void bind_call_site_info(b, used, modified) PTR_BFND b; PTR_LLND *used, *modified; { PTR_LLND funargs, formal_used, formal_modified; PTR_SYMB fun, s,formal_args[50]; PTR_BFND fun_bif; /* PTR_BLOB bl; */ PTR_LLND u, m, explst; int i, num_formal_args; PTR_LLND called_with[50]; PTR_LLND copy_llnd(); PTR_BFND find_fun_by_name(); int fun_found ; *used = NULL; *modified = NULL; fun = NULL; fun_found = 0; formal_used = NULL; formal_modified = NULL; formal_args[0] = NULL; num_formal_args = 0;; if(b == NULL) return; if(b->variant == PROC_STAT){ funargs = b->entry.Template.ll_ptr1; fun = b->entry.Template.symbol; } else if(b->variant == ASSIGN_STAT){ funargs = search_call(b->entry.Template.ll_ptr2,&fun); } else if(b->variant == EXPR_STMT_NODE){ funargs = search_call(b->entry.Template.ll_ptr1,&fun); } /* if(fun != NULL) fprintf(stderr, "funargs = %s\n", (UnparseBfnd[cur_file->lang])(funargs)); */ else { fprintf(stderr, "serch_call error. node is %s", (UnparseBfnd[cur_file->lang])(b)); fprintf(stderr, "node type is %d\n",b->variant); return; } if(fun == NULL) return; if(funargs == NULL) return; fun_bif = find_fun_by_name(fun->ident); /*no longer need loop search*/ if(fun_bif == NULL){ fprintf(stderr, "find fun_by_name failed %s\n",fun->ident); return; } else if (strcmp(fun_bif->entry.Template.symbol->ident,fun->ident)){ fprintf(stderr, "find fun by name returned wrong fun\n"); return; } if(fun_bif->variant == PROC_HEDR || fun_bif->variant == FUNC_HEDR){ if(!strcmp(fun_bif->entry.Template.symbol->ident,fun->ident)){ fun_found = 1; s = fun_bif->entry.Template.symbol; s = s->entry.proc_decl.in_list; while(s != NULL){ /* gather formal args in formal_args */ formal_args[num_formal_args++] = s; s = s->entry.var_decl.next_in; } explst = fun_bif->entry.Template.ll_ptr3; if(explst == NULL) return; if(explst->entry.Template.ll_ptr2 == NULL){ /* only first pass analysis done */ formal_used = explst->entry.Template.ll_ptr1; /* bif graph */ } else formal_used = explst->entry.Template.ll_ptr2; explst = fun_bif->entry.Template.ll_ptr2; if(explst == NULL) return; if(explst->entry.Template.ll_ptr2 == NULL){ /* only first pass analysis done */ formal_modified = explst->entry.Template.ll_ptr1; /* bif graph*/ } else formal_modified = explst->entry.Template.ll_ptr2; } } if(fun_found == 0){ fprintf(stderr, "could not locate source for function %s\n",fun->ident); return; } if(num_formal_args == 0) return; u = copy_llnd(formal_used); m = copy_llnd(formal_modified); for(i = 0; i < num_formal_args; i++){ /* gather actual args in called_with*/ if(funargs == NULL){ printf("ERROR: function not called with enough arguments\n"); exit(0); } called_with[i] = copy_llnd(funargs->entry.Template.ll_ptr1); funargs = funargs->entry.Template.ll_ptr2; } search_and_replace_call(&u,num_formal_args,formal_args,called_with); search_and_replace_call(&m,num_formal_args,formal_args,called_with); *used = u; *modified = m; /* fprintf(stderr, "formal_used are:\n"); fprintf(stderr, "%s",UnparseLlnd[cur_file->lang](formal_used)); fprintf(stderr, "actual used are:\n"); fprintf(stderr, "%s",UnparseLlnd[cur_file->lang](u)); fprintf(stderr, "formal_modified are:\n"); fprintf(stderr, "%s",UnparseLlnd[cur_file->lang](formal_modified)); fprintf(stderr, "actual modified are:\n"); fprintf(stderr, "%s",UnparseLlnd[cur_file->lang](m)); fprintf(stderr, "called with:\n"); for(i = 0; i < num_formal_args; i++) fprintf(stderr, " %s,",UnparseLlnd[cur_file->lang](called_with[i])); fprintf(stderr, "\n"); if(formal_args[0] == NULL) return; fprintf(stderr, "formal args are:\n"); for(i = 0; i < num_formal_args; i++) fprintf(stderr, " %s,",formal_args[i]->ident); fprintf(stderr, "\n"); */ } int get_fargs_index(s,n,fargs) PTR_SYMB s; int n; PTR_SYMB fargs[]; { int i; for(i = 0; i < n; i++) if(fargs[i] == s) return(i); return(-1); } void add_offset(offset,term) PTR_LLND offset, *term; { PTR_LLND p,q,r, make_llnd(), copy_llnd(); if(offset == NULL){ fprintf(stderr, "bad offset in add_offset\n"); return; } if(term == NULL){ fprintf(stderr, "badd term in add_offset\n"); return; } if(*term == NULL){ fprintf(stderr, " null term in add_offset\n"); } if(*term == NULL || ( offset->variant == DDOT && *term != NULL && (*term)->variant == DDOT)){ q = make_llnd(cur_file, STAR_RANGE,NULL,NULL,NULL); *term = q; } else if((*term)->variant == STAR_RANGE){ /* term is of the form x[:] and no offset will help */ } else if(offset->variant == STAR_RANGE){ /* MANNHO add 9/10 */ *term = offset; } else if((*term)->variant == DDOT){ PTR_LLND offset1, offset2; offset1 = copy_llnd(offset); p = (*term)->entry.Template.ll_ptr1; q = make_llnd(cur_file, ADD_OP,p,offset1,NULL); /* MANNHO delete if(cur_file->lang == ForSrc){ p = make_llnd(cur_file, INT_VAL,NULL,NULL,NULL); p->entry.ival = 1; q = make_llnd(cur_file, SUBT_OP,q,p,NULL); } */ normal_form(&q); /* normal_form(&q); */ (*term)->entry.Template.ll_ptr1 = q; p = (*term)->entry.Template.ll_ptr2; offset2 = copy_llnd(offset); q = make_llnd(cur_file, ADD_OP,p,offset2,NULL); /* MANNHO delete if(cur_file->lang == ForSrc){ p = make_llnd(cur_file, INT_VAL,NULL,NULL,NULL); p->entry.ival = 1; q = make_llnd(cur_file, SUBT_OP,q,p,NULL); } */ /* normal_form(&q); */ normal_form(&q); (*term)->entry.Template.ll_ptr2 = q; } else if(offset->variant == DDOT){ r = copy_llnd(*term); offset = copy_llnd(offset); p = offset->entry.Template.ll_ptr1; q = make_llnd(cur_file, ADD_OP,p,r,NULL); offset->entry.Template.ll_ptr1 = q; p = offset->entry.Template.ll_ptr2; q = make_llnd(cur_file, ADD_OP,p,r,NULL); offset->entry.Template.ll_ptr2 = q; *term = offset; } else{ offset = copy_llnd(offset); q = make_llnd(cur_file, ADD_OP,*term,offset,NULL); *term = q; } } PTR_LLND get_array_dim_decl(AR) /* MANNHO add */ PTR_LLND AR; /* ARRAY_REF */ { PTR_LLND RL, R_L = NULL, ll0, ll1; PTR_TYPE TY; PTR_LLND copy_llnd(), make_llnd(); TY = AR->entry.Template.symbol->type; switch (TY->variant) { case T_ARRAY : /* MANNHO mod */ R_L = TY->entry.ar_decl.ranges; if (R_L->variant != EXPR_LIST) R_L = R_L->entry.Template.ll_ptr1; break; case T_POINTER : R_L = NULL; break; } if (R_L == NULL) return(NULL); RL = R_L = copy_llnd(R_L); while (RL) { ll1 = RL->entry.Template.ll_ptr1; if (ll1->variant != DDOT) { if (cur_file->lang == ForSrc) ll0 = make_llnd(cur_file, INT_VAL, NULL, NULL, 1); else ll0 = make_llnd(cur_file, INT_VAL, NULL, NULL, 0); RL->entry.Template.ll_ptr1 = make_llnd(cur_file, DDOT, ll0, ll1, NULL); } RL = RL->entry.Template.ll_ptr2; } return (R_L); } /* u is a reference to an expression describing the result of an action */ /* by a call to the function. fargs is the associated set of formal */ /* formal parameters. call is the actual values passed to the formal */ /* parameter. search_and_replace modifies u so that it reflects the */ /* the action in terms of the actual parameters. */ void search_and_replace_call(u,n,fargs,call) PTR_LLND *u; int n; PTR_SYMB fargs[]; PTR_LLND call[]; { int i; PTR_LLND v,index,a,b, b1, b2; PTR_LLND make_llnd(), copy_llnd(), linearize_array_range(); PTR_LLND get_array_dim_decl(); if (*u == NULL) return ; /* *u is the result of the call in terms of the formal params */ switch((*u)->variant){ case VAR_REF: /* find the position of *u in the parameter list */ i = get_fargs_index((*u)->entry.Template.symbol,n,fargs); if (i<0) return ; if(call[i]->variant == ADDRESS_OP) v = call[i]->entry.Template.ll_ptr1; else v = call[i]; *u = copy_llnd(v); break; case ARRAY_REF: i = get_fargs_index((*u)->entry.Template.symbol,n,fargs); if(i < 0) return ; v = call[i]; /* v is the expression that is passed in position i */ if(v->variant == VAR_REF){ (*u)->entry.Template.symbol = v->entry.Template.symbol; search_and_replace_call(&((*u)->entry.Template.ll_ptr1), n,fargs,call); search_and_replace_call(&((*u)->entry.Template.ll_ptr2), n,fargs,call); } else if(cur_file->lang != ForSrc && v->variant == ARRAY_REF){ /* if v has dim 1 greater than *u */ index = (*u)->entry.Template.ll_ptr1; (*u)->entry.Template.symbol = v->entry.Template.symbol; search_and_replace_call(&index,n,fargs,call); index = v->entry.Template.ll_ptr1; while(index->entry.Template.ll_ptr2 != NULL) index = index->entry.Template.ll_ptr2; index->entry.Template.ll_ptr2 = (*u)->entry.Template.ll_ptr1; (*u)->entry.Template.ll_ptr1 = v->entry.Template.ll_ptr1; } else if(v->variant == ADDRESS_OP){ /* something like &(x[i]) */ a = v->entry.Template.ll_ptr1; /* the x[i] part */ if(a->variant == EXPR_LIST) a = a->entry.Template.ll_ptr1; (*u)->entry.Template.symbol=a->entry.Template.symbol; if(a->variant == VAR_REF ){ search_and_replace_call(&((*u)->entry.Template.ll_ptr1), n,fargs,call); } else if(a->variant == ARRAY_REF){ PTR_LLND second_index; /* we are adding the offset from &(x[i]) to y[10:2] */ /* u is a *pointer to the summary data and a is a pointer to */ /* the actual argument. make u look like a */ search_and_replace_call(&((*u)->entry.Template.ll_ptr1), n,fargs,call); b = (*u)->entry.Template.ll_ptr1; /* range list */ index = a->entry.Template.ll_ptr1; /*range list */ if(index != NULL) second_index = index->entry.Template.ll_ptr2; else second_index = NULL; if(index == NULL){ } else if(b == NULL){ (*u)->entry.Template.ll_ptr1 = copy_llnd(index); } else { b1 = b->entry.Template.ll_ptr1; b2 = b->entry.Template.ll_ptr2; b->entry.Template.ll_ptr1 = copy_llnd(index->entry.Template.ll_ptr1); b->entry.Template.ll_ptr2 = copy_llnd(second_index); while (b->entry.Template.ll_ptr2 != NULL) b = b->entry.Template.ll_ptr2; add_offset(b1, &(b->entry.Template.ll_ptr1)); b->entry.Template.ll_ptr2 = b2; } } else fprintf(stderr, "a variant is %d\n",a->variant); } else if (cur_file->lang == ForSrc && v->variant == ARRAY_REF) { /* u is a *pointer to a copy of the summary data and v points to */ /* the passed argument. make u look like v. */ int udim, adim; a = v; if(a->variant == EXPR_LIST) a = a->entry.Template.ll_ptr1; if(a->variant == VAR_REF ){ (*u)->entry.Template.symbol=a->entry.Template.symbol; /* u now has the symbol of v, now do the substitution on the subscripts */ search_and_replace_call(&((*u)->entry.Template.ll_ptr1), n,fargs,call); } else if(a->variant == ARRAY_REF){ PTR_LLND size,ls,rs,adec; /* we are adding the offset from &(a[i]) to u[10:2] */ /* u is a *pointer to the summary data and a is a pointer to */ /* the actual argument. make u look like a. first fix the index */ /* terms in u */ search_and_replace_call(&((*u)->entry.Template.ll_ptr1), n,fargs,call); /* next get the dimensions of these array references. */ /* let b be the index expression range list for *u. */ udim = (*u)->entry.Template.symbol->type->entry.ar_decl.num_dimensions; adim = a->entry.Template.symbol->type->entry.ar_decl.num_dimensions; size = get_array_dim_decl(*u); /* MANNHO mod */ adec = get_array_dim_decl(a); if(adec->variant == EXPR_LIST || adec->variant == RANGE_LIST) adec = adec->entry.Template.ll_ptr1; search_and_replace_call(&size,n,fargs,call); (*u)->entry.Template.symbol=a->entry.Template.symbol; /* we now must linearize the segments described by *u and */ /* then add the offset provided by a */ b = (*u)->entry.Template.ll_ptr1; /* range list */ index = a->entry.Template.ll_ptr1; /*range list */ if(index == NULL && udim == adim){ /* *u already has the correct form */ } else if(index == NULL && adim < udim){ /* if adim = 1 and udim is bigger */ b = linearize_array_range(b,udim,size); ls = b->entry.Template.ll_ptr1->entry.Template.ll_ptr1; rs = b->entry.Template.ll_ptr1->entry.Template.ll_ptr2; add_offset(adec->entry.Template.ll_ptr1, &(b->entry.Template.ll_ptr1)); b->entry.Template.ll_ptr2 = NULL; /* fprintf(stderr," %s ",UnparseLlnd[cur_file->lang](b)); */ } else if(b == NULL){ (*u)->entry.Template.ll_ptr1 = copy_llnd(index); } else if(index == NULL && adim > udim){ int ii; PTR_LLND c; c = make_llnd(cur_file, INT_VAL,NULL,NULL,NULL); c->entry.ival = 1; for(ii = 0; ii < (adim-udim); ii++){ b->entry.Template.ll_ptr2 = make_llnd(cur_file, EXPR_LIST,copy_llnd(c),NULL,NULL); b = b->entry.Template.ll_ptr2; } b->entry.Template.ll_ptr2 = NULL; } else { b = linearize_array_range(b,udim,size); add_offset(index->entry.Template.ll_ptr1, &(b->entry.Template.ll_ptr1)); if(index->entry.Template.ll_ptr2 == NULL) b->entry.Template.ll_ptr2 = NULL; else{ if(index->entry.Template.ll_ptr2 !=NULL && index->entry.Template.ll_ptr2->variant != EXPR_LIST) b->entry.Template.ll_ptr2 = make_llnd(cur_file, EXPR_LIST,index->entry.Template.ll_ptr2,NULL,NULL); else b->entry.Template.ll_ptr2 = index->entry.Template.ll_ptr2; } } } else fprintf(stderr, "a variant is %d\n",a->variant); } else{ /* something like p+3 for a pointer p */ fprintf(stderr, "a strange pointer case in ser. and repl.\n"); } break; default: /* an expression */ search_and_replace_call(&((*u)->entry.Template.ll_ptr1), n,fargs,call); search_and_replace_call(&((*u)->entry.Template.ll_ptr2), n,fargs,call);; } } /* MANNHO delete whole this procedure PTR_LLND get_leading_arr_dim(s) PTR_SYMB s; { PTR_LLND x, copy_llnd(); x = s->type->entry.ar_decl.ranges; if(x->variant == ARRAY_REF) x = x->entry.Template.ll_ptr1; if(x->variant == EXPR_LIST) x = x->entry.Template.ll_ptr1; return(copy_llnd(x)); } */ void make_zero_base(ref, decl) /* MANNHO add */ PTR_LLND ref, decl; { PTR_LLND ref_index, ref_low, ref_up, decl_low, dlow; PTR_LLND make_llnd(), copy_llnd(); while (ref) { ref_index = ref->entry.Template.ll_ptr1; decl_low =decl->entry.Template.ll_ptr1->entry.Template.ll_ptr1; if (ref_index->variant == DDOT) { ref_low = ref_index->entry.Template.ll_ptr1; ref_up = ref_index->entry.Template.ll_ptr2; if(ref_low != NULL && decl_low != NULL){ dlow = copy_llnd(decl_low); ref_low = make_llnd(cur_file, SUBT_OP, ref_low, dlow, NULL); } if(ref_up != NULL && decl_low != NULL){ dlow = copy_llnd(decl_low); ref_up = make_llnd(cur_file, SUBT_OP, ref_up, dlow, NULL); } ref_index->entry.Template.ll_ptr1 = ref_low; ref_index->entry.Template.ll_ptr2 = ref_up; } else if(decl_low != NULL && ref_index->variant != STAR_RANGE){ dlow = copy_llnd(decl_low); ref_index = make_llnd(cur_file, SUBT_OP, ref_index, dlow, NULL); ref->entry.Template.ll_ptr1 = ref_index; } ref = ref->entry.Template.ll_ptr2; decl = decl->entry.Template.ll_ptr2; } } /* linearize_array_range takes a range list and returns a range */ /* list consiting of a 1-D ddot discription of the range */ PTR_LLND linearize_array_range(rl,dim,size) /* MANNHO mod */ PTR_LLND rl; /* a range list of expressions and ddots */ int dim; PTR_LLND size; /* size is the declared dimension of the parameter */ { PTR_LLND RL, sz1, s; PTR_LLND size_upto, size_up, addend, low, up, one; PTR_LLND index, index_low, index_up; int shift_needed; PTR_LLND make_llnd(), copy_llnd(); make_zero_base(rl, size); s = size; shift_needed = 0; while(s != NULL){ sz1 = s->entry.Template.ll_ptr1; if(sz1->entry.Template.ll_ptr1 != NULL && (( sz1->entry.Template.ll_ptr1->variant != CONST_REF && sz1->entry.Template.ll_ptr1->variant != INT_VAL) || sz1->entry.Template.ll_ptr1->entry.ival != 1)){ printf(" ival is %d\n",sz1->entry.Template.ll_ptr1->entry.ival); shift_needed = 1; } s = s->entry.Template.ll_ptr2; } s = copy_llnd(size); make_zero_base(size, s); if(shift_needed) s = copy_llnd(size); /* fprintf(stderr, " rl = %s",UnparseLlnd[cur_file->lang](rl)); fprintf(stderr, " size = %s",UnparseLlnd[cur_file->lang](size)); */ size_upto = NULL; low = NULL; up = NULL; RL = rl; while (RL) { index = RL->entry.Template.ll_ptr1; sz1 = size->entry.Template.ll_ptr1; if (index->variant == DDOT) { index_low = index->entry.Template.ll_ptr1; index_up = index->entry.Template.ll_ptr2; } else { index_low = index; index_up = copy_llnd(index); } if(index->variant == STAR_RANGE){ index->variant = DDOT; index_low = sz1->entry.Template.ll_ptr1; index_up = sz1->entry.Template.ll_ptr2; } if (low == NULL) { /* 1st index */ low = index_low; up = index_up; } else { if(low != NULL && size_upto != NULL){ addend = make_llnd(cur_file, MULT_OP, copy_llnd(size_upto), index_low, NULL); low = make_llnd(cur_file, ADD_OP, low, addend, NULL); } if(up != NULL && size_upto != NULL){ addend = make_llnd(cur_file, MULT_OP, copy_llnd(size_upto), index_up, NULL); up = make_llnd(cur_file, ADD_OP, up, addend, NULL); } } size_up = s->entry.Template.ll_ptr1->entry.Template.ll_ptr2; if(shift_needed){ one = make_llnd(cur_file, INT_VAL, NULL, NULL, 1); size_up = make_llnd(cur_file, ADD_OP, size_up, one, NULL); } size_upto = (size_upto == NULL) ? size_up : make_llnd(cur_file, MULT_OP, size_upto, size_up, NULL); size = size->entry.Template.ll_ptr2; s = s->entry.Template.ll_ptr2; RL = RL->entry.Template.ll_ptr2; } if (low == NULL && up == NULL){ RL = make_llnd(cur_file,STAR_RANGE,NULL, NULL, NULL); } else if (identical(low, up)) { RL = low; /* free_ll_tree(up); */ } else { RL = make_llnd(cur_file, DDOT, low, up, NULL); } rl->entry.Template.ll_ptr1 = RL; rl->entry.Template.ll_ptr2 = NULL; return(rl); } PTR_BLOB1 NGetCallInfo(filename,line) char *filename; int line; { PTR_BLOB1 lb, nb,tb; PTR_BFND b, FindBifNode(); char *s; PTR_LLND used, modified; used = NULL; modified = NULL; b = FindBifNode(filename,line); if(b == NULL){ nb = (PTR_BLOB1) malloc(sizeof(struct blob1)); s = malloc(256); #ifdef __SPF addToCollection(__LINE__, __FILE__,nb, 0); addToCollection(__LINE__, __FILE__,s, 0); #endif sprintf(s,"Could not find code at line %d\n",line); nb->ref = s; nb->next = NULL; return(nb); } if(b->variant != PROC_STAT && b->variant != EXPR_STMT_NODE){ nb = (PTR_BLOB1) malloc(sizeof(struct blob1)); s = malloc(256); #ifdef __SPF addToCollection(__LINE__, __FILE__,nb, 0); addToCollection(__LINE__, __FILE__,s, 0); #endif sprintf(s,"Cound not find call at line %d\n",line); nb->ref = s; nb->next = NULL; return(nb); } bind_call_site_info(b,&used,&modified); if(used == NULL){ tb = nb = (PTR_BLOB1) malloc(sizeof(struct blob1)); s = malloc(256); #ifdef __SPF addToCollection(__LINE__, __FILE__,tb, 0); addToCollection(__LINE__, __FILE__,s, 0); #endif sprintf(s,"nothing used in call. \n"); nb->ref = s; nb->next = NULL; lb = nb; } else{ tb = nb = (PTR_BLOB1) malloc(sizeof(struct blob1)); s = malloc(256); #ifdef __SPF addToCollection(__LINE__, __FILE__,tb, 0); addToCollection(__LINE__, __FILE__,s, 0); #endif sprintf(s,"variables used in call are: \n"); nb->ref = s; tb->next = nb = (PTR_BLOB1) malloc(sizeof(struct blob1)); #ifdef __SPF addToCollection(__LINE__, __FILE__,tb->next, 0); #endif s = (UnparseLlnd[cur_file->lang])(used); nb->ref = s; nb->next = NULL; lb = nb; } if(modified == NULL){ lb->next = nb = (PTR_BLOB1) malloc(sizeof(struct blob1)); s = malloc(256); #ifdef __SPF addToCollection(__LINE__, __FILE__,lb->next, 0); addToCollection(__LINE__, __FILE__,s, 0); #endif sprintf(s,"nothing modified by call. \n"); nb->ref = s; nb->next = NULL; return(tb); } else{ lb->next = nb = (PTR_BLOB1) malloc(sizeof(struct blob1)); s = malloc(256); #ifdef __SPF addToCollection(__LINE__, __FILE__,lb->next, 0); addToCollection(__LINE__, __FILE__,s, 0); #endif sprintf(s,"variables modified in call are: \n"); nb->ref = s; nb->next = (PTR_BLOB1) malloc(sizeof(struct blob1)); #ifdef __SPF addToCollection(__LINE__, __FILE__,nb->next, 0); #endif nb = nb->next; s = (UnparseLlnd[cur_file->lang])(modified); nb->ref = s; nb->next = NULL; return(tb); } } PTR_BLOB1 NGetDepInfo(filename, line) char *filename; int line; { PTR_BFND b,bpar; PTR_DEP d; int depth; char * s; PTR_BLOB1 nb, lb, btmp; PTR_BLOB q; PTR_SYMB induct_list[100], local_list[100], rename_list[100]; int induct_num, local_num, rename_num; /* PTR_LLND used, modified; */ PTR_BFND FindBifNode(); int i; induct_num = 0; local_num = 0; rename_num = 0; b = FindBifNode(filename,line); /* bind_call_site_info(b,&used,&modified);*/ if(b == NULL){ nb = (PTR_BLOB1) malloc(sizeof(struct blob1)); s = malloc(256); #ifdef __SPF addToCollection(__LINE__, __FILE__,nb, 0); addToCollection(__LINE__, __FILE__,s, 0); #endif sprintf(s,"Could not find code at line %d\n",line); nb->ref = s; nb->next = NULL; return(nb); } /* if b is a loop, we look for all loop carried deps for */ /* this loop. otherwise just list dependence going out */ if(b->variant == FOR_NODE || b->variant == WHILE_NODE){ depth = 0; bpar = b; current_par_loop = b; while(bpar != NULL && bpar->variant != GLOBAL){ if(bpar->variant == FOR_NODE || bpar->variant == CDOALL_NODE || bpar->variant == WHILE_NODE || bpar->variant == FORALL_NODE) depth++; bpar = bpar->control_parent; } q = b->entry.Template.bl_ptr1; nb = (PTR_BLOB1) malloc(sizeof(struct blob1)); s = malloc(256); #ifdef __SPF addToCollection(__LINE__, __FILE__,nb, 0); addToCollection(__LINE__, __FILE__,s, 0); #endif sprintf(s,"Loop Carried Dependences Prohibiting Parallelism:\n"); nb->ref = s; nb->next = NULL; nb = Nsearch_deps(nb,q,depth,induct_list, &induct_num, local_list,&local_num, rename_list, &rename_num); if (nb->next == NULL) { if (induct_num == 0 && local_num == 0 && rename_num == 0) sprintf(nb->ref, "this loop is perfect! parallelize it.\n"); else sprintf(nb->ref, "Loop is Parallelizable. First fix these problems.\n"); } for(lb = nb; lb->next != NULL; lb = lb->next); if(induct_num > 0){ btmp = (PTR_BLOB1) malloc(sizeof(struct blob1)); lb->next = btmp; lb = btmp; s = malloc(256); #ifdef __SPF addToCollection(__LINE__, __FILE__,btmp, 0); addToCollection(__LINE__, __FILE__,s, 0); #endif sprintf(s,"The following seem to be pseudo induction variables:\n"); lb->ref = s; lb->next = NULL; for(i = 0; i < induct_num; i++){ lb->next = (PTR_BLOB1) malloc(sizeof(struct blob1)); #ifdef __SPF addToCollection(__LINE__, __FILE__,lb->next, 0); #endif lb = lb->next; s = malloc(3+strlen(induct_list[i]->ident) ); #ifdef __SPF addToCollection(__LINE__, __FILE__,s, 0); #endif sprintf(s,"%s\n",induct_list[i]->ident); lb->next = NULL; lb->ref = s; } subtract_list(induct_list,&induct_num,local_list,&local_num); subtract_list(induct_list,&induct_num,rename_list,&rename_num); } if(local_num > 0){ btmp = (PTR_BLOB1) malloc(sizeof(struct blob1)); #ifdef __SPF addToCollection(__LINE__, __FILE__,btmp, 0); #endif lb->next = btmp; lb = btmp; s = malloc(256); #ifdef __SPF addToCollection(__LINE__, __FILE__,s, 0); #endif sprintf(s,"Variables that should be made local to loop:\n"); lb->ref = s; lb->next = NULL; for(i = 0; i < local_num; i++){ lb->next = (PTR_BLOB1) malloc(sizeof(struct blob1)); #ifdef __SPF addToCollection(__LINE__, __FILE__,lb->next, 0); #endif lb = lb->next; s = malloc(3+strlen(local_list[i]->ident)); #ifdef __SPF addToCollection(__LINE__, __FILE__,s, 0); #endif sprintf(s,"%s\n",local_list[i]->ident); lb->next = NULL; lb->ref = s; } subtract_list(local_list, &local_num, rename_list, &rename_num); } if(rename_num > 0){ btmp = (PTR_BLOB1) malloc(sizeof(struct blob1)); #ifdef __SPF addToCollection(__LINE__, __FILE__,btmp, 0); #endif lb->next = btmp; lb = btmp; s = malloc(256); #ifdef __SPF addToCollection(__LINE__, __FILE__,s, 0); #endif sprintf(s,"Variables that are reused in a funny way:\n"); lb->ref = s; lb->next = NULL; for(i = 0; i < rename_num; i++){ lb->next = (PTR_BLOB1) malloc(sizeof(struct blob1)); #ifdef __SPF addToCollection(__LINE__, __FILE__,lb->next, 0); #endif lb = lb->next; s = malloc(64); #ifdef __SPF addToCollection(__LINE__, __FILE__,s, 0); #endif sprintf(s,"%s\n",rename_list[i]->ident); lb->next = NULL; lb->ref = s; } } return(nb); } /* if loop case */ d = b->entry.Template.dep_ptr1; nb = NULL; btmp = (PTR_BLOB1) malloc(sizeof(struct blob1)); #ifdef __SPF addToCollection(__LINE__, __FILE__,btmp, 0); #endif s = malloc(256); #ifdef __SPF addToCollection(__LINE__, __FILE__,s, 0); #endif sprintf(s,"variant of this node is %d\n",b->variant); btmp->ref = s; btmp->next = NULL; nb = lb = btmp; while(d != NULL){ btmp = (PTR_BLOB1) malloc( sizeof(struct blob1)); #ifdef __SPF addToCollection(__LINE__, __FILE__,btmp, 0); #endif if (nb == NULL){ nb = btmp; lb = btmp;} else{ lb->next = btmp; lb = btmp;} s = malloc(256); #ifdef __SPF addToCollection(__LINE__, __FILE__,s, 0); #endif sprintf(s,"id:%s type:%s to line %d dir_vect =(%s,%s,%s)\n", d->symbol->ident, depstrs[(int) (d->type)], d->to.stmt->g_line, dirstrs[(int) (d->direct[1])], dirstrs[(int) (d->direct[2])], dirstrs[(int) (d->direct[3])]); btmp->ref = s; btmp->next = NULL; d = d->from_fwd; } return(nb); } static void subtract_list(a,na, b, nb) PTR_SYMB a[], b[]; int *na, *nb; { int i, j; for(i = 0; i < *na; i++){ for(j = 0; j < *nb; j++){ if(a[i] == b[j]){ if(j < *nb-1) b[j] = b[*nb -1]; (*nb)--; } } } } int pointer_as_array(d) PTR_DEP d; { /* if(d->from.refer == NULL) fprintf(stderr, "no from llnode\n"); if(d->to.refer == NULL) fprintf(stderr, "no to llnode\n"); fprintf(stderr, " from <%s to <%s\n", unparse_llnd(d->from.refer), unparse_llnd(d->to.refer)); */ if (d->to.refer->variant == ARRAY_REF || d->from.refer->variant==ARRAY_REF) return 1; else return 0; } static PTR_BLOB1 Nsearch_deps(nb,q,depth,induct_list, induct_num, local_list,local_num,rename_list,rename_num) PTR_BLOB1 nb; PTR_BLOB q; int depth; PTR_SYMB induct_list[], local_list[], rename_list[]; int *induct_num, *local_num, *rename_num; { PTR_BFND bchild; PTR_DEP d; char *s; PTR_BLOB1 lb = NULL, btmp; int i,found; PTR_LLND from_list[500]; int from_line[500], to_line[500]; int from_num; if(nb != NULL) lb = nb; from_num = 0; while(q != NULL){ bchild = q->ref; q = q->next; d = bchild->entry.Template.dep_ptr1; while(d != NULL){ /* if the dependence is a carried array dependence (on a array type */ /* or used as an array (fix)) or it is a flow dependence that is */ /* caried then classify appropriately. */ if (((d->symbol->type->variant == T_ARRAY || pointer_as_array(d)) && d->direct[depth] >1) || (d->type == 0 && d->direct[depth] >1)){ /* this is a loop carried flow dependence */ if(d->from.stmt == d->to.stmt && (d->symbol->type->variant == T_INT || (pointer_as_array(d) == 0 && d->symbol->type->variant == T_POINTER) )){ for(i = 0, found = 0; i < *induct_num; i++) if( induct_list[i] == d->symbol) found = 1; if(found == 0) induct_list[(*induct_num)++] = d->symbol; } else if(same_loop(d->from.stmt,d->to.stmt)){ found = 0; for(i = 0; i < from_num; i++) if(d->from.refer == from_list[i] && d->from.stmt->g_line == from_line[i] && d->to.stmt->g_line == to_line[i]) found = 1; if(found == 0){ btmp = (PTR_BLOB1) malloc( sizeof(struct blob1)); #ifdef __SPF addToCollection(__LINE__, __FILE__,btmp, 0); #endif if (nb == NULL){ nb = btmp; lb = btmp;} else{ lb->next = btmp; lb = btmp;} s = malloc(256); #ifdef __SPF addToCollection(__LINE__, __FILE__,s, 0); #endif sprintf(s, "an assignment to %s at line %d used in line %d in another iteration\n", (UnparseLlnd[cur_file->lang])(d->from.refer), d->from.stmt->g_line, d->to.stmt->g_line); btmp->ref = s; btmp->next = NULL; from_list[from_num] = d->from.refer; from_line[from_num] = d->from.stmt->g_line; to_line[from_num++] = d->to.stmt->g_line; } } } else if(d->symbol->type->variant != T_ARRAY && d->type != 0 && d->direct[depth] > 1 && same_loop(d->from.stmt,d->to.stmt)){ /* this is a loop caried output or anti dep */ /* add symbol to list for suggestion for localization */ for(i = 0, found = 0; i < *local_num; i++) if( local_list[i] == d->symbol) found = 1; if(found == 0) local_list[(*local_num)++] = d->symbol; } else if(d->type == 2 && d->direct[depth] <= 1 && same_loop(d->from.stmt,d->to.stmt)){ /* this is an output dependence of distance 0 */ /* suggest renaming. */ for(i = 0, found = 0; i < *rename_num; i++) if( rename_list[i] == d->symbol) found = 1; if(found == 0) rename_list[(*rename_num)++] = d->symbol; } d = d->from_fwd; } if(bchild->entry.Template.bl_ptr1 != NULL){ nb = Nsearch_deps(nb,bchild->entry.Template.bl_ptr1,depth,induct_list, induct_num, local_list, local_num, rename_list, rename_num); lb = nb; while(lb != NULL && lb->next != NULL) lb = lb->next; } if(bchild->entry.Template.bl_ptr2 != NULL){ nb = Nsearch_deps(nb,bchild->entry.Template.bl_ptr2,depth,induct_list, induct_num, local_list, local_num, rename_list, rename_num); lb = nb; while(lb != NULL && lb->next != NULL) lb = lb->next; } } return(nb); } static int same_loop(from, to) PTR_BFND from, to; { PTR_BFND c; c = from; while(c != NULL && c->variant != GLOBAL && c != current_par_loop) c = c->control_parent; if(c != current_par_loop) return(0); c = to; while(c != NULL && c->variant != GLOBAL && c != current_par_loop) c = c->control_parent; if(c != current_par_loop) return(0); return(1); }