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 #ifdef USE_PCH
00056 #include "cg_pch.h"
00057 #endif // USE_PCH
00058 #pragma hdrstop
00059
00060 #define USE_STANDARD_TYPES
00061 #include <sys/types.h>
00062 #include <map>
00063 #include "defs.h"
00064 #include "mempool.h"
00065 #include "errors.h"
00066 #include "op.h"
00067 #include "tn.h"
00068
00069 #include "wn.h"
00070 #include "opt_alias_interface.h"
00071 #include "opt_points_to.h"
00072 #include "whirl2ops.h"
00073 #include "pf_cg.h"
00074 #include "wn_map.h"
00075
00076 #include "cg.h"
00077 #include "cgir.h"
00078 #include "cg_dep_graph.h"
00079 #include "data_layout.h"
00080
00081 #include "opt_wn.h"
00082 #include "targ_issue_port.h"
00083 #include "targ_cache_info.h"
00084
00085 #include "ipfec_options.h"
00086 #include "be_util.h"
00087
00088 static WN_MAP wn_in_cache;
00089 BOOL cache_analyzed = FALSE;
00090 BOOL trace = FALSE;
00091 MEM_POOL cache_map_pool;
00092
00093
00094
00095 BOOL Cache_L2_Has_Data(OP *op)
00096 {
00097 if (!cache_analyzed) return FALSE;
00098 WN *wn = Get_WN_From_Memory_OP( op );
00099 return wn && WN_MAP32_Get(wn_in_cache,wn)==2 ? TRUE : FALSE;
00100 }
00101
00102
00103
00104 BOOL Cache_L1_Has_Data(OP *op)
00105 {
00106 if (!cache_analyzed) return FALSE;
00107 WN *wn = Get_WN_From_Memory_OP( op );
00108 return wn && WN_MAP32_Get(wn_in_cache,wn)==1 ? TRUE : FALSE;
00109 }
00110
00111
00112
00113 BOOL Cache_L2_Analysis(OP *op)
00114 {
00115 Is_True(OP_load(op)||OP_store(op), ("wrong OP here for only permitting load!"));
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127 WN *wn, *pf_wn;
00128 PF_POINTER *pf_ptr;
00129 if (( wn = Get_WN_From_Memory_OP( op ) )
00130 && (pf_ptr = (PF_POINTER *) WN_MAP_Get(WN_MAP_PREFETCH,wn) ) ) {
00131
00132 UINT confidence;
00133
00134 if (( pf_wn = PF_PTR_wn_pref_1L(pf_ptr) )
00135 && ( (confidence = WN_pf_confidence( pf_wn )) != 1 )
00136 && ( Prefetch_Kind_Enabled( pf_wn ) ) ) {
00137 return FALSE;
00138 }
00139
00140 if (( pf_wn = PF_PTR_wn_pref_2L(pf_ptr) )
00141 && ( (confidence = WN_pf_confidence( pf_wn )) != 1 )
00142 && ( Prefetch_Kind_Enabled( pf_wn ) ) ) {
00143 if ( confidence) {
00144
00145
00146 BB *bb = OP_bb(op);
00147 OP *cur_op;
00148 FOR_ALL_BB_OPs(bb,cur_op) {
00149 if (cur_op == op) continue;
00150 if (OP_load(cur_op)) {
00151 WN *cur_wn = Get_WN_From_Memory_OP( cur_op );
00152 PF_POINTER *cur_pf_ptr = (PF_POINTER *) WN_MAP_Get(WN_MAP_PREFETCH,wn);
00153 if (cur_wn && cur_pf_ptr &&
00154 pf_wn == PF_PTR_wn_pref_2L(cur_pf_ptr)) {
00155 return FALSE;
00156 }
00157 }
00158 }
00159 return TRUE;
00160 }
00161 }
00162 }
00163
00164 if (OP_Prefetched(op)) return FALSE;
00165 if (wn == NULL) return FALSE;
00166
00167 BB *bb = OP_bb(op);
00168 if (BB_loop_head_bb(bb) == NULL ) return FALSE;
00169
00170
00171 OPERATOR opr = OPCODE_operator(WN_opcode(wn));
00172 if (OPERATOR_is_scalar_iload(opr) ||
00173 OPERATOR_is_scalar_istore(opr)) {
00174
00175 if (BB_length(bb) < 7 ) return FALSE;
00176 if (BB_freq(bb)<50000000) return FALSE;
00177 if (!BB_innermost(bb) || BB_nest_level(bb)<2) return FALSE;
00178
00179 TY_IDX ty;
00180 if (OP_load(op)) {ty=WN_load_addr_ty(wn);}
00181 if (OP_load(op) && TY_kind(ty) == KIND_POINTER ||
00182 OP_store(op) ){
00183 WN *kid;
00184 if (OP_load(op)) {
00185 TY_IDX p_ty = TY_pointed(ty);
00186 if (!(TY_kind(p_ty) == KIND_STRUCT && TY_size(p_ty) >= 64 ||
00187 TY_kind(p_ty) == KIND_SCALAR && TY_size(p_ty) <=1 )
00188 ) return FALSE;
00189 kid = WN_kid0(wn);
00190 } else {
00191 kid = WN_kid1(wn);
00192 }
00193
00194 if (kid != NULL) opr = OPCODE_operator(WN_opcode(kid));
00195 else {return FALSE;}
00196 INT pred_idx;
00197 if ( ((pred_idx=WN_offset(kid)-Last_Dedicated_Preg_Offset)>0) ||
00198 OPERATOR_is_scalar_iload(opr) ||
00199 OPERATOR_is_scalar_istore(opr) ) {
00200
00201 if (OPERATOR_is_load(opr) ||
00202 OPERATOR_is_store(opr)) {
00203 DevWarn("Catch L2 case in BB %d", BB_id(bb));
00204 return TRUE;
00205 }
00206 }
00207 }
00208
00209 }
00210
00211 return FALSE;
00212 }
00213
00214
00215 BOOL Cache_L1_Analysis(OP *op)
00216 {
00217 Is_True(OP_load(op)||OP_store(op), ("wrong OP here for only permitting load!"));
00218
00219 if (OP_Prefetched(op)) return TRUE;
00220
00221 WN *wn, *pf_wn;
00222 PF_POINTER *pf_ptr;
00223 if (( wn = Get_WN_From_Memory_OP( op ) )
00224 && (pf_ptr = (PF_POINTER *) WN_MAP_Get(WN_MAP_PREFETCH,wn) ) ) {
00225
00226 UINT confidence;
00227
00228 if (( pf_wn = PF_PTR_wn_pref_1L(pf_ptr) )
00229 && ( (confidence = WN_pf_confidence( pf_wn )) != 1 )
00230 && ( Prefetch_Kind_Enabled( pf_wn ) ) ) {
00231 return TRUE;
00232 }
00233 }
00234 return FALSE;
00235
00236 }
00237
00238
00239 WN *WN_address_kid(WN *wn)
00240 {
00241 if (OPERATOR_is_scalar_iload (WN_operator(wn)) ||
00242 OPERATOR_is_scalar_istore (WN_operator(wn))) {
00243 WN *wn_tmp = OPERATOR_is_load (WN_operator(wn)) ?
00244 WN_kid0(wn) : WN_kid1(wn);
00245 if (OPERATOR_is_load(WN_operator(wn_tmp)))
00246 return wn_tmp;
00247 }
00248 return NULL;
00249 }
00250
00251
00252 BOOL Cache_Access_Same_Line(const ALIAS_MANAGER *am, WN *wn1, WN *wn2, INT *diff)
00253 {
00254 *diff = 0;
00255
00256
00257 if (wn1 == wn2 || wn1 == NULL || wn2 == NULL ) return FALSE;
00258
00259 ALIAS_RESULT alias_result = Aliased(am,wn1,wn2);
00260
00261
00262 if (alias_result == SAME_LOCATION) return TRUE;
00263
00264
00265 WN *addr1 = WN_address_kid(wn1);
00266 WN *addr2 = WN_address_kid(wn2);
00267
00268 if (addr1 && addr2 && alias_result != NOT_ALIASED &&
00269 Aliased(am, addr1,addr2)==SAME_LOCATION &&
00270 ((WN_offset(wn1) - WN_offset(wn2)) <= 256) &&
00271 (WN_offset(wn1) - WN_offset(wn2)) >= -256) {
00272
00273 *diff = WN_offset(wn1) - WN_offset(wn2);
00274 if (*diff < 0) {*diff = WN_offset(wn2) - WN_offset(wn1);}
00275 return TRUE;
00276 }
00277
00278
00279 if (alias_result == POSSIBLY_ALIASED &&
00280 WN_offset(wn1) == WN_offset(wn2) &&
00281 WN_offset(wn1) != 0)
00282 return TRUE;
00283
00284 return FALSE;
00285 }
00286
00287 BOOL Cache_Access_Same_Line(OP *op1, OP *op2, INT *diff)
00288 {
00289 WN *wn1 = Get_WN_From_Memory_OP( op1 );
00290 WN *wn2 = Get_WN_From_Memory_OP( op2 );
00291
00292 if (Alias_Manager && wn1 && wn2) {
00293 return Cache_Access_Same_Line(Alias_Manager, wn1, wn2, diff);
00294 }
00295 return FALSE;
00296 }
00297
00299
00300
00301
00302
00303
00304
00305
00306
00307 BOOL Cache_Has_Conflict(OP *pred, OP *op, INT *distance, BOOL *equal)
00308 {
00309 if (PROCESSOR_Version == 1) return FALSE;
00310
00311 Is_True((OP_load(pred) || OP_store(pred)), ("pred op is not a memory op"));
00312 Is_True((OP_load(op) || OP_store(op)), ("pred op is not a memory op"));
00313
00314 *equal = TRUE;
00315 *distance = 0;
00316 BOOL result = FALSE;
00317
00318
00319
00320 float fraction_clsize = 0.1;
00321
00322 if (!cache_analyzed) return FALSE;
00323
00324 if (OP_has_disjoint_predicate(pred,op)) return FALSE;
00325 if (pred == op || OP_has_immediate(pred) || OP_has_immediate(op))
00326 { return FALSE;}
00327 if (OP_unrolling(op) != OP_unrolling(pred)) return FALSE;
00328
00329 WN *pred_wn = OP_hoisted(pred) ? NULL : Get_WN_From_Memory_OP(pred);
00330 WN *succ_wn = OP_hoisted(op) ? NULL : Get_WN_From_Memory_OP(op);
00331
00332
00333 INT addr_diff;
00334 if ((Alias_Manager && pred_wn && succ_wn &&
00335 Cache_Access_Same_Line(Alias_Manager, pred_wn, succ_wn, &addr_diff)))
00336 {
00337 float diff_threshold = fraction_clsize * Cache_Line_Size(CACHE_L1D);
00338
00339
00340 if (Cache_L1_Has_Data(pred) && addr_diff<= diff_threshold) {
00341 if (OP_store(pred) && OP_load(op)) {
00342 *distance = 3;
00343 result = TRUE;
00344 }
00345
00346
00347
00348 if (OP_store(pred) && OP_store(op)) {
00349 *distance = 1;
00350 result = TRUE;
00351 }
00352 }
00353
00354 diff_threshold = fraction_clsize * Cache_Line_Size(CACHE_L2);
00355
00356
00357 if (Cache_L2_Has_Data(pred)) {
00358
00359
00360 if (OP_load(pred) && OP_store(op) &&
00361 addr_diff <= diff_threshold) {
00362 *distance = 2;
00363 result = TRUE;
00364 }
00365
00366
00367
00368 if (addr_diff < 16 && (OP_load(pred) && OP_load(op) ||
00369 OP_store(pred) && OP_store(op))) {
00370 *distance = 1;
00371 result = TRUE;
00372 }
00373
00374
00375 if (addr_diff < 16 && OP_store(pred) && OP_load(op)) {
00376
00377
00378 }
00379 }
00380
00381 if (result) {
00382 if (trace) {
00383 fprintf(TFile, "Conflict in Cache %d distance %d equal %d in BB %d between\n",
00384 Cache_L2_Has_Data(pred)?2:1,
00385 *distance,
00386 *equal,
00387 BB_id(OP_bb(pred)));
00388 Print_OP_No_SrcLine(pred);
00389 fprintf(TFile, "and\n");
00390 Print_OP_No_SrcLine(op);
00391 }
00392 return TRUE;
00393 }
00394 }
00395 return FALSE;
00396 }
00397 BOOL Cache_Has_Conflict(OP *pred, OP *op, CG_DEP_KIND kind)
00398 {
00399 INT distance;
00400 BOOL equal;
00401 if (kind != CG_DEP_MEMIN &&
00402 kind != CG_DEP_MEMANTI &&
00403 kind != CG_DEP_MEMOUT &&
00404 kind != CG_DEP_MEMREAD) return FALSE;
00405
00406 return Cache_Has_Conflict(pred,op, &distance, &equal);
00407 }
00408 void Cache_Adjust_Latency(OP *pred, OP *op, CG_DEP_KIND kind, INT *latency)
00409 {
00410
00411 INT ident=FALSE;
00412 if (!(OP_load(pred) || OP_store(pred)) ||
00413 !(OP_load(op) ||OP_store(op))) return;
00414 if (kind != CG_DEP_MEMIN &&
00415 kind != CG_DEP_MEMANTI &&
00416 kind != CG_DEP_MEMOUT) return;
00417
00418 INT distance=0;
00419 BOOL equal=TRUE;
00420
00421
00422 if (Cache_Has_Conflict(pred,op, &distance, &equal)) {
00423 if (equal) *latency = MAX(distance,*latency);
00424
00425 if (OP_has_disjoint_predicate(pred,op)) *latency = 0;
00426 }
00427 }
00428
00430
00431
00432 void Cache_Location_Analysis(void)
00433 {
00434
00435 MEM_POOL_Initialize(&cache_map_pool, "Cache MAP", FALSE);
00436 MEM_POOL_Push(&cache_map_pool);
00437 wn_in_cache = WN_MAP32_Create(&cache_map_pool);
00438
00439 cache_analyzed = TRUE;
00440 trace = Get_Trace(TP_A_CANA, 0x1);
00441
00442
00443
00444 for (BB *bb= REGION_First_BB; bb != NULL; bb = BB_next(bb)) {
00445 OP *op;
00446 FOR_ALL_BB_OPs(bb,op) {
00447 if (!OP_load(op) && !OP_store(op)) continue;
00448 WN *wn = Get_WN_From_Memory_OP(op);
00449 if (wn && Cache_L2_Analysis(op)) {
00450 WN_MAP32_Set(wn_in_cache, wn, 2);
00451 continue;
00452 }
00453 if (wn && Cache_L1_Analysis(op)) {
00454 WN_MAP32_Set(wn_in_cache, wn, 1);
00455 continue;
00456 }
00457 }
00458 }
00459 }
00460
00461
00462 void Cache_Analysis_End(void)
00463 {
00464 if (!cache_analyzed) return;
00465
00466
00467 WN_MAP_Delete(wn_in_cache);
00468 MEM_POOL_Pop(&cache_map_pool);
00469 MEM_POOL_Delete(&cache_map_pool);
00470 cache_analyzed = FALSE;
00471 }