diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e2b5cd64beaa..b4c34975168f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2005-04-21 Devang Patel + + PR optimization/20994 + * tree-if-conv.c (find_phi_replacement_condition): Avoid generating + x = !(a == b) : p , q;. + (pass_if_conversion): Verify stmts and flow. + 2005-04-21 Nathan Sidwell * optabs.c (gen_conditional_trap): Restore #define. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 522c884be9f3..179b8bfe6738 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2005-04-21 Devang Patel + + PR optimization/20994 + * gcc.dg/tree-ssa/ifc-3.c: New test. + 2005-04-20 Joseph S. Myers PR c/12913 diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ifc-3.c b/gcc/testsuite/gcc.dg/tree-ssa/ifc-3.c new file mode 100644 index 000000000000..e853ec4df9bc --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ifc-3.c @@ -0,0 +1,12 @@ +/* PR 20994 */ +/* { dg-do compile } */ +int foo(double* p, double* q) +{ + int i=0; + + for (; q!=p; ++q) + if (*q) + ++i; + + return i; +} diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c index 2770539d435b..4eb5a26e6c9b 100644 --- a/gcc/tree-if-conv.c +++ b/gcc/tree-if-conv.c @@ -665,46 +665,64 @@ find_phi_replacement_condition (struct loop *loop, basic_block bb, tree *cond, block_stmt_iterator *bsi) { - edge e; - basic_block p1 = NULL; - basic_block p2 = NULL; - basic_block true_bb = NULL; + basic_block first_bb = NULL; + basic_block second_bb = NULL; tree tmp_cond; - edge_iterator ei; - FOR_EACH_EDGE (e, ei, bb->preds) - { - if (p1 == NULL) - p1 = e->src; - else - { - gcc_assert (!p2); - p2 = e->src; - } - } + gcc_assert (EDGE_COUNT (bb->preds) == 2); + first_bb = (EDGE_PRED (bb, 0))->src; + second_bb = (EDGE_PRED (bb, 1))->src; - /* Use condition that is not TRUTH_NOT_EXPR in conditional modify expr. */ - tmp_cond = p1->aux; + /* Use condition based on following criteria: + 1) + S1: x = !c ? a : b; + + S2: x = c ? b : a; + + S2 is preferred over S1. Make 'b' first_bb and use its condition. + + 2) Do not make loop header first_bb. + + 3) + S1: x = !(c == d)? a : b; + + S21: t1 = c == d; + S22: x = t1 ? b : a; + + S3: x = (c == d) ? b : a; + + S3 is preferred over S1 and S2*, Make 'b' first_bb and use + its condition. */ + + /* Select condition that is not TRUTH_NOT_EXPR. */ + tmp_cond = first_bb->aux; if (TREE_CODE (tmp_cond) == TRUTH_NOT_EXPR) { - /* If p2 is loop->header than its aux field does not have useful - info. Instead use !(cond) where cond is p1's aux field. */ - if (p2 == loop->header) - *cond = invert_truthvalue (unshare_expr (p1->aux)); + basic_block tmp_bb; + tmp_bb = first_bb; + first_bb = second_bb; + second_bb = first_bb; + } + + /* Check if FIRST_BB is loop header or not. */ + if (first_bb == loop->header) + { + 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)); + } else - *cond = p2->aux; - true_bb = p2; + { + /* Select non loop header condition. */ + first_bb = second_bb; + *cond = first_bb->aux; + } } else - { - /* If p1 is loop->header than its aux field does not have useful - info. Instead use !(cond) where cond is p2's aux field. */ - if (p1 == loop->header) - *cond = invert_truthvalue (unshare_expr (p2->aux)); - else - *cond = p1->aux; - true_bb = p1; - } + /* FIRST_BB is not loop header */ + *cond = first_bb->aux; /* Create temp. for the condition. Vectorizer prefers to have gimple value as condition. Various targets use different means to communicate @@ -722,7 +740,7 @@ find_phi_replacement_condition (struct loop *loop, gcc_assert (*cond); - return true_bb; + return first_bb; } @@ -1119,6 +1137,7 @@ struct tree_opt_pass pass_if_conversion = 0, /* properties_provided */ 0, /* properties_destroyed */ 0, /* todo_flags_start */ - TODO_dump_func | TODO_verify_loops, /* todo_flags_finish */ + TODO_dump_func | TODO_verify_loops | TODO_verify_stmts | TODO_verify_flow, + /* todo_flags_finish */ 0 /* letter */ };