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 #define __STDC_LIMIT_MACROS
00054 #include <stdint.h>
00055 #if defined(BUILD_OS_DARWIN)
00056 #include <darwin_elf.h>
00057 #else
00058 #include <elf.h>
00059 #endif
00060 #include <cmplrs/host.h>
00061 #define USE_STANDARD_TYPES // override unwanted defines in defs.h
00062 #include "defs.h"
00063 #include "errors.h"
00064 #include "tracing.h"
00065 #include "ipa_cg.h"
00066 #include "ipc_bread.h"
00067 #include "ipa_summary.h"
00068 #include "ipa_inline.h"
00069 #include "ipa_option.h"
00070 #include "ipc_symtab_merge.h"
00071 #include "ipc_file.h"
00072 #include "ipa_pad.h"
00073 #define MAX_ALIGN 16
00074
00075 INT IPO_Pad_Count = 0;
00076 COMMON_SNODE_TBL* IPA_Common_Table = NULL;
00077
00078 static MEM_POOL IPA_Pad_Split_Mem_Pool;
00079 static BOOL trace_split_common = FALSE;
00080
00081
00082
00083
00084
00085 void
00086 COMMON_SNODE_LIST::New_Append(ST* st, MEM_POOL *m)
00087 {
00088 Append(CXX_NEW(COMMON_SNODE(m, st), m));
00089 }
00090
00091
00092
00093
00094
00095 void
00096 COMMON_SNODE_LIST::Free_Nodes (MEM_POOL *m)
00097 {
00098 COMMON_SNODE_LIST_ITER list_iter(this);
00099 COMMON_SNODE *last_node;
00100
00101 list_iter.First();
00102 while (!list_iter.Is_Empty()) {
00103 last_node = list_iter.Cur();
00104 list_iter.Next();
00105 CXX_DELETE(last_node, m);
00106 }
00107 }
00108
00109
00110
00111
00112
00113 COMMON_SNODE_LIST::COMMON_SNODE_LIST(MEM_POOL *m, ST* s)
00114 {
00115 _map = CXX_NEW(ST_TO_FLD_MAP_ARRAY(m), m);
00116 _flags = 0;
00117 _st = s;
00118 _split_array = CXX_NEW(SPLIT_COMMON_DYN_ARRAY(m), m);
00119 if (!IPA_Enable_Padding)
00120 Set_No_Pad();
00121 if (!IPA_Enable_Split_Common)
00122 Set_No_Split();
00123 }
00124
00125
00126
00127
00128
00129 COMMON_SNODE::COMMON_SNODE(MEM_POOL *m, ST* s)
00130 {
00131 _st = s;
00132 _flags = 0;
00133 _bounds_array = CXX_NEW(BOUNDS_ARRAY(m),m);
00134 }
00135
00136
00137
00138
00139
00140 static BOOL
00141 Intersects_Col_Boundary (WN_OFFSET start1, WN_OFFSET size1,
00142 WN_OFFSET col_size,
00143 WN_OFFSET start2, WN_OFFSET size2)
00144 {
00145
00146
00147
00148
00149
00150 BOOL intersects;
00151
00152 if (start2 > (start1 + size1))
00153 intersects = FALSE;
00154 else if (size2 <= 0)
00155 intersects = TRUE;
00156 else if (start2+size2 < start1)
00157 intersects = FALSE;
00158 else if (start2 < start1)
00159 intersects = TRUE;
00160 else
00161
00162
00163
00164 intersects = (((start2-start1) % col_size) + size2) > col_size;
00165
00166 return intersects;
00167 }
00168
00169
00170
00171
00172
00173
00174 extern BOOL
00175 Is_Common_Based_Symbol (const ST* st)
00176 {
00177 if (ST_base_idx (st) == ST_st_idx (st))
00178 return FALSE;
00179
00180 const ST* base = ST_base (st);
00181
00182 return ((ST_sclass(base) == SCLASS_COMMON ||
00183 ST_sclass(base) == SCLASS_DGLOBAL) &&
00184 TY_kind (ST_type (base)) == KIND_STRUCT);
00185 }
00186
00187
00188
00189
00190
00191 static inline
00192 BOOL
00193 Is_Global_Array(const ST* st)
00194 {
00195 if (ST_sclass(st) == SCLASS_UGLOBAL)
00196 {
00197 if ((TY_kind(ST_type(st)) == KIND_ARRAY))
00198 return TRUE;
00199 }
00200 return FALSE;
00201 }
00202
00203
00204
00205
00206
00207 static BOOL
00208 FLD_equivalent(FLD_HANDLE fld1, FLD_HANDLE fld2)
00209 {
00210 if (FLD_name_idx(fld1) != FLD_name_idx(fld2))
00211 return FALSE;
00212
00213 if (FLD_ofst(fld1) != FLD_ofst(fld2) ||
00214 FLD_bsize(fld1) != FLD_bsize(fld2) ||
00215 FLD_bofst(fld1) != FLD_bofst(fld2) ||
00216 FLD_flags(fld1) != FLD_flags(fld2) ||
00217 FLD_st(fld1) != FLD_st(fld2))
00218 return FALSE;
00219 return TRUE;
00220 }
00221
00222
00223
00224
00225
00226 static BOOL
00227 Is_Bad_Equivalence (const ST* st)
00228 {
00229
00230
00231
00232
00233 const TY& common_ty = Ty_Table[ST_type (st)];
00234 BOOL intersected = FALSE;
00235
00236 if (ST_sclass(st) != SCLASS_COMMON || TY_kind(common_ty) != KIND_STRUCT)
00237 return FALSE;
00238
00239 FLD_ITER fld_iter1 = Make_fld_iter (TY_fld (common_ty));
00240
00241 do {
00242 FLD_HANDLE fld1 (fld_iter1);
00243 const TY& fld1_ty = Ty_Table[FLD_type (fld1)];
00244 if (FLD_equivalence (fld1) &&
00245 TY_kind (fld1_ty) == KIND_ARRAY &&
00246 TY_AR_ndims (fld1_ty) > 1 &&
00247 TY_AR_const_stride (fld1_ty, 0) &&
00248 TY_size (fld1_ty) > 0) {
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265 FLD_ITER fld_iter2 = Make_fld_iter (TY_fld (common_ty));
00266
00267 do {
00268 FLD_HANDLE fld2 (fld_iter2);
00269 if (!FLD_equivalent(fld1, fld2) &&
00270 (FLD_type(fld1) != FLD_type(fld2))
00271 && FLD_equivalence(fld2))
00272 {
00273
00274 if (FLD_ofst(fld2) >= FLD_ofst(fld1) &&
00275 (FLD_ofst(fld2) <= FLD_ofst(fld1) + TY_size(fld1_ty)))
00276 intersected =
00277 (FLD_equivalence(fld2) &&
00278 Intersects_Col_Boundary(FLD_ofst(fld1),
00279 TY_size(fld1_ty),
00280 TY_AR_stride_val(fld1_ty, 0),
00281 FLD_ofst(fld2),
00282 TY_size(FLD_type(fld2))));
00283 }
00284 } while (!FLD_last_field (fld_iter2++));
00285 }
00286 } while (!FLD_last_field (fld_iter1++));
00287 return intersected;
00288 }
00289
00290
00291
00292
00293
00294
00295 static BOOL
00296 FLD_Intersects (FLD_HANDLE fld2, FLD_HANDLE fld1)
00297 {
00298 TY_IDX fld1_ty = FLD_type (fld1);
00299 TY_IDX fld2_ty = FLD_type (fld2);
00300
00301 return (FLD_ofst (fld1) == FLD_ofst (fld2) &&
00302 TY_size (fld1_ty) <= TY_size (fld2_ty) &&
00303 TY_align_exp (fld1_ty) == TY_align (fld2_ty));
00304
00305 }
00306
00307
00308
00309
00310
00311
00312 static BOOL
00313 Is_Bad_Split_Equivalence (const ST* s)
00314 {
00315 const TY& common_ty = Ty_Table[ST_type (s)];
00316
00317 if (ST_sclass(s) != SCLASS_COMMON || TY_kind(common_ty) != KIND_STRUCT)
00318 return FALSE;
00319
00320 BOOL intersected = FALSE;
00321 FLD_ITER fld_iter1 = Make_fld_iter (TY_fld (common_ty));
00322
00323 do {
00324
00325
00326
00327
00328 if (FLD_equivalence (fld_iter1)) {
00329 FLD_ITER fld_iter2 = Make_fld_iter (TY_fld (common_ty));
00330
00331 do {
00332
00333
00334
00335 if (!FLD_equivalence(fld_iter2)) {
00336 if (FLD_Intersects(fld_iter2, fld_iter1))
00337 intersected = TRUE;
00338 }
00339 } while (!FLD_last_field (fld_iter2++));
00340
00341
00342
00343 if (!intersected)
00344 return TRUE;
00345 }
00346 } while (!FLD_last_field (fld_iter1++));
00347
00348 return FALSE;
00349 }
00350
00351
00352
00353
00354
00355
00356
00357 static void
00358 Group_Common_STs(COMMON_SNODE_TBL *common_st_tbl)
00359 {
00360 ST *st;
00361 INT i;
00362 COMMON_SNODE_LIST *common_snode_list;
00363 FOREACH_SYMBOL(GLOBAL_SYMTAB, st, i) {
00364 if (Is_Common_Based_Symbol(st)) {
00365 STR_IDX common_name = ST_name_idx(ST_base(st));
00366 common_snode_list = common_st_tbl->Find(common_name);
00367 if (!common_snode_list)
00368 {
00369 common_snode_list =
00370 CXX_NEW(COMMON_SNODE_LIST(&IPA_Pad_Split_Mem_Pool, ST_base(st)),
00371 &IPA_Pad_Split_Mem_Pool);
00372 common_st_tbl->Enter(common_name, common_snode_list);
00373 if (!common_snode_list->No_Split())
00374 if (Is_Bad_Split_Equivalence(ST_base(st)))
00375 common_snode_list->Set_No_Split();
00376
00377 if (!common_snode_list->No_Pad())
00378 if (Is_Bad_Equivalence(ST_base(st)))
00379 {
00380 common_snode_list->Set_No_Pad();
00381 common_snode_list->Set_No_Split();
00382 }
00383
00384 INT st_idx = ST_st_idx(ST_base(st));
00385 if ((ST_export(St_Table[st_idx]) != EXPORT_INTERNAL) &&
00386 (ST_export(St_Table[st_idx]) != EXPORT_HIDDEN))
00387 {
00388 common_snode_list->Set_No_Pad();
00389 common_snode_list->Set_No_Split();
00390 }
00391
00392 if (ST_is_initialized(ST_base(st)) ||
00393 ST_is_initialized(st))
00394 {
00395 common_snode_list->Set_No_Pad();
00396 common_snode_list->Set_No_Split();
00397 }
00398 }
00399 if (ST_is_equivalenced(st))
00400 {
00401
00402 common_snode_list->Set_No_Split();
00403 }
00404 common_snode_list->New_Append(st, &IPA_Pad_Split_Mem_Pool);
00405 }
00406
00407
00408 if (Is_Global_Array(st) && (ST_export(st) == EXPORT_INTERNAL) &&
00409 !ST_addr_saved(st) && !ST_addr_passed(st))
00410 {
00411 common_snode_list = common_st_tbl->Find(ST_name_idx(st));
00412 if (!common_snode_list)
00413 {
00414 common_snode_list =
00415 CXX_NEW(COMMON_SNODE_LIST(&IPA_Pad_Split_Mem_Pool, st),
00416 &IPA_Pad_Split_Mem_Pool);
00417 common_st_tbl->Enter(ST_name_idx(st), common_snode_list);
00418 common_snode_list->New_Append(st,
00419 &IPA_Pad_Split_Mem_Pool);
00420 common_snode_list->Set_No_Split();
00421 }
00422 }
00423 }
00424 }
00425
00426
00427
00428
00429
00430 static void
00431 Update_Summaries (COMMON_SNODE_TBL* common_snode_tbl, INT num_ir)
00432 {
00433 for (INT i = 0; i < num_ir; ++i) {
00434 INT32 symbol_count;
00435 SUMMARY_SYMBOL* symbol_node_array =
00436 IPA_get_symbol_file_array(IP_File_header[i], symbol_count);
00437
00438 for (INT j = 0; j < symbol_count; ++j) {
00439 SUMMARY_SYMBOL* s = &symbol_node_array[j];
00440 if (s->Is_common_block() &&
00441 (s->Common_io_no_pad() || s->Is_parm() || s->Is_addr_saved())) {
00442 COMMON_SNODE_LIST* common_snode_list =
00443 common_snode_tbl->Find(ST_name_idx(ST_ptr(s->St_idx())));
00444 if (common_snode_list) {
00445 common_snode_list->Set_No_Pad();
00446 }
00447 }
00448 }
00449 }
00450 }
00451
00452
00453
00454
00455
00456 extern INT64
00457 Common_Array_Pad_Size (INT column_size)
00458 {
00459 #ifdef TARG_X8664
00460 if (column_size % 16 != 0)
00461 return column_size % 16;
00462 #endif
00463
00464
00465
00466
00467
00468 INT64 bad_dim_size = 256*8;
00469 INT64 mod = column_size % bad_dim_size;
00470 if ((column_size > bad_dim_size) && (mod < bad_dim_size/20)) {
00471 return (bad_dim_size/10 - mod);
00472 } else if ((column_size > bad_dim_size) &&
00473 ((bad_dim_size - mod) < bad_dim_size/20)) {
00474 return (bad_dim_size/20 + (bad_dim_size - mod));
00475 }
00476
00477
00478
00479 bad_dim_size = 128*8;
00480 mod = column_size % bad_dim_size;
00481 if ((column_size > bad_dim_size) && (mod < bad_dim_size/20)) {
00482 return (bad_dim_size/10 - mod);
00483 } else if ((column_size > bad_dim_size) &&
00484 ((bad_dim_size - mod) < bad_dim_size/20)) {
00485 return (bad_dim_size/20 + (bad_dim_size - mod));
00486 } else {
00487 return 0;
00488 }
00489 }
00490
00491
00492
00493
00494
00495
00496 static void
00497 Store_Orig_Dims(ST* s, BOUNDS_ARRAY* b)
00498 {
00499 Is_True((TY_kind(ST_type(s)) == KIND_ARRAY), (" Expecting KIND_ARRAY in Store_Orig_Dims \n"));
00500
00501 Is_True( (b!=NULL), ("NULL bounds in Store_Orig_Dims \n"));
00502
00503 INT lower, upper, stride;
00504 ARB_HANDLE arb_base = TY_arb(ST_type(s));
00505 INT num_dims = ARB_dimension(arb_base);
00506
00507 if (num_dims > 1) {
00508 for (INT i=0; i<num_dims; ++i)
00509 {
00510 ARB_HANDLE arb = arb_base[num_dims-1-i];
00511 if (ARB_const_lbnd(arb) && ARB_const_ubnd(arb) &&
00512 ARB_const_stride(arb))
00513 {
00514 lower = ARB_lbnd_val(arb);
00515 upper = ARB_ubnd_val(arb);
00516 stride = ARB_stride_val(arb);
00517 INT id = b->Newidx();
00518 BOUNDS *belement = &(*b)[id];
00519 belement->Init(upper, lower,stride);
00520 belement->Set_Constant();
00521 }
00522 else
00523 {
00524 INT id = b->Newidx();
00525 BOUNDS *belement = &(*b)[id];
00526 belement->Init();
00527 }
00528 }
00529 }
00530 }
00531
00532
00533
00534
00535
00536
00537 INT64
00538 Pad_Size(INT pad_dim, INT padding, INT end_dim,
00539 BOUNDS_ARRAY *bounds, BOOL extra_pad)
00540 {
00541 INT size = 1;
00542 INT size2 = 1;
00543 INT pad_dim_size = 1;
00544
00545 if (trace_split_common)
00546 fprintf(TFile,"end_dim = %d, padding = %d \n", end_dim, padding);
00547
00548 if (end_dim == 0)
00549 return padding;
00550
00551 for (INT i=0; i<=end_dim; ++i) {
00552 BOUNDS *b = &(*bounds)[i];
00553 INT upper = b->Get_Upper();
00554 INT lower = b->Get_Lower();
00555 if (i != pad_dim)
00556 size = size* abs(upper-lower+1);
00557 else
00558 pad_dim_size = (upper-lower+1);
00559 size2 = size2*abs(upper-lower+1);
00560 }
00561
00562 INT total_size = size2+(padding/(*bounds)[0].Get_Stride());
00563 float fpad_size = float(total_size/size - pad_dim_size);
00564 if (fpad_size > 0.0)
00565 fpad_size = fpad_size - .001;
00566
00567 if (trace_split_common)
00568 fprintf(TFile, "fpad_size = %f \n", fpad_size);
00569
00570 INT64 pad_size;
00571 if (extra_pad)
00572 pad_size = (INT64)(fpad_size+2)*(*bounds)[0].Get_Stride();
00573 else
00574 pad_size = (INT64)(fpad_size+1)*(*bounds)[0].Get_Stride();
00575
00576 if (pad_size == 0)
00577 {
00578 if (trace_split_common)
00579 fprintf(TFile, "pad size = %lld for dim %d \n",(*bounds)[0].Get_Stride(), pad_dim);
00580 return (*bounds)[0].Get_Stride();
00581 }
00582 else
00583 {
00584 if (trace_split_common)
00585 fprintf(TFile, "pad size = %lld for dim %d \n", pad_size,pad_dim);
00586 return pad_size;
00587 }
00588 }
00589
00590
00591
00592
00593
00594
00595
00596
00597 static BOOL
00598 Padding_Threshold(INT64 pad_size, INT pad_dim, BOUNDS_ARRAY *b,
00599 ARB_HANDLE idx)
00600 {
00601 Is_True(pad_dim <= b->Lastidx(), ("pad dim is TOO high in Padding Threshold \n"));
00602
00603 BOUNDS *belement = &(*b)[pad_dim];
00604
00605
00606
00607 ARB_HANDLE arb = idx[b->Lastidx()-pad_dim];
00608 Is_True((ARB_const_ubnd(arb) && ARB_const_lbnd(arb) && ARB_const_stride(arb)), ("constant bounds expected \n"));
00609
00610 INT size = abs(ARB_ubnd_val(arb) - ARB_lbnd_val(arb) + 1);
00611 float padt = ((pad_size/(*b)[0].Get_Stride() + size)*100)/size;
00612 if (padt > 110)
00613 {
00614 if (trace_split_common)
00615 fprintf(TFile, "padding threshold = %f, pad_size = %lld, dim_size = %d \n", padt, pad_size, size);
00616 return FALSE;
00617 }
00618 if (trace_split_common)
00619 fprintf(TFile, "padding threshold = %f, pad_size = %lld, dim_size = %d \n", padt, pad_size, size);
00620 return TRUE;
00621
00622 }
00623
00624
00625
00626
00627
00628 static INT
00629 Get_Pad_Dim(INT last_dim, INT element_size, BOUNDS_ARRAY *b)
00630 {
00631 INT size, lower, upper, max_element, max_dim;
00632 max_element = 0;
00633 max_dim = last_dim;
00634
00635
00636
00637 if (trace_split_common)
00638 fprintf(TFile, "last dimension = %d \n", last_dim);
00639
00640 INT last_dim_size = abs((*b)[last_dim].Get_Upper() -
00641 (*b)[last_dim].Get_Lower() + 1);
00642 for (INT i=last_dim; i >= 0; --i)
00643 {
00644 BOUNDS* bounds_elem = &(*b)[i];
00645 lower = bounds_elem->Get_Lower();
00646 upper = bounds_elem->Get_Upper();
00647 size = abs(upper-lower+1);
00648
00649 if (((size*element_size) % (128*8)) == 0)
00650 {
00651 if (trace_split_common)
00652 fprintf(TFile, "Get_Pad_Dim = %d, Size = %d \n", i, size);
00653 return i;
00654 }
00655 if (size > max_element)
00656 {
00657 if (size > (last_dim_size*130)/100)
00658 {
00659 max_element = size;
00660 max_dim = i;
00661 }
00662 else
00663 {
00664 max_element = last_dim_size;
00665 max_dim = last_dim;
00666 }
00667 }
00668 }
00669 if (trace_split_common)
00670 fprintf(TFile, "Get_Pad_Dim = %d \n", max_dim);
00671 return max_dim;
00672 }
00673
00674
00675
00676
00677 static
00678 BOOL Pad_Dim(BOUNDS *b)
00679 {
00680 INT one_count = 0;
00681 INT size = abs (b->Get_Upper() - b->Get_Lower() + 1);
00682 while (size != 0)
00683 {
00684 size = size >> 1;
00685 if (size & 1)
00686 ++one_count;
00687 }
00688
00689 if (trace_split_common)
00690 fprintf(TFile, "Size = %d , one_count = %d \n", abs(b->Get_Upper() - b->Get_Lower() + 1), one_count);
00691
00692 if (one_count > 1)
00693 return FALSE;
00694 return TRUE;
00695 }
00696
00697
00698
00699
00700
00701 static INT64
00702 Update_Pad_Size(INT last_dim, BOUNDS_ARRAY *barray)
00703 {
00704 INT64 pad_size = 1;
00705 for (INT i=0; i<= last_dim; ++i)
00706 {
00707 INT upper = (*barray)[i].Get_Upper();
00708 INT lower = (*barray)[i].Get_Lower();
00709
00710 pad_size = pad_size* (abs(upper - lower + 1));
00711 }
00712
00713 return pad_size;
00714 }
00715
00716
00717
00718
00719
00720 static void
00721 Update_Bounds_After_Padding(INT64 pad_size,
00722 INT pad_dim, BOUNDS_ARRAY *barray)
00723 {
00724 BOUNDS *bounds = &(*barray)[pad_dim];
00725 INT64 stride = bounds->Get_Stride();
00726 for (INT i=pad_dim; i<=barray->Lastidx();++i)
00727 {
00728 bounds = &(*barray)[i];
00729 if (i == pad_dim)
00730 {
00731 if (pad_size > (*barray)[0].Get_Stride())
00732 pad_size = pad_size + pad_size %
00733 (*barray)[0].Get_Stride();
00734 pad_size = pad_size/(*barray)[0].Get_Stride();
00735 if (IPA_Common_Pad_Size) {
00736
00737 pad_size = IPA_Common_Pad_Size;
00738 }
00739 bounds->Set_Upper(pad_size+bounds->Get_Upper());
00740 if (trace_split_common)
00741 fprintf(TFile, "dimension %d padded by %lld\n", pad_dim, pad_size);
00742 }
00743 bounds->Set_Stride(stride);
00744 stride = stride * abs(bounds->Get_Upper() - bounds->Get_Lower() + 1);
00745 if (trace_split_common)
00746 fprintf(TFile, "upper = %lld, lower = %lld, stride = %lld \n", bounds->Get_Upper(), bounds->Get_Lower(), bounds->Get_Stride());
00747 }
00748 }
00749
00750
00751
00752
00753
00754 static BOOL
00755 Pad_Multi_Dims(COMMON_SNODE *common_snode)
00756 {
00757 ST* s = common_snode->Get_ST();
00758 BOOL to_pad = FALSE;
00759
00760
00761 if (common_snode->Pad())
00762 return TRUE;
00763
00764 if ((TY_kind(ST_type(s)) == KIND_ARRAY)) {
00765
00766 if (trace_split_common)
00767 fprintf(TFile, "Padding common %s \n", ST_name(s));
00768
00769 Store_Orig_Dims(s, common_snode->Get_Bounds_Array());
00770 INT64 lower, upper, stride;
00771 ARB_HANDLE arb_base = TY_arb(ST_type(s));
00772 INT num_dims = ARB_dimension(arb_base);
00773
00774 if (num_dims > 1) {
00775 INT64 pad_size = 1;
00776 INT64 padding;
00777 INT pad_dim;
00778
00779 BOUNDS_ARRAY *bounds_array = common_snode->Get_Bounds_Array();
00780 Is_True(bounds_array!=NULL, (" NULL bounds array in Pad_Multi_Dims \n"));
00781
00782 BOUNDS *b = &(*bounds_array)[0];
00783 if (b->Is_Constant()) {
00784 pad_size = abs(b->Get_Upper() - b->Get_Lower() + 1);
00785 }
00786 else return to_pad;
00787
00788 pad_size = 1;
00789 for (INT i=0; i<num_dims-1; ++i) {
00790 b = &(*bounds_array)[i];
00791 if (b->Is_Constant()) {
00792 lower = b->Get_Lower();
00793 upper = b->Get_Upper();
00794 pad_size = pad_size * abs(upper-lower+1);
00795 padding = Common_Array_Pad_Size(pad_size*(*bounds_array)[0].Get_Stride());
00796 if (trace_split_common)
00797 fprintf(TFile, "padding = %lld, pad_size = %lld \n",padding, pad_size);
00798 if (padding) {
00799 for (INT j =i; j >= 0; --j) {
00800 if ((j != i) && Pad_Dim(&(*bounds_array)[j]))
00801 pad_dim = j;
00802 else
00803 pad_dim =
00804 Get_Pad_Dim(i,((*bounds_array)[0]).Get_Stride(),bounds_array);
00805
00806 INT pad_size1=0;
00807 if (j == i)
00808 pad_size1 = Pad_Size(pad_dim,padding,i,bounds_array,TRUE);
00809 else if (Pad_Dim(&(*bounds_array)[j]))
00810 pad_size1 =
00811 Pad_Size(pad_dim,padding,i,bounds_array,FALSE);
00812
00813 if (Padding_Threshold(pad_size1,pad_dim,bounds_array,arb_base))
00814 {
00815 IPO_Pad_Count += pad_size1;
00816 to_pad = TRUE;
00817 common_snode->Set_Pad();
00818 if (trace_split_common)
00819 fprintf(TFile, "Padding array %s for common %s \n", ST_name(s), ST_name(ST_base(s)));
00820 Update_Bounds_After_Padding(pad_size1, pad_dim, bounds_array);
00821 pad_size = Update_Pad_Size(i,bounds_array);
00822 }
00823 }
00824 }
00825 }
00826
00827 else
00828 return to_pad;
00829 }
00830 }
00831 }
00832 return to_pad;
00833 }
00834
00835
00836
00837
00838
00839 static BOOL
00840 Pad_Common_Elements(COMMON_SNODE_LIST* common_snode_list)
00841 {
00842 BOOL to_pad = FALSE;
00843
00844 COMMON_SNODE_LIST_ITER common_snode_list_iter(common_snode_list);
00845
00846 for (common_snode_list_iter.First();
00847 !common_snode_list_iter.Is_Empty();
00848 common_snode_list_iter.Next())
00849 {
00850 COMMON_SNODE *common_snode = common_snode_list_iter.Cur();
00851 if (!to_pad)
00852 to_pad = Pad_Multi_Dims(common_snode);
00853 else
00854 Pad_Multi_Dims(common_snode);
00855 }
00856 return to_pad;
00857
00858 }
00859
00860
00861
00862
00863
00864
00865
00866 static void
00867 Update_Padding_Size(COMMON_SNODE_TBL *common_snode_tbl)
00868 {
00869 BOOL to_pad = FALSE;
00870 Is_True(common_snode_tbl != NULL, ("Null Table in Update_Padding_Size \n"));
00871
00872 COMMON_SNODE_TBL_ITER common_snode_tbl_iter(common_snode_tbl);
00873 COMMON_SNODE_LIST *snode_list;
00874 STR_IDX common_name;
00875
00876 while (common_snode_tbl_iter.Step (&common_name, &snode_list))
00877 {
00878 if (!snode_list->No_Pad())
00879 {
00880 if (!Pad_Common_Elements(snode_list))
00881 snode_list->Set_No_Pad();
00882 }
00883 }
00884 }
00885
00886
00887
00888
00889
00890 static INT
00891 Padding_Count(COMMON_SNODE_TBL *common_snode_tbl)
00892 {
00893 INT count = 0;
00894 STR_IDX common_name;
00895 COMMON_SNODE_LIST *snode_list;
00896 COMMON_SNODE_TBL_ITER common_snode_tbl_iter(common_snode_tbl);
00897
00898
00899 while (common_snode_tbl_iter.Step (&common_name, &snode_list))
00900 {
00901 if (!snode_list->No_Pad())
00902 ++count;
00903 }
00904 return count;
00905 }
00906
00907
00908
00909
00910
00911
00912 static void
00913 Free_Common_Tbl(COMMON_SNODE_TBL *common_snode_tbl)
00914 {
00915 COMMON_SNODE_LIST *snode_list;
00916 COMMON_SNODE_TBL_ITER common_snode_tbl_iter(common_snode_tbl);
00917
00918 STR_IDX common_name;
00919 while (common_snode_tbl_iter.Step (&common_name, &snode_list))
00920 snode_list->Free_Nodes(&IPA_Pad_Split_Mem_Pool);
00921 }
00922
00923
00924
00925
00926 static void
00927 Print_Split(char *name, FILE *fp, SPLIT_COMMON_DYN_ARRAY *Split_Common_Shape)
00928 {
00929
00930 INT last_idx = Split_Common_Shape->Lastidx();
00931
00932 fprintf(fp,
00933 "=======Recording Split Information for common %s ======= \n",name);
00934 for (INT i=0 ; i<=last_idx;++i)
00935 {
00936 SPLIT_COMMON *split = &(*Split_Common_Shape)[i];
00937 fprintf(fp, "offset = %lld, size = %lld, element_size = %d, split = %d\n",
00938 split->Get_offset(), split->Get_size(), split->Get_element_size(),
00939 split->Get_split_position());
00940 }
00941 }
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962 INT64 Primary_Cache = 16*1024;
00963 INT64 Secondary_Cache = 512*1024;
00964 INT64 Primary_Delta = 819;
00965 INT64 Secondary_Delta = 26214;
00966
00967
00968
00969
00970
00971
00972 static void
00973 Full_Split(SPLIT_COMMON_DYN_ARRAY *split_common_shape)
00974 {
00975 INT count = split_common_shape->Lastidx();
00976 if (count)
00977 {
00978 INT group = (*split_common_shape)[0].Get_group_position();
00979 INT cur_pos = 0;
00980 for (INT i=0; i<=count; ++i)
00981 {
00982 if ((*split_common_shape)[i].Get_group_position() == group)
00983 (*split_common_shape)[i].Set_split_position(cur_pos);
00984 else
00985 {
00986 group = (*split_common_shape)[i].Get_group_position();
00987 cur_pos++;
00988 (*split_common_shape)[i].Set_split_position(cur_pos);
00989 }
00990 }
00991 }
00992 }
00993
00994
00995
00996
00997 static void
00998 Compute_Equivalenced_Split_Regions(SPLIT_COMMON_DYN_ARRAY
00999 *split_common_shape)
01000 {
01001 Full_Split(split_common_shape);
01002 }
01003
01004
01005
01006
01007 static void
01008 Compute_Split_Regions(SPLIT_COMMON_DYN_ARRAY *split_common_shape)
01009 {
01010 INT64 offset, size, element_size, size_bytes;
01011 INT64 current_split = 0;
01012 INT count = split_common_shape->Lastidx();
01013 INT64 current_split_index = 0;
01014 INT current_split_id = 0;
01015 BOOL split_useful = FALSE;
01016
01017 if ((count) && (*split_common_shape)[count].Get_group_position() > 0)
01018 Compute_Equivalenced_Split_Regions(split_common_shape);
01019
01020 for (INT i=0; i<=count; ++i)
01021 {
01022 offset = (*split_common_shape)[i].Get_offset();
01023 size = (*split_common_shape)[i].Get_size();
01024 element_size = (*split_common_shape)[i].Get_element_size();
01025 size_bytes = size*element_size;
01026 split_useful = TRUE;
01027
01028 (*split_common_shape)[i].Set_split_position(current_split_id);
01029
01030
01031 if ((size_bytes >= Primary_Cache) &&
01032 (offset >= Primary_Cache - Primary_Delta)
01033 #ifdef KEY
01034 && (i != 0)
01035 #endif
01036 )
01037 {
01038 offset = offset - current_split;
01039
01040 for (INT j = current_split_index; j <= i && split_useful; j++)
01041 {
01042 INT64 offset_j = (*split_common_shape)[j].Get_offset();
01043 INT64 size_bytes_j =
01044 (*split_common_shape)[j].Get_element_size()*
01045 (*split_common_shape)[j].Get_size();
01046
01047
01048
01049
01050 if (size_bytes_j >= Primary_Cache)
01051 {
01052 INT64 current_offset = offset - offset_j;
01053 INT64 mod_primary = current_offset % Primary_Cache;
01054 INT64 mod_second = current_offset % Secondary_Cache;
01055 if (trace_split_common)
01056 {
01057 fprintf(TFile, "current_offset = %lli, mod_primary = %lli \n", current_offset, mod_primary);
01058 fprintf(TFile, "current_offset = %lli, mod_second = %lli \n", current_offset, mod_second);
01059 }
01060 if ((mod_primary > Primary_Delta) &&
01061 (mod_second > Secondary_Delta))
01062 {
01063 split_useful = FALSE;
01064 }
01065 }
01066 }
01067
01068 if (split_useful)
01069 {
01070 (*split_common_shape)[i].Set_split_position(current_split_id+1);
01071 ++current_split_id;
01072 current_split_index = i+1;
01073 current_split = (*split_common_shape)[i].Get_offset();
01074 }
01075 }
01076 }
01077 }
01078
01079
01080
01081
01082
01083 static BOOL
01084 All_O3(INT num_ir)
01085 {
01086 for (INT i=0; i<num_ir; ++i)
01087 {
01088 SUMMARY_FILE_HEADER *s = IP_FILE_HDR_file_header(IP_File_header[i]);
01089 if (s->Get_opt_level() != 3)
01090 return FALSE;
01091 }
01092 return TRUE;
01093 }
01094
01095
01096
01097
01098 static void
01099 Build_Split_Array(COMMON_SNODE_LIST* snode_list)
01100 {
01101 ST *s = snode_list->Get_ST();
01102 SPLIT_COMMON_DYN_ARRAY *split_array =
01103 snode_list->Get_Split_Array();
01104
01105 Is_True(((ST_sclass(s) == SCLASS_COMMON || ST_sclass(s) ==
01106 SCLASS_DGLOBAL) && TY_kind(ST_type(s)) == KIND_STRUCT), ("Expecting a common ST in Build_Split_Array \n"));
01107
01108 Is_True(split_array != NULL, ("NULL split array in Build_Split_Array \n"));
01109
01110
01111
01112
01113 INT64 ofst = 0;
01114 INT64 size = 0;
01115 INT group = 0;
01116 FLD_ITER fld_iter = Make_fld_iter (TY_fld (Ty_Table[ST_type (s)]));
01117 do {
01118
01119 FLD_HANDLE fld (fld_iter);
01120 if (FLD_equivalence(fld) && (ofst == 0)) {
01121 ofst = FLD_ofst(fld);
01122 size = TY_size(Ty_Table[FLD_type(fld)]);
01123 group++;
01124 }
01125
01126
01127 else if (FLD_equivalence(fld)) {
01128 if ((FLD_ofst(fld) >= ofst) && (FLD_ofst(fld) <= ofst+size))
01129 ;
01130 else if (TY_size(Ty_Table[FLD_type(fld)]) > size)
01131 size = TY_size(Ty_Table[FLD_type(fld)]);
01132 }
01133 else if (ofst != 0) {
01134 ofst = 0;
01135 size = 0;
01136 group++;
01137 }
01138
01139
01140 INT64 element_size = 0;
01141 const TY& fld_type = Ty_Table[FLD_type (fld)];
01142 if (TY_kind(fld_type) == KIND_ARRAY)
01143 element_size = TY_size(TY_etype(fld_type));
01144 else
01145 element_size = TY_size(fld_type);
01146
01147 INT64 total_size = (element_size ? TY_size(fld_type)/element_size : 0);
01148 INT id = split_array->Newidx();
01149 SPLIT_COMMON *node = &(*split_array)[id];
01150 node->Set_Vals(FLD_ofst(fld), total_size, element_size, 0, group);
01151
01152 } while (!FLD_last_field (fld_iter++));
01153 }
01154
01155
01156
01157
01158 static void
01159 Build_Splits(COMMON_SNODE_TBL *common_snode_tbl)
01160 {
01161 STR_IDX common_name;
01162 COMMON_SNODE_LIST *snode_list;
01163 COMMON_SNODE_TBL_ITER common_snode_tbl_iter(common_snode_tbl);
01164
01165
01166 while (common_snode_tbl_iter.Step (&common_name, &snode_list))
01167 {
01168 if (!snode_list->No_Split())
01169 {
01170 Build_Split_Array(snode_list);
01171 if (snode_list->Get_Split_Array()->Elements())
01172 {
01173 SPLIT_COMMON_DYN_ARRAY *split_array =
01174 snode_list->Get_Split_Array();
01175
01176 if (!snode_list->No_Pad())
01177 Full_Split(split_array);
01178 else
01179 Compute_Split_Regions(split_array);
01180 SPLIT_COMMON *split =
01181 &(*split_array)[split_array->Lastidx()];
01182
01183
01184 if (split->Get_split_position() == 0)
01185 snode_list->Set_No_Split();
01186 }
01187 else
01188 snode_list->Set_No_Split();
01189 }
01190 }
01191 }
01192
01193
01194
01195
01196
01197 static INT
01198 Split_Count(COMMON_SNODE_TBL *common_snode_tbl)
01199 {
01200 INT count = 0;
01201 Is_True(common_snode_tbl != NULL, ("Null Table in Split_Count \n"));
01202
01203 COMMON_SNODE_TBL_ITER common_snode_tbl_iter(common_snode_tbl);
01204 COMMON_SNODE_LIST *snode_list;
01205 STR_IDX common_name;
01206
01207 while (common_snode_tbl_iter.Step (&common_name, &snode_list))
01208 {
01209 if (!snode_list->No_Split())
01210 ++count;
01211 }
01212 return count;
01213 }
01214
01215
01216
01217
01218 void Print_Splits(COMMON_SNODE_TBL *common_snode_tbl)
01219 {
01220 Is_True(common_snode_tbl != NULL, ("Null Table in Split_Count \n"));
01221
01222 COMMON_SNODE_TBL_ITER common_snode_tbl_iter(common_snode_tbl);
01223 COMMON_SNODE_LIST *snode_list;
01224 STR_IDX common_name;
01225
01226 while (common_snode_tbl_iter.Step (&common_name, &snode_list))
01227 {
01228 if (!snode_list->No_Split())
01229 Print_Split(ST_name(snode_list->Get_ST()), TFile,
01230 snode_list->Get_Split_Array());
01231 }
01232 }
01233
01234
01235
01236
01237
01238
01239 void
01240 Padding_Analysis(INT num_ir)
01241 {
01242 MEM_POOL_Initialize(&IPA_Pad_Split_Mem_Pool, "IPA pad-split pool", 0);
01243 MEM_POOL_Push(&IPA_Pad_Split_Mem_Pool);
01244
01245 trace_split_common = Get_Trace(TP_IPA, IPA_TRACE_SPLIT_COMMON);
01246 if (trace_split_common)
01247 fprintf(TFile, "Padding and Split Common Analysis\n");
01248
01249
01250 COMMON_SNODE_TBL *common_snode_tbl;
01251 common_snode_tbl = CXX_NEW(COMMON_SNODE_TBL(512, &IPA_Pad_Split_Mem_Pool),
01252 &IPA_Pad_Split_Mem_Pool);
01253
01254 if (!IPA_Enable_Picopt) {
01255 if (trace_split_common)
01256 {
01257 if (IPA_Enable_Padding)
01258 fprintf(TFile, "Padding is OFF since PICOPT is OFF \n");
01259 if (IPA_Enable_Split_Common)
01260 fprintf(TFile, "Splitting is OFF since PICOPT is OFF \n");
01261 }
01262 IPA_Enable_Split_Common = FALSE;
01263 IPA_Enable_Padding = FALSE;
01264 return;
01265 }
01266
01267 if (IPA_Enable_Split_Common && !All_O3(num_ir))
01268 {
01269 IPA_Enable_Split_Common = FALSE;
01270 if (trace_split_common)
01271 fprintf(TFile, "IPA_Enable_Split_Common is OFF, file(s) NOT compiled -O3 -IPA \n");
01272 }
01273
01274
01275 Group_Common_STs(common_snode_tbl);
01276
01277 INT pad_count = 0;
01278 INT split_count = 0;
01279 if (IPA_Enable_Padding)
01280 {
01281
01282 Update_Summaries (common_snode_tbl, num_ir);
01283
01284 Update_Padding_Size(common_snode_tbl);
01285
01286
01287 pad_count = Padding_Count(common_snode_tbl);
01288 if (!pad_count)
01289 IPA_Enable_Padding = FALSE;
01290 if (trace_split_common)
01291 fprintf(TFile, "pad count = %d \n", pad_count);
01292 }
01293
01294 if (IPA_Enable_Split_Common)
01295 {
01296 Build_Splits(common_snode_tbl);
01297 split_count = Split_Count(common_snode_tbl);
01298 if (!split_count)
01299 IPA_Enable_Split_Common = FALSE;
01300 if (trace_split_common)
01301 {
01302 fprintf(TFile, "split count = %d \n", split_count);
01303 Print_Splits(common_snode_tbl);
01304 }
01305 }
01306
01307 if ((pad_count == 0) && (split_count == 0))
01308 {
01309 MEM_POOL_Pop(&IPA_Pad_Split_Mem_Pool);
01310 MEM_POOL_Delete(&IPA_Pad_Split_Mem_Pool);
01311 }
01312 else
01313 IPA_Common_Table = common_snode_tbl;
01314 }