Index: tree-if-conv.c =================================================================== --- tree-if-conv.c (revision 126189) +++ tree-if-conv.c (working copy) @@ -114,7 +114,8 @@ static bool if_convertible_stmt_p (struc 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, b { 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, b 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, b 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 * /* 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 /* ??? 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, t 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 * 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 * 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 l 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 l 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)) - { - 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)); - } + if (first_edge->src == loop->header + || dominated_by_p (CDI_DOMINATORS, + second_edge->src, first_edge->src)) + { + *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 l gcc_assert (*cond); - return first_bb; + return first_edge->src; } @@ -791,10 +823,6 @@ replace_phi_with_cond_gimple_modify_stmt /* 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) { Index: testsuite/gfortran.dg/pr32533.f90 =================================================================== --- testsuite/gfortran.dg/pr32533.f90 (revision 0) +++ testsuite/gfortran.dg/pr32533.f90 (revision 0) @@ -0,0 +1,18 @@ +! { dg-do run } +! { dg-options "-O2 -ftree-vectorize -ffast-math" } +! +! Contributed by Joost VandeVondele +! +SUBROUTINE T(nsubcell,sab_max,subcells) + INTEGER, PARAMETER :: dp=KIND(0.0D0) + REAL(dp) :: sab_max(3), subcells,nsubcell(3) + nsubcell(:) = MIN(MAX(1,NINT(0.5_dp*subcells/sab_max(:))),20) +END SUBROUTINE T + +INTEGER, PARAMETER :: dp=KIND(0.0D0) +REAL(dp) :: sab_max(3), subcells,nsubcell(3) +subcells=2.0_dp +sab_max=0.590060749244805_dp +CALL T(nsubcell,sab_max,subcells) +IF (ANY(nsubcell.NE.2.0_dp)) CALL ABORT() +END Index: testsuite/gcc.dg/tree-ssa/pr31966.c =================================================================== --- testsuite/gcc.dg/tree-ssa/pr31966.c (revision 0) +++ testsuite/gcc.dg/tree-ssa/pr31966.c (revision 0) @@ -0,0 +1,50 @@ +/* Contributed by Jack Lloyd */ + +/* { dg-options "-O2 -ftree-vectorize" } */ +/* { dg-options "-O2 -ftree-vectorize -march=nocona" { target { i?86-*-* x86_64-*-* } } } */ + +typedef unsigned long long word; + +const unsigned int MP_WORD_BITS = 64; +const word MP_WORD_MASK = ~((word)0); +const word MP_WORD_TOP_BIT = (word)1 << (8*sizeof(word) - 1); + +extern void abort (void); + +word do_div(word n1, word n0, word d) +{ + word high = n1 % d, quotient = 0; + unsigned int j; + + for(j = 0; j != MP_WORD_BITS; ++j) + { + word high_top_bit = (high & MP_WORD_TOP_BIT); + + high <<= 1; + high |= (n0 >> (MP_WORD_BITS-1-j)) & 1; + quotient <<= 1; + + if(high_top_bit || high >= d) + { + high -= d; + quotient |= 1; + } + } + + return quotient; +} + +int main() +{ + word result; + + result = do_div(0x0000000000200000ll, + 0x0000000000000000ll, + 0x86E53497CE000000ll); + + + if (result != 0x3CBA83) + abort (); + + return 0; +}