diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr71437.c b/gcc/testsuite/gcc.dg/tree-ssa/pr71437.c new file mode 100644 index 0000000..66a5405 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr71437.c @@ -0,0 +1,42 @@ +/* { dg-do compile } */ +/* { dg-options "-ffast-math -O3 -fdump-tree-vrp1-details" } */ + +int I = 50, J = 50; +int S, L; +const int *pL; +const int *pS; + +void bar (float, float); + +void foo (int K) +{ + int k, i, j; + static float LD, SD; + for (k = 0 ; k < K; k++) + { + for( i = 0 ; i < ( I - 1 ) ; i++ ) + { + if( ( L < pL[i+1] ) && ( L >= pL[i] ) ) + break ; + } + + if( i == ( I - 1 ) ) + L = pL[i] ; + LD = (float)( L - pL[i] ) / + (float)( pL[i + 1] - pL[i] ) ; + + for( j = 0 ; j < ( J-1 ) ; j++ ) + { + if( ( S < pS[j+1] ) && ( S >= pS[j] ) ) + break ; + } + + if( j == ( J - 1 ) ) + S = pS[j] ; + SD = (float)( S - pS[j] ) / + (float)( pS[j + 1] - pS[j] ) ; + + bar (LD, SD); + } +} +/* { dg-final { scan-tree-dump-times "Threaded jump " 2 "vrp1" } } */ diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c index efcf3ed..52baad1 100644 --- a/gcc/tree-ssa-loop-niter.c +++ b/gcc/tree-ssa-loop-niter.c @@ -2057,12 +2057,14 @@ tree_simplify_using_condition_1 (tree cond, tree expr) Wrapper around tree_simplify_using_condition_1 that ensures that chains of simple operations in definitions of ssa names in COND are expanded, so that things like casts or incrementing the value of the bound before - the loop do not cause us to fail. */ + the loop do not cause us to fail. COND is expanded before simplifying + if EXPAND is true. */ -static tree -tree_simplify_using_condition (tree cond, tree expr) +tree +tree_simplify_using_condition (tree cond, tree expr, bool expand) { - cond = expand_simple_operations (cond); + if (expand) + cond = expand_simple_operations (cond); return tree_simplify_using_condition_1 (cond, expr); } diff --git a/gcc/tree-ssa-loop-niter.h b/gcc/tree-ssa-loop-niter.h index b009857..4e572df 100644 --- a/gcc/tree-ssa-loop-niter.h +++ b/gcc/tree-ssa-loop-niter.h @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see #define GCC_TREE_SSA_LOOP_NITER_H extern tree expand_simple_operations (tree, tree = NULL); +extern tree tree_simplify_using_condition (tree, tree, bool = true); extern tree simplify_using_initial_conditions (struct loop *, tree); extern bool loop_only_exit_p (const struct loop *, const_edge); extern bool number_of_iterations_exit (struct loop *, edge, diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c index 4949bfa..fa2891d 100644 --- a/gcc/tree-ssa-threadedge.c +++ b/gcc/tree-ssa-threadedge.c @@ -30,6 +30,7 @@ along with GCC; see the file COPYING3. If not see #include "cfgloop.h" #include "gimple-iterator.h" #include "tree-cfg.h" +#include "tree-ssa-loop-niter.h" #include "tree-ssa-threadupdate.h" #include "params.h" #include "tree-ssa-scopedtables.h" @@ -561,6 +562,46 @@ simplify_control_stmt_condition_1 (edge e, if (limit == 0) return NULL_TREE; + /* Simplify condition using assertion conditions. */ + if (handle_dominating_asserts + && TREE_CODE (op0) == SSA_NAME && TREE_CODE (op1) == SSA_NAME) + { + tree assert_op0 = op0, assert_op1 = op1; + tree assert_cond0 = NULL_TREE, assert_cond1 = NULL_TREE; + gimple *def0 = SSA_NAME_DEF_STMT (op0), *def1 = SSA_NAME_DEF_STMT (op1); + + if (is_gimple_assign (def0) + && TREE_CODE (gimple_assign_rhs1 (def0)) == ASSERT_EXPR) + { + assert_op0 = TREE_OPERAND (gimple_assign_rhs1 (def0), 0); + assert_cond0 = TREE_OPERAND (gimple_assign_rhs1 (def0), 1); + } + if (is_gimple_assign (def1) + && TREE_CODE (gimple_assign_rhs1 (def1)) == ASSERT_EXPR) + { + assert_op1 = TREE_OPERAND (gimple_assign_rhs1 (def1), 0); + assert_cond1 = TREE_OPERAND (gimple_assign_rhs1 (def1), 1); + } + + if (assert_cond0 || assert_cond1) + { + tree res = fold_build2 (cond_code, boolean_type_node, + assert_op0, assert_op1); + if (assert_cond0) + { + res = tree_simplify_using_condition (assert_cond0, res, false); + if (is_gimple_min_invariant (res)) + return res; + } + if (assert_cond1) + { + res = tree_simplify_using_condition (assert_cond1, res, false); + if (is_gimple_min_invariant (res)) + return res; + } + } + } + /* We may need to canonicalize the comparison. For example, op0 might be a constant while op1 is an SSA_NAME. Failure to canonicalize will cause us to