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 #include "defs.h"
00037 #include "errors.h"
00038 #include "tracing.h"
00039 #include "timing.h"
00040 #include "stab.h"
00041 #include "util.h"
00042 #include "strtab.h"
00043 #include "wn.h"
00044 #include "wn_util.h"
00045 #include "stblock.h"
00046 #include "ir_reader.h"
00047 #include "config.h"
00048 #include "config_opt.h"
00049 #include "targ_sim.h"
00050 #include "targ_const.h"
00051 #include "const.h"
00052 #include "wn_map.h"
00053 #include "wn_simp.h"
00054
00055
00056
00057
00058 #define EXTERN extern
00059 #include "wtable.h"
00060
00061 #include "f90_utils.h"
00062
00063 #define F90_LOWER_INTERNAL
00064 #include "f90_lower.h"
00065
00066
00067 #define is_constant(x) (WN_operator(x)==OPR_INTCONST)
00068
00069
00070 #define WN_GET_INTRINSIC(x) (INTRINSIC) WN_intrinsic(x)
00071
00072
00073 #define TRACE_DEPENDENCE 2
00074 #define TRACE_INSERTIONS 4
00075 #define TRACE_DOLOOPS 8
00076 #define TRACE_DEPENDENCE_ANALYSIS 0x20
00077 #define TRACE_SYMTAB 0x1
00078 #define TRACE_TRANSFORMATIONALS 0x40
00079 #define TRACE_COPIES 0x80
00080 #define TRACE_DEPINFO 0x100
00081
00082 static BOOL trace_dependence;
00083 static BOOL trace_depinfo;
00084
00085 typedef struct f90lower_aux_data_s {
00086 WN *prelist;
00087 WN *postlist;
00088 WN *alloc_prelist;
00089 WN *dealloc_postlist;
00090 WN **iter_count;
00091
00092 mINT16 *perm_index;
00093 DIR_FLAG *directions;
00094 mINT16 ndim;
00095 COPY_FLAG_T copy_flag:4;
00096 BOOL known_independent:2;
00097 } F90_LOWER_AUX_DATA;
00098
00099
00100
00101 typedef struct f90_dep_info_s {
00102 INT ndim;
00103 DEP_SUMMARY summary;
00104 DIR_FLAG directions[MAX_NDIM];
00105 } DEP_INFO;
00106
00107 #define DEP_NDIM(x) ((x)->ndim)
00108 #define DEP_DIRECTION(x,n) ((x)->directions[(n)])
00109 #define DEP_SUMMARY(x) ((x)->summary)
00110 #define SET_DEP_NDIM(x,y) (x)->ndim=(y)
00111 #define SET_DEP_SUMMARY(x,y) (x)->summary=(y)
00112 #define SET_DEP_DIRECTION(x,n,d) (x)->directions[(n)]=(d)
00113
00114
00115 #define PRELIST(x) ((x)->prelist)
00116 #define POSTLIST(x) ((x)->postlist)
00117 #define ALLOC_PRELIST(x) ((x)->alloc_prelist)
00118 #define DEALLOC_POSTLIST(x) ((x)->dealloc_postlist)
00119 #define ITER_COUNT(x,n) (*(((x)->iter_count) + (n)))
00120 #define ITER_COUNT_PTR(x) ((x)->iter_count)
00121 #define PERM_INDEX(x,n) (*(((x)->perm_index) + (n)))
00122 #define DIRECTION(x,n) (*(((x)->directions) + (n)))
00123 #define NDIM(x) ((x)->ndim)
00124 #define COPY_FLAG(x) ((x)->copy_flag)
00125 #define KNOWN_INDEPENDENT(x) ((x)->known_independent)
00126
00127 #define SET_PRELIST(x,y) (x)->prelist = (y)
00128 #define SET_POSTLIST(x,y) (x)->postlist = (y)
00129 #define SET_ALLOC_PRELIST(x,y) (x)->alloc_prelist = (y)
00130 #define SET_DEALLOC_POSTLIST(x,y) (x)->dealloc_postlist = (y)
00131 #define SET_ITER_COUNT(x,n,y) *(((x)->iter_count) + (n)) = (y)
00132 #define SET_PERM_INDEX(x,n,y) *(((x)->perm_index) + (n)) = (y)
00133 #define SET_DIRECTION(x,n,y) *(((x)->directions) + (n)) = (y)
00134 #define SET_NDIM(x,y) (x)->ndim = (y)
00135 #define SET_COPY_FLAG(x,y) (x)->copy_flag = (COPY_FLAG_T) (y)
00136 #define SET_KNOWN_INDEPENDENT(x,y) (x)->known_independent = (y)
00137
00138
00139 #define SET_ITER_COUNT_P(x,y) (x)->iter_count = (y)
00140 #define SET_DIRECTION_P(x,y) (x)->directions = (y)
00141 #define SET_PERM_INDEX_P(x,y) (x)->perm_index = (y)
00142
00143
00144
00145 static WN_MAP f90_lower_map;
00146 #define SET_F90_MAP(x,t) WN_MAP_Set(f90_lower_map,(x),(void *) (t))
00147 #define GET_F90_MAP(x) ((F90_LOWER_AUX_DATA *) WN_MAP_Get(f90_lower_map,(x)))
00148
00149
00150 static OPCODE OPCmpy,OPCadd,OPCsub,OPCarrsection,OPCtriplet,OPCint,OPCmod;
00151 static INT INTRNalloca,INTRNfree,INTRNmalloc,INTRNgetstack,INTRNsetstack;
00152 static TYPE_ID doloop_ty;
00153 static INT num_temps = 0;
00154 static BOOL pointer8 = 0;
00155 #define SELECT_OP(x,y) (pointer8 ? x : y)
00156 static PREG_NUM pointer_return_reg;
00157 static TY *char_ty;
00158 static SRCPOS current_srcpos;
00159
00160 static BOOL array_statement_seen;
00161 static BOOL temp_allocations_inserted;
00162
00163
00164 static WN * F90_Lower_Walk(WN *expr, PREG_NUM *indices, INT ndim,
00165 WN * block, WN *insert_point);
00166
00167
00168 static WN * F90_Current_Block;
00169 static WN * F90_Current_Loopnest;
00170 static WN * F90_Current_Stmt;
00171
00172
00173 #define ARREXP_SIZES(x) &WN_kid1(x)
00174
00175
00176
00177
00178
00179 static WN * get_assignment_from_stmt(WN *stmt)
00180 {
00181 WN *assignment;
00182 if (WN_opcode(stmt) == OPC_WHERE) {
00183 assignment = WN_first(WN_kid1(stmt));
00184 if (!assignment) assignment = WN_first(WN_kid2(stmt));
00185 } else {
00186 assignment = stmt;
00187 }
00188 return(assignment);
00189 }
00190
00191
00192
00193
00194
00195
00196
00197 static BOOL arrayexp_in_subtree(WN *tree)
00198 {
00199 WN_ITER *tree_iter;
00200 WN *node;
00201 OPERATOR opr;
00202
00203 tree_iter = WN_WALK_TreeIter(tree);
00204 while (tree_iter) {
00205 node = WN_ITER_wn(tree_iter);
00206 opr = WN_operator(node);
00207 if (opr == OPR_ARRAYEXP ||
00208 opr == OPR_ARRSECTION ||
00209 (opr == OPR_INTRINSIC_OP && F90_Is_Transformational(WN_GET_INTRINSIC(node)))) {
00210 WN_WALK_Abort(tree_iter);
00211 return (TRUE);
00212 }
00213 tree_iter = WN_WALK_TreeNext(tree_iter);
00214 }
00215 return (FALSE);
00216 }
00217
00218
00219
00220
00221 static WN *find_arrsection(WN * tree)
00222 {
00223 WN *r;
00224 INT num_kids,i;
00225
00226 switch (WN_operator(tree)) {
00227 case OPR_ARRSECTION:
00228 return (tree);
00229
00230 case OPR_ARRAY:
00231 case OPR_ARRAYEXP:
00232 return (find_arrsection(WN_kid0(tree)));
00233
00234 default:
00235 num_kids = WN_kid_count(tree);
00236 r = NULL;
00237 for (i=0; i < num_kids; i++) {
00238 r = find_arrsection(WN_kid(tree,i));
00239 if (r) break;
00240 }
00241 return (r);
00242 }
00243 }
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253 static INT find_vector_axes(INT * vecaxes, WN *arrsect)
00254 {
00255 INT numaxes,i,num_kids;
00256 OPERATOR opr;
00257
00258 if (WN_operator(arrsect) != OPR_ARRSECTION) return (0);
00259 num_kids = (WN_kid_count(arrsect)-1)/2;
00260 numaxes = 0;
00261 for (i=0; i < num_kids; i++) {
00262 opr = WN_operator(WN_kid(arrsect,i+1+num_kids));
00263 if (opr == OPR_ARRAYEXP || opr == OPR_TRIPLET) {
00264 vecaxes[numaxes] = i;
00265 ++numaxes;
00266 }
00267 }
00268 return (numaxes);
00269 }
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 static WN *insert_handle;
00290
00291
00292 static BOOL do_prewalk(WN * tree, WN * block, BOOL prewalk(WN * node, WN *block1))
00293 {
00294 BOOL keep_going;
00295 WN *new_tree;
00296 WN *old_prev;
00297
00298
00299
00300
00301 current_srcpos = WN_Get_Linenum(tree);
00302 if (current_srcpos) {
00303 old_prev = WN_prev(tree);
00304 WN_prev(insert_handle) = old_prev;
00305 WN_next(insert_handle) = tree;
00306 if (old_prev) WN_next(old_prev) = insert_handle;
00307 WN_prev(tree) = insert_handle;
00308 if (block) {
00309 if (WN_first(block) == tree) WN_first(block) = insert_handle;
00310 }
00311
00312 keep_going = prewalk(tree,block);
00313
00314 new_tree = WN_next(insert_handle);
00315 WN_Set_Linenum(new_tree,current_srcpos);
00316 old_prev = WN_prev(insert_handle);
00317 WN_prev(new_tree) = old_prev;
00318 if (old_prev) WN_next(old_prev) = new_tree;
00319 if (block) {
00320 if (WN_first(block) == insert_handle) WN_first(block) = new_tree;
00321 }
00322 } else {
00323 keep_going = prewalk(tree,block);
00324 }
00325 return (keep_going);
00326 }
00327
00328
00329 static BOOL F90_Walk_Statements_Helper(WN * tree, WN * block,
00330 BOOL prewalk(WN * node, WN *block),
00331 BOOL walk_scf)
00332 {
00333 OPCODE op;
00334 WN *callblock;
00335 WN *node,*nextnode;
00336 BOOL keep_going = TRUE;
00337 INT i,numkids;
00338
00339 op = WN_opcode(tree);
00340 if (op == OPC_BLOCK) {
00341 callblock = tree;
00342 node = WN_first(tree);
00343 while (node && keep_going) {
00344 nextnode = WN_next(node);
00345 keep_going = F90_Walk_Statements_Helper(node, callblock, prewalk, walk_scf);
00346 node = nextnode;
00347 }
00348 } else if (OPCODE_is_scf(op) && op != OPC_WHERE) {
00349 if (walk_scf) {
00350 keep_going = do_prewalk(tree,block,prewalk);
00351 if (!keep_going) return (keep_going);
00352 }
00353 numkids = WN_kid_count(tree);
00354 for (i=0; i < numkids; i++) {
00355 keep_going = F90_Walk_Statements_Helper(WN_kid(tree,i), block, prewalk, walk_scf);
00356 if (!keep_going) break;
00357 }
00358 } else if (OPCODE_is_stmt(op) || op == OPC_WHERE) {
00359 keep_going = do_prewalk(tree,block,prewalk);
00360 }
00361 return (keep_going);
00362 }
00363
00364 static void F90_Walk_Statements(WN * tree, BOOL prewalk(WN * node, WN *block))
00365 {
00366
00367 insert_handle = WN_Create(OPC_COMMENT,0);
00368 (void) F90_Walk_Statements_Helper(tree, NULL, prewalk,FALSE);
00369 WN_Delete(insert_handle);
00370 }
00371
00372 static void F90_Walk_All_Statements(WN * tree, BOOL prewalk(WN * node, WN *block))
00373 {
00374
00375 insert_handle = WN_Create(OPC_COMMENT,0);
00376 (void) F90_Walk_Statements_Helper(tree, NULL, prewalk,TRUE);
00377 WN_Delete(insert_handle);
00378 }
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389 static MEM_POOL f90_lower_pool_s;
00390 static MEM_POOL *f90_lower_pool=NULL;
00391
00392
00393
00394
00395
00396
00397 static INT num_alloca;
00398 static INT max_num_alloca;
00399
00400 typedef struct {
00401 WN_OFFSET offset;
00402 ST *alloc_st;
00403 PREG_NUM saved_sp;
00404 } alloc_correspond_s;
00405
00406
00407 static alloc_correspond_s *alloc_correspond;
00408
00409
00410
00411
00412
00413 static void F90_Lower_Init(void) {
00414 TYPE_ID mtype1;
00415 TYPE_ID mtype2;
00416 PREG_NUM rreg2;
00417
00418
00419 if (! f90_lower_pool) {
00420 f90_lower_pool = &f90_lower_pool_s;
00421 MEM_POOL_Initialize(f90_lower_pool,"f90_lower_pool",TRUE);
00422 }
00423 MEM_POOL_Push(f90_lower_pool);
00424
00425
00426 f90_lower_map = WN_MAP_Create(f90_lower_pool);
00427
00428
00429 Get_Return_Mtypes(Be_Type_Tbl(Pointer_type), Use_Simulated, &mtype1, &mtype2);
00430 Get_Return_Pregs(mtype1, mtype2, &pointer_return_reg, &rreg2);
00431
00432 num_alloca = 0;
00433 max_num_alloca = 0;
00434
00435
00436 pointer8 = Pointer_Size == 8;
00437 if (pointer8) {
00438 OPCmpy = OPC_I8MPY;
00439 OPCadd = OPC_I8ADD;
00440 OPCsub = OPC_I8SUB;
00441 OPCmod = OPC_I8MOD;
00442 OPCint = OPC_I8INTCONST;
00443 OPCtriplet = OPC_I8TRIPLET;
00444 OPCarrsection = OPC_U8ARRSECTION;
00445 INTRNalloca = INTRN_U8I8ALLOCA;
00446 INTRNfree = INTRN_U8FREE;
00447 INTRNmalloc = INTRN_U8I8MALLOC;
00448 INTRNgetstack = INTRN_U8READSTACKPOINTER;
00449 INTRNsetstack = INTRN_U8I8SETSTACKPOINTER;
00450 doloop_ty = MTYPE_I8;
00451 } else {
00452 OPCmpy = OPC_I4MPY;
00453 OPCadd = OPC_I4ADD;
00454 OPCsub = OPC_I4SUB;
00455 OPCmod = OPC_I4MOD;
00456 OPCint = OPC_I4INTCONST;
00457 OPCtriplet = OPC_I4TRIPLET;
00458 OPCarrsection = OPC_U4ARRSECTION;
00459 INTRNalloca = INTRN_U4I4ALLOCA;
00460 INTRNfree = INTRN_U4FREE;
00461 INTRNmalloc = INTRN_U4I4MALLOC;
00462 INTRNgetstack = INTRN_U4READSTACKPOINTER;
00463 INTRNsetstack = INTRN_U4I4SETSTACKPOINTER;
00464 doloop_ty = MTYPE_I4;
00465 }
00466 char_ty = NULL;
00467 temp_allocations_inserted = FALSE;
00468 array_statement_seen = FALSE;
00469 }
00470
00471
00472
00473
00474 static void F90_Lower_Term(void) {
00475
00476 WN_MAP_Delete(f90_lower_map);
00477
00478 MEM_POOL_Pop(f90_lower_pool);
00479 }
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493 static void add_alloca_correspondence(ST *alloca_data, WN_OFFSET offset, PREG_NUM alloca_save_sp)
00494 {
00495 #define ALLOCA_CHUNK_SIZE 64
00496 num_alloca += 1;
00497 if (num_alloca > max_num_alloca) {
00498
00499 if (max_num_alloca == 0) {
00500 alloc_correspond = TYPE_MEM_POOL_ALLOC_N(alloc_correspond_s,f90_lower_pool,ALLOCA_CHUNK_SIZE);
00501 } else {
00502 alloc_correspond = TYPE_MEM_POOL_REALLOC_N(alloc_correspond_s,
00503 f90_lower_pool,alloc_correspond,
00504 max_num_alloca,
00505 max_num_alloca + ALLOCA_CHUNK_SIZE);
00506 }
00507 max_num_alloca += ALLOCA_CHUNK_SIZE;
00508 }
00509 alloc_correspond[num_alloca-1].offset = offset;
00510 alloc_correspond[num_alloca-1].alloc_st = alloca_data;
00511 alloc_correspond[num_alloca-1].saved_sp = alloca_save_sp;
00512 }
00513
00514 static PREG_NUM get_corresponding_sp(ST * alloca_data, WN_OFFSET offset)
00515 {
00516 INT i;
00517 for (i=0; i < num_alloca; i++) {
00518 if (alloc_correspond[i].offset == offset &&
00519 alloc_correspond[i].alloc_st == alloca_data) {
00520 return (alloc_correspond[i].saved_sp);
00521 }
00522 }
00523 DevAssert(0,("Couldn't find sp corresponding to ST/offset 0x%x %d",alloca_data,offset));
00524 return (0);
00525 }
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536 static F90_LOWER_AUX_DATA * F90_Lower_New_Aux_Data(INT ndim)
00537 {
00538 F90_LOWER_AUX_DATA *r;
00539 WN **iter_count;
00540 mINT16 *perm_index;
00541 DIR_FLAG *directions;
00542 INT i;
00543
00544
00545 r = TYPE_MEM_POOL_ALLOC( F90_LOWER_AUX_DATA,f90_lower_pool);
00546 SET_NDIM(r,ndim);
00547 SET_KNOWN_INDEPENDENT(r,FALSE);
00548 SET_COPY_FLAG(r,COPY_NONE);
00549
00550
00551 if (ndim > 0) {
00552 iter_count = TYPE_MEM_POOL_ALLOC_N(WN *,f90_lower_pool,ndim);
00553 perm_index = TYPE_MEM_POOL_ALLOC_N(mINT16,f90_lower_pool,ndim);
00554 directions = TYPE_MEM_POOL_ALLOC_N(DIR_FLAG,f90_lower_pool,ndim);
00555
00556 SET_ITER_COUNT_P(r,iter_count);
00557 SET_PERM_INDEX_P(r,perm_index);
00558 SET_DIRECTION_P(r,directions);
00559 }
00560
00561
00562
00563 SET_PRELIST(r,WN_CreateBlock());
00564 SET_POSTLIST(r,WN_CreateBlock());
00565 SET_ALLOC_PRELIST(r,WN_CreateBlock());
00566 SET_DEALLOC_POSTLIST(r,WN_CreateBlock());
00567
00568
00569 for (i=0; i < ndim; i++) {
00570 SET_PERM_INDEX(r,i,i);
00571 SET_DIRECTION(r,i,DIR_DONTCARE);
00572 }
00573 return (r);
00574 }
00575
00576
00577
00578 static F90_LOWER_AUX_DATA * F90_Lower_Copy_Aux_Data(F90_LOWER_AUX_DATA * adata)
00579 {
00580 F90_LOWER_AUX_DATA * r;
00581 INT ndim;
00582 INT i;
00583 ndim = NDIM(adata);
00584
00585 r = F90_Lower_New_Aux_Data(ndim);
00586 for (i=0; i < ndim; i++) {
00587 SET_PERM_INDEX(r,i,PERM_INDEX(adata,i));
00588 SET_ITER_COUNT(r,i,WN_COPY_Tree(ITER_COUNT(adata,i)));
00589 SET_DIRECTION(r,i,DIRECTION(adata,i));
00590 }
00591
00592 return (r);
00593 }
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605 static char * create_tempname(char * name)
00606 {
00607 static char buf[64];
00608 num_temps += 1;
00609 sprintf(buf,"%s_%d",name,num_temps);
00610 return(buf);
00611 }
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635 static ST * F90_Lower_Create_Temp(WN **alloc_block, WN **free_block, WN **size,
00636 INT ndim, TY *ty,
00637 WN *element_size)
00638 {
00639 INT i;
00640 WN *total_size,*save_temp;
00641 ST *st;
00642 TY *pty;
00643 OPCODE callop;
00644 WN *call;
00645 BOOL allocate_on_stack = TRUE;
00646 INTRINSIC aintrin,fintrin;
00647
00648
00649 st = New_ST(FALSE);
00650 ST_name(st) = Save_Str(create_tempname("@f90"));
00651 ST_class(st) = CLASS_VAR;
00652 Set_ST_sclass(st, SCLASS_AUTO);
00653
00654 if (ndim > 0) {
00655 pty = Make_Pointer_Type(ty,FALSE);
00656 ST_type(st) = pty;
00657 Set_ST_pt_to_unique_mem(st);
00658 Set_ST_is_not_aliased(st);
00659 } else {
00660 ST_type(st) = ty;
00661 }
00662 Enter_ST(st);
00663 if (ndim == 0) {
00664 return (st);
00665 }
00666
00667
00668 if (!*alloc_block) *alloc_block = WN_CreateBlock();
00669 if (!*free_block) *free_block = WN_CreateBlock();
00670
00671
00672 if (element_size) {
00673 total_size = WN_COPY_Tree(element_size);
00674 } else {
00675 if (TY_size(ty) != 0) {
00676 total_size = WN_CreateIntconst(OPCint,TY_size(ty));
00677 } else {
00678 total_size = WN_COPY_Tree(TY_AR_ubnd_tree(ty,0));
00679 }
00680 }
00681 for (i=0; i < ndim; i++) {
00682 total_size = WN_CreateExp2(OPCmpy,total_size,WN_COPY_Tree(size[i]));
00683 }
00684
00685 if (allocate_on_stack) {
00686 aintrin = INTRN_F90_STACKTEMPALLOC;
00687 fintrin = INTRN_F90_STACKTEMPFREE;
00688 } else {
00689 aintrin = INTRN_F90_HEAPTEMPALLOC;
00690 fintrin = INTRN_F90_HEAPTEMPFREE;
00691 }
00692
00693
00694 callop = OPCODE_make_op(OPR_INTRINSIC_OP, Pointer_type, MTYPE_V);
00695 call = WN_CreateParm(Pointer_type, total_size, Be_Type_Tbl(Pointer_type),
00696 WN_PARM_BY_VALUE);
00697 call = WN_Create_Intrinsic(callop,aintrin,1,&call);
00698 save_temp = WN_Stid(Pointer_type,(WN_OFFSET) 0,st,pty,call);
00699 WN_INSERT_BlockLast(*alloc_block,save_temp);
00700
00701
00702 callop = OPCODE_make_op(OPR_INTRINSIC_CALL, Pointer_type, MTYPE_V);
00703 call = WN_Ldid(Pointer_type,(WN_OFFSET) 0, st, pty);
00704 call = WN_CreateParm(Pointer_type,call,pty,WN_PARM_BY_VALUE);
00705 call = WN_Create_Intrinsic(callop,fintrin,1,&call);
00706 WN_INSERT_BlockFirst(*free_block,call);
00707
00708
00709 return (st);
00710 }
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722 static BOOL F90_Lower_Alloc_Dealloc(WN *stmt, WN *block)
00723 {
00724 static OPCODE callop=OPCODE_UNKNOWN;
00725 OPERATOR opr;
00726 WN *k0,*k0k0;
00727 WN *call;
00728 WN * save_sp;
00729 PREG_NUM free_preg,sp_tmp;
00730 INTRINSIC intr;
00731
00732 if (callop==OPCODE_UNKNOWN) callop = OPCODE_make_op(OPR_INTRINSIC_CALL, Pointer_type, MTYPE_V);
00733
00734 opr = WN_operator(stmt);
00735
00736 if (opr == OPR_INTRINSIC_CALL) {
00737 intr = WN_GET_INTRINSIC(stmt);
00738 if (intr == INTRN_F90_HEAPTEMPFREE) {
00739 WN_intrinsic(stmt) = INTRNfree;
00740 } else if (intr == INTRN_F90_STACKTEMPFREE) {
00741
00742 WN_intrinsic(stmt) = INTRNsetstack;
00743 k0 = WN_kid0(WN_kid0(stmt));
00744
00745 DevAssert((WN_operator(k0)==OPR_LDID),("Lower_Alloc_Dealloc saw something bad"));
00746 free_preg = get_corresponding_sp(WN_st(k0),WN_offset(k0));
00747 WN_DELETE_Tree(k0);
00748 k0 = WN_LdidPreg(Pointer_type,free_preg);
00749 WN_kid0(WN_kid0(stmt)) = k0;
00750 }
00751 } else if (opr == OPR_STID) {
00752 k0 = WN_kid0(stmt);
00753 if (WN_operator(k0) == OPR_INTRINSIC_OP) {
00754 if (WN_GET_INTRINSIC(k0) == INTRN_F90_HEAPTEMPALLOC) {
00755
00756 k0k0 = WN_kid0(k0);
00757 call = WN_Create_Intrinsic(callop, INTRNmalloc, 1, &k0k0);
00758 WN_INSERT_BlockBefore(block,stmt,call);
00759 WN_Delete(k0);
00760 WN_kid0(stmt) = WN_LdidPreg(Pointer_type,pointer_return_reg);
00761 } else if (WN_GET_INTRINSIC(k0) == INTRN_F90_STACKTEMPALLOC) {
00762 Set_SYMTAB_has_alloca(Current_Symtab);
00763
00764 sp_tmp = Create_Preg(Pointer_type,create_tempname("@f90sp"),NULL);
00765 call = WN_Create_Intrinsic(callop,INTRNgetstack,0,NULL);
00766 WN_INSERT_BlockBefore(block,stmt,call);
00767
00768 save_sp = WN_LdidPreg(Pointer_type,pointer_return_reg);
00769 save_sp = WN_StidIntoPreg(Pointer_type,sp_tmp,MTYPE_To_PREG(Pointer_type), save_sp);
00770 WN_INSERT_BlockBefore(block,stmt,save_sp);
00771
00772 k0k0 = WN_kid0(k0);
00773 call = WN_Create_Intrinsic(callop,INTRNalloca,1,&k0k0);
00774 WN_INSERT_BlockBefore(block,stmt,call);
00775 WN_Delete(k0);
00776 WN_kid0(stmt) = WN_LdidPreg(Pointer_type,pointer_return_reg);
00777
00778
00779 add_alloca_correspondence(WN_st(stmt),WN_offset(stmt), sp_tmp);
00780 }
00781 }
00782 }
00783
00784 return (TRUE);
00785 }
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804 static WN * F90_Lower_Copy_To_ATemp(WN **alloc_block, WN **free_block, WN **copy_store,
00805 WN *expr, WN **size, INT ndim)
00806 {
00807 ST *temp_st;
00808 TY *temp_ty,*ptr_ty;
00809 WN_ESIZE element_size;
00810 WN *arrsection;
00811 WN *arrexp;
00812 WN *store;
00813 WN *load;
00814 WN *arg;
00815 WN *kid0;
00816 WN *stride;
00817 WN *mload_size;
00818 INT i;
00819 OPCODE expr_op;
00820 BOOL is_mexpr;
00821 BOOL is_char;
00822 BOOL multiply_indices=FALSE;
00823 WN *sizemult;
00824
00825
00826 is_mexpr = FALSE;
00827 is_char = FALSE;
00828 mload_size = NULL;
00829
00830 expr_op = WN_opcode(expr);
00831 if (OPCODE_operator(expr_op) == OPR_ARRAYEXP) {
00832
00833 kid0 = WN_kid0(expr);
00834 WN_kid0(expr) = WN_Zerocon(MTYPE_I4);
00835 WN_DELETE_Tree(expr);
00836 return F90_Lower_Copy_To_ATemp(alloc_block,free_block,copy_store,kid0,size,ndim);
00837 }
00838
00839 if (expr_op == OPC_MLOAD) {
00840 is_mexpr = TRUE;
00841 mload_size = WN_kid1(expr);
00842 ptr_ty = WN_ty(expr);
00843 temp_ty = TY_pointed(ptr_ty);
00844 if (TY_kind(temp_ty) == KIND_ARRAY) {
00845 temp_ty = TY_AR_etype(temp_ty);
00846 }
00847 is_char = TY_is_character(temp_ty);
00848 if (is_char) {
00849
00850 temp_ty = TY_pointed(ptr_ty);
00851 }
00852 if (WN_operator(mload_size)==OPR_INTCONST) {
00853 element_size = WN_const_val(mload_size);
00854 } else {
00855 element_size = -1;
00856 multiply_indices = TRUE;
00857 }
00858 } else if (expr_op == OPC_MINTRINSIC_OP ||
00859 (OPCODE_operator(expr_op) == OPR_INTRINSIC_OP &&
00860 F90_Is_Transformational(WN_GET_INTRINSIC(expr)) &&
00861 WN_opcode(WN_kid0(expr)) == OPC_MPARM)) {
00862 is_mexpr = TRUE;
00863
00864 arg = WN_kid0(expr);
00865 temp_ty = WN_ty(arg);
00866
00867
00868
00869 temp_ty = TY_AR_etype(temp_ty);
00870 is_char = TY_is_character(temp_ty);
00871
00872 ptr_ty = Make_Pointer_Type(temp_ty,FALSE);
00873 element_size = TY_size(temp_ty);
00874 if (element_size == 0) {
00875 element_size = -1;
00876 multiply_indices = TRUE;
00877 mload_size = WN_COPY_Tree(TY_AR_ubnd_tree(temp_ty,0));
00878 } else {
00879 mload_size = WN_CreateIntconst(OPCint,element_size);
00880 }
00881 } else {
00882 temp_ty = Be_Type_Tbl(OPCODE_rtype(expr_op));
00883 element_size = TY_size(temp_ty);
00884 ptr_ty = Make_Pointer_Type(temp_ty,FALSE);
00885 }
00886
00887 temp_st = F90_Lower_Create_Temp(alloc_block,free_block,size,ndim,temp_ty,mload_size);
00888
00889
00890 arrsection = WN_Create(OPCarrsection,2*ndim+1);
00891
00892 if (TY_is_f90_pointer(ptr_ty)) {
00893 temp_ty = TY_pointed(ptr_ty);
00894 ptr_ty = Make_Pointer_Type(temp_ty,TY_is_global(temp_ty));
00895 }
00896 WN_kid0(arrsection) = WN_Ldid(Pointer_type, (WN_OFFSET) 0, temp_st, ptr_ty);
00897 WN_element_size(arrsection) = element_size;
00898 if (multiply_indices) {
00899 sizemult = WN_COPY_Tree(mload_size);
00900 }
00901 for (i=0; i < ndim; i++) {
00902
00903 if (multiply_indices) {
00904 WN_kid(arrsection,i+1) = WN_COPY_Tree(sizemult);
00905 sizemult = WN_CreateExp2(OPCmpy,sizemult,WN_COPY_Tree(size[i]));
00906 } else {
00907 WN_kid(arrsection,i+1) = WN_COPY_Tree(size[i]);
00908 }
00909
00910 stride = WN_CreateIntconst(OPCint,(INT64) 1);
00911 WN_kid(arrsection,i+1+ndim) = WN_CreateExp3(OPCtriplet,
00912 WN_CreateIntconst(OPCint,(INT64) 0),
00913 stride,
00914 WN_COPY_Tree(size[i]));
00915 }
00916 if (multiply_indices) {
00917 WN_DELETE_Tree(sizemult);
00918 }
00919
00920 arrexp = F90_Wrap_ARREXP(arrsection);
00921 if (is_mexpr) {
00922 store = WN_CreateMstore((WN_OFFSET) 0, ptr_ty, expr, arrexp, WN_COPY_Tree(mload_size));
00923 load = WN_CreateMload((WN_OFFSET) 0, ptr_ty,
00924 WN_COPY_Tree(arrsection),WN_COPY_Tree(mload_size));
00925 } else {
00926 TYPE_ID type = OPCODE_rtype(expr_op);
00927
00928 store = WN_Istore(type,(WN_OFFSET) 0, ptr_ty, arrexp, expr);
00929 load = WN_RIload(type,type,(WN_OFFSET) 0, ptr_ty, WN_COPY_Tree(arrsection));
00930 }
00931
00932 *copy_store = store;
00933 temp_allocations_inserted = TRUE;
00934 return (load);
00935 }
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948 static WN * F90_Lower_Copy_To_STemp(WN **copy_store,WN *expr)
00949 {
00950 ST *temp_st;
00951 TY *temp_ty,*ptr_ty;
00952 WN *lda;
00953 WN *load;
00954 OPCODE expr_op;
00955 TYPE_ID type;
00956 PREG_NUM p;
00957
00958
00959 expr_op = WN_opcode(expr);
00960 if (expr_op == OPC_MLOAD) {
00961 ptr_ty = WN_ty(expr);
00962
00963 temp_ty = TY_pointed(ptr_ty);
00964
00965 ptr_ty = Make_Pointer_Type(temp_ty,TY_is_global(temp_ty));
00966 temp_st = F90_Lower_Create_Temp(NULL,NULL,NULL,0,temp_ty,NULL);
00967 Set_ST_addr_used_locally(temp_st);
00968 lda = WN_Lda(Pointer_type,(WN_OFFSET) 0, temp_st);
00969 *copy_store = WN_CreateMstore((WN_OFFSET) 0, ptr_ty, expr, lda, WN_COPY_Tree(WN_kid1(expr)));
00970 load = WN_CreateMload((WN_OFFSET) 0, ptr_ty, WN_COPY_Tree(lda),WN_COPY_Tree(WN_kid1(expr)));
00971 } else {
00972 type = OPCODE_rtype(expr_op);
00973 p = Create_Preg(type,create_tempname("@f90s"),NULL);
00974 *copy_store = WN_StidPreg(type,p,expr);
00975 load = WN_LdidPreg(type,p);
00976 }
00977
00978 return (load);
00979 }
00980
00981
00982
00983
00984
00985
00986
00987
00988 BOOL F90_Insert_All_Prelists(WN *stmt, WN *i_block)
00989 {
00990 WN *block;
00991 F90_LOWER_AUX_DATA *adata;
00992
00993 adata = GET_F90_MAP(stmt);
00994 if (adata) {
00995 block = PRELIST(adata);
00996 if (block) {
00997 WN_INSERT_BlockBefore(i_block,stmt,block);
00998 SET_PRELIST(adata,NULL);
00999 }
01000 block = POSTLIST(adata);
01001 if (block) {
01002 WN_INSERT_BlockAfter(i_block,stmt,block);
01003 SET_POSTLIST(adata,NULL);
01004 }
01005 }
01006 return(TRUE);
01007 }
01008
01009
01010
01011
01012
01013
01014
01015 static BOOL F90_Insert_Temp_Allocations(WN *stmt, WN *i_block)
01016 {
01017 WN *block;
01018 F90_LOWER_AUX_DATA *adata;
01019
01020 adata = GET_F90_MAP(stmt);
01021 if (adata) {
01022 block = ALLOC_PRELIST(adata);
01023 if (block) {
01024 WN_INSERT_BlockBefore(i_block,stmt,block);
01025 SET_ALLOC_PRELIST(adata,NULL);
01026 }
01027 block = DEALLOC_POSTLIST(adata);
01028 if (block) {
01029 WN_INSERT_BlockAfter(i_block,stmt,block);
01030 SET_DEALLOC_POSTLIST(adata,NULL);
01031 }
01032 }
01033 return (TRUE);
01034 }
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044 static void convert_to_reference(WN *wn,WN *block, WN *insert_point)
01045 {
01046 ST *st;
01047 TY *ptr_ty;
01048 TY *ty;
01049 WN *lda;
01050 WN *store;
01051 WN *val;
01052
01053
01054 if ((WN_flag(wn) & WN_PARM_BY_REFERENCE) != 0) return;
01055
01056
01057 ty = WN_ty(wn);
01058 WN_set_flag(wn, WN_PARM_BY_REFERENCE);
01059 WN_set_opcode(wn,OPCODE_make_op(OPR_PARM,Pointer_Mtype,MTYPE_V));
01060
01061 st = New_ST(FALSE);
01062 ST_name(st) = Save_Str(create_tempname("@f90_reftemp"));
01063 ST_class(st) = CLASS_VAR;
01064 Set_ST_sclass(st, SCLASS_AUTO);
01065 ST_type(st) = ty;
01066 Set_ST_addr_taken_passed(st);
01067 Set_ST_addr_used_locally(st);
01068 Enter_ST(st);
01069
01070 ptr_ty = Make_Pointer_Type(ty, TY_is_global(ty));
01071 WN_set_ty(wn,ptr_ty);
01072 lda = WN_CreateLda(OPCODE_make_op(OPR_LDA,Pointer_Mtype,MTYPE_V),0,ptr_ty,st);
01073 val = WN_kid0(wn);
01074 WN_kid0(wn) = lda;
01075 store = WN_Stid(TY_btype(ty),(WN_OFFSET) 0,st,ty,val);
01076
01077 WN_INSERT_BlockBefore(block,insert_point,store);
01078 }
01079
01080
01081 static WN * lower_random_number(WN *rcall, WN *block, WN *insert_point)
01082 {
01083 WN *wn;
01084 TYPE_ID rt;
01085 INTRINSIC intr;
01086 PREG_NUM rreg1,rreg2,rpreg;
01087
01088 intr = WN_GET_INTRINSIC(rcall);
01089 if (intr == INTRN_F8I4RAN) {
01090 rt = MTYPE_F8;
01091 } else {
01092 rt = MTYPE_F4;
01093 }
01094
01095 Get_Return_Pregs(rt,MTYPE_V, &rreg1, &rreg2);
01096
01097 WN_DELETE_Tree(rcall);
01098 rcall = WN_Create_Intrinsic(OPCODE_make_op(OPR_INTRINSIC_CALL,rt,MTYPE_V),intr,0,NULL);
01099 WN_INSERT_BlockBefore(block, insert_point, rcall);
01100 rpreg = Create_Preg(rt,create_tempname("@f90ran"),NULL);
01101 wn = WN_StidPreg(rt,rpreg,WN_LdidPreg(rt,rreg1));
01102 WN_INSERT_BlockBefore(block, insert_point, wn);
01103 wn = WN_LdidPreg(rt,rpreg);
01104 return (wn);
01105 }
01106
01107
01108
01109 static WN * lower_char (WN *ival,WN *block, WN *insert_point)
01110 {
01111 ST *st;
01112 TY *ptr_ty;
01113 WN *lda;
01114 WN *istore;
01115
01116
01117 if (!char_ty) {
01118 char_ty = New_TY (FALSE) ;
01119
01120 TY_size(char_ty) = 1 ;
01121 TY_align(char_ty) = 1 ;
01122 TY_btype(char_ty) = MTYPE_I1;
01123 TY_kind(char_ty) = KIND_SCALAR;
01124 TY_name(char_ty) = Save_Str(".character.");
01125
01126 Set_TY_is_character(char_ty);
01127 Enter_TY (char_ty);
01128 }
01129 st = New_ST(FALSE);
01130 ST_name(st) = Save_Str("@f90_chartemp");
01131 ST_class(st) = CLASS_VAR;
01132 Set_ST_sclass(st, SCLASS_AUTO);
01133 ST_type(st) = char_ty;
01134 Set_ST_addr_used_locally(st);
01135 Enter_ST(st);
01136
01137 ptr_ty = Make_Pointer_Type(char_ty, TY_is_global(char_ty));
01138 lda = WN_CreateLda(OPCODE_make_op(OPR_LDA,Pointer_Mtype,MTYPE_V),0,ptr_ty,st);
01139
01140 istore = WN_CreateIstore(OPC_I1ISTORE,0,ptr_ty,WN_kid0(ival),WN_COPY_Tree(lda));
01141 WN_Delete(ival);
01142
01143 WN_INSERT_BlockBefore(block,insert_point,istore);
01144 return (lda);
01145 }
01146
01147
01148
01149 static WN * lower_merge (WN *kids[],WN *block, WN *insert_point)
01150 {
01151 WN *t_case;
01152 WN *f_case;
01153 WN *condition;
01154 TY *ptr_ty;
01155 TY *temp_ty;
01156 ST *temp_st;
01157 WN *lda;
01158 WN *size;
01159 WN *true_block,*false_block;
01160 WN *store;
01161 WN *result;
01162
01163 condition = WN_kid0(kids[0]);
01164 t_case = WN_kid0(kids[1]);
01165 f_case = WN_kid0(kids[2]);
01166 WN_Delete(kids[0]);
01167 WN_Delete(kids[1]);
01168 WN_Delete(kids[2]);
01169
01170
01171 FmtAssert((WN_opcode(t_case) == OPC_MLOAD),("Expected an MLOAD node"));
01172 FmtAssert((WN_opcode(f_case) == OPC_MLOAD),("Expected an MLOAD node"));
01173
01174 ptr_ty = WN_ty(t_case);
01175
01176 temp_ty = TY_pointed(ptr_ty);
01177 temp_st = F90_Lower_Create_Temp(NULL,NULL,NULL,0,temp_ty,NULL);
01178 Set_ST_addr_used_locally(temp_st);
01179 lda = WN_Lda(Pointer_type,(WN_OFFSET) 0, temp_st);
01180 size = WN_kid1(t_case);
01181
01182 true_block = WN_CreateBlock();
01183 false_block = WN_CreateBlock();
01184
01185 store = WN_CreateMstore((WN_OFFSET) 0, ptr_ty, t_case, WN_COPY_Tree(lda), WN_COPY_Tree(size));
01186 WN_INSERT_BlockFirst(true_block,store);
01187
01188 store = WN_CreateMstore((WN_OFFSET) 0, ptr_ty, f_case, WN_COPY_Tree(lda), WN_COPY_Tree(size));
01189 WN_INSERT_BlockFirst(false_block,store);
01190
01191
01192 store = WN_CreateIf(condition,true_block,false_block);
01193 WN_INSERT_BlockBefore(block,insert_point,store);
01194
01195 if (TY_is_character(temp_ty)) {
01196 result = lda;
01197 } else {
01198 result = WN_CreateMload((WN_OFFSET) 0, ptr_ty, lda, WN_COPY_Tree(size));
01199 }
01200 return (result);
01201 }
01202
01203 static void F90_Lower_Intrinsic_Fixup_walk(WN *expr, WN *stmt, WN *block)
01204 {
01205 OPERATOR opr;
01206 WN *kid;
01207 WN *newkid;
01208 INT i,j,numkids;
01209 INTRINSIC intr;
01210
01211 opr = WN_operator(expr);
01212
01213 if (opr == OPR_BLOCK) {
01214 kid = WN_first(expr);
01215 while (kid) {
01216 F90_Lower_Intrinsic_Fixup_walk(kid, kid, expr);
01217 kid = WN_next(kid);
01218 }
01219 } else {
01220 numkids = WN_kid_count(expr);
01221 for (i=0; i < numkids; i++) {
01222 kid = WN_kid(expr,i);
01223 F90_Lower_Intrinsic_Fixup_walk(kid, stmt, block);
01224 if (WN_operator(kid) == OPR_INTRINSIC_OP) {
01225 intr = WN_GET_INTRINSIC(kid);
01226 switch (intr) {
01227
01228
01229
01230 case INTRN_CEQEXPR:
01231 case INTRN_CNEEXPR:
01232 case INTRN_CGEEXPR:
01233 case INTRN_CGTEXPR:
01234 case INTRN_CLEEXPR:
01235 case INTRN_CLTEXPR:
01236 break;
01237
01238 case INTRN_F8I4RAN:
01239 case INTRN_F4I4RAN:
01240 newkid = lower_random_number(kid,block,stmt);
01241 WN_kid(expr,i) = newkid;
01242 break;
01243
01244 case INTRN_CHAR:
01245 newkid = lower_char(WN_kid0(kid),block,stmt);
01246 WN_kid(expr,i) = newkid;
01247 WN_Delete(kid);
01248 break;
01249
01250 case INTRN_MERGE:
01251 newkid = lower_merge(&WN_kid0(kid),block,stmt);
01252 WN_kid(expr,i) = newkid;
01253 WN_Delete(kid);
01254 break;
01255
01256 default:
01257 if (!INTR_by_value(intr)) {
01258 for (j=0; j < WN_kid_count(kid); j++) {
01259 convert_to_reference(WN_kid(kid,j),block,stmt);
01260 }
01261 }
01262 break;
01263 }
01264 }
01265 }
01266 }
01267 }
01268
01269 static BOOL F90_Lower_Intrinsic_Fixup(WN *stmt, WN *block)
01270 {
01271 F90_Lower_Intrinsic_Fixup_walk(stmt,stmt,block);
01272 return (TRUE);
01273 }
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290 static WN * F90_Lower_Copy_Expr_to_Temp(WN *expr, WN *stmt, WN *block)
01291 {
01292 INT ndim,i;
01293 WN *sizes[MAX_NDIM];
01294 WN *temp;
01295 WN *copy_store;
01296
01297 F90_LOWER_AUX_DATA *adata,*adatatemp;
01298
01299 adata = GET_F90_MAP(stmt);
01300 if (!adata) {
01301 adata = F90_Lower_New_Aux_Data(0);
01302 SET_F90_MAP(stmt,adata);
01303 }
01304
01305 if (F90_Size_Walk(expr,&ndim,sizes)) {
01306
01307 adatatemp = F90_Lower_New_Aux_Data(ndim);
01308
01309 for (i=0; i <ndim ; i++) {
01310 SET_ITER_COUNT(adatatemp,i,sizes[i]);
01311 }
01312 temp = F90_Lower_Copy_To_ATemp(&ALLOC_PRELIST(adatatemp),&DEALLOC_POSTLIST(adata),
01313 ©_store,expr,sizes,ndim);
01314 SET_F90_MAP(copy_store,adatatemp);
01315 WN_INSERT_BlockFirst(PRELIST(adatatemp),PRELIST(adata));
01316 WN_INSERT_BlockFirst(ALLOC_PRELIST(adatatemp),ALLOC_PRELIST(adata));
01317 SET_PRELIST(adata,WN_CreateBlock());
01318 SET_ALLOC_PRELIST(adata,WN_CreateBlock());
01319 } else {
01320
01321 temp = F90_Lower_Copy_To_STemp(©_store,expr);
01322 }
01323 WN_INSERT_BlockBefore(block,stmt,copy_store);
01324 return (temp);
01325 }
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338 static void F90_Lower_Init_Dep_Info(DEP_INFO *d, INT ndim)
01339 {
01340 INT i;
01341
01342
01343 SET_DEP_NDIM(d,ndim);
01344 SET_DEP_SUMMARY(d,DEP_INDEPENDENT);
01345
01346
01347 for (i=0; i < MAX_NDIM; i++) {
01348 SET_DEP_DIRECTION(d,i,DIR_DONTCARE);
01349 }
01350 return;
01351 }
01352
01353 static void print_dep_info(DEP_INFO *d)
01354 {
01355 static char * summ[4] = {"UNK","IND","===","REM"};
01356 static char * dirr[5] = {"/","+","-","0","?"};
01357 INT i;
01358
01359 fprintf(TFile,"%s ",summ[d->summary]);
01360 if (d->summary == DEP_REMOVABLE) {
01361 fprintf(TFile,":");
01362 for (i=0; i < d->ndim; i++) {
01363 fprintf(TFile," %s",dirr[DEP_DIRECTION(d,i)]);
01364 }
01365 }
01366 fprintf(TFile,"\n");
01367 }
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401 static BOOL F90_Lower_Merge_Dep_Info(DEP_INFO *in1, DEP_INFO *in2)
01402 {
01403
01404 INT ndim1,ndim2;
01405 INT i;
01406 DEP_SUMMARY sum1,sum2;
01407 DIR_FLAG dir1,dir2,dir_merge;
01408 BOOL all_zero;
01409
01410 #define SHOW_DEP_RES if (trace_depinfo) {fprintf(TFile,"M :"); print_dep_info(in1);}
01411
01412 if (trace_depinfo) {
01413 fprintf(TFile,"===============\n1 :");
01414 print_dep_info(in1);
01415 fprintf(TFile,"2 :");
01416 print_dep_info(in2);
01417 }
01418
01419 ndim1 = DEP_NDIM(in1);
01420 ndim2 = DEP_NDIM(in2);
01421 sum1 = DEP_SUMMARY(in1);
01422 sum2 = DEP_SUMMARY(in2);
01423
01424
01425 if ((ndim1 != ndim2) ||
01426 (sum1 == DEP_UNKNOWN) ||
01427 (sum2 == DEP_UNKNOWN)) {
01428 SET_DEP_SUMMARY(in1,DEP_UNKNOWN);
01429 SHOW_DEP_RES;
01430 return (FALSE);
01431 }
01432 if (sum2 == DEP_INDEPENDENT) {
01433 SHOW_DEP_RES;
01434 return (TRUE);
01435 }
01436 if (sum2 == DEP_IDENTICAL) {
01437 if (sum1 == DEP_INDEPENDENT) {
01438 SET_DEP_SUMMARY(in1,DEP_IDENTICAL);
01439 }
01440 SHOW_DEP_RES;
01441 return (TRUE);
01442 }
01443
01444
01445 if (sum1 == DEP_IDENTICAL || sum1 == DEP_INDEPENDENT) {
01446 *in1 = *in2;
01447 SHOW_DEP_RES;
01448 return (TRUE);
01449 }
01450
01451 all_zero = TRUE;
01452 for (i=0; i < ndim1; i++) {
01453 dir1 = DEP_DIRECTION(in1,i);
01454 dir2 = DEP_DIRECTION(in2,i);
01455 if (dir1 == dir2) {
01456 dir_merge = dir1;
01457 } else if (dir1 == DIR_UNKNOWN || dir2 == DIR_UNKNOWN) {
01458 dir_merge = DIR_UNKNOWN;
01459 } else if (dir1 == DIR_ZERO) {
01460 dir_merge = dir2;
01461 } else if (dir2 == DIR_ZERO) {
01462 dir_merge = dir1;
01463 } else if ((dir1 == DIR_POSITIVE && dir2 == DIR_NEGATIVE) ||
01464 (dir2 == DIR_POSITIVE && dir1 == DIR_NEGATIVE)) {
01465 dir_merge = DIR_UNKNOWN;
01466 }
01467 if (dir_merge == DIR_UNKNOWN) {
01468 SET_DEP_SUMMARY(in1,DEP_UNKNOWN);
01469 SHOW_DEP_RES;
01470 return (FALSE);
01471 }
01472 if (dir_merge != DIR_ZERO) all_zero = FALSE;
01473 SET_DEP_DIRECTION(in1,i,dir_merge);
01474 }
01475 if (all_zero) {
01476 SET_DEP_SUMMARY(in1,DEP_IDENTICAL);
01477 }
01478 SHOW_DEP_RES;
01479 return (TRUE);
01480 }
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491 #define F90_FORMAL 1
01492 #define F90_UNALIASED 2
01493 #define F90_BASED 4
01494 #define F90_UNKNOWN 8
01495 #define F90_TARGET 16
01496 #define F90_POINTER 32
01497 #define F90_THROUGH_ARRAY 64
01498 #define F90_THROUGH_EXPR 128
01499 #define F90_EXPR 256
01500 #define F90_ARRSECTION 512
01501 #define F90_INDIRECTION 1024
01502
01503
01504 static void f90_flag_dump(FILE *f, INT flag)
01505 {
01506 fprintf(f,"Flag = 0x%x: ",flag);
01507 if (flag & F90_FORMAL) fprintf(f,"formal,");
01508 if (flag & F90_UNALIASED) fprintf(f,"unaliased,");
01509 if (flag & F90_BASED) fprintf(f,"based,");
01510 if (flag & F90_UNKNOWN) fprintf(f,"unknown,");
01511 if (flag & F90_TARGET) fprintf(f,"target,");
01512 if (flag & F90_POINTER) fprintf(f,"pointer,");
01513 if (flag & F90_THROUGH_ARRAY) fprintf(f,"array,");
01514 if (flag & F90_THROUGH_EXPR) fprintf(f,"texpr,");
01515 if (flag & F90_EXPR) fprintf(f,"expr,");
01516 if (flag & F90_ARRSECTION) fprintf(f,"asect,");
01517 if (flag & F90_INDIRECTION) fprintf(f,"indirect");
01518 fprintf(f,"\n");
01519 }
01520
01521 INT f90_fdump(INT f)
01522 {
01523 f90_flag_dump(stdout,f);
01524 return (0);
01525 }
01526
01527 static char * f90_depsum_name(DEP_SUMMARY d)
01528 {
01529 switch (d) {
01530 case DEP_UNKNOWN: return ("UNKNOWN");
01531 case DEP_INDEPENDENT: return ("INDEPENDENT");
01532 case DEP_IDENTICAL: return ("IDENTICAL");
01533 case DEP_REMOVABLE: return ("REMOVABLE");
01534 }
01535 return ("error");
01536 }
01537
01538 #define MAX_ADDR_PIECES 128
01539
01540
01541 static WN *lhs_address;
01542 static WN *lhs_arrsection;
01543 static ST *lhs_sym;
01544 static WN *lhs_pieces[MAX_ADDR_PIECES];
01545 static INT lhs_num_pieces;
01546 static INT64 lhs_const_offset,lhs_base_offset,lhs_size;
01547 static INT lhs_flag;
01548 static TY *lhs_ty;
01549
01550
01551 static ST *rhs_sym;
01552 static WN *rhs_pieces[MAX_ADDR_PIECES];
01553 static INT rhs_num_pieces;
01554 static INT64 rhs_const_offset,rhs_base_offset,rhs_size;
01555 static INT rhs_flag;
01556 static TY *rhs_ty;
01557
01558
01559 static BOOL is_f90_pointer(WN *addr)
01560 {
01561 OPERATOR opr;
01562 ST *st;
01563 opr = WN_operator(addr);
01564 if (opr == OPR_LDID || opr == OPR_LDA) {
01565 st = WN_st(addr);
01566 if (ST_class(st) == CLASS_VAR) {
01567 return (ST_is_f90_pointer(st));
01568 } else {
01569 return (FALSE);
01570 }
01571 } else if (opr == OPR_ILOAD) {
01572 return (TY_is_f90_pointer(TY_pointed(WN_load_addr_ty(addr))) ||
01573 TY_is_f90_pointer(WN_load_addr_ty(addr)));
01574 } else {
01575 return (TRUE);
01576 }
01577 }
01578
01579 static BOOL is_f90_target(WN *addr)
01580 {
01581 OPERATOR opr;
01582 ST *st;
01583 opr = WN_operator(addr);
01584 if (opr == OPR_LDID || opr == OPR_LDA) {
01585 st = WN_st(addr);
01586 if (ST_class(st) == CLASS_VAR) {
01587 return (ST_is_f90_target(st));
01588 } else {
01589 return (FALSE);
01590 }
01591 } else {
01592 return (TY_is_f90_pointer(TY_pointed(WN_load_addr_ty(addr))));
01593 }
01594 }
01595
01596 static BOOL is_f90_formal(WN *addr)
01597 {
01598 OPERATOR opr;
01599 WN *kid;
01600 ST *st;
01601 opr = WN_operator(addr);
01602 if (opr == OPR_LDID || opr == OPR_LDA) {
01603 st = WN_st(addr);
01604 return ((ST_sclass(st) == SCLASS_FORMAL) ||
01605 (ST_sclass(st) == SCLASS_FORMAL_REF));
01606 } else if (opr == OPR_ILOAD) {
01607 kid = WN_kid0(addr);
01608 opr = WN_operator(kid);
01609 if (opr == OPR_LDID || opr == OPR_LDA) {
01610 st = WN_st(kid);
01611 return ((ST_sclass(st) == SCLASS_FORMAL) ||
01612 (ST_sclass(st) == SCLASS_FORMAL_REF));
01613 } else {
01614 return (FALSE);
01615 }
01616 }
01617 return (FALSE);
01618 }
01619
01620 #define ADD_PIECE(x) if (*num_pieces < MAX_ADDR_PIECES) { \
01621 pieces[*num_pieces] = (x); \
01622 *num_pieces = *num_pieces + 1; \
01623 } else { \
01624 *sym = NULL; \
01625 *flag = F90_UNKNOWN; \
01626 done = TRUE; \
01627 continue; \
01628 }
01629
01630
01631 static void Analyze_one_address(WN *a, ST **sym, WN **pieces, INT *num_pieces,
01632 INT64 *const_offset, INT64 *base_offset, INT64 *size,
01633 INT *flag, TY **ty)
01634 {
01635 OPERATOR opr,opr1;
01636 ST *s;
01637 TY *t;
01638 WN *addr;
01639 BOOL done;
01640 WN *kid;
01641
01642 *base_offset = 0;
01643 *size = 0;
01644 *sym = NULL;
01645 *num_pieces = 0;
01646 *flag = 0;
01647 *ty = NULL;
01648 addr = a;
01649 done = FALSE;
01650
01651 while (!done) {
01652 opr = WN_operator(addr);
01653 if (opr == OPR_LDID) {
01654 ADD_PIECE(addr);
01655 if (trace_dependence) fprintf(TFile," Analyze_one_address (LDID): ");
01656
01657 s = WN_st(addr);
01658 t = WN_ty(addr);
01659 *const_offset += WN_offset(addr);
01660 *ty = t;
01661 *sym = s;
01662 if (ST_class(s) == CLASS_CONST) {
01663 *flag = F90_UNALIASED;
01664
01665 return;
01666 }
01667 if (ST_sclass(s) == SCLASS_FORMAL || ST_sclass(s) == SCLASS_FORMAL_REF ) {
01668 *flag |= F90_FORMAL | F90_UNALIASED;
01669 } else if (ST_sclass(s) == SCLASS_REG) {
01670 DevWarn(("Should not see in PREG in F90 alias analysis"));
01671 } else {
01672
01673
01674 *flag |= F90_INDIRECTION;
01675 Base_Symbol_And_Offset(s,sym,base_offset);
01676 if (ST_pt_to_unique_mem(s) || ST_is_not_aliased(s)) {
01677 *flag |= F90_UNALIASED;
01678 }
01679 if (ST_is_f90_target(s)) {
01680 *flag |= F90_TARGET;
01681 }
01682 if (ST_is_f90_pointer(s)) {
01683 *flag |= F90_POINTER;
01684 }
01685 }
01686 if (TY_kind(t) != KIND_POINTER) {
01687
01688 *flag |= F90_EXPR;
01689 }
01690 done = TRUE;
01691 } else if (opr == OPR_LDA) {
01692 ADD_PIECE(addr);
01693 if (trace_dependence) fprintf(TFile," Analyze_one_address (LDA): ");
01694
01695 s = WN_st(addr);
01696 t = ST_type(s);
01697 *sym = s;
01698 *ty = t;
01699 *const_offset += WN_offset(addr);
01700 if (ST_class(s) == CLASS_CONST) {
01701 *flag = F90_UNALIASED;
01702
01703 return;
01704 }
01705 if (ST_sclass(s) == SCLASS_BASED) {
01706 Base_Symbol_And_Offset(s,sym,base_offset);
01707 *flag |= F90_BASED;
01708 *size = TY_size(t);
01709 }
01710 if (ST_is_f90_target(s)) {
01711 *flag |= F90_TARGET;
01712 }
01713 if (ST_is_f90_pointer(s)) {
01714 *flag |= F90_POINTER;
01715 }
01716 if (!*flag & (F90_TARGET | F90_POINTER)) {
01717
01718 *flag |= F90_UNALIASED;
01719 }
01720 done = TRUE;
01721 } else if (opr == OPR_ARRAY || opr == OPR_ARRSECTION || opr == OPR_ILOAD) {
01722 if (opr == OPR_ARRSECTION) {
01723 *flag |= F90_ARRSECTION;
01724 } else if (opr == OPR_ILOAD) {
01725 *flag |= F90_INDIRECTION;
01726
01727 *flag |= is_f90_pointer(addr);
01728 }
01729
01730 ADD_PIECE(addr);
01731 addr = WN_kid0(addr);
01732 *flag |= F90_THROUGH_ARRAY;
01733 if (trace_dependence) fprintf(TFile," Analyze_one_address (ARRAY/ARRSECT %d)\n",*num_pieces);
01734 continue;
01735 } else if (opr == OPR_ARRAYEXP) {
01736
01737 addr = WN_kid0(addr);
01738 continue;
01739 } else if (opr == OPR_ADD) {
01740 kid = WN_kid1(addr);
01741 if (WN_operator(kid) == OPR_INTCONST) {
01742 ADD_PIECE(kid);
01743 addr = WN_kid0(addr);
01744 if (trace_dependence) fprintf(TFile," Analyze_one_address (Add %lld)\n",WN_const_val(kid));
01745 continue;
01746 }
01747 kid = WN_kid0(addr);
01748 if (WN_operator(kid) == OPR_INTCONST) {
01749 ADD_PIECE(kid);
01750 addr = WN_kid1(addr);
01751 if (trace_dependence) fprintf(TFile," Analyze_one_address (Add %lld)\n",WN_const_val(kid));
01752 continue;
01753 }
01754
01755
01756
01757 ADD_PIECE(addr);
01758 opr1 = WN_operator(WN_kid0(addr));
01759 if (opr1 == OPR_LDID || opr1 == OPR_LDA ||
01760 opr1 == OPR_ARRAY || opr1 == OPR_ARRSECTION) {
01761 addr = WN_kid0(addr);
01762 *flag |= F90_THROUGH_EXPR;
01763 if (trace_dependence) fprintf(TFile," Analyze_one_address (Add expr %d\n)",*num_pieces );
01764 continue;
01765 }
01766 opr1 = WN_operator(WN_kid1(addr));
01767 if (opr1 == OPR_LDID || opr1 == OPR_LDA ||
01768 opr1 == OPR_ARRAY || opr1 == OPR_ARRSECTION) {
01769 addr = WN_kid1(addr);
01770 *flag |= F90_THROUGH_EXPR;
01771 if (trace_dependence) fprintf(TFile," Analyze_one_address (Add expr %d\n)",*num_pieces );
01772 continue;
01773 }
01774
01775 *flag = F90_UNKNOWN;
01776 *sym = NULL;
01777 done = TRUE;
01778 continue;
01779 } else {
01780
01781 *flag = F90_UNKNOWN;
01782 *sym = NULL;
01783 done = TRUE;
01784 continue;
01785 }
01786 }
01787 if (trace_dependence) {
01788 if (*sym) {
01789 fprintf(TFile,"sym: %s, base_offset %lld, const_offset %lld, size %lld\n",
01790 ST_name(*sym),*base_offset,*const_offset,*size);
01791 f90_flag_dump(TFile,*flag);
01792 } else {
01793 fprintf(TFile,"sym not found\n");
01794 }
01795 }
01796
01797 return;
01798 }
01799
01800
01801 static WN * get_difference(WN *t1, WN *t2)
01802 {
01803 INT ty1,ty2;
01804 OPCODE subop;
01805 ty1 = MTYPE_size_reg(OPCODE_rtype(WN_opcode(t1)));
01806 ty2 = MTYPE_size_reg(OPCODE_rtype(WN_opcode(t2)));
01807 if (ty1 == 32 && ty2 == 32) {
01808 subop = OPC_I4SUB;
01809 } else {
01810 subop = OPC_I8SUB;
01811 }
01812 return (WN_CreateExp2(subop,t1,t2));
01813 }
01814
01815
01816
01817
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830 #define SHOW_REASON(x) if (trace_dependence){fprintf(TFile,"returns %d %s\n",r,x);}
01831
01832 static DIR_FLAG Analyze_index(WN *i1, WN *i2) {
01833 DIR_FLAG r;
01834 OPERATOR opr1,opr2;
01835 WN *lb1, *ex1, *st1, *st2;
01836 WN *temp,*temp1;
01837 INT64 diff;
01838 INT64 s1,s2,e,l;
01839 BOOL e_constant;
01840 BOOL l_constant;
01841 BOOL s_constant;
01842 BOOL one_scalar;
01843
01844 if (trace_dependence) {
01845 fprintf(TFile,"Analyze Index:\n");
01846 fdump_tree(TFile,i1);
01847 fprintf(TFile,"------\n");
01848 fdump_tree(TFile,i2);
01849 }
01850
01851 r = DIR_UNKNOWN;
01852 opr1 = WN_operator(i1);
01853 opr2 = WN_operator(i2);
01854
01855
01856 if (opr1 == OPR_ARRAYEXP || opr2 == OPR_ARRAYEXP) {
01857 SHOW_REASON("not arrayexp");
01858 return(r);
01859 }
01860
01861
01862 temp = get_difference(WN_COPY_Tree(i1),WN_COPY_Tree(i2));
01863 if (is_constant(temp)) {
01864 diff = WN_const_val(temp);
01865 if (diff == 0) {
01866 r = DIR_ZERO;
01867 SHOW_REASON("equality");
01868 } else {
01869 r = DIR_DONTCARE;
01870 SHOW_REASON("scalar !=");
01871 }
01872 }
01873 WN_DELETE_Tree(temp);
01874 if (r != DIR_UNKNOWN) return (r);
01875
01876
01877 if (opr1 != OPR_TRIPLET && opr2 != OPR_TRIPLET) {
01878 SHOW_REASON("no triplets");
01879 return(r);
01880 }
01881
01882 if (opr1 != OPR_TRIPLET) {
01883
01884 lb1 = get_difference(WN_COPY_Tree(i1),WN_COPY_Tree(WN_kid0(i2)));
01885 ex1 = WN_COPY_Tree(WN_kid2(i2));
01886 st1 = WN_COPY_Tree(WN_kid1(i2));
01887 one_scalar = TRUE;
01888 } else if (opr2 != OPR_TRIPLET) {
01889
01890 lb1 = get_difference(WN_COPY_Tree(i2),WN_COPY_Tree(WN_kid0(i1)));
01891 ex1 = WN_COPY_Tree(WN_kid2(i1));
01892 st1 = WN_COPY_Tree(WN_kid1(i1));
01893 one_scalar = TRUE;
01894 } else {
01895
01896 ex1 = WN_COPY_Tree(WN_kid2(i1));
01897 lb1 = get_difference(WN_COPY_Tree(WN_kid0(i1)),WN_COPY_Tree(WN_kid0(i2)));
01898 st1 = WN_COPY_Tree(WN_kid1(i1));
01899 st2 = WN_COPY_Tree(WN_kid1(i2));
01900 one_scalar = FALSE;
01901 }
01902
01903
01904 if (one_scalar) {
01905
01906 temp = WN_CreateExp2(OPC_I8MOD,WN_COPY_Tree(lb1),WN_COPY_Tree(st1));
01907 if (!is_constant(temp)) {
01908 SHOW_REASON("l mod s not const");
01909 r = DIR_UNKNOWN;
01910 WN_DELETE_Tree(temp);
01911 } else {
01912 diff = WN_const_val(temp);
01913 WN_DELETE_Tree(temp);
01914
01915 if (diff != 0) {
01916 r = DIR_DONTCARE;
01917 SHOW_REASON("l mod s != 0");
01918 } else {
01919
01920
01921
01922 lb1 = WN_CreateExp2(OPC_I8DIV,lb1,WN_COPY_Tree(st1));
01923 temp = WN_CreateExp2(OPC_I8LT,WN_COPY_Tree(lb1),WN_Zerocon(MTYPE_I8));
01924 temp1 = WN_CreateExp2(OPC_I8GE,WN_COPY_Tree(lb1),WN_COPY_Tree(ex1));
01925 temp = WN_CreateExp2(OPC_LIOR,temp,temp1);
01926 if (is_constant(temp) && WN_const_val(temp) != 0) {
01927 r = DIR_DONTCARE;
01928 SHOW_REASON("not contained");
01929 } else {
01930 r = DIR_UNKNOWN;
01931 SHOW_REASON("contained");
01932 }
01933 WN_DELETE_Tree(temp);
01934 }
01935 }
01936 WN_DELETE_Tree(lb1);
01937 WN_DELETE_Tree(st1);
01938 WN_DELETE_Tree(ex1);
01939 SHOW_REASON("returning");
01940 return (r);
01941 }
01942
01943
01944
01945 e_constant = is_constant(ex1);
01946 if (e_constant) e = WN_const_val(ex1);
01947 l_constant = is_constant(lb1);
01948 if (l_constant) l = WN_const_val(lb1);
01949 s_constant = is_constant(st1) && is_constant(st2);
01950 if (s_constant) {
01951 s1 = WN_const_val(st1);
01952 s2 = WN_const_val(st2);
01953 }
01954 WN_DELETE_Tree(lb1);
01955 WN_DELETE_Tree(ex1);
01956
01957 if (trace_dependence) {
01958 if (e_constant) fprintf(TFile,"E = %lld\n",e);
01959 if (l_constant) fprintf(TFile,"L = %lld\n",l);
01960 if (s_constant) fprintf(TFile,"S1,S2 = %lld %lld\n",s1,s2);
01961 }
01962
01963
01964
01965
01966 temp = get_difference(st1,st2);
01967 if (is_constant(temp) && WN_const_val(temp) == 0 && l_constant) {
01968
01969 if (s_constant) {
01970 if (l % s1 != 0) {
01971 r = DIR_DONTCARE;
01972 } else if (l < 0 && s1 > 0 || l < 0 && s1 > 0) {
01973 r = DIR_POSITIVE;
01974 } else if (l > 0 && s1 > 0 || l < 0 && s1 < 0) {
01975 r = DIR_NEGATIVE;
01976 } else if (l == 0) {
01977 r = DIR_ZERO;
01978 }
01979 }
01980 }
01981 WN_DELETE_Tree(temp);
01982 if (r != DIR_UNKNOWN) {
01983 SHOW_REASON("triplet case 1");
01984 return (r);
01985 }
01986
01987
01988 if (e_constant && e == 1 && l_constant) {
01989 if (l == 0) {
01990 r = DIR_ZERO;
01991 } else {
01992 r = DIR_DONTCARE;
01993 }
01994 }
01995 if (r != DIR_UNKNOWN) {
01996 SHOW_REASON("triplet case 2");
01997 return (r);
01998 }
01999
02000
02001 if (l_constant && s_constant) {
02002 r = F90_Lower_Analyze_Triplet(l,s1,s2,e,e_constant,f90_lower_pool);
02003 SHOW_REASON("general constant case");
02004 } else {
02005 SHOW_REASON("done");
02006 }
02007 return (r);
02008 }
02009
02010
02011
02012
02013
02014
02015
02016
02017
02018 static DEP_SUMMARY Analyze_all_indices(WN *lhs, WN *rhs, DEP_INFO *kid_dep)
02019 {
02020 BOOL allzero,allzerounknown;
02021 INT lhskids,rhskids;
02022 INT ndim,i;
02023 DIR_FLAG dir;
02024
02025 lhskids = WN_kid_count(lhs);
02026 rhskids = WN_kid_count(rhs);
02027 if ((lhskids != rhskids) || (WN_element_size(lhs) != WN_element_size(rhs))) {
02028 SET_DEP_SUMMARY(kid_dep,DEP_UNKNOWN);
02029 return (DEP_UNKNOWN);
02030 }
02031 ndim = (lhskids - 1) / 2;
02032 SET_DEP_NDIM(kid_dep,ndim);
02033
02034
02035 allzero = TRUE;
02036 allzerounknown = TRUE;
02037 for (i=0; i < ndim; i++) {
02038 dir = Analyze_index(WN_kid(lhs,i+ndim+1),WN_kid(rhs,i+ndim+1));
02039 SET_DEP_DIRECTION(kid_dep,i,dir);
02040 if (dir == DIR_DONTCARE) {
02041 SET_DEP_SUMMARY(kid_dep,DEP_INDEPENDENT);
02042 allzero = FALSE;
02043 allzerounknown = FALSE;
02044 break;
02045 } else if (dir == DIR_UNKNOWN) {
02046 allzero = FALSE;
02047 } else if (dir == DIR_POSITIVE || dir == DIR_NEGATIVE) {
02048 SET_DEP_SUMMARY(kid_dep,DEP_REMOVABLE);
02049 allzero = FALSE;
02050 allzerounknown = FALSE;
02051 }
02052 }
02053 if (allzero) {
02054
02055 SET_DEP_SUMMARY(kid_dep,DEP_IDENTICAL);
02056 } else if (allzerounknown && !allzero) {
02057
02058 SET_DEP_SUMMARY(kid_dep,DEP_UNKNOWN);
02059 }
02060 return (DEP_SUMMARY(kid_dep));
02061 }
02062
02063
02064
02065
02066
02067
02068
02069
02070
02071
02072
02073
02074
02075
02076 static DEP_SUMMARY check_overlap(INT64 base1, INT64 base2, INT64 size1, INT64 size2)
02077 {
02078 INT64 t;
02079 if (base2 == base1 && size2 == size1) return (DEP_IDENTICAL);
02080
02081
02082 if (base1 > base2) {
02083 t = base2;
02084 base2 = base1;
02085 base1 = t;
02086 t = size2;
02087 size2 = size1;
02088 size1 = t;
02089 }
02090 if (base2 < base1 + size1) {
02091 return (DEP_UNKNOWN);
02092 } else {
02093 return (DEP_INDEPENDENT);
02094 }
02095 }
02096
02097
02098
02099
02100
02101
02102
02103 static DEP_SUMMARY analyze_structure_bases(INT lhs_start, INT rhs_start, INT *lhs_end1, INT *rhs_end1)
02104 {
02105 INT64 lc,rc;
02106 INT i,ri,li,lhs_end,rhs_end;
02107 OPERATOR opr;
02108 WN *lhsa,*rhsa;
02109 DEP_SUMMARY t;
02110 DEP_INFO dummy_dep;
02111
02112 lc = lhs_const_offset;
02113 rc = rhs_const_offset;
02114
02115 for (i = lhs_start; i >= 0; i--) {
02116 opr = WN_operator(lhs_pieces[i]);
02117 if (opr == OPR_ILOAD ||
02118 opr == OPR_LDID) {
02119 break;
02120 } else if (opr == OPR_INTCONST) {
02121 lc += WN_const_val(lhs_pieces[i]);
02122 }
02123 }
02124 lhs_end = i;
02125 if (lhs_end1) *lhs_end1 = lhs_end;
02126
02127 for (i = rhs_start; i >= 0; i--) {
02128 opr = WN_operator(rhs_pieces[i]);
02129 if (opr == OPR_ILOAD ||
02130 opr == OPR_LDID) {
02131 break;
02132 } else if (opr == OPR_INTCONST) {
02133 rc += WN_const_val(rhs_pieces[i]);
02134 }
02135 }
02136 rhs_end = i;
02137 if (rhs_end1) *rhs_end1 = rhs_end;
02138
02139
02140
02141
02142
02143
02144 if (lhs_ty == rhs_ty) {
02145 if (lc != rc) return (DEP_INDEPENDENT);
02146 } else {
02147 return (DEP_UNKNOWN);
02148 }
02149
02150
02151 ri = rhs_start;
02152 li = lhs_start;
02153 while (ri > rhs_end && li > lhs_end) {
02154
02155 for (; li > lhs_end ; li--) {
02156 opr = WN_operator(lhs_pieces[li]);
02157 if (opr == OPR_ARRSECTION || opr == OPR_ARRAY) break;
02158 }
02159 for (; ri > rhs_end ; ri--) {
02160 opr = WN_operator(rhs_pieces[ri]);
02161 if (opr == OPR_ARRSECTION || opr == OPR_ARRAY) break;
02162 }
02163
02164 if (li > lhs_end && ri > rhs_end) {
02165 lhsa = lhs_pieces[li];
02166 rhsa = rhs_pieces[ri];
02167
02168 if (WN_operator(lhsa) == OPR_ARRSECTION &&
02169 WN_operator(rhsa) == OPR_ARRSECTION) {
02170 li--;
02171 ri--;
02172 continue;
02173 }
02174
02175
02176
02177 t = Analyze_all_indices(lhsa,rhsa,&dummy_dep);
02178 if (t == DEP_UNKNOWN || t == DEP_INDEPENDENT) {
02179 return (t);
02180 } else if (t == DEP_REMOVABLE) {
02181
02182 return (DEP_UNKNOWN);
02183 }
02184
02185 li--;
02186 ri--;
02187 } else if ((li > lhs_end && ri <= rhs_end) ||
02188 (ri > rhs_end && li <= lhs_end)) {
02189
02190 return (DEP_UNKNOWN);
02191 } else {
02192 li--;
02193 ri--;
02194 }
02195 }
02196
02197
02198 return (DEP_IDENTICAL);
02199 }
02200
02201
02202
02203
02204
02205
02206
02207
02208
02209
02210
02211
02212
02213
02214
02215
02216
02217 static DEP_SUMMARY Analyze_bases(WN * addr, BOOL is_expr)
02218 {
02219 DEP_SUMMARY r;
02220 OPERATOR opr;
02221 INT i;
02222 BOOL same;
02223 INT li,ri;
02224 WN *lhsa,*rhsa;
02225 BOOL l_pointer,l_target,l_formal;
02226 BOOL r_pointer,r_target,r_formal;
02227
02228 r = DEP_UNKNOWN;
02229 if (trace_dependence) fprintf(TFile,"Analyze_bases: ");
02230
02231
02232 if (!is_expr) {
02233 if (WN_Simp_Compare_Trees(lhs_address,addr) == 0) {
02234 if (trace_dependence) fprintf(TFile,"same addresses\n");
02235 return (DEP_IDENTICAL);
02236 }
02237 }
02238
02239 if (trace_dependence) fprintf(TFile,"\n");
02240
02241 if (lhs_sym == NULL || rhs_sym == NULL ||
02242 (F90_UNKNOWN & (lhs_flag | rhs_flag))) {
02243 if (trace_dependence) fprintf(TFile,"unanalyzable symbols\n");
02244 return (DEP_UNKNOWN);
02245 }
02246
02247
02248
02249 if (!((lhs_flag | rhs_flag) & F90_INDIRECTION)) {
02250
02251
02252 if (lhs_sym != rhs_sym) {
02253 if (trace_dependence) fprintf(TFile,"no indirection, different symbols\n");
02254 return (DEP_INDEPENDENT);
02255 }
02256
02257 r = check_overlap(lhs_base_offset,rhs_base_offset,lhs_size,rhs_size);
02258 if (r == DEP_INDEPENDENT || r == DEP_UNKNOWN) {
02259 if (trace_dependence) fprintf(TFile,"same base, overlap check %s\n",f90_depsum_name(r));
02260 return (r);
02261 }
02262
02263
02264
02265 r = analyze_structure_bases(lhs_num_pieces-1,rhs_num_pieces-1,NULL,NULL);
02266 if (trace_dependence) fprintf(TFile,"no indirection, same symbol %s\n",f90_depsum_name(r));
02267 return (r);
02268 }
02269
02270
02271 if (lhs_num_pieces == rhs_num_pieces) {
02272 same = TRUE;
02273 for (i = 0; i < lhs_num_pieces ; i++) {
02274 if (WN_operator(lhs_pieces[i]) != OPR_ARRSECTION &&
02275 WN_operator(rhs_pieces[i]) != OPR_ARRSECTION) {
02276 if (WN_Simp_Compare_Trees(lhs_pieces[i],rhs_pieces[i]) != 0) {
02277 same = FALSE;
02278 break;
02279 }
02280 }
02281 }
02282 if (same) {
02283 if (trace_dependence) fprintf(TFile,"all but ARRSECTIONs IDENTICAL\n");
02284 return (DEP_IDENTICAL);
02285 }
02286 }
02287
02288
02289
02290 li = 0;
02291 ri = 0;
02292 while (li < lhs_num_pieces) {
02293 opr = WN_operator(lhs_pieces[li]);
02294 if (opr == OPR_ILOAD ||
02295 opr == OPR_LDID ||
02296 opr == OPR_LDA) {
02297 break;
02298 }
02299 li++;
02300 }
02301 while (ri < rhs_num_pieces) {
02302 opr = WN_operator(rhs_pieces[ri]);
02303 if (opr == OPR_ILOAD ||
02304 opr == OPR_LDID ||
02305 opr == OPR_LDA) {
02306 break;
02307 }
02308 ri++;
02309 }
02310 if (ri < rhs_num_pieces && li < lhs_num_pieces) {
02311 lhsa = lhs_pieces[li];
02312 rhsa = rhs_pieces[ri];
02313 if (WN_Simp_Compare_Trees(lhsa,rhsa)==0) {
02314
02315 r = analyze_structure_bases(li-1,ri-1,NULL,NULL);
02316 if (trace_dependence) fprintf(TFile,"same top base addresses %s\n",f90_depsum_name(r));
02317 return (r);
02318 }
02319
02320
02321
02322
02323
02324
02325
02326
02327
02328
02329
02330
02331
02332
02333
02334
02335
02336
02337
02338
02339
02340
02341
02342
02343
02344 l_pointer = is_f90_pointer(lhsa);
02345 l_target = is_f90_target(lhsa);
02346 l_formal = is_f90_formal(lhsa);
02347 r_pointer = is_f90_pointer(rhsa);
02348 r_target = is_f90_target(rhsa);
02349 r_formal = is_f90_formal(rhsa);
02350 if (l_formal) {
02351 l_pointer = l_pointer || ST_is_f90_pointer(lhs_sym);
02352 l_target = l_target || ST_is_f90_target(lhs_sym);
02353 }
02354 if (r_formal) {
02355 r_pointer = r_pointer || ST_is_f90_pointer(rhs_sym);
02356 r_target = r_target || ST_is_f90_target(rhs_sym);
02357 }
02358 if ((l_pointer && r_target) ||
02359 (r_pointer && l_target) ||
02360 (r_pointer && l_pointer)) {
02361 if (Alias_F90_Pointer_Unaliased) {
02362 r = DEP_INDEPENDENT;
02363 } else {
02364 r = DEP_UNKNOWN;
02365 }
02366 } else if (is_f90_formal(lhsa) || is_f90_formal(rhsa)) {
02367 r = DEP_INDEPENDENT;
02368 } else {
02369
02370 if ((rhs_flag ^ lhs_flag) & F90_INDIRECTION) {
02371
02372 r = DEP_INDEPENDENT;
02373 } else if ((rhs_flag | lhs_flag) & F90_UNALIASED) {
02374 r = DEP_INDEPENDENT;
02375 } else {
02376 r = DEP_UNKNOWN;
02377 }
02378 }
02379 } else {
02380
02381 r = DEP_UNKNOWN;
02382 }
02383 if (trace_dependence) fprintf(TFile,"bases with indirection %s\n",f90_depsum_name(r));
02384 return (r);
02385 }
02386
02387
02388
02389
02390
02391
02392
02393
02394
02395
02396
02397
02398
02399
02400
02401
02402
02403
02404
02405
02406
02407
02408
02409 static void Dependence_Walk(WN *expr,F90_LOWER_AUX_DATA *adata, DEP_INFO *dep,
02410 BOOL transformational_seen,
02411 WN *parent, INT kidno, INT lhsdim)
02412 {
02413 OPCODE op;
02414 OPERATOR opr;
02415 DEP_INFO kid_dep;
02416 WN *kid;
02417 WN *copy_store;
02418 INT i,num_kids;
02419 BOOL keep_going;
02420 DEP_SUMMARY base_dep;
02421
02422 op = WN_opcode(expr);
02423 opr = OPCODE_operator(op);
02424
02425 if (opr == OPR_LDID) {
02426 return;
02427 } else if (opr == OPR_ILOAD || opr == OPR_MLOAD) {
02428 kid = WN_kid0(expr);
02429 if (opr == OPR_MLOAD) {
02430
02431 if (WN_operator(kid) == OPR_ARRAYEXP) {
02432 kid = WN_kid0(kid);
02433 }
02434 if (WN_operator(kid) == OPR_INTRINSIC_OP) {
02435
02436 goto check_kids;
02437 }
02438 }
02439 rhs_const_offset = WN_offset(expr);
02440 Analyze_one_address(kid,&rhs_sym,rhs_pieces,&rhs_num_pieces,&rhs_const_offset,
02441 &rhs_base_offset,&rhs_size,&rhs_flag,&rhs_ty);
02442 base_dep = Analyze_bases(expr,FALSE);
02443
02444 if (base_dep == DEP_UNKNOWN) {
02445 if (rhs_sym != NULL && !(rhs_flag & F90_ARRSECTION) && parent) {
02446 kid = F90_Lower_Copy_To_STemp(©_store,expr);
02447 WN_kid(parent,kidno) = kid;
02448 WN_INSERT_BlockLast(PRELIST(adata),copy_store);
02449 SET_DEP_SUMMARY(dep,DEP_INDEPENDENT);
02450 } else {
02451 SET_DEP_SUMMARY(dep,DEP_UNKNOWN);
02452 }
02453 return;
02454 } else if (base_dep == DEP_INDEPENDENT) {
02455 goto check_kids;
02456 } else {
02457
02458 if (!(rhs_flag & F90_ARRSECTION) && parent) {
02459 kid = F90_Lower_Copy_To_STemp(©_store,expr);
02460 WN_kid(parent,kidno) = kid;
02461 WN_INSERT_BlockLast(PRELIST(adata),copy_store);
02462 SET_DEP_SUMMARY(dep,DEP_INDEPENDENT);
02463 return;
02464 }
02465
02466 if (transformational_seen) {
02467 SET_DEP_SUMMARY(dep,DEP_UNKNOWN);
02468 return;
02469 }
02470
02471
02472 if (lhs_arrsection) {
02473 for (i=0; i < rhs_num_pieces && WN_operator(rhs_pieces[i]) != OPR_ARRSECTION; i++);
02474 DevAssert((WN_operator(rhs_pieces[i])==OPR_ARRSECTION),("Expected to find an arrsection"));
02475 (void) Analyze_all_indices(lhs_arrsection,rhs_pieces[i],&kid_dep);
02476 keep_going = F90_Lower_Merge_Dep_Info(dep,&kid_dep);
02477 if (!keep_going) return;
02478 }
02479 }
02480 } else if (opr == OPR_INTRINSIC_OP && F90_Is_Transformational(WN_GET_INTRINSIC(expr))) {
02481
02482 transformational_seen = TRUE;
02483 }
02484
02485 check_kids:
02486
02487 num_kids = WN_kid_count(expr);
02488 if (opr == OPR_TRIPLET) num_kids = 2;
02489 for (i=0; i < num_kids; i++) {
02490 kid = WN_kid(expr,i);
02491 F90_Lower_Init_Dep_Info(&kid_dep,lhsdim);
02492 Dependence_Walk(kid, adata, &kid_dep, transformational_seen,expr,i,lhsdim);
02493 keep_going = F90_Lower_Merge_Dep_Info(dep,&kid_dep);
02494 if (!keep_going) break;
02495 }
02496
02497 return;
02498 }
02499
02500
02501
02502
02503
02504
02505
02506 static void f90_analyze_mstore(WN *stmt, WN *block)
02507 {
02508 F90_LOWER_AUX_DATA *adata;
02509 WN *lhs,*rhs;
02510 DEP_INFO dep;
02511
02512 stmt = stmt;
02513 lhs = WN_kid1(stmt);
02514 rhs = WN_kid0(stmt);
02515
02516 adata = F90_Lower_New_Aux_Data(0);
02517 SET_F90_MAP(stmt,adata);
02518
02519 lhs_const_offset = WN_offset(stmt);
02520
02521 F90_Lower_Init_Dep_Info(&dep,0);
02522
02523 lhs_address = lhs;
02524 lhs_arrsection = NULL;
02525 Analyze_one_address(lhs,&lhs_sym,lhs_pieces,&lhs_num_pieces,&lhs_const_offset,
02526 &lhs_base_offset,&lhs_size,&lhs_flag,&lhs_ty);
02527
02528
02529
02530 Dependence_Walk(rhs,adata,&dep,FALSE,stmt,0,0);
02531
02532
02533 (void) F90_Insert_All_Prelists(stmt,block);
02534 (void) F90_Insert_Temp_Allocations(stmt,block);
02535 return;
02536 }
02537
02538
02539
02540
02541
02542
02543
02544
02545
02546
02547
02548
02549
02550
02551
02552 static void f90_analyze_assignment(WN *stmt, WN *block, BOOL is_call)
02553 {
02554 F90_LOWER_AUX_DATA *adata;
02555 WN *lhs_arrayexp;
02556 INT ndim;
02557 INT lhsdim;
02558 INT i,num_kids;
02559 INT vec_axes,vec_axis_list[MAX_NDIM],axis;
02560 WN *assignment;
02561 WN *lhs,*rhs;
02562 WN *count,*copy_store;
02563 DEP_INFO lhs_dep,rhs_dep;
02564 INTRINSIC intr;
02565
02566 if (is_call) {
02567 if (WN_opcode(stmt) != OPC_WHERE) {
02568 if (WN_operator(stmt)==OPR_INTRINSIC_CALL) {
02569 intr = WN_GET_INTRINSIC(stmt);
02570 } else {
02571 intr = INTRINSIC_NONE;
02572 }
02573 if (WN_operator(stmt) == OPR_CALL || WN_operator(stmt) == OPR_ICALL) {
02574 num_kids = WN_kid_count(stmt);
02575 for (i=0; i < num_kids; i++) {
02576 lhs_arrayexp = WN_kid0(WN_kid(stmt,i));
02577 if (WN_operator(lhs_arrayexp) == OPR_ARRAYEXP) {
02578 break;
02579 }
02580 }
02581 } else {
02582 lhs_arrayexp = WN_kid0(WN_kid0(stmt));
02583 }
02584 assignment = stmt;
02585 ndim = WN_kid_count(lhs_arrayexp) - 1;
02586 } else if (WN_opcode(stmt) == OPC_WHERE) {
02587
02588 lhs_arrayexp = WN_kid0(stmt);
02589 ndim = WN_kid_count(lhs_arrayexp)-1;
02590 assignment = get_assignment_from_stmt(stmt);
02591 lhs_arrayexp = WN_kid0(WN_kid0(assignment));
02592 if (WN_operator(assignment)==OPR_INTRINSIC_CALL) {
02593 intr = WN_GET_INTRINSIC(assignment);
02594 } else {
02595 intr = INTRINSIC_NONE;
02596 }
02597 }
02598
02599
02600
02601 lhs = WN_kid0(lhs_arrayexp);
02602 if (intr == INTRN_CASSIGNSTMT) {
02603 rhs = WN_kid0(WN_kid1(assignment));
02604 } else {
02605 rhs = NULL;
02606 }
02607 } else {
02608
02609 if (WN_opcode(stmt) != OPC_WHERE) {
02610 lhs_arrayexp = WN_kid1(stmt);
02611 ndim = WN_kid_count(lhs_arrayexp) - 1;
02612 assignment = stmt;
02613 } else if (WN_opcode(stmt) == OPC_WHERE) {
02614
02615 lhs_arrayexp = WN_kid0(stmt);
02616 ndim = WN_kid_count(lhs_arrayexp)-1;
02617 assignment = get_assignment_from_stmt(stmt);
02618 lhs_arrayexp = WN_kid1(assignment);
02619 }
02620 rhs = WN_kid0(assignment);
02621 lhs = WN_kid0(lhs_arrayexp);
02622 }
02623 adata = F90_Lower_New_Aux_Data(ndim);
02624 SET_F90_MAP(stmt,adata);
02625
02626
02627
02628
02629
02630 if (rhs) {
02631 if (is_call) {
02632 lhs_const_offset = 0;
02633 } else {
02634 lhs_const_offset = WN_offset(assignment);
02635 }
02636 lhs_arrsection = find_arrsection(lhs);
02637 lhsdim = (WN_kid_count(lhs_arrsection)-1)/2;
02638
02639 F90_Lower_Init_Dep_Info(&lhs_dep,lhsdim);
02640 F90_Lower_Init_Dep_Info(&rhs_dep,lhsdim);
02641
02642 lhs_address = lhs;
02643 Analyze_one_address(lhs,&lhs_sym,lhs_pieces,&lhs_num_pieces,&lhs_const_offset,
02644 &lhs_base_offset,&lhs_size,&lhs_flag,&lhs_ty);
02645
02646
02647 num_kids = WN_kid_count(lhs_arrsection);
02648 for (i=lhsdim+1; i < num_kids ; i++) {
02649 Dependence_Walk(WN_kid(lhs_arrsection,i),adata,&lhs_dep,FALSE,lhs_arrsection,i,lhsdim);
02650 }
02651
02652 if (DEP_SUMMARY(&lhs_dep) != DEP_INDEPENDENT) {
02653
02654 SET_COPY_FLAG(adata,COPY_LEFT | COPY_FLAG(adata));
02655 }
02656
02657
02658 for (i=1; i <= ndim ; i++) {
02659 Dependence_Walk(WN_kid(lhs_arrayexp,i),adata,&lhs_dep,FALSE,lhs_arrayexp,i,lhsdim);
02660 }
02661
02662
02663 Dependence_Walk(rhs,adata,&rhs_dep,FALSE,assignment,0,lhsdim);
02664 switch (DEP_SUMMARY(&rhs_dep)) {
02665 case DEP_INDEPENDENT:
02666 case DEP_IDENTICAL:
02667
02668 break;
02669
02670 case DEP_UNKNOWN:
02671
02672 SET_COPY_FLAG(adata,COPY_RIGHT | COPY_FLAG(adata));
02673 break;
02674
02675 case DEP_REMOVABLE:
02676
02677
02678
02679 vec_axes = find_vector_axes(vec_axis_list,lhs_arrsection);
02680 for (i=0; i <vec_axes; i++) {
02681 axis = vec_axis_list[i];
02682 if (DEP_DIRECTION(&rhs_dep,axis) == DIR_POSITIVE ||
02683 DEP_DIRECTION(&rhs_dep,axis) == DIR_NEGATIVE) {
02684 SET_DIRECTION(adata,i,DEP_DIRECTION(&rhs_dep,axis));
02685 }
02686 }
02687 FmtAssert((vec_axes == ndim),("found wrong number of vector axes"));
02688 break;
02689 }
02690 }
02691
02692
02693
02694
02695
02696
02697 for (i=0; i < ndim; i++) {
02698 if (ITER_COUNT(adata,i)) {
02699
02700 WN_DELETE_Tree(WN_kid(lhs_arrayexp,i+1));
02701 } else {
02702 count = WN_kid(lhs_arrayexp,i+1);
02703 if (arrayexp_in_subtree(count)) {
02704 count = F90_Lower_Copy_To_STemp(©_store,count);
02705 WN_INSERT_BlockBefore(block,stmt,copy_store);
02706 }
02707 SET_ITER_COUNT(adata,i,count);
02708 }
02709 }
02710
02711 if (is_call) {
02712 WN_kid0(WN_kid0(assignment)) = WN_kid0(lhs_arrayexp);
02713 } else {
02714 WN_kid1(assignment) = WN_kid0(lhs_arrayexp);
02715 }
02716 WN_Delete(lhs_arrayexp);
02717
02718 return;
02719 }
02720
02721
02722
02723
02724
02725
02726
02727
02728 static BOOL F90_Do_Dependence_Analysis(WN *stmt, WN *block)
02729 {
02730 OPCODE op;
02731 OPERATOR opr;
02732 BOOL is_arrayexp;
02733 WN *arrayexp;
02734 INT i,num_kids;
02735
02736
02737
02738
02739 is_arrayexp = arrayexp_in_subtree(stmt);
02740 array_statement_seen = array_statement_seen || is_arrayexp;
02741
02742 op = WN_opcode(stmt);
02743 opr = OPCODE_operator(op);
02744
02745
02746 if (opr == OPR_MSTORE &&
02747 WN_operator(WN_kid1(stmt)) != OPR_ARRAYEXP) {
02748 f90_analyze_mstore(stmt,block);
02749 return(TRUE);
02750 }
02751
02752
02753
02754
02755
02756
02757
02758
02759
02760
02761
02762 if (opr == OPR_WHERE) {
02763 arrayexp = get_assignment_from_stmt(stmt);
02764 if (WN_operator(arrayexp) == OPR_INTRINSIC_CALL) {
02765 f90_analyze_assignment(stmt, block, TRUE);
02766 } else {
02767 f90_analyze_assignment(stmt, block, FALSE);
02768 }
02769 } else if (opr == OPR_MSTORE || opr == OPR_ISTORE) {
02770
02771 arrayexp = WN_kid1(stmt);
02772 if (WN_operator(arrayexp) == OPR_ARRAYEXP) {
02773
02774 f90_analyze_assignment(stmt, block, FALSE);
02775 }
02776 } else if (opr == OPR_INTRINSIC_CALL) {
02777 if (WN_kid_count(stmt) > 0) {
02778 arrayexp = WN_kid0(WN_kid0(stmt));
02779 if (WN_operator(arrayexp) == OPR_ARRAYEXP) {
02780 f90_analyze_assignment(stmt,block,TRUE);
02781 }
02782 }
02783 } else if (opr == OPR_CALL || opr == OPR_ICALL) {
02784 if (opr == OPR_ICALL) {
02785
02786 num_kids = WN_kid_count(stmt) - 1;
02787 } else {
02788 num_kids = WN_kid_count(stmt);
02789 }
02790 for (i=0 ; i < num_kids; i++) {
02791 arrayexp = WN_kid0(WN_kid(stmt,i));
02792 if (WN_operator(arrayexp) == OPR_ARRAYEXP) {
02793 f90_analyze_assignment(stmt,block,TRUE);
02794 break;
02795 }
02796 }
02797 }
02798
02799 return (TRUE);
02800 }
02801
02802
02803 static void F90_Analyze_Dependencies (WN *pu)
02804 {
02805 F90_Walk_Statements(pu,F90_Do_Dependence_Analysis);
02806 }
02807
02808
02809
02810
02811
02812
02813
02814
02815
02816
02817
02818
02819
02820
02821
02822 static WN * F90_Triplet_Scalarization_Walk(WN *expr, WN *stmt, WN *block, INT move)
02823 {
02824 OPERATOR opr;
02825 INT i,numkids;
02826 WN *copy_store;
02827 WN *kid;
02828
02829 opr = WN_operator(expr);
02830 numkids = WN_kid_count(expr);
02831
02832 if (opr == OPR_ARRAYEXP) {
02833 WN_kid0(expr) = F90_Triplet_Scalarization_Walk(WN_kid0(expr),stmt,block,FALSE);
02834 for (i=1; i<numkids; i++) {
02835 WN_kid(expr,i) = F90_Triplet_Scalarization_Walk(WN_kid(expr,i),stmt,block,TRUE);
02836 }
02837 } else if (opr == OPR_TRIPLET) {
02838 WN_kid0(expr) = F90_Triplet_Scalarization_Walk(WN_kid0(expr),stmt,block,1);
02839 WN_kid1(expr) = F90_Triplet_Scalarization_Walk(WN_kid1(expr),stmt,block,1);
02840
02841 WN_kid2(expr) = F90_Triplet_Scalarization_Walk(WN_kid2(expr),stmt,block,0);
02842 } else if (opr == OPR_DO_LOOP) {
02843
02844 kid = WN_kid1(expr);
02845 WN_kid0(kid) = F90_Triplet_Scalarization_Walk(WN_kid0(kid),stmt,block,2);
02846 for (i = 2; i < numkids; i++) {
02847 WN_kid(expr,i) = F90_Triplet_Scalarization_Walk(WN_kid(expr,i),stmt,block,move);
02848 }
02849 } else if ((move > 0) && opr == OPR_INTRINSIC_OP &&
02850 (F90_Is_Transformational(WN_GET_INTRINSIC(expr)) || move == 2)) {
02851
02852 expr = F90_Lower_Copy_To_STemp(©_store,expr);
02853 WN_INSERT_BlockBefore(block,stmt,copy_store);
02854 } else {
02855
02856 for (i=0; i<numkids; i++) {
02857 WN_kid(expr,i) = F90_Triplet_Scalarization_Walk(WN_kid(expr,i),stmt,block,move);
02858 }
02859 }
02860 return (expr);
02861 }
02862
02863
02864 static BOOL F90_Scalarize_Triplets_And_Sizes(WN *stmt, WN *block)
02865 {
02866 (void) F90_Triplet_Scalarization_Walk(stmt,stmt,block,0);
02867 return (TRUE);
02868 }
02869
02870
02871
02872
02873
02874
02875 static BOOL F90_Do_Copies(WN *stmt, WN *block)
02876 {
02877 F90_LOWER_AUX_DATA *adata,*copy_adata;
02878 INT ndim,i;
02879 COPY_FLAG_T copy;
02880 WN *assignment;
02881 WN *new_rhs,*new_lhsptr;
02882 WN *copy_store;
02883 WN *rhs;
02884 TY *ty;
02885 OPERATOR assign_opr;
02886 BOOL in_where,in_elsewhere;
02887 WN *sizes[MAX_NDIM];
02888 WN *new_where;
02889
02890 adata = GET_F90_MAP(stmt);
02891 if (!adata) return (TRUE);
02892 copy = COPY_FLAG(adata);
02893 if (copy == COPY_NONE) return (TRUE);
02894
02895 if (WN_opcode(stmt) == OPC_WHERE) {
02896 in_where = TRUE;
02897 in_elsewhere = FALSE;
02898 assignment = WN_first(WN_kid1(stmt));
02899 if (!assignment) {
02900 assignment = WN_first(WN_kid2(stmt));
02901 in_elsewhere = TRUE;
02902 }
02903 } else {
02904 in_where = FALSE;
02905 assignment = stmt;
02906 }
02907
02908 assignment = get_assignment_from_stmt(stmt);
02909 assign_opr = WN_operator(assignment);
02910
02911
02912 if (copy == COPY_RIGHT || copy == COPY_BOTH) {
02913 if (assign_opr == OPR_ISTORE || assign_opr == OPR_MSTORE) {
02914 if (in_where) {
02915
02916 copy_adata = F90_Lower_Copy_Aux_Data(adata);
02917 ndim = NDIM(copy_adata);
02918
02919 for (i=0; i <ndim ; i++) {
02920 sizes[i] = ITER_COUNT(copy_adata,i);
02921 }
02922 new_rhs = F90_Lower_Copy_To_ATemp(&ALLOC_PRELIST(copy_adata),&DEALLOC_POSTLIST(adata),
02923 ©_store,WN_kid0(assignment),sizes,ndim);
02924 WN_INSERT_BlockFirst(PRELIST(copy_adata),PRELIST(adata));
02925 WN_INSERT_BlockFirst(ALLOC_PRELIST(copy_adata),ALLOC_PRELIST(adata));
02926 SET_PRELIST(adata,WN_CreateBlock());
02927 SET_ALLOC_PRELIST(adata,WN_CreateBlock());
02928
02929 new_where = WN_Create(OPC_WHERE,3);
02930 WN_kid0(new_where) = WN_COPY_Tree(WN_kid0(stmt));
02931 WN_kid1(new_where) = WN_CreateBlock();
02932 WN_kid2(new_where) = WN_CreateBlock();
02933
02934 if (in_elsewhere) {
02935 WN_INSERT_BlockFirst(WN_kid2(new_where),copy_store);
02936 } else {
02937 WN_INSERT_BlockFirst(WN_kid1(new_where),copy_store);
02938 }
02939 SET_F90_MAP(new_where,copy_adata);
02940 WN_INSERT_BlockBefore(block,stmt,new_where);
02941 } else {
02942 new_rhs = F90_Lower_Copy_Expr_to_Temp(WN_kid0(assignment),stmt,block);
02943 }
02944 WN_kid0(assignment) = new_rhs;
02945 } else {
02946
02947
02948
02949 copy_adata = F90_Lower_Copy_Aux_Data(adata);
02950 rhs = WN_kid0(WN_kid1(assignment));
02951 ty = WN_ty(WN_kid0(assignment));
02952 rhs = WN_CreateMload(0,ty,rhs,WN_COPY_Tree(WN_kid0(WN_kid(assignment,3))));
02953 new_rhs = F90_Lower_Copy_To_ATemp(&ALLOC_PRELIST(copy_adata), &DEALLOC_POSTLIST(adata),
02954 ©_store,rhs,
02955 ITER_COUNT_PTR(adata), NDIM(adata));
02956
02957 WN_kid0(WN_kid1(assignment)) = WN_kid0(new_rhs);
02958 WN_DELETE_Tree(WN_kid1(new_rhs));
02959 WN_Delete(new_rhs);
02960 SET_F90_MAP(copy_store,copy_adata);
02961 WN_INSERT_BlockBefore(block,stmt,copy_store);
02962 WN_INSERT_BlockFirst(ALLOC_PRELIST(copy_adata),ALLOC_PRELIST(adata));
02963 SET_ALLOC_PRELIST(adata,WN_CreateBlock());
02964 }
02965 }
02966
02967 if (copy == COPY_LEFT || copy == COPY_BOTH) {
02968
02969 if (assign_opr == OPR_ISTORE || assign_opr == OPR_MSTORE) {
02970 new_lhsptr = F90_Lower_Copy_Expr_to_Temp(WN_kid1(assignment),stmt,block);
02971 WN_kid1(assignment) = new_lhsptr;
02972 } else {
02973
02974
02975
02976 new_lhsptr = F90_Lower_Copy_Expr_to_Temp(WN_kid0(WN_kid0(assignment)),stmt,block);
02977 WN_kid0(WN_kid0(assignment)) = new_lhsptr;
02978
02979 }
02980 }
02981 return (TRUE);
02982 }
02983
02984
02985
02986
02987
02988
02989
02990
02991
02992
02993
02994
02995 static WN * F90_Move_Transformational_Walk(WN *t, WN *stmt, WN *block, WN *parent, BOOL in_where)
02996 {
02997 INT numkids;
02998 WN *kid;
02999 WN *temp;
03000 INT i;
03001 OPERATOR opr;
03002 BOOL walking_where;
03003
03004
03005 numkids = WN_kid_count(t);
03006 opr = WN_operator(t);
03007
03008 if (opr == OPR_BLOCK) {
03009 kid = WN_first(t);
03010 while (kid) {
03011 (void) F90_Move_Transformational_Walk(kid, stmt, block,t,in_where);
03012 kid = WN_next(kid);
03013 }
03014 } else {
03015 for (i=0; i < numkids; i++) {
03016 kid = WN_kid(t,i);
03017 walking_where = (opr == OPR_WHERE) || in_where;
03018 temp = F90_Move_Transformational_Walk(kid,stmt,block,t,walking_where);
03019 WN_kid(t,i) = temp;
03020 }
03021 }
03022
03023 if (opr != OPR_INTRINSIC_OP) {
03024 return (t);
03025 }
03026
03027
03028 switch (WN_GET_INTRINSIC(t)) {
03029 case INTRN_SPREAD:
03030
03031 kid = WN_kid0(WN_kid0(t));
03032 if (WN_operator(kid) != OPR_ILOAD && WN_operator(kid) != OPR_MLOAD &&
03033 WN_operator(kid) != OPR_LDID &&
03034 (WN_operator(kid) != OPR_INTRINSIC_OP && WN_GET_INTRINSIC(kid) != INTRN_SPREAD )) {
03035
03036 temp = F90_Lower_Copy_Expr_to_Temp(kid,stmt,block);
03037 WN_kid0(WN_kid0(t)) = temp;
03038 }
03039 return (t);
03040
03041 case INTRN_PACK:
03042 case INTRN_UNPACK:
03043 case INTRN_EOSHIFT:
03044 if (!OPCODE_is_stmt(WN_opcode(parent)) || in_where) {
03045 temp = F90_Lower_Copy_Expr_to_Temp(t,stmt,block);
03046 return(temp);
03047 } else {
03048
03049 return (t);
03050 }
03051
03052 default:
03053 return (t);
03054 }
03055 }
03056
03057
03058
03059
03060
03061
03062
03063
03064
03065 static BOOL F90_Move_Transformationals(WN *stmt, WN *block)
03066 {
03067
03068 (void) F90_Move_Transformational_Walk(stmt,stmt,block,NULL,FALSE);
03069 return (TRUE);
03070 }
03071
03072
03073
03074
03075
03076
03077
03078
03079
03080
03081
03082
03083
03084
03085 static WN * create_doloop(PREG_NUM *index, char *index_name, WN *count, DIR_FLAG dir, WN *body)
03086 {
03087 WN *index_id, *count_expr, *start, *end, *step, *doloop;
03088 OPCODE intconst_op;
03089 TYPE_ID index_type;
03090 WN *temp;
03091
03092 index_type = doloop_ty;
03093 intconst_op = OPCODE_make_op(OPR_INTCONST,index_type,MTYPE_V);
03094
03095
03096 *index = Create_Preg(index_type,Save_Str(index_name),NULL);
03097
03098 index_id = WN_CreateIdname(*index,MTYPE_To_PREG(index_type));
03099 count_expr = WN_CreateExp2(OPCODE_make_op(OPR_SUB,index_type,MTYPE_V),
03100 count,
03101 WN_CreateIntconst(intconst_op,1));
03102
03103 if (dir == DIR_NEGATIVE) {
03104
03105 start = WN_StidPreg(index_type,*index,count_expr);
03106 end = WN_CreateExp2(OPCODE_make_op(OPR_GE,MTYPE_I4,index_type),
03107 WN_LdidPreg(index_type,*index),
03108 WN_CreateIntconst(intconst_op,0));
03109
03110 step = WN_CreateExp2(OPCODE_make_op(OPR_SUB,index_type,MTYPE_V),
03111 WN_LdidPreg(index_type,*index),
03112 WN_CreateIntconst(intconst_op,1));
03113 step = WN_StidPreg(index_type,*index,step);
03114 } else {
03115
03116 start = WN_StidPreg(index_type,*index, WN_CreateIntconst(intconst_op,0));
03117 end = WN_CreateExp2(OPCODE_make_op(OPR_LE,MTYPE_I4,index_type),
03118 WN_LdidPreg(index_type,*index),
03119 count_expr);
03120
03121 step = WN_CreateExp2(OPCODE_make_op(OPR_ADD,index_type,MTYPE_V),
03122 WN_LdidPreg(index_type,*index),
03123 WN_CreateIntconst(intconst_op,1));
03124 step = WN_StidPreg(index_type,*index,step);
03125 }
03126
03127
03128 if (WN_opcode(body) != OPC_BLOCK) {
03129 temp = WN_CreateBlock();
03130 WN_INSERT_BlockFirst(temp,body);
03131 } else {
03132 temp = body;
03133 }
03134
03135 WN_Set_Linenum(start,current_srcpos);
03136 WN_Set_Linenum(step,current_srcpos);
03137 doloop = WN_CreateDO(index_id, start, end, step, temp, NULL);
03138 WN_Set_Linenum(doloop,current_srcpos);
03139 return (doloop);
03140 }
03141
03142
03143
03144
03145
03146
03147
03148
03149
03150
03151
03152 static WN * create_doloop_nest(PREG_NUM indices[], WN **doloop, WN *sizes[], INT ndim)
03153 {
03154 INT i;
03155 WN *loopnest, *stlist;
03156 char tempname[32];
03157 PREG_NUM index;
03158
03159 loopnest = WN_CreateBlock();
03160 stlist = loopnest;
03161 num_temps += 1;
03162 for (i=ndim-1; i >= 0; i--) {
03163 sprintf(tempname,"@f90li_%d_%d",i,num_temps);
03164
03165
03166 loopnest = create_doloop(&index,tempname,sizes[i],DIR_POSITIVE,loopnest);
03167 indices[i] = index;
03168 }
03169 *doloop = loopnest;
03170 return (stlist);
03171 }
03172
03173
03174
03175
03176
03177
03178
03179
03180
03181
03182
03183
03184
03185
03186
03187
03188
03189
03190
03191
03192
03193
03194
03195
03196
03197 static WN * lower_reduction(TYPE_ID rty, OPERATOR reduction_opr,
03198 WN *kids[], PREG_NUM *indices, INT ndim,
03199 WN * block, WN *insert_point)
03200 {
03201 INT dim;
03202 OPCODE reduction_op;
03203 PREG_NUM accum;
03204 WN *sizes[MAX_NDIM];
03205 PREG_NUM new_indices[MAX_NDIM],index;
03206 INT rank,i,j;
03207 WN *idty_store;
03208 WN *accum_store,*accum_block;
03209 WN *loopnest,*stlist,*mask_expr,*accum_expr;
03210 char tempname[32];
03211 WN *result;
03212 BOOL Mask_Present;
03213 F90_LOWER_AUX_DATA *adata;
03214 WN *dealloc_post,*post;
03215 TYPE_ID ty;
03216
03217 if (kids[1]) {
03218 dim = F90_Get_Dim(kids[1]);
03219 WN_DELETE_Tree(kids[1]);
03220 } else {
03221 dim = 0;
03222 }
03223
03224 if (!kids[2] || (WN_operator(kids[2]) == OPR_INTCONST &&
03225 WN_const_val(kids[2]) == 1)) {
03226 Mask_Present = FALSE;
03227 } else {
03228 Mask_Present = TRUE;
03229 }
03230
03231 ty = Mtype_comparison(rty);
03232
03233
03234 accum = Create_Preg(ty,create_tempname("@f90acc"),NULL);
03235
03236 reduction_op = OPCODE_make_op(reduction_opr,ty,MTYPE_V);
03237 idty_store = WN_StidPreg(ty,accum,Make_Reduction_Identity(reduction_opr,rty));
03238
03239
03240 (void) F90_Size_Walk(kids[0],&rank,sizes);
03241 loopnest = WN_CreateBlock();
03242 stlist = loopnest;
03243
03244
03245 if (dim == 0 || (dim == 1 && rank == 1)) {
03246 WN_INSERT_BlockBefore(F90_Current_Block,F90_Current_Loopnest,idty_store);
03247 adata = GET_F90_MAP(F90_Current_Loopnest);
03248 if (adata) {
03249 dealloc_post = DEALLOC_POSTLIST(adata);
03250 post = POSTLIST(adata);
03251 SET_DEALLOC_POSTLIST(adata,WN_CreateBlock());
03252 SET_POSTLIST(adata,WN_CreateBlock());
03253 }
03254
03255
03256 num_temps += 1;
03257 for (i=rank-1; i >= 0 ; i--) {
03258 sprintf(tempname,"@f90li_%d_%d",i,num_temps);
03259 loopnest = create_doloop(&index,tempname,sizes[i],DIR_POSITIVE,loopnest);
03260 new_indices[i] = index;
03261 }
03262 WN_INSERT_BlockBefore(F90_Current_Block,F90_Current_Loopnest,loopnest);
03263
03264
03265 F90_Current_Loopnest = loopnest;
03266
03267
03268 if (adata) {
03269 adata = F90_Lower_New_Aux_Data(0);
03270 SET_POSTLIST(adata,post);
03271 SET_DEALLOC_POSTLIST(adata,dealloc_post);
03272 SET_F90_MAP(loopnest,adata);
03273 }
03274
03275
03276 accum_expr = F90_Lower_Walk(kids[0],new_indices,rank,stlist,NULL);
03277 accum_store = WN_StidPreg(ty,accum,WN_CreateExp2(reduction_op,
03278 WN_LdidPreg(ty,accum),
03279 accum_expr));
03280 accum_block = WN_CreateBlock();
03281 WN_INSERT_BlockFirst(accum_block,accum_store);
03282 if (Mask_Present) {
03283 mask_expr = F90_Lower_Walk(kids[2],new_indices,rank,stlist,NULL);
03284
03285 accum_block = WN_CreateIf(mask_expr,accum_block,WN_CreateBlock());
03286 }
03287
03288 WN_INSERT_BlockLast(stlist,accum_block);
03289
03290
03291
03292 } else {
03293
03294
03295 WN_INSERT_BlockBefore(block,insert_point,idty_store);
03296
03297
03298 num_temps += 1;
03299 dim = ndim + 2 - dim;
03300 sprintf(tempname,"@f90red_%d",num_temps);
03301 loopnest = create_doloop(&index,tempname,sizes[dim-1],DIR_POSITIVE,loopnest);
03302 for (i=0,j=0; i < ndim+1; i++) {
03303 if (i != dim-1) {
03304 WN_DELETE_Tree(sizes[i]);
03305 new_indices[i] = indices[j];
03306 j += 1;
03307 } else {
03308 new_indices[i] = index;
03309 }
03310 }
03311
03312 WN_INSERT_BlockBefore(block,insert_point,loopnest);
03313
03314 accum_expr = F90_Lower_Walk(kids[0],new_indices,ndim+1,stlist,NULL);
03315 accum_store = WN_StidPreg(ty,accum,WN_CreateExp2(reduction_op,
03316 WN_LdidPreg(ty,accum),
03317 accum_expr));
03318 accum_block = WN_CreateBlock();
03319 WN_INSERT_BlockFirst(accum_block,accum_store);
03320 if (Mask_Present) {
03321 mask_expr = F90_Lower_Walk(kids[2],new_indices,rank,stlist,NULL);
03322
03323 accum_block = WN_CreateIf(mask_expr,accum_block,WN_CreateBlock());
03324 }
03325
03326 WN_INSERT_BlockLast(stlist,accum_block);
03327 }
03328
03329
03330 result = WN_LdidPreg(ty,accum);
03331 if (rty == MTYPE_I1) {
03332 result = WN_CreateCvtl(OPC_I4CVTL,8,result);
03333 } else if (rty == MTYPE_I2) {
03334 result = WN_CreateCvtl(OPC_I4CVTL,16,result);
03335 }
03336
03337 return (result);
03338 }
03339
03340
03341
03342
03343
03344
03345
03346
03347
03348
03349
03350
03351
03352
03353
03354
03355
03356
03357
03358
03359
03360 static WN * lower_maxminloc(OPERATOR reduction_opr,
03361 WN *kids[], PREG_NUM *indices, INT ndim,
03362 WN * block, WN *insert_point)
03363 {
03364 OPCODE reduction_op;
03365 PREG_NUM accum;
03366 WN *sizes[MAX_NDIM];
03367 PREG_NUM new_indices[MAX_NDIM],index,red_index;
03368 INT rank,i,j,dim;
03369 WN *idty_store;
03370 WN *accum_store,*accum_block;
03371 WN *loopnest,*stlist,*mask_expr,*accum_expr,*comp_expr,*red_store;
03372 char tempname[32];
03373 WN *result;
03374 BOOL Mask_Present;
03375 PREG_NUM cur_val;
03376 ST * retval;
03377 TY * retty, *retty_ptr;
03378 TYPE_ID expr_ty;
03379
03380 if (kids[1]) {
03381 dim = F90_Get_Dim(kids[1]);
03382 WN_DELETE_Tree(kids[1]);
03383 } else {
03384 dim = 0;
03385 }
03386
03387 if (!kids[2] || (WN_operator(kids[2]) == OPR_INTCONST &&
03388 WN_const_val(kids[2]) == 1)) {
03389 Mask_Present = FALSE;
03390 } else {
03391 Mask_Present = TRUE;
03392 }
03393
03394
03395 expr_ty = OPCODE_rtype(WN_opcode(kids[0]));
03396 accum = Create_Preg(expr_ty,create_tempname("@f90acc"),NULL);
03397 cur_val = Create_Preg(expr_ty,create_tempname("@f90accval"),NULL);
03398 if (reduction_opr == OPR_MAX) {
03399 reduction_op = OPCODE_make_op(OPR_GT,MTYPE_I4,expr_ty);
03400 } else {
03401 reduction_op = OPCODE_make_op(OPR_LT,MTYPE_I4,expr_ty);
03402 }
03403 idty_store = WN_StidPreg(expr_ty,accum,Make_Reduction_Identity(reduction_opr,expr_ty));
03404
03405 if (dim == 0) {
03406
03407
03408
03409 (void) F90_Size_Walk(kids[0],&rank,sizes);
03410 loopnest = WN_CreateBlock();
03411 stlist = loopnest;
03412
03413 WN_INSERT_BlockBefore(F90_Current_Block,F90_Current_Loopnest,idty_store);
03414
03415
03416 num_temps += 1;
03417 for (i=rank-1; i >=0 ; i--) {
03418 sprintf(tempname,"@f90li_%d_%d",i,num_temps);
03419 loopnest = create_doloop(&index,tempname,sizes[i],DIR_POSITIVE,loopnest);
03420 new_indices[i] = index;
03421 }
03422 WN_INSERT_BlockBefore(F90_Current_Block,F90_Current_Loopnest,loopnest);
03423
03424
03425 F90_Current_Loopnest = idty_store;
03426
03427
03428
03429
03430 retval = New_ST(FALSE);
03431 ST_name(retval) = Save_Str(create_tempname("@f90mmloc"));
03432 ST_class(retval) = CLASS_VAR;
03433 Set_ST_sclass(retval, SCLASS_AUTO);
03434 retty = Make_Array_Type(doloop_ty,1,rank,FALSE);
03435 retty_ptr = Make_Pointer_Type(retty,TY_is_global(retty));
03436 ST_type(retval) = retty;
03437 Set_ST_addr_used_locally(retval);
03438 Enter_ST(retval);
03439
03440
03441 accum_expr = F90_Lower_Walk(kids[0],new_indices,rank,stlist,NULL);
03442 accum_store = WN_StidPreg(expr_ty,cur_val,accum_expr);
03443 WN_INSERT_BlockFirst(stlist,accum_store);
03444
03445 comp_expr = WN_CreateExp2(reduction_op,WN_LdidPreg(expr_ty,cur_val),
03446 WN_LdidPreg(expr_ty,accum));
03447 if (Mask_Present) {
03448 mask_expr = F90_Lower_Walk(kids[2],new_indices,rank,stlist,NULL);
03449 mask_expr = WN_CreateExp2(OPC_LAND,mask_expr,comp_expr);
03450 } else {
03451 mask_expr = comp_expr;
03452 }
03453 accum_block = WN_CreateBlock();
03454 accum_store = WN_StidPreg(expr_ty,accum,WN_LdidPreg(expr_ty,cur_val));
03455 WN_INSERT_BlockLast(accum_block,accum_store);
03456
03457 for (i = 0; i < rank; i++) {
03458
03459
03460 result = WN_Create(OPCODE_make_op(OPR_ARRAY,Pointer_Mtype,MTYPE_V),3);
03461 WN_element_size(result) = Pointer_Size;
03462 WN_kid1(result) = WN_Intconst(MTYPE_I4,rank);
03463 WN_kid2(result) = WN_Intconst(doloop_ty,i);
03464 WN_kid0(result) = WN_Lda(Pointer_type,0,retval);
03465 accum_store = WN_Istore(doloop_ty, (WN_OFFSET) 0, retty_ptr, WN_COPY_Tree(result),
03466 WN_LdidPreg(doloop_ty,new_indices[rank-i-1]));
03467
03468 WN_INSERT_BlockLast(accum_block,accum_store);
03469
03470 accum_store = WN_Istore(doloop_ty, (WN_OFFSET) 0, retty_ptr,result,
03471 WN_Intconst(doloop_ty,-1));
03472 WN_INSERT_BlockBefore(F90_Current_Block,idty_store,accum_store);
03473 }
03474 accum_store = WN_CreateIf(mask_expr,accum_block,WN_CreateBlock());
03475 WN_INSERT_BlockLast(stlist,accum_store);
03476 result = WN_Create(OPCODE_make_op(OPR_ARRAY,Pointer_Mtype,MTYPE_V),3);
03477 WN_element_size(result) = Pointer_Size;
03478 WN_kid1(result) = WN_Intconst(MTYPE_I4,rank);
03479 WN_kid2(result) = WN_LdidPreg(doloop_ty,indices[0]);
03480 WN_kid0(result) = WN_Lda(Pointer_type,0,retval);
03481 result = WN_Iload(doloop_ty,0,retty,result);
03482 result = WN_CreateExp2(OPCODE_make_op(OPR_ADD,doloop_ty,MTYPE_V),result,
03483 WN_Intconst(doloop_ty,1));
03484
03485
03486 } else {
03487
03488
03489
03490 red_index = Create_Preg(doloop_ty,create_tempname("@f90redindex"),NULL);
03491 red_store = WN_StidPreg(doloop_ty,red_index,WN_Intconst(doloop_ty,-1));
03492
03493
03494 (void) F90_Size_Walk(kids[0],&rank,sizes);
03495 loopnest = WN_CreateBlock();
03496 stlist = loopnest;
03497
03498 WN_INSERT_BlockBefore(block,insert_point,idty_store);
03499 WN_INSERT_BlockBefore(block,insert_point,red_store);
03500
03501
03502 num_temps += 1;
03503 dim = ndim + 2 - dim;
03504 sprintf(tempname,"@f90red_%d",num_temps);
03505 loopnest = create_doloop(&index,tempname,sizes[dim-1],DIR_POSITIVE,loopnest);
03506 for (i=0,j=0; i < ndim+1; i++) {
03507 if (i != dim-1) {
03508 WN_DELETE_Tree(sizes[i]);
03509 new_indices[i] = indices[j];
03510 j += 1;
03511 } else {
03512 new_indices[i] = index;
03513 }
03514 }
03515
03516 WN_INSERT_BlockBefore(block,insert_point,loopnest);
03517
03518
03519 accum_expr = F90_Lower_Walk(kids[0],new_indices,rank,stlist,NULL);
03520 accum_store = WN_StidPreg(expr_ty,cur_val,accum_expr);
03521 WN_INSERT_BlockFirst(stlist,accum_store);
03522
03523 comp_expr = WN_CreateExp2(reduction_op,WN_LdidPreg(expr_ty,cur_val),
03524 WN_LdidPreg(expr_ty,accum));
03525 if (Mask_Present) {
03526 mask_expr = F90_Lower_Walk(kids[2],new_indices,rank,stlist,NULL);
03527 mask_expr = WN_CreateExp2(OPC_LAND,mask_expr,comp_expr);
03528 } else {
03529 mask_expr = comp_expr;
03530 }
03531
03532
03533
03534 accum_block = WN_CreateBlock();
03535 accum_store = WN_StidPreg(expr_ty,accum,WN_LdidPreg(expr_ty,cur_val));
03536 WN_INSERT_BlockLast(accum_block,accum_store);
03537
03538
03539 accum_store = WN_CreateExp2(OPCODE_make_op(OPR_ADD,doloop_ty,MTYPE_V),
03540 WN_LdidPreg(doloop_ty,index),
03541 WN_Intconst(doloop_ty,1));
03542 accum_store = WN_StidPreg(doloop_ty,red_index,accum_store);
03543 WN_INSERT_BlockLast(accum_block,accum_store);
03544
03545
03546 accum_store = WN_CreateIf(mask_expr,accum_block,WN_CreateBlock());
03547 WN_INSERT_BlockLast(stlist,accum_store);
03548
03549
03550 result = WN_LdidPreg(doloop_ty,red_index);
03551 }
03552
03553 return (result);
03554 }
03555
03556
03557
03558
03559
03560
03561 static WN * lower_pack(WN *kids[],PREG_NUM *indices,INT ndim,WN *block, WN *insert_point)
03562 {
03563
03564
03565
03566
03567
03568
03569
03570
03571
03572
03573
03574
03575 WN *store;
03576 WN *lhs;
03577 WN *vector, *mask, *array;
03578 WN *sizes[MAX_NDIM];
03579 PREG_NUM new_indices[MAX_NDIM];
03580 INT ndim_array;
03581 PREG_NUM pack_index;
03582 WN *loopnest;
03583 WN *stlist;
03584 WN *temp;
03585 WN *increment;
03586
03587
03588 store = F90_Current_Stmt;
03589 temp = WN_kid0(store);
03590 WN_kid0(store) = WN_Zerocon(MTYPE_I4);
03591 lhs = WN_COPY_Tree(store);
03592 WN_kid0(store) = temp;
03593
03594 vector = F90_Lower_Walk(kids[2],indices,ndim,block,insert_point);
03595
03596
03597 (void) F90_Size_Walk(kids[0],&ndim_array,sizes);
03598 stlist = create_doloop_nest(new_indices,&loopnest,sizes,ndim_array);
03599
03600
03601 pack_index = Create_Preg(doloop_ty,create_tempname("@f90pack"),NULL);
03602
03603
03604 temp = WN_StidPreg(doloop_ty,pack_index,WN_Zerocon(doloop_ty));
03605 WN_INSERT_BlockAfter(F90_Current_Block,F90_Current_Loopnest,loopnest);
03606 WN_INSERT_BlockAfter(F90_Current_Block,F90_Current_Loopnest,temp);
03607
03608
03609 mask = F90_Lower_Walk(kids[1],new_indices,ndim_array,stlist,NULL);
03610 array= F90_Lower_Walk(kids[0],new_indices,ndim_array,stlist,NULL);
03611 (void) F90_Lower_Walk(lhs, &pack_index, 1, stlist, NULL);
03612 WN_Delete(WN_kid0(lhs));
03613 WN_kid0(lhs) = array;
03614
03615
03616 temp = WN_CreateBlock();
03617 WN_INSERT_BlockFirst(temp,lhs);
03618 increment = WN_StidPreg(doloop_ty,pack_index,
03619 WN_CreateExp2(OPCadd,WN_LdidPreg(doloop_ty,pack_index),
03620 WN_Intconst(doloop_ty,1)));
03621 WN_INSERT_BlockLast(temp,increment);
03622 temp = WN_CreateIf(mask,temp,WN_CreateBlock());
03623 WN_INSERT_BlockFirst(stlist,temp);
03624 return (vector);
03625 }
03626
03627 static WN * lower_unpack(WN *kids[],PREG_NUM *indices,INT ndim,WN *block, WN *insert_point)
03628 {
03629 WN *vector, *mask, *field;
03630 PREG_NUM pack_index,p;
03631 WN *if_stmt,*then_block,*else_block;
03632 WN *temp;
03633 WN *increment;
03634 TY *ptr_ty,*temp_ty;
03635 WN *lda;
03636 ST *temp_st;
03637 TYPE_ID type;
03638 WN *true_store;
03639 WN *false_store;
03640 WN *load;
03641
03642
03643 pack_index = Create_Preg(doloop_ty,create_tempname("@f90pack"),NULL);
03644
03645
03646 temp = WN_StidPreg(doloop_ty,pack_index,WN_Zerocon(doloop_ty));
03647 WN_INSERT_BlockBefore(F90_Current_Block,F90_Current_Loopnest,temp);
03648
03649
03650 vector = F90_Lower_Walk(kids[0],&pack_index,1,block,insert_point);
03651 mask = F90_Lower_Walk(kids[1],indices,ndim,block,insert_point);
03652 field = F90_Lower_Walk(kids[2],indices,ndim,block,insert_point);
03653
03654
03655 if (WN_opcode(vector) == OPC_MLOAD) {
03656 ptr_ty = WN_ty(vector);
03657
03658 temp_ty = TY_pointed(ptr_ty);
03659 temp_st = F90_Lower_Create_Temp(NULL,NULL,NULL,0,temp_ty,NULL);
03660 Set_ST_addr_used_locally(temp_st);
03661 lda = WN_Lda(Pointer_type,(WN_OFFSET) 0, temp_st);
03662 true_store = WN_CreateMstore((WN_OFFSET) 0, ptr_ty, vector, WN_COPY_Tree(lda),
03663 WN_COPY_Tree(WN_kid1(vector)));
03664 false_store = WN_CreateMstore((WN_OFFSET) 0, ptr_ty, field, WN_COPY_Tree(lda),
03665 WN_COPY_Tree(WN_kid1(vector)));
03666 load = WN_CreateMload((WN_OFFSET) 0, ptr_ty, lda,WN_COPY_Tree(WN_kid1(vector)));
03667 } else {
03668 type = OPCODE_rtype(WN_opcode(vector));
03669 p = Create_Preg(type,create_tempname("@f90s"),NULL);
03670 true_store = WN_StidPreg(type,p,vector);
03671 false_store = WN_StidPreg(type,p,field);
03672 load = WN_LdidPreg(type,p);
03673 }
03674
03675 then_block = WN_CreateBlock();
03676 else_block = WN_CreateBlock();
03677 WN_INSERT_BlockFirst(then_block,true_store);
03678 increment = WN_StidPreg(doloop_ty,pack_index,
03679 WN_CreateExp2(OPCadd,WN_LdidPreg(doloop_ty,pack_index),
03680 WN_Intconst(doloop_ty,1)));
03681 WN_INSERT_BlockLast(then_block,increment);
03682 WN_INSERT_BlockFirst(else_block,false_store);
03683 if_stmt = WN_CreateIf(mask,then_block,else_block);
03684 WN_INSERT_BlockBefore(block,insert_point,if_stmt);
03685 return (load);
03686 }
03687
03688
03689
03690
03691
03692
03693
03694
03695
03696
03697
03698
03699
03700
03701
03702
03703
03704
03705
03706
03707
03708
03709
03710
03711
03712
03713
03714
03715
03716
03717
03718
03719
03720
03721
03722
03723
03724
03725
03726
03727
03728
03729
03730
03731
03732
03733
03734
03735
03736
03737 static WN *lower_eoshift(WN *kids[],PREG_NUM indices[],INT ndim,WN *block, WN *insert_point)
03738 {
03739 INT dim;
03740 WN *shift;
03741 WN *limit_shift;
03742 WN *boundary;
03743 PREG_NUM new_indices[MAX_NDIM],index,sb_indices[MAX_NDIM];
03744 WN *sizes[MAX_NDIM];
03745 WN *extent;
03746 WN *result;
03747 INT ndim_array;
03748 PREG_NUM shift_index,new_index;
03749 BOOL shift_pos,shift_neg;
03750 char tempname[32];
03751 WN *pos_block;
03752 WN *neg_block;
03753 WN *temp;
03754 WN *setup;
03755 WN *start,*end,*step,*index_id,*body;
03756 WN *lhs;
03757 WN *shift_comp;
03758 PREG_NUM l1,l2,u1,u2;
03759 WN *loopnest,*stlist;
03760 WN *temp_store;
03761 WN * original_loopnest;
03762
03763 INT i,j;
03764
03765 dim = ndim - F90_Get_Dim(kids[3]);
03766 WN_DELETE_Tree(kids[3]);
03767
03768
03769 for (i=0, j=0; i < ndim; i++) {
03770 if (i != dim) {
03771 new_indices[j++] = indices[i];
03772 }
03773 }
03774 shift = kids[1];
03775
03776
03777 (void) F90_Size_Walk(kids[0],&ndim_array,sizes);
03778 extent = sizes[dim];
03779
03780
03781 if (WN_operator(shift)==OPR_INTCONST) {
03782 if (WN_const_val(shift) == 0) {
03783 WN_DELETE_Tree(shift);
03784 WN_DELETE_Tree(kids[2]);
03785 for (i=0 ; i <ndim; i++) {
03786 WN_DELETE_Tree(sizes[i]);
03787 }
03788 result = F90_Lower_Walk(kids[0],indices,ndim,block,insert_point);
03789 return (result);
03790 } else if (WN_operator(extent) == OPR_INTCONST) {
03791 if (WN_const_val(shift) >= WN_const_val(extent) ||
03792 -WN_const_val(shift) >= WN_const_val(extent)) {
03793 WN_DELETE_Tree(kids[0]);
03794 WN_DELETE_Tree(shift);
03795 for (i=0 ; i <ndim; i++) {
03796 WN_DELETE_Tree(sizes[i]);
03797 }
03798 boundary = F90_Lower_Walk(kids[2],new_indices,ndim-1,block,insert_point);
03799 return (boundary);
03800 }
03801 }
03802 }
03803
03804
03805
03806
03807
03808 temp_store = F90_Current_Stmt;
03809 WN_EXTRACT_FromBlock(block,temp_store);
03810 original_loopnest = F90_Current_Loopnest;
03811
03812 num_temps += 1;
03813 loopnest = WN_CreateBlock();
03814 stlist = loopnest;
03815 if (ndim > 1) {
03816 for (i=ndim-1,j=ndim-2; i >=0 ; i--) {
03817 if (i != dim) {
03818 sprintf(tempname,"@f90li_%d_%d",i,num_temps);
03819 loopnest = create_doloop(&index,tempname,sizes[i],DIR_POSITIVE,loopnest);
03820 sb_indices[j--] = index;
03821 new_indices[i] = index;
03822 }
03823 }
03824 WN_INSERT_BlockBefore(F90_Current_Block,F90_Current_Loopnest,loopnest);
03825 F90_Current_Loopnest = loopnest;
03826 }
03827
03828
03829 boundary = F90_Lower_Walk(kids[2],sb_indices,ndim-1,block,insert_point);
03830 shift = F90_Lower_Walk(kids[1],sb_indices,ndim-1,block,insert_point);
03831
03832
03833 l1 = Create_Preg(doloop_ty,create_tempname("@f90_eos_l1"),NULL);
03834 u1 = Create_Preg(doloop_ty,create_tempname("@f90_eos_u1"),NULL);
03835 l2 = Create_Preg(doloop_ty,create_tempname("@f90_eos_l2"),NULL);
03836 u2 = Create_Preg(doloop_ty,create_tempname("@f90_eos_u2"),NULL);
03837
03838 shift_comp = WN_CreateExp2(OPCODE_make_op(OPR_GT,MTYPE_I4,doloop_ty),
03839 WN_COPY_Tree(shift),
03840 WN_Intconst(doloop_ty,0));
03841 if (WN_operator(shift_comp) == OPR_INTCONST) {
03842 if (WN_const_val(shift_comp) == 0) {
03843 shift_neg = TRUE;
03844 shift_pos = FALSE;
03845 } else {
03846 shift_neg = FALSE;
03847 shift_pos = TRUE;
03848 }
03849 WN_DELETE_Tree(shift_comp);
03850 } else {
03851 shift_neg = TRUE;
03852 shift_pos = TRUE;
03853 }
03854
03855
03856 if (shift_pos) {
03857
03858
03859
03860
03861
03862
03863 pos_block = WN_CreateBlock();
03864 temp = WN_StidPreg(doloop_ty,l1,WN_Intconst(doloop_ty,0));
03865 WN_INSERT_BlockLast(pos_block,temp);
03866
03867 limit_shift = WN_CreateExp2(OPCODE_make_op(OPR_MIN,doloop_ty,MTYPE_V),
03868 WN_COPY_Tree(sizes[dim]),WN_COPY_Tree(shift));
03869
03870 temp = WN_StidPreg(doloop_ty,u2,
03871 WN_CreateExp2(OPCsub,WN_COPY_Tree(sizes[dim]),
03872 WN_Intconst(doloop_ty,1)));
03873 WN_INSERT_BlockLast(pos_block,temp);
03874
03875 temp = WN_StidPreg(doloop_ty,u1,WN_CreateExp2(OPCsub,
03876 WN_LdidPreg(doloop_ty,u2),
03877 limit_shift));
03878 WN_INSERT_BlockLast(pos_block,temp);
03879
03880 temp = WN_StidPreg(doloop_ty,l2,WN_CreateExp2(OPCadd,
03881 WN_LdidPreg(doloop_ty,u1),
03882 WN_Intconst(doloop_ty,1)));
03883 WN_INSERT_BlockLast(pos_block,temp);
03884 setup = pos_block;
03885 }
03886
03887 if (shift_neg) {
03888
03889
03890
03891
03892
03893
03894 neg_block = WN_CreateBlock();
03895 temp = WN_StidPreg(doloop_ty,l2,WN_Intconst(doloop_ty,0));
03896 WN_INSERT_BlockLast(neg_block,temp);
03897
03898 limit_shift = WN_CreateExp1(OPCODE_make_op(OPR_NEG,doloop_ty,MTYPE_V),
03899 WN_COPY_Tree(shift));
03900 limit_shift = WN_CreateExp2(OPCODE_make_op(OPR_MIN,doloop_ty,MTYPE_V),
03901 WN_COPY_Tree(sizes[dim]),limit_shift);
03902
03903 temp = WN_StidPreg(doloop_ty,u1,
03904 WN_CreateExp2(OPCsub,WN_COPY_Tree(sizes[dim]),
03905 WN_Intconst(doloop_ty,1)));
03906 WN_INSERT_BlockLast(neg_block,temp);
03907
03908 temp = WN_StidPreg(doloop_ty,l1,limit_shift);
03909
03910 WN_INSERT_BlockLast(neg_block,temp);
03911
03912 temp = WN_StidPreg(doloop_ty,u2,WN_CreateExp2(OPCsub,
03913 WN_LdidPreg(doloop_ty,l1),
03914 WN_Intconst(doloop_ty,1)));
03915 WN_INSERT_BlockLast(neg_block,temp);
03916 setup = neg_block;
03917 }
03918
03919 if (shift_pos && shift_neg) {
03920 setup = WN_CreateIf(shift_comp, pos_block, neg_block);
03921 }
03922
03923
03924 WN_INSERT_BlockFirst(stlist,setup);
03925
03926 new_index = Create_Preg(doloop_ty,create_tempname("@f90_eos_idx"),NULL);
03927 shift_index = Create_Preg(doloop_ty,create_tempname("@f90_eos_shft"),NULL);
03928
03929
03930 start = WN_StidPreg(doloop_ty,new_index,WN_LdidPreg(doloop_ty,l1));
03931 end = WN_CreateExp2(OPCODE_make_op(OPR_LE,MTYPE_I4,doloop_ty),
03932 WN_LdidPreg(doloop_ty,new_index),
03933 WN_LdidPreg(doloop_ty,u1));
03934 step = WN_StidPreg(doloop_ty,new_index,
03935 WN_CreateExp2(OPCadd,WN_LdidPreg(doloop_ty,new_index),
03936 WN_Intconst(doloop_ty,1)));
03937 index_id = WN_CreateIdname(new_index,MTYPE_To_PREG(doloop_ty));
03938
03939
03940 body = WN_CreateBlock();
03941 temp = WN_CreateDO(index_id, start, end, step, body, NULL);
03942 WN_INSERT_BlockLast(stlist,temp);
03943
03944 temp = WN_StidPreg(doloop_ty,shift_index,WN_CreateExp2(OPCadd,
03945 WN_LdidPreg(doloop_ty,new_index),
03946 shift));
03947 WN_INSERT_BlockFirst(body,temp);
03948
03949
03950
03951
03952
03953 WN_kid0(temp_store) = WN_Intconst(doloop_ty,0);
03954 lhs = WN_COPY_Tree(temp_store);
03955 WN_DELETE_Tree(WN_kid0(temp_store));
03956 WN_DELETE_Tree(WN_kid0(lhs));
03957
03958 WN_INSERT_BlockLast(body,temp_store);
03959 new_indices[dim] = shift_index;
03960 temp = F90_Lower_Walk(kids[0],new_indices,ndim,body,temp_store);
03961 WN_kid0(temp_store) = temp;
03962 new_indices[dim] = new_index;
03963 temp = F90_Lower_Walk(WN_kid1(temp_store),new_indices,ndim,body,temp_store);
03964
03965 WN_kid1(temp_store) = temp;
03966 WN_kid1(lhs) = WN_COPY_Tree(temp);
03967 WN_kid0(lhs) = boundary;
03968
03969
03970 start = WN_StidPreg(doloop_ty,new_index,WN_LdidPreg(doloop_ty,l2));
03971 end = WN_CreateExp2(OPCODE_make_op(OPR_LE,MTYPE_I4,doloop_ty),
03972 WN_LdidPreg(doloop_ty,new_index),
03973 WN_LdidPreg(doloop_ty,u2));
03974 step = WN_StidPreg(doloop_ty,new_index,
03975 WN_CreateExp2(OPCadd,WN_LdidPreg(doloop_ty,new_index),
03976 WN_Intconst(doloop_ty,1)));
03977
03978 body = WN_CreateBlock();
03979 temp = WN_CreateDO(WN_COPY_Tree(index_id), start, end, step, body, NULL);
03980 WN_INSERT_BlockLast(stlist,temp);
03981 WN_INSERT_BlockLast(body,lhs);
03982
03983
03984
03985 if (ndim == 1) {
03986 WN_INSERT_BlockBefore(F90_Current_Block,F90_Current_Loopnest,stlist);
03987 }
03988
03989
03990 WN_EXTRACT_FromBlock(F90_Current_Block,original_loopnest);
03991 WN_DELETE_Tree(original_loopnest);
03992
03993 return (NULL);
03994 }
03995
03996
03997 static WN *lower_cshift(WN *kids[],PREG_NUM indices[],INT ndim,WN *block, WN *insert_point)
03998 {
03999 INT dim;
04000 WN *shift;
04001 PREG_NUM new_indices[MAX_NDIM];
04002 WN *sizes[MAX_NDIM];
04003 WN *extent;
04004 WN *store;
04005 WN *result;
04006 INT ndim_array;
04007 PREG_NUM shifted_index,shift_preg;
04008
04009 INT i,j;
04010
04011 dim = ndim - F90_Get_Dim(kids[2]);
04012 WN_DELETE_Tree(kids[2]);
04013
04014
04015 for (i=0, j=0; i < ndim; i++) {
04016 if (i != dim) {
04017 new_indices[j++] = indices[i];
04018 }
04019 }
04020 shift = F90_Lower_Walk(kids[1],new_indices,ndim-1,block,insert_point);
04021
04022
04023 (void) F90_Size_Walk(kids[0],&ndim_array,sizes);
04024 for (i=0; i < ndim; i++) {
04025 if (i != dim) {
04026 new_indices[i] = indices[i];
04027 WN_DELETE_Tree(sizes[i]);
04028 } else {
04029 extent = sizes[i];
04030 }
04031 }
04032 shift = WN_CreateExp2(OPCmod,shift,WN_COPY_Tree(extent));
04033
04034
04035 if (WN_operator(shift)==OPR_INTCONST && WN_const_val(shift) == 0) {
04036 WN_DELETE_Tree(shift);
04037 WN_DELETE_Tree(extent);
04038 new_indices[dim] = indices[dim];
04039 } else {
04040 shifted_index = Create_Preg(doloop_ty,create_tempname("@f90cshift"),NULL);
04041 shift_preg = Create_Preg(doloop_ty,create_tempname("@f90cshiftp"),NULL);
04042 new_indices[dim] = shifted_index;
04043
04044
04045 store = WN_StidPreg(doloop_ty,shift_preg,
04046 WN_CreateExp2(OPCadd,WN_LdidPreg(doloop_ty,indices[dim]),shift));
04047 WN_INSERT_BlockBefore(block,insert_point,store);
04048
04049 store = WN_CreateExp3(OPCODE_make_op(OPR_SELECT,doloop_ty,MTYPE_V),
04050 WN_CreateExp2(OPCODE_make_op(OPR_GE,MTYPE_I4,doloop_ty),
04051 WN_LdidPreg(doloop_ty,shift_preg),
04052 WN_COPY_Tree(extent)),
04053 extent,
04054 WN_Intconst(doloop_ty,0));
04055 store = WN_CreateExp2(OPCsub,WN_LdidPreg(doloop_ty,shift_preg),store);
04056 store = WN_StidPreg(doloop_ty,shifted_index,store);
04057 WN_INSERT_BlockBefore(block,insert_point,store);
04058 }
04059
04060 result = F90_Lower_Walk(kids[0],new_indices,ndim,block,insert_point);
04061 return (result);
04062 }
04063
04064
04065
04066
04067
04068
04069
04070
04071
04072
04073
04074 static WN * lower_transformationals(WN *expr, PREG_NUM *indices, INT ndim, WN * block, WN *insert_point)
04075 {
04076 WN *result;
04077 WN *kids[6];
04078 WN *kid;
04079 INT dim;
04080 TYPE_ID ty;
04081 INTRINSIC intrin;
04082 INT numargs,i,j;
04083 PREG_NUM new_indices[MAX_NDIM];
04084
04085 numargs = WN_kid_count(expr);
04086 ty = OPCODE_rtype(WN_opcode(expr));
04087 intrin = WN_GET_INTRINSIC(expr);
04088
04089
04090 for (i=0 ; i < numargs; i++) {
04091 kid = WN_kid(expr,i);
04092 if (WN_kid_count(kid) == 0 || WN_opcode(kid) == OPC_VPARM) {
04093 kids[i] = NULL;
04094 WN_Delete(kid);
04095 } else if (WN_operator(kid) == OPR_PARM) {
04096 kids[i] = WN_kid0(kid);
04097 WN_Delete(kid);
04098 } else {
04099 kids[i] = kid;
04100 }
04101 }
04102 WN_Delete(expr);
04103
04104 switch (intrin) {
04105 case INTRN_RESHAPE:
04106 case INTRN_MATMUL:
04107 case INTRN_DOT_PRODUCT:
04108 case INTRN_COUNT:
04109 DevAssert((0),("Intrinsic should not get inlined"));
04110 break;
04111
04112 case INTRN_SPREAD:
04113 dim = ndim - WN_const_val(kids[1]);
04114 for (i=0,j=0; i < ndim; i++) {
04115 if (dim != i) {
04116 new_indices[j++] = indices[i];
04117 }
04118 }
04119 WN_DELETE_Tree(kids[1]);
04120 WN_DELETE_Tree(kids[2]);
04121 result = F90_Lower_Walk(kids[0],new_indices,ndim-1, block,insert_point);
04122 break;
04123
04124
04125 case INTRN_TRANSPOSE:
04126 new_indices[0] = indices[1];
04127 new_indices[1] = indices[0];
04128 result = F90_Lower_Walk(kids[0],new_indices,2, block,insert_point);
04129 break;
04130
04131
04132 case INTRN_ALL:
04133 kids[2] = NULL;
04134 result = lower_reduction(MTYPE_I4,OPR_LAND,kids,indices,ndim,block,insert_point);
04135 break;
04136 case INTRN_ANY:
04137 kids[2] = NULL;
04138 result = lower_reduction(MTYPE_I4,OPR_LIOR,kids,indices,ndim,block,insert_point);
04139 break;
04140 case INTRN_PRODUCT:
04141 result = lower_reduction(ty,OPR_MPY,kids,indices,ndim,block,insert_point);
04142 break;
04143 case INTRN_SUM:
04144 result = lower_reduction(ty,OPR_ADD,kids,indices,ndim,block,insert_point);
04145 break;
04146 case INTRN_MAXVAL:
04147 result = lower_reduction(ty,OPR_MAX,kids,indices,ndim,block,insert_point);
04148 break;
04149 case INTRN_MINVAL:
04150 result = lower_reduction(ty,OPR_MIN,kids,indices,ndim,block,insert_point);
04151 break;
04152
04153 case INTRN_PACK:
04154 result = lower_pack(kids,indices,ndim,block,insert_point);
04155 break;
04156
04157 case INTRN_UNPACK:
04158 result = lower_unpack(kids,indices,ndim,block,insert_point);
04159 break;
04160
04161 case INTRN_MAXLOC:
04162 result = lower_maxminloc(OPR_MAX,kids,indices,ndim,block,insert_point);
04163 break;
04164
04165 case INTRN_MINLOC:
04166 result = lower_maxminloc(OPR_MIN,kids,indices,ndim,block,insert_point);
04167 break;
04168
04169 case INTRN_CSHIFT:
04170 result = lower_cshift(kids,indices,ndim,block,insert_point);
04171 break;
04172
04173 case INTRN_EOSHIFT:
04174 result = lower_eoshift(kids,indices,ndim,block,insert_point);
04175 break;
04176
04177 default:
04178 DevAssert((0),("Unknown intrinsic in lower_transformationals"));
04179 }
04180
04181 return (result);
04182 }
04183
04184
04185
04186
04187
04188
04189
04190 static WN * strip_mloads(WN *w)
04191 {
04192 WN *kid;
04193 while (WN_opcode(w) == OPC_MLOAD) {
04194 kid = WN_kid0(w);
04195 WN_DELETE_Tree(WN_kid1(w));
04196 WN_Delete(w);
04197 w = kid;
04198 }
04199 return (w);
04200 }
04201
04202
04203
04204
04205
04206
04207
04208
04209
04210
04211
04212
04213
04214
04215
04216
04217
04218
04219
04220
04221
04222
04223 static WN * F90_Lower_Walk(WN *expr, PREG_NUM *indices, INT ndim, WN * block, WN *insert_point)
04224 {
04225 OPCODE op,kidop;
04226 OPERATOR opr,kidopr;
04227 WN *kid,*kid1;
04228 WN *result;
04229 INT numkids,array_ndim,i,j;
04230 BOOL do_kids = FALSE;
04231 TYPE_ID ty;
04232 WN * index_ldid;
04233 INTRINSIC intr;
04234
04235 op = WN_opcode(expr);
04236 opr = OPCODE_operator(op);
04237 numkids = WN_kid_count(expr);
04238 result = expr;
04239
04240 switch (opr) {
04241 case OPR_BLOCK:
04242 kid = WN_first(expr);
04243 while (kid) {
04244 F90_Lower_Walk(kid,indices,ndim,block,insert_point);
04245 kid = WN_next(kid);
04246 }
04247 break;
04248
04249 case OPR_ARRAYEXP:
04250
04251 for (i=1; i<numkids; i++) {
04252 WN_DELETE_Tree(WN_kid(expr,i));
04253 }
04254 kid = WN_kid0(expr);
04255 WN_Delete(expr);
04256 result = F90_Lower_Walk(kid,indices,ndim,block,insert_point);
04257 break;
04258
04259 case OPR_ARRSECTION:
04260
04261 WN_set_opcode(result,OPCODE_make_op(OPR_ARRAY,OPCODE_rtype(op),MTYPE_V));
04262
04263
04264 array_ndim = (numkids - 1) / 2;
04265 j = 0;
04266 for (i=array_ndim+1; i < numkids; i++) {
04267 kid = WN_kid(expr,i);
04268 kidop = WN_opcode(kid);
04269 kidopr = OPCODE_operator(kidop);
04270 if (kidopr == OPR_ARRAYEXP || kidopr == OPR_TRIPLET) {
04271
04272 kid = F90_Lower_Walk(kid,&indices[j],1,block,insert_point);
04273 j += 1;
04274 WN_kid(expr,i) = kid;
04275 }
04276 }
04277 break;
04278
04279 case OPR_TRIPLET:
04280
04281 FmtAssert((ndim==1),("F90_Lower_Walk: trying to lower a triplet with ndim != 1"));
04282 WN_DELETE_Tree(WN_kid2(expr));
04283 kid = F90_Lower_Walk(WN_kid0(expr),NULL,0,block,insert_point);
04284 kid1 = F90_Lower_Walk(WN_kid1(expr),NULL,0,block,insert_point);
04285 ty = doloop_ty;
04286 index_ldid = WN_LdidPreg(ty,indices[0]);
04287 result = WN_CreateExp2(OPCODE_make_op(OPR_ADD,ty,MTYPE_V),
04288 kid,
04289 WN_CreateExp2(OPCODE_make_op(OPR_MPY,ty,MTYPE_V),
04290 index_ldid,
04291 kid1));
04292 break;
04293
04294 case OPR_WHERE:
04295
04296 WN_set_opcode(result,OPC_IF);
04297 do_kids = TRUE;
04298 break;
04299
04300 case OPR_MLOAD:
04301
04302 kid = F90_Lower_Walk(WN_kid0(expr),indices,ndim,block,insert_point);
04303 WN_kid0(expr) = strip_mloads(kid);
04304 kid = F90_Lower_Walk(WN_kid1(expr),indices,ndim,block,insert_point);
04305 WN_kid1(expr) = kid;
04306 do_kids = FALSE;
04307 break;
04308
04309 case OPR_INTRINSIC_CALL:
04310 case OPR_INTRINSIC_OP:
04311 intr = WN_GET_INTRINSIC(expr);
04312 if (F90_Is_Transformational(intr)) {
04313 result = lower_transformationals(expr,indices, ndim, block, insert_point);
04314 do_kids = FALSE;
04315 } else if (F90_Is_Char_Intrinsic(intr)) {
04316 for (i=0; i < numkids; i++) {
04317 kid = WN_kid0(WN_kid(expr,i));
04318 kid = F90_Lower_Walk(kid,indices,ndim,block,insert_point);
04319 WN_kid0(WN_kid(expr,i)) = strip_mloads(kid);
04320 }
04321 do_kids = FALSE;
04322 } else {
04323 do_kids = TRUE;
04324 }
04325 break;
04326
04327 default:
04328
04329 do_kids = TRUE;
04330 break;
04331 }
04332
04333 if (do_kids) {
04334 for (i=0; i < numkids; i++) {
04335 kid = WN_kid(expr,i);
04336 kid = F90_Lower_Walk(kid,indices,ndim,block,insert_point);
04337 if (kid) {
04338 WN_kid(expr,i) = kid;
04339 }
04340 }
04341 }
04342
04343 return (result);
04344 }
04345
04346
04347
04348
04349
04350
04351
04352
04353
04354
04355 static BOOL F90_Generate_Loops(WN *stmt, WN *block)
04356 {
04357 F90_LOWER_AUX_DATA *adata;
04358 INT ndim;
04359 PREG_NUM indices[MAX_NDIM];
04360 PREG_NUM index;
04361 INT i;
04362 INT perm;
04363 DIR_FLAG dir;
04364 WN *count;
04365 WN *loopnest,*stlist;
04366 char tempname[32];
04367
04368
04369
04370 if (WN_operator(stmt) == OPR_IO) {
04371 return(TRUE);
04372 }
04373
04374 adata = GET_F90_MAP(stmt);
04375 if (adata) {
04376 ndim = NDIM(adata);
04377 } else {
04378 ndim = 0;
04379 }
04380
04381 if (ndim > 0) {
04382
04383 loopnest = WN_CreateBlock();
04384 stlist = loopnest;
04385 num_temps += 1;
04386 for (i=ndim-1; i >= 0; i--) {
04387 perm = PERM_INDEX(adata,i);
04388 count = ITER_COUNT(adata,perm);
04389 dir = DIRECTION(adata,perm);
04390 sprintf(tempname,"@f90li_%d_%d",i,num_temps);
04391
04392
04393 loopnest = create_doloop(&index,tempname,count,dir,loopnest);
04394 indices[i] = index;
04395 }
04396
04397
04398
04399 WN_INSERT_BlockBefore(block,stmt,loopnest);
04400 (void) WN_EXTRACT_FromBlock(block,stmt);
04401 WN_INSERT_BlockFirst(stlist,stmt);
04402
04403
04404 F90_Current_Stmt = stmt;
04405 F90_Current_Loopnest = loopnest;
04406 } else {
04407
04408 F90_Current_Stmt = stmt;
04409 F90_Current_Loopnest = stmt;
04410 stlist = block;
04411 }
04412 F90_Current_Block = block;
04413 stmt = F90_Lower_Walk(stmt,indices,ndim,stlist,stmt);
04414
04415 return (TRUE);
04416 }
04417
04418
04419
04420
04421
04422
04423
04424
04425
04426
04427
04428
04429
04430 #define TRACE_AFTER(x,y) if (Get_Trace(TP_LOWER90,x)) {\
04431 fprintf(TFile,"\n\n========== Dump after %s ==========\n",y); fdump_tree(TFile,pu);}
04432
04433 #ifdef Is_True_On
04434 #define DUPCHECK 1
04435 #else
04436 #undef DUPCHECK
04437 #endif
04438
04439 #ifdef DUPCHECK
04440 #define SET_P_MAP(x,t) WN_MAP_Set(f90_parent_map,(x),(void *) (t))
04441 #define GET_P_MAP(x) ((WN *) WN_MAP_Get(f90_parent_map,(x)))
04442
04443 static void check_for_duplicates(WN *pu,char *str)
04444 {
04445
04446 static WN_MAP f90_parent_map;
04447 WN_ITER *ti;
04448 WN *w, *k, *p;
04449 INT i;
04450 BOOL found_dup = FALSE;
04451
04452 f90_parent_map = WN_MAP_Create(f90_lower_pool);
04453
04454
04455 ti = WN_WALK_TreeIter(pu);
04456 while (ti) {
04457 w = WN_ITER_wn(ti);
04458
04459 for (i=0; i < WN_kid_count(w) ; i++) {
04460 k = WN_kid(w,i);
04461 p = GET_P_MAP(k);
04462 if ((p != NULL) && (p != w)) {
04463 fprintf(TFile,"\n%s: Multiparented node p=%08x, w=%08x, k=%d\n",str,p,w,i);
04464 fprintf(TFile,"parent:\n"); fdump_tree(TFile,p);
04465 fprintf(TFile,"current:\n"); fdump_tree(TFile,w);
04466 fprintf(TFile,"multichild:\n"); fdump_tree(TFile,k);
04467 found_dup = TRUE;
04468 } else {
04469 SET_P_MAP(k,w);
04470 }
04471 }
04472 ti = WN_WALK_TreeNext(ti);
04473 }
04474 WN_MAP_Delete(f90_parent_map);
04475 if (found_dup) {
04476 DevWarn(("Duplicate WHIRL nodes found %s\n"),str);
04477 }
04478 }
04479 #endif
04480
04481
04482
04483
04484
04485
04486
04487
04488
04489
04490
04491
04492
04493 WN * F90_Lower (WN *pu) {
04494
04495 if (!(SYMTAB_src_lang(Current_Symtab) & SYMTAB_F90_LANG)) return (pu);
04496
04497 F90_Lower_Init();
04498
04499 trace_dependence = Get_Trace(TP_LOWER90,TRACE_DEPENDENCE_ANALYSIS);
04500 trace_depinfo = Get_Trace(TP_LOWER90,TRACE_DEPINFO);
04501
04502 if (Get_Trace ( TKIND_IR, TP_LOWER90 )) {
04503 fprintf(TFile,"\n\n========== Dump before F90 Lowering ==========\n");
04504 fdump_tree(TFile,pu);
04505 }
04506
04507 #ifdef DUPCHECK
04508 check_for_duplicates(pu,"before");
04509 #endif
04510
04511
04512 F90_Walk_All_Statements(pu,F90_Scalarize_Triplets_And_Sizes);
04513
04514
04515
04516
04517
04518
04519 F90_Analyze_Dependencies(pu);
04520
04521 if (array_statement_seen) {
04522 TRACE_AFTER(TRACE_DEPENDENCE,"Dependence Analysis");
04523
04524
04525 F90_Walk_Statements(pu,F90_Do_Copies);
04526 TRACE_AFTER(TRACE_COPIES,"Copy motion");
04527
04528
04529 F90_Walk_Statements(pu, F90_Move_Transformationals);
04530 TRACE_AFTER(TRACE_TRANSFORMATIONALS,"Transformational motion");
04531
04532 F90_Walk_All_Statements(pu, F90_Insert_All_Prelists);
04533 TRACE_AFTER(TRACE_INSERTIONS,"Extra statement insertions");
04534
04535
04536 if (temp_allocations_inserted) {
04537 F90_Walk_All_Statements(pu, F90_Insert_Temp_Allocations);
04538 temp_allocations_inserted = FALSE;
04539 }
04540
04541
04542 F90_Walk_Statements(pu,F90_Generate_Loops);
04543 if (temp_allocations_inserted) {
04544 F90_Walk_All_Statements(pu, F90_Insert_Temp_Allocations);
04545 temp_allocations_inserted = FALSE;
04546 }
04547 TRACE_AFTER(TRACE_DOLOOPS,"Do loop creation");
04548 }
04549
04550
04551
04552 F90_Walk_All_Statements(pu,F90_Lower_Intrinsic_Fixup);
04553
04554
04555
04556 F90_Walk_Statements(pu,F90_Lower_Alloc_Dealloc);
04557
04558 #ifdef DUPCHECK
04559 check_for_duplicates(pu,"after");
04560 #endif
04561
04562 if (Get_Trace ( TKIND_IR, TP_LOWER90 )) {
04563 fprintf(TFile,"\n\n========== Dump after F90 Lowering ==========\n");
04564 fdump_tree(TFile,pu);
04565 }
04566 if (Get_Trace(TKIND_SYMTAB,TP_LOWER90)) {
04567 fprintf(TFile,"\n\n========== Symbol tables after F90 Lowering ==========\n");
04568 Trace_SYMTAB (TFile, Global_Symtab, TRUE);
04569 Trace_SYMTAB (TFile, Current_Symtab, TRUE);
04570 }
04571
04572 F90_Lower_Term();
04573
04574 return (pu);
04575 }
04576