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 "tree.h"
00026 #include "flags.h"
00027 #include "rtl.h"
00028 #include "tm_p.h"
00029 #include "ggc.h"
00030 #include "basic-block.h"
00031 #include "output.h"
00032 #include "expr.h"
00033 #include "function.h"
00034 #include "diagnostic.h"
00035 #include "timevar.h"
00036 #include "tree-dump.h"
00037 #include "tree-flow.h"
00038 #include "domwalk.h"
00039 #include "real.h"
00040 #include "tree-pass.h"
00041 #include "tree-ssa-propagate.h"
00042 #include "langhooks.h"
00043
00044
00045
00046
00047 struct edge_equivalency
00048 {
00049 tree rhs;
00050 tree lhs;
00051 };
00052
00053
00054
00055
00056
00057
00058
00059
00060 static void
00061 associate_equivalences_with_edges (void)
00062 {
00063 basic_block bb;
00064
00065
00066
00067 FOR_EACH_BB (bb)
00068 {
00069 block_stmt_iterator bsi = bsi_last (bb);
00070 tree stmt;
00071
00072
00073
00074 if (bsi_end_p (bsi))
00075 continue;
00076
00077 stmt = bsi_stmt (bsi);
00078
00079 if (!stmt)
00080 continue;
00081
00082
00083
00084 if (TREE_CODE (stmt) == COND_EXPR)
00085 {
00086 tree cond = COND_EXPR_COND (stmt);
00087 edge true_edge;
00088 edge false_edge;
00089 struct edge_equivalency *equivalency;
00090
00091 extract_true_false_edges_from_block (bb, &true_edge, &false_edge);
00092
00093
00094
00095 if (TREE_CODE (cond) == SSA_NAME
00096 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (cond))
00097 {
00098 equivalency = XNEW (struct edge_equivalency);
00099 equivalency->rhs = constant_boolean_node (1, TREE_TYPE (cond));
00100 equivalency->lhs = cond;
00101 true_edge->aux = equivalency;
00102
00103 equivalency = XNEW (struct edge_equivalency);
00104 equivalency->rhs = constant_boolean_node (0, TREE_TYPE (cond));
00105 equivalency->lhs = cond;
00106 false_edge->aux = equivalency;
00107 }
00108
00109 else if (TREE_CODE (cond) == EQ_EXPR || TREE_CODE (cond) == NE_EXPR)
00110 {
00111 tree op0 = TREE_OPERAND (cond, 0);
00112 tree op1 = TREE_OPERAND (cond, 1);
00113
00114
00115
00116
00117 if (TREE_CODE (op0) == SSA_NAME
00118 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op0)
00119 && TREE_CODE (TREE_TYPE (op0)) == BOOLEAN_TYPE
00120 && is_gimple_min_invariant (op1))
00121 {
00122 if (TREE_CODE (cond) == EQ_EXPR)
00123 {
00124 equivalency = XNEW (struct edge_equivalency);
00125 equivalency->lhs = op0;
00126 equivalency->rhs = (integer_zerop (op1)
00127 ? boolean_false_node
00128 : boolean_true_node);
00129 true_edge->aux = equivalency;
00130
00131 equivalency = XNEW (struct edge_equivalency);
00132 equivalency->lhs = op0;
00133 equivalency->rhs = (integer_zerop (op1)
00134 ? boolean_true_node
00135 : boolean_false_node);
00136 false_edge->aux = equivalency;
00137 }
00138 else
00139 {
00140 equivalency = XNEW (struct edge_equivalency);
00141 equivalency->lhs = op0;
00142 equivalency->rhs = (integer_zerop (op1)
00143 ? boolean_true_node
00144 : boolean_false_node);
00145 true_edge->aux = equivalency;
00146
00147 equivalency = XNEW (struct edge_equivalency);
00148 equivalency->lhs = op0;
00149 equivalency->rhs = (integer_zerop (op1)
00150 ? boolean_false_node
00151 : boolean_true_node);
00152 false_edge->aux = equivalency;
00153 }
00154 }
00155
00156 if (TREE_CODE (op0) == SSA_NAME
00157 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op0)
00158 && (is_gimple_min_invariant (op1)
00159 || (TREE_CODE (op1) == SSA_NAME
00160 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op1))))
00161 {
00162
00163
00164
00165
00166 if (HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (op0)))
00167 && (TREE_CODE (op1) != REAL_CST
00168 || REAL_VALUES_EQUAL (dconst0, TREE_REAL_CST (op1))))
00169 continue;
00170
00171 equivalency = XNEW (struct edge_equivalency);
00172 equivalency->lhs = op0;
00173 equivalency->rhs = op1;
00174 if (TREE_CODE (cond) == EQ_EXPR)
00175 true_edge->aux = equivalency;
00176 else
00177 false_edge->aux = equivalency;
00178
00179 }
00180 }
00181
00182
00183 }
00184
00185
00186
00187
00188 if (TREE_CODE (stmt) == SWITCH_EXPR)
00189 {
00190 tree cond = SWITCH_COND (stmt);
00191
00192 if (TREE_CODE (cond) == SSA_NAME
00193 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (cond))
00194 {
00195 tree labels = SWITCH_LABELS (stmt);
00196 int i, n_labels = TREE_VEC_LENGTH (labels);
00197 tree *info = XCNEWVEC (tree, n_basic_blocks);
00198
00199
00200
00201
00202 for (i = 0; i < n_labels; i++)
00203 {
00204 tree label = TREE_VEC_ELT (labels, i);
00205 basic_block bb = label_to_block (CASE_LABEL (label));
00206
00207
00208 if (CASE_HIGH (label)
00209 || !CASE_LOW (label)
00210 || info[bb->index])
00211 info[bb->index] = error_mark_node;
00212 else
00213 info[bb->index] = label;
00214 }
00215
00216
00217
00218 for (i = 0; i < n_basic_blocks; i++)
00219 {
00220 tree node = info[i];
00221
00222 if (node != NULL
00223 && node != error_mark_node)
00224 {
00225 tree x = fold_convert (TREE_TYPE (cond), CASE_LOW (node));
00226 struct edge_equivalency *equivalency;
00227
00228
00229
00230 equivalency = XNEW (struct edge_equivalency);
00231 equivalency->rhs = x;
00232 equivalency->lhs = cond;
00233 find_edge (bb, BASIC_BLOCK (i))->aux = equivalency;
00234 }
00235 }
00236 free (info);
00237 }
00238 }
00239
00240 }
00241 }
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
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
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293 static VEC(tree,heap) *equiv_stack;
00294
00295
00296
00297
00298 static htab_t equiv;
00299
00300
00301 struct equiv_hash_elt
00302 {
00303
00304 tree value;
00305
00306
00307 VEC(tree,heap) *equivalences;
00308 };
00309
00310 static void uncprop_initialize_block (struct dom_walk_data *, basic_block);
00311 static void uncprop_finalize_block (struct dom_walk_data *, basic_block);
00312 static void uncprop_into_successor_phis (struct dom_walk_data *, basic_block);
00313
00314
00315
00316 static hashval_t
00317 equiv_hash (const void *p)
00318 {
00319 tree value = ((struct equiv_hash_elt *)p)->value;
00320 return iterative_hash_expr (value, 0);
00321 }
00322
00323 static int
00324 equiv_eq (const void *p1, const void *p2)
00325 {
00326 tree value1 = ((struct equiv_hash_elt *)p1)->value;
00327 tree value2 = ((struct equiv_hash_elt *)p2)->value;
00328
00329 return operand_equal_p (value1, value2, 0);
00330 }
00331
00332
00333
00334 static void
00335 equiv_free (void *p)
00336 {
00337 struct equiv_hash_elt *elt = (struct equiv_hash_elt *) p;
00338 VEC_free (tree, heap, elt->equivalences);
00339 free (elt);
00340 }
00341
00342
00343
00344 static void
00345 remove_equivalence (tree value)
00346 {
00347 struct equiv_hash_elt equiv_hash_elt, *equiv_hash_elt_p;
00348 void **slot;
00349
00350 equiv_hash_elt.value = value;
00351 equiv_hash_elt.equivalences = NULL;
00352
00353 slot = htab_find_slot (equiv, &equiv_hash_elt, NO_INSERT);
00354
00355 equiv_hash_elt_p = (struct equiv_hash_elt *) *slot;
00356 VEC_pop (tree, equiv_hash_elt_p->equivalences);
00357 }
00358
00359
00360
00361 static void
00362 record_equiv (tree value, tree equivalence)
00363 {
00364 struct equiv_hash_elt *equiv_hash_elt;
00365 void **slot;
00366
00367 equiv_hash_elt = XNEW (struct equiv_hash_elt);
00368 equiv_hash_elt->value = value;
00369 equiv_hash_elt->equivalences = NULL;
00370
00371 slot = htab_find_slot (equiv, equiv_hash_elt, INSERT);
00372
00373 if (*slot == NULL)
00374 *slot = (void *) equiv_hash_elt;
00375 else
00376 free (equiv_hash_elt);
00377
00378 equiv_hash_elt = (struct equiv_hash_elt *) *slot;
00379
00380 VEC_safe_push (tree, heap, equiv_hash_elt->equivalences, equivalence);
00381 }
00382
00383
00384
00385 static unsigned int
00386 tree_ssa_uncprop (void)
00387 {
00388 struct dom_walk_data walk_data;
00389 basic_block bb;
00390
00391 associate_equivalences_with_edges ();
00392
00393
00394 equiv = htab_create (1024, equiv_hash, equiv_eq, equiv_free);
00395 equiv_stack = VEC_alloc (tree, heap, 2);
00396
00397
00398
00399 calculate_dominance_info (CDI_DOMINATORS);
00400
00401
00402 walk_data.walk_stmts_backward = false;
00403 walk_data.dom_direction = CDI_DOMINATORS;
00404 walk_data.initialize_block_local_data = NULL;
00405 walk_data.before_dom_children_before_stmts = uncprop_initialize_block;
00406 walk_data.before_dom_children_walk_stmts = NULL;
00407 walk_data.before_dom_children_after_stmts = uncprop_into_successor_phis;
00408 walk_data.after_dom_children_before_stmts = NULL;
00409 walk_data.after_dom_children_walk_stmts = NULL;
00410 walk_data.after_dom_children_after_stmts = uncprop_finalize_block;
00411 walk_data.global_data = NULL;
00412 walk_data.block_local_data_size = 0;
00413 walk_data.interesting_blocks = NULL;
00414
00415
00416 init_walk_dominator_tree (&walk_data);
00417
00418
00419
00420 walk_dominator_tree (&walk_data, ENTRY_BLOCK_PTR);
00421
00422
00423 fini_walk_dominator_tree (&walk_data);
00424
00425
00426
00427
00428 htab_delete (equiv);
00429 VEC_free (tree, heap, equiv_stack);
00430 FOR_EACH_BB (bb)
00431 {
00432 edge e;
00433 edge_iterator ei;
00434
00435 FOR_EACH_EDGE (e, ei, bb->succs)
00436 {
00437 if (e->aux)
00438 {
00439 free (e->aux);
00440 e->aux = NULL;
00441 }
00442 }
00443 }
00444 return 0;
00445 }
00446
00447
00448
00449
00450
00451
00452 static void
00453 uncprop_finalize_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
00454 basic_block bb ATTRIBUTE_UNUSED)
00455 {
00456
00457 tree value = VEC_pop (tree, equiv_stack);
00458
00459
00460
00461 if (value != NULL)
00462 remove_equivalence (value);
00463 }
00464
00465
00466
00467 static void
00468 uncprop_into_successor_phis (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
00469 basic_block bb)
00470 {
00471 edge e;
00472 edge_iterator ei;
00473
00474
00475
00476
00477 FOR_EACH_EDGE (e, ei, bb->succs)
00478 {
00479 tree phi = phi_nodes (e->dest);
00480
00481
00482
00483 if (!phi)
00484 continue;
00485
00486
00487 if (e->aux)
00488 {
00489 struct edge_equivalency *equiv = (struct edge_equivalency *) e->aux;
00490 record_equiv (equiv->rhs, equiv->lhs);
00491 }
00492
00493
00494 for ( ; phi; phi = PHI_CHAIN (phi))
00495 {
00496
00497 tree arg = PHI_ARG_DEF (phi, e->dest_idx);
00498 struct equiv_hash_elt equiv_hash_elt;
00499 void **slot;
00500
00501
00502
00503
00504 if (!is_gimple_min_invariant (arg)
00505 && SSA_NAME_VAR (arg) != SSA_NAME_VAR (PHI_RESULT (phi)))
00506 continue;
00507
00508
00509 equiv_hash_elt.value = arg;
00510 equiv_hash_elt.equivalences = NULL;
00511 slot = htab_find_slot (equiv, &equiv_hash_elt, NO_INSERT);
00512
00513 if (slot)
00514 {
00515 struct equiv_hash_elt *elt = (struct equiv_hash_elt *) *slot;
00516 int j;
00517
00518
00519
00520
00521
00522
00523 for (j = VEC_length (tree, elt->equivalences) - 1; j >= 0; j--)
00524 {
00525 tree equiv = VEC_index (tree, elt->equivalences, j);
00526
00527 if (SSA_NAME_VAR (equiv) == SSA_NAME_VAR (PHI_RESULT (phi)))
00528 {
00529 SET_PHI_ARG_DEF (phi, e->dest_idx, equiv);
00530 break;
00531 }
00532 }
00533 }
00534 }
00535
00536
00537 if (e->aux)
00538 {
00539 struct edge_equivalency *equiv = (struct edge_equivalency *) e->aux;
00540 remove_equivalence (equiv->rhs);
00541 }
00542 }
00543 }
00544
00545
00546
00547 static edge
00548 single_incoming_edge_ignoring_loop_edges (basic_block bb)
00549 {
00550 edge retval = NULL;
00551 edge e;
00552 edge_iterator ei;
00553
00554 FOR_EACH_EDGE (e, ei, bb->preds)
00555 {
00556
00557
00558 if (dominated_by_p (CDI_DOMINATORS, e->src, e->dest))
00559 continue;
00560
00561
00562
00563 if (retval)
00564 return NULL;
00565
00566
00567
00568 retval = e;
00569 }
00570
00571 return retval;
00572 }
00573
00574 static void
00575 uncprop_initialize_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
00576 basic_block bb)
00577 {
00578 basic_block parent;
00579 edge e;
00580 bool recorded = false;
00581
00582
00583
00584
00585 parent = get_immediate_dominator (CDI_DOMINATORS, bb);
00586 if (parent)
00587 {
00588 e = single_incoming_edge_ignoring_loop_edges (bb);
00589
00590 if (e && e->src == parent && e->aux)
00591 {
00592 struct edge_equivalency *equiv = (struct edge_equivalency *) e->aux;
00593
00594 record_equiv (equiv->rhs, equiv->lhs);
00595 VEC_safe_push (tree, heap, equiv_stack, equiv->rhs);
00596 recorded = true;
00597 }
00598 }
00599
00600 if (!recorded)
00601 VEC_safe_push (tree, heap, equiv_stack, NULL_TREE);
00602 }
00603
00604 static bool
00605 gate_uncprop (void)
00606 {
00607 return flag_tree_dom != 0;
00608 }
00609
00610 struct tree_opt_pass pass_uncprop =
00611 {
00612 "uncprop",
00613 gate_uncprop,
00614 tree_ssa_uncprop,
00615 NULL,
00616 NULL,
00617 0,
00618 TV_TREE_SSA_UNCPROP,
00619 PROP_cfg | PROP_ssa,
00620 0,
00621 0,
00622 0,
00623 TODO_dump_func | TODO_verify_ssa,
00624 0
00625 };