diff options
author | uros <uros@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-07-02 14:26:11 +0000 |
---|---|---|
committer | uros <uros@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-07-02 14:26:11 +0000 |
commit | 58bc8309d5b60a741be3f24372cbf9fdbff79d8a (patch) | |
tree | e6256265d9ec807148d707395d47c9e9a81a175e /gcc/tree-if-conv.c | |
parent | f22edc2d9eb75dca87bf3d2a8e4c12e23e42e01b (diff) | |
download | gcc-58bc8309d5b60a741be3f24372cbf9fdbff79d8a.tar.gz |
PR tree-optimization/31966
PR tree-optimization/32533
* tree-if-conv.c (add_to_dst_predicate_list): Use "edge", not
"basic_block" description as its third argument. Update function
calls to get destination bb from "edge" argument. Save "cond" into
aux field of the edge. Update prototype for changed arguments.
(find_phi_replacement_condition): Operate on incoming edges, not
on predecessor blocks. If there is a condition saved in the
incoming edge aux field, AND it with incoming bb predicate.
Return source bb of the first edge.
(clean_predicate_lists): Clean aux field of outgoing node edges.
(tree_if_conversion): Do not initialize cond variable. Move
variable declaration into the loop.
(replace_phi_with_cond_gimple_modify_stmt): Remove unneded
initializations of new_stmt, arg0 and arg1 variables.
testsuite/ChangeLog:
PR tree-optimization/31966
PR tree-optimization/32533
* gcc.dg/tree-ssa/pr31966.c: New runtime test.
* gfortran.dg/pr32533.f90: Ditto.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@126206 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-if-conv.c')
-rw-r--r-- | gcc/tree-if-conv.c | 118 |
1 files changed, 73 insertions, 45 deletions
diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c index de2933e53ce..bd828bcf463 100644 --- a/gcc/tree-if-conv.c +++ b/gcc/tree-if-conv.c @@ -114,7 +114,8 @@ static bool if_convertible_stmt_p (struct loop *, basic_block, tree); static bool if_convertible_bb_p (struct loop *, basic_block, basic_block); static bool if_convertible_loop_p (struct loop *, bool); static void add_to_predicate_list (basic_block, tree); -static tree add_to_dst_predicate_list (struct loop * loop, basic_block, tree, tree, +static tree add_to_dst_predicate_list (struct loop * loop, edge, + tree, tree, block_stmt_iterator *); static void clean_predicate_lists (struct loop *loop); static basic_block find_phi_replacement_condition (struct loop *loop, @@ -144,7 +145,6 @@ tree_if_conversion (struct loop *loop, bool for_vectorizer) { basic_block bb; block_stmt_iterator itr; - tree cond; unsigned int i; ifc_bbs = NULL; @@ -164,11 +164,11 @@ tree_if_conversion (struct loop *loop, bool for_vectorizer) return false; } - cond = NULL_TREE; - /* Do actual work now. */ for (i = 0; i < loop->num_nodes; i++) { + tree cond; + bb = ifc_bbs [i]; /* Update condition using predicate list. */ @@ -192,7 +192,6 @@ tree_if_conversion (struct loop *loop, bool for_vectorizer) basic_block bb_n = single_succ (bb); if (cond != NULL_TREE) add_to_predicate_list (bb_n, cond); - cond = NULL_TREE; } } @@ -276,12 +275,12 @@ tree_if_convert_cond_expr (struct loop *loop, tree stmt, tree cond, /* Add new condition into destination's predicate list. */ /* If 'c' is true then TRUE_EDGE is taken. */ - add_to_dst_predicate_list (loop, true_edge->dest, cond, + add_to_dst_predicate_list (loop, true_edge, cond, unshare_expr (c), bsi); /* If 'c' is false then FALSE_EDGE is taken. */ c2 = invert_truthvalue (unshare_expr (c)); - add_to_dst_predicate_list (loop, false_edge->dest, cond, c2, bsi); + add_to_dst_predicate_list (loop, false_edge, cond, c2, bsi); /* Now this conditional statement is redundant. Remove it. But, do not remove exit condition! Update exit condition @@ -578,7 +577,15 @@ if_convertible_loop_p (struct loop *loop, bool for_vectorizer ATTRIBUTE_UNUSED) /* ??? Check data dependency for vectorizer. */ /* What about phi nodes ? */ - for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi)) + phi = phi_nodes (bb); + + /* Clear aux field of incoming edges to a bb with a phi node. */ + if (phi) + FOR_EACH_EDGE (e, ei, bb->preds) + e->aux = NULL; + + /* Check statements. */ + for (; phi; phi = PHI_CHAIN (phi)) if (!if_convertible_phi_p (loop, bb, phi)) return false; @@ -615,13 +622,13 @@ add_to_predicate_list (basic_block bb, tree new_cond) existing condition. */ static tree -add_to_dst_predicate_list (struct loop * loop, basic_block bb, +add_to_dst_predicate_list (struct loop * loop, edge e, tree prev_cond, tree cond, block_stmt_iterator *bsi) { tree new_cond = NULL_TREE; - if (!flow_bb_inside_loop_p (loop, bb)) + if (!flow_bb_inside_loop_p (loop, e->dest)) return NULL_TREE; if (prev_cond == boolean_true_node || !prev_cond) @@ -642,6 +649,11 @@ add_to_dst_predicate_list (struct loop * loop, basic_block bb, if (tmp_stmts2) bsi_insert_before (bsi, tmp_stmts2, BSI_SAME_STMT); + /* Add the condition to aux field of the edge. In case edge + destination is a PHI node, this condition will be ANDed with + block predicate to construct complete condition. */ + e->aux = cond; + /* new_cond == prev_cond AND cond */ tmp = build2 (TRUTH_AND_EXPR, boolean_type_node, unshare_expr (prev_cond), cond); @@ -649,22 +661,30 @@ add_to_dst_predicate_list (struct loop * loop, basic_block bb, bsi_insert_before (bsi, tmp_stmt, BSI_SAME_STMT); new_cond = GIMPLE_STMT_OPERAND (tmp_stmt, 0); } - add_to_predicate_list (bb, new_cond); + add_to_predicate_list (e->dest, new_cond); return new_cond; } -/* During if-conversion aux field from basic block is used to hold predicate - list. Clean each basic block's predicate list for the given LOOP. */ +/* During if-conversion aux field from basic block structure is used to hold + predicate list. Clean each basic block's predicate list for the given LOOP. + Also clean aux field of succesor edges, used to hold true and false + condition from conditional expression. */ static void clean_predicate_lists (struct loop *loop) { basic_block *bb; unsigned int i; + edge e; + edge_iterator ei; + bb = get_loop_body (loop); for (i = 0; i < loop->num_nodes; i++) - bb[i]->aux = NULL; - + { + bb[i]->aux = NULL; + FOR_EACH_EDGE (e, ei, bb[i]->succs) + e->aux = NULL; + } free (bb); } @@ -677,13 +697,12 @@ find_phi_replacement_condition (struct loop *loop, basic_block bb, tree *cond, block_stmt_iterator *bsi) { - basic_block first_bb = NULL; - basic_block second_bb = NULL; + edge first_edge, second_edge; tree tmp_cond, new_stmts; gcc_assert (EDGE_COUNT (bb->preds) == 2); - first_bb = (EDGE_PRED (bb, 0))->src; - second_bb = (EDGE_PRED (bb, 1))->src; + first_edge = EDGE_PRED (bb, 0); + second_edge = EDGE_PRED (bb, 1); /* Use condition based on following criteria: 1) @@ -704,42 +723,55 @@ find_phi_replacement_condition (struct loop *loop, S3: x = (c == d) ? b : a; S3 is preferred over S1 and S2*, Make 'b' first_bb and use - its condition. + its condition. 4) If pred B is dominated by pred A then use pred B's condition. See PR23115. */ /* Select condition that is not TRUTH_NOT_EXPR. */ - tmp_cond = first_bb->aux; + tmp_cond = (first_edge->src)->aux; if (TREE_CODE (tmp_cond) == TRUTH_NOT_EXPR) { - basic_block tmp_bb; - tmp_bb = first_bb; - first_bb = second_bb; - second_bb = tmp_bb; + edge tmp_edge; + + tmp_edge = first_edge; + first_edge = second_edge; + second_edge = tmp_edge; } /* Check if FIRST_BB is loop header or not and make sure that FIRST_BB does not dominate SECOND_BB. */ - if (first_bb == loop->header - || dominated_by_p (CDI_DOMINATORS, second_bb, first_bb)) + if (first_edge->src == loop->header + || dominated_by_p (CDI_DOMINATORS, + second_edge->src, first_edge->src)) { - tmp_cond = second_bb->aux; - if (TREE_CODE (tmp_cond) == TRUTH_NOT_EXPR) - { - /* Select non loop header condition but do not switch basic blocks. */ - *cond = invert_truthvalue (unshare_expr (tmp_cond)); - } + *cond = (second_edge->src)->aux; + + /* If there is a condition on an incoming edge, + AND it with the incoming bb predicate. */ + if (second_edge->aux) + *cond = build2 (TRUTH_AND_EXPR, boolean_type_node, + *cond, first_edge->aux); + + if (TREE_CODE (*cond) == TRUTH_NOT_EXPR) + /* We can be smart here and choose inverted + condition without switching bbs. */ + *cond = invert_truthvalue (*cond); else - { - /* Select non loop header condition. */ - first_bb = second_bb; - *cond = first_bb->aux; - } + /* Select non loop header bb. */ + first_edge = second_edge; } else - /* FIRST_BB is not loop header */ - *cond = first_bb->aux; + { + /* FIRST_BB is not loop header */ + *cond = (first_edge->src)->aux; + + /* If there is a condition on an incoming edge, + AND it with the incoming bb predicate. */ + if (first_edge->aux) + *cond = build2 (TRUTH_AND_EXPR, boolean_type_node, + *cond, first_edge->aux); + } /* Create temp. for the condition. Vectorizer prefers to have gimple value as condition. Various targets use different means to communicate @@ -759,7 +791,7 @@ find_phi_replacement_condition (struct loop *loop, gcc_assert (*cond); - return first_bb; + return first_edge->src; } @@ -791,10 +823,6 @@ replace_phi_with_cond_gimple_modify_stmt (tree phi, tree cond, /* Find basic block and initialize iterator. */ bb = bb_for_stmt (phi); - new_stmt = NULL_TREE; - arg_0 = NULL_TREE; - arg_1 = NULL_TREE; - /* Use condition that is not TRUTH_NOT_EXPR in conditional modify expr. */ if (EDGE_PRED (bb, 1)->src == true_bb) { |