00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #define __STDC_LIMIT_MACROS
00043 #include <stdint.h>
00044 #ifdef USE_PCH
00045 #include "lno_pch.h"
00046 #endif // USE_PCH
00047 #pragma hdrstop
00048
00049 #ifdef _KEEP_RCS_ID
00050 static char *rcs_id = "$Source: /home/bos/bk/kpro64-pending/be/lno/SCCS/s.fiz_fuse.cxx $ $Revision: 1.8 $";
00051 #endif
00052
00053 #include <sys/types.h>
00054 #include <limits.h>
00055 #include "pu_info.h"
00056 #include "lnoutils.h"
00057 #include "defs.h"
00058 #include "stab.h"
00059 #include "fission.h"
00060 #include "fusion.h"
00061 #include "fiz_fuse.h"
00062 #include "lwn_util.h"
00063 #include "wn_map.h"
00064 #include "ff_utils.h"
00065 #include "lnopt_main.h"
00066 #include "glob.h"
00067 #include "tlog.h"
00068 #include "whirl2src.h"
00069 #include "parallel.h"
00070 #include "prompf.h"
00071
00072
00073 typedef HASH_TABLE<WN*,INT> WN2INT;
00074 typedef enum { INFO, FAIL, SUCCEED } INFO_TYPE;
00075
00076 static void fiz_fuse_analysis_info(
00077 INFO_TYPE info_type,
00078 SRCPOS srcpos1,
00079 SRCPOS srcpos2,
00080 UINT32 level,
00081 const char* message)
00082 {
00083 switch (info_type) {
00084 case INFO:
00085 fprintf(LNO_Analysis,"( LNO_Fiz_Fuse_Info ");
00086 break;
00087 case FAIL:
00088 fprintf(LNO_Analysis,"( LNO_Fiz_Fuse_Failure ");
00089 break;
00090 case SUCCEED:
00091 fprintf(LNO_Analysis,"( LNO_Fiz_Fuse_Success ");
00092 break;
00093 }
00094
00095 fprintf(LNO_Analysis,"(%s %d) (%s %d) %d \"%s\")\n",
00096 Cur_PU_Name, Srcpos_To_Line(srcpos1),
00097 Cur_PU_Name, Srcpos_To_Line(srcpos2),
00098 level, message);
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109 }
00110
00111 static void fiz_fuse_tlog_info(
00112 INFO_TYPE info_type,
00113 SRCPOS srcpos1,
00114 SRCPOS srcpos2,
00115 UINT32 level,
00116 const char* message)
00117 {
00118 char tmp_string[300];
00119 sprintf(tmp_string,"%d %d %d %d",
00120 info_type, Srcpos_To_Line(srcpos1), Srcpos_To_Line(srcpos2),
00121 level);
00122 Generate_Tlog("LNO","fiz_fuse", Srcpos_To_Line(srcpos1), "",
00123 tmp_string, "", message);
00124 }
00125
00126 SNL_INFO::SNL_INFO(WN* loop) {
00127 _type=Invalid; _wn=loop; _depth=0;
00128 OPCODE opc=WN_opcode(loop);
00129 if (opc==OPC_DO_LOOP) {
00130 WN* last_loop=NULL;
00131 while (loop && (Do_Loop_Is_Good(loop) && !Do_Loop_Has_Exits(loop))) {
00132 _depth++;
00133 last_loop=loop;
00134 loop=Get_Only_Loop_Inside(loop,FALSE);
00135 }
00136 if (last_loop)
00137 if (Do_Loop_Is_Inner(last_loop))
00138 _type=Inner;
00139 else
00140 _type=Not_Inner;
00141 else
00142 _type=Non_SNL;
00143 } else if (opc==OPC_IF || opc==OPC_WHILE_DO || opc==OPC_DO_WHILE ||
00144 OPCODE_is_non_scf(opc) || opc==OPC_LABEL) {
00145 _type=Non_SNL;
00146 }
00147 }
00148
00149 void FIZ_FUSE_INFO::Print(INT i, FILE* fp) {
00150
00151 if (_snl_info[i]._type==Invalid)
00152 return;
00153 if (WN_opcode(_snl_info[i]._wn)==OPC_IF)
00154 fprintf(fp,"Print FIZ_FUSE_INFO for SNL %3d : is a IF structure\n", i);
00155 else if (WN_opcode(_snl_info[i]._wn)==OPC_REGION)
00156 fprintf(fp,
00157 "Print FIZ_FUSE_INFO for SNL %3d : is a REGION structure\n", i);
00158 else if (WN_opcode(_snl_info[i]._wn)==OPC_DO_WHILE)
00159 fprintf(fp,
00160 "Print FIZ_FUSE_INFO for SNL %3d : is a DO WHILE structure\n", i);
00161 else if (WN_opcode(_snl_info[i]._wn)==OPC_WHILE_DO)
00162 fprintf(fp,
00163 "Print FIZ_FUSE_INFO for SNL %3d : is a WHILE DO structure\n", i);
00164 else {
00165
00166 ST *st;
00167 const char* name;
00168 st=WN_st(WN_index(_snl_info[i]._wn));
00169 if (ST_class(st) == CLASS_PREG)
00170 name=Preg_Name(WN_offset(WN_index(_snl_info[i]._wn)));
00171 else
00172 name=ST_name(st);
00173
00174 fprintf(fp,"Print FIZ_FUSE_INFO for SNL %3d (%s): Depth %3d, Type %2d\n",
00175 i,name,_snl_info[i]._depth, _snl_info[i]._type);
00176 WN* loop=_snl_info[i]._wn;
00177 WN* func_nd=LWN_Get_Parent(loop);
00178 while (func_nd && WN_opcode(func_nd)!=OPC_FUNC_ENTRY)
00179 func_nd=LWN_Get_Parent(func_nd);
00180 Is_True(func_nd,("SNL loops not in a function?"));
00181 Whirl2Src_Init(func_nd);
00182 char indent[80];
00183 indent[0]='\0';
00184 for (INT j=0; j<_snl_info[i]._depth; j++) {
00185
00186 st=WN_st(WN_index(loop));
00187 if (ST_class(st) == CLASS_PREG)
00188 name=Preg_Name(WN_offset(WN_index(loop)));
00189 else
00190 name=ST_name(st);
00191
00192 fprintf(fp,"Line %5d %sDO %s=",
00193 Srcpos_To_Line(WN_Get_Linenum(loop)), indent, name);
00194 indent[j*2]=' ';
00195 indent[j*2+1]=' ';
00196 indent[j*2+2]='\0';
00197 Whirl2Src_Emit(fp,WN_kid0(WN_start(loop)));
00198 fprintf(fp,",");
00199 Whirl2Src_Emit(fp,WN_end(loop));
00200 fprintf(fp,",");
00201 Whirl2Src_Emit(fp,WN_kid1(WN_kid0(WN_step(loop))));
00202 fprintf(fp,"\n");
00203 loop=Get_Only_Loop_Inside(loop,FALSE);
00204 }
00205 }
00206 }
00207
00208 void FIZ_FUSE_INFO::Check() {
00209 INT total_snl=_snl_info.Elements();
00210 WN2INT *snl_info_table=CXX_NEW(WN2INT(total_snl*5,_mpool),_mpool);
00211 for (INT i=0; i<total_snl; i++) {
00212 INT depth=_snl_info[i]._depth;
00213 SNL_TYPE type=_snl_info[i]._type;
00214 WN* wn=_snl_info[i]._wn;
00215 WN* outer_loop=NULL;
00216 if (type==Not_Inner || type==Inner) {
00217 for (INT j=0; j<depth; j++) {
00218 if (wn==NULL) {
00219 DevWarn("Not enough SNL level %d < %d in SNL info (%d), fixed",
00220 j, depth, i);
00221 if (j==0)
00222 _snl_info[i]._type=Invalid;
00223 else {
00224 _snl_info[i]._depth=j;
00225 if (outer_loop)
00226 if (Find_SCF_Inside(outer_loop, OPC_DO_LOOP))
00227 _snl_info[i]._type=Not_Inner;
00228 else
00229 _snl_info[i]._type=Inner;
00230 }
00231 break;
00232 }
00233 INT old_index=snl_info_table->Find(wn);
00234 if (old_index) {
00235 DevWarn("Duplicate found for loop <0x%p> in SNL info (%d) and (%d), fixed",
00236 wn, old_index, i);
00237 if (j==0)
00238 _snl_info[i]._type=Invalid;
00239 else {
00240 _snl_info[i]._depth=j;
00241 if (outer_loop)
00242 if (Find_SCF_Inside(outer_loop,OPC_DO_LOOP))
00243 _snl_info[i]._type=Not_Inner;
00244 else
00245 _snl_info[i]._type=Inner;
00246 }
00247 break;
00248 }
00249 snl_info_table->Enter(wn,i);
00250 outer_loop=wn;
00251 if (j<depth-1)
00252 wn=Get_Only_Loop_Inside(wn,FALSE);
00253 else if (type==Inner && Find_SCF_Inside(wn,OPC_DO_LOOP)) {
00254 DevWarn("Type Inner SNL has other loops inside in SNL info (%d), fixed", i);
00255 _snl_info[i]._type=Not_Inner;
00256 break;
00257 }
00258 }
00259 }
00260 }
00261 }
00262
00263 void FIZ_FUSE_INFO::Build(WN* root, BOOL all_loops) {
00264
00265 WN2INT *loop_table=CXX_NEW(WN2INT(1024,_mpool),_mpool);
00266 UINT snl_id=_snl_info.Newidx();
00267 _snl_info[snl_id]._type=Invalid;
00268
00269 WN_ITER* wn_walker=WN_WALK_SCFIter(root);
00270 while (WN_WALK_SCFNext(wn_walker)) {
00271 WN* wn=WN_ITER_wn(wn_walker);
00272 if (WN_opcode(wn)==OPC_DO_LOOP && loop_table->Find(wn)==0) {
00273 if (!all_loops && (!Do_Loop_Is_Good(wn) || Do_Loop_Has_Exits(wn) ||
00274 Do_Loop_Is_Mp(wn)))
00275 continue;
00276 snl_id=_snl_info.Newidx();
00277 loop_table->Enter(wn,snl_id);
00278 UINT level=1;
00279 WN* inner_most_loop=wn;
00280 WN* inner_loop=Get_Only_Loop_Inside(wn,FALSE);
00281 while (inner_loop) {
00282 Is_True(loop_table->Find(inner_loop)==0, ("Strange traversal order"));
00283 loop_table->Enter(inner_loop,snl_id);
00284 level++;
00285 inner_most_loop=inner_loop;
00286 inner_loop=Get_Only_Loop_Inside(inner_loop,FALSE);
00287 }
00288 if (Find_SCF_Inside(inner_most_loop,OPC_DO_LOOP))
00289 _snl_info[snl_id]._type=Not_Inner;
00290 else
00291 _snl_info[snl_id]._type=Inner;
00292 _snl_info[snl_id]._depth=level;
00293 _snl_info[snl_id]._wn=wn;
00294 }
00295 }
00296
00297 }
00298
00299 extern FIZ_FUSE_INFO*
00300 If_While_Region_Fiz_Fuse(WN* wn, FIZ_FUSE_INFO* snls, MEM_POOL* mpool) {
00301
00302 FIZ_FUSE_INFO *rval;
00303
00304 rval = CXX_NEW(FIZ_FUSE_INFO(mpool), mpool);
00305 rval->New_Snl(wn,0,Non_SNL);
00306
00307 WN* bodies[2];
00308 bodies[0]=bodies[1]=NULL;
00309
00310 OPCODE opc = WN_opcode(wn);
00311 IF_INFO *ii;
00312 switch (opc) {
00313 case OPC_IF:
00314 ii=Get_If_Info(wn);
00315 if (!ii->Contains_Do_Loops)
00316 return rval;
00317 bodies[0]=WN_then(wn);
00318 bodies[1]=WN_else(wn);
00319 break;
00320 case OPC_REGION:
00321 bodies[0]=WN_region_body(wn);
00322 break;
00323 case OPC_DO_WHILE:
00324 case OPC_WHILE_DO:
00325 bodies[0]=WN_while_body(wn);
00326 break;
00327 default:
00328 Is_True(0, ("Invalid WN in If_While_Region_Fiz_Fuse."));
00329 return rval;
00330 }
00331
00332 MEM_POOL_Push(&LNO_local_pool);
00333
00334
00335 for (INT i=0; i<2 && bodies[i]!=NULL; i++)
00336 for (WN* wn1=WN_first(bodies[i]); wn1; ) {
00337 WN* next_wn=WN_next(wn1);
00338 opc=WN_opcode(wn1);
00339 if (opc==OPC_DO_LOOP && !Do_Loop_Is_Mp(wn1))
00340 *snls += *Fiz_Fuse(wn1, snls, &LNO_default_pool);
00341 else if (opc == OPC_IF || opc==OPC_REGION ||
00342 opc==OPC_DO_WHILE || opc==OPC_WHILE_DO)
00343 (void)If_While_Region_Fiz_Fuse(wn1, snls, &LNO_default_pool);
00344 wn1=next_wn;
00345 }
00346
00347 MEM_POOL_Pop(&LNO_local_pool);
00348 return rval;
00349
00350 }
00351
00352 static void
00353 fast_fuse_check_msg(const char *msg, WN *lp1, WN *lp2, UINT level)
00354 {
00355 char buf[200];
00356 SRCPOS srcpos1;
00357 SRCPOS srcpos2;
00358
00359 if ( LNO_Verbose || LNO_Analysis || LNO_Tlog ) {
00360 sprintf(buf, "fast_fuse_check_msg %s", msg);
00361 srcpos1 = WN_Get_Linenum(lp1);
00362 srcpos2 = WN_Get_Linenum(lp2);
00363 }
00364 if (LNO_Verbose) {
00365 printf("#### fiz_fuse(%d+%d:%d): %s\n",
00366 Srcpos_To_Line(srcpos1), Srcpos_To_Line(srcpos2), level, buf);
00367 }
00368 if (LNO_Analysis) {
00369 fiz_fuse_analysis_info(FAIL, srcpos1, srcpos2, level, buf);
00370 }
00371 if ( LNO_Tlog ) {
00372 fiz_fuse_tlog_info(FAIL, srcpos1, srcpos2, level, buf);
00373 }
00374 }
00375
00376
00377
00378
00379
00380
00381
00382 static BOOL
00383 fast_fuse_check_ok(WN *loop1, WN *loop2, UINT fusion_levels)
00384 {
00385 WN *lp1 = loop1;
00386 WN *lp2 = loop2;
00387
00388 for (INT j = 0; j < fusion_levels; j++) {
00389
00390 FmtAssert(WN_opcode(lp1)==OPC_DO_LOOP,
00391 ("lp1 non-loop in fast_fuse_check_ok()\n"));
00392 FmtAssert(WN_opcode(lp2)==OPC_DO_LOOP,
00393 ("lp2 non-loop in fast_fuse_check_ok()\n"));
00394
00395 INT64 trips1 = Iterations(lp1, &LNO_default_pool);
00396 INT64 trips2 = Iterations(lp2, &LNO_default_pool);
00397
00398 if ( trips1 != trips2 ) {
00399 fast_fuse_check_msg("FALSE: const trips different.", lp1, lp2, j);
00400 return FALSE;
00401 }
00402 if ( trips1 == -1 ) {
00403
00404 DO_LOOP_INFO* dli1 = (DO_LOOP_INFO *)WN_MAP_Get(LNO_Info_Map, lp1);
00405 DO_LOOP_INFO* dli2 = (DO_LOOP_INFO *)WN_MAP_Get(LNO_Info_Map, lp2);
00406
00407 if ( dli1->No_Fusion || dli2->No_Fusion ) {
00408 fast_fuse_check_msg("FALSE: No_Fusion.", lp1, lp2, j);
00409 return FALSE;
00410 }
00411 if ( !Do_Loop_Is_Good(lp1) || !Do_Loop_Is_Good(lp2) ) {
00412 fast_fuse_check_msg("FALSE: not Good.", lp1, lp2, j);
00413 return FALSE;
00414 }
00415 if ( Do_Loop_Has_Calls(lp1) || Do_Loop_Has_Calls(lp2) ) {
00416 fast_fuse_check_msg("FALSE: has Calls.", lp1, lp2, j);
00417 return FALSE;
00418 }
00419 if ( Do_Loop_Has_Gotos(lp1) || Do_Loop_Has_Gotos(lp2) ) {
00420 fast_fuse_check_msg("FALSE: has Gotos.", lp1, lp2, j);
00421 return FALSE;
00422 }
00423 if ( !dli1->Step->Is_Const() || !dli2->Step->Is_Const() ) {
00424 fast_fuse_check_msg("TRUE: non-const step.", lp1, lp2, j);
00425 return TRUE;
00426 }
00427 ACCESS_VECTOR *step_diff = Subtract(dli1->Step, dli2->Step,
00428 &LNO_default_pool);
00429
00430 if ( !step_diff->Is_Const() || step_diff->Const_Offset != 0 ) {
00431 fast_fuse_check_msg("TRUE: diff steps.", lp1, lp2, j);
00432 return TRUE;
00433 }
00434 if ( Upper_Bound_Standardize( WN_end(lp1), TRUE ) == FALSE ) {
00435 fast_fuse_check_msg("FALSE: lp1 upper bnd not std.", lp1, lp2, j);
00436 return FALSE;
00437 }
00438 if ( Upper_Bound_Standardize( WN_end(lp2), TRUE ) == FALSE ) {
00439 fast_fuse_check_msg("FALSE: lp2 upper bnd not std.", lp1, lp2, j);
00440 return FALSE;
00441 }
00442 BOOL step_pos = (dli1->Step->Const_Offset > 0);
00443 BOOL ident_exp = FALSE;
00444 ACCESS_VECTOR *lb_diff = NULL;
00445 ACCESS_VECTOR *ub_diff = NULL;
00446
00447 if ( step_pos ) {
00448 if ( Compare_Bounds(WN_start(lp1), WN_index(lp1),
00449 WN_start(lp2), WN_index(lp2)) ==0 ) {
00450 ident_exp = TRUE;
00451 } else if ( Bound_Is_Too_Messy(dli1->LB) || dli1->LB->Num_Vec()!=1 ||
00452 Bound_Is_Too_Messy(dli2->LB) || dli2->LB->Num_Vec()!=1 ){
00453 fast_fuse_check_msg("FALSE: messy lower bnd.", lp1, lp2, j);
00454 return FALSE;
00455 } else {
00456 lb_diff = Subtract( dli1->LB->Dim(0), dli2->LB->Dim(0),
00457 &LNO_default_pool );
00458 }
00459 } else {
00460 if ( Compare_Bounds(WN_end(lp1), WN_index(lp1),
00461 WN_end(lp2), WN_index(lp2)) == 0 ) {
00462 ident_exp=TRUE;
00463 } else if ( Bound_Is_Too_Messy(dli1->UB) || dli1->UB->Num_Vec()!=1 ||
00464 Bound_Is_Too_Messy(dli2->UB) || dli2->UB->Num_Vec()!=1 ){
00465 fast_fuse_check_msg("FALSE: messy upper bnd.", lp1, lp2, j);
00466 return FALSE;
00467 } else {
00468 lb_diff = Subtract( dli1->UB->Dim(0), dli2->UB->Dim(0),
00469 &LNO_default_pool );
00470 }
00471 }
00472 if ( ident_exp ) {
00473 lb_diff = NULL;
00474 } else if ( !lb_diff->Is_Const() ) {
00475 fast_fuse_check_msg("FALSE: low bnd diff not const.", lp1, lp2, j);
00476 return FALSE;
00477 } else if ( lb_diff->Const_Offset ) {
00478 fast_fuse_check_msg("TRUE: low bnd diff const != 0.", lp1, lp2, j);
00479 return TRUE;
00480 }
00481
00482 ident_exp=FALSE;
00483 if ( step_pos ) {
00484 if ( Compare_Bounds(WN_end(lp1), WN_index(lp1),
00485 WN_end(lp2), WN_index(lp2)) == 0 ) {
00486 ident_exp=TRUE;
00487 } else if ( Bound_Is_Too_Messy(dli1->UB) || dli1->UB->Num_Vec()!=1 ||
00488 Bound_Is_Too_Messy(dli2->UB) || dli2->UB->Num_Vec()!=1 ){
00489 fast_fuse_check_msg("FALSE: messy upper bnd.", lp1, lp2, j);
00490 return FALSE;
00491 } else {
00492 ub_diff = Subtract( dli1->UB->Dim(0), dli2->UB->Dim(0),
00493 &LNO_default_pool );
00494 }
00495 } else {
00496 if ( Compare_Bounds(WN_start(lp1), WN_index(lp1),
00497 WN_start(lp2), WN_index(lp2)) == 0 ) {
00498 ident_exp=TRUE;
00499 } else if ( Bound_Is_Too_Messy(dli1->LB) || dli1->LB->Num_Vec()!=1 ||
00500 Bound_Is_Too_Messy(dli2->LB) || dli2->LB->Num_Vec()!=1 ){
00501 fast_fuse_check_msg("messy lower bnd.", lp1, lp2, j);
00502 return FALSE;
00503 } else {
00504 ub_diff = Subtract( dli1->LB->Dim(0), dli2->LB->Dim(0),
00505 &LNO_default_pool );
00506 }
00507 }
00508 if ( ident_exp ) {
00509 ub_diff = NULL;
00510 } else if ( !ub_diff->Is_Const() ) {
00511 fast_fuse_check_msg("FALSE: upper bnd diff not const.", lp1, lp2, j);
00512 return FALSE;
00513 } else if ( ub_diff->Const_Offset != 0 ) {
00514 fast_fuse_check_msg("TRUE: upper bnd diff const != 0.", lp1, lp2, j);
00515 return TRUE;
00516 }
00517 }
00518 lp1 = Get_Only_Loop_Inside(lp1, FALSE);
00519 lp2 = Get_Only_Loop_Inside(lp2, FALSE);
00520 }
00521 fast_fuse_check_msg("pass all checks", lp1, lp2, 0);
00522 return TRUE;
00523 }
00524
00525
00526
00527
00528
00529
00530
00531 static WN* Version_Loop(WN* wn_loop)
00532 {
00533 ARRAY_DIRECTED_GRAPH16* dg = Array_Dependence_Graph;
00534 REDUCTION_MANAGER* rm = red_manager;
00535 WN_MAP version_map = WN_MAP_Create(&LNO_local_pool);
00536 WN* wn_copy = LWN_Copy_Tree(wn_loop, TRUE, LNO_Info_Map, TRUE, version_map);
00537 if (Prompf_Info != NULL && Prompf_Info->Is_Enabled()) {
00538 STACK<WN*> st_old(&LNO_local_pool);
00539 STACK<WN*> st_new(&LNO_local_pool);
00540 Prompf_Assign_Ids(wn_loop, wn_copy, &st_old, &st_new, TRUE);
00541 }
00542 BOOL all_internal = WN_Rename_Duplicate_Labels(wn_loop, wn_copy,
00543 Current_Func_Node, &LNO_local_pool);
00544 Is_True(all_internal, ("external labels renamed"));
00545
00546
00547 WN* wn_array[2];
00548 wn_array[0] = wn_loop;
00549 wn_array[1] = wn_copy;
00550 Unrolled_DU_Update(wn_array, 2, Do_Loop_Depth(wn_loop) - 1, TRUE, FALSE);
00551 dg->Versioned_Dependences_Update(wn_loop, wn_copy, Do_Loop_Depth(wn_loop),
00552 version_map);
00553 WN_MAP_Delete(version_map);
00554 if (rm != NULL)
00555 rm->Unroll_Update(wn_array, 2);
00556
00557
00558 WN* wn_total_cond = LWN_Make_Icon(Boolean_type, 1);
00559 LWN_Extract_From_Block(wn_loop);
00560 WN* wn_if = LWN_CreateIf(wn_total_cond, WN_CreateBlock(), WN_CreateBlock());
00561 LWN_Insert_Block_After(WN_then(wn_if), NULL, wn_loop);
00562 LWN_Insert_Block_After(WN_else(wn_if), NULL, wn_copy);
00563 WN_Set_Linenum(wn_if, WN_Get_Linenum(wn_loop));
00564 IF_INFO *ii =
00565 CXX_NEW(IF_INFO(&LNO_default_pool, TRUE, TRUE), &LNO_default_pool);
00566 WN_MAP_Set(LNO_Info_Map, wn_if, (void *) ii);
00567 DOLOOP_STACK *stack = CXX_NEW(DOLOOP_STACK(&LNO_default_pool),
00568 &LNO_default_pool);
00569 Build_Doloop_Stack(wn_if, stack);
00570 LNO_Build_If_Access(wn_if, stack);
00571 return wn_if;
00572 }
00573
00574
00575
00576
00577
00578
00579
00580 static WN* Version_and_Splice_Loop(WN* wn_loop)
00581 {
00582 WN* wn_parent = LWN_Get_Parent(wn_loop);
00583 WN* wn_prev = WN_prev(wn_loop);
00584 WN* wn_if = Version_Loop(wn_loop);
00585 LWN_Insert_Block_After(wn_parent, wn_prev, wn_if);
00586 return wn_if;
00587 }
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597 static WN* Version_Loop_Pair(WN* wn_loop1,
00598 WN* wn_loop2)
00599 {
00600 WN* wn_if1 = Version_and_Splice_Loop(wn_loop1);
00601 WN* wn_if2 = Version_and_Splice_Loop(wn_loop2);
00602 WN* wn_then = WN_first(WN_then(wn_if2));
00603 LWN_Extract_From_Block(wn_then);
00604 WN* wn_thenlp = WN_first(WN_then(wn_if1));
00605 LWN_Insert_Block_After(LWN_Get_Parent(wn_thenlp), wn_thenlp, wn_then);
00606 WN* wn_else = WN_first(WN_else(wn_if2));
00607 LWN_Extract_From_Block(wn_else);
00608 WN* wn_elselp = WN_first(WN_else(wn_if1));
00609 LWN_Insert_Block_After(LWN_Get_Parent(wn_elselp), wn_elselp, wn_else);
00610 LWN_Delete_Tree(wn_if2);
00611 return wn_if1;
00612 }
00613
00614
00615
00616
00617
00618
00619
00620 static void Prompf_Zero_Ids(WN* wn_tree)
00621 {
00622 INT map_id = WN_MAP32_Get(Prompf_Id_Map, wn_tree);
00623 if (map_id != 0)
00624 WN_MAP32_Set(Prompf_Id_Map, wn_tree, 0);
00625 if (WN_operator(wn_tree) == OPR_BLOCK) {
00626 for (WN* wn = WN_first(wn_tree); wn != NULL; wn = WN_next(wn))
00627 Prompf_Zero_Ids(wn);
00628 } else {
00629 for (INT i = 0; i < WN_kid_count(wn_tree); i++)
00630 Prompf_Zero_Ids(WN_kid(wn_tree, i));
00631 }
00632 }
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642 static void Extract_Branch(WN* wn_if,
00643 WN* wn_start,
00644 BOOL need_backout)
00645 {
00646 WN* wnn = NULL;
00647 for (WN* wn = WN_first(wn_start); wn != NULL; wn = wnn) {
00648 wnn = WN_next(wn);
00649 LWN_Extract_From_Block(wn);
00650 LWN_Insert_Block_Before(LWN_Get_Parent(wn_if), wn_if, wn);
00651 }
00652 if (Prompf_Info != NULL && Prompf_Info->Is_Enabled()) {
00653 Prompf_Zero_Ids(wn_if);
00654 if (need_backout)
00655 Prompf_Info->Restore();
00656 else
00657 Prompf_Info->Clear();
00658 }
00659 LWN_Delete_Tree(wn_if);
00660 }
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671 static void Save_Corresponding_Loops(WN* wn_if,
00672 DYN_ARRAY<WN*>* loop_list_one,
00673 DYN_ARRAY<WN*>* loop_list_two)
00674 {
00675 WN* wn_block1 = WN_then(wn_if);
00676 WN* wn_block2 = WN_else(wn_if);
00677 WN* wn2 = WN_first(wn_block2);
00678 for (WN* wn1 = WN_first(wn_block1); wn1 != NULL; wn1 = WN_next(wn1)) {
00679 LWN_ITER* itr1 = LWN_WALK_TreeIter(wn1);
00680 LWN_ITER* itr2 = LWN_WALK_TreeIter(wn2);
00681 for (; itr1 != NULL; itr1 = LWN_WALK_TreeNext(itr1),
00682 itr2 = LWN_WALK_TreeNext(itr2)) {
00683 WN* wn_one = itr1->wn;
00684 WN* wn_two = itr2->wn;
00685 if (WN_operator(wn_one) == OPR_DO_LOOP) {
00686 FmtAssert(WN_operator(wn_two) == OPR_DO_LOOP,
00687 ("Save_Corresponding_Loops: Nodes do not correspond"));
00688 loop_list_one->AddElement(wn1);
00689 loop_list_two->AddElement(wn2);
00690 }
00691 }
00692 wn2 = WN_next(wn2);
00693 }
00694 }
00695
00696
00697
00698
00699
00700
00701
00702 static void Replace_Corresponding_Loops(FIZ_FUSE_INFO* ffi,
00703 DYN_ARRAY<WN*>* loop_list_one,
00704 DYN_ARRAY<WN*>* loop_list_two)
00705 {
00706 for (INT i = 0; i < ffi->Num_Snl(); i++) {
00707 WN* wn_old = ffi->Get_Wn(i);
00708 INT j;
00709 for (j = 0; j <= loop_list_one->Lastidx(); j++)
00710 if ((*loop_list_one)[j] == wn_old)
00711 break;
00712 if (j <= loop_list_one->Lastidx())
00713 ffi->Set_Wn(i, (*loop_list_two)[j]);
00714 }
00715 }
00716
00717 extern FISSION_FUSION_STATUS
00718 Fuse_Level_By_Level(WN* loop1, WN* loop2, UINT *fusion_level_io,
00719 UINT peeling_limit,
00720 BOOL allow_partial_fusion, BOOL allow_outer_peeling,
00721 FIZ_FUSE_INFO* ffi) {
00722
00723 UINT fusion_level= *fusion_level_io;
00724 UINT fused_level=0;
00725 WN** fused_loop2=CXX_NEW_ARRAY(WN*, fusion_level, &LNO_local_pool);
00726
00727 FISSION_FUSION_STATUS fusion_status;
00728 DYN_ARRAY<WN*> loop_list_one(&LNO_local_pool);
00729 DYN_ARRAY<WN*> loop_list_two(&LNO_local_pool);
00730
00731 if ( fusion_level > 1
00732 && !allow_partial_fusion
00733 && !allow_outer_peeling
00734 && !fast_fuse_check_ok(loop1, loop2, fusion_level) ) {
00735 *fusion_level_io = 0;
00736 return Failed;
00737 }
00738
00739 WN* wn_if = Version_Loop_Pair(loop1, loop2);
00740 Save_Corresponding_Loops(wn_if, &loop_list_one, &loop_list_two);
00741 if (Prompf_Info != NULL && Prompf_Info->Is_Enabled())
00742 Prompf_Info->Save();
00743
00744 for (INT j=0; j< fusion_level; j++) {
00745
00746 if (Move_Adjacent(loop1,loop2)==FALSE) {
00747 fusion_status=Failed;
00748 break;
00749 }
00750 UINT tmp_peeling_limit=peeling_limit;
00751 if (j< fusion_level-1)
00752 if (allow_outer_peeling && j==0)
00753 tmp_peeling_limit=INT32_MAX-1;
00754 else
00755 tmp_peeling_limit=0;
00756 fusion_status=Fuse(loop1, loop2, 1, tmp_peeling_limit, j==fusion_level-1);
00757 if (fusion_status==Succeeded) {
00758 fused_level++;
00759 if (j< fusion_level-1) {
00760 WN* body=WN_do_body(loop1);
00761 WN* wn=WN_first(body);
00762 while (WN_opcode(wn)!=OPC_DO_LOOP)
00763 wn=WN_next(wn);
00764 loop1=wn;
00765 wn=WN_next(wn);
00766 while (WN_opcode(wn)!=OPC_DO_LOOP)
00767 wn=WN_next(wn);
00768 loop2=wn;
00769 fused_loop2[j]=wn;
00770 }
00771 } else if (fusion_status==Succeeded_and_Inner_Loop_Removed) {
00772
00773 break;
00774 } else
00775 break;
00776 }
00777 if (fused_level==fusion_level) {
00778
00779 *fusion_level_io=fused_level;
00780 Extract_Branch(wn_if, WN_then(wn_if), FALSE);
00781 return fusion_status;
00782 } else if (fusion_status==Succeeded_and_Inner_Loop_Removed) {
00783 *fusion_level_io=fused_level;
00784 Extract_Branch(wn_if, WN_then(wn_if), FALSE);
00785 return fusion_status;
00786 } else if (fused_level>0 && allow_partial_fusion) {
00787 *fusion_level_io=fused_level;
00788 Extract_Branch(wn_if, WN_then(wn_if), FALSE);
00789 return Partially_fused;
00790 } else if (fused_level>0 && !allow_partial_fusion) {
00791
00792 *fusion_level_io = 0;
00793 Replace_Corresponding_Loops(ffi, &loop_list_one, &loop_list_two);
00794 Extract_Branch(wn_if, WN_else(wn_if), TRUE);
00795 return Failed;
00796 }
00797
00798 *fusion_level_io = 0;
00799 Replace_Corresponding_Loops(ffi, &loop_list_one, &loop_list_two);
00800 Extract_Branch(wn_if, WN_else(wn_if), TRUE);
00801 return Failed;
00802 }
00803
00804
00805
00806
00807
00808 extern FIZ_FUSE_INFO* Fiz_Fuse(WN* loop, FIZ_FUSE_INFO* snls, MEM_POOL* mpool) {
00809
00810 FIZ_FUSE_INFO *info, *rval;
00811
00812 rval = CXX_NEW(FIZ_FUSE_INFO(mpool), mpool);
00813
00814 MEM_POOL_Push(&LNO_local_pool);
00815
00816 info = CXX_NEW(FIZ_FUSE_INFO(&LNO_local_pool), &LNO_local_pool);
00817
00818
00819 DYN_ARRAY<WN*> sloops(&LNO_local_pool);
00820
00821 WN* wn=loop;
00822 WN* wn1=loop;
00823 INT i;
00824
00825
00826
00827 INT level=0;
00828 while (wn) {
00829
00830 if ((!Do_Loop_Is_Good(wn1) ||
00831 (Do_Loop_Has_Calls(wn1) || Do_Loop_Has_Gotos(wn1))) &&
00832 Do_Loop_Is_Good(wn) &&
00833 (!Do_Loop_Has_Calls(wn) && !Do_Loop_Has_Gotos(wn)))
00834 loop=wn;
00835
00836 if (Do_Loop_Is_Good(wn)&&!Do_Loop_Has_Calls(wn)&&!Do_Loop_Has_Gotos(wn)) {
00837 i=sloops.Newidx();
00838 sloops[i]=wn;
00839 level++;
00840
00841 }
00842
00843 wn1 = wn;
00844 wn=Get_Only_Loop_Inside(wn,FALSE);
00845
00846 if (Do_Loop_Is_Good(wn1) && !Do_Loop_Has_Calls(wn1) &&
00847 !Do_Loop_Has_Gotos(wn1) &&
00848 !Do_Loop_Is_Inner(wn1))
00849 toplogical_reordering(wn1, level, Array_Dependence_Graph);
00850
00851 }
00852
00853
00854 for (wn=WN_first(WN_do_body(wn1)); wn;) {
00855 WN* next_stmt=WN_next(wn);
00856
00857 OPCODE opc=WN_opcode(wn);
00858 if (opc==OPC_DO_LOOP && !Do_Loop_Is_Mp(wn))
00859 *info += *Fiz_Fuse(wn, snls, &LNO_default_pool);
00860 else if (opc==OPC_IF || opc==OPC_REGION ||
00861 opc==OPC_DO_WHILE || opc==OPC_WHILE_DO)
00862 *info += *If_While_Region_Fiz_Fuse(wn, snls, &LNO_default_pool);
00863 wn=next_stmt;
00864 }
00865
00866 if (!Do_Loop_Is_Good(loop) || Do_Loop_Has_Calls(loop) ||
00867 Do_Loop_Has_Gotos(loop)) {
00868 *snls += *info;
00869 sloops.Free_array();
00870 MEM_POOL_Pop(&LNO_local_pool);
00871 return rval;
00872 }
00873
00874
00875
00876 if (info->Num_Snl()==0) {
00877
00878 if (Find_SCF_Inside(wn1,OPC_DO_LOOP))
00879 rval->New_Snl(loop,sloops.Lastidx()+1,Not_Inner);
00880 else
00881 rval->New_Snl(loop,sloops.Lastidx()+1,Inner);
00882 sloops.Free_array();
00883 MEM_POOL_Pop(&LNO_local_pool);
00884 return rval;
00885 }
00886
00887 rval->New_Snl(loop,sloops.Lastidx()+1,Inner);
00888 INT relts = 1;
00889 WN* last_outer_loop=loop;
00890 INT last_loop=0;
00891 UINT last_fissioned_level=sloops.Lastidx()+1;
00892 UINT max_fissioned_level=0;
00893
00894 for (i=1; i< info->Num_Snl(); i++) {
00895 INT d1 = info->Get_Depth(last_loop);
00896 INT d2 = info->Get_Depth(i);
00897 INT min_snl_level=MIN(d1,d2);
00898 INT peeling_limit= (d1==d2) ? LNO_Fusion_Peeling_Limit : 0;
00899 WN* wn1=info->Get_Wn(last_loop);
00900 WN* wn2=info->Get_Wn(i);
00901 SNL_TYPE type0= rval->Get_Type(relts-1);
00902 SNL_TYPE type1= info->Get_Type(last_loop);
00903 SNL_TYPE type2= info->Get_Type(i);
00904 WN* parent_wn=LWN_Get_Parent(LWN_Get_Parent(wn1));
00905 DO_LOOP_INFO* dli0=Get_Do_Loop_Info(parent_wn);
00906 DO_LOOP_INFO* dli1=NULL;
00907 DO_LOOP_INFO* dli2=NULL;
00908 SRCPOS srcpos1=WN_Get_Linenum(wn1);
00909 SRCPOS srcpos2=WN_Get_Linenum(wn2);
00910
00911
00912 if (!Do_Loop_Is_Good(rval->Get_Wn(relts-1)) ||
00913 Do_Loop_Has_Gotos(rval->Get_Wn(relts-1)) ||
00914 Do_Loop_Has_Calls(rval->Get_Wn(relts-1))) {
00915
00916 snls->Copy_Snl(info,last_loop);
00917 for (INT j=i; j< info->Num_Snl(); j++) {
00918 snls->Copy_Snl(info,j);
00919 }
00920 break;
00921 }
00922
00923 if (WN_opcode(wn1)==OPC_DO_LOOP)
00924 dli1=Get_Do_Loop_Info(wn1);
00925 if (WN_opcode(wn2)==OPC_DO_LOOP)
00926 dli2=Get_Do_Loop_Info(wn2);
00927 BOOL try_fusion = (LNO_Fusion!=0) &&
00928 (((type0==Inner) && (type1==Inner) && (type2==Inner)) ||
00929 ((type1==Not_Inner) && (type2==Not_Inner))) &&
00930 (dli1 && !dli1->No_Fusion) &&
00931 (dli2 && !dli2->No_Fusion) &&
00932 min_snl_level>0 &&
00933 (!Do_Loop_Is_Mp(wn1) && !Do_Loop_Is_Mp(wn2)) &&
00934 (!Cannot_Concurrentize(wn1) && !Cannot_Concurrentize(wn2)
00935 || Cannot_Concurrentize(wn1) && Cannot_Concurrentize(wn2));
00936
00937 if ( try_fusion
00938 && dli1->Parallelizable != dli2->Parallelizable
00939 && !inside_parallelizable_loop( wn1 ) ) {
00940
00941 if (LNO_Analysis) {
00942 fiz_fuse_analysis_info(INFO, srcpos1, srcpos2, min_snl_level,
00943 "don't fuse parallel with serial loop, unless inside parallel.");
00944 }
00945 if ( LNO_Tlog ) {
00946 fiz_fuse_tlog_info(INFO, srcpos1, srcpos2, min_snl_level,
00947 "don't fuse parallel with serial loop, unless inside parallel.");
00948 }
00949 try_fusion = FALSE;
00950 }
00951 #ifdef KEY
00952 if ( try_fusion && LNO_Run_Simd > 0 && LNO_Simd_Avoid_Fusion &&
00953 (dli1->Vectorizable ^ dli2->Vectorizable) ) {
00954
00955 if (LNO_Analysis) {
00956 fiz_fuse_analysis_info(INFO, srcpos1, srcpos2, min_snl_level,
00957 "don't fuse vectorizable with serial loop.");
00958 }
00959 if ( LNO_Tlog ) {
00960 fiz_fuse_tlog_info(INFO, srcpos1, srcpos2, min_snl_level,
00961 "don't fuse vectorizable with serial loop.");
00962 }
00963 try_fusion = FALSE;
00964 }
00965 #endif
00966
00967 BOOL try_fission = (LNO_Fission!=0) && !dli0->No_Fission &&
00968 !Do_Loop_Is_Mp(Enclosing_Do_Loop(LWN_Get_Parent(wn1))) &&
00969 (type1 == Inner || type1 == Not_Inner) &&
00970 (type2 == Inner || type2 == Not_Inner) &&
00971 (((last_fissioned_level!=0) && (type1==Inner)) || (type2==Inner));
00972 BOOL cannot_fuse = FALSE;
00973
00974 BOOL prefer_fusion = try_fusion &&
00975 ((LNO_Fusion > LNO_Fission) ||
00976 ((LNO_Fusion == LNO_Fission) && (d1==d2)));
00977
00978 FISSION_FUSION_STATUS fusion_status=Failed;
00979 FISSION_FUSION_STATUS fission_status=Failed;
00980
00981 if (prefer_fusion) {
00982 if (LNO_Analysis)
00983 fiz_fuse_analysis_info(INFO, srcpos1, srcpos2, min_snl_level,
00984 "Attempted to fuse to create a deeper Simply Nested Loop");
00985 if ( LNO_Tlog )
00986 fiz_fuse_tlog_info(INFO, srcpos1, srcpos2, min_snl_level,
00987 "Attempted to fuse to create a deeper Simply Nested Loop");
00988
00989
00990 if (Move_Adjacent(info->Get_Wn(last_loop), info->Get_Wn(i))==TRUE)
00991 fusion_status= Fuse(wn1, wn2, min_snl_level,
00992 peeling_limit,TRUE);
00993 else
00994 fusion_status= Failed;
00995 if (fusion_status==Succeeded ||
00996 fusion_status==Succeeded_and_Inner_Loop_Removed) {
00997
00998 if (LNO_Analysis)
00999 fiz_fuse_analysis_info(SUCCEED, srcpos1, srcpos2, min_snl_level,
01000 "Fused to create a deeper Simply Nested Loop");
01001 if ( LNO_Tlog )
01002 fiz_fuse_tlog_info(SUCCEED, srcpos1, srcpos2, min_snl_level,
01003 "Fused to create a deeper Simply Nested Loop");
01004
01005 if (fusion_status==Succeeded_and_Inner_Loop_Removed)
01006 if (min_snl_level>1)
01007 info->Set_Depth(last_loop,min_snl_level-1);
01008 else {
01009 info->Set_Type(last_loop,Invalid);
01010 last_loop= ++i;
01011 }
01012 continue;
01013 } else {
01014 if (LNO_Analysis)
01015 fiz_fuse_analysis_info(FAIL, srcpos1, srcpos2, min_snl_level,
01016 "Failed to create a deeper Simply Nested Loop by fusion");
01017 if ( LNO_Tlog )
01018 fiz_fuse_tlog_info(FAIL, srcpos1, srcpos2, min_snl_level,
01019 "Failed to create a deeper Simply Nested Loop by fusion");
01020
01021 cannot_fuse = TRUE;
01022 }
01023 }
01024 if (try_fission) {
01025 if (LNO_Analysis)
01026 fiz_fuse_analysis_info(INFO, srcpos1, srcpos2, sloops.Lastidx()+1,
01027 "Attempted to fission in between to create a deeper Simply Nested Loop");
01028 if ( LNO_Tlog )
01029 fiz_fuse_tlog_info(INFO, srcpos1, srcpos2, sloops.Lastidx()+1,
01030 "Attempted to fission in between to create a deeper Simply Nested Loop");
01031
01032 fission_status= Fission(parent_wn, wn1, wn2, sloops.Lastidx()+1);
01033 if (fission_status==Succeeded)
01034 {
01035
01036
01037 if (LNO_Analysis)
01038 fiz_fuse_analysis_info(SUCCEED, srcpos1, srcpos2, sloops.Lastidx()+1,
01039 "Created a deeper Simply Nested Loop by fission");
01040 if ( LNO_Tlog )
01041 fiz_fuse_tlog_info(SUCCEED, srcpos1, srcpos2, sloops.Lastidx()+1,
01042 "Created a deeper Simply Nested Loop by fission");
01043
01044
01045
01046
01047 if (rval->Get_Type(relts-1)==Not_Inner) {
01048 rval->Set_Depth(relts-1,sloops.Lastidx()+1-max_fissioned_level);
01049 WN* tmp=info->Get_Wn(last_loop);
01050 for (INT k=0; k<last_fissioned_level; k++) {
01051 tmp=LWN_Get_Parent(LWN_Get_Parent(tmp));
01052 }
01053 snls->New_Snl(tmp,info->Get_Depth(last_loop)+last_fissioned_level,
01054 info->Get_Type(last_loop));
01055 } else if (info->Get_Type(last_loop)==Inner) {
01056 rval->Set_Depth(relts-1,
01057 sloops.Lastidx()+1+info->Get_Depth(last_loop));
01058 } else {
01059 rval->Set_Depth(relts-1,sloops.Lastidx()+1);
01060 rval->Set_Type(relts-1,Not_Inner);
01061 }
01062
01063
01064 last_outer_loop=WN_next(last_outer_loop);
01065 rval->New_Snl(last_outer_loop,sloops.Lastidx()+1,Inner);
01066
01067 relts++;
01068 last_loop=i;
01069 last_fissioned_level=sloops.Lastidx()+1;
01070 max_fissioned_level=0;
01071 continue;
01072 } else {
01073
01074 if (LNO_Analysis)
01075 fiz_fuse_analysis_info(FAIL, srcpos1, srcpos2, sloops.Lastidx()+1,
01076 "Failed to create a deeper Simply Nested Loop by fission");
01077 if ( LNO_Tlog )
01078 fiz_fuse_tlog_info(FAIL, srcpos1, srcpos2, sloops.Lastidx()+1,
01079 "Failed to create a deeper Simply Nested Loop by fission");
01080 }
01081
01082 }
01083 if (try_fusion && !cannot_fuse) {
01084 if (LNO_Analysis)
01085 fiz_fuse_analysis_info(INFO, srcpos1, srcpos2, min_snl_level,
01086 "Attempted to fuse to create a deeper Simply Nested Loop");
01087 if ( LNO_Tlog )
01088 fiz_fuse_tlog_info(INFO, srcpos1, srcpos2, min_snl_level,
01089 "Attempted to fuse to create a deeper Simply Nested Loop");
01090
01091 if (Move_Adjacent(info->Get_Wn(last_loop), info->Get_Wn(i))==TRUE)
01092 fusion_status=Fuse(info->Get_Wn(last_loop), info->Get_Wn(i),
01093 min_snl_level, peeling_limit,TRUE);
01094 else
01095 fusion_status=Failed;
01096 if (fusion_status==Succeeded ||
01097 fusion_status==Succeeded_and_Inner_Loop_Removed) {
01098 if (LNO_Analysis)
01099 fiz_fuse_analysis_info(SUCCEED, srcpos1, srcpos2, min_snl_level,
01100 "Fused to create a deeper Simply Nested Loop");
01101 if ( LNO_Tlog )
01102 fiz_fuse_tlog_info(SUCCEED, srcpos1, srcpos2, min_snl_level,
01103 "Fused to create a deeper Simply Nested Loop");
01104
01105 if (fusion_status==Succeeded_and_Inner_Loop_Removed)
01106 if (min_snl_level>1)
01107 info->Set_Depth(last_loop,min_snl_level-1);
01108 else {
01109 info->Set_Type(last_loop,Invalid);
01110 last_loop= ++i;
01111 }
01112 continue;
01113 } else {
01114 if (LNO_Analysis)
01115 fiz_fuse_analysis_info(FAIL, srcpos1, srcpos2, min_snl_level,
01116 "Failed to create a deeper Simply Nested Loop by fusion");
01117 if ( LNO_Tlog )
01118 fiz_fuse_tlog_info(FAIL, srcpos1, srcpos2, min_snl_level,
01119 "Failed to create a deeper Simply Nested Loop by fusion");
01120
01121 cannot_fuse = TRUE;
01122 }
01123 }
01124
01125 WN* last_loop_nest=info->Get_Wn(last_loop);
01126 WN* current_loop_nest=info->Get_Wn(i);
01127
01128
01129 INT fissioned_level=0;
01130 if (try_fusion && min_snl_level>1 && fusion_status==Try_Level_By_Level) {
01131
01132 if (LNO_Analysis)
01133 fiz_fuse_analysis_info(INFO, srcpos1, srcpos2, min_snl_level,
01134 "Attempting level-by-level fusion to create a deeper Simply Nested Loop");
01135 if ( LNO_Tlog )
01136 fiz_fuse_tlog_info(INFO, srcpos1, srcpos2, min_snl_level,
01137 "Attempting level-by-level fusion to create a deeper Simply Nested Loop");
01138
01139 UINT tmp_fused_level=min_snl_level;
01140 FISSION_FUSION_STATUS fusion_status=
01141 Fuse_Level_By_Level(last_loop_nest, current_loop_nest,
01142 &tmp_fused_level, peeling_limit,
01143 FALSE,FALSE, info);
01144 if (fusion_status==Succeeded ||
01145 fusion_status==Succeeded_and_Inner_Loop_Removed) {
01146
01147 if (LNO_Analysis)
01148 fiz_fuse_analysis_info(SUCCEED, srcpos1, srcpos2, min_snl_level,
01149 "Fused to create a deeper Simply Nested Loop");
01150 if ( LNO_Tlog )
01151 fiz_fuse_tlog_info(SUCCEED, srcpos1, srcpos2, min_snl_level,
01152 "Fused to create a deeper Simply Nested Loop");
01153
01154 if (fusion_status==Succeeded_and_Inner_Loop_Removed)
01155 if (min_snl_level>1)
01156 info->Set_Depth(last_loop,min_snl_level-1);
01157 else {
01158 info->Set_Type(last_loop,Invalid);
01159 last_loop= ++i;
01160 }
01161 continue;
01162 } else {
01163 if (LNO_Analysis)
01164 fiz_fuse_analysis_info(FAIL, srcpos1, srcpos2, min_snl_level,
01165 "Failed to create a deeper Simply Nested Loop by fusion");
01166 if ( LNO_Tlog )
01167 fiz_fuse_tlog_info(FAIL, srcpos1, srcpos2, min_snl_level,
01168 "Failed to create a deeper Simply Nested Loop by fusion");
01169
01170 if (tmp_fused_level!=0) {
01171
01172 DevWarn("Unable to re-fission partially fused SNL: level=%d.\n",
01173 tmp_fused_level);
01174
01175 WN* tmp=info->Get_Wn(last_loop);
01176
01177
01178 for (INT k=0; k<tmp_fused_level-1; k++) {
01179 tmp=Get_Only_Loop_Inside(tmp,FALSE);
01180 FmtAssert(tmp != NULL, ("Expected single loop.\n"));
01181 }
01182 WN* block=WN_do_body(tmp);
01183 tmp=WN_first(block);
01184 while (WN_opcode(tmp)!=OPC_DO_LOOP)
01185 tmp=WN_next(tmp);
01186 snls->New_Snl(tmp, info->Get_Depth(last_loop)-tmp_fused_level,
01187 info->Get_Type(last_loop));
01188 tmp=WN_next(tmp);
01189 while (WN_opcode(tmp)!=OPC_DO_LOOP)
01190 tmp=WN_next(tmp);
01191 snls->New_Snl(tmp, info->Get_Depth(i)-tmp_fused_level,
01192 info->Get_Type(i));
01193
01194 info->Set_Depth(last_loop, tmp_fused_level);
01195 info->Set_Type(last_loop, Not_Inner);
01196
01197 continue;
01198 }
01199
01200
01201
01202
01203 info->Set_Wn(i,WN_next(info->Get_Wn(last_loop)));
01204 }
01205 }
01206 if (try_fission && sloops.Lastidx()+1>1) {
01207
01208 if (LNO_Analysis)
01209 fiz_fuse_analysis_info(INFO, srcpos1, srcpos2, sloops.Lastidx()+1,
01210 "Attempting level-by-level fission to create a deeper Simply Nested Loop");
01211 if ( LNO_Tlog )
01212 fiz_fuse_tlog_info(INFO, srcpos1, srcpos2, sloops.Lastidx()+1,
01213 "Attempting level-by-level fission to create a deeper Simply Nested Loop");
01214
01215 last_loop_nest=info->Get_Wn(last_loop);
01216 current_loop_nest=info->Get_Wn(i);
01217
01218 INT j;
01219 for (j=0; j<sloops.Lastidx()+1; j++) {
01220
01221 if (Fission(LWN_Get_Parent(LWN_Get_Parent(last_loop_nest)),
01222 last_loop_nest, current_loop_nest, 1)==Succeeded) {
01223 fissioned_level++;
01224 last_loop_nest=LWN_Get_Parent(LWN_Get_Parent(last_loop_nest));
01225 current_loop_nest=LWN_Get_Parent(LWN_Get_Parent(current_loop_nest));
01226 } else
01227 break;
01228 }
01229 if (fissioned_level==sloops.Lastidx()+1) {
01230
01231 if (LNO_Analysis)
01232 fiz_fuse_analysis_info(SUCCEED, srcpos1, srcpos2, sloops.Lastidx()+1,
01233 "Created a deeper Simply Nested Loop by fission");
01234 if ( LNO_Tlog )
01235 fiz_fuse_tlog_info(SUCCEED, srcpos1, srcpos2, sloops.Lastidx()+1,
01236 "Created a deeper Simply Nested Loop by fission");
01237
01238
01239
01240
01241 if (rval->Get_Type(relts-1)==Not_Inner) {
01242 rval->Set_Depth(relts-1,sloops.Lastidx()+1-max_fissioned_level);
01243 WN* tmp=info->Get_Wn(last_loop);
01244 for (INT k=0; k<last_fissioned_level; k++) {
01245 tmp=LWN_Get_Parent(LWN_Get_Parent(tmp));
01246 }
01247 snls->New_Snl(tmp,info->Get_Depth(last_loop)+last_fissioned_level,
01248 info->Get_Type(last_loop));
01249 } else if (info->Get_Type(last_loop)==Inner) {
01250 rval->Set_Depth(relts-1,
01251 sloops.Lastidx()+1+info->Get_Depth(last_loop));
01252 } else {
01253 rval->Set_Depth(relts-1,sloops.Lastidx()+1);
01254 rval->Set_Type(relts-1,Not_Inner);
01255 }
01256
01257
01258 last_outer_loop=WN_next(last_outer_loop);
01259 rval->New_Snl(last_outer_loop,sloops.Lastidx()+1,Inner);
01260
01261 relts++;
01262 last_loop=i;
01263 last_fissioned_level=sloops.Lastidx()+1;
01264 max_fissioned_level=0;
01265 continue;
01266 } else if (fissioned_level>0) {
01267
01268
01269
01270
01271 rval->Set_Type(relts-1,Not_Inner);
01272 if (fissioned_level>max_fissioned_level)
01273 max_fissioned_level=fissioned_level;
01274
01275 if (last_fissioned_level<fissioned_level)
01276 j=last_fissioned_level;
01277 else
01278 j=fissioned_level;
01279 WN* tmp=info->Get_Wn(last_loop);
01280 for (INT k=0; k<j; k++) {
01281 tmp=LWN_Get_Parent(LWN_Get_Parent(tmp));
01282 }
01283 snls->New_Snl(tmp, info->Get_Depth(last_loop)+j,
01284 info->Get_Type(last_loop));
01285
01286 last_loop=i;
01287 last_fissioned_level=fissioned_level;
01288 continue;
01289 } else {
01290 if (LNO_Analysis)
01291 fiz_fuse_analysis_info(FAIL, srcpos1, srcpos2, sloops.Lastidx()+1,
01292 "Failed to create a deeper Simply Nested Loop by fission");
01293 if ( LNO_Tlog )
01294 fiz_fuse_tlog_info(FAIL, srcpos1, srcpos2, sloops.Lastidx()+1,
01295 "Failed to create a deeper Simply Nested Loop by fission");
01296 last_fissioned_level=0;
01297 }
01298 } else
01299 last_fissioned_level=0;
01300
01301
01302
01303 if (i!=info->Num_Snl()-1)
01304 (void)Move_Adjacent(info->Get_Wn(i), info->Get_Wn(i+1));
01305
01306 snls->Copy_Snl(info,last_loop);
01307 last_loop=i;
01308
01309
01310
01311 rval->Set_Type(relts-1,Not_Inner);
01312
01313 }
01314
01315 if (!Do_Loop_Is_Good(rval->Get_Wn(relts-1)) ||
01316 Do_Loop_Has_Gotos(rval->Get_Wn(relts-1)) ||
01317 Do_Loop_Has_Calls(rval->Get_Wn(relts-1))) {
01318 rval->Delete_Last_Snl();
01319 relts--;
01320 } else if (rval->Get_Type(relts-1)==Not_Inner) {
01321
01322 rval->Set_Depth(relts-1,sloops.Lastidx()+1-max_fissioned_level);
01323 if (last_loop<info->Num_Snl()) {
01324 WN* tmp=info->Get_Wn(last_loop);
01325 for (INT k=0; k<last_fissioned_level; k++) {
01326 tmp=LWN_Get_Parent(LWN_Get_Parent(tmp));
01327 }
01328 snls->New_Snl(tmp,info->Get_Depth(last_loop)+last_fissioned_level,
01329 info->Get_Type(last_loop));
01330 }
01331 } else if (last_loop<info->Num_Snl()) {
01332 SNL_TYPE t=info->Get_Type(last_loop);
01333 if (t==Inner || t==Not_Inner) {
01334 rval->Set_Depth(relts-1,sloops.Lastidx()+1+info->Get_Depth(last_loop));
01335 rval->Set_Type(relts-1,t);
01336 } else {
01337 rval->Set_Depth(relts-1,sloops.Lastidx()+1);
01338 if (t==Non_SNL &&
01339 Find_SCF_Inside(info->Get_Wn(last_loop),OPC_DO_LOOP)==NULL)
01340 rval->Set_Type(relts-1,Inner);
01341 else
01342 rval->Set_Type(relts-1,Not_Inner);
01343 }
01344 } else
01345 rval->Set_Depth(relts-1,sloops.Lastidx()+1);
01346
01347 sloops.Free_array();
01348 MEM_POOL_Pop(&LNO_local_pool);
01349 return rval;
01350 }
01351