00001 #include "tracing.h"
00002 #include "error.h"
00003
00004 #include "mempool_allocator.h"
00005 #include "cxx_memory.h"
00006
00007 #include "op.h"
00008 #include "bb.h"
00009 #include "bb_set.h"
00010
00011 #include "gtn_universe.h"
00012 #include "gtn_set.h"
00013 #include "register.h"
00014 #include "gra_live.h"
00015
00016 #include "dominate.h"
00017 #include "cgtarget.h"
00018 #include "cg_dep_graph.h"
00019 #include "cg_loop.h"
00020
00021 #include "gcm_licm.h"
00022 #include "gcm.h"
00023 #include "loop_dce.h"
00024 #include "tag.h"
00025
00026 #include <list>
00027
00028 extern BOOL LOOP_DCE_Skip_Op_Binary_Search( int );
00029
00030 class LOOP_DCE
00031 {
00032 private:
00033 MEM_POOL *_pool;
00034 LOOP_DESCR *_loop;
00035
00036 BB *_epilog;
00037 BB *_prolog;
00038 BB *_head;
00039 BB *_tail;
00040 BB_SET *_loop_bbs;
00041
00042 BOOL _unsuitable;
00043 BOOL _trace;
00044
00045 public:
00046 LOOP_DCE( LOOP_DESCR *, MEM_POOL * );
00047 ~LOOP_DCE();
00048
00049 void Find_Epilog();
00050 void Find_Prolog();
00051
00052 void Dead_Code_Elimination();
00053 };
00054
00055 LOOP_DCE::LOOP_DCE( LOOP_DESCR *l, MEM_POOL *p) :
00056 _loop(l), _pool(p),
00057 _unsuitable(FALSE),
00058 _epilog(NULL),
00059 _prolog(NULL),
00060 _head(NULL),
00061 _tail(NULL)
00062 {
00063 _head = LOOP_DESCR_loophead(_loop);
00064 _loop_bbs = LOOP_DESCR_bbset(_loop);
00065
00066 _trace = Get_Trace (TP_GCM, GCM_TRACE_DCE );
00067
00068 Find_Prolog();
00069 Find_Epilog();
00070 }
00071
00072 LOOP_DCE::~LOOP_DCE()
00073 {
00074 }
00075
00076
00077
00078
00079
00080 void LOOP_DCE::Find_Prolog()
00081 {
00082 _prolog = Loop_Is_Zdl( _loop );
00083 if( _prolog ){
00084 if( _trace )
00085 fprintf( TFile, "this is zero delay loop\n" );
00086 return;
00087 }else{
00088 if( _trace )
00089 fprintf( TFile, "this is NOT zero delay loop\n" );
00090 }
00091
00092
00093 BBLIST* p;
00094 FOR_ALL_BB_PREDS( _head, p ){
00095 BB* pred = BBLIST_item (p);
00096 if( BB_SET_MemberP( _loop_bbs, pred ) )
00097 continue;
00098 if( _prolog ){
00099 _prolog = NULL;
00100 break;
00101 }else{
00102 _prolog = pred;
00103 }
00104 }
00105
00106 if( _prolog )
00107 Set_BB_gra_spill(_prolog);
00108
00109 if( _prolog && BB_prev(_head) != _prolog ){
00110 DevWarn( "prolog BB:%d not fall through to BB:%d. Ugly due to cflow",
00111 BB_id(_prolog), BB_id(_head) );
00112 DevWarn( "I don't do LICM for it" );
00113 _unsuitable = TRUE;
00114 return;
00115 }else{
00116 if( !_prolog ){
00117 if( _trace )
00118 fprintf( TFile, "Create a new :\n" );
00119 _prolog = CG_LOOP_Gen_And_Prepend_To_Prolog( _head,_loop );
00120
00121 Set_BB_dom_set( _prolog, BS_Create_Empty( 2+PU_BB_Count+1, _pool ) );
00122 BS_UnionD( BB_dom_set(_prolog), BB_dom_set(_head), _pool );
00123 BS_Union1D( BB_dom_set(_prolog), BB_id(_prolog), _pool );
00124 BS_Difference1D( BB_dom_set(_prolog), BB_id(_head) );
00125
00126 Set_BB_pdom_set( _prolog, BS_Create_Empty( 2+PU_BB_Count+1, _pool ) );
00127 BS_UnionD( BB_pdom_set(_prolog), BB_pdom_set(_head), _pool );
00128 BS_Union1D( BB_pdom_set(_prolog), BB_id(_prolog), _pool );
00129 }
00130 if( _trace ){
00131 fprintf( TFile, "Prolog is :\n" );
00132 Print_BB_No_Srclines( _prolog );
00133 }
00134
00135 return;
00136 }
00137 }
00138
00139
00140
00141
00142
00143 void LOOP_DCE::Find_Epilog()
00144 {
00145
00146 BB *bb;
00147 FOR_ALL_BB_SET_members(_loop_bbs, bb) {
00148 BBLIST *succs;
00149 FOR_ALL_BB_SUCCS(bb, succs){
00150 BB *succ = BBLIST_item(succs);
00151 if( !BB_SET_MemberP(_loop_bbs, succ) ){
00152 if( _epilog && succ != _epilog ){
00153 _epilog = NULL;
00154 if( _trace )
00155 fprintf(TFile, "There are more than one epilogs");
00156 break;
00157 }
00158 _epilog = succ;
00159 _tail = bb;
00160 }
00161 }
00162 }
00163
00164 if( _epilog == NULL ){
00165 if( _trace )
00166 fprintf( TFile, "cannot find epilog" );
00167 _unsuitable = TRUE;
00168 }else{
00169 if( _trace )
00170 fprintf( TFile, "epilog is BB:%i\n", BB_id(_epilog) );
00171 }
00172
00173 return;
00174 }
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188 static inline BOOL BB_not_processed( BB *bb, std::list<BB*> processed_list )
00189 {
00190 std::list<BB*>::const_iterator cit = processed_list.begin();
00191 for( ; cit != processed_list.end(); cit++ ){
00192 if( bb == *cit )
00193 return FALSE;
00194 }
00195 return TRUE;
00196 }
00197
00198 static inline BOOL OP_cannot_remove( OP *op )
00199 {
00200 if( OP_xfer(op) || OP_is_loop(op) || OP_volatile(op) ||
00201 OP_store(op) || OP_side_effects(op) ||
00202 TOP_is_c2_store(OP_code(op)) ||
00203 TOP_is_c3_store(OP_code(op)) )
00204 return TRUE;
00205 else
00206 return FALSE;
00207 }
00208
00209 static inline BOOL OP_not_live( OP *op, std::list<OP*> live_ops )
00210 {
00211 std::list<OP*>::const_iterator cit = live_ops.begin();
00212 for( ; cit != live_ops.end(); cit++ ){
00213 if( op == *cit )
00214 return FALSE;
00215 }
00216 return TRUE;
00217 }
00218
00219 void LOOP_DCE::Dead_Code_Elimination()
00220 {
00221 TN_SET *live_tns;
00222 std::list< OP* > live_ops;
00223 std::list< BB* > processed_bbs;
00224 std::list< BB* > workinglist;
00225
00226 if( _unsuitable )
00227 return;
00228
00229 if( _trace )
00230 fprintf( TFile, "==== begin GCM DCE ====\n" );
00231
00232 Is_True( _epilog, ("no epilog") );
00233
00234
00235
00236
00237 GTN_SET *epilog_live_in = BB_live_in(_epilog);
00238 live_tns = TN_SET_Create_Empty( Last_TN + 1, _pool );
00239 for( TN *tn = GTN_SET_Choose(epilog_live_in);
00240 tn != GTN_SET_CHOOSE_FAILURE;
00241 tn = GTN_SET_Choose_Next(epilog_live_in,tn))
00242 {
00243 FmtAssert(TN_is_global_reg(tn),("TN%d is not global",TN_number(tn)));
00244 live_tns = TN_SET_Union1D(live_tns, tn, _pool);
00245 }
00246
00247 if( _trace ){
00248 fprintf( TFile, "the bbs in loop are:" );
00249 BB_SET_Print( _loop_bbs, TFile );
00250
00251 fprintf( TFile, "the live in TNs of epilog:" );
00252 TN_SET_Print( live_tns, TFile );
00253 fprintf( TFile, "\n" );
00254 }
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282 BB *bb = NULL;
00283 TN_SET *old_live_tns;
00284 BOOL changed = TRUE;
00285
00286
00287
00288 BOOL suitable = TRUE;
00289
00290 while( changed && suitable ){
00291 old_live_tns = TN_SET_Copy( live_tns, _pool );
00292 workinglist.push_back( _tail );
00293 processed_bbs.clear();
00294
00295 while( !workinglist.empty() ){
00296
00297 bb = workinglist.front();
00298 workinglist.pop_front();
00299 if( _trace ){
00300 fprintf( TFile, "..DCEing BB:%i\n", BB_id(bb) );
00301 }
00302
00303
00304
00305 processed_bbs.push_back(bb);
00306
00307
00308
00309
00310 BBLIST *pred_list;
00311 FOR_ALL_BB_PREDS( bb, pred_list ){
00312 BB *pred;
00313 pred = BBLIST_item( pred_list );
00314 if( BB_SET_MemberP(_loop_bbs, pred) &&
00315 BB_not_processed(pred, processed_bbs) ){
00316
00317
00318
00319 BOOL all_succs_done = TRUE;
00320 BBLIST *succ_list;
00321 FOR_ALL_BB_SUCCS( pred, succ_list ){
00322 BB *s = BBLIST_item(succ_list);
00323 if( s != pred &&
00324 BB_SET_MemberP(_loop_bbs, s) &&
00325 BB_not_processed(s, processed_bbs) &&
00326 ( s != BB_loop_head_bb(pred) ) ){
00327 all_succs_done = FALSE;
00328 break;
00329 }
00330 }
00331 if( all_succs_done )
00332 workinglist.push_back( pred );
00333 }
00334 }
00335
00336
00337
00338 OP *op;
00339 FOR_ALL_BB_OPs_REV(bb, op){
00340 BOOL removable = TRUE;
00341 int i = 0;
00342 for( i=0; i < OP_results(op); i++ ){
00343 TN *tn = OP_result(op, i);
00344 if( TN_is_label(tn) || TN_is_constant(tn) )
00345 continue;
00346 if( TN_SET_MemberP(live_tns, tn) || TN_is_dedicated(tn) ){
00347 removable = FALSE;
00348 break;
00349 }
00350 }
00351
00352 if( !removable || OP_cannot_remove(op) ){
00353 live_ops.push_back(op);
00354 for( i=0 ; i < OP_opnds(op); i++ ){
00355 TN *tn = OP_opnd(op, i);
00356 if( TN_is_label(tn) || TN_is_constant(tn) )
00357 continue;
00358 live_tns = TN_SET_Union1D( live_tns, tn, _pool );
00359 }
00360 }
00361 }
00362 }
00363 changed = !TN_SET_EqualP( old_live_tns, live_tns );
00364 suitable = ( BB_SET_Size(_loop_bbs) == processed_bbs.size() );
00365 }
00366
00367 if( !suitable ){
00368 fprintf( TFile, "this loop is not suitable for DCE, since it cannot be done with reverse topological sorting\n" );
00369 fprintf( TFile, "==== end GCM DCE ====\n" );
00370 return;
00371 }
00372
00373
00374 bb = NULL;
00375 INT32 del_num = 0;
00376 FOR_ALL_BB_SET_members( _loop_bbs, bb ){
00377 if( _trace ){
00378 fprintf( TFile, "--before delete OPs--\n" );
00379 Print_BB_No_Srclines(bb);
00380 }
00381
00382 if( _trace )
00383 fprintf( TFile, "delete following OP from BB:%i", BB_id(bb) );
00384
00385 OP *op = NULL;
00386 FOR_ALL_BB_OPs_REV(bb, op){
00387 if( OP_not_live(op, live_ops) ){
00388 if( !LOOP_DCE_Skip_Op_Binary_Search(del_num) ){
00389 if( _trace )
00390 Print_OP_No_SrcLine(op);
00391 BB_Remove_Op(bb, op);
00392 del_num++;
00393 }
00394 }
00395 }
00396
00397 if( _trace ){
00398 fprintf( TFile, "--after delete OPs--\n" );
00399 Print_BB_No_Srclines(bb);
00400 }
00401 }
00402
00403 if( _trace ){
00404 fprintf( TFile, " Total delete OPs: %i\n", del_num );
00405 fprintf( TFile, "==== end GCM DCE ====\n" );
00406 }
00407 }
00408
00409
00410
00411
00412
00413
00414 void GCM_Dead_Code_Elimination( LOOP_DESCR *loop, MEM_POOL *pool )
00415 {
00416 LOOP_DCE loop_dce(loop, pool);
00417 loop_dce.Dead_Code_Elimination();
00418 }