00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "config.h"
00022 #include "system.h"
00023 #include "coretypes.h"
00024 #include "tm.h"
00025 #include "errors.h"
00026 #include "ggc.h"
00027 #include "tree.h"
00028 #include "rtl.h"
00029 #include "tm_p.h"
00030 #include "basic-block.h"
00031 #include "timevar.h"
00032 #include "diagnostic.h"
00033 #include "tree-flow.h"
00034 #include "tree-pass.h"
00035 #include "tree-dump.h"
00036 #include "domwalk.h"
00037 #include "flags.h"
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
00067
00068
00069 struct dse_global_data
00070 {
00071
00072
00073
00074
00075
00076 bitmap stores;
00077 };
00078
00079
00080
00081
00082 struct dse_block_local_data
00083 {
00084 bitmap stores;
00085 };
00086
00087 static bool gate_dse (void);
00088 static void tree_ssa_dse (void);
00089 static void dse_initialize_block_local_data (struct dom_walk_data *,
00090 basic_block,
00091 bool);
00092 static void dse_optimize_stmt (struct dom_walk_data *,
00093 basic_block,
00094 block_stmt_iterator);
00095 static void dse_record_phis (struct dom_walk_data *, basic_block);
00096 static void dse_finalize_block (struct dom_walk_data *, basic_block);
00097 static void fix_phi_uses (tree, tree);
00098 static void fix_stmt_v_may_defs (tree, tree);
00099 static void record_voperand_set (bitmap, bitmap *, unsigned int);
00100
00101 static unsigned max_stmt_uid;
00102
00103
00104
00105
00106
00107 static unsigned
00108 get_stmt_uid (tree stmt)
00109 {
00110 if (TREE_CODE (stmt) == PHI_NODE)
00111 return SSA_NAME_VERSION (PHI_RESULT (stmt)) + max_stmt_uid;
00112
00113 return stmt_ann (stmt)->uid;
00114 }
00115
00116
00117
00118
00119
00120 static bool
00121 need_imm_uses_for (tree var)
00122 {
00123 return !is_gimple_reg (var);
00124 }
00125
00126
00127
00128
00129
00130 static void
00131 fix_phi_uses (tree phi, tree stmt)
00132 {
00133 use_operand_p use_p;
00134 def_operand_p def_p;
00135 ssa_op_iter iter;
00136 int i;
00137 edge e;
00138 edge_iterator ei;
00139
00140 FOR_EACH_EDGE (e, ei, PHI_BB (phi)->preds)
00141 if (e->flags & EDGE_ABNORMAL)
00142 break;
00143
00144 get_stmt_operands (stmt);
00145
00146 FOR_EACH_SSA_MAYDEF_OPERAND (def_p, use_p, stmt, iter)
00147 {
00148 tree v_may_def = DEF_FROM_PTR (def_p);
00149 tree v_may_use = USE_FROM_PTR (use_p);
00150
00151
00152
00153 for (i = 0; i < PHI_NUM_ARGS (phi); i++)
00154 if (v_may_def == PHI_ARG_DEF (phi, i))
00155 {
00156 SET_PHI_ARG_DEF (phi, i, v_may_use);
00157
00158 if (e != NULL)
00159 SSA_NAME_OCCURS_IN_ABNORMAL_PHI (v_may_use) = 1;
00160 }
00161 }
00162 }
00163
00164
00165
00166
00167 static void
00168 fix_stmt_v_may_defs (tree stmt1, tree stmt2)
00169 {
00170 bool found = false;
00171 ssa_op_iter iter1;
00172 ssa_op_iter iter2;
00173 use_operand_p use1_p, use2_p;
00174 def_operand_p def1_p, def2_p;
00175
00176 get_stmt_operands (stmt1);
00177 get_stmt_operands (stmt2);
00178
00179
00180 FOR_EACH_SSA_MAYDEF_OPERAND (def1_p, use1_p, stmt1, iter1)
00181 {
00182 tree use = USE_FROM_PTR (use1_p);
00183
00184
00185 FOR_EACH_SSA_MAYDEF_OPERAND (def2_p, use2_p, stmt2, iter2)
00186 {
00187 tree def = DEF_FROM_PTR (def2_p);
00188 if (use == def)
00189 {
00190
00191 SET_USE (use1_p, USE_FROM_PTR (use2_p));
00192 found = true;
00193 break;
00194 }
00195 }
00196
00197
00198
00199 gcc_assert (found);
00200 }
00201 }
00202
00203
00204
00205 static void
00206 record_voperand_set (bitmap global, bitmap *local, unsigned int uid)
00207 {
00208
00209
00210
00211 if (*local == NULL)
00212 *local = BITMAP_GGC_ALLOC ();
00213
00214
00215 bitmap_set_bit (*local, uid);
00216 bitmap_set_bit (global, uid);
00217 }
00218
00219
00220 static void
00221 dse_initialize_block_local_data (struct dom_walk_data *walk_data,
00222 basic_block bb ATTRIBUTE_UNUSED,
00223 bool recycled)
00224 {
00225 struct dse_block_local_data *bd
00226 = VARRAY_TOP_GENERIC_PTR (walk_data->block_data_stack);
00227
00228
00229
00230 if (recycled)
00231 {
00232 if (bd->stores)
00233 bitmap_clear (bd->stores);
00234 }
00235 }
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248 static void
00249 dse_optimize_stmt (struct dom_walk_data *walk_data,
00250 basic_block bb ATTRIBUTE_UNUSED,
00251 block_stmt_iterator bsi)
00252 {
00253 struct dse_block_local_data *bd
00254 = VARRAY_TOP_GENERIC_PTR (walk_data->block_data_stack);
00255 struct dse_global_data *dse_gd = walk_data->global_data;
00256 tree stmt = bsi_stmt (bsi);
00257 stmt_ann_t ann = stmt_ann (stmt);
00258 v_may_def_optype v_may_defs;
00259
00260 get_stmt_operands (stmt);
00261 v_may_defs = V_MAY_DEF_OPS (ann);
00262
00263
00264
00265 if (NUM_V_MAY_DEFS (v_may_defs) == 0)
00266 return;
00267
00268
00269
00270 if (get_call_expr_in (stmt))
00271 return;
00272
00273 if (ann->has_volatile_ops)
00274 return;
00275
00276 if (TREE_CODE (stmt) == MODIFY_EXPR)
00277 {
00278 dataflow_t df = get_immediate_uses (stmt);
00279 unsigned int num_uses = num_immediate_uses (df);
00280 tree use;
00281 tree skipped_phi;
00282
00283
00284 if (num_uses == 0)
00285 {
00286 record_voperand_set (dse_gd->stores, &bd->stores, ann->uid);
00287 return;
00288 }
00289
00290 use = immediate_use (df, 0);
00291 skipped_phi = NULL;
00292
00293
00294
00295
00296
00297
00298
00299 while (num_uses == 1
00300 && TREE_CODE (use) == PHI_NODE
00301 && bitmap_bit_p (dse_gd->stores, get_stmt_uid (use)))
00302 {
00303
00304
00305 if (!skipped_phi)
00306 skipped_phi = use;
00307
00308
00309
00310 df = get_immediate_uses (use);
00311 num_uses = num_immediate_uses (df);
00312 use = immediate_use (df, 0);
00313 }
00314
00315
00316
00317 if (num_uses == 1
00318 && bitmap_bit_p (dse_gd->stores, get_stmt_uid (use))
00319 && operand_equal_p (TREE_OPERAND (stmt, 0),
00320 TREE_OPERAND (use, 0), 0))
00321 {
00322
00323
00324
00325 if (skipped_phi)
00326 fix_phi_uses (skipped_phi, stmt);
00327 else
00328 fix_stmt_v_may_defs (use, stmt);
00329
00330 if (dump_file && (dump_flags & TDF_DETAILS))
00331 {
00332 fprintf (dump_file, " Deleted dead store '");
00333 print_generic_expr (dump_file, bsi_stmt (bsi), dump_flags);
00334 fprintf (dump_file, "'\n");
00335 }
00336
00337
00338
00339
00340 redirect_immediate_uses (stmt, skipped_phi ? skipped_phi : use);
00341
00342
00343
00344 free_df_for_stmt (stmt);
00345
00346
00347
00348 release_defs (stmt);
00349
00350
00351 bsi_remove (&bsi);
00352 }
00353
00354 record_voperand_set (dse_gd->stores, &bd->stores, ann->uid);
00355 }
00356 }
00357
00358
00359
00360 static void
00361 dse_record_phis (struct dom_walk_data *walk_data, basic_block bb)
00362 {
00363 struct dse_block_local_data *bd
00364 = VARRAY_TOP_GENERIC_PTR (walk_data->block_data_stack);
00365 struct dse_global_data *dse_gd = walk_data->global_data;
00366 tree phi;
00367
00368 for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
00369 if (need_imm_uses_for (PHI_RESULT (phi)))
00370 record_voperand_set (dse_gd->stores,
00371 &bd->stores,
00372 get_stmt_uid (phi));
00373 }
00374
00375 static void
00376 dse_finalize_block (struct dom_walk_data *walk_data,
00377 basic_block bb ATTRIBUTE_UNUSED)
00378 {
00379 struct dse_block_local_data *bd
00380 = VARRAY_TOP_GENERIC_PTR (walk_data->block_data_stack);
00381 struct dse_global_data *dse_gd = walk_data->global_data;
00382 bitmap stores = dse_gd->stores;
00383 unsigned int i;
00384 bitmap_iterator bi;
00385
00386
00387 if (bd->stores)
00388 EXECUTE_IF_SET_IN_BITMAP (bd->stores, 0, i, bi)
00389 {
00390 bitmap_clear_bit (stores, i);
00391 }
00392 }
00393
00394 static void
00395 tree_ssa_dse (void)
00396 {
00397 struct dom_walk_data walk_data;
00398 struct dse_global_data dse_gd;
00399 basic_block bb;
00400
00401
00402
00403 max_stmt_uid = 0;
00404 FOR_EACH_BB (bb)
00405 {
00406 block_stmt_iterator bsi;
00407
00408 for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
00409 stmt_ann (bsi_stmt (bsi))->uid = max_stmt_uid++;
00410 }
00411
00412
00413
00414
00415
00416 calculate_dominance_info (CDI_POST_DOMINATORS);
00417
00418
00419 compute_immediate_uses (TDFA_USE_VOPS, need_imm_uses_for);
00420
00421
00422
00423 walk_data.walk_stmts_backward = true;
00424 walk_data.dom_direction = CDI_POST_DOMINATORS;
00425 walk_data.initialize_block_local_data = dse_initialize_block_local_data;
00426 walk_data.before_dom_children_before_stmts = NULL;
00427 walk_data.before_dom_children_walk_stmts = dse_optimize_stmt;
00428 walk_data.before_dom_children_after_stmts = dse_record_phis;
00429 walk_data.after_dom_children_before_stmts = NULL;
00430 walk_data.after_dom_children_walk_stmts = NULL;
00431 walk_data.after_dom_children_after_stmts = dse_finalize_block;
00432
00433 walk_data.block_local_data_size = sizeof (struct dse_block_local_data);
00434
00435
00436 dse_gd.stores = BITMAP_ALLOC (NULL);
00437 walk_data.global_data = &dse_gd;
00438
00439
00440 init_walk_dominator_tree (&walk_data);
00441
00442
00443 walk_dominator_tree (&walk_data, EXIT_BLOCK_PTR);
00444
00445
00446 fini_walk_dominator_tree (&walk_data);
00447
00448
00449 BITMAP_FREE (dse_gd.stores);
00450
00451
00452 free_df ();
00453
00454
00455 free_dominance_info (CDI_POST_DOMINATORS);
00456 }
00457
00458 static bool
00459 gate_dse (void)
00460 {
00461 return flag_tree_dse != 0;
00462 }
00463
00464 struct tree_opt_pass pass_dse = {
00465 "dse",
00466 gate_dse,
00467 tree_ssa_dse,
00468 NULL,
00469 NULL,
00470 0,
00471 TV_TREE_DSE,
00472 PROP_cfg | PROP_ssa
00473 | PROP_alias,
00474 0,
00475 0,
00476 0,
00477 TODO_dump_func | TODO_ggc_collect
00478 | TODO_verify_ssa,
00479 0
00480 };