00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #define __STDC_LIMIT_MACROS
00041 #include <stdint.h>
00042 #include "defs.h"
00043 #include "errors.h"
00044 #include "tracing.h"
00045 #include "timing.h"
00046 #include "stab.h"
00047 #include "util.h"
00048 #include "strtab.h"
00049 #include "wn.h"
00050 #include "wn_util.h"
00051 #include "stblock.h"
00052 #include "ir_reader.h"
00053 #include "config.h"
00054 #include "config_opt.h"
00055 #include "targ_sim.h"
00056 #include "targ_const.h"
00057 #include "const.h"
00058 #include "wn_map.h"
00059 #include "wn_simp.h"
00060 #include "cxx_template.h"
00061 #include "cxx_memory.h"
00062 #include "pu_info.h"
00063 #include "prompf.h"
00064 #include "anl_driver.h"
00065 #include "wb_f90_lower.h"
00066
00067 #include "intrn_info.h"
00068
00069 #include "f90_utils.h"
00070
00071 #define F90_LOWER_INTERNAL
00072 #include "f90_lower.h"
00073
00074 #ifdef __GNUC__
00075 #if ! defined(BUILD_OS_DARWIN)
00076 #pragma weak Anl_File_Path
00077 #pragma weak New_Construct_Id
00078 #endif
00079 #endif
00080
00081
00082 #define is_constant(x) (WN_operator(x)==OPR_INTCONST)
00083 #define ST_is_f90_pointer(x) TY_is_f90_pointer(ST_type(x))
00084
00085
00086 #define WN_GET_INTRINSIC(x) (INTRINSIC) WN_intrinsic(x)
00087
00088
00089 #define TRACE_DEPENDENCE 2
00090 #define TRACE_INSERTIONS 4
00091 #define TRACE_DOLOOPS 8
00092 #define TRACE_DEPENDENCE_ANALYSIS 0x20
00093 #define TRACE_SYMTAB 0x1
00094 #define TRACE_TRANSFORMATIONALS 0x40
00095 #define TRACE_COPIES 0x80
00096 #define TRACE_DEPINFO 0x100
00097
00098 #ifdef KEY
00099 extern void Set_addr_saved_expr(WN *, BOOL);
00100 #endif
00101
00102 static BOOL trace_dependence;
00103 static BOOL trace_depinfo;
00104
00105 typedef struct f90lower_aux_data_s {
00106 WN *prelist;
00107 WN *postlist;
00108 WN *alloc_prelist;
00109 WN *dealloc_postlist;
00110 WN **iter_count;
00111
00112 mINT16 *perm_index;
00113 DIR_FLAG *directions;
00114 mINT16 ndim;
00115 COPY_FLAG_T copy_flag:4;
00116 BOOL known_independent:2;
00117 BOOL no_prompf_info:2;
00118 } F90_LOWER_AUX_DATA;
00119
00120
00121
00122 static MEM_POOL f90_lower_pool_s;
00123 static MEM_POOL *f90_lower_pool=NULL;
00124
00125 typedef struct f90_dep_info_s {
00126 INT ndim;
00127 DEP_SUMMARY summary;
00128 DIR_FLAG directions[MAX_NDIM];
00129 } DEP_INFO;
00130
00131 #define DEP_NDIM(x) ((x)->ndim)
00132 #define DEP_DIRECTION(x,n) ((x)->directions[(n)])
00133 #define DEP_SUMMARY(x) ((x)->summary)
00134 #define SET_DEP_NDIM(x,y) (x)->ndim=(y)
00135 #define SET_DEP_SUMMARY(x,y) (x)->summary=(y)
00136 #define SET_DEP_DIRECTION(x,n,d) (x)->directions[(n)]=(d)
00137
00138
00139 #define PRELIST(x) ((x)->prelist)
00140 #define POSTLIST(x) ((x)->postlist)
00141 #define ALLOC_PRELIST(x) ((x)->alloc_prelist)
00142 #define DEALLOC_POSTLIST(x) ((x)->dealloc_postlist)
00143 #define ITER_COUNT(x,n) (*(((x)->iter_count) + (n)))
00144 #define ITER_COUNT_PTR(x) ((x)->iter_count)
00145 #define PERM_INDEX(x,n) (*(((x)->perm_index) + (n)))
00146 #define DIRECTION(x,n) (*(((x)->directions) + (n)))
00147 #define NDIM(x) ((x)->ndim)
00148 #define COPY_FLAG(x) ((x)->copy_flag)
00149 #define KNOWN_INDEPENDENT(x) ((x)->known_independent)
00150 #define NO_PROMPF_INFO(x) ((x)->no_prompf_info)
00151
00152 #define SET_PRELIST(x,y) (x)->prelist = (y)
00153 #define SET_POSTLIST(x,y) (x)->postlist = (y)
00154 #define SET_ALLOC_PRELIST(x,y) (x)->alloc_prelist = (y)
00155 #define SET_DEALLOC_POSTLIST(x,y) (x)->dealloc_postlist = (y)
00156 #define SET_ITER_COUNT(x,n,y) *(((x)->iter_count) + (n)) = (y)
00157 #define SET_PERM_INDEX(x,n,y) *(((x)->perm_index) + (n)) = (y)
00158 #define SET_DIRECTION(x,n,y) *(((x)->directions) + (n)) = (y)
00159 #define SET_NDIM(x,y) (x)->ndim = (y)
00160 #define SET_COPY_FLAG(x,y) (x)->copy_flag = (COPY_FLAG_T) (y)
00161 #define SET_KNOWN_INDEPENDENT(x,y) (x)->known_independent = (y)
00162 #define SET_NO_PROMPF_INFO(x,y) (x)->no_prompf_info = (y)
00163
00164
00165 #define SET_ITER_COUNT_P(x,y) (x)->iter_count = (y)
00166 #define SET_DIRECTION_P(x,y) (x)->directions = (y)
00167 #define SET_PERM_INDEX_P(x,y) (x)->perm_index = (y)
00168
00169
00170
00171 static WN_MAP f90_lower_map;
00172 #define SET_F90_MAP(x,t) WN_MAP_Set(f90_lower_map,(x),(void *) (t))
00173 #define GET_F90_MAP(x) ((F90_LOWER_AUX_DATA *) WN_MAP_Get(f90_lower_map,(x)))
00174
00175
00176 static OPCODE OPCmpy,OPCadd,OPCsub,OPCarrsection,OPCtriplet,OPCint,OPCmod;
00177 static INTRINSIC INTRNalloca,INTRNfree,INTRNmalloc,INTRNgetstack,INTRNsetstack;
00178 static TYPE_ID doloop_ty;
00179 static INT num_temps = 0;
00180 static BOOL pointer8 = 0;
00181 #define SELECT_OP(x,y) (pointer8 ? x : y)
00182 static PREG_NUM pointer_return_reg;
00183 static TY_IDX char_ty;
00184 static SRCPOS current_srcpos;
00185
00186 static BOOL array_statement_seen;
00187 static BOOL temp_allocations_inserted;
00188
00189
00190 static WN * F90_Lower_Walk(WN *expr, PREG_NUM *indices, INT ndim,
00191 WN * block, WN *insert_point);
00192
00193
00194 static WN * F90_Current_Block;
00195 static WN * F90_Current_Loopnest;
00196 static WN * F90_Current_Stmt;
00197
00198 static WN_VECTOR F90_MP_Region;
00199 static BOOL_VECTOR F90_MP_Region_Isworkshare;
00200
00201
00202 static PU *current_pu;
00203
00204
00205 #define ARREXP_SIZES(x) &WN_kid1(x)
00206
00207
00208
00209
00210
00211
00212 static void F90_Lower_Prompf_Init(PU_Info* pu_info)
00213 {
00214 if (Run_prompf
00215 && !Is_Set_PU_Info_flags(pu_info, PU_IS_COMPILER_GENERATED)) {
00216 Prompf_Info->Enable();
00217 Prompf_Info->Mark_F90_Lower();
00218 WB_F90_Lower_Set_Prompf_Info(Prompf_Info);
00219 }
00220 }
00221
00222
00223
00224
00225
00226
00227 static void F90_Lower_Prompf_Finish(PU_Info* pu_info)
00228 {
00229 if (Run_prompf
00230 && !Is_Set_PU_Info_flags(pu_info, PU_IS_COMPILER_GENERATED)) {
00231 const char *path = Anl_File_Path();
00232 FILE *fp_anl = fopen(path, "a");
00233 Prompf_Info->Print_Compact(fp_anl, PTL_F90_LOWER);
00234 fclose(fp_anl);
00235 Prompf_Info->Disable();
00236 }
00237 }
00238
00239
00240
00241
00242
00243 static WN * get_assignment_from_stmt(WN *stmt)
00244 {
00245 WN *assignment;
00246 if (WN_opcode(stmt) == OPC_WHERE) {
00247 assignment = WN_first(WN_kid1(stmt));
00248 if (!assignment) assignment = WN_first(WN_kid2(stmt));
00249 } else {
00250 assignment = stmt;
00251 }
00252 return(assignment);
00253 }
00254
00255
00256
00257
00258
00259
00260
00261 static BOOL arrayexp_in_subtree(WN *tree)
00262 {
00263 WN_ITER *tree_iter;
00264 WN *node;
00265 OPERATOR opr;
00266
00267 tree_iter = WN_WALK_TreeIter(tree);
00268 while (tree_iter) {
00269 node = WN_ITER_wn(tree_iter);
00270 opr = WN_operator(node);
00271 if (opr == OPR_ARRAYEXP ||
00272 opr == OPR_ARRSECTION ||
00273 (opr == OPR_INTRINSIC_OP && F90_Is_Transformational(WN_GET_INTRINSIC(node)))) {
00274 WN_WALK_Abort(tree_iter);
00275 return (TRUE);
00276 }
00277 tree_iter = WN_WALK_TreeNext(tree_iter);
00278 }
00279 return (FALSE);
00280 }
00281
00282
00283
00284
00285 static WN *find_arrsection(WN * tree)
00286 {
00287 WN *r;
00288 INT num_kids,i;
00289
00290 switch (WN_operator(tree)) {
00291 case OPR_ARRSECTION:
00292 return (tree);
00293
00294 case OPR_ARRAY:
00295 case OPR_ARRAYEXP:
00296 return (find_arrsection(WN_kid0(tree)));
00297
00298 default:
00299 num_kids = WN_kid_count(tree);
00300 r = NULL;
00301 for (i=0; i < num_kids; i++) {
00302 r = find_arrsection(WN_kid(tree,i));
00303 if (r) break;
00304 }
00305 return (r);
00306 }
00307 }
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317 static INT find_vector_axes(INT * vecaxes, WN *arrsect)
00318 {
00319 INT numaxes,i,num_kids;
00320 OPERATOR opr;
00321
00322 if (WN_operator(arrsect) != OPR_ARRSECTION) return (0);
00323 num_kids = (WN_kid_count(arrsect)-1)/2;
00324 numaxes = 0;
00325 for (i=0; i < num_kids; i++) {
00326 opr = WN_operator(WN_kid(arrsect,i+1+num_kids));
00327 if (opr == OPR_ARRAYEXP || opr == OPR_TRIPLET) {
00328 vecaxes[numaxes] = i;
00329 ++numaxes;
00330 }
00331 }
00332 return (numaxes);
00333 }
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354 static WN *insert_handle;
00355
00356
00357 static BOOL do_prewalk(WN * tree, WN * block, BOOL prewalk(WN * node, WN *block1))
00358 {
00359 BOOL keep_going;
00360 WN *new_tree;
00361 WN *old_prev;
00362
00363
00364
00365
00366 current_srcpos = WN_Get_Linenum(tree);
00367 if (current_srcpos) {
00368 old_prev = WN_prev(tree);
00369 WN_prev(insert_handle) = old_prev;
00370 WN_next(insert_handle) = tree;
00371 if (old_prev) WN_next(old_prev) = insert_handle;
00372 WN_prev(tree) = insert_handle;
00373 if (block) {
00374 if (WN_first(block) == tree) WN_first(block) = insert_handle;
00375 }
00376
00377 keep_going = prewalk(tree,block);
00378
00379 new_tree = WN_next(insert_handle);
00380 WN_Set_Linenum(new_tree,current_srcpos);
00381 old_prev = WN_prev(insert_handle);
00382 WN_prev(new_tree) = old_prev;
00383 if (old_prev) WN_next(old_prev) = new_tree;
00384 if (block) {
00385 if (WN_first(block) == insert_handle) WN_first(block) = new_tree;
00386 }
00387 } else {
00388 keep_going = prewalk(tree,block);
00389 }
00390 return (keep_going);
00391 }
00392
00393 #ifdef KEY
00394 #include "cxx_base.h"
00395 class FF_STMT_NODE: public SLIST_NODE {
00396 DECLARE_SLIST_NODE_CLASS( FF_STMT_NODE);
00397 private:
00398 WN *_stmt;
00399 public:
00400 FF_STMT_NODE() { _stmt = NULL; };
00401 FF_STMT_NODE(WN *stmt) { _stmt = stmt; };
00402 ~FF_STMT_NODE() {};
00403 void Set_Stmt(WN *stmt) { _stmt = stmt; }
00404 WN *Get_Stmt() const { return _stmt; }
00405 };
00406
00407 class FF_STMT_LIST: public SLIST {
00408 DECLARE_SLIST_CLASS( FF_STMT_LIST, FF_STMT_NODE )
00409 public:
00410 ~FF_STMT_LIST(void){};
00411 void Append(WN *stmt, MEM_POOL *mpool) {
00412 Append(CXX_NEW(FF_STMT_NODE(stmt), mpool));
00413 }
00414 void Prepend(WN *stmt, MEM_POOL *mpool) {
00415 Prepend(CXX_NEW(FF_STMT_NODE(stmt), mpool));
00416 }
00417 };
00418
00419 class FF_STMT_ITER: public SLIST_ITER {
00420 DECLARE_SLIST_ITER_CLASS( FF_STMT_ITER, FF_STMT_NODE, FF_STMT_LIST )
00421 public:
00422 ~FF_STMT_ITER() {};
00423 };
00424
00425 struct F90_LOOP_INFO{
00426 INT start, end, step;
00427 };
00428
00429 static BOOL Find_Preceeding_Pragma(WN* wn, WN_PRAGMA_ID pragma_id)
00430 {
00431 WN* prev_pragma=WN_prev(wn);
00432 while (prev_pragma &&
00433 (WN_opcode(prev_pragma)==OPC_PRAGMA ||
00434 WN_opcode(prev_pragma)==OPC_XPRAGMA)) {
00435 if (WN_pragma(prev_pragma)==pragma_id)
00436 return TRUE;
00437 prev_pragma=WN_prev(prev_pragma);
00438 }
00439 return FALSE;
00440 }
00441 static void
00442 F90_Separate(WN* in_loop, WN* block, WN* in_stmt, UINT8 level, WN** new_loop, BOOL create_empty_loop = FALSE)
00443 {
00444
00445 WN* loop_body1;
00446 WN* loop_body2;
00447 WN* wn1;
00448 WN* wn2;
00449
00450 FmtAssert(WN_opcode(in_loop)==OPC_DO_LOOP,
00451 ("non-loop input node in Separate()\n") );
00452
00453 if (!in_stmt && !create_empty_loop) {
00454 Is_True(0, ("Null stmt passed into LNO:Separate()\n"));
00455 return;
00456 }
00457
00458
00459 if (in_stmt && !create_empty_loop && (WN_next(in_stmt) == NULL)) {
00460
00461 *new_loop=NULL;
00462 return;
00463 }
00464
00465
00466 *new_loop =WN_CreateDO (
00467 WN_COPY_Tree(WN_index(in_loop)),
00468 WN_COPY_Tree(WN_start(in_loop)),
00469 WN_COPY_Tree(WN_end(in_loop)),
00470 WN_COPY_Tree(WN_step(in_loop)),
00471 WN_CreateBlock(),
00472 NULL);
00473
00474 WN_Set_Linenum(WN_do_body(*new_loop),WN_Get_Linenum(WN_do_body(in_loop)));
00475
00476
00477 loop_body1=WN_do_body(in_loop);
00478 loop_body2=WN_do_body(*new_loop);
00479
00480
00481 if (in_stmt){
00482 if (WN_next(in_stmt)!=NULL){
00483 WN_first(loop_body2)=WN_next(in_stmt);
00484 WN_last(loop_body2)=WN_last(loop_body1);
00485 WN_last(loop_body1)=in_stmt;
00486 WN_prev(WN_first(loop_body2))=NULL;
00487 WN_next(WN_last(loop_body2))=NULL;
00488 WN_next(WN_last(loop_body1))=NULL;
00489 }
00490 } else {
00491 WN_first(loop_body2)=WN_first(loop_body1);
00492 WN_last(loop_body2)=WN_last(loop_body1);
00493 WN_first(loop_body1)=NULL;
00494 WN_last(loop_body1)=NULL;
00495 }
00496
00497 wn1 = in_loop;
00498 wn2 = *new_loop;
00499
00500 WN_Set_Linenum(wn2, WN_Get_Linenum(wn1));
00501 WN_INSERT_BlockAfter(block,
00502 wn1,
00503 wn2
00504 );
00505
00506 }
00507 static void F90_Separate_And_Update(WN* in_loop, WN* block, DYN_ARRAY<FF_STMT_LIST>& loop, UINT fission_level)
00508 {
00509 UINT total_loops=loop.Lastidx()+1;
00510 WN*** wn_starts=CXX_NEW_ARRAY(WN**, fission_level, f90_lower_pool);
00511 WN*** wn_ends=CXX_NEW_ARRAY(WN**, fission_level, f90_lower_pool);
00512 WN*** wn_steps=CXX_NEW_ARRAY(WN**, fission_level, f90_lower_pool);
00513 INT i;
00514
00515 for (i=0; i<fission_level; i++) {
00516 wn_starts[i]=CXX_NEW_ARRAY(WN*, total_loops, f90_lower_pool);
00517 wn_ends[i]=CXX_NEW_ARRAY(WN*, total_loops, f90_lower_pool);
00518 wn_steps[i]=CXX_NEW_ARRAY(WN*, total_loops, f90_lower_pool);
00519 }
00520
00521 WN*** new_loop=CXX_NEW_ARRAY(WN**, fission_level, f90_lower_pool);
00522 WN* wn = in_loop;
00523 WN* outer_most_loop;
00524
00525 for (i=fission_level-1; i>=0; i--) {
00526 new_loop[i]=CXX_NEW_ARRAY(WN*,total_loops,f90_lower_pool);
00527 new_loop[i][0]=wn;
00528 wn_starts[i][0]=WN_kid0(WN_start(wn));
00529 wn_ends[i][0]=WN_end(wn);
00530 wn_steps[i][0]=WN_kid0(WN_step(wn));
00531 if (i==0)
00532 outer_most_loop=wn;
00533 }
00534
00535 for (i=total_loops-1; i>0; i--) {
00536 WN* loop_body = WN_do_body(in_loop);
00537 WN* first_stmt = loop[i].Head()->Get_Stmt();
00538 FF_STMT_NODE* stmt_node_p;
00539 F90_Separate(in_loop, block, WN_prev(first_stmt), fission_level, &wn);
00540 }
00541 }
00542
00543 static BOOL Arraysection_in_Subtree(WN *tree)
00544 {
00545 WN_ITER *tree_iter;
00546 WN *node;
00547 OPERATOR opr;
00548
00549 tree_iter = WN_WALK_TreeIter(tree);
00550 while (tree_iter) {
00551 node = WN_ITER_wn(tree_iter);
00552 opr = WN_operator(node);
00553 if (opr == OPR_ARRSECTION) {
00554 WN_WALK_Abort(tree_iter);
00555 return (TRUE);
00556 }
00557 tree_iter = WN_WALK_TreeNext(tree_iter);
00558 }
00559 return (FALSE);
00560 }
00561
00562 static BOOL F90_Processed_ST(ST *st, STACK<ST*> *processed)
00563 {
00564 for (INT i=0; i<processed->Elements(); ++i)
00565 if (processed->Bottom_nth(i)==st)
00566 return TRUE;
00567 return FALSE;
00568
00569 }
00570 static inline INT64
00571 Num_Elements(ARB_HANDLE arb)
00572 {
00573 return abs(ARB_ubnd_val(arb) - ARB_lbnd_val(arb) + 1);
00574 }
00575 static INT64
00576 Get_New_Size_Padding(TY_IDX new_array_ty_idx, TY_IDX old_array_ty_idx,
00577 INT32 start_dim)
00578 {
00579 TY& new_array_ty = Ty_Table[new_array_ty_idx];
00580 TY& old_array_ty = Ty_Table[old_array_ty_idx];
00581
00582 INT64 old_size = 1;
00583 INT64 new_size = 1;
00584 INT old_num_dims = TY_AR_ndims(old_array_ty);
00585 INT new_num_dims = TY_AR_ndims(new_array_ty);
00586 ARB_HANDLE old_arb_base = TY_arb(old_array_ty);
00587 ARB_HANDLE new_arb_base = TY_arb(new_array_ty);
00588
00589 Is_True((start_dim < old_num_dims), ("start dim = %d , num_dims = %d in Get_New_Size_Padding \n", start_dim, old_num_dims));
00590
00591 for (INT i=start_dim; i<old_num_dims; ++i)
00592 {
00593 ARB_HANDLE old_arb = old_arb_base[i];
00594 ARB_HANDLE new_arb = new_arb_base[i];
00595 old_size = old_size*Num_Elements(old_arb);
00596 new_size = new_size*Num_Elements(new_arb);
00597 }
00598 for (INT i=old_num_dims;i<new_num_dims; ++i){
00599 ARB_HANDLE new_arb = new_arb_base[i];
00600 new_size = new_size*Num_Elements(new_arb);
00601 }
00602
00603 new_size = new_size - old_size;
00604 return new_size;
00605 }
00606
00607 static void F90_Expand_Array(ST *st, F90_LOOP_INFO *loop_info, WN *parent_loop, WN **new_subscript, STACK<ST*> *processed)
00608 {
00609 WN *index = WN_index(parent_loop);
00610 if (!F90_Processed_ST(st, processed)){
00611 TY_IDX old_array_ty_idx = ST_type(st);
00612 INT num_dims = TY_AR_ndims(old_array_ty_idx);
00613 TY_IDX etype_idx = TY_etype(old_array_ty_idx);
00614 const TY& etype = Ty_Table[etype_idx];
00615 TY_IDX new_array_ty_idx = Make_Array_Type(TY_mtype(etype), num_dims+1, 1);
00616 Set_TY_etype(new_array_ty_idx, etype_idx);
00617 Set_TY_name_idx(Ty_Table[new_array_ty_idx], TY_name_idx(Ty_Table[old_array_ty_idx]));
00618 Set_TY_size(Ty_Table[new_array_ty_idx],TY_size(Ty_Table[old_array_ty_idx]));
00619 num_dims = TY_AR_ndims(new_array_ty_idx);
00620 ARB_HANDLE arb_base = TY_arb(new_array_ty_idx);
00621 ARB_HANDLE old_arb_base = TY_arb(old_array_ty_idx);
00622 ARB_HANDLE arb, old_arb;
00623 UINT i;
00624 #ifndef KEY
00625 for (i = 0; i < num_dims-1 ; ++i)
00626 {
00627 arb = arb_base[i];
00628 old_arb = old_arb_base[i];
00629 ARB_Init(arb, ARB_lbnd_val(old_arb),
00630 ARB_ubnd_val(old_arb),
00631 ARB_stride_val(old_arb)*(loop_info->end-loop_info->start+1)/loop_info->step);
00632 Set_ARB_dimension(arb, num_dims-i);
00633 if (i==0)
00634 Set_ARB_first_dimen(arb_base[0]);
00635 }
00636 arb = arb_base[i];
00637 ARB_Init(arb, 1, 1+abs((loop_info->end-loop_info->start)/loop_info->step), abs((loop_info->end-loop_info->start)/loop_info->step));
00638 Set_ARB_dimension(arb, num_dims-i);
00639 Set_ARB_last_dimen(arb_base[i]);
00640 #else
00641
00642
00643
00644
00645
00646 arb = arb_base[0];
00647 ARB_Init(arb, 1, 1+abs((loop_info->end-loop_info->start)/loop_info->step), abs((loop_info->end-loop_info->start)/loop_info->step));
00648 Set_ARB_first_dimen(arb_base[0]);
00649 Set_ARB_dimension(arb, num_dims);
00650 for (i = 1; i < num_dims ; ++i)
00651 {
00652 arb = arb_base[i];
00653 old_arb = old_arb_base[i-1];
00654 ARB_Init(arb, ARB_lbnd_val(old_arb),
00655 ARB_ubnd_val(old_arb),
00656 ARB_stride_val(old_arb)*(loop_info->end-loop_info->start+1)/loop_info->step);
00657 Set_ARB_dimension(arb, num_dims-i);
00658 if (i==num_dims-1)
00659 Set_ARB_last_dimen(arb_base[i]);
00660 }
00661 #endif
00662
00663 TY& new_array_ty = Ty_Table[new_array_ty_idx];
00664 TY& old_array_ty = Ty_Table[old_array_ty_idx];
00665 etype_idx = TY_etype(old_array_ty);
00666 INT64 add_size = Get_New_Size_Padding(new_array_ty_idx,
00667 old_array_ty_idx,0);
00668 add_size = add_size*TY_size(etype_idx);
00669 Set_TY_size(new_array_ty, TY_size(old_array_ty) + add_size);
00670 Set_ST_type(*st, new_array_ty_idx);
00671 processed->Push(st);
00672 }
00673
00674 TYPE_ID index_type = WN_desc(WN_start(parent_loop));
00675 ST *loop_index = WN_st(index);
00676 *new_subscript = WN_Div(index_type,
00677 WN_Sub(index_type,
00678 WN_Ldid(index_type, WN_idname_offset(index), loop_index, MTYPE_To_TY(index_type)),
00679 WN_Intconst(index_type, loop_info->start)),
00680 WN_Intconst(index_type,loop_info->step));
00681 *new_subscript = WN_Simplify_Tree(*new_subscript);
00682
00683 }
00684
00685 static WN *Find_Arrsection_and_Pos(WN *tree, WN **parent, INT* pos, STACK<WN*> *processed_wn)
00686 {
00687 WN *r;
00688 INT num_kids,i;
00689 switch (WN_operator(tree)) {
00690 case OPR_ARRSECTION:
00691 for ( i=0; i<processed_wn->Elements(); ++i)
00692 if (processed_wn->Bottom_nth(i)==tree)
00693 return NULL;
00694 processed_wn->Push(tree);
00695 return (tree);
00696 case OPR_ARRAY:
00697 case OPR_ARRAYEXP:
00698 *pos = 0;
00699 *parent = tree;
00700 return (Find_Arrsection_and_Pos(WN_kid0(tree), parent, pos, processed_wn));
00701 default:
00702 num_kids = WN_kid_count(tree);
00703 r = NULL;
00704 for (i=0; i < num_kids; i++) {
00705 *pos = i;
00706 *parent = tree;
00707 r = Find_Arrsection_and_Pos(WN_kid(tree,i), parent, pos, processed_wn);
00708 if (r) break;
00709 }
00710 return (r);
00711 }
00712 }
00713 static void F90_Modify_Array_Section(ST *st, WN *old_wn, WN *parent, INT pos, WN *new_wn, STACK<WN*> *processed_wn)
00714 {
00715 TY_IDX array_ty_idx = ST_type(st);
00716 INT ndim = TY_AR_ndims(array_ty_idx);
00717
00718
00719 WN *arrsection = WN_Create(OPCarrsection,2*ndim+1);
00720 TY_IDX temp_ty = TY_etype(array_ty_idx);
00721 TY_IDX ptr_ty = Make_Pointer_Type(temp_ty);
00722 WN_kid0(arrsection) = WN_Lda(Pointer_type, (WN_OFFSET) 0, st);
00723 INT element_size = TY_size(temp_ty);
00724 WN_element_size(arrsection) = element_size;
00725
00726 ARB_HANDLE arb_base = TY_arb(array_ty_idx);
00727 #ifndef KEY
00728 WN_kid(arrsection, 1) = WN_Intconst(MTYPE_I8, ARB_ubnd_val(arb_base[ndim-1]));
00729 #else
00730
00731
00732
00733
00734
00735 WN_kid(arrsection, 1) = WN_Intconst(MTYPE_I8, ARB_ubnd_val(arb_base[0]));
00736 #endif
00737 WN_kid(arrsection, ndim+1) = WN_COPY_Tree(new_wn);
00738
00739 for (INT i=1; i < ndim; i++) {
00740
00741 WN_kid(arrsection,i+1) = WN_COPY_Tree(WN_kid(old_wn,i));
00742
00743 WN_kid(arrsection,i+1+ndim) = WN_COPY_Tree(WN_kid(old_wn,i+ndim-1));
00744 }
00745 WN_kid(parent, pos) = arrsection;
00746 processed_wn->Push(arrsection);
00747 }
00748
00749 static void F90_Array_Expansion(F90_LOOP_INFO *loop_info, WN *parent_loop, WN *stmt, STACK<ST*> *processed)
00750 {
00751 OPCODE op;
00752 OPERATOR opr;
00753 BOOL is_arrayexp;
00754 WN *arrayexp = NULL;
00755 INT i,num_kids;
00756 WN *arraysection = NULL;
00757 WN *new_subscript = NULL;
00758
00759 op = WN_opcode(stmt);
00760 opr = OPCODE_operator(op);
00761
00762 if (opr == OPR_WHERE)
00763 arrayexp = WN_first(WN_kid0(stmt));
00764 else if (opr == OPR_MSTORE || opr == OPR_ISTORE) {
00765 if (WN_operator(WN_kid1(stmt)) == OPR_ARRAYEXP)
00766 arrayexp = WN_kid1(stmt);
00767 }
00768 WN *parent;
00769 INT pos;
00770 if (arrayexp) {
00771 STACK<WN*> *processed_wn = CXX_NEW(STACK<WN*>(f90_lower_pool), f90_lower_pool);
00772 arraysection = Find_Arrsection_and_Pos(arrayexp, &parent, &pos, processed_wn);
00773 while (arraysection){
00774 WN *addr = WN_kid0(arraysection);
00775 if (WN_operator(addr) == OPR_LDA && ST_is_temp_var(WN_st(addr))){
00776 F90_Expand_Array(WN_st(addr), loop_info, parent_loop, &new_subscript, processed);
00777 F90_Modify_Array_Section(WN_st(addr), arraysection, parent, pos, new_subscript, processed_wn);
00778 }
00779 arraysection = Find_Arrsection_and_Pos(arrayexp, &parent, &pos, processed_wn);
00780 }
00781 }
00782 }
00783
00784 static BOOL F90_Get_Loop_Info(WN *parent_loop, F90_LOOP_INFO *loop_info){
00785 WN *start = WN_kid0(WN_start(parent_loop));
00786 WN *end = WN_kid1(WN_end(parent_loop));
00787 WN *step = WN_kid1(WN_kid0(WN_step(parent_loop)));
00788 if (WN_operator(start)!=OPR_INTCONST || WN_operator(end)!=OPR_INTCONST || WN_operator(step)!=OPR_INTCONST)
00789 return FALSE;
00790 loop_info->start = WN_const_val(start);
00791 loop_info->end = WN_const_val(end);
00792 loop_info->step = WN_const_val(step);
00793 return TRUE;
00794 }
00795
00796 static void F90_Fission_Loop(WN* wn, WN *block)
00797 {
00798 INT level = 1;
00799 WN* parent_loop = wn;
00800 DYN_ARRAY<FF_STMT_LIST> loops(f90_lower_pool);
00801 F90_LOOP_INFO loop_info;
00802
00803 STACK<ST*> *processed = CXX_NEW(STACK<ST*>(f90_lower_pool), f90_lower_pool);
00804 WN* stmt=WN_first(WN_do_body(parent_loop));
00805 if (!F90_Get_Loop_Info(parent_loop, &loop_info))
00806 return;
00807 INT total_loops = 0;
00808 while (stmt){
00809
00810 if (WN_operator(stmt) == OPR_DO_LOOP)
00811 return;
00812
00813 loops.Newidx();
00814 if (Arraysection_in_Subtree(stmt))
00815 F90_Array_Expansion(&loop_info, parent_loop, stmt, processed);
00816 loops[total_loops++].Append(stmt, f90_lower_pool);
00817 stmt=WN_next(stmt);
00818 }
00819 F90_Separate_And_Update(parent_loop, block, loops, level);
00820 }
00821 static void F90_Walk_Stmts_return_where (WN *tree, BOOL *where_flag)
00822 {
00823 OPCODE op;
00824 WN *node;
00825
00826 if (*where_flag == TRUE)
00827 return;
00828
00829 op = WN_opcode(tree);
00830 if (op == OPC_BLOCK) {
00831 node = WN_first(tree);
00832 while (node) {
00833 F90_Walk_Stmts_return_where(node, where_flag);
00834 node = WN_next(node);
00835 }
00836 } else if (OPCODE_is_scf(op) && op != OPC_WHERE) {
00837 for (INT i=0; i < WN_kid_count(tree); i++) {
00838 F90_Walk_Stmts_return_where(WN_kid(tree,i), where_flag);
00839 }
00840 } else if (OPCODE_is_stmt(op) || op == OPC_WHERE) {
00841 if (op == OPC_WHERE)
00842 *where_flag = TRUE;
00843 return;
00844 }
00845 return;
00846 }
00847
00848 #endif
00849
00850 static BOOL F90_Walk_Statements_Helper(WN * tree, WN * block,
00851 BOOL prewalk(WN * node, WN *block),
00852 BOOL walk_scf)
00853 {
00854 OPCODE op;
00855 WN *callblock;
00856 WN *node,*nextnode;
00857 BOOL keep_going = TRUE;
00858 BOOL is_mp_region = FALSE;
00859 INT i,numkids;
00860
00861 op = WN_opcode(tree);
00862
00863 if (op == OPC_REGION && WN_region_kind(tree) == REGION_KIND_MP) {
00864 is_mp_region = TRUE;
00865 F90_MP_Region.insert(F90_MP_Region.begin(),tree);
00866 WN *pragma_wn = WN_first(WN_region_pragmas(tree));
00867 bool bWorkshare;
00868 if( (pragma_wn != NULL) &&
00869 (WN_opcode(pragma_wn) == OPC_PRAGMA) ){
00870 WN_PRAGMA_ID pragma = (WN_PRAGMA_ID)WN_pragma(pragma_wn);
00871 bWorkshare = (pragma == WN_PRAGMA_PWORKSHARE_BEGIN) ||
00872 (pragma == WN_PRAGMA_PARALLEL_WORKSHARE);
00873 }
00874 else{
00875 bWorkshare = false;
00876 }
00877 F90_MP_Region_Isworkshare.insert(F90_MP_Region_Isworkshare.begin(), bWorkshare);
00878 }
00879
00880 if (op == OPC_BLOCK) {
00881 callblock = tree;
00882 node = WN_first(tree);
00883 while (node && keep_going) {
00884 nextnode = WN_next(node);
00885 keep_going = F90_Walk_Statements_Helper(node, callblock, prewalk, walk_scf);
00886 node = nextnode;
00887 }
00888 } else if (OPCODE_is_scf(op) && op != OPC_WHERE) {
00889 if (walk_scf) {
00890 keep_going = do_prewalk(tree,block,prewalk);
00891 if (!keep_going) goto done;
00892 }
00893 #ifdef KEY
00894 if (WN_operator(tree) == OPR_DO_LOOP) {
00895 BOOL forall_flag = Find_Preceeding_Pragma(tree,WN_PRAGMA_FORALL);
00896 BOOL where_flag = FALSE;
00897 F90_Walk_Stmts_return_where(tree, &where_flag);
00898 if (forall_flag == TRUE && where_flag == TRUE)
00899 F90_Fission_Loop(tree, block);
00900 }
00901 #endif
00902 numkids = WN_kid_count(tree);
00903 for (i=0; i < numkids; i++) {
00904 keep_going = F90_Walk_Statements_Helper(WN_kid(tree,i), block, prewalk, walk_scf);
00905 if (!keep_going) break;
00906 }
00907 } else if (OPCODE_is_stmt(op) || op == OPC_WHERE) {
00908 keep_going = do_prewalk(tree,block,prewalk);
00909 }
00910 done:
00911 if (is_mp_region) {
00912 F90_MP_Region.erase(F90_MP_Region.begin());
00913 F90_MP_Region_Isworkshare.erase(F90_MP_Region_Isworkshare.begin());
00914 }
00915 return (keep_going);
00916 }
00917
00918 static void F90_Walk_Statements(WN * tree, BOOL prewalk(WN * node, WN *block))
00919 {
00920
00921 insert_handle = WN_Create(OPC_COMMENT,0);
00922 (void) F90_Walk_Statements_Helper(tree, NULL, prewalk,FALSE);
00923 WN_Delete(insert_handle);
00924 }
00925
00926 static void F90_Walk_All_Statements(WN * tree, BOOL prewalk(WN * node, WN *block))
00927 {
00928
00929 insert_handle = WN_Create(OPC_COMMENT,0);
00930 (void) F90_Walk_Statements_Helper(tree, NULL, prewalk,TRUE);
00931 WN_Delete(insert_handle);
00932 }
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947 static INT num_alloca;
00948 static INT max_num_alloca;
00949
00950 typedef struct {
00951 WN_OFFSET offset;
00952 ST *alloc_st;
00953 PREG_NUM saved_sp;
00954 } alloc_correspond_s;
00955
00956
00957 static alloc_correspond_s *alloc_correspond;
00958
00959
00960
00961
00962
00963 static void F90_Lower_Init(void) {
00964 TYPE_ID mtype1;
00965 TYPE_ID mtype2;
00966 PREG_NUM rreg2;
00967
00968
00969 if (! f90_lower_pool) {
00970 f90_lower_pool = &f90_lower_pool_s;
00971 MEM_POOL_Initialize(f90_lower_pool,"f90_lower_pool",TRUE);
00972 }
00973 MEM_POOL_Push(f90_lower_pool);
00974
00975
00976 f90_lower_map = WN_MAP_Create(f90_lower_pool);
00977
00978
00979 if (WHIRL_Return_Info_On) {
00980
00981 RETURN_INFO return_info = Get_Return_Info (Be_Type_Tbl(Pointer_type),
00982 Use_Simulated);
00983
00984 if (RETURN_INFO_count(return_info) <= 2) {
00985
00986 mtype1 = RETURN_INFO_mtype (return_info, 0);
00987 mtype2 = RETURN_INFO_mtype (return_info, 1);
00988 pointer_return_reg = RETURN_INFO_preg (return_info, 0);
00989 rreg2 = RETURN_INFO_preg (return_info, 1);
00990 }
00991
00992 else
00993 Fail_FmtAssertion ("F90_Lower_Init: more than 2 return registers");
00994 }
00995
00996 else {
00997 Get_Return_Mtypes(Be_Type_Tbl(Pointer_type), Use_Simulated, &mtype1, &mtype2);
00998 Get_Return_Pregs(mtype1, mtype2, &pointer_return_reg, &rreg2);
00999 }
01000
01001 num_alloca = 0;
01002 max_num_alloca = 0;
01003
01004
01005 pointer8 = Pointer_Size == 8;
01006 if (pointer8) {
01007 OPCmpy = OPC_I8MPY;
01008 OPCadd = OPC_I8ADD;
01009 OPCsub = OPC_I8SUB;
01010 OPCmod = OPC_I8MOD;
01011 OPCint = OPC_I8INTCONST;
01012 OPCtriplet = OPC_I8TRIPLET;
01013 OPCarrsection = OPC_U8ARRSECTION;
01014 INTRNalloca = INTRN_U8I8ALLOCA;
01015 INTRNfree = INTRN_U8FREE;
01016 INTRNmalloc = INTRN_U8I8MALLOC;
01017 INTRNgetstack = INTRN_U8READSTACKPOINTER;
01018 INTRNsetstack = INTRN_U8I8SETSTACKPOINTER;
01019 doloop_ty = MTYPE_I8;
01020 } else {
01021 OPCmpy = OPC_I4MPY;
01022 OPCadd = OPC_I4ADD;
01023 OPCsub = OPC_I4SUB;
01024 OPCmod = OPC_I4MOD;
01025 OPCint = OPC_I4INTCONST;
01026 OPCtriplet = OPC_I4TRIPLET;
01027 OPCarrsection = OPC_U4ARRSECTION;
01028 INTRNalloca = INTRN_U4I4ALLOCA;
01029 INTRNfree = INTRN_U4FREE;
01030 INTRNmalloc = INTRN_U4I4MALLOC;
01031 INTRNgetstack = INTRN_U4READSTACKPOINTER;
01032 INTRNsetstack = INTRN_U4I4SETSTACKPOINTER;
01033 doloop_ty = MTYPE_I4;
01034 }
01035 char_ty = TY_IDX_ZERO;
01036 temp_allocations_inserted = FALSE;
01037 array_statement_seen = FALSE;
01038 }
01039
01040
01041
01042
01043 static void F90_Lower_Term(void) {
01044
01045 WN_MAP_Delete(f90_lower_map);
01046
01047 MEM_POOL_Pop(f90_lower_pool);
01048 }
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062 static void add_alloca_correspondence(ST *alloca_data, WN_OFFSET offset, PREG_NUM alloca_save_sp)
01063 {
01064 #define ALLOCA_CHUNK_SIZE 64
01065 num_alloca += 1;
01066 if (num_alloca > max_num_alloca) {
01067
01068 if (max_num_alloca == 0) {
01069 alloc_correspond = TYPE_MEM_POOL_ALLOC_N(alloc_correspond_s,f90_lower_pool,ALLOCA_CHUNK_SIZE);
01070 } else {
01071 alloc_correspond = TYPE_MEM_POOL_REALLOC_N(alloc_correspond_s,
01072 f90_lower_pool,alloc_correspond,
01073 max_num_alloca,
01074 max_num_alloca + ALLOCA_CHUNK_SIZE);
01075 }
01076 max_num_alloca += ALLOCA_CHUNK_SIZE;
01077 }
01078 alloc_correspond[num_alloca-1].offset = offset;
01079 alloc_correspond[num_alloca-1].alloc_st = alloca_data;
01080 alloc_correspond[num_alloca-1].saved_sp = alloca_save_sp;
01081 }
01082
01083 static PREG_NUM get_existing_sp(ST * alloca_data, WN_OFFSET offset)
01084 {
01085 INT i;
01086 for (i=0; i < num_alloca; i++) {
01087 if (alloc_correspond[i].offset == offset &&
01088 alloc_correspond[i].alloc_st == alloca_data) {
01089 return (alloc_correspond[i].saved_sp);
01090 }
01091 }
01092 return (0);
01093 }
01094
01095 static PREG_NUM get_corresponding_sp(ST * alloca_data, WN_OFFSET offset)
01096 {
01097 INT i;
01098 for (i=0; i < num_alloca; i++) {
01099 if (alloc_correspond[i].offset == offset &&
01100 alloc_correspond[i].alloc_st == alloca_data) {
01101 return (alloc_correspond[i].saved_sp);
01102 }
01103 }
01104 DevAssert(0,("Couldn't find sp corresponding to ST/offset 0x%x %d",alloca_data,offset));
01105 return (0);
01106 }
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117 static F90_LOWER_AUX_DATA * F90_Lower_New_Aux_Data(INT ndim)
01118 {
01119 F90_LOWER_AUX_DATA *r;
01120 WN **iter_count;
01121 mINT16 *perm_index;
01122 DIR_FLAG *directions;
01123 INT i;
01124
01125
01126 r = TYPE_MEM_POOL_ALLOC( F90_LOWER_AUX_DATA,f90_lower_pool);
01127 SET_NDIM(r,ndim);
01128 SET_KNOWN_INDEPENDENT(r,FALSE);
01129 SET_NO_PROMPF_INFO(r,FALSE);
01130 SET_COPY_FLAG(r,COPY_NONE);
01131
01132
01133 if (ndim > 0) {
01134 iter_count = TYPE_MEM_POOL_ALLOC_N(WN *,f90_lower_pool,ndim);
01135 perm_index = TYPE_MEM_POOL_ALLOC_N(mINT16,f90_lower_pool,ndim);
01136 directions = TYPE_MEM_POOL_ALLOC_N(DIR_FLAG,f90_lower_pool,ndim);
01137
01138 SET_ITER_COUNT_P(r,iter_count);
01139 SET_PERM_INDEX_P(r,perm_index);
01140 SET_DIRECTION_P(r,directions);
01141 }
01142
01143
01144
01145 SET_PRELIST(r,WN_CreateBlock());
01146 SET_POSTLIST(r,WN_CreateBlock());
01147 SET_ALLOC_PRELIST(r,WN_CreateBlock());
01148 SET_DEALLOC_POSTLIST(r,WN_CreateBlock());
01149
01150
01151 for (i=0; i < ndim; i++) {
01152 SET_PERM_INDEX(r,i,i);
01153 SET_DIRECTION(r,i,DIR_DONTCARE);
01154 }
01155 return (r);
01156 }
01157
01158
01159
01160 static F90_LOWER_AUX_DATA * F90_Lower_Copy_Aux_Data(F90_LOWER_AUX_DATA * adata)
01161 {
01162 F90_LOWER_AUX_DATA * r;
01163 INT ndim;
01164 INT i;
01165 ndim = NDIM(adata);
01166
01167 r = F90_Lower_New_Aux_Data(ndim);
01168 for (i=0; i < ndim; i++) {
01169 SET_PERM_INDEX(r,i,PERM_INDEX(adata,i));
01170 SET_ITER_COUNT(r,i,WN_COPY_Tree(ITER_COUNT(adata,i)));
01171 SET_DIRECTION(r,i,DIRECTION(adata,i));
01172 }
01173
01174 return (r);
01175 }
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187 static char * create_tempname(const char * name)
01188 {
01189 static char buf[64];
01190 num_temps += 1;
01191 sprintf(buf,"%s_%d",name,num_temps);
01192 return(buf);
01193 }
01194
01195
01196
01197
01198 static ST * new_temp_st(const char * name)
01199 {
01200 ST * st;
01201 st = New_ST();
01202 ST_Init(st,Save_Str(create_tempname(name)),
01203 CLASS_VAR, SCLASS_AUTO, EXPORT_LOCAL, (TY_IDX) 0);
01204
01205 Add_Pragma_To_MP_Regions (&F90_MP_Region,WN_PRAGMA_LOCAL,
01206 st,0,WN_MAP_UNDEFINED,FALSE);
01207 #ifdef KEY
01208
01209
01210
01211 Set_ST_is_temp_var(st);
01212 #endif
01213 return (st);
01214 }
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225 static WN * get_first_dimension_ubound(TY_IDX ty)
01226 {
01227 ST_IDX bound_st_idx;
01228 TY_IDX bound_st_ty;
01229 WN *r;
01230
01231 bound_st_idx = TY_AR_ubnd_var(ty,0);
01232 bound_st_ty = ST_type(bound_st_idx);
01233
01234 r = WN_Ldid(TY_mtype(bound_st_ty),0,bound_st_idx,bound_st_ty);
01235 return (r);
01236 }
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259 static ST * F90_Lower_Create_Temp(WN **alloc_block, WN **free_block, WN **size,
01260 INT ndim, TY_IDX ty,
01261 WN *element_size)
01262 {
01263 INT i;
01264 WN *total_size,*save_temp;
01265 ST *st;
01266 TY_IDX pty;
01267 OPCODE callop;
01268 WN *call;
01269 INTRINSIC aintrin,fintrin;
01270 BOOL is_var_len_char = FALSE;
01271 WN *cur_size;
01272
01273
01274 st = new_temp_st("@f90");
01275
01276 if (TY_is_character(ty) &&
01277 TY_kind(ty) == KIND_ARRAY &&
01278 TY_size(ty) == 0 &&
01279 ! ARB_const_ubnd(TY_arb(ty))) {
01280
01281 is_var_len_char = TRUE;
01282 }
01283
01284 if (ndim > 0 || is_var_len_char) {
01285 pty = Make_Pointer_Type(ty);
01286 Set_ST_type(st,pty);
01287 Set_ST_pt_to_unique_mem(st);
01288 } else {
01289 Set_ST_type(st,ty);
01290 }
01291
01292 if (ndim == 0 && ! is_var_len_char) {
01293 return (st);
01294 }
01295
01296 DevAssert((alloc_block),("missing alloc_block in F90_Lower_Create_Temp"));
01297
01298
01299 if (!*alloc_block) *alloc_block = WN_CreateBlock();
01300 if (!*free_block) *free_block = WN_CreateBlock();
01301
01302
01303 if (element_size) {
01304 total_size = WN_COPY_Tree(element_size);
01305 } else {
01306 if (TY_size(ty) != 0) {
01307 total_size = WN_CreateIntconst(OPCint,TY_size(ty));
01308 } else {
01309 total_size = get_first_dimension_ubound(ty);
01310 }
01311 }
01312 for (i=0; i < ndim; i++) {
01313 cur_size = WN_COPY_Tree(size[i]);
01314 #ifdef KEY
01315 if (MTYPE_size_min(WN_rtype(cur_size)) != MTYPE_size_min(WN_rtype(total_size)))
01316 cur_size = WN_Cvt(WN_rtype(cur_size), WN_rtype(total_size), cur_size);
01317 #endif
01318 total_size = WN_CreateExp2(OPCmpy,total_size,cur_size);
01319 }
01320
01321 if (Heap_Allocation_Threshold == -1) {
01322 aintrin = INTRN_F90_STACKTEMPALLOC;
01323 fintrin = INTRN_F90_STACKTEMPFREE;
01324 } else if (Heap_Allocation_Threshold == 0) {
01325 aintrin = INTRN_F90_HEAPTEMPALLOC;
01326 fintrin = INTRN_F90_HEAPTEMPFREE;
01327 } else {
01328 aintrin = INTRN_F90_DYNAMICTEMPALLOC;
01329 fintrin = INTRN_F90_DYNAMICTEMPFREE;
01330 }
01331
01332
01333 callop = OPCODE_make_op(OPR_INTRINSIC_OP, Pointer_type, MTYPE_V);
01334 call = WN_CreateParm(Pointer_type, total_size, Be_Type_Tbl(Pointer_type),
01335 WN_PARM_BY_VALUE);
01336 call = WN_Create_Intrinsic(callop,aintrin,1,&call);
01337 save_temp = WN_Stid(Pointer_type,(WN_OFFSET) 0,st,pty,call);
01338 WN_INSERT_BlockLast(*alloc_block,save_temp);
01339
01340
01341 callop = OPCODE_make_op(OPR_INTRINSIC_CALL, Pointer_type, MTYPE_V);
01342 call = WN_Ldid(Pointer_type,(WN_OFFSET) 0, st, pty);
01343 call = WN_CreateParm(Pointer_type,call,pty,WN_PARM_BY_VALUE);
01344 call = WN_Create_Intrinsic(callop,fintrin,1,&call);
01345 WN_INSERT_BlockFirst(*free_block,call);
01346
01347
01348 return (st);
01349 }
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361 static BOOL F90_Lower_Alloc_Dealloc(WN *stmt, WN *block)
01362 {
01363 static OPCODE callop=OPCODE_UNKNOWN;
01364 OPERATOR opr;
01365 WN *k0,*k0k0;
01366 WN *call;
01367 WN * save_sp;
01368 PREG_NUM free_preg,sp_tmp;
01369 INTRINSIC intr;
01370
01371 WN * heap_block;
01372 WN * stack_block;
01373 WN * tmp_stmt;
01374 WN * if_stmt;
01375 WN * alloc_size;
01376 WN * preg_load;
01377 TYPE_ID alloc_type;
01378
01379 if (callop==OPCODE_UNKNOWN) callop = OPCODE_make_op(OPR_INTRINSIC_CALL, Pointer_type, MTYPE_V);
01380
01381 opr = WN_operator(stmt);
01382
01383 if (opr == OPR_INTRINSIC_CALL) {
01384 intr = WN_GET_INTRINSIC(stmt);
01385
01386 if (intr == INTRN_F90_HEAPTEMPFREE) {
01387 WN_intrinsic(stmt) = INTRNfree;
01388 WN_Set_Call_Does_Mem_Free(stmt);
01389
01390
01391 } else if (intr == INTRN_F90_STACKTEMPFREE) {
01392 k0 = WN_kid0(stmt);
01393 k0k0 = WN_kid0(k0);
01394
01395 DevAssert((WN_operator(k0k0)==OPR_LDID),("Lower_Alloc_Dealloc saw something bad"));
01396 free_preg = get_corresponding_sp(WN_st(k0k0),WN_offset(k0k0));
01397 preg_load = WN_LdidPreg(Pointer_type,free_preg);
01398
01399 if (Alloca_Dealloca_On) {
01400 call = WN_CreateDealloca(2);
01401 WN_INSERT_BlockBefore(block,stmt,call);
01402 WN_kid1(call) = k0k0;
01403 WN_kid0(call) = preg_load;
01404
01405 WN_EXTRACT_FromBlock(block,stmt);
01406 WN_Delete(k0);
01407 WN_Delete(stmt);
01408 } else {
01409
01410 WN_intrinsic(stmt) = INTRNsetstack;
01411 WN_Set_Call_Does_Mem_Free(stmt);
01412 WN_DELETE_Tree(k0k0);
01413 WN_kid0(WN_kid0(stmt)) = preg_load;
01414 }
01415
01416
01417 } else if (intr == INTRN_F90_DYNAMICTEMPFREE) {
01418
01419
01420 k0 = WN_kid0(WN_kid0(stmt));
01421 DevAssert((WN_operator(k0)==OPR_LDID),("Lower_Alloc_Dealloc saw something bad"));
01422 free_preg = get_corresponding_sp(WN_st(k0),WN_offset(k0));
01423 preg_load = WN_LdidPreg(Pointer_type,free_preg);
01424
01425 heap_block = WN_CreateBlock();
01426 stack_block = WN_CreateBlock();
01427
01428
01429 if_stmt = WN_EQ(Pointer_Mtype,WN_LdidPreg(Pointer_type,free_preg),WN_Zerocon(Pointer_Mtype));
01430 if_stmt = WN_CreateIf(if_stmt,heap_block,stack_block);
01431 WN_INSERT_BlockBefore(block,stmt,if_stmt);
01432 WN_EXTRACT_FromBlock(block,stmt);
01433
01434
01435 tmp_stmt = WN_COPY_Tree(stmt);
01436 WN_intrinsic(tmp_stmt) = INTRNfree;
01437 WN_Set_Call_Does_Mem_Free(tmp_stmt);
01438 WN_INSERT_BlockFirst(heap_block,tmp_stmt);
01439
01440
01441 if (Alloca_Dealloca_On) {
01442 call = WN_CreateDealloca(2);
01443 WN_INSERT_BlockFirst(stack_block,call);
01444 WN_kid0(call) = preg_load;
01445 WN_kid1(call) = WN_kid0(WN_kid0(stmt));
01446 WN_Delete(WN_kid0(stmt));
01447 WN_Delete(stmt);
01448 } else {
01449 WN_INSERT_BlockFirst(stack_block,stmt);
01450 WN_intrinsic(stmt) = INTRNsetstack;
01451 WN_Set_Call_Does_Mem_Free(stmt);
01452 WN_DELETE_Tree(k0);
01453 WN_kid0(WN_kid0(stmt)) = preg_load;
01454 }
01455 }
01456
01457 } else if (opr == OPR_STID) {
01458 k0 = WN_kid0(stmt);
01459 if (WN_operator(k0) == OPR_INTRINSIC_OP) {
01460
01461 if (WN_GET_INTRINSIC(k0) == INTRN_F90_HEAPTEMPALLOC) {
01462
01463 k0k0 = WN_kid0(k0);
01464 call = WN_Create_Intrinsic(callop, INTRNmalloc, 1, &k0k0);
01465 WN_Set_Call_Default_Flags(call);
01466 WN_Set_Call_Does_Mem_Alloc(call);
01467 WN_INSERT_BlockBefore(block,stmt,call);
01468 WN_Delete(k0);
01469 WN_kid0(stmt) = WN_LdidPreg(Pointer_type,pointer_return_reg);
01470
01471
01472 } else if (WN_GET_INTRINSIC(k0) == INTRN_F90_STACKTEMPALLOC) {
01473 Set_PU_has_alloca(*current_pu);
01474 sp_tmp = get_existing_sp(WN_st(stmt),WN_offset(stmt));
01475 if (sp_tmp == 0) {
01476 sp_tmp = Create_Preg(Pointer_type,create_tempname("@f90sp"));
01477
01478 add_alloca_correspondence(WN_st(stmt),WN_offset(stmt), sp_tmp);
01479 }
01480
01481 if (Alloca_Dealloca_On) {
01482
01483 call = WN_CreateAlloca(WN_Zerocon(Pointer_Mtype));
01484 call = WN_StidPreg(Pointer_Mtype,sp_tmp,call);
01485 WN_INSERT_BlockBefore(block,stmt,call);
01486
01487 k0k0 = WN_kid0(k0);
01488 WN_Delete(k0);
01489 k0 = k0k0;
01490 k0k0 = WN_kid0(k0);
01491 WN_Delete(k0);
01492 call = WN_CreateAlloca(k0k0);
01493 WN_kid0(stmt) = call;
01494 } else {
01495
01496 call = WN_Create_Intrinsic(callop,INTRNgetstack,0,NULL);
01497 WN_Set_Call_Non_Parm_Ref(call);
01498 WN_Set_Call_Non_Data_Ref(call);
01499 WN_INSERT_BlockBefore(block,stmt,call);
01500
01501 save_sp = WN_LdidPreg(Pointer_type,pointer_return_reg);
01502 save_sp = WN_StidIntoPreg(Pointer_type,sp_tmp,MTYPE_To_PREG(Pointer_type), save_sp);
01503 WN_INSERT_BlockBefore(block,stmt,save_sp);
01504
01505 k0k0 = WN_kid0(k0);
01506 call = WN_Create_Intrinsic(callop,INTRNalloca,1,&k0k0);
01507 WN_Set_Call_Default_Flags(call);
01508 WN_Set_Call_Does_Mem_Alloc(call);
01509 WN_INSERT_BlockBefore(block,stmt,call);
01510 WN_Delete(k0);
01511 WN_kid0(stmt) = WN_LdidPreg(Pointer_type,pointer_return_reg);
01512 }
01513
01514
01515 } else if (WN_GET_INTRINSIC(k0) == INTRN_F90_DYNAMICTEMPALLOC) {
01516 Set_PU_has_alloca(*current_pu);
01517 heap_block = WN_CreateBlock();
01518 stack_block = WN_CreateBlock();
01519
01520 alloc_size = WN_COPY_Tree(WN_kid0(WN_kid0(k0)));
01521 alloc_type = WN_rtype(alloc_size);
01522 if_stmt = WN_GT(alloc_type,alloc_size,WN_Intconst(alloc_type,Heap_Allocation_Threshold));
01523 if_stmt = WN_CreateIf(if_stmt,heap_block,stack_block);
01524 WN_INSERT_BlockBefore(block,stmt,if_stmt);
01525 WN_EXTRACT_FromBlock(block,stmt);
01526
01527
01528 tmp_stmt = WN_COPY_Tree(stmt);
01529 sp_tmp = get_existing_sp(WN_st(stmt),WN_offset(stmt));
01530 if (sp_tmp == 0) {
01531 sp_tmp = Create_Preg(Pointer_type,create_tempname("@f90sp"));
01532
01533 add_alloca_correspondence(WN_st(stmt),WN_offset(stmt), sp_tmp);
01534 }
01535
01536 if (Alloca_Dealloca_On) {
01537 save_sp = WN_CreateAlloca(WN_Zerocon(Pointer_Mtype));
01538 save_sp = WN_StidPreg(Pointer_Mtype,sp_tmp,save_sp);
01539 WN_INSERT_BlockLast(stack_block,save_sp);
01540
01541 k0 = WN_kid0(tmp_stmt);
01542 k0k0 = WN_kid0(k0);
01543 WN_Delete(k0);
01544 k0 = k0k0;
01545 k0k0 = WN_kid0(k0);
01546 WN_Delete(k0);
01547 call = WN_CreateAlloca(k0k0);
01548 WN_kid0(tmp_stmt) = call;
01549 WN_INSERT_BlockLast(stack_block,tmp_stmt);
01550 } else {
01551 call = WN_Create_Intrinsic(callop,INTRNgetstack,0,NULL);
01552 WN_Set_Call_Non_Parm_Ref(call);
01553 WN_Set_Call_Non_Data_Ref(call);
01554 WN_INSERT_BlockLast(stack_block,call);
01555
01556 save_sp = WN_LdidPreg(Pointer_type,pointer_return_reg);
01557 save_sp = WN_StidIntoPreg(Pointer_type,sp_tmp,MTYPE_To_PREG(Pointer_type), save_sp);
01558 WN_INSERT_BlockLast(stack_block,save_sp);
01559
01560 k0 = WN_kid0(tmp_stmt);
01561 k0k0 = WN_kid0(k0);
01562 call = WN_Create_Intrinsic(callop,INTRNalloca,1,&k0k0);
01563 WN_Set_Call_Default_Flags(call);
01564 WN_Set_Call_Does_Mem_Alloc(call);
01565 WN_INSERT_BlockLast(stack_block,call);
01566 WN_Delete(k0);
01567 WN_kid0(tmp_stmt) = WN_LdidPreg(Pointer_type,pointer_return_reg);
01568 WN_INSERT_BlockLast(stack_block,tmp_stmt);
01569 }
01570
01571
01572 save_sp = WN_StidIntoPreg(Pointer_type,sp_tmp,MTYPE_To_PREG(Pointer_type),
01573 WN_Zerocon(Pointer_Mtype));
01574 WN_INSERT_BlockFirst(heap_block,save_sp);
01575 k0 = WN_kid0(stmt);
01576 k0k0 = WN_kid0(k0);
01577 call = WN_Create_Intrinsic(callop, INTRNmalloc, 1, &k0k0);
01578 WN_Set_Call_Default_Flags(call);
01579 WN_Set_Call_Does_Mem_Alloc(call);
01580 WN_INSERT_BlockLast(heap_block,call);
01581 WN_Delete(k0);
01582 WN_kid0(stmt) = WN_LdidPreg(Pointer_type,pointer_return_reg);
01583 WN_INSERT_BlockLast(heap_block,stmt);
01584
01585 }
01586 }
01587 }
01588
01589 return (TRUE);
01590 }
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609 static WN * F90_Lower_Copy_To_ATemp(WN **alloc_block, WN **free_block, WN **copy_store,
01610 WN *expr, WN **size, INT ndim)
01611 {
01612 ST *temp_st;
01613 TY_IDX temp_ty,ptr_ty;
01614 WN_ESIZE element_size;
01615 WN *arrsection;
01616 WN *arrexp;
01617 WN *store;
01618 WN *load;
01619 WN *arg;
01620 WN *kid0;
01621 WN *stride;
01622 WN *mload_size;
01623 INT i;
01624 OPCODE expr_op;
01625 BOOL is_mexpr;
01626 BOOL is_char;
01627 BOOL multiply_indices=FALSE;
01628 WN *sizemult;
01629 TYPE_ID expr_type;
01630
01631 #ifdef KEY // bug 8083
01632 Set_addr_saved_expr(expr, FALSE);
01633 #endif
01634
01635
01636 is_mexpr = FALSE;
01637 is_char = FALSE;
01638 mload_size = NULL;
01639
01640 expr_op = WN_opcode(expr);
01641 expr_type = OPCODE_rtype(expr_op);
01642 if (expr_type == MTYPE_B) expr_type = MTYPE_I4;
01643
01644 if (OPCODE_operator(expr_op) == OPR_ARRAYEXP) {
01645
01646 kid0 = WN_kid0(expr);
01647 WN_kid0(expr) = WN_Zerocon(MTYPE_I4);
01648 WN_DELETE_Tree(expr);
01649 return F90_Lower_Copy_To_ATemp(alloc_block,free_block,copy_store,kid0,size,ndim);
01650 }
01651
01652 if (expr_op == OPC_MLOAD) {
01653 is_mexpr = TRUE;
01654 mload_size = WN_kid1(expr);
01655 ptr_ty = WN_ty(expr);
01656 temp_ty = TY_pointed(ptr_ty);
01657 if (TY_kind(temp_ty) == KIND_ARRAY) {
01658 temp_ty = TY_AR_etype(temp_ty);
01659 }
01660 is_char = TY_is_character(temp_ty);
01661 if (is_char) {
01662
01663 temp_ty = TY_pointed(ptr_ty);
01664 }
01665 if (WN_operator(mload_size)==OPR_INTCONST) {
01666 element_size = WN_const_val(mload_size);
01667 } else {
01668 element_size = -1;
01669 multiply_indices = TRUE;
01670 }
01671 } else if (expr_op == OPC_MINTRINSIC_OP ||
01672 (OPCODE_operator(expr_op) == OPR_INTRINSIC_OP &&
01673 F90_Is_Transformational(WN_GET_INTRINSIC(expr)) &&
01674 WN_opcode(WN_kid0(expr)) == OPC_MPARM)) {
01675 is_mexpr = TRUE;
01676
01677 arg = WN_kid0(expr);
01678 temp_ty = WN_ty(arg);
01679
01680
01681
01682 if (TY_kind(temp_ty) == KIND_ARRAY) {
01683 temp_ty = TY_AR_etype(temp_ty);
01684 }
01685 is_char = TY_is_character(temp_ty);
01686
01687 ptr_ty = Make_Pointer_Type(temp_ty);
01688 element_size = TY_size(temp_ty);
01689 if (element_size == 0) {
01690 element_size = -1;
01691 multiply_indices = TRUE;
01692 mload_size = get_first_dimension_ubound(temp_ty);
01693 } else {
01694 mload_size = WN_CreateIntconst(OPCint,element_size);
01695 }
01696 } else {
01697 temp_ty = Be_Type_Tbl(expr_type);
01698 element_size = TY_size(temp_ty);
01699 ptr_ty = Make_Pointer_Type(temp_ty);
01700 }
01701
01702 temp_st = F90_Lower_Create_Temp(alloc_block,free_block,size,ndim,temp_ty,mload_size);
01703
01704
01705 arrsection = WN_Create(OPCarrsection,2*ndim+1);
01706
01707 if (TY_is_f90_pointer(ptr_ty)) {
01708 temp_ty = TY_pointed(ptr_ty);
01709 ptr_ty = Make_Pointer_Type(temp_ty);
01710 }
01711 WN_kid0(arrsection) = WN_Ldid(Pointer_type, (WN_OFFSET) 0, temp_st, ptr_ty);
01712 WN_element_size(arrsection) = element_size;
01713 if (multiply_indices) {
01714 sizemult = WN_COPY_Tree(mload_size);
01715 }
01716 for (i=0; i < ndim; i++) {
01717
01718 if (multiply_indices) {
01719 WN_kid(arrsection,i+1) = WN_COPY_Tree(sizemult);
01720 sizemult = WN_CreateExp2(OPCmpy,sizemult,WN_COPY_Tree(size[i]));
01721 } else {
01722 WN_kid(arrsection,i+1) = WN_COPY_Tree(size[i]);
01723 }
01724
01725 stride = WN_CreateIntconst(OPCint,(INT64) 1);
01726 WN_kid(arrsection,i+1+ndim) = WN_CreateExp3(OPCtriplet,
01727 WN_CreateIntconst(OPCint,(INT64) 0),
01728 stride,
01729 WN_COPY_Tree(size[i]));
01730 }
01731 if (multiply_indices) {
01732 WN_DELETE_Tree(sizemult);
01733 }
01734
01735 arrexp = F90_Wrap_ARREXP(arrsection);
01736 if (is_mexpr) {
01737 store = WN_CreateMstore((WN_OFFSET) 0, ptr_ty, expr, arrexp, WN_COPY_Tree(mload_size));
01738 load = WN_CreateMload((WN_OFFSET) 0, ptr_ty,
01739 WN_COPY_Tree(arrsection),WN_COPY_Tree(mload_size));
01740 } else {
01741 store = WN_Istore(expr_type,(WN_OFFSET) 0, ptr_ty, arrexp, expr);
01742 load = WN_RIload(expr_type,expr_type,(WN_OFFSET) 0, ptr_ty, WN_COPY_Tree(arrsection));
01743 }
01744
01745 *copy_store = store;
01746 temp_allocations_inserted = TRUE;
01747 return (load);
01748 }
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761 static WN * F90_Lower_Copy_To_STemp(WN **copy_store,WN *expr)
01762 {
01763 ST *temp_st;
01764 TY_IDX temp_ty,ptr_ty;
01765 WN *lda;
01766 WN *load;
01767 OPCODE expr_op;
01768 TYPE_ID type;
01769 PREG_NUM p;
01770
01771
01772 expr_op = WN_opcode(expr);
01773 if (expr_op == OPC_MLOAD) {
01774 ptr_ty = WN_ty(expr);
01775
01776 temp_ty = TY_pointed(ptr_ty);
01777
01778 ptr_ty = Make_Pointer_Type(temp_ty);
01779 temp_st = F90_Lower_Create_Temp(NULL,NULL,NULL,0,temp_ty,NULL);
01780 lda = WN_Lda(Pointer_type,(WN_OFFSET) 0, temp_st);
01781 *copy_store = WN_CreateMstore((WN_OFFSET) 0, ptr_ty, expr, lda, WN_COPY_Tree(WN_kid1(expr)));
01782 load = WN_CreateMload((WN_OFFSET) 0, ptr_ty, WN_COPY_Tree(lda),WN_COPY_Tree(WN_kid1(expr)));
01783 } else {
01784 type = OPCODE_rtype(expr_op);
01785 p = Create_Preg(type,create_tempname("@f90s"));
01786 *copy_store = WN_StidPreg(type,p,expr);
01787 load = WN_LdidPreg(type,p);
01788 }
01789
01790 return (load);
01791 }
01792
01793
01794
01795
01796
01797
01798
01799
01800 BOOL F90_Insert_All_Prelists(WN *stmt, WN *i_block)
01801 {
01802 WN *block;
01803 F90_LOWER_AUX_DATA *adata;
01804
01805 adata = GET_F90_MAP(stmt);
01806 if (adata) {
01807 block = PRELIST(adata);
01808 if (block) {
01809 WN_INSERT_BlockBefore(i_block,stmt,block);
01810 SET_PRELIST(adata,NULL);
01811 }
01812 block = POSTLIST(adata);
01813 if (block) {
01814 WN_INSERT_BlockAfter(i_block,stmt,block);
01815 SET_POSTLIST(adata,NULL);
01816 }
01817 }
01818 return(TRUE);
01819 }
01820
01821
01822
01823
01824
01825
01826
01827 static BOOL F90_Insert_Temp_Allocations(WN *stmt, WN *i_block)
01828 {
01829 WN *block;
01830 F90_LOWER_AUX_DATA *adata;
01831
01832 adata = GET_F90_MAP(stmt);
01833 if (adata) {
01834 block = ALLOC_PRELIST(adata);
01835 if (block) {
01836 WN_INSERT_BlockBefore(i_block,stmt,block);
01837 SET_ALLOC_PRELIST(adata,NULL);
01838 }
01839 block = DEALLOC_POSTLIST(adata);
01840 if (block) {
01841 WN_INSERT_BlockAfter(i_block,stmt,block);
01842 SET_DEALLOC_POSTLIST(adata,NULL);
01843 }
01844 }
01845 return (TRUE);
01846 }
01847
01848
01849
01850
01851
01852
01853
01854
01855
01856 static void convert_to_reference(WN *wn,WN *block, WN *insert_point)
01857 {
01858 ST *st;
01859 TY_IDX ptr_ty;
01860 TY_IDX ty;
01861 WN *lda;
01862 WN *store;
01863 WN *val;
01864
01865
01866 if ((WN_flag(wn) & WN_PARM_BY_REFERENCE) != 0) return;
01867
01868
01869 ty = WN_ty(wn);
01870 WN_set_flag(wn, WN_PARM_BY_REFERENCE);
01871 WN_set_opcode(wn,OPCODE_make_op(OPR_PARM,Pointer_Mtype,MTYPE_V));
01872
01873 st = new_temp_st("@f90_reftemp");
01874 Set_ST_type(*st,ty);
01875 Set_ST_addr_passed(*st);
01876
01877 ptr_ty = Make_Pointer_Type(ty);
01878 WN_set_ty(wn,ptr_ty);
01879 lda = WN_CreateLda(OPCODE_make_op(OPR_LDA,Pointer_Mtype,MTYPE_V),0,ptr_ty,st);
01880 val = WN_kid0(wn);
01881 WN_kid0(wn) = lda;
01882 store = WN_Stid(TY_mtype(ty),(WN_OFFSET) 0,st,ty,val);
01883
01884 WN_INSERT_BlockBefore(block,insert_point,store);
01885 }
01886
01887
01888 static WN * lower_random_number(WN *rcall, WN *block, WN *insert_point)
01889 {
01890 WN *wn;
01891 TYPE_ID rt;
01892 INTRINSIC intr;
01893 PREG_NUM rreg1,rreg2,rpreg;
01894
01895 intr = WN_GET_INTRINSIC(rcall);
01896 if (intr == INTRN_F8I4RAN) {
01897 rt = MTYPE_F8;
01898 } else {
01899 rt = MTYPE_F4;
01900 }
01901
01902 if (WHIRL_Return_Info_On) {
01903
01904 RETURN_INFO return_info = Get_Return_Info (Be_Type_Tbl(rt),
01905 Use_Simulated);
01906
01907 if (RETURN_INFO_count(return_info) <= 2) {
01908
01909 rreg1 = RETURN_INFO_preg (return_info, 0);
01910 rreg2 = RETURN_INFO_preg (return_info, 1);
01911 }
01912
01913 else
01914 Fail_FmtAssertion ("lower_random_number: more than 2 return registers");
01915 }
01916
01917 else
01918 Get_Return_Pregs(rt,MTYPE_V, &rreg1, &rreg2);
01919
01920 WN_DELETE_Tree(rcall);
01921 rcall = WN_Create_Intrinsic(OPCODE_make_op(OPR_INTRINSIC_CALL,rt,MTYPE_V),intr,0,NULL);
01922 WN_INSERT_BlockBefore(block, insert_point, rcall);
01923 rpreg = Create_Preg(rt,create_tempname("@f90ran"));
01924 wn = WN_StidPreg(rt,rpreg,WN_LdidPreg(rt,rreg1));
01925 WN_INSERT_BlockBefore(block, insert_point, wn);
01926 wn = WN_LdidPreg(rt,rpreg);
01927 return (wn);
01928 }
01929
01930
01931
01932 static WN * lower_char (WN *ival,WN *block, WN *insert_point)
01933 {
01934 ST *st;
01935 TY_IDX ptr_ty;
01936 WN *lda;
01937 WN *istore;
01938 TY *char_ty_p;
01939
01940
01941 if (!char_ty) {
01942 char_ty_p = &New_TY (char_ty) ;
01943
01944 TY_Init(*char_ty_p,1,KIND_SCALAR,MTYPE_I1,Save_Str(".character."));
01945 Set_TY_align(char_ty,1) ;
01946 Set_TY_is_character(*char_ty_p);
01947 }
01948 st = new_temp_st("@f90_chartemp");
01949 Set_ST_type(*st,char_ty);
01950
01951 ptr_ty = Make_Pointer_Type(char_ty);
01952 lda = WN_CreateLda(OPCODE_make_op(OPR_LDA,Pointer_Mtype,MTYPE_V),0,ptr_ty,st);
01953
01954 istore = WN_CreateIstore(OPC_I1ISTORE,0,ptr_ty,WN_kid0(ival),WN_COPY_Tree(lda));
01955 WN_Delete(ival);
01956
01957 WN_INSERT_BlockBefore(block,insert_point,istore);
01958 return (lda);
01959 }
01960
01961
01962
01963 static WN * lower_merge (WN *kids[],WN *block, WN *insert_point)
01964 {
01965 WN *t_case;
01966 WN *f_case;
01967 WN *condition;
01968 TY_IDX ptr_ty;
01969 TY_IDX temp_ty;
01970 ST *temp_st;
01971 WN *lda;
01972 WN *size;
01973 WN *true_block,*false_block;
01974 WN *store;
01975 WN *t_store;
01976 WN *f_store;
01977 WN *result;
01978 WN *alloc_block = NULL;
01979 WN *free_block = NULL;
01980
01981 condition = WN_kid0(kids[0]);
01982 t_case = WN_kid0(kids[1]);
01983 f_case = WN_kid0(kids[2]);
01984 WN_Delete(kids[0]);
01985 WN_Delete(kids[1]);
01986 WN_Delete(kids[2]);
01987
01988 if (WN_opcode(t_case) == OPC_MMLDID ||
01989 WN_opcode(t_case) == OPC_MMILOAD) {
01990
01991 temp_ty = WN_ty(t_case);
01992
01993 temp_st = F90_Lower_Create_Temp(&alloc_block,&free_block,NULL,0,
01994 temp_ty,NULL);
01995
01996 t_store = WN_CreateStid(OPC_MSTID, 0, temp_st, temp_ty, t_case);
01997 f_store = WN_CreateStid(OPC_MSTID, 0, temp_st, temp_ty, f_case);
01998
01999 result = WN_CreateLdid(OPC_MMLDID, 0, temp_st, temp_ty);
02000 }
02001 else {
02002
02003 FmtAssert((WN_opcode(t_case) == OPC_MLOAD),("Expected an MLOAD node"));
02004 FmtAssert((WN_opcode(f_case) == OPC_MLOAD),("Expected an MLOAD node"));
02005
02006 ptr_ty = WN_ty(t_case);
02007
02008 temp_ty = TY_pointed(ptr_ty);
02009 temp_st = F90_Lower_Create_Temp(&alloc_block,&free_block,NULL,0,
02010 temp_ty,NULL);
02011 lda = WN_Lda(Pointer_type,(WN_OFFSET) 0, temp_st);
02012 size = WN_kid1(t_case);
02013
02014 t_store = WN_CreateMstore((WN_OFFSET) 0, ptr_ty, t_case, WN_COPY_Tree(lda), WN_COPY_Tree(size));
02015
02016 f_store = WN_CreateMstore((WN_OFFSET) 0, ptr_ty, f_case, WN_COPY_Tree(lda), WN_COPY_Tree(size));
02017
02018 if (TY_is_character(temp_ty)) {
02019 result = lda;
02020 } else {
02021 result = WN_CreateMload((WN_OFFSET) 0, ptr_ty, lda, WN_COPY_Tree(size));
02022 }
02023 }
02024
02025 true_block = WN_CreateBlock();
02026 false_block = WN_CreateBlock();
02027
02028 WN_INSERT_BlockFirst(true_block,t_store);
02029 WN_INSERT_BlockFirst(false_block,f_store);
02030
02031 if (alloc_block) {
02032 WN_INSERT_BlockBefore(block,insert_point,alloc_block);
02033 }
02034
02035
02036 store = WN_CreateIf(condition,true_block,false_block);
02037 WN_INSERT_BlockBefore(block,insert_point,store);
02038
02039 if (free_block) {
02040 WN_INSERT_BlockAfter(block,insert_point,free_block);
02041 }
02042
02043 return (result);
02044 }
02045
02046 static void F90_Lower_Intrinsic_Fixup_walk(WN *expr, WN *stmt, WN *block)
02047 {
02048 WN *kid;
02049 WN *newkid;
02050 INT i,j,numkids;
02051 INTRINSIC intr;
02052
02053 numkids = WN_kid_count(expr);
02054 for (i=0; i < numkids; i++) {
02055 kid = WN_kid(expr,i);
02056 F90_Lower_Intrinsic_Fixup_walk(kid, stmt, block);
02057 if (WN_operator(kid) == OPR_INTRINSIC_OP) {
02058 intr = WN_GET_INTRINSIC(kid);
02059 switch (intr) {
02060
02061
02062
02063 case INTRN_CEQEXPR:
02064 case INTRN_CNEEXPR:
02065 case INTRN_CGEEXPR:
02066 case INTRN_CGTEXPR:
02067 case INTRN_CLEEXPR:
02068 case INTRN_CLTEXPR:
02069 break;
02070
02071 case INTRN_F8I4RAN:
02072 case INTRN_F4I4RAN:
02073 newkid = lower_random_number(kid,block,stmt);
02074 WN_kid(expr,i) = newkid;
02075 break;
02076
02077 case INTRN_CHAR:
02078 newkid = lower_char(WN_kid0(kid),block,stmt);
02079 WN_kid(expr,i) = newkid;
02080 WN_Delete(kid);
02081 break;
02082
02083 case INTRN_MERGE:
02084 newkid = lower_merge(&WN_kid0(kid),block,stmt);
02085 WN_kid(expr,i) = newkid;
02086 WN_Delete(kid);
02087 break;
02088
02089 default:
02090 if (!INTRN_by_value(intr)) {
02091 for (j=0; j < WN_kid_count(kid); j++) {
02092 convert_to_reference(WN_kid(kid,j),block,stmt);
02093 }
02094 }
02095 break;
02096 }
02097 }
02098 }
02099 }
02100
02101 static BOOL F90_Lower_Intrinsic_Fixup(WN *stmt, WN *block)
02102 {
02103 F90_Lower_Intrinsic_Fixup_walk(stmt,stmt,block);
02104 return (TRUE);
02105 }
02106
02107
02108
02109
02110
02111
02112
02113
02114
02115
02116
02117
02118
02119
02120
02121
02122 static WN * F90_Lower_Copy_Expr_to_Temp(WN *expr, WN *stmt, WN *block, BOOL no_prompf_info=FALSE)
02123 {
02124 INT ndim,i;
02125 WN *sizes[MAX_NDIM];
02126 WN *temp;
02127 WN *copy_store;
02128
02129 F90_LOWER_AUX_DATA *adata,*adatatemp;
02130
02131 adata = GET_F90_MAP(stmt);
02132 if (!adata) {
02133 adata = F90_Lower_New_Aux_Data(0);
02134 SET_F90_MAP(stmt,adata);
02135 }
02136
02137 if (F90_Size_Walk(expr,&ndim,sizes)) {
02138
02139 adatatemp = F90_Lower_New_Aux_Data(ndim);
02140 SET_NO_PROMPF_INFO(adatatemp,no_prompf_info);
02141
02142 for (i=0; i <ndim ; i++) {
02143 SET_ITER_COUNT(adatatemp,i,sizes[i]);
02144 }
02145 temp = F90_Lower_Copy_To_ATemp(&ALLOC_PRELIST(adatatemp),&DEALLOC_POSTLIST(adata),
02146 ©_store,expr,sizes,ndim);
02147 SET_F90_MAP(copy_store,adatatemp);
02148 WN_INSERT_BlockFirst(PRELIST(adatatemp),PRELIST(adata));
02149 WN_INSERT_BlockFirst(ALLOC_PRELIST(adatatemp),ALLOC_PRELIST(adata));
02150 SET_PRELIST(adata,WN_CreateBlock());
02151 SET_ALLOC_PRELIST(adata,WN_CreateBlock());
02152 } else {
02153
02154 temp = F90_Lower_Copy_To_STemp(©_store,expr);
02155 }
02156 WN_INSERT_BlockBefore(block,stmt,copy_store);
02157 return (temp);
02158 }
02159
02160
02161
02162
02163
02164
02165
02166
02167
02168
02169
02170
02171 static void F90_Lower_Init_Dep_Info(DEP_INFO *d, INT ndim)
02172 {
02173 INT i;
02174
02175
02176 SET_DEP_NDIM(d,ndim);
02177 SET_DEP_SUMMARY(d,DEP_INDEPENDENT);
02178
02179
02180 for (i=0; i < MAX_NDIM; i++) {
02181 SET_DEP_DIRECTION(d,i,DIR_DONTCARE);
02182 }
02183 return;
02184 }
02185
02186 static void print_dep_info(DEP_INFO *d)
02187 {
02188 static const char * summ[4] = {"UNK","IND","===","REM"};
02189 static const char * dirr[5] = {"/","+","-","0","?"};
02190 INT i;
02191
02192 fprintf(TFile,"%s ",summ[d->summary]);
02193 if (d->summary == DEP_REMOVABLE) {
02194 fprintf(TFile,":");
02195 for (i=0; i < d->ndim; i++) {
02196 fprintf(TFile," %s",dirr[DEP_DIRECTION(d,i)]);
02197 }
02198 }
02199 fprintf(TFile,"\n");
02200 }
02201
02202
02203
02204
02205
02206
02207
02208
02209
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219
02220
02221
02222
02223
02224
02225
02226
02227
02228
02229
02230
02231
02232
02233
02234 static BOOL F90_Lower_Merge_Dep_Info(DEP_INFO *in1, DEP_INFO *in2)
02235 {
02236
02237 INT ndim1,ndim2;
02238 INT i;
02239 DEP_SUMMARY sum1,sum2;
02240 DIR_FLAG dir1,dir2,dir_merge;
02241 BOOL all_zero;
02242
02243 #define SHOW_DEP_RES if (trace_depinfo) {fprintf(TFile,"M :"); print_dep_info(in1);}
02244
02245 if (trace_depinfo) {
02246 fprintf(TFile,"===============\n1 :");
02247 print_dep_info(in1);
02248 fprintf(TFile,"2 :");
02249 print_dep_info(in2);
02250 }
02251
02252 ndim1 = DEP_NDIM(in1);
02253 ndim2 = DEP_NDIM(in2);
02254 sum1 = DEP_SUMMARY(in1);
02255 sum2 = DEP_SUMMARY(in2);
02256
02257
02258 if ((ndim1 != ndim2) ||
02259 (sum1 == DEP_UNKNOWN) ||
02260 (sum2 == DEP_UNKNOWN)) {
02261 SET_DEP_SUMMARY(in1,DEP_UNKNOWN);
02262 SHOW_DEP_RES;
02263 return (FALSE);
02264 }
02265 if (sum2 == DEP_INDEPENDENT) {
02266 SHOW_DEP_RES;
02267 return (TRUE);
02268 }
02269 if (sum2 == DEP_IDENTICAL) {
02270 if (sum1 == DEP_INDEPENDENT) {
02271 SET_DEP_SUMMARY(in1,DEP_IDENTICAL);
02272 }
02273 SHOW_DEP_RES;
02274 return (TRUE);
02275 }
02276
02277
02278 if (sum1 == DEP_IDENTICAL || sum1 == DEP_INDEPENDENT) {
02279 *in1 = *in2;
02280 SHOW_DEP_RES;
02281 return (TRUE);
02282 }
02283
02284 all_zero = TRUE;
02285 for (i=0; i < ndim1; i++) {
02286 dir1 = DEP_DIRECTION(in1,i);
02287 dir2 = DEP_DIRECTION(in2,i);
02288 if (dir1 == dir2) {
02289 dir_merge = dir1;
02290 } else if (dir1 == DIR_UNKNOWN || dir2 == DIR_UNKNOWN) {
02291 dir_merge = DIR_UNKNOWN;
02292 } else if (dir1 == DIR_ZERO) {
02293 dir_merge = dir2;
02294 } else if (dir2 == DIR_ZERO) {
02295 dir_merge = dir1;
02296 } else if ((dir1 == DIR_POSITIVE && dir2 == DIR_NEGATIVE) ||
02297 (dir2 == DIR_POSITIVE && dir1 == DIR_NEGATIVE)) {
02298 dir_merge = DIR_UNKNOWN;
02299 }
02300 if (dir_merge == DIR_UNKNOWN) {
02301 SET_DEP_SUMMARY(in1,DEP_UNKNOWN);
02302 SHOW_DEP_RES;
02303 return (FALSE);
02304 }
02305 if (dir_merge != DIR_ZERO) all_zero = FALSE;
02306 SET_DEP_DIRECTION(in1,i,dir_merge);
02307 }
02308 if (all_zero) {
02309 SET_DEP_SUMMARY(in1,DEP_IDENTICAL);
02310 }
02311 SHOW_DEP_RES;
02312 return (TRUE);
02313 }
02314
02315
02316
02317
02318
02319
02320
02321
02322
02323
02324 #define F90_FORMAL 1
02325 #define F90_UNALIASED 2
02326 #define F90_BASED 4
02327 #define F90_UNKNOWN 8
02328 #define F90_TARGET 16
02329 #define F90_POINTER 32
02330 #define F90_THROUGH_ARRAY 64
02331 #define F90_THROUGH_EXPR 128
02332 #define F90_EXPR 256
02333 #define F90_ARRSECTION 512
02334 #define F90_INDIRECTION 1024
02335
02336
02337 static void f90_flag_dump(FILE *f, INT flag)
02338 {
02339 fprintf(f,"Flag = 0x%x: ",flag);
02340 if (flag & F90_FORMAL) fprintf(f,"formal,");
02341 if (flag & F90_UNALIASED) fprintf(f,"unaliased,");
02342 if (flag & F90_BASED) fprintf(f,"based,");
02343 if (flag & F90_UNKNOWN) fprintf(f,"unknown,");
02344 if (flag & F90_TARGET) fprintf(f,"target,");
02345 if (flag & F90_POINTER) fprintf(f,"pointer,");
02346 if (flag & F90_THROUGH_ARRAY) fprintf(f,"array,");
02347 if (flag & F90_THROUGH_EXPR) fprintf(f,"texpr,");
02348 if (flag & F90_EXPR) fprintf(f,"expr,");
02349 if (flag & F90_ARRSECTION) fprintf(f,"asect,");
02350 if (flag & F90_INDIRECTION) fprintf(f,"indirect");
02351 fprintf(f,"\n");
02352 }
02353
02354 INT f90_fdump(INT f)
02355 {
02356 f90_flag_dump(stdout,f);
02357 return (0);
02358 }
02359
02360 static const char * f90_depsum_name(DEP_SUMMARY d)
02361 {
02362 switch (d) {
02363 case DEP_UNKNOWN: return ("UNKNOWN");
02364 case DEP_INDEPENDENT: return ("INDEPENDENT");
02365 case DEP_IDENTICAL: return ("IDENTICAL");
02366 case DEP_REMOVABLE: return ("REMOVABLE");
02367 }
02368 return ("error");
02369 }
02370
02371 #define MAX_ADDR_PIECES 128
02372
02373
02374 static WN *lhs_address;
02375 static WN *lhs_arrsection;
02376 static ST *lhs_sym;
02377 static WN *lhs_pieces[MAX_ADDR_PIECES];
02378 static INT lhs_num_pieces;
02379 static INT64 lhs_const_offset,lhs_base_offset,lhs_size;
02380 static INT lhs_flag;
02381 static TY_IDX lhs_ty;
02382
02383
02384 static ST *rhs_sym;
02385 static WN *rhs_pieces[MAX_ADDR_PIECES];
02386 static INT rhs_num_pieces;
02387 static INT64 rhs_const_offset,rhs_base_offset,rhs_size;
02388 static INT rhs_flag;
02389 static TY_IDX rhs_ty;
02390
02391
02392 static BOOL is_f90_pointer(WN *addr)
02393 {
02394 OPERATOR opr;
02395 ST *st;
02396 opr = WN_operator(addr);
02397 if (opr == OPR_LDID || opr == OPR_LDA) {
02398 st = WN_st(addr);
02399 if (ST_sym_class(st) == CLASS_VAR) {
02400 return (ST_is_f90_pointer(st));
02401 } else {
02402 return (FALSE);
02403 }
02404 } else if (opr == OPR_ILOAD) {
02405 return (TY_is_f90_pointer(TY_pointed(WN_load_addr_ty(addr))) ||
02406 TY_is_f90_pointer(WN_load_addr_ty(addr)));
02407 } else {
02408 return (TRUE);
02409 }
02410 }
02411
02412 static BOOL is_f90_target(WN *addr)
02413 {
02414 OPERATOR opr;
02415 ST *st;
02416 opr = WN_operator(addr);
02417 if (opr == OPR_LDID || opr == OPR_LDA) {
02418 st = WN_st(addr);
02419 if (ST_sym_class(st) == CLASS_VAR) {
02420 return (ST_is_f90_target(st));
02421 } else {
02422 return (FALSE);
02423 }
02424 } else {
02425 return (TY_is_f90_pointer(TY_pointed(WN_load_addr_ty(addr))));
02426 }
02427 }
02428
02429 static BOOL is_f90_formal(WN *addr)
02430 {
02431 OPERATOR opr;
02432 WN *kid;
02433 ST *st;
02434 opr = WN_operator(addr);
02435 if (opr == OPR_LDID || opr == OPR_LDA) {
02436 st = WN_st(addr);
02437 return ((ST_sclass(st) == SCLASS_FORMAL) ||
02438 (ST_sclass(st) == SCLASS_FORMAL_REF));
02439 } else if (opr == OPR_ILOAD) {
02440 kid = WN_kid0(addr);
02441 opr = WN_operator(kid);
02442 if (opr == OPR_LDID || opr == OPR_LDA) {
02443 st = WN_st(kid);
02444 return ((ST_sclass(st) == SCLASS_FORMAL) ||
02445 (ST_sclass(st) == SCLASS_FORMAL_REF));
02446 } else {
02447 return (FALSE);
02448 }
02449 }
02450 return (FALSE);
02451 }
02452
02453 #define ADD_PIECE(x) if (*num_pieces < MAX_ADDR_PIECES) { \
02454 pieces[*num_pieces] = (x); \
02455 *num_pieces = *num_pieces + 1; \
02456 } else { \
02457 *sym = NULL; \
02458 *flag = F90_UNKNOWN; \
02459 done = TRUE; \
02460 continue; \
02461 }
02462
02463
02464 static void Analyze_one_address(WN *a, ST **sym, WN **pieces, INT *num_pieces,
02465 INT64 *const_offset, INT64 *base_offset, INT64 *size,
02466 INT *flag, TY_IDX *ty)
02467 {
02468 OPERATOR opr,opr1;
02469 ST *s;
02470 TY_IDX t;
02471 WN *addr;
02472 BOOL done;
02473 WN *kid;
02474
02475 *base_offset = 0;
02476 *size = 0;
02477 *sym = NULL;
02478 *num_pieces = 0;
02479 *flag = 0;
02480 *ty = (TY_IDX)0;
02481 addr = a;
02482 done = FALSE;
02483
02484 while (!done) {
02485 opr = WN_operator(addr);
02486 if (opr == OPR_LDID) {
02487 ADD_PIECE(addr);
02488 if (trace_dependence) fprintf(TFile," Analyze_one_address (LDID): ");
02489
02490 s = WN_st(addr);
02491 t = WN_ty(addr);
02492 *const_offset += WN_offset(addr);
02493 *ty = t;
02494 *sym = s;
02495 if (ST_sym_class(s) == CLASS_CONST) {
02496 *flag = F90_UNALIASED;
02497
02498 return;
02499 }
02500 if (ST_sclass(s) == SCLASS_FORMAL || ST_sclass(s) == SCLASS_FORMAL_REF ) {
02501 *flag |= F90_FORMAL | F90_UNALIASED;
02502 } else if (ST_sclass(s) == SCLASS_REG) {
02503 DevWarn(("Should not see in PREG in F90 alias analysis"));
02504 } else {
02505
02506
02507 *flag |= F90_INDIRECTION;
02508 Base_Symbol_And_Offset(s,sym,base_offset);
02509 if (ST_pt_to_unique_mem(s)) {
02510 *flag |= F90_UNALIASED;
02511 }
02512 if (ST_is_f90_target(s)) {
02513 *flag |= F90_TARGET;
02514 }
02515 if (ST_is_f90_pointer(s)) {
02516 *flag |= F90_POINTER;
02517 }
02518 }
02519 if (TY_kind(t) != KIND_POINTER) {
02520
02521 *flag |= F90_EXPR;
02522 }
02523 done = TRUE;
02524 } else if (opr == OPR_LDA) {
02525 ADD_PIECE(addr);
02526 if (trace_dependence) fprintf(TFile," Analyze_one_address (LDA): ");
02527
02528 s = WN_st(addr);
02529 t = ST_type(s);
02530 *sym = s;
02531 *ty = t;
02532 *const_offset += WN_offset(addr);
02533 if (ST_sym_class(s) == CLASS_CONST) {
02534 *flag = F90_UNALIASED;
02535
02536 return;
02537 }
02538 Base_Symbol_And_Offset(s,sym,base_offset);
02539 *size = TY_size(t);
02540 if (ST_is_f90_target(s)) {
02541 *flag |= F90_TARGET;
02542 }
02543 if (ST_is_f90_pointer(s)) {
02544 *flag |= F90_POINTER;
02545 }
02546 if (!*flag & (F90_TARGET | F90_POINTER)) {
02547
02548 *flag |= F90_UNALIASED;
02549 }
02550 done = TRUE;
02551 } else if (opr == OPR_ARRAY || opr == OPR_ARRSECTION || opr == OPR_ILOAD) {
02552 if (opr == OPR_ARRSECTION) {
02553 *flag |= F90_ARRSECTION;
02554 } else if (opr == OPR_ILOAD) {
02555 *flag |= F90_INDIRECTION;
02556
02557 if (is_f90_pointer(addr)) {
02558 *flag |= F90_POINTER;
02559 }
02560 }
02561
02562 ADD_PIECE(addr);
02563 addr = WN_kid0(addr);
02564 *flag |= F90_THROUGH_ARRAY;
02565 if (trace_dependence) fprintf(TFile," Analyze_one_address (ARRAY/ARRSECT %d)\n",*num_pieces);
02566 continue;
02567 } else if (opr == OPR_ARRAYEXP) {
02568
02569 addr = WN_kid0(addr);
02570 continue;
02571 } else if (opr == OPR_ADD) {
02572 kid = WN_kid1(addr);
02573 if (WN_operator(kid) == OPR_INTCONST) {
02574 ADD_PIECE(kid);
02575 addr = WN_kid0(addr);
02576 if (trace_dependence) fprintf(TFile," Analyze_one_address (Add %lld)\n",WN_const_val(kid));
02577 continue;
02578 }
02579 kid = WN_kid0(addr);
02580 if (WN_operator(kid) == OPR_INTCONST) {
02581 ADD_PIECE(kid);
02582 addr = WN_kid1(addr);
02583 if (trace_dependence) fprintf(TFile," Analyze_one_address (Add %lld)\n",WN_const_val(kid));
02584 continue;
02585 }
02586
02587
02588
02589 ADD_PIECE(addr);
02590 opr1 = WN_operator(WN_kid0(addr));
02591 if (opr1 == OPR_LDID || opr1 == OPR_LDA ||
02592 opr1 == OPR_ARRAY || opr1 == OPR_ARRSECTION) {
02593 addr = WN_kid0(addr);
02594 *flag |= F90_THROUGH_EXPR;
02595 if (trace_dependence) fprintf(TFile," Analyze_one_address (Add expr %d\n)",*num_pieces );
02596 continue;
02597 }
02598 opr1 = WN_operator(WN_kid1(addr));
02599 if (opr1 == OPR_LDID || opr1 == OPR_LDA ||
02600 opr1 == OPR_ARRAY || opr1 == OPR_ARRSECTION) {
02601 addr = WN_kid1(addr);
02602 *flag |= F90_THROUGH_EXPR;
02603 if (trace_dependence) fprintf(TFile," Analyze_one_address (Add expr %d\n)",*num_pieces );
02604 continue;
02605 }
02606
02607 *flag = F90_UNKNOWN;
02608 *sym = NULL;
02609 done = TRUE;
02610 continue;
02611 } else {
02612
02613 *flag = F90_UNKNOWN;
02614 *sym = NULL;
02615 done = TRUE;
02616 continue;
02617 }
02618 }
02619 if (trace_dependence) {
02620 if (*sym) {
02621 fprintf(TFile,"sym: %s, base_offset %lld, const_offset %lld, size %lld\n",
02622 ST_name(*sym),*base_offset,*const_offset,*size);
02623 f90_flag_dump(TFile,*flag);
02624 } else {
02625 fprintf(TFile,"sym not found\n");
02626 }
02627 }
02628
02629 return;
02630 }
02631
02632
02633 static WN * get_difference(WN *t1, WN *t2)
02634 {
02635 INT ty1,ty2;
02636 OPCODE subop;
02637 ty1 = MTYPE_size_reg(WN_rtype(t1));
02638 ty2 = MTYPE_size_reg(WN_rtype(t2));
02639 if (ty1 == 32 && ty2 == 32) {
02640 subop = OPC_I4SUB;
02641 } else {
02642 subop = OPC_I8SUB;
02643 }
02644 return (WN_CreateExp2(subop,t1,t2));
02645 }
02646
02647
02648
02649
02650
02651
02652
02653
02654
02655
02656
02657
02658
02659
02660
02661
02662 #define SHOW_REASON(x) if (trace_dependence){fprintf(TFile,"returns %d %s\n",r,x);}
02663
02664 static DIR_FLAG Analyze_index(WN *i1, WN *i2) {
02665 DIR_FLAG r;
02666 OPERATOR opr1,opr2;
02667 WN *lb1, *ex1, *st1, *st2;
02668 WN *temp,*temp1;
02669 INT64 diff;
02670 INT64 s1,s2,e,l;
02671 BOOL e_constant;
02672 BOOL l_constant;
02673 BOOL s_constant;
02674 BOOL one_scalar;
02675
02676 if (trace_dependence) {
02677 fprintf(TFile,"Analyze Index:\n");
02678 fdump_tree(TFile,i1);
02679 fprintf(TFile,"------\n");
02680 fdump_tree(TFile,i2);
02681 }
02682
02683 r = DIR_UNKNOWN;
02684 opr1 = WN_operator(i1);
02685 opr2 = WN_operator(i2);
02686
02687
02688 if (opr1 == OPR_ARRAYEXP || opr2 == OPR_ARRAYEXP) {
02689 SHOW_REASON("not arrayexp");
02690 return(r);
02691 }
02692
02693
02694 temp = get_difference(WN_COPY_Tree(i1),WN_COPY_Tree(i2));
02695 if (is_constant(temp)) {
02696 diff = WN_const_val(temp);
02697 if (diff == 0) {
02698 r = DIR_ZERO;
02699 SHOW_REASON("equality");
02700 } else {
02701 r = DIR_DONTCARE;
02702 SHOW_REASON("scalar !=");
02703 }
02704 }
02705 WN_DELETE_Tree(temp);
02706 if (r != DIR_UNKNOWN) return (r);
02707
02708
02709 if (opr1 != OPR_TRIPLET && opr2 != OPR_TRIPLET) {
02710 SHOW_REASON("no triplets");
02711 return(r);
02712 }
02713
02714 if (opr1 != OPR_TRIPLET) {
02715
02716 lb1 = get_difference(WN_COPY_Tree(i1),WN_COPY_Tree(WN_kid0(i2)));
02717 ex1 = WN_COPY_Tree(WN_kid2(i2));
02718 st1 = WN_COPY_Tree(WN_kid1(i2));
02719 one_scalar = TRUE;
02720 } else if (opr2 != OPR_TRIPLET) {
02721
02722 lb1 = get_difference(WN_COPY_Tree(i2),WN_COPY_Tree(WN_kid0(i1)));
02723 ex1 = WN_COPY_Tree(WN_kid2(i1));
02724 st1 = WN_COPY_Tree(WN_kid1(i1));
02725 one_scalar = TRUE;
02726 } else {
02727
02728 ex1 = WN_COPY_Tree(WN_kid2(i1));
02729 lb1 = get_difference(WN_COPY_Tree(WN_kid0(i1)),WN_COPY_Tree(WN_kid0(i2)));
02730 st1 = WN_COPY_Tree(WN_kid1(i1));
02731 st2 = WN_COPY_Tree(WN_kid1(i2));
02732 one_scalar = FALSE;
02733 }
02734
02735
02736 if (one_scalar) {
02737
02738 temp = WN_CreateExp2(OPC_I8MOD,WN_COPY_Tree(lb1),WN_COPY_Tree(st1));
02739 if (!is_constant(temp)) {
02740 SHOW_REASON("l mod s not const");
02741 r = DIR_UNKNOWN;
02742 WN_DELETE_Tree(temp);
02743 } else {
02744 diff = WN_const_val(temp);
02745 WN_DELETE_Tree(temp);
02746
02747 if (diff != 0) {
02748 r = DIR_DONTCARE;
02749 SHOW_REASON("l mod s != 0");
02750 } else {
02751
02752
02753
02754 lb1 = WN_CreateExp2(OPC_I8DIV,lb1,WN_COPY_Tree(st1));
02755 temp = WN_LT(MTYPE_I8,WN_COPY_Tree(lb1),WN_Zerocon(MTYPE_I8));
02756 temp1 = WN_GE(MTYPE_I8,WN_COPY_Tree(lb1),WN_COPY_Tree(ex1));
02757 temp = WN_LIOR(temp,temp1);
02758 if (is_constant(temp) && WN_const_val(temp) != 0) {
02759 r = DIR_DONTCARE;
02760 SHOW_REASON("not contained");
02761 } else {
02762 r = DIR_UNKNOWN;
02763 SHOW_REASON("contained");
02764 }
02765 WN_DELETE_Tree(temp);
02766 }
02767 }
02768 WN_DELETE_Tree(lb1);
02769 WN_DELETE_Tree(st1);
02770 WN_DELETE_Tree(ex1);
02771 SHOW_REASON("returning");
02772 return (r);
02773 }
02774
02775
02776
02777 e_constant = is_constant(ex1);
02778 if (e_constant) e = WN_const_val(ex1);
02779 l_constant = is_constant(lb1);
02780 if (l_constant) l = WN_const_val(lb1);
02781 s_constant = is_constant(st1) && is_constant(st2);
02782 if (s_constant) {
02783 s1 = WN_const_val(st1);
02784 s2 = WN_const_val(st2);
02785 }
02786 WN_DELETE_Tree(lb1);
02787 WN_DELETE_Tree(ex1);
02788
02789 if (trace_dependence) {
02790 if (e_constant) fprintf(TFile,"E = %lld\n",e);
02791 if (l_constant) fprintf(TFile,"L = %lld\n",l);
02792 if (s_constant) fprintf(TFile,"S1,S2 = %lld %lld\n",s1,s2);
02793 }
02794
02795
02796
02797
02798 temp = get_difference(st1,st2);
02799 if (is_constant(temp) && WN_const_val(temp) == 0 && l_constant) {
02800
02801 if (s_constant) {
02802 if (l % s1 != 0) {
02803 r = DIR_DONTCARE;
02804 } else if (l < 0 && s1 > 0 || l < 0 && s1 > 0) {
02805 r = DIR_POSITIVE;
02806 } else if (l > 0 && s1 > 0 || l < 0 && s1 < 0) {
02807 r = DIR_NEGATIVE;
02808 } else if (l == 0) {
02809 r = DIR_ZERO;
02810 }
02811 }
02812 }
02813 WN_DELETE_Tree(temp);
02814 if (r != DIR_UNKNOWN) {
02815 SHOW_REASON("triplet case 1");
02816 return (r);
02817 }
02818
02819
02820 if (e_constant && e == 1 && l_constant) {
02821 if (l == 0) {
02822 r = DIR_ZERO;
02823 } else {
02824 r = DIR_DONTCARE;
02825 }
02826 }
02827 if (r != DIR_UNKNOWN) {
02828 SHOW_REASON("triplet case 2");
02829 return (r);
02830 }
02831
02832
02833 if (l_constant && s_constant) {
02834 r = F90_Lower_Analyze_Triplet(l,s1,s2,e,e_constant,f90_lower_pool);
02835 SHOW_REASON("general constant case");
02836 } else {
02837 SHOW_REASON("done");
02838 }
02839 return (r);
02840 }
02841
02842
02843
02844
02845
02846
02847
02848
02849
02850 static DEP_SUMMARY Analyze_all_indices(WN *lhs, WN *rhs, DEP_INFO *kid_dep)
02851 {
02852 BOOL allzero,allzerounknown;
02853 INT lhskids,rhskids;
02854 INT ndim,i;
02855 DIR_FLAG dir;
02856
02857 lhskids = WN_kid_count(lhs);
02858 rhskids = WN_kid_count(rhs);
02859 if ((lhskids != rhskids) || (WN_element_size(lhs) != WN_element_size(rhs))) {
02860 SET_DEP_SUMMARY(kid_dep,DEP_UNKNOWN);
02861 return (DEP_UNKNOWN);
02862 }
02863 ndim = (lhskids - 1) / 2;
02864 SET_DEP_NDIM(kid_dep,ndim);
02865
02866
02867 allzero = TRUE;
02868 allzerounknown = TRUE;
02869 for (i=0; i < ndim; i++) {
02870 dir = Analyze_index(WN_kid(lhs,i+ndim+1),WN_kid(rhs,i+ndim+1));
02871 SET_DEP_DIRECTION(kid_dep,i,dir);
02872 if (dir == DIR_DONTCARE) {
02873 SET_DEP_SUMMARY(kid_dep,DEP_INDEPENDENT);
02874 allzero = FALSE;
02875 allzerounknown = FALSE;
02876 break;
02877 } else if (dir == DIR_UNKNOWN) {
02878 allzero = FALSE;
02879 } else if (dir == DIR_POSITIVE || dir == DIR_NEGATIVE) {
02880 SET_DEP_SUMMARY(kid_dep,DEP_REMOVABLE);
02881 allzero = FALSE;
02882 allzerounknown = FALSE;
02883 }
02884 }
02885 if (allzero) {
02886
02887 SET_DEP_SUMMARY(kid_dep,DEP_IDENTICAL);
02888 } else if (allzerounknown && !allzero) {
02889
02890 SET_DEP_SUMMARY(kid_dep,DEP_UNKNOWN);
02891 }
02892 return (DEP_SUMMARY(kid_dep));
02893 }
02894
02895
02896
02897
02898
02899
02900
02901
02902
02903
02904
02905
02906
02907
02908 static DEP_SUMMARY check_overlap(INT64 base1, INT64 base2, INT64 size1, INT64 size2)
02909 {
02910 INT64 t;
02911 if (base2 == base1 && size2 == size1) return (DEP_IDENTICAL);
02912
02913
02914 if (base1 > base2) {
02915 t = base2;
02916 base2 = base1;
02917 base1 = t;
02918 t = size2;
02919 size2 = size1;
02920 size1 = t;
02921 }
02922 if (base2 < base1 + size1) {
02923 return (DEP_UNKNOWN);
02924 } else {
02925 return (DEP_INDEPENDENT);
02926 }
02927 }
02928
02929
02930
02931
02932
02933
02934
02935 static DEP_SUMMARY analyze_structure_bases(INT lhs_start, INT rhs_start, INT *lhs_end1, INT *rhs_end1)
02936 {
02937 INT64 lc,rc;
02938 INT i,ri,li,lhs_end,rhs_end;
02939 OPERATOR opr;
02940 WN *lhsa,*rhsa;
02941 DEP_SUMMARY t;
02942 DEP_INFO dummy_dep;
02943
02944 lc = lhs_const_offset;
02945 rc = rhs_const_offset;
02946
02947 for (i = lhs_start; i >= 0; i--) {
02948 opr = WN_operator(lhs_pieces[i]);
02949 if (opr == OPR_ILOAD ||
02950 opr == OPR_LDID) {
02951 break;
02952 } else if (opr == OPR_INTCONST) {
02953 lc += WN_const_val(lhs_pieces[i]);
02954 }
02955 }
02956 lhs_end = i;
02957 if (lhs_end1) *lhs_end1 = lhs_end;
02958
02959 for (i = rhs_start; i >= 0; i--) {
02960 opr = WN_operator(rhs_pieces[i]);
02961 if (opr == OPR_ILOAD ||
02962 opr == OPR_LDID) {
02963 break;
02964 } else if (opr == OPR_INTCONST) {
02965 rc += WN_const_val(rhs_pieces[i]);
02966 }
02967 }
02968 rhs_end = i;
02969 if (rhs_end1) *rhs_end1 = rhs_end;
02970
02971
02972
02973
02974
02975
02976 if (lhs_ty == rhs_ty) {
02977 if (lc != rc) return (DEP_INDEPENDENT);
02978 } else {
02979 return (DEP_UNKNOWN);
02980 }
02981
02982
02983 ri = rhs_start;
02984 li = lhs_start;
02985 while (ri > rhs_end && li > lhs_end) {
02986
02987 for (; li > lhs_end ; li--) {
02988 opr = WN_operator(lhs_pieces[li]);
02989 if (opr == OPR_ARRSECTION || opr == OPR_ARRAY) break;
02990 }
02991 for (; ri > rhs_end ; ri--) {
02992 opr = WN_operator(rhs_pieces[ri]);
02993 if (opr == OPR_ARRSECTION || opr == OPR_ARRAY) break;
02994 }
02995
02996 if (li > lhs_end && ri > rhs_end) {
02997 lhsa = lhs_pieces[li];
02998 rhsa = rhs_pieces[ri];
02999
03000 if (WN_operator(lhsa) == OPR_ARRSECTION &&
03001 WN_operator(rhsa) == OPR_ARRSECTION) {
03002 li--;
03003 ri--;
03004 continue;
03005 }
03006
03007
03008
03009 t = Analyze_all_indices(lhsa,rhsa,&dummy_dep);
03010 if (t == DEP_UNKNOWN || t == DEP_INDEPENDENT) {
03011 return (t);
03012 } else if (t == DEP_REMOVABLE) {
03013
03014 return (DEP_UNKNOWN);
03015 }
03016
03017 li--;
03018 ri--;
03019 } else if ((li > lhs_end && ri <= rhs_end) ||
03020 (ri > rhs_end && li <= lhs_end)) {
03021
03022 return (DEP_UNKNOWN);
03023 } else {
03024 li--;
03025 ri--;
03026 }
03027 }
03028
03029
03030 return (DEP_IDENTICAL);
03031 }
03032
03033
03034
03035
03036
03037
03038
03039
03040
03041
03042
03043
03044
03045
03046
03047
03048
03049
03050 static DEP_SUMMARY Analyze_bases(WN * addr, BOOL is_expr, BOOL is_char)
03051 {
03052 DEP_SUMMARY r;
03053 OPERATOR opr;
03054 INT i;
03055 BOOL same;
03056 INT li,ri;
03057 WN *lhsa,*rhsa;
03058 BOOL l_pointer,l_target,l_formal;
03059 BOOL r_pointer,r_target,r_formal;
03060
03061 r = DEP_UNKNOWN;
03062 if (trace_dependence) fprintf(TFile,"Analyze_bases: ");
03063
03064
03065 if (!is_expr) {
03066 if (WN_Simp_Compare_Trees(lhs_address,addr) == 0) {
03067 if (trace_dependence) fprintf(TFile,"same addresses\n");
03068 return (DEP_IDENTICAL);
03069 }
03070 }
03071
03072 if (trace_dependence) fprintf(TFile,"\n");
03073
03074 if (lhs_sym == NULL || rhs_sym == NULL ||
03075 (F90_UNKNOWN & (lhs_flag | rhs_flag))) {
03076 if (trace_dependence) fprintf(TFile,"unanalyzable symbols\n");
03077 return (DEP_UNKNOWN);
03078 }
03079
03080
03081
03082 if (!((lhs_flag | rhs_flag) & F90_INDIRECTION)) {
03083
03084
03085 if (lhs_sym != rhs_sym) {
03086 if (trace_dependence) fprintf(TFile,"no indirection, different symbols\n");
03087 return (DEP_INDEPENDENT);
03088 }
03089
03090 r = check_overlap(lhs_base_offset,rhs_base_offset,lhs_size,rhs_size);
03091 if (r == DEP_INDEPENDENT || r == DEP_UNKNOWN) {
03092 if (trace_dependence) fprintf(TFile,"same base, overlap check %s\n",f90_depsum_name(r));
03093 return (r);
03094 }
03095
03096
03097 if (!is_char) {
03098 r = analyze_structure_bases(lhs_num_pieces-1,rhs_num_pieces-1,NULL,NULL);
03099 if (trace_dependence) fprintf(TFile,"no indirection, same symbol %s\n",f90_depsum_name(r));
03100 } else {
03101
03102
03103 r = DEP_IDENTICAL;
03104 if (trace_dependence) fprintf(TFile,"no indirection, same symbol (char) %s\n",
03105 f90_depsum_name(r));
03106 }
03107 return (r);
03108 }
03109
03110
03111 if (lhs_num_pieces == rhs_num_pieces) {
03112 same = TRUE;
03113 for (i = 0; i < lhs_num_pieces ; i++) {
03114 if (WN_operator(lhs_pieces[i]) != OPR_ARRSECTION &&
03115 WN_operator(rhs_pieces[i]) != OPR_ARRSECTION) {
03116 if (WN_Simp_Compare_Trees(lhs_pieces[i],rhs_pieces[i]) != 0) {
03117 same = FALSE;
03118 break;
03119 }
03120 }
03121 }
03122 if (same) {
03123 if (trace_dependence) fprintf(TFile,"all but ARRSECTIONs IDENTICAL\n");
03124 return (DEP_IDENTICAL);
03125 }
03126 }
03127
03128
03129
03130 li = 0;
03131 ri = 0;
03132 while (li < lhs_num_pieces) {
03133 opr = WN_operator(lhs_pieces[li]);
03134 if (opr == OPR_ILOAD ||
03135 opr == OPR_LDID ||
03136 opr == OPR_LDA) {
03137 break;
03138 }
03139 li++;
03140 }
03141 while (ri < rhs_num_pieces) {
03142 opr = WN_operator(rhs_pieces[ri]);
03143 if (opr == OPR_ILOAD ||
03144 opr == OPR_LDID ||
03145 opr == OPR_LDA) {
03146 break;
03147 }
03148 ri++;
03149 }
03150 if (ri < rhs_num_pieces && li < lhs_num_pieces) {
03151 lhsa = lhs_pieces[li];
03152 rhsa = rhs_pieces[ri];
03153 if (WN_Simp_Compare_Trees(lhsa,rhsa)==0) {
03154
03155 r = analyze_structure_bases(li-1,ri-1,NULL,NULL);
03156 if (trace_dependence) fprintf(TFile,"same top base addresses %s\n",f90_depsum_name(r));
03157 return (r);
03158 }
03159
03160
03161
03162
03163
03164
03165
03166
03167
03168
03169
03170
03171
03172
03173
03174
03175
03176
03177
03178
03179
03180
03181
03182
03183
03184 l_pointer = is_f90_pointer(lhsa);
03185 l_target = is_f90_target(lhsa);
03186 l_formal = is_f90_formal(lhsa);
03187 r_pointer = is_f90_pointer(rhsa);
03188 r_target = is_f90_target(rhsa);
03189 r_formal = is_f90_formal(rhsa);
03190 if (l_formal) {
03191 l_pointer = l_pointer || ST_is_f90_pointer(lhs_sym);
03192 l_target = l_target || ST_is_f90_target(lhs_sym);
03193 }
03194 if (r_formal) {
03195 r_pointer = r_pointer || ST_is_f90_pointer(rhs_sym);
03196 r_target = r_target || ST_is_f90_target(rhs_sym);
03197 }
03198 if (is_f90_formal(lhsa) || is_f90_formal(rhsa)) {
03199 r = DEP_INDEPENDENT;
03200 } else if ((l_pointer && r_target) ||
03201 (r_pointer && l_target) ||
03202 (r_pointer && l_pointer)) {
03203 if (Alias_F90_Pointer_Unaliased) {
03204 r = DEP_INDEPENDENT;
03205 } else {
03206 r = DEP_UNKNOWN;
03207 }
03208 } else {
03209
03210 if ((rhs_flag ^ lhs_flag) & F90_INDIRECTION) {
03211
03212 r = DEP_INDEPENDENT;
03213 } else if ((rhs_flag | lhs_flag) & F90_UNALIASED) {
03214 r = DEP_INDEPENDENT;
03215 } else {
03216
03217
03218
03219 l_pointer = (lhs_flag & F90_POINTER) != 0;
03220 r_pointer = (rhs_flag & F90_POINTER) != 0;
03221 l_target = l_pointer || ((lhs_flag & F90_TARGET) != 0);
03222 r_target = r_pointer || ((rhs_flag & F90_TARGET) != 0);
03223 if ((l_pointer && r_target) ||
03224 (r_pointer && l_target)) {
03225 r = DEP_UNKNOWN;
03226 } else {
03227 r = DEP_INDEPENDENT;
03228 }
03229 }
03230 }
03231 } else {
03232
03233 r = DEP_UNKNOWN;
03234 }
03235 if (trace_dependence) fprintf(TFile,"bases with indirection %s\n",f90_depsum_name(r));
03236 return (r);
03237 }
03238
03239
03240
03241
03242
03243
03244
03245
03246
03247
03248
03249
03250
03251
03252
03253
03254
03255
03256
03257
03258
03259
03260
03261
03262
03263 static void Dependence_Walk(WN *expr,F90_LOWER_AUX_DATA *adata, DEP_INFO *dep,
03264 BOOL transformational_seen,
03265 WN *parent, INT kidno, INT lhsdim, BOOL is_char_load)
03266 {
03267 OPCODE op;
03268 OPERATOR opr;
03269 DEP_INFO kid_dep;
03270 WN *kid;
03271 WN *copy_store;
03272 INT i,num_kids;
03273 BOOL keep_going;
03274 DEP_SUMMARY base_dep;
03275
03276 op = WN_opcode(expr);
03277 opr = OPCODE_operator(op);
03278
03279 if (opr == OPR_LDID) {
03280 return;
03281 } else if (opr == OPR_ILOAD || opr == OPR_MLOAD || is_char_load) {
03282 if (opr == OPR_ILOAD || opr == OPR_MLOAD) {
03283 rhs_const_offset = WN_offset(expr);
03284 kid = WN_kid0(expr);
03285 if (opr == OPR_MLOAD) {
03286
03287 if (WN_operator(kid) == OPR_ARRAYEXP) {
03288 kid = WN_kid0(kid);
03289 }
03290 if (WN_operator(kid) == OPR_INTRINSIC_OP) {
03291
03292 goto check_kids;
03293 }
03294 }
03295 } else {
03296
03297 rhs_const_offset = 0;
03298 kid = expr;
03299 if (WN_operator(kid) == OPR_ARRAYEXP) {
03300 kid = WN_kid0(kid);
03301 }
03302 }
03303 Analyze_one_address(kid,&rhs_sym,rhs_pieces,&rhs_num_pieces,&rhs_const_offset,
03304 &rhs_base_offset,&rhs_size,&rhs_flag,&rhs_ty);
03305 base_dep = Analyze_bases(expr,FALSE,is_char_load);
03306
03307 if (base_dep == DEP_UNKNOWN) {
03308 if (rhs_sym != NULL && !(rhs_flag & F90_ARRSECTION) && parent) {
03309 kid = F90_Lower_Copy_To_STemp(©_store,expr);
03310 WN_kid(parent,kidno) = kid;
03311 WN_INSERT_BlockLast(PRELIST(adata),copy_store);
03312 SET_DEP_SUMMARY(dep,DEP_INDEPENDENT);
03313 } else {
03314 SET_DEP_SUMMARY(dep,DEP_UNKNOWN);
03315 }
03316 return;
03317 } else if (base_dep == DEP_INDEPENDENT) {
03318 goto check_kids;
03319 } else {
03320
03321 if (!(rhs_flag & F90_ARRSECTION) && parent) {
03322 kid = F90_Lower_Copy_To_STemp(©_store,expr);
03323 WN_kid(parent,kidno) = kid;
03324 WN_INSERT_BlockLast(PRELIST(adata),copy_store);
03325 SET_DEP_SUMMARY(dep,DEP_INDEPENDENT);
03326 return;
03327 }
03328
03329 if (transformational_seen) {
03330 SET_DEP_SUMMARY(dep,DEP_UNKNOWN);
03331 return;
03332 }
03333
03334
03335 if (lhs_arrsection) {
03336 for (i=0; i < rhs_num_pieces && WN_operator(rhs_pieces[i]) != OPR_ARRSECTION; i++);
03337 DevAssert((WN_operator(rhs_pieces[i])==OPR_ARRSECTION),("Expected to find an arrsection"));
03338 (void) Analyze_all_indices(lhs_arrsection,rhs_pieces[i],&kid_dep);
03339 keep_going = F90_Lower_Merge_Dep_Info(dep,&kid_dep);
03340 if (!keep_going) return;
03341 }
03342 }
03343 } else if (opr == OPR_INTRINSIC_OP && F90_Is_Transformational(WN_GET_INTRINSIC(expr))) {
03344
03345 transformational_seen = TRUE;
03346 }
03347
03348 check_kids:
03349
03350 num_kids = WN_kid_count(expr);
03351 if (opr == OPR_TRIPLET) num_kids = 2;
03352 for (i=0; i < num_kids; i++) {
03353 kid = WN_kid(expr,i);
03354 F90_Lower_Init_Dep_Info(&kid_dep,lhsdim);
03355 Dependence_Walk(kid, adata, &kid_dep, transformational_seen,expr,i,lhsdim,FALSE);
03356 keep_going = F90_Lower_Merge_Dep_Info(dep,&kid_dep);
03357 if (!keep_going) break;
03358 }
03359
03360 return;
03361 }
03362
03363
03364
03365
03366
03367
03368
03369 static void f90_analyze_mstore(WN *stmt, WN *block)
03370 {
03371 F90_LOWER_AUX_DATA *adata;
03372 WN *lhs,*rhs;
03373 DEP_INFO dep;
03374
03375 stmt = stmt;
03376 lhs = WN_kid1(stmt);
03377 rhs = WN_kid0(stmt);
03378
03379 adata = F90_Lower_New_Aux_Data(0);
03380 SET_F90_MAP(stmt,adata);
03381
03382 lhs_const_offset = WN_offset(stmt);
03383
03384 F90_Lower_Init_Dep_Info(&dep,0);
03385
03386 lhs_address = lhs;
03387 lhs_arrsection = NULL;
03388 Analyze_one_address(lhs,&lhs_sym,lhs_pieces,&lhs_num_pieces,&lhs_const_offset,
03389 &lhs_base_offset,&lhs_size,&lhs_flag,&lhs_ty);
03390
03391
03392
03393 Dependence_Walk(rhs,adata,&dep,FALSE,stmt,0,0,FALSE);
03394
03395
03396 (void) F90_Insert_All_Prelists(stmt,block);
03397 (void) F90_Insert_Temp_Allocations(stmt,block);
03398 return;
03399 }
03400
03401
03402
03403
03404
03405
03406
03407
03408
03409
03410
03411
03412
03413
03414
03415
03416 static void f90_analyze_assignment(WN *stmt, WN *block, BOOL is_call)
03417 {
03418 F90_LOWER_AUX_DATA *adata;
03419 WN *lhs_arrayexp;
03420 INT lhs_arrayexp_kid = 0;
03421 INT ndim;
03422 INT lhsdim;
03423 INT i,num_kids;
03424 INT vec_axes,vec_axis_list[MAX_NDIM],axis;
03425 WN *assignment;
03426 WN *lhs,*rhs;
03427 WN *count,*copy_store;
03428 DEP_INFO lhs_dep,rhs_dep;
03429 INTRINSIC intr;
03430 int rhs_kidno;
03431 WN *rhs_parent;
03432
03433 if (is_call) {
03434 if (WN_opcode(stmt) != OPC_WHERE) {
03435 if (WN_operator(stmt)==OPR_INTRINSIC_CALL) {
03436 intr = WN_GET_INTRINSIC(stmt);
03437 } else {
03438 intr = INTRINSIC_NONE;
03439 }
03440 if (WN_operator(stmt) == OPR_CALL || WN_operator(stmt) == OPR_ICALL) {
03441 num_kids = WN_kid_count(stmt);
03442 for (i=0; i < num_kids; i++) {
03443 lhs_arrayexp = WN_kid0(WN_kid(stmt,i));
03444 lhs_arrayexp_kid = i;
03445 if (WN_operator(lhs_arrayexp) == OPR_ARRAYEXP) {
03446 break;
03447 }
03448 }
03449 } else {
03450 lhs_arrayexp = WN_kid0(WN_kid0(stmt));
03451 }
03452 assignment = stmt;
03453 ndim = WN_kid_count(lhs_arrayexp) - 1;
03454 } else if (WN_opcode(stmt) == OPC_WHERE) {
03455
03456
03457 lhs_arrayexp = WN_kid0(stmt);
03458 ndim = WN_kid_count(lhs_arrayexp)-1;
03459 assignment = get_assignment_from_stmt(stmt);
03460 lhs_arrayexp = WN_kid0(WN_kid0(assignment));
03461 if (WN_operator(assignment)==OPR_INTRINSIC_CALL) {
03462 intr = WN_GET_INTRINSIC(assignment);
03463 } else {
03464 intr = INTRINSIC_NONE;
03465 }
03466 }
03467
03468
03469
03470 lhs = WN_kid0(lhs_arrayexp);
03471 if (intr == INTRN_CASSIGNSTMT) {
03472 rhs = WN_kid0(WN_kid1(assignment));
03473 rhs_kidno = 0;
03474 rhs_parent = WN_kid1(assignment);
03475 } else if (WN_opcode(stmt) == OPC_WHERE &&
03476 (WN_operator(assignment) == OPR_CALL ||
03477 WN_operator(assignment) == OPR_ICALL)) {
03478 rhs = WN_kid0(WN_kid1(assignment));
03479 rhs_kidno = 0;
03480 rhs_parent = WN_kid1(assignment);
03481 } else {
03482 rhs = NULL;
03483 rhs_kidno = 0;
03484 rhs_parent = NULL;
03485 }
03486 } else {
03487
03488 if (WN_opcode(stmt) != OPC_WHERE) {
03489 lhs_arrayexp = WN_kid1(stmt);
03490 ndim = WN_kid_count(lhs_arrayexp) - 1;
03491 assignment = stmt;
03492 } else if (WN_opcode(stmt) == OPC_WHERE) {
03493
03494
03495 lhs_arrayexp = WN_kid0(stmt);
03496 ndim = WN_kid_count(lhs_arrayexp)-1;
03497 assignment = get_assignment_from_stmt(stmt);
03498 lhs_arrayexp = WN_kid1(assignment);
03499 }
03500 rhs = WN_kid0(assignment);
03501 rhs_kidno = 0;
03502 rhs_parent = assignment;
03503 lhs = WN_kid0(lhs_arrayexp);
03504 }
03505 adata = F90_Lower_New_Aux_Data(ndim);
03506 SET_F90_MAP(stmt,adata);
03507
03508
03509
03510
03511
03512 if (rhs) {
03513 if (is_call) {
03514 lhs_const_offset = 0;
03515 } else {
03516 lhs_const_offset = WN_offset(assignment);
03517 }
03518 lhs_arrsection = find_arrsection(lhs);
03519 lhsdim = (WN_kid_count(lhs_arrsection)-1)/2;
03520
03521 F90_Lower_Init_Dep_Info(&lhs_dep,lhsdim);
03522 F90_Lower_Init_Dep_Info(&rhs_dep,lhsdim);
03523
03524 lhs_address = lhs;
03525 Analyze_one_address(lhs,&lhs_sym,lhs_pieces,&lhs_num_pieces,&lhs_const_offset,
03526 &lhs_base_offset,&lhs_size,&lhs_flag,&lhs_ty);
03527
03528
03529 num_kids = WN_kid_count(lhs_arrsection);
03530 for (i=lhsdim+1; i < num_kids ; i++) {
03531 Dependence_Walk(WN_kid(lhs_arrsection,i),adata,&lhs_dep,FALSE,lhs_arrsection,i,lhsdim,FALSE);
03532 }
03533
03534 if (DEP_SUMMARY(&lhs_dep) != DEP_INDEPENDENT) {
03535
03536 SET_COPY_FLAG(adata,COPY_LEFT | COPY_FLAG(adata));
03537 }
03538
03539
03540 for (i=1; i <= ndim ; i++) {
03541 Dependence_Walk(WN_kid(lhs_arrayexp,i),adata,&lhs_dep,FALSE,lhs_arrayexp,i,lhsdim,FALSE);
03542 }
03543
03544
03545 Dependence_Walk(rhs,adata,&rhs_dep,FALSE,rhs_parent,rhs_kidno,lhsdim,is_call);
03546 switch (DEP_SUMMARY(&rhs_dep)) {
03547 case DEP_INDEPENDENT:
03548 case DEP_IDENTICAL:
03549
03550 break;
03551
03552 case DEP_UNKNOWN:
03553
03554 SET_COPY_FLAG(adata,COPY_RIGHT | COPY_FLAG(adata));
03555 break;
03556
03557 case DEP_REMOVABLE:
03558
03559
03560
03561 vec_axes = find_vector_axes(vec_axis_list,lhs_arrsection);
03562 for (i=0; i <vec_axes; i++) {
03563 axis = vec_axis_list[i];
03564 if (DEP_DIRECTION(&rhs_dep,axis) == DIR_POSITIVE ||
03565 DEP_DIRECTION(&rhs_dep,axis) == DIR_NEGATIVE) {
03566 SET_DIRECTION(adata,i,DEP_DIRECTION(&rhs_dep,axis));
03567 }
03568 }
03569 FmtAssert((vec_axes == ndim),("found wrong number of vector axes"));
03570 break;
03571 }
03572 }
03573
03574
03575
03576
03577
03578
03579 for (i=0; i < ndim; i++) {
03580 if (ITER_COUNT(adata,i)) {
03581
03582 WN_DELETE_Tree(WN_kid(lhs_arrayexp,i+1));
03583 } else {
03584 count = WN_kid(lhs_arrayexp,i+1);
03585 if (arrayexp_in_subtree(count)) {
03586 count = F90_Lower_Copy_To_STemp(©_store,count);
03587 WN_INSERT_BlockBefore(block,stmt,copy_store);
03588 }
03589 SET_ITER_COUNT(adata,i,count);
03590 }
03591 }
03592
03593 if (is_call) {
03594 WN_kid0(WN_kid(assignment,lhs_arrayexp_kid)) = WN_kid0(lhs_arrayexp);
03595 } else {
03596 WN_kid1(assignment) = WN_kid0(lhs_arrayexp);
03597 }
03598 WN_Delete(lhs_arrayexp);
03599
03600 return;
03601 }
03602
03603
03604
03605
03606
03607
03608
03609
03610 static BOOL F90_Do_Dependence_Analysis(WN *stmt, WN *block)
03611 {
03612 OPCODE op;
03613 OPERATOR opr;
03614 BOOL is_arrayexp;
03615 WN *arrayexp;
03616 INT i,num_kids;
03617
03618
03619
03620
03621 is_arrayexp = arrayexp_in_subtree(stmt);
03622 array_statement_seen = array_statement_seen || is_arrayexp;
03623
03624 op = WN_opcode(stmt);
03625 opr = OPCODE_operator(op);
03626
03627
03628 if (opr == OPR_MSTORE &&
03629 WN_operator(WN_kid1(stmt)) != OPR_ARRAYEXP) {
03630 f90_analyze_mstore(stmt,block);
03631 return(TRUE);
03632 }
03633
03634
03635
03636
03637
03638
03639
03640
03641
03642
03643
03644 if (opr == OPR_WHERE) {
03645 arrayexp = get_assignment_from_stmt(stmt);
03646 if (WN_operator(arrayexp) == OPR_INTRINSIC_CALL) {
03647 f90_analyze_assignment(stmt, block, TRUE);
03648 } else if (WN_operator(arrayexp) == OPR_CALL ||
03649 WN_operator(arrayexp) == OPR_ICALL) {
03650 if (WN_operator(arrayexp) == OPR_ICALL) {
03651 num_kids = WN_kid_count(stmt) - 1;
03652 } else {
03653 num_kids = WN_kid_count(stmt);
03654 }
03655 for (i=0 ; i < num_kids; i++) {
03656 arrayexp = WN_kid0(WN_kid(stmt,i));
03657 if (WN_operator(arrayexp) == OPR_ARRAYEXP) {
03658 f90_analyze_assignment(stmt,block,TRUE);
03659 break;
03660 }
03661 }
03662 } else {
03663 f90_analyze_assignment(stmt, block, FALSE);
03664 }
03665 } else if (opr == OPR_MSTORE || opr == OPR_ISTORE) {
03666
03667 arrayexp = WN_kid1(stmt);
03668 if (WN_operator(arrayexp) == OPR_ARRAYEXP) {
03669
03670 f90_analyze_assignment(stmt, block, FALSE);
03671 }
03672 } else if (opr == OPR_INTRINSIC_CALL) {
03673 if (WN_kid_count(stmt) > 0) {
03674 arrayexp = WN_kid0(WN_kid0(stmt));
03675 if (WN_operator(arrayexp) == OPR_ARRAYEXP) {
03676 f90_analyze_assignment(stmt,block,TRUE);
03677 }
03678 }
03679 } else if (opr == OPR_CALL || opr == OPR_ICALL) {
03680 if (opr == OPR_ICALL) {
03681
03682 num_kids = WN_kid_count(stmt) - 1;
03683 } else {
03684 num_kids = WN_kid_count(stmt);
03685 }
03686 for (i=0 ; i < num_kids; i++) {
03687 arrayexp = WN_kid0(WN_kid(stmt,i));
03688 if (WN_operator(arrayexp) == OPR_ARRAYEXP) {
03689 f90_analyze_assignment(stmt,block,TRUE);
03690 break;
03691 }
03692 }
03693 }
03694
03695 return (TRUE);
03696 }
03697
03698
03699 static void F90_Analyze_Dependencies (WN *pu)
03700 {
03701 F90_Walk_Statements(pu,F90_Do_Dependence_Analysis);
03702 }
03703
03704
03705
03706
03707
03708
03709
03710
03711
03712
03713
03714
03715
03716
03717
03718 static WN * F90_Triplet_Scalarization_Walk(WN *expr, WN *stmt, WN *block, INT move)
03719 {
03720 OPERATOR opr;
03721 INT i,numkids;
03722 WN *copy_store;
03723 WN *kid;
03724
03725 opr = WN_operator(expr);
03726 numkids = WN_kid_count(expr);
03727
03728 if (opr == OPR_ARRAYEXP) {
03729 WN_kid0(expr) = F90_Triplet_Scalarization_Walk(WN_kid0(expr),stmt,block,FALSE);
03730 for (i=1; i<numkids; i++) {
03731 WN_kid(expr,i) = F90_Triplet_Scalarization_Walk(WN_kid(expr,i),stmt,block,TRUE);
03732 }
03733 } else if (opr == OPR_TRIPLET) {
03734 WN_kid0(expr) = F90_Triplet_Scalarization_Walk(WN_kid0(expr),stmt,block,1);
03735 WN_kid1(expr) = F90_Triplet_Scalarization_Walk(WN_kid1(expr),stmt,block,1);
03736
03737 WN_kid2(expr) = F90_Triplet_Scalarization_Walk(WN_kid2(expr),stmt,block,0);
03738 } else if (opr == OPR_DO_LOOP) {
03739
03740 kid = WN_kid1(expr);
03741 WN_kid0(kid) = F90_Triplet_Scalarization_Walk(WN_kid0(kid),stmt,block,2);
03742 for (i = 2; i < numkids; i++) {
03743 WN_kid(expr,i) = F90_Triplet_Scalarization_Walk(WN_kid(expr,i),stmt,block,move);
03744 }
03745 } else if ((move > 0) && opr == OPR_INTRINSIC_OP &&
03746 (F90_Is_Transformational(WN_GET_INTRINSIC(expr)) || move == 2)) {
03747
03748 expr = F90_Lower_Copy_To_STemp(©_store,expr);
03749 WN_INSERT_BlockBefore(block,stmt,copy_store);
03750 } else {
03751
03752 for (i=0; i<numkids; i++) {
03753 WN_kid(expr,i) = F90_Triplet_Scalarization_Walk(WN_kid(expr,i),stmt,block,move);
03754 }
03755 }
03756 return (expr);
03757 }
03758
03759
03760 static BOOL F90_Scalarize_Triplets_And_Sizes(WN *stmt, WN *block)
03761 {
03762 (void) F90_Triplet_Scalarization_Walk(stmt,stmt,block,0);
03763 return (TRUE);
03764 }
03765
03766
03767
03768
03769
03770
03771 static BOOL F90_Do_Copies(WN *stmt, WN *block)
03772 {
03773 F90_LOWER_AUX_DATA *adata,*copy_adata;
03774 INT ndim,i;
03775 COPY_FLAG_T copy;
03776 WN *assignment;
03777 WN *new_rhs,*new_lhsptr;
03778 WN *copy_store;
03779 WN *rhs;
03780 TY_IDX ty;
03781 OPERATOR assign_opr;
03782 BOOL in_where,in_elsewhere;
03783 WN *sizes[MAX_NDIM];
03784 WN *new_where;
03785
03786 adata = GET_F90_MAP(stmt);
03787 if (!adata) return (TRUE);
03788 copy = COPY_FLAG(adata);
03789 if (copy == COPY_NONE) return (TRUE);
03790
03791 if (WN_opcode(stmt) == OPC_WHERE) {
03792 in_where = TRUE;
03793 in_elsewhere = FALSE;
03794 assignment = WN_first(WN_kid1(stmt));
03795 if (!assignment) {
03796 assignment = WN_first(WN_kid2(stmt));
03797 in_elsewhere = TRUE;
03798 }
03799 } else {
03800 in_where = FALSE;
03801 assignment = stmt;
03802 }
03803
03804 assignment = get_assignment_from_stmt(stmt);
03805 assign_opr = WN_operator(assignment);
03806
03807
03808 if (copy == COPY_RIGHT || copy == COPY_BOTH) {
03809 if (assign_opr == OPR_ISTORE || assign_opr == OPR_MSTORE) {
03810 if (in_where) {
03811
03812 copy_adata = F90_Lower_Copy_Aux_Data(adata);
03813 ndim = NDIM(copy_adata);
03814
03815 for (i=0; i <ndim ; i++) {
03816 sizes[i] = ITER_COUNT(copy_adata,i);
03817 }
03818 new_rhs = F90_Lower_Copy_To_ATemp(&ALLOC_PRELIST(copy_adata),&DEALLOC_POSTLIST(adata),
03819 ©_store,WN_kid0(assignment),sizes,ndim);
03820 WN_INSERT_BlockFirst(PRELIST(copy_adata),PRELIST(adata));
03821 WN_INSERT_BlockFirst(ALLOC_PRELIST(copy_adata),ALLOC_PRELIST(adata));
03822 SET_PRELIST(adata,WN_CreateBlock());
03823 SET_ALLOC_PRELIST(adata,WN_CreateBlock());
03824
03825 new_where = WN_Create(OPC_WHERE,3);
03826 WN_kid0(new_where) = WN_COPY_Tree(WN_kid0(stmt));
03827 WN_kid1(new_where) = WN_CreateBlock();
03828 WN_kid2(new_where) = WN_CreateBlock();
03829
03830 if (in_elsewhere) {
03831 WN_INSERT_BlockFirst(WN_kid2(new_where),copy_store);
03832 } else {
03833 WN_INSERT_BlockFirst(WN_kid1(new_where),copy_store);
03834 }
03835 SET_F90_MAP(new_where,copy_adata);
03836 WN_INSERT_BlockBefore(block,stmt,new_where);
03837 } else {
03838 new_rhs = F90_Lower_Copy_Expr_to_Temp(WN_kid0(assignment),stmt,block);
03839 }
03840 WN_kid0(assignment) = new_rhs;
03841 } else {
03842
03843
03844
03845 copy_adata = F90_Lower_Copy_Aux_Data(adata);
03846 rhs = WN_kid0(WN_kid1(assignment));
03847 ty = WN_ty(WN_kid0(assignment));
03848 rhs = WN_CreateMload(0,ty,rhs,WN_COPY_Tree(WN_kid0(WN_kid(assignment,3))));
03849 new_rhs = F90_Lower_Copy_To_ATemp(&ALLOC_PRELIST(copy_adata), &DEALLOC_POSTLIST(adata),
03850 ©_store,rhs,
03851 ITER_COUNT_PTR(adata), NDIM(adata));
03852
03853 WN_kid0(WN_kid1(assignment)) = WN_kid0(new_rhs);
03854 WN_DELETE_Tree(WN_kid1(new_rhs));
03855 WN_Delete(new_rhs);
03856 SET_F90_MAP(copy_store,copy_adata);
03857 WN_INSERT_BlockBefore(block,stmt,copy_store);
03858
03859 #ifdef KEY // because rhs may use them
03860 WN_INSERT_BlockFirst(PRELIST(copy_adata),PRELIST(adata));
03861 SET_PRELIST(adata,WN_CreateBlock());
03862 #endif
03863 WN_INSERT_BlockFirst(ALLOC_PRELIST(copy_adata),ALLOC_PRELIST(adata));
03864 SET_ALLOC_PRELIST(adata,WN_CreateBlock());
03865 }
03866 }
03867
03868 if (copy == COPY_LEFT || copy == COPY_BOTH) {
03869
03870 if (assign_opr == OPR_ISTORE || assign_opr == OPR_MSTORE) {
03871 new_lhsptr = F90_Lower_Copy_Expr_to_Temp(WN_kid1(assignment),stmt,block);
03872 WN_kid1(assignment) = new_lhsptr;
03873 } else {
03874
03875
03876
03877 new_lhsptr = F90_Lower_Copy_Expr_to_Temp(WN_kid0(WN_kid0(assignment)),stmt,block);
03878 WN_kid0(WN_kid0(assignment)) = new_lhsptr;
03879
03880 }
03881 }
03882 return (TRUE);
03883 }
03884
03885
03886
03887
03888
03889
03890
03891 static BOOL move_kid_for_mm_or_spread(WN * expr)
03892 {
03893 OPERATOR opr;
03894 opr = WN_operator(expr);
03895
03896 if (opr == OPR_PARM || opr == OPR_ARRAYEXP) {
03897 return move_kid_for_mm_or_spread(WN_kid0(expr));
03898 } else if (opr == OPR_ILOAD ||
03899 opr == OPR_MLOAD ||
03900 opr == OPR_LDID ||
03901 opr == OPR_TRIPLET ||
03902 opr == OPR_ARRAY ||
03903 opr == OPR_ARRSECTION) {
03904 return (FALSE);
03905 } else if (opr == OPR_INTRINSIC_OP) {
03906 INTRINSIC i = WN_GET_INTRINSIC(expr);
03907
03908 if (i == INTRN_TRANSPOSE || i == INTRN_SPREAD) {
03909 return (FALSE);
03910 } else {
03911 return (TRUE);
03912 }
03913 } else {
03914 return (TRUE);
03915 }
03916 }
03917
03918
03919
03920
03921
03922
03923
03924
03925
03926
03927
03928
03929 static WN * F90_Move_Transformational_Walk(WN *t, WN *stmt, WN *block, WN *parent, BOOL in_where)
03930 {
03931 INT numkids;
03932 WN *kid;
03933 WN *temp;
03934 INT i;
03935 INT rank,rank1,rank2;
03936 OPERATOR opr;
03937 BOOL walking_where;
03938 F90_LOWER_AUX_DATA *adata;
03939
03940
03941
03942 numkids = WN_kid_count(t);
03943 opr = WN_operator(t);
03944
03945 if (opr == OPR_BLOCK) {
03946 kid = WN_first(t);
03947 while (kid) {
03948 (void) F90_Move_Transformational_Walk(kid, stmt, block,t,in_where);
03949 kid = WN_next(kid);
03950 }
03951 } else {
03952 for (i=0; i < numkids; i++) {
03953 kid = WN_kid(t,i);
03954 walking_where = (opr == OPR_WHERE) || in_where;
03955 temp = F90_Move_Transformational_Walk(kid,stmt,block,t,walking_where);
03956 WN_kid(t,i) = temp;
03957 }
03958 }
03959
03960 if (opr != OPR_INTRINSIC_OP) {
03961 return (t);
03962 }
03963
03964
03965 switch (WN_GET_INTRINSIC(t)) {
03966 case INTRN_MATMUL:
03967 rank = F90_Rank_Walk(t);
03968 rank1 = F90_Rank_Walk(WN_kid0(t));
03969 rank2 = F90_Rank_Walk(WN_kid1(t));
03970 if ((rank==2 || rank1==1) && move_kid_for_mm_or_spread(WN_kid0(t))) {
03971 kid = WN_kid0(WN_kid0(t));
03972 temp = F90_Lower_Copy_Expr_to_Temp(kid,stmt,block);
03973 WN_kid0(WN_kid0(t)) = temp;
03974 }
03975 if ((rank==2 || rank2==1) && move_kid_for_mm_or_spread(WN_kid1(t))) {
03976 kid = WN_kid0(WN_kid1(t));
03977 temp = F90_Lower_Copy_Expr_to_Temp(kid,stmt,block);
03978 WN_kid0(WN_kid1(t)) = temp;
03979 }
03980 return (t);
03981
03982 case INTRN_SPREAD:
03983 if (move_kid_for_mm_or_spread(WN_kid0(t))) {
03984 kid = WN_kid0(WN_kid0(t));
03985 temp = F90_Lower_Copy_Expr_to_Temp(kid,stmt,block);
03986 WN_kid0(WN_kid0(t)) = temp;
03987 }
03988 return (t);
03989
03990 case INTRN_PACK:
03991 case INTRN_UNPACK:
03992 if (!OPCODE_is_stmt(WN_opcode(parent)) || in_where) {
03993 temp = F90_Lower_Copy_Expr_to_Temp(t,stmt,block);
03994 return(temp);
03995 } else {
03996
03997 return (t);
03998 }
03999
04000 case INTRN_EOSHIFT:
04001
04002 if (!OPCODE_is_stmt(WN_opcode(parent)) || in_where) {
04003 temp = F90_Lower_Copy_Expr_to_Temp(t,stmt,block,TRUE);
04004 return(temp);
04005 } else {
04006
04007 adata = GET_F90_MAP(parent);
04008 if (adata) {
04009 SET_NO_PROMPF_INFO(adata,TRUE);
04010 }
04011 return (t);
04012 }
04013
04014 default:
04015 return (t);
04016 }
04017 }
04018
04019
04020
04021
04022
04023
04024
04025
04026
04027 static BOOL F90_Move_Transformationals(WN *stmt, WN *block)
04028 {
04029
04030 (void) F90_Move_Transformational_Walk(stmt,stmt,block,NULL,FALSE);
04031 return (TRUE);
04032 }
04033
04034
04035
04036
04037
04038 static WN * create_doloop_node(WN *index_id, WN *start, WN *end,
04039 WN *step, WN *body, BOOL add_prompf=TRUE)
04040 {
04041 WN *temp;
04042 WN_Set_Linenum(start,current_srcpos);
04043 WN_Set_Linenum(step,current_srcpos);
04044 temp = WN_CreateDO(index_id, start, end, step, body, NULL);
04045 WN_Set_Linenum(temp,current_srcpos);
04046
04047 if (add_prompf && Prompf_Info != NULL && Prompf_Info->Is_Enabled()) {
04048 INT new_id = New_Construct_Id();
04049 WN_MAP32_Set(Prompf_Id_Map, temp, new_id);
04050 PROMPF_LINES* pl = CXX_NEW(PROMPF_LINES(temp, &PROMPF_pool),
04051 &PROMPF_pool);
04052 WN* wn_symbol = WN_index(temp);
04053 const char* name = ST_class(WN_st(wn_symbol)) != CLASS_PREG
04054 ? ST_name(WN_st(wn_symbol)) :
04055 WN_offset(wn_symbol) > Last_Dedicated_Preg_Offset
04056 ? Preg_Name(WN_offset(wn_symbol)) : "DEDICATED PREG";
04057 Prompf_Info->F90_Array_Stmt(new_id, pl, (char*) name);
04058 }
04059 return (temp);
04060 }
04061
04062
04063
04064
04065
04066
04067
04068
04069
04070
04071
04072
04073
04074
04075
04076 static WN * create_doloop(PREG_NUM *index, char *index_name, WN *count, DIR_FLAG dir, WN *body,
04077 BOOL prompf_info = TRUE)
04078 {
04079 WN *index_id, *count_expr, *start, *end, *step, *doloop;
04080 OPCODE intconst_op;
04081 TYPE_ID index_type;
04082 WN *temp;
04083
04084 index_type = doloop_ty;
04085 intconst_op = OPCODE_make_op(OPR_INTCONST,index_type,MTYPE_V);
04086 #ifdef KEY
04087 if (MTYPE_size_min(index_type) != MTYPE_size_min(WN_rtype(count)))
04088 count = WN_Cvt(WN_rtype(count), index_type, count);
04089 #endif
04090
04091
04092 *index = Create_Preg(index_type,Index_To_Str(Save_Str(index_name)));
04093
04094 index_id = WN_CreateIdname(*index,MTYPE_To_PREG(index_type));
04095 count_expr = WN_CreateExp2(OPCODE_make_op(OPR_SUB,index_type,MTYPE_V),
04096 count,
04097 WN_CreateIntconst(intconst_op,1));
04098
04099 if (dir == DIR_NEGATIVE) {
04100
04101 start = WN_StidPreg(index_type,*index,count_expr);
04102 end = WN_CreateExp2(OPCODE_make_op(OPR_GE,MTYPE_I4,index_type),
04103 WN_LdidPreg(index_type,*index),
04104 WN_CreateIntconst(intconst_op,0));
04105
04106 step = WN_CreateExp2(OPCODE_make_op(OPR_SUB,index_type,MTYPE_V),
04107 WN_LdidPreg(index_type,*index),
04108 WN_CreateIntconst(intconst_op,1));
04109 step = WN_StidPreg(index_type,*index,step);
04110 } else {
04111
04112 start = WN_StidPreg(index_type,*index, WN_CreateIntconst(intconst_op,0));
04113 end = WN_CreateExp2(OPCODE_make_op(OPR_LE,MTYPE_I4,index_type),
04114 WN_LdidPreg(index_type,*index),
04115 count_expr);
04116
04117 step = WN_CreateExp2(OPCODE_make_op(OPR_ADD,index_type,MTYPE_V),
04118 WN_LdidPreg(index_type,*index),
04119 WN_CreateIntconst(intconst_op,1));
04120 step = WN_StidPreg(index_type,*index,step);
04121 }
04122
04123
04124 if (WN_opcode(body) != OPC_BLOCK) {
04125 temp = WN_CreateBlock();
04126 WN_INSERT_BlockFirst(temp,body);
04127 } else {
04128 temp = body;
04129 }
04130
04131 doloop = create_doloop_node(index_id, start, end, step, temp, prompf_info);
04132 return (doloop);
04133 }
04134
04135
04136
04137
04138
04139
04140
04141
04142
04143
04144
04145 static WN * create_doloop_nest(PREG_NUM indices[], WN **doloop, WN *sizes[], INT ndim,
04146 BOOL prompf_info=TRUE)
04147 {
04148 INT i;
04149 WN *loopnest, *stlist;
04150 char tempname[32];
04151 PREG_NUM index;
04152
04153 loopnest = WN_CreateBlock();
04154 stlist = loopnest;
04155 num_temps += 1;
04156 for (i=ndim-1; i >= 0; i--) {
04157 sprintf(tempname,"@f90li_%d_%d",i,num_temps);
04158
04159
04160 loopnest = create_doloop(&index,tempname,sizes[i],DIR_POSITIVE,loopnest,prompf_info);
04161 indices[i] = index;
04162 }
04163 *doloop = loopnest;
04164 return (stlist);
04165 }
04166
04167
04168
04169
04170
04171
04172
04173
04174
04175
04176
04177
04178
04179
04180
04181
04182
04183
04184
04185
04186
04187
04188
04189
04190
04191 static WN * lower_reduction(TYPE_ID rty, OPERATOR reduction_opr,
04192 WN *kids[], PREG_NUM *indices, INT ndim,
04193 WN * block, WN *insert_point)
04194 {
04195 INT dim;
04196 OPCODE reduction_op;
04197 PREG_NUM accum;
04198 ST * accum_st;
04199 WN *sizes[MAX_NDIM];
04200 PREG_NUM new_indices[MAX_NDIM],index;
04201 INT rank,i,j;
04202 WN *idty_store;
04203 WN *accum_store,*accum_block;
04204 WN *loopnest,*stlist,*mask_expr,*accum_expr;
04205 char tempname[32];
04206 WN *result;
04207 BOOL Mask_Present;
04208 F90_LOWER_AUX_DATA *adata;
04209 WN *dealloc_post,*post;
04210 TYPE_ID ty;
04211 WN* region;
04212
04213 #ifdef KEY // bug14194
04214 for (i=0; i<MAX_NDIM; i++)
04215 sizes[i] = NULL;
04216 #endif
04217
04218 if (kids[1]) {
04219 dim = F90_Get_Dim(kids[1]);
04220 WN_DELETE_Tree(kids[1]);
04221 } else {
04222 dim = 0;
04223 }
04224
04225 if (!kids[2] || (WN_operator(kids[2]) == OPR_INTCONST &&
04226 WN_const_val(kids[2]) == 1)) {
04227 Mask_Present = FALSE;
04228 } else {
04229 Mask_Present = TRUE;
04230 }
04231
04232 ty = Mtype_comparison(rty);
04233
04234
04235 accum_st = New_ST(CURRENT_SYMTAB);
04236 ST_Init(accum_st, Save_Str(create_tempname("@f90acc")),
04237 CLASS_VAR, SCLASS_AUTO, EXPORT_LOCAL, MTYPE_To_TY(ty));
04238 Add_Pragma_To_MP_Regions (&F90_MP_Region,WN_PRAGMA_LOCAL,
04239 accum_st,0,WN_MAP_UNDEFINED,FALSE);
04240 #ifdef DEBUG
04241 printf("%s:%d -- accum_st = 0x%x, ST_type(accum_st) = %d\n",
04242 __FILE__, __LINE__, (unsigned)accum_st, (int)ST_type(accum_st) );
04243 #endif
04244
04245 reduction_op = OPCODE_make_op(reduction_opr,ty,MTYPE_V);
04246 idty_store = WN_Stid(ty,0,accum_st,MTYPE_To_TY(ty),
04247 Make_Reduction_Identity(reduction_opr,rty));
04248
04249
04250 (void) F90_Size_Walk(kids[0],&rank,sizes);
04251 loopnest = WN_CreateBlock();
04252 stlist = loopnest;
04253
04254
04255 if (dim == 0 || (dim == 1 && rank == 1)) {
04256 WN_INSERT_BlockBefore(F90_Current_Block,F90_Current_Loopnest,idty_store);
04257 adata = GET_F90_MAP(F90_Current_Loopnest);
04258 if (adata) {
04259 dealloc_post = DEALLOC_POSTLIST(adata);
04260 post = POSTLIST(adata);
04261 SET_DEALLOC_POSTLIST(adata,WN_CreateBlock());
04262 SET_POSTLIST(adata,WN_CreateBlock());
04263 }
04264
04265
04266 num_temps += 1;
04267 for (i=rank-1; i >= 0 ; i--) {
04268 sprintf(tempname,"@f90li_%d_%d",i,num_temps);
04269 loopnest = create_doloop(&index,tempname,sizes[i],DIR_POSITIVE,loopnest);
04270 new_indices[i] = index;
04271 }
04272 BOOL_VECTOR::iterator bi = F90_MP_Region_Isworkshare.begin();
04273 if( (bi != F90_MP_Region_Isworkshare.end()) && *bi ){
04274
04275 region = WN_CreateRegion(REGION_KIND_MP,
04276 WN_CreateBlock(),
04277 WN_CreateBlock(),
04278 WN_CreateBlock(),
04279 -1,
04280 0);
04281 WN_INSERT_BlockBefore(F90_Current_Block, F90_Current_Loopnest, region);
04282 WN_INSERT_BlockFirst(WN_region_body(region), loopnest);
04283 F90_Current_Loopnest = region;
04284
04285 WN* pragmas = WN_region_pragmas(region);
04286
04287 WN* pragma = WN_CreatePragma(WN_PRAGMA_PDO_BEGIN, (ST *)NULL, 0, 1);
04288 WN_set_pragma_omp(pragma);
04289 WN_set_pragma_compiler_generated(pragma);
04290 WN_INSERT_BlockFirst(pragmas, pragma);
04291
04292 pragma = WN_CreatePragma(WN_PRAGMA_REDUCTION, accum_st, 0, reduction_opr);
04293 WN_set_pragma_omp(pragma);
04294 WN_set_pragma_compiler_generated(pragma);
04295 WN_INSERT_BlockLast(pragmas, pragma);
04296
04297 ST *index_st = MTYPE_To_PREG(doloop_ty);
04298
04299 for(i=0; i<rank; i++){
04300 pragma = WN_CreatePragma(WN_PRAGMA_LOCAL, index_st, new_indices[i], 0);
04301 WN_set_pragma_omp(pragma);
04302 WN_set_pragma_compiler_generated(pragma);
04303 WN_INSERT_BlockLast(pragmas, pragma);
04304 }
04305
04306 pragma = WN_CreatePragma(WN_PRAGMA_END_MARKER, (ST *)NULL, 0, 0);
04307 WN_set_pragma_omp(pragma);
04308 WN_set_pragma_compiler_generated(pragma);
04309 WN_INSERT_BlockLast(pragmas, pragma);
04310 }
04311 else{
04312 WN_INSERT_BlockBefore(F90_Current_Block,F90_Current_Loopnest,loopnest);
04313
04314
04315 F90_Current_Loopnest = loopnest;
04316 }
04317
04318
04319 if (adata) {
04320 adata = F90_Lower_New_Aux_Data(0);
04321 SET_POSTLIST(adata,post);
04322 SET_DEALLOC_POSTLIST(adata,dealloc_post);
04323 SET_F90_MAP(loopnest,adata);
04324 }
04325
04326
04327 accum_expr = F90_Lower_Walk(kids[0],new_indices,rank,stlist,NULL);
04328 accum_store = WN_Stid(ty,0,accum_st,MTYPE_To_TY(ty),WN_CreateExp2(reduction_op,
04329 WN_Ldid(ty, 0, accum_st, MTYPE_To_TY(ty)),
04330 accum_expr));
04331 accum_block = WN_CreateBlock();
04332 WN_INSERT_BlockFirst(accum_block,accum_store);
04333 if (Mask_Present) {
04334 mask_expr = F90_Lower_Walk(kids[2],new_indices,rank,stlist,NULL);
04335
04336 accum_block = WN_CreateIf(mask_expr,accum_block,WN_CreateBlock());
04337 }
04338
04339 WN_INSERT_BlockLast(stlist,accum_block);
04340
04341
04342
04343 } else {
04344
04345
04346 WN_INSERT_BlockBefore(block,insert_point,idty_store);
04347
04348
04349 num_temps += 1;
04350 #ifdef KEY // bug14194
04351 dim = rank + 1 - dim;
04352 #else
04353 dim = ndim + 2 - dim;
04354 #endif
04355 sprintf(tempname,"@f90red_%d",num_temps);
04356 loopnest = create_doloop(&index,tempname,sizes[dim-1],DIR_POSITIVE,loopnest);
04357 for (i=0,j=0; i < ndim+1; i++) {
04358 if (i != dim-1) {
04359 WN_DELETE_Tree(sizes[i]);
04360 new_indices[i] = indices[j];
04361 j += 1;
04362 } else {
04363 new_indices[i] = index;
04364 }
04365 }
04366
04367 WN_INSERT_BlockBefore(block,insert_point,loopnest);
04368
04369 accum_expr = F90_Lower_Walk(kids[0],new_indices,ndim+1,stlist,NULL);
04370 accum_store = WN_Stid(ty,0,accum_st,MTYPE_To_TY(ty),WN_CreateExp2(reduction_op,
04371 WN_Ldid(ty, 0, accum_st, MTYPE_To_TY(ty)),
04372 accum_expr));
04373 accum_block = WN_CreateBlock();
04374 WN_INSERT_BlockFirst(accum_block,accum_store);
04375 if (Mask_Present) {
04376 mask_expr = F90_Lower_Walk(kids[2],new_indices,rank,stlist,NULL);
04377
04378 accum_block = WN_CreateIf(mask_expr,accum_block,WN_CreateBlock());
04379 }
04380
04381 WN_INSERT_BlockLast(stlist,accum_block);
04382 }
04383
04384
04385 result = WN_Ldid(ty, 0, accum_st, MTYPE_To_TY(ty));
04386 if (rty == MTYPE_I1) {
04387 result = WN_CreateCvtl(OPC_I4CVTL,8,result);
04388 } else if (rty == MTYPE_I2) {
04389 result = WN_CreateCvtl(OPC_I4CVTL,16,result);
04390 }
04391
04392 return (result);
04393 }
04394
04395
04396
04397
04398
04399
04400
04401
04402
04403
04404
04405
04406
04407
04408
04409
04410
04411
04412
04413
04414
04415 static WN * lower_maxminloc(OPERATOR reduction_opr,
04416 WN *kids[], PREG_NUM *indices, INT ndim,
04417 WN * block, WN *insert_point)
04418 {
04419 OPCODE reduction_op;
04420 PREG_NUM accum;
04421 WN *sizes[MAX_NDIM];
04422 PREG_NUM new_indices[MAX_NDIM],index,red_index;
04423 INT rank,i,j,dim;
04424 WN *idty_store;
04425 WN *accum_store,*accum_block;
04426 WN *loopnest,*stlist,*mask_expr,*accum_expr,*comp_expr,*red_store;
04427 char tempname[32];
04428 WN *result;
04429 BOOL Mask_Present;
04430 PREG_NUM cur_val;
04431 ST * retval;
04432 TY_IDX retty, ret_elem_ptr;
04433 TYPE_ID expr_ty;
04434
04435 #ifdef KEY // bug14194
04436 for (i=0; i<MAX_NDIM; i++)
04437 sizes[i] = NULL;
04438 #endif
04439
04440 if (kids[1]) {
04441 dim = F90_Get_Dim(kids[1]);
04442 WN_DELETE_Tree(kids[1]);
04443 } else {
04444 dim = 0;
04445 }
04446
04447 if (!kids[2] || (WN_operator(kids[2]) == OPR_INTCONST &&
04448 WN_const_val(kids[2]) == 1)) {
04449 Mask_Present = FALSE;
04450 } else {
04451 Mask_Present = TRUE;
04452 }
04453
04454
04455 expr_ty = WN_rtype(kids[0]);
04456 accum = Create_Preg(expr_ty,create_tempname("@f90acc"));
04457 cur_val = Create_Preg(expr_ty,create_tempname("@f90accval"));
04458 if (reduction_opr == OPR_MAX) {
04459 #ifdef KEY
04460 reduction_op = OPCODE_make_op(OPR_GE,MTYPE_I4,expr_ty);
04461 #else
04462 reduction_op = OPCODE_make_op(OPR_GT,MTYPE_I4,expr_ty);
04463 #endif
04464 } else {
04465 #ifdef KEY
04466 reduction_op = OPCODE_make_op(OPR_LE,MTYPE_I4,expr_ty);
04467 #else
04468 reduction_op = OPCODE_make_op(OPR_LT,MTYPE_I4,expr_ty);
04469 #endif
04470 }
04471 idty_store = WN_StidPreg(expr_ty,accum,Make_Reduction_Identity(reduction_opr,expr_ty));
04472
04473 if (dim == 0) {
04474
04475
04476
04477 (void) F90_Size_Walk(kids[0],&rank,sizes);
04478 loopnest = WN_CreateBlock();
04479 stlist = loopnest;
04480
04481 WN_INSERT_BlockBefore(F90_Current_Block,F90_Current_Loopnest,idty_store);
04482
04483
04484 num_temps += 1;
04485 for (i=rank-1; i >=0 ; i--) {
04486 sprintf(tempname,"@f90li_%d_%d",i,num_temps);
04487 #ifdef KEY
04488 loopnest = create_doloop(&index,tempname,sizes[i],DIR_NEGATIVE,loopnest);
04489 #else
04490 loopnest = create_doloop(&index,tempname,sizes[i],DIR_POSITIVE,loopnest);
04491 #endif
04492 new_indices[i] = index;
04493 }
04494 WN_INSERT_BlockBefore(F90_Current_Block,F90_Current_Loopnest,loopnest);
04495
04496
04497 F90_Current_Loopnest = idty_store;
04498
04499
04500
04501
04502 retval = new_temp_st("@f90mmloc");
04503 retty = Make_Array_Type(doloop_ty,1,rank);
04504 ret_elem_ptr = Make_Pointer_Type(Be_Type_Tbl(doloop_ty));
04505 Set_ST_type(*retval,retty);
04506
04507
04508 accum_expr = F90_Lower_Walk(kids[0],new_indices,rank,stlist,NULL);
04509 accum_store = WN_StidPreg(expr_ty,cur_val,accum_expr);
04510
04511 #ifdef KEY
04512 WN_INSERT_BlockLast(stlist,accum_store);
04513 #else
04514 WN_INSERT_BlockFirst(stlist,accum_store);
04515 #endif
04516
04517 comp_expr = WN_CreateExp2(reduction_op,WN_LdidPreg(expr_ty,cur_val),
04518 WN_LdidPreg(expr_ty,accum));
04519 if (Mask_Present) {
04520 mask_expr = F90_Lower_Walk(kids[2],new_indices,rank,stlist,NULL);
04521 mask_expr = WN_LAND(mask_expr,comp_expr);
04522 } else {
04523 mask_expr = comp_expr;
04524 }
04525 accum_block = WN_CreateBlock();
04526 accum_store = WN_StidPreg(expr_ty,accum,WN_LdidPreg(expr_ty,cur_val));
04527 WN_INSERT_BlockLast(accum_block,accum_store);
04528
04529 for (i = 0; i < rank; i++) {
04530
04531
04532 result = WN_Create(OPCODE_make_op(OPR_ARRAY,Pointer_Mtype,MTYPE_V),3);
04533 WN_element_size(result) = Pointer_Size;
04534 WN_kid1(result) = WN_Intconst(MTYPE_I4,rank);
04535 WN_kid2(result) = WN_Intconst(doloop_ty,i);
04536 WN_kid0(result) = WN_Lda(Pointer_type,0,retval);
04537 accum_store = WN_Istore(doloop_ty, (WN_OFFSET) 0, ret_elem_ptr, WN_COPY_Tree(result),
04538 WN_LdidPreg(doloop_ty,new_indices[rank-i-1]));
04539
04540 WN_INSERT_BlockLast(accum_block,accum_store);
04541
04542 accum_store = WN_Istore(doloop_ty, (WN_OFFSET) 0, ret_elem_ptr,result,
04543 WN_Intconst(doloop_ty,-1));
04544 WN_INSERT_BlockBefore(F90_Current_Block,idty_store,accum_store);
04545 }
04546 accum_store = WN_CreateIf(mask_expr,accum_block,WN_CreateBlock());
04547 WN_INSERT_BlockLast(stlist,accum_store);
04548 result = WN_Create(OPCODE_make_op(OPR_ARRAY,Pointer_Mtype,MTYPE_V),3);
04549 WN_element_size(result) = Pointer_Size;
04550 WN_kid1(result) = WN_Intconst(MTYPE_I4,rank);
04551 WN_kid2(result) = WN_LdidPreg(doloop_ty,indices[0]);
04552 WN_kid0(result) = WN_Lda(Pointer_type,0,retval);
04553 result = WN_Iload(doloop_ty,0,ret_elem_ptr,result);
04554 result = WN_CreateExp2(OPCODE_make_op(OPR_ADD,doloop_ty,MTYPE_V),result,
04555 WN_Intconst(doloop_ty,1));
04556
04557
04558 } else {
04559
04560
04561
04562 red_index = Create_Preg(doloop_ty,create_tempname("@f90redindex"));
04563
04564 # ifdef KEY
04565 red_store = WN_StidPreg(doloop_ty,red_index,WN_Intconst(doloop_ty,0));
04566 # else
04567 red_store = WN_StidPreg(doloop_ty,red_index,WN_Intconst(doloop_ty,-1));
04568 # endif
04569
04570
04571 (void) F90_Size_Walk(kids[0],&rank,sizes);
04572 loopnest = WN_CreateBlock();
04573 stlist = loopnest;
04574
04575 WN_INSERT_BlockBefore(block,insert_point,idty_store);
04576 WN_INSERT_BlockBefore(block,insert_point,red_store);
04577
04578
04579 num_temps += 1;
04580 #ifdef KEY // bug14194
04581 dim = rank + 1 - dim;
04582 #else
04583 dim = ndim + 2 - dim;
04584 #endif
04585 sprintf(tempname,"@f90red_%d",num_temps);
04586 #ifdef KEY
04587 loopnest = create_doloop(&index,tempname,sizes[dim-1],DIR_NEGATIVE,loopnest);
04588 #else
04589 loopnest = create_doloop(&index,tempname,sizes[dim-1],DIR_POSITIVE,loopnest);
04590 #endif
04591 for (i=0,j=0; i < ndim+1; i++) {
04592 if (i != dim-1) {
04593 WN_DELETE_Tree(sizes[i]);
04594 new_indices[i] = indices[j];
04595 j += 1;
04596 } else {
04597 new_indices[i] = index;
04598 }
04599 }
04600
04601 WN_INSERT_BlockBefore(block,insert_point,loopnest);
04602
04603
04604 accum_expr = F90_Lower_Walk(kids[0],new_indices,rank,stlist,NULL);
04605 accum_store = WN_StidPreg(expr_ty,cur_val,accum_expr);
04606 WN_INSERT_BlockFirst(stlist,accum_store);
04607
04608 comp_expr = WN_CreateExp2(reduction_op,WN_LdidPreg(expr_ty,cur_val),
04609 WN_LdidPreg(expr_ty,accum));
04610 if (Mask_Present) {
04611 mask_expr = F90_Lower_Walk(kids[2],new_indices,rank,stlist,NULL);
04612 mask_expr = WN_LAND(mask_expr,comp_expr);
04613 } else {
04614 mask_expr = comp_expr;
04615 }
04616
04617
04618
04619 accum_block = WN_CreateBlock();
04620 accum_store = WN_StidPreg(expr_ty,accum,WN_LdidPreg(expr_ty,cur_val));
04621 WN_INSERT_BlockLast(accum_block,accum_store);
04622
04623
04624 accum_store = WN_CreateExp2(OPCODE_make_op(OPR_ADD,doloop_ty,MTYPE_V),
04625 WN_LdidPreg(doloop_ty,index),
04626 WN_Intconst(doloop_ty,1));
04627 accum_store = WN_StidPreg(doloop_ty,red_index,accum_store);
04628 WN_INSERT_BlockLast(accum_block,accum_store);
04629
04630
04631 accum_store = WN_CreateIf(mask_expr,accum_block,WN_CreateBlock());
04632 WN_INSERT_BlockLast(stlist,accum_store);
04633
04634
04635 result = WN_LdidPreg(doloop_ty,red_index);
04636 }
04637
04638 return (result);
04639 }
04640
04641
04642
04643
04644
04645
04646 static WN * lower_pack(WN *kids[],PREG_NUM *indices,INT ndim,WN *block, WN *insert_point)
04647 {
04648
04649
04650
04651
04652
04653
04654
04655
04656
04657
04658
04659
04660 WN *store;
04661 WN *lhs;
04662 WN *vector, *mask, *array;
04663 WN *sizes[MAX_NDIM];
04664 PREG_NUM new_indices[MAX_NDIM];
04665 INT ndim_array;
04666 PREG_NUM pack_index;
04667 WN *loopnest;
04668 WN *stlist;
04669 WN *temp;
04670 WN *increment;
04671
04672
04673 store = F90_Current_Stmt;
04674 temp = WN_kid0(store);
04675 WN_kid0(store) = WN_Zerocon(MTYPE_I4);
04676 lhs = WN_COPY_Tree(store);
04677 WN_kid0(store) = temp;
04678
04679 vector = F90_Lower_Walk(kids[2],indices,ndim,block,insert_point);
04680
04681
04682 (void) F90_Size_Walk(kids[0],&ndim_array,sizes);
04683 stlist = create_doloop_nest(new_indices,&loopnest,sizes,ndim_array);
04684
04685
04686 pack_index = Create_Preg(doloop_ty,create_tempname("@f90pack"));
04687
04688
04689 temp = WN_StidPreg(doloop_ty,pack_index,WN_Zerocon(doloop_ty));
04690 WN_INSERT_BlockAfter(F90_Current_Block,F90_Current_Loopnest,loopnest);
04691 WN_INSERT_BlockAfter(F90_Current_Block,F90_Current_Loopnest,temp);
04692
04693
04694 mask = F90_Lower_Walk(kids[1],new_indices,ndim_array,stlist,NULL);
04695 array= F90_Lower_Walk(kids[0],new_indices,ndim_array,stlist,NULL);
04696 (void) F90_Lower_Walk(lhs, &pack_index, 1, stlist, NULL);
04697 WN_Delete(WN_kid0(lhs));
04698 WN_kid0(lhs) = array;
04699
04700
04701 temp = WN_CreateBlock();
04702 WN_INSERT_BlockFirst(temp,lhs);
04703 increment = WN_StidPreg(doloop_ty,pack_index,
04704 WN_CreateExp2(OPCadd,WN_LdidPreg(doloop_ty,pack_index),
04705 WN_Intconst(doloop_ty,1)));
04706 WN_INSERT_BlockLast(temp,increment);
04707 temp = WN_CreateIf(mask,temp,WN_CreateBlock());
04708 WN_INSERT_BlockFirst(stlist,temp);
04709 return (vector);
04710 }
04711
04712 static WN * lower_unpack(WN *kids[],PREG_NUM *indices,INT ndim,WN *block, WN *insert_point)
04713 {
04714 WN *vector, *mask, *field;
04715 PREG_NUM pack_index,p;
04716 WN *if_stmt,*then_block,*else_block;
04717 WN *temp;
04718 WN *increment;
04719 TY_IDX ptr_ty,temp_ty;
04720 WN *lda;
04721 ST *temp_st;
04722 TYPE_ID type;
04723 WN *true_store;
04724 WN *false_store;
04725 WN *load;
04726
04727
04728 pack_index = Create_Preg(doloop_ty,create_tempname("@f90pack"));
04729
04730
04731 temp = WN_StidPreg(doloop_ty,pack_index,WN_Zerocon(doloop_ty));
04732 WN_INSERT_BlockBefore(F90_Current_Block,F90_Current_Loopnest,temp);
04733
04734
04735 vector = F90_Lower_Walk(kids[0],&pack_index,1,block,insert_point);
04736 mask = F90_Lower_Walk(kids[1],indices,ndim,block,insert_point);
04737 field = F90_Lower_Walk(kids[2],indices,ndim,block,insert_point);
04738
04739
04740 if (WN_opcode(vector) == OPC_MLOAD) {
04741 ptr_ty = WN_ty(vector);
04742
04743 temp_ty = TY_pointed(ptr_ty);
04744 temp_st = F90_Lower_Create_Temp(NULL,NULL,NULL,0,temp_ty,NULL);
04745 lda = WN_Lda(Pointer_type,(WN_OFFSET) 0, temp_st);
04746 true_store = WN_CreateMstore((WN_OFFSET) 0, ptr_ty, vector, WN_COPY_Tree(lda),
04747 WN_COPY_Tree(WN_kid1(vector)));
04748 false_store = WN_CreateMstore((WN_OFFSET) 0, ptr_ty, field, WN_COPY_Tree(lda),
04749 WN_COPY_Tree(WN_kid1(vector)));
04750 load = WN_CreateMload((WN_OFFSET) 0, ptr_ty, lda,WN_COPY_Tree(WN_kid1(vector)));
04751 } else {
04752 type = WN_rtype(vector);
04753 p = Create_Preg(type,create_tempname("@f90s"));
04754 true_store = WN_StidPreg(type,p,vector);
04755 false_store = WN_StidPreg(type,p,field);
04756 load = WN_LdidPreg(type,p);
04757 }
04758
04759 then_block = WN_CreateBlock();
04760 else_block = WN_CreateBlock();
04761 WN_INSERT_BlockFirst(then_block,true_store);
04762 increment = WN_StidPreg(doloop_ty,pack_index,
04763 WN_CreateExp2(OPCadd,WN_LdidPreg(doloop_ty,pack_index),
04764 WN_Intconst(doloop_ty,1)));
04765 WN_INSERT_BlockLast(then_block,increment);
04766 WN_INSERT_BlockFirst(else_block,false_store);
04767 if_stmt = WN_CreateIf(mask,then_block,else_block);
04768 WN_INSERT_BlockBefore(block,insert_point,if_stmt);
04769 return (load);
04770 }
04771
04772
04773
04774
04775
04776
04777
04778
04779
04780
04781
04782
04783
04784
04785
04786
04787
04788
04789
04790
04791
04792
04793
04794
04795
04796
04797
04798
04799
04800
04801
04802
04803
04804
04805
04806
04807
04808
04809
04810
04811
04812
04813
04814
04815
04816
04817
04818
04819
04820
04821 static WN *lower_eoshift(WN *kids[],PREG_NUM indices[],INT ndim,WN *block, WN *insert_point)
04822 {
04823 INT dim;
04824 WN *shift;
04825 WN *limit_shift;
04826 WN *boundary;
04827 PREG_NUM new_indices[MAX_NDIM],index,sb_indices[MAX_NDIM];
04828 WN *sizes[MAX_NDIM];
04829 WN *extent;
04830 WN *result;
04831 INT ndim_array;
04832 PREG_NUM shift_index,new_index;
04833 BOOL shift_pos,shift_neg;
04834 char tempname[32];
04835 WN *pos_block;
04836 WN *neg_block;
04837 WN *temp;
04838 WN *setup;
04839 WN *start,*end,*step,*index_id,*body;
04840 WN *lhs;
04841 WN *shift_comp;
04842 PREG_NUM l1,l2,u1,u2;
04843 WN *loopnest,*stlist;
04844 WN *temp_store;
04845 WN * original_loopnest;
04846
04847 INT i,j;
04848
04849 dim = ndim - F90_Get_Dim(kids[3]);
04850 WN_DELETE_Tree(kids[3]);
04851
04852
04853 for (i=0, j=0; i < ndim; i++) {
04854 if (i != dim) {
04855 new_indices[j++] = indices[i];
04856 }
04857 }
04858 shift = kids[1];
04859
04860
04861 (void) F90_Size_Walk(kids[0],&ndim_array,sizes);
04862 extent = sizes[dim];
04863
04864
04865 if (WN_operator(shift)==OPR_INTCONST) {
04866 if (WN_const_val(shift) == 0) {
04867 WN_DELETE_Tree(shift);
04868 WN_DELETE_Tree(kids[2]);
04869 for (i=0 ; i <ndim; i++) {
04870 WN_DELETE_Tree(sizes[i]);
04871 }
04872 result = F90_Lower_Walk(kids[0],indices,ndim,block,insert_point);
04873 return (result);
04874 } else if (WN_operator(extent) == OPR_INTCONST) {
04875 if (WN_const_val(shift) >= WN_const_val(extent) ||
04876 -WN_const_val(shift) >= WN_const_val(extent)) {
04877 WN_DELETE_Tree(kids[0]);
04878 WN_DELETE_Tree(shift);
04879 for (i=0 ; i <ndim; i++) {
04880 WN_DELETE_Tree(sizes[i]);
04881 }
04882 boundary = F90_Lower_Walk(kids[2],new_indices,ndim-1,block,insert_point);
04883 return (boundary);
04884 }
04885 }
04886 }
04887
04888
04889
04890
04891
04892 #ifdef KEY
04893
04894 if (MTYPE_bit_size(Pointer_type) == 64 && WN_rtype(shift) != MTYPE_I8)
04895 kids[1] = WN_Type_Conversion(kids[1], MTYPE_I8);
04896 #endif
04897
04898 temp_store = F90_Current_Stmt;
04899 WN_EXTRACT_FromBlock(block,temp_store);
04900 original_loopnest = F90_Current_Loopnest;
04901
04902 num_temps += 1;
04903 loopnest = WN_CreateBlock();
04904 stlist = loopnest;
04905 if (ndim > 1) {
04906 for (i=ndim-1,j=ndim-2; i >=0 ; i--) {
04907 if (i != dim) {
04908 sprintf(tempname,"@f90li_%d_%d",i,num_temps);
04909 loopnest = create_doloop(&index,tempname,sizes[i],DIR_POSITIVE,loopnest);
04910 sb_indices[j--] = index;
04911 new_indices[i] = index;
04912 }
04913 }
04914 WN_INSERT_BlockBefore(F90_Current_Block,F90_Current_Loopnest,loopnest);
04915 F90_Current_Loopnest = loopnest;
04916 }
04917
04918
04919 boundary = F90_Lower_Walk(kids[2],sb_indices,ndim-1,block,insert_point);
04920 shift = F90_Lower_Walk(kids[1],sb_indices,ndim-1,block,insert_point);
04921
04922
04923 l1 = Create_Preg(doloop_ty,create_tempname("@f90_eos_l1"));
04924 u1 = Create_Preg(doloop_ty,create_tempname("@f90_eos_u1"));
04925 l2 = Create_Preg(doloop_ty,create_tempname("@f90_eos_l2"));
04926 u2 = Create_Preg(doloop_ty,create_tempname("@f90_eos_u2"));
04927
04928 shift_comp = WN_CreateExp2(OPCODE_make_op(OPR_GT,MTYPE_I4,doloop_ty),
04929 WN_COPY_Tree(shift),
04930 WN_Intconst(doloop_ty,0));
04931 if (WN_operator(shift_comp) == OPR_INTCONST) {
04932 if (WN_const_val(shift_comp) == 0) {
04933 shift_neg = TRUE;
04934 shift_pos = FALSE;
04935 } else {
04936 shift_neg = FALSE;
04937 shift_pos = TRUE;
04938 }
04939 WN_DELETE_Tree(shift_comp);
04940 } else {
04941 shift_neg = TRUE;
04942 shift_pos = TRUE;
04943 }
04944
04945
04946 if (shift_pos) {
04947
04948
04949
04950
04951
04952
04953 pos_block = WN_CreateBlock();
04954 temp = WN_StidPreg(doloop_ty,l1,WN_Intconst(doloop_ty,0));
04955 WN_INSERT_BlockLast(pos_block,temp);
04956
04957 limit_shift = WN_CreateExp2(OPCODE_make_op(OPR_MIN,doloop_ty,MTYPE_V),
04958 WN_COPY_Tree(sizes[dim]),WN_COPY_Tree(shift));
04959
04960 temp = WN_StidPreg(doloop_ty,u2,
04961 WN_CreateExp2(OPCsub,WN_COPY_Tree(sizes[dim]),
04962 WN_Intconst(doloop_ty,1)));
04963 WN_INSERT_BlockLast(pos_block,temp);
04964
04965 temp = WN_StidPreg(doloop_ty,u1,WN_CreateExp2(OPCsub,
04966 WN_LdidPreg(doloop_ty,u2),
04967 limit_shift));
04968 WN_INSERT_BlockLast(pos_block,temp);
04969
04970 temp = WN_StidPreg(doloop_ty,l2,WN_CreateExp2(OPCadd,
04971 WN_LdidPreg(doloop_ty,u1),
04972 WN_Intconst(doloop_ty,1)));
04973 WN_INSERT_BlockLast(pos_block,temp);
04974 setup = pos_block;
04975 }
04976
04977 if (shift_neg) {
04978
04979
04980
04981
04982
04983
04984 neg_block = WN_CreateBlock();
04985 temp = WN_StidPreg(doloop_ty,l2,WN_Intconst(doloop_ty,0));
04986 WN_INSERT_BlockLast(neg_block,temp);
04987
04988 limit_shift = WN_CreateExp1(OPCODE_make_op(OPR_NEG,doloop_ty,MTYPE_V),
04989 WN_COPY_Tree(shift));
04990 limit_shift = WN_CreateExp2(OPCODE_make_op(OPR_MIN,doloop_ty,MTYPE_V),
04991 WN_COPY_Tree(sizes[dim]),limit_shift);
04992
04993 temp = WN_StidPreg(doloop_ty,u1,
04994 WN_CreateExp2(OPCsub,WN_COPY_Tree(sizes[dim]),
04995 WN_Intconst(doloop_ty,1)));
04996 WN_INSERT_BlockLast(neg_block,temp);
04997
04998 temp = WN_StidPreg(doloop_ty,l1,limit_shift);
04999
05000 WN_INSERT_BlockLast(neg_block,temp);
05001
05002 temp = WN_StidPreg(doloop_ty,u2,WN_CreateExp2(OPCsub,
05003 WN_LdidPreg(doloop_ty,l1),
05004 WN_Intconst(doloop_ty,1)));
05005 WN_INSERT_BlockLast(neg_block,temp);
05006 setup = neg_block;
05007 }
05008
05009 if (shift_pos && shift_neg) {
05010 setup = WN_CreateIf(shift_comp, pos_block, neg_block);
05011 }
05012
05013
05014 WN_INSERT_BlockFirst(stlist,setup);
05015
05016 new_index = Create_Preg(doloop_ty,create_tempname("@f90_eos_idx"));
05017 shift_index = Create_Preg(doloop_ty,create_tempname("@f90_eos_shft"));
05018
05019
05020 start = WN_StidPreg(doloop_ty,new_index,WN_LdidPreg(doloop_ty,l1));
05021 end = WN_CreateExp2(OPCODE_make_op(OPR_LE,MTYPE_I4,doloop_ty),
05022 WN_LdidPreg(doloop_ty,new_index),
05023 WN_LdidPreg(doloop_ty,u1));
05024 step = WN_StidPreg(doloop_ty,new_index,
05025 WN_CreateExp2(OPCadd,WN_LdidPreg(doloop_ty,new_index),
05026 WN_Intconst(doloop_ty,1)));
05027 index_id = WN_CreateIdname(new_index,MTYPE_To_PREG(doloop_ty));
05028
05029
05030 body = WN_CreateBlock();
05031 temp = create_doloop_node(index_id, start, end, step, body, TRUE);
05032
05033 WN_INSERT_BlockLast(stlist,temp);
05034
05035 temp = WN_StidPreg(doloop_ty,shift_index,WN_CreateExp2(OPCadd,
05036 WN_LdidPreg(doloop_ty,new_index),
05037 shift));
05038 WN_INSERT_BlockFirst(body,temp);
05039
05040
05041
05042
05043
05044 WN_kid0(temp_store) = WN_Intconst(doloop_ty,0);
05045 lhs = WN_COPY_Tree(temp_store);
05046 WN_DELETE_Tree(WN_kid0(temp_store));
05047 WN_DELETE_Tree(WN_kid0(lhs));
05048
05049 WN_INSERT_BlockLast(body,temp_store);
05050 new_indices[dim] = shift_index;
05051 temp = F90_Lower_Walk(kids[0],new_indices,ndim,body,temp_store);
05052 WN_kid0(temp_store) = temp;
05053 new_indices[dim] = new_index;
05054 temp = F90_Lower_Walk(WN_kid1(temp_store),new_indices,ndim,body,temp_store);
05055
05056 WN_kid1(temp_store) = temp;
05057 WN_kid1(lhs) = WN_COPY_Tree(temp);
05058 WN_kid0(lhs) = boundary;
05059
05060
05061 start = WN_StidPreg(doloop_ty,new_index,WN_LdidPreg(doloop_ty,l2));
05062 end = WN_CreateExp2(OPCODE_make_op(OPR_LE,MTYPE_I4,doloop_ty),
05063 WN_LdidPreg(doloop_ty,new_index),
05064 WN_LdidPreg(doloop_ty,u2));
05065 step = WN_StidPreg(doloop_ty,new_index,
05066 WN_CreateExp2(OPCadd,WN_LdidPreg(doloop_ty,new_index),
05067 WN_Intconst(doloop_ty,1)));
05068
05069 body = WN_CreateBlock();
05070 temp = create_doloop_node(WN_COPY_Tree(index_id), start, end, step, body, TRUE);
05071 WN_INSERT_BlockLast(stlist,temp);
05072 WN_INSERT_BlockLast(body,lhs);
05073
05074
05075
05076 if (ndim == 1) {
05077 WN_INSERT_BlockBefore(F90_Current_Block,F90_Current_Loopnest,stlist);
05078 }
05079
05080
05081 WN_EXTRACT_FromBlock(F90_Current_Block,original_loopnest);
05082 WN_DELETE_Tree(original_loopnest);
05083
05084 return (NULL);
05085 }
05086
05087
05088 static WN *lower_cshift(WN *kids[],PREG_NUM indices[],INT ndim,WN *block, WN *insert_point)
05089 {
05090 INT dim;
05091 WN *shift;
05092 PREG_NUM new_indices[MAX_NDIM];
05093 WN *sizes[MAX_NDIM];
05094 WN *extent;
05095 WN *store;
05096 WN *result;
05097 INT ndim_array;
05098 PREG_NUM shifted_index,shift_preg;
05099
05100 INT i,j;
05101
05102 dim = ndim - F90_Get_Dim(kids[2]);
05103 WN_DELETE_Tree(kids[2]);
05104
05105
05106 for (i=0, j=0; i < ndim; i++) {
05107 if (i != dim) {
05108 new_indices[j++] = indices[i];
05109 }
05110 }
05111 shift = F90_Lower_Walk(kids[1],new_indices,ndim-1,block,insert_point);
05112
05113
05114 (void) F90_Size_Walk(kids[0],&ndim_array,sizes);
05115 for (i=0; i < ndim; i++) {
05116 if (i != dim) {
05117 new_indices[i] = indices[i];
05118 WN_DELETE_Tree(sizes[i]);
05119 } else {
05120 extent = sizes[i];
05121 }
05122 }
05123 #ifdef KEY
05124
05125 if (MTYPE_bit_size(Pointer_type) == 64 && WN_rtype(shift) != MTYPE_I8)
05126 shift = WN_Type_Conversion(shift, MTYPE_I8);
05127 #endif
05128 shift = WN_CreateExp2(OPCmod,shift,WN_COPY_Tree(extent));
05129
05130
05131 if (WN_operator(shift)==OPR_INTCONST && WN_const_val(shift) == 0) {
05132 WN_DELETE_Tree(shift);
05133 WN_DELETE_Tree(extent);
05134 new_indices[dim] = indices[dim];
05135 } else {
05136 shifted_index = Create_Preg(doloop_ty,create_tempname("@f90cshift"));
05137 shift_preg = Create_Preg(doloop_ty,create_tempname("@f90cshiftp"));
05138 new_indices[dim] = shifted_index;
05139
05140
05141 store = WN_StidPreg(doloop_ty,shift_preg,
05142 WN_CreateExp2(OPCadd,WN_LdidPreg(doloop_ty,indices[dim]),shift));
05143 WN_INSERT_BlockBefore(block,insert_point,store);
05144
05145 store = WN_CreateExp3(OPCODE_make_op(OPR_SELECT,doloop_ty,MTYPE_V),
05146 WN_CreateExp2(OPCODE_make_op(OPR_GE,MTYPE_I4,doloop_ty),
05147 WN_LdidPreg(doloop_ty,shift_preg),
05148 WN_COPY_Tree(extent)),
05149 extent,
05150 WN_Intconst(doloop_ty,0));
05151 store = WN_CreateExp2(OPCsub,WN_LdidPreg(doloop_ty,shift_preg),store);
05152 store = WN_StidPreg(doloop_ty,shifted_index,store);
05153 WN_INSERT_BlockBefore(block,insert_point,store);
05154 }
05155
05156 result = F90_Lower_Walk(kids[0],new_indices,ndim,block,insert_point);
05157 return (result);
05158 }
05159
05160
05161
05162
05163
05164
05165
05166
05167 static WN * lower_mm_matmul(TYPE_ID rty,WN *kids[],PREG_NUM indices[],WN *block,WN *insert_point)
05168 {
05169 WN *inner_sizes[2];
05170 TYPE_ID ty;
05171 INT ndim;
05172 PREG_NUM A1_indices[2];
05173 PREG_NUM A2_indices[2];
05174 PREG_NUM accum;
05175 PREG_NUM inner_index;
05176 WN * idty_store;
05177 WN *a1, *a2;
05178 WN * stlist, *loopnest;
05179 WN * result;
05180 OPCODE add_op, mpy_op;
05181
05182
05183
05184 (void) F90_Size_Walk(kids[0],&ndim,inner_sizes);
05185 WN_DELETE_Tree(inner_sizes[1]);
05186
05187
05188 ty = Mtype_comparison(rty);
05189
05190 if (rty == MTYPE_B) {
05191 add_op = OPC_I4LIOR;
05192 mpy_op = OPC_I4LAND;
05193 ty = MTYPE_I4;
05194 rty = MTYPE_I4;
05195 } else {
05196 add_op = OPCODE_make_op(OPR_ADD,ty,MTYPE_V);
05197 mpy_op = OPCODE_make_op(OPR_MPY,ty,MTYPE_V);
05198 }
05199
05200 accum = Create_Preg(rty,create_tempname("@f90mm"));
05201 idty_store = WN_StidPreg(rty,accum,WN_Zerocon(ty));
05202 WN_INSERT_BlockBefore(block,insert_point,idty_store);
05203
05204 loopnest = WN_CreateBlock();
05205 stlist = loopnest;
05206 loopnest = create_doloop(&inner_index,create_tempname("@f90_mmidx"),inner_sizes[0],DIR_POSITIVE,
05207 loopnest);
05208 WN_INSERT_BlockBefore(block,insert_point,loopnest);
05209 A1_indices[0] = inner_index;
05210 A1_indices[1] = indices[1];
05211 A2_indices[0] = indices[0];
05212 A2_indices[1] = inner_index;
05213
05214
05215 a1 = F90_Lower_Walk(kids[0],A1_indices,2,stlist,NULL);
05216 a2 = F90_Lower_Walk(kids[1],A2_indices,2,stlist,NULL);
05217
05218
05219 a1 = WN_CreateExp2(mpy_op,a1,a2);
05220 a1 = WN_StidPreg(rty,accum,WN_CreateExp2(add_op,WN_LdidPreg(rty,accum),a1));
05221
05222 WN_INSERT_BlockLast(stlist,a1);
05223
05224
05225 result = WN_LdidPreg(rty,accum);
05226
05227 return (result);
05228
05229 }
05230
05231
05232
05233
05234
05235
05236 static WN * lower_mv_matmul(TYPE_ID rty,WN *kids[],PREG_NUM indices[],WN *block,WN *insert_point)
05237 {
05238 WN *inner_sizes1[2];
05239 WN *inner_sizes2[2];
05240 TYPE_ID ty;
05241 INT ndim1,ndim2;
05242 PREG_NUM A1_indices[2];
05243 PREG_NUM A2_indices[2];
05244 PREG_NUM accum;
05245 PREG_NUM inner_index;
05246 WN * idty_store;
05247 WN *a1, *a2;
05248 WN * stlist, *loopnest;
05249 WN * result;
05250 OPCODE add_op, mpy_op;
05251
05252
05253
05254 ty = Mtype_comparison(rty);
05255
05256 if (rty == MTYPE_B) {
05257 add_op = OPC_I4LIOR;
05258 mpy_op = OPC_I4LAND;
05259 ty = MTYPE_I4;
05260 rty = MTYPE_I4;
05261 } else {
05262 add_op = OPCODE_make_op(OPR_ADD,ty,MTYPE_V);
05263 mpy_op = OPCODE_make_op(OPR_MPY,ty,MTYPE_V);
05264 }
05265
05266 accum = Create_Preg(rty,create_tempname("@f90mv"));
05267 idty_store = WN_StidPreg(rty,accum,WN_Zerocon(ty));
05268 WN_INSERT_BlockBefore(block,insert_point,idty_store);
05269
05270
05271 (void) F90_Size_Walk(kids[0],&ndim1,inner_sizes1);
05272 (void) F90_Size_Walk(kids[1],&ndim2,inner_sizes2);
05273
05274 loopnest = WN_CreateBlock();
05275 stlist = loopnest;
05276
05277
05278 if (ndim1 == 2) {
05279
05280 WN_DELETE_Tree(inner_sizes1[0]);
05281 WN_DELETE_Tree(inner_sizes1[1]);
05282 loopnest = create_doloop(&inner_index,create_tempname("@f90_mvidx"),inner_sizes2[0],DIR_POSITIVE,
05283 loopnest);
05284 A1_indices[0] = inner_index;
05285 A1_indices[1] = indices[0];
05286 a1 = F90_Lower_Walk(kids[0],A1_indices,2,stlist,NULL);
05287 A2_indices[0] = inner_index;
05288 a2 = F90_Lower_Walk(kids[1],A2_indices,1,stlist,NULL);
05289 } else {
05290
05291 WN_DELETE_Tree(inner_sizes2[0]);
05292 WN_DELETE_Tree(inner_sizes2[1]);
05293 loopnest = create_doloop(&inner_index,create_tempname("@f90_mvidx"),inner_sizes1[0],DIR_POSITIVE,
05294 loopnest);
05295 A1_indices[0] = inner_index;
05296 a1 = F90_Lower_Walk(kids[0],A1_indices,1,stlist,NULL);
05297 A2_indices[0] = indices[0];
05298 A2_indices[1] = inner_index;
05299 a2 = F90_Lower_Walk(kids[1],A2_indices,2,stlist,NULL);
05300 }
05301 WN_INSERT_BlockBefore(block,insert_point,loopnest);
05302
05303
05304 a1 = WN_CreateExp2(mpy_op,a1,a2);
05305 a1 = WN_StidPreg(rty,accum,WN_CreateExp2(add_op,WN_LdidPreg(rty,accum),a1));
05306
05307 WN_INSERT_BlockLast(stlist,a1);
05308
05309
05310 result = WN_LdidPreg(rty,accum);
05311
05312 return (result);
05313
05314 }
05315
05316
05317
05318
05319
05320
05321
05322
05323
05324 static WN * lower_transformationals(WN *expr, PREG_NUM *indices, INT ndim, WN * block, WN *insert_point)
05325 {
05326 WN *result;
05327 WN *kids[6];
05328 WN *kid;
05329 INT dim;
05330 TYPE_ID ty;
05331 INTRINSIC intrin;
05332 INT numargs,i,j;
05333 PREG_NUM new_indices[MAX_NDIM];
05334
05335 numargs = WN_kid_count(expr);
05336 ty = WN_rtype(expr);
05337 intrin = WN_GET_INTRINSIC(expr);
05338
05339
05340 for (i=0 ; i < numargs; i++) {
05341 kid = WN_kid(expr,i);
05342 if (WN_kid_count(kid) == 0 || WN_opcode(kid) == OPC_VPARM) {
05343 kids[i] = NULL;
05344 WN_Delete(kid);
05345 } else if (WN_operator(kid) == OPR_PARM) {
05346 kids[i] = WN_kid0(kid);
05347 WN_Delete(kid);
05348 } else {
05349 kids[i] = kid;
05350 }
05351 }
05352 WN_Delete(expr);
05353
05354 switch (intrin) {
05355 case INTRN_RESHAPE:
05356 case INTRN_DOT_PRODUCT:
05357 case INTRN_COUNT:
05358 DevAssert((0),("Intrinsic should not get inlined"));
05359 break;
05360
05361 case INTRN_SPREAD:
05362 dim = ndim - WN_const_val(kids[1]);
05363 for (i=0,j=0; i < ndim; i++) {
05364 if (dim != i) {
05365 new_indices[j++] = indices[i];
05366 }
05367 }
05368 WN_DELETE_Tree(kids[1]);
05369 WN_DELETE_Tree(kids[2]);
05370 result = F90_Lower_Walk(kids[0],new_indices,ndim-1, block,insert_point);
05371 break;
05372
05373
05374 case INTRN_TRANSPOSE:
05375 new_indices[0] = indices[1];
05376 new_indices[1] = indices[0];
05377 result = F90_Lower_Walk(kids[0],new_indices,2, block,insert_point);
05378 break;
05379
05380
05381 case INTRN_MATMUL:
05382 if (ndim == 1) {
05383 result = lower_mv_matmul(ty,kids,indices,block,insert_point);
05384 } else if (ndim==2) {
05385 result = lower_mm_matmul(ty,kids,indices,block,insert_point);
05386 } else {
05387 Is_True(FALSE,("matmul with ndim != 1 or 2"));
05388 }
05389 break;
05390
05391 case INTRN_ALL:
05392 kids[2] = NULL;
05393 result = lower_reduction(MTYPE_I4,OPR_LAND,kids,indices,ndim,block,insert_point);
05394 break;
05395 case INTRN_ANY:
05396 kids[2] = NULL;
05397 result = lower_reduction(MTYPE_I4,OPR_LIOR,kids,indices,ndim,block,insert_point);
05398 break;
05399 case INTRN_PRODUCT:
05400 result = lower_reduction(ty,OPR_MPY,kids,indices,ndim,block,insert_point);
05401 break;
05402 case INTRN_SUM:
05403 result = lower_reduction(ty,OPR_ADD,kids,indices,ndim,block,insert_point);
05404 break;
05405 case INTRN_MAXVAL:
05406 result = lower_reduction(ty,OPR_MAX,kids,indices,ndim,block,insert_point);
05407 break;
05408 case INTRN_MINVAL:
05409 result = lower_reduction(ty,OPR_MIN,kids,indices,ndim,block,insert_point);
05410 break;
05411
05412 case INTRN_PACK:
05413 result = lower_pack(kids,indices,ndim,block,insert_point);
05414 break;
05415
05416 case INTRN_UNPACK:
05417 result = lower_unpack(kids,indices,ndim,block,insert_point);
05418 break;
05419
05420 case INTRN_MAXLOC:
05421 result = lower_maxminloc(OPR_MAX,kids,indices,ndim,block,insert_point);
05422 break;
05423
05424 case INTRN_MINLOC:
05425 result = lower_maxminloc(OPR_MIN,kids,indices,ndim,block,insert_point);
05426 break;
05427
05428 case INTRN_CSHIFT:
05429 result = lower_cshift(kids,indices,ndim,block,insert_point);
05430 break;
05431
05432 case INTRN_EOSHIFT:
05433 result = lower_eoshift(kids,indices,ndim,block,insert_point);
05434 break;
05435
05436 default:
05437 DevAssert((0),("Unknown intrinsic in lower_transformationals"));
05438 }
05439
05440 return (result);
05441 }
05442
05443
05444
05445
05446
05447
05448
05449 static WN * strip_mloads(WN *w)
05450 {
05451 WN *kid;
05452 while (WN_opcode(w) == OPC_MLOAD) {
05453 kid = WN_kid0(w);
05454 WN_DELETE_Tree(WN_kid1(w));
05455 WN_Delete(w);
05456 w = kid;
05457 }
05458 return (w);
05459 }
05460
05461
05462
05463
05464
05465
05466
05467
05468
05469
05470
05471
05472
05473
05474
05475
05476
05477
05478
05479
05480
05481
05482 static WN * F90_Lower_Walk(WN *expr, PREG_NUM *indices, INT ndim, WN * block, WN *insert_point)
05483 {
05484 OPCODE op,kidop;
05485 OPERATOR opr,kidopr;
05486 WN *kid,*kid1;
05487 WN *result;
05488 INT numkids,array_ndim,i,j;
05489 BOOL do_kids = FALSE;
05490 TYPE_ID ty;
05491 WN * index_ldid;
05492 INTRINSIC intr;
05493
05494 op = WN_opcode(expr);
05495 opr = OPCODE_operator(op);
05496 numkids = WN_kid_count(expr);
05497 result = expr;
05498
05499 switch (opr) {
05500 case OPR_BLOCK:
05501 kid = WN_first(expr);
05502 while (kid) {
05503 F90_Lower_Walk(kid,indices,ndim,block,insert_point);
05504 kid = WN_next(kid);
05505 }
05506 break;
05507
05508 case OPR_ARRAYEXP:
05509
05510 for (i=1; i<numkids; i++) {
05511 WN_DELETE_Tree(WN_kid(expr,i));
05512 }
05513 kid = WN_kid0(expr);
05514 WN_Delete(expr);
05515 result = F90_Lower_Walk(kid,indices,ndim,block,insert_point);
05516 break;
05517
05518 case OPR_ARRSECTION:
05519
05520 WN_set_opcode(result,OPCODE_make_op(OPR_ARRAY,OPCODE_rtype(op),MTYPE_V));
05521
05522
05523 array_ndim = (numkids - 1) / 2;
05524 j = 0;
05525 for (i=array_ndim+1; i < numkids; i++) {
05526 kid = WN_kid(expr,i);
05527 kidop = WN_opcode(kid);
05528 kidopr = OPCODE_operator(kidop);
05529 if (kidopr == OPR_ARRAYEXP || kidopr == OPR_TRIPLET) {
05530
05531 kid = F90_Lower_Walk(kid,&indices[j],1,block,insert_point);
05532 j += 1;
05533 WN_kid(expr,i) = kid;
05534 } else {
05535
05536 kid = F90_Lower_Walk(kid,NULL,0,block,insert_point);
05537 WN_kid(expr,i) = kid;
05538 }
05539 }
05540 break;
05541
05542 case OPR_TRIPLET:
05543
05544 FmtAssert((ndim==1),("F90_Lower_Walk: trying to lower a triplet with ndim != 1"));
05545 WN_DELETE_Tree(WN_kid2(expr));
05546 kid = F90_Lower_Walk(WN_kid0(expr),NULL,0,block,insert_point);
05547 kid1 = F90_Lower_Walk(WN_kid1(expr),NULL,0,block,insert_point);
05548 ty = doloop_ty;
05549 #ifdef KEY // bug 3130
05550 if (MTYPE_byte_size(ty) != MTYPE_byte_size(WN_rtype(kid)))
05551 kid = WN_Cvt(WN_rtype(kid), ty, kid);
05552 #endif
05553 #ifdef KEY // bug 3518
05554 if (MTYPE_byte_size(ty) != MTYPE_byte_size(WN_rtype(kid1)))
05555 kid1 = WN_Cvt(WN_rtype(kid1), ty, kid1);
05556 #endif
05557 index_ldid = WN_LdidPreg(ty,indices[0]);
05558 kid1 = WN_CreateExp2(OPCODE_make_op(OPR_MPY,ty,MTYPE_V),
05559 index_ldid,
05560 kid1);
05561 #ifdef KEY // bug 3130
05562 if (MTYPE_byte_size(ty) != MTYPE_byte_size(WN_rtype(kid1)))
05563 kid1 = WN_Cvt(WN_rtype(kid1), ty, kid1);
05564 #endif
05565 result = WN_CreateExp2(OPCODE_make_op(OPR_ADD,ty,MTYPE_V), kid, kid1);
05566 break;
05567
05568 case OPR_WHERE:
05569
05570 WN_set_opcode(result,OPC_IF);
05571 do_kids = TRUE;
05572 break;
05573
05574 case OPR_MLOAD:
05575
05576 kid = F90_Lower_Walk(WN_kid0(expr),indices,ndim,block,insert_point);
05577 WN_kid0(expr) = strip_mloads(kid);
05578 kid = F90_Lower_Walk(WN_kid1(expr),indices,ndim,block,insert_point);
05579 WN_kid1(expr) = kid;
05580 do_kids = FALSE;
05581 break;
05582
05583 case OPR_INTRINSIC_CALL:
05584 case OPR_INTRINSIC_OP:
05585 intr = WN_GET_INTRINSIC(expr);
05586 if (F90_Is_Transformational(intr)) {
05587 result = lower_transformationals(expr,indices, ndim, block, insert_point);
05588 do_kids = FALSE;
05589 } else if (F90_Is_Char_Intrinsic(intr)) {
05590 for (i=0; i < numkids; i++) {
05591 kid = WN_kid0(WN_kid(expr,i));
05592 kid = F90_Lower_Walk(kid,indices,ndim,block,insert_point);
05593 WN_kid0(WN_kid(expr,i)) = strip_mloads(kid);
05594 }
05595 do_kids = FALSE;
05596 } else {
05597 do_kids = TRUE;
05598 }
05599 break;
05600
05601 default:
05602
05603 do_kids = TRUE;
05604 break;
05605 }
05606
05607 if (do_kids) {
05608 for (i=0; i < numkids; i++) {
05609 kid = WN_kid(expr,i);
05610 kid = F90_Lower_Walk(kid,indices,ndim,block,insert_point);
05611 if (kid) {
05612 WN_kid(expr,i) = kid;
05613 }
05614 }
05615 }
05616
05617 return (result);
05618 }
05619
05620
05621
05622
05623
05624
05625
05626
05627
05628
05629 static BOOL F90_Generate_Loops(WN *stmt, WN *block)
05630 {
05631 F90_LOWER_AUX_DATA *adata;
05632 INT ndim;
05633 PREG_NUM indices[MAX_NDIM];
05634 PREG_NUM index;
05635 INT i;
05636 INT perm;
05637 DIR_FLAG dir;
05638 WN *count;
05639 WN *loopnest,*stlist;
05640 char tempname[32];
05641 BOOL add_prompf;
05642
05643 #ifndef KEY // bug 8567
05644
05645 if (WN_operator(stmt) == OPR_IO) {
05646 return(TRUE);
05647 }
05648 #endif
05649
05650 adata = GET_F90_MAP(stmt);
05651 if (adata) {
05652 ndim = NDIM(adata);
05653 add_prompf = !NO_PROMPF_INFO(adata);
05654 } else {
05655 ndim = 0;
05656 }
05657
05658 if (ndim > 0) {
05659
05660 loopnest = WN_CreateBlock();
05661 stlist = loopnest;
05662 num_temps += 1;
05663 for (i=ndim-1; i >= 0; i--) {
05664 perm = PERM_INDEX(adata,i);
05665 count = ITER_COUNT(adata,perm);
05666 dir = DIRECTION(adata,perm);
05667 sprintf(tempname,"@f90li_%d_%d",i,num_temps);
05668
05669
05670 loopnest = create_doloop(&index,tempname,count,dir,loopnest,add_prompf);
05671 indices[i] = index;
05672 }
05673
05674
05675
05676 WN_INSERT_BlockBefore(block,stmt,loopnest);
05677 (void) WN_EXTRACT_FromBlock(block,stmt);
05678 WN_INSERT_BlockFirst(stlist,stmt);
05679
05680
05681 BOOL_VECTOR::iterator bi = F90_MP_Region_Isworkshare.begin();
05682 if( (bi != F90_MP_Region_Isworkshare.end()) && *bi ){
05683 WN* region = WN_CreateRegion(REGION_KIND_MP,
05684 WN_CreateBlock(),
05685 WN_CreateBlock(),
05686 WN_CreateBlock(),
05687 -1,
05688 0);
05689 WN* region_body = WN_region_body(region);
05690
05691 WN_INSERT_BlockBefore(block,loopnest,region);
05692 (void) WN_EXTRACT_FromBlock(block, loopnest);
05693 WN_INSERT_BlockFirst(region_body,loopnest);
05694
05695 WN* pragmas = WN_region_pragmas(region);
05696
05697 WN* pragma = WN_CreatePragma(WN_PRAGMA_PDO_BEGIN, (ST *)NULL, 0, 1);
05698 WN_set_pragma_omp(pragma);
05699 WN_INSERT_BlockFirst(pragmas, pragma);
05700
05701 ST *index_st = MTYPE_To_PREG(doloop_ty);
05702
05703 for(i=0; i<ndim; i++){
05704 pragma = WN_CreatePragma(WN_PRAGMA_LOCAL, index_st, indices[i], 0);
05705 WN_set_pragma_omp(pragma);
05706 WN_INSERT_BlockLast(pragmas, pragma);
05707 }
05708
05709 pragma = WN_CreatePragma(WN_PRAGMA_END_MARKER, (ST *)NULL, 0, 0);
05710 WN_set_pragma_omp(pragma);
05711 WN_INSERT_BlockLast(pragmas, pragma);
05712 F90_Current_Loopnest = region;
05713 }
05714 else{
05715 F90_Current_Loopnest = loopnest;
05716 }
05717
05718
05719 F90_Current_Stmt = stmt;
05720 F90_Current_Loopnest = loopnest;
05721 } else {
05722
05723 F90_Current_Stmt = stmt;
05724 F90_Current_Loopnest = stmt;
05725 stlist = block;
05726 }
05727 F90_Current_Block = block;
05728 stmt = F90_Lower_Walk(stmt,indices,ndim,stlist,stmt);
05729
05730 return (TRUE);
05731 }
05732
05733
05734
05735
05736
05737
05738
05739
05740
05741
05742
05743
05744
05745 #define TRACE_AFTER(x,y) if (Get_Trace(TP_LOWER90,x)) {\
05746 fprintf(TFile,"\n\n========== Dump after %s ==========\n",y); fdump_tree(TFile,pu);}
05747
05748 #ifdef Is_True_On
05749 #define DUPCHECK 1
05750 #else
05751 #undef DUPCHECK
05752 #endif
05753
05754 #ifdef DUPCHECK
05755 #define SET_P_MAP(x,t) WN_MAP_Set(f90_parent_map,(x),(void *) (t))
05756 #define GET_P_MAP(x) ((WN *) WN_MAP_Get(f90_parent_map,(x)))
05757
05758 static void check_for_duplicates(WN *pu, const char *str)
05759 {
05760
05761 static WN_MAP f90_parent_map;
05762 WN_ITER *ti;
05763 WN *w, *k, *p;
05764 INT i;
05765 BOOL found_dup = FALSE;
05766
05767 f90_parent_map = WN_MAP_Create(f90_lower_pool);
05768 WB_F90_Lower_Set_Parent_Map(f90_parent_map);
05769
05770
05771 ti = WN_WALK_TreeIter(pu);
05772 while (ti) {
05773 w = WN_ITER_wn(ti);
05774
05775 for (i=0; i < WN_kid_count(w) ; i++) {
05776 k = WN_kid(w,i);
05777 p = GET_P_MAP(k);
05778 if ((p != NULL) && (p != w)) {
05779 fprintf(TFile,"\n%s: Multiparented node p=%8p, w=%8p, k=%d\n",str,p,w,i);
05780 fprintf(TFile,"parent:\n"); fdump_tree(TFile,p);
05781 fprintf(TFile,"current:\n"); fdump_tree(TFile,w);
05782
05783
05784 WN * temp_csc = GET_P_MAP(w);
05785 if( temp_csc != NULL ){
05786 fprintf(TFile, "current's parent:\n");
05787 fdump_tree(TFile, temp_csc );
05788 }
05789
05790 fprintf(TFile,"multichild:\n"); fdump_tree(TFile,k);
05791 found_dup = TRUE;
05792 } else {
05793 SET_P_MAP(k,w);
05794 }
05795 }
05796 ti = WN_WALK_TreeNext(ti);
05797 }
05798 WB_F90_Lower_Set_Parent_Map(WN_MAP_UNDEFINED);
05799 WN_MAP_Delete(f90_parent_map);
05800 if (found_dup) {
05801 DevWarn(("Duplicate WHIRL nodes found %s\n"),str);
05802 }
05803 }
05804 #endif
05805
05806
05807
05808
05809
05810
05811
05812
05813
05814 void Strip_OMP_Workshare(WN * pu)
05815 {
05816 OPCODE opcode = WN_opcode(pu);
05817 if(opcode != OPC_REGION){
05818 if(opcode == OPC_BLOCK){
05819 WN *kid = WN_first(pu);
05820 while(kid){
05821 Strip_OMP_Workshare(kid);
05822 kid = WN_next(kid);
05823 }
05824 }
05825 else if(OPCODE_is_scf(opcode)){
05826 INT numkids = WN_kid_count(pu);
05827 for(INT i=0; i<numkids; i++){
05828 Strip_OMP_Workshare(WN_kid(pu,i));
05829 }
05830 }
05831 return;
05832 }
05833 WN *pragmas = WN_region_pragmas(pu);
05834 WN *body = WN_region_body(pu);
05835 if(pragmas){
05836 WN *pragma = WN_first(pragmas);
05837 while(pragma){
05838 if(WN_opcode(pragma)==OPC_PRAGMA){
05839 if((WN_PRAGMA_ID)WN_pragma(pragma)==WN_PRAGMA_PWORKSHARE_BEGIN){
05840 WN_Delete(WN_EXTRACT_FromBlock(pragmas, pragma));
05841 WN *end_wn = WN_last(pragmas);
05842 if(end_wn && WN_opcode(end_wn) == OPC_PRAGMA &&
05843 ((WN_PRAGMA_ID)WN_pragma(end_wn)==WN_PRAGMA_NOWAIT) ||
05844 ((WN_PRAGMA_ID)WN_pragma(end_wn)==WN_PRAGMA_END_MARKER) ){
05845 WN_Delete(WN_EXTRACT_FromBlock(pragmas, end_wn));
05846 }
05847 break;
05848 }
05849 if((WN_PRAGMA_ID)WN_pragma(pragma)==WN_PRAGMA_PARALLEL_WORKSHARE){
05850 WN_pragma(pragma) = WN_PRAGMA_PARALLEL_BEGIN;
05851 break;
05852 }
05853 }
05854 pragma = WN_next(pragma);
05855 }
05856 }
05857 Strip_OMP_Workshare(body);
05858 }
05859
05860
05861
05862
05863
05864
05865
05866
05867
05868
05869
05870
05871
05872 WN * F90_Lower (PU_Info* pu_info, WN *pu) {
05873
05874 current_pu = &Get_Current_PU();
05875 F90_Lower_Prompf_Init(pu_info);
05876
05877
05878 if (!PU_f90_lang(*current_pu)){
05879 if(PU_has_mp(*current_pu)) Strip_OMP_Workshare(pu);
05880 return (pu);
05881 }
05882
05883 F90_Lower_Init();
05884
05885 trace_dependence = Get_Trace(TP_LOWER90,TRACE_DEPENDENCE_ANALYSIS);
05886 trace_depinfo = Get_Trace(TP_LOWER90,TRACE_DEPINFO);
05887
05888 if (Get_Trace ( TKIND_IR, TP_LOWER90)) {
05889 fprintf(TFile,"\n\n========== Dump before F90 Lowering ==========\n");
05890 fdump_tree(TFile,pu);
05891 }
05892
05893 #ifdef DUPCHECK
05894 check_for_duplicates(pu,"before");
05895 #endif
05896
05897
05898 F90_Walk_All_Statements(pu,F90_Scalarize_Triplets_And_Sizes);
05899
05900
05901
05902
05903
05904
05905 F90_Analyze_Dependencies(pu);
05906
05907 if (array_statement_seen) {
05908 TRACE_AFTER(TRACE_DEPENDENCE,"Dependence Analysis");
05909
05910
05911 F90_Walk_Statements(pu,F90_Do_Copies);
05912 TRACE_AFTER(TRACE_COPIES,"Copy motion");
05913
05914
05915 F90_Walk_Statements(pu, F90_Move_Transformationals);
05916 TRACE_AFTER(TRACE_TRANSFORMATIONALS,"Transformational motion");
05917
05918 F90_Walk_All_Statements(pu, F90_Insert_All_Prelists);
05919 TRACE_AFTER(TRACE_INSERTIONS,"Extra statement insertions");
05920
05921
05922 if (temp_allocations_inserted) {
05923 F90_Walk_All_Statements(pu, F90_Insert_Temp_Allocations);
05924 temp_allocations_inserted = FALSE;
05925 }
05926
05927
05928 F90_Walk_Statements(pu,F90_Generate_Loops);
05929 if (temp_allocations_inserted) {
05930 F90_Walk_All_Statements(pu, F90_Insert_Temp_Allocations);
05931 temp_allocations_inserted = FALSE;
05932 }
05933 TRACE_AFTER(TRACE_DOLOOPS,"Do loop creation");
05934 }
05935
05936
05937
05938 F90_Walk_All_Statements(pu,F90_Lower_Intrinsic_Fixup);
05939
05940
05941
05942 F90_Walk_Statements(pu,F90_Lower_Alloc_Dealloc);
05943
05944 #ifdef DUPCHECK
05945 check_for_duplicates(pu,"after");
05946 #endif
05947
05948 if (Get_Trace ( TKIND_IR, TP_LOWER90)) {
05949 fprintf(TFile,"\n\n========== Dump after F90 Lowering ==========\n");
05950 fdump_tree(TFile,pu);
05951 }
05952 if (Get_Trace(TKIND_SYMTAB,TP_LOWER90)) {
05953 fprintf(TFile,"\n\n========== Symbol tables after F90 Lowering ==========\n");
05954 Print_symtab (TFile, GLOBAL_SYMTAB);
05955 Print_symtab (TFile, CURRENT_SYMTAB);
05956 }
05957
05958 F90_Lower_Term();
05959 F90_Lower_Prompf_Finish(pu_info);
05960
05961 return (pu);
05962 }