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
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 #define __STDC_LIMIT_MACROS
00067 #include <stdint.h>
00068 #ifdef USE_PCH
00069 #include "lno_pch.h"
00070 #endif // USE_PCH
00071 #pragma hdrstop
00072
00073 const static char *source_file = __FILE__;
00074 const static char *rcs_id = "$Source: /home/bos/bk/kpro64-pending/be/lno/SCCS/s.lno_split.cxx $ $Revision: 1.6 $";
00075
00076 #include <sys/types.h>
00077 #include "lnopt_main.h"
00078 #include "dep_graph.h"
00079 #include "model.h"
00080 #include "lnoutils.h"
00081 #include "lwn_util.h"
00082 #include "config_targ_opt.h"
00083 #include "config_targ.h"
00084 #include "config_opt.h"
00085 #include "opt_du.h"
00086 #include "opt_alias_interface.h"
00087 #include "reduc.h"
00088
00089 static INT Split_Statement(WN *statement, ARRAY_DIRECTED_GRAPH16 *dep_graph);
00090 static BOOL Scalar_Interferes(WN *store, WN *expr, WN *split_point,
00091 ARRAY_DIRECTED_GRAPH16 *dep_graph);
00092 static WN *Find_Inner(WN *wn);
00093 static WN *Find_Split_Point(WN *store);
00094 static INT Num_Leaves_Or_Arrays(WN *wn);
00095 static WN *Find_Enough_Subtree(WN *wn, INT enough, INT *num_leaves);
00096 static BOOL Need_To_Split(WN *region);
00097 extern BOOL Variant_Array(WN *store, WN *split_point,
00098 ARRAY_DIRECTED_GRAPH16 *dep_graph);
00099 extern WN *Split_Using_Preg(WN *statement, WN *split_point,
00100 ARRAY_DIRECTED_GRAPH16 *dep_graph,
00101 BOOL recursive=TRUE);
00102 extern INT Split_Array(WN *statement, WN *split_point,
00103 ARRAY_DIRECTED_GRAPH16 *dep_graph);
00104
00105 static BOOL is_ok_to_reassociate(OPCODE opc)
00106 {
00107
00108
00109
00110 switch (OPCODE_operator(opc)) {
00111 case OPR_MAX:
00112 case OPR_MIN:
00113 case OPR_BAND:
00114 case OPR_BIOR:
00115 case OPR_BXOR:
00116 case OPR_LAND:
00117 case OPR_LIOR:
00118 return (TRUE);
00119
00120 case OPR_ADD:
00121 case OPR_MPY:
00122 if ( MTYPE_is_integral(OPCODE_rtype(opc)) ) {
00123 return TRUE;
00124 } else if ( MTYPE_is_float(OPCODE_rtype(opc)) ) {
00125 return ( Enable_Cfold_Reassociate );
00126 } else {
00127
00128 return FALSE;
00129 }
00130
00131 default:
00132 return FALSE;
00133 }
00134 }
00135
00136 static WN *reassoc_expr(WN *wn)
00137 {
00138 if ( ! is_ok_to_reassociate( WN_opcode(wn) ) ) {
00139 for (INT i = 0; i < WN_kid_count(wn); ++i) {
00140 WN_kid(wn, i) = reassoc_expr(WN_kid(wn,i));
00141 }
00142 return wn;
00143 }
00144 OPERATOR opr = WN_operator(wn);
00145 TYPE_ID rtype = WN_rtype(wn);
00146 WN *lhs = reassoc_expr(WN_kid0(wn));
00147 WN *rhs = reassoc_expr(WN_kid1(wn));
00148 WN *e = rhs;
00149 WN *e2 = e;
00150
00151 WN_kid0(wn) = lhs;
00152 WN_kid1(wn) = rhs;
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163 while ( WN_operator(e2) == opr && WN_rtype(e2) == rtype ) {
00164 e = e2;
00165 e2 = WN_kid0(e2);
00166 }
00167 if ( e2 != e ) {
00168 WN_kid1(wn) = e2;
00169 WN_kid0(e) = wn;
00170 return rhs;
00171 }
00172 return wn;
00173 }
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184 INT Split_Region(WN *region, ARRAY_DIRECTED_GRAPH16 *dep_graph)
00185 {
00186 if (Target_FPRs < 32) return 1;
00187
00188 OPCODE opcode = WN_opcode(region);
00189 if (opcode == OPC_BLOCK) {
00190 WN *kid = WN_first(region);
00191 while (kid) {
00192 WN *next = WN_next(kid);
00193 if (!Split_Region(kid,dep_graph)) return 0;
00194 kid = next;
00195 }
00196 } else if (OPCODE_is_store(opcode) &&
00197
00198
00199
00200 WN_opcode(LWN_Get_Parent(region)) == OPC_BLOCK) {
00201 if (Need_To_Split(region)) {
00202 if ( Enable_Cfold_Reassociate ) {
00203 OPERATOR opr = WN_operator(region);
00204 if ( opr == OPR_STID || opr == OPR_ISTORE ) {
00205
00206
00207
00208
00209 WN_kid0(region) = reassoc_expr(WN_kid0(region));
00210 LWN_Parentize(region);
00211 }
00212 }
00213 if (!Split_Statement(region,dep_graph)) return 0;
00214 }
00215 } else if (!OPCODE_is_expression(opcode)) {
00216 for (INT kidno=0; kidno<WN_kid_count(region); kidno++) {
00217 if (!Split_Region(WN_kid(region,kidno),dep_graph)) return 0;
00218 }
00219 }
00220 return 1;
00221 }
00222
00223 static BOOL Need_To_Split(WN *region)
00224 {
00225 MEM_POOL_Push(&LNO_local_pool);
00226 REGISTER_MODEL *reg_model = CXX_NEW(REGISTER_MODEL(&LNO_local_pool),
00227 &LNO_local_pool);
00228 reg_model->Add_Statement(region);
00229 INT fpr,intr,tlb;
00230 reg_model->Calculate_Register_Usage(Find_Inner(region),&fpr,&intr,&tlb);
00231 if (fpr >= (Target_FPRs-2) || intr >= Target_INTRs-2 ||
00232 tlb >= Mhd.L[0].TLB_Entries-2) {
00233 MEM_POOL_Pop(&LNO_local_pool);
00234 return TRUE;
00235 }
00236 MEM_POOL_Pop(&LNO_local_pool);
00237 return FALSE;
00238 }
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257 static INT Split_Statement(WN *statement, ARRAY_DIRECTED_GRAPH16 *dep_graph)
00258 {
00259 WN *split_point = Find_Split_Point(statement);
00260 if (!WN_kid_count(split_point)) {
00261 return 1;
00262 }
00263
00264 if ((WN_operator(statement)==OPR_STID || WN_operator(statement)==OPR_ISTORE)
00265 && split_point == WN_kid0(statement)) {
00266
00267
00268 return 1;
00269 }
00270
00271 if (Variant_Array(statement,split_point,dep_graph) &&
00272 (WN_rtype(split_point) == WN_desc(statement))) {
00273 if (!Split_Array(statement,split_point,dep_graph)) {
00274 return 0;
00275 }
00276 } else {
00277 Split_Using_Preg(statement,split_point,dep_graph);
00278 }
00279 return 1;
00280 }
00281
00282
00283 extern INT Split_Array(WN *store, WN *split_point,
00284 ARRAY_DIRECTED_GRAPH16 *dep_graph)
00285 {
00286
00287 WN *array1 = LWN_Copy_Tree(WN_kid1(store),TRUE,LNO_Info_Map);
00288 LWN_Copy_Def_Use(WN_kid1(store),array1,Du_Mgr);
00289 WN *array2 = LWN_Copy_Tree(WN_kid1(store),TRUE,LNO_Info_Map);
00290 LWN_Copy_Def_Use(WN_kid1(store),array2,Du_Mgr);
00291
00292
00293 WN *split_point_parent = LWN_Get_Parent(split_point);
00294 TY_IDX addr_type = WN_ty(store);
00295 TY_IDX el_type = TY_pointed(addr_type);
00296 TYPE_ID mtype = WN_desc(store);
00297 OPCODE l_opcode = OPCODE_make_op(OPR_ILOAD,Promote_Type(mtype),mtype);
00298 #ifndef KEY
00299 WN *load =
00300 LWN_CreateIload(l_opcode,WN_offset(store),el_type,addr_type,array1);
00301 #else
00302 WN *load =
00303 LWN_CreateIload(l_opcode,WN_offset(store),el_type,addr_type,array1,
00304 WN_field_id(store));
00305 #endif
00306 Copy_alias_info(Alias_Mgr,store,load);
00307 LWN_Set_Parent(load,split_point_parent);
00308 INT i=0;
00309 while (WN_kid(split_point_parent,i) != split_point) i++;
00310 WN_kid(split_point_parent,i) = load;
00311 if (dep_graph->Add_Deps_To_Copy_Block(WN_kid1(store),array1,FALSE)==0) {
00312 LNO_Erase_Dg_From_Here_In(load,dep_graph);
00313 if (red_manager)
00314 red_manager->Erase(store);
00315 return 0;
00316 }
00317
00318
00319 #ifndef KEY
00320 WN *new_store = LWN_CreateIstore(WN_opcode(store),WN_offset(store),
00321 WN_ty(store),split_point,array2);
00322 #else
00323 WN *new_store = LWN_CreateIstore(WN_opcode(store),WN_offset(store),
00324 WN_ty(store),split_point,array2, WN_field_id(store));
00325 #endif
00326 Copy_alias_info(Alias_Mgr,store,new_store);
00327 LWN_Copy_Linenumber(store,new_store);
00328 LWN_Insert_Block_Before(LWN_Get_Parent(store),store,new_store);
00329 if (dep_graph->Add_Deps_To_Copy_Block(WN_kid1(store),array2,FALSE)==0) {
00330 LNO_Erase_Dg_From_Here_In(new_store,dep_graph);
00331 if (red_manager) {
00332 red_manager->Erase(store);
00333 red_manager->Erase(new_store);
00334 }
00335 return 0;
00336 }
00337
00338
00339 BOOL not_overflow;
00340 VINDEX16 new_sv = dep_graph->Add_Vertex(new_store);
00341
00342 if (!new_sv) {
00343 LNO_Erase_Dg_From_Here_In(new_store,dep_graph);
00344 if (red_manager) {
00345 red_manager->Erase(store);
00346 red_manager->Erase(new_store);
00347 }
00348 return 0;
00349 }
00350 VINDEX16 new_lv = dep_graph->Add_Vertex(load);
00351
00352 if (!new_lv) {
00353 LNO_Erase_Dg_From_Here_In(load,dep_graph);
00354 if (red_manager) {
00355 red_manager->Erase(store);
00356 red_manager->Erase(new_store);
00357 }
00358 return 0;
00359 }
00360
00361
00362
00363
00364 VINDEX16 store_v = dep_graph->Get_Vertex(store);
00365 EINDEX16 e = dep_graph->Get_Out_Edge(store_v);
00366 while (e) {
00367 VINDEX16 sink = dep_graph->Get_Sink(e);
00368 if (sink != store_v) {
00369 not_overflow = dep_graph->Add_Edge(new_sv,sink,
00370 Create_DEPV_ARRAY(dep_graph->Depv_Array(e),&LNO_default_pool));
00371
00372 if (!not_overflow) {
00373 LNO_Erase_Dg_From_Here_In(store,dep_graph);
00374 if (red_manager) {
00375 red_manager->Erase(store);
00376 red_manager->Erase(new_store);
00377 }
00378 return 0;
00379 }
00380 if (!OPCODE_is_load(WN_opcode(dep_graph->Get_Wn(sink)))) {
00381 not_overflow = dep_graph->Add_Edge(new_lv,sink,
00382 Create_DEPV_ARRAY(dep_graph->Depv_Array(e),&LNO_default_pool));
00383
00384 if (!not_overflow) {
00385 LNO_Erase_Dg_From_Here_In(store,dep_graph);
00386 if (red_manager) {
00387 red_manager->Erase(store);
00388 red_manager->Erase(new_store);
00389 }
00390 return 0;
00391 }
00392 }
00393 }
00394 e = dep_graph->Get_Next_Out_Edge(e);
00395 }
00396
00397 e = dep_graph->Get_In_Edge(store_v);
00398 while (e) {
00399 VINDEX16 source = dep_graph->Get_Source(e);
00400 if (source != store_v) {
00401 not_overflow = dep_graph->Add_Edge(source, new_sv,
00402 Create_DEPV_ARRAY(dep_graph->Depv_Array(e),&LNO_default_pool));
00403
00404 if (!not_overflow) {
00405 LNO_Erase_Dg_From_Here_In(store,dep_graph);
00406 if (red_manager) {
00407 red_manager->Erase(store);
00408 red_manager->Erase(new_store);
00409 }
00410 return 0;
00411 }
00412 if (!OPCODE_is_load(WN_opcode(dep_graph->Get_Wn(source)))) {
00413 not_overflow = dep_graph->Add_Edge(source, new_lv,
00414 Create_DEPV_ARRAY(dep_graph->Depv_Array(e),&LNO_default_pool));
00415
00416 if (!not_overflow) {
00417 LNO_Erase_Dg_From_Here_In(store,dep_graph);
00418 if (red_manager) {
00419 red_manager->Erase(store);
00420 red_manager->Erase(new_store);
00421 }
00422 return 0;
00423 }
00424 }
00425 }
00426 e = dep_graph->Get_Next_In_Edge(e);
00427 }
00428
00429
00430
00431 WN *inner = Find_Inner(store);
00432 INT depth = Do_Loop_Depth(inner);
00433 INT good_depth = Good_Do_Depth(store);
00434 INT num_bad = depth - good_depth;
00435
00436 EINDEX16 self_e = dep_graph->Get_Edge(store_v,store_v);
00437 if (!self_e) {
00438 DEPV_ARRAY *zero = Create_DEPV_ARRAY(1,good_depth+1,num_bad,
00439 &LNO_default_pool);
00440 for (INT ii=0; ii<=good_depth; ii++) {
00441 DEPV_Dep(zero->Depv(0),ii) = DEP_SetDirection(DIR_EQ);
00442 }
00443 DEPV_ARRAY *zero2 = Create_DEPV_ARRAY(zero,&LNO_default_pool);
00444 DEPV_ARRAY *zero3 = Create_DEPV_ARRAY(zero,&LNO_default_pool);
00445
00446 not_overflow = dep_graph->Add_Edge(new_sv,store_v,zero);
00447 not_overflow = not_overflow && dep_graph->Add_Edge(new_sv,new_lv,zero2);
00448 not_overflow = not_overflow && dep_graph->Add_Edge(new_lv,store_v,zero3);
00449 } else {
00450 DEPV_ARRAY *self_dep = dep_graph->Depv_Array(self_e);
00451 DEPV *tmp_dep = DEPV_Create(&LNO_local_pool,good_depth+1);
00452 for (INT ii=0; ii<=good_depth; ii++) {
00453 DEPV_Dep(tmp_dep,ii) = DEP_SetDirection(DIR_EQ);
00454 }
00455 DEPV_LIST *tmp = CXX_NEW(DEPV_LIST(self_dep,&LNO_local_pool),
00456 &LNO_local_pool);
00457 tmp->Append(CXX_NEW(DEPV_NODE(tmp_dep),&LNO_local_pool));
00458
00459 not_overflow = dep_graph->Add_Edge(new_sv,new_sv,
00460 Create_DEPV_ARRAY(self_dep,&LNO_default_pool));
00461 not_overflow = not_overflow && dep_graph->Add_Edge(store_v,new_sv,
00462 Create_DEPV_ARRAY(self_dep,&LNO_default_pool));
00463 not_overflow = not_overflow && dep_graph->Add_Edge(new_sv,store_v,
00464 Create_DEPV_ARRAY(tmp,&LNO_default_pool));
00465 not_overflow = not_overflow && dep_graph->Add_Edge(new_lv,new_sv,
00466 Create_DEPV_ARRAY(self_dep,&LNO_default_pool));
00467 not_overflow = not_overflow && dep_graph->Add_Edge(new_sv,new_lv,
00468 Create_DEPV_ARRAY(tmp,&LNO_default_pool));
00469 not_overflow = not_overflow && dep_graph->Add_Edge(store_v,new_lv,
00470 Create_DEPV_ARRAY(self_dep,&LNO_default_pool));
00471 not_overflow = not_overflow && dep_graph->Add_Edge(new_lv,store_v,
00472 Create_DEPV_ARRAY(tmp,&LNO_default_pool));
00473 }
00474
00475
00476 if (!not_overflow) {
00477 LNO_Erase_Dg_From_Here_In(store,dep_graph);
00478 if (red_manager) {
00479 red_manager->Erase(store);
00480 red_manager->Erase(new_store);
00481 }
00482 return 0;
00483 }
00484
00485
00486
00487 if (red_manager && (red_manager->Which_Reduction(store) != RED_NONE)) {
00488 red_manager->Erase(store);
00489 red_manager->Erase(new_store);
00490 red_manager->Build(store,TRUE,TRUE,dep_graph);
00491 red_manager->Build(new_store,TRUE,TRUE,dep_graph);
00492 }
00493
00494
00495
00496 if (Need_To_Split(new_store)) {
00497 Split_Statement(new_store,dep_graph);
00498 }
00499
00500 #if 0
00501
00502 if (Need_To_Split(store)) {
00503 Split_Statement(store,dep_graph);
00504 }
00505 #endif
00506
00507 return 1;
00508
00509 }
00510
00511
00512
00513
00514
00515
00516 extern WN *Split_Using_Preg(WN *statement, WN *split_point,
00517 ARRAY_DIRECTED_GRAPH16 *dep_graph,
00518 BOOL recursive)
00519 {
00520
00521 OPCODE store_opcode = WN_opcode(statement);
00522 OPCODE split_opcode = WN_opcode(split_point);
00523 TYPE_ID type = OPCODE_rtype(split_opcode);
00524 ST *preg_st = MTYPE_To_PREG(type);
00525 const char *orig_name;
00526 if (OPCODE_operator(store_opcode) == OPR_STID) {
00527 orig_name = ST_name(WN_st(statement));
00528 } else if ((WN_operator(WN_kid1(statement)) == OPR_ARRAY) &&
00529 (OPCODE_has_sym(WN_opcode(WN_array_base(WN_kid1(statement)))))) {
00530 orig_name = ST_name(WN_st(WN_array_base(WN_kid1(statement))));
00531 } else {
00532 orig_name = "blank";
00533 }
00534 char new_name[20];
00535 INT length = strlen(orig_name);
00536 WN_OFFSET preg_num;
00537 if (length < 18) {
00538 strcpy(new_name,orig_name);
00539 new_name[length] = '_';
00540 new_name[length+1] = '1';
00541 new_name[length+2] = 0;
00542 #ifdef _NEW_SYMTAB
00543 preg_num = Create_Preg(type,new_name);
00544 } else {
00545 preg_num = Create_Preg(type,NULL);
00546 }
00547 #else
00548 preg_num = Create_Preg(type,new_name, NULL);
00549 } else {
00550 preg_num = Create_Preg(type,NULL,NULL);
00551 }
00552 #endif
00553
00554
00555 WN *split_point_parent = LWN_Get_Parent(split_point);
00556 OPCODE preg_l_opcode = OPCODE_make_op(OPR_LDID,Promote_Type(type),type);
00557 WN *preg_load = WN_CreateLdid(preg_l_opcode,preg_num,preg_st,
00558 Be_Type_Tbl(type));
00559 LWN_Set_Parent(preg_load,split_point_parent);
00560 INT i=0;
00561 while (WN_kid(split_point_parent,i) != split_point) i++;
00562 WN_kid(split_point_parent,i) = preg_load;
00563
00564
00565 OPCODE preg_s_opcode = OPCODE_make_op(OPR_STID,MTYPE_V,type);
00566 WN *preg_store = LWN_CreateStid(preg_s_opcode,
00567 preg_num,preg_st,
00568 Be_Type_Tbl(type),split_point);
00569 LWN_Copy_Linenumber(statement,preg_store);
00570 LWN_Insert_Block_Before(LWN_Get_Parent(statement),statement,preg_store);
00571
00572 WN_set_st_addr_saved(split_point);
00573
00574
00575 Du_Mgr->Add_Def_Use(preg_store,preg_load);
00576
00577
00578
00579 if (red_manager && (red_manager->Which_Reduction(statement) != RED_NONE)) {
00580 red_manager->Erase(statement);
00581 red_manager->Erase(preg_store);
00582 red_manager->Build(statement,TRUE,TRUE,dep_graph);
00583
00584 }
00585
00586
00587 if (recursive &&
00588 WN_kid_count(split_point_parent) > 1 &&
00589
00590 Need_To_Split(preg_store)) {
00591 Split_Statement(preg_store,dep_graph);
00592 }
00593
00594 if (recursive && Need_To_Split(statement)) {
00595 Split_Statement(statement,dep_graph);
00596 }
00597 return preg_store;
00598 }
00599
00600
00601
00602
00603
00604
00605 extern BOOL Variant_Array(WN *store, WN *split_point,
00606 ARRAY_DIRECTED_GRAPH16 *dep_graph)
00607 {
00608 if (WN_operator(store) != OPR_ISTORE) return FALSE;
00609
00610
00611 if (WN_kid_count(store) != 2) return FALSE;
00612 WN *array = WN_kid1(store);
00613 if (WN_operator(array) != OPR_ARRAY) return FALSE;
00614
00615 ACCESS_ARRAY *aa = (ACCESS_ARRAY *) WN_MAP_Get(LNO_Info_Map,array);
00616 if (aa->Too_Messy) return FALSE;
00617
00618 WN *inner = Find_Inner(store);
00619 if (!Do_Loop_Is_Good(inner) || Do_Loop_Has_Gotos(inner)) return FALSE;
00620 INT depth = Do_Loop_Depth(inner);
00621
00622 BOOL seen_var = FALSE;
00623 for (INT i=0; i<aa->Num_Vec(); i++) {
00624 ACCESS_VECTOR *av = aa->Dim(i);
00625 if (av->Too_Messy || (av->Non_Const_Loops() == (depth+1))) return FALSE;
00626 if (av->Delinearized_Symbol)
00627 return FALSE;
00628 if (av->Loop_Coeff(depth)) seen_var=TRUE;
00629 }
00630 if (!seen_var) return FALSE;
00631
00632
00633
00634 VINDEX16 v = dep_graph->Get_Vertex(store);
00635 if (!v) return FALSE;
00636 EINDEX16 e;
00637 for (e=dep_graph->Get_In_Edge(v); e; e=dep_graph->Get_Next_In_Edge(e)) {
00638 if (dep_graph->Depv_Array(e)->Max_Level() > depth) {
00639 WN *source_wn = dep_graph->Get_Wn(dep_graph->Get_Source(e));
00640 if (Is_Descendent(source_wn,store) &&
00641 !Is_Descendent(source_wn,split_point)) {
00642 return FALSE;
00643 }
00644 }
00645 }
00646
00647
00648
00649 if (Scalar_Interferes(store,WN_kid0(store),split_point,dep_graph)) {
00650 return FALSE;
00651 }
00652 return TRUE;
00653 }
00654
00655
00656
00657
00658
00659
00660 static BOOL Scalar_Interferes(WN *store, WN *expr, WN *split_point,
00661 ARRAY_DIRECTED_GRAPH16 *dep_graph)
00662 {
00663 if (expr == split_point) {
00664 return FALSE;
00665 }
00666
00667 if (OPCODE_is_load(WN_opcode(expr))) {
00668 VINDEX16 v = dep_graph->Get_Vertex(expr);
00669 if (v) return FALSE;
00670 return (Aliased(Alias_Mgr,store,expr) != NOT_ALIASED);
00671 } else {
00672 for (INT kidno=0; kidno < WN_kid_count(expr); kidno++) {
00673 if (Scalar_Interferes(store,WN_kid(expr,kidno),split_point,dep_graph)) {
00674 return TRUE;
00675 }
00676 }
00677 return FALSE;
00678 }
00679 }
00680
00681
00682
00683
00684
00685 static WN *Find_Inner(WN *wn)
00686 {
00687 while (WN_opcode(wn) != OPC_DO_LOOP) wn = LWN_Get_Parent(wn);
00688 return wn;
00689 }
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699 static WN *Find_Split_Point(WN *store)
00700 {
00701 WN *rhs = WN_kid0(store);
00702 INT enough_leaves = (Num_Leaves_Or_Arrays(rhs) >> 1) ;
00703 INT tmp;
00704 WN *result = Find_Enough_Subtree(rhs,enough_leaves,&tmp);
00705 if (WN_operator(result) == OPR_PARM) {
00706 result = WN_kid0(result);
00707 }
00708 if (WN_operator(result) == OPR_ARRAY &&
00709 WN_operator(LWN_Get_Parent(result)) == OPR_ILOAD) {
00710
00711 result = LWN_Get_Parent(result);
00712 }
00713 return result;
00714 }
00715
00716
00717 static INT Num_Leaves_Or_Arrays(WN *wn)
00718 {
00719 if ((WN_kid_count(wn) == 0) ||
00720 (WN_operator(wn) == OPR_ARRAY)) {
00721 return 1;
00722 }
00723 INT result = 0;
00724 for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) {
00725 result += Num_Leaves_Or_Arrays(WN_kid(wn,kidno));
00726 }
00727 return result;
00728 }
00729
00730
00731
00732
00733 static WN *Find_Enough_Subtree(WN *wn, INT enough, INT *num_leaves)
00734 {
00735 *num_leaves = 0;
00736 if ((WN_kid_count(wn) == 0) ||
00737 (WN_operator(wn) == OPR_ARRAY)) {
00738 *num_leaves = 1;
00739 return wn;
00740 }
00741
00742 INT temp = 0;
00743 WN *result;
00744 for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) {
00745 result = Find_Enough_Subtree(WN_kid(wn,kidno),enough, &temp);
00746 if (temp >= enough) {
00747 *num_leaves = temp;
00748 return result;
00749 } else {
00750 *num_leaves += temp;
00751 }
00752 }
00753 return wn;
00754 }
00755