From: Roger Sayle Date: Thu, 20 May 2004 22:08:46 +0000 (+0000) Subject: re PR middle-end/3074 (Statement with no effect not flagged with -Wall) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f4085d4c0b2c20282d8197507f6ffb35522aa2e6;p=gcc.git re PR middle-end/3074 (Statement with no effect not flagged with -Wall) PR middle-end/3074 * fold-const.c (strip_compound_expr): Delete function. (count_cond): Delete function. (fold_binary_op_with_conditional_arg): Only perform transformations "a + (b?c:d) -> b ? a+c : a+d" and "(b?c:d) + a -> b ? c+a : d+a" when a is constant. This greatly simplifies this routine. * tree.c (saved_expr_p): Delete function. * tree.h (saved_expr_p): Delete function prototype. * gcc.dg/pr3074-1.c: New test case. * gcc.dg/sequence-pt-1.c: Remove an XFAIL. From-SVN: r82071 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 18cbee3547f..bc2efca0ab5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2004-05-20 Roger Sayle + + PR middle-end/3074 + * fold-const.c (strip_compound_expr): Delete function. + (count_cond): Delete function. + (fold_binary_op_with_conditional_arg): Only perform transformations + "a + (b?c:d) -> b ? a+c : a+d" and "(b?c:d) + a -> b ? c+a : d+a" + when a is constant. This greatly simplifies this routine. + + * tree.c (saved_expr_p): Delete function. + * tree.h (saved_expr_p): Delete function prototype. + 2004-05-20 Andrew Pinski * common.opt (ftree-loop-optimize): Remove. diff --git a/gcc/fold-const.c b/gcc/fold-const.c index ecdc126db7e..03f0cdcaaf4 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -98,10 +98,8 @@ static tree fold_truthop (enum tree_code, tree, tree, tree); static tree optimize_minmax_comparison (tree); static tree extract_muldiv (tree, tree, enum tree_code, tree); static tree extract_muldiv_1 (tree, tree, enum tree_code, tree); -static tree strip_compound_expr (tree, tree); static int multiple_of_p (tree, tree, tree); static tree constant_boolean_node (int, tree); -static int count_cond (tree, int); static tree fold_binary_op_with_conditional_arg (enum tree_code, tree, tree, tree, int); static bool fold_real_zero_addition_p (tree, tree, int); @@ -4738,40 +4736,6 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type) return 0; } -/* If T contains a COMPOUND_EXPR which was inserted merely to evaluate - S, a SAVE_EXPR, return the expression actually being evaluated. Note - that we may sometimes modify the tree. */ - -static tree -strip_compound_expr (tree t, tree s) -{ - enum tree_code code = TREE_CODE (t); - - /* See if this is the COMPOUND_EXPR we want to eliminate. */ - if (code == COMPOUND_EXPR && TREE_CODE (TREE_OPERAND (t, 0)) == CONVERT_EXPR - && TREE_OPERAND (TREE_OPERAND (t, 0), 0) == s) - return TREE_OPERAND (t, 1); - - /* See if this is a COND_EXPR or a simple arithmetic operator. We - don't bother handling any other types. */ - else if (code == COND_EXPR) - { - TREE_OPERAND (t, 0) = strip_compound_expr (TREE_OPERAND (t, 0), s); - TREE_OPERAND (t, 1) = strip_compound_expr (TREE_OPERAND (t, 1), s); - TREE_OPERAND (t, 2) = strip_compound_expr (TREE_OPERAND (t, 2), s); - } - else if (TREE_CODE_CLASS (code) == '1') - TREE_OPERAND (t, 0) = strip_compound_expr (TREE_OPERAND (t, 0), s); - else if (TREE_CODE_CLASS (code) == '<' - || TREE_CODE_CLASS (code) == '2') - { - TREE_OPERAND (t, 0) = strip_compound_expr (TREE_OPERAND (t, 0), s); - TREE_OPERAND (t, 1) = strip_compound_expr (TREE_OPERAND (t, 1), s); - } - - return t; -} - /* Return a node which has the indicated constant VALUE (either 0 or 1), and is of the indicated TYPE. */ @@ -4792,25 +4756,6 @@ constant_boolean_node (int value, tree type) } } -/* Utility function for the following routine, to see how complex a nesting of - COND_EXPRs can be. EXPR is the expression and LIMIT is a count beyond which - we don't care (to avoid spending too much time on complex expressions.). */ - -static int -count_cond (tree expr, int lim) -{ - int ctrue, cfalse; - - if (TREE_CODE (expr) != COND_EXPR) - return 0; - else if (lim <= 0) - return 0; - - ctrue = count_cond (TREE_OPERAND (expr, 1), lim - 1); - cfalse = count_cond (TREE_OPERAND (expr, 2), lim - 1 - ctrue); - return MIN (lim, 1 + ctrue + cfalse); -} - /* Transform `a + (b ? x : y)' into `b ? (a + x) : (a + y)'. Transform, `a + (x < y)' into `(x < y) ? (a + 1) : (a + 0)'. Here CODE corresponds to the `+', COND to the `(b ? x : y)' or `(x < y)' @@ -4827,53 +4772,13 @@ fold_binary_op_with_conditional_arg (enum tree_code code, tree type, tree test, true_value, false_value; tree lhs = NULL_TREE; tree rhs = NULL_TREE; - /* In the end, we'll produce a COND_EXPR. Both arms of the - conditional expression will be binary operations. The left-hand - side of the expression to be executed if the condition is true - will be pointed to by TRUE_LHS. Similarly, the right-hand side - of the expression to be executed if the condition is true will be - pointed to by TRUE_RHS. FALSE_LHS and FALSE_RHS are analogous -- - but apply to the expression to be executed if the conditional is - false. */ - tree *true_lhs; - tree *true_rhs; - tree *false_lhs; - tree *false_rhs; - /* These are the codes to use for the left-hand side and right-hand - side of the COND_EXPR. Normally, they are the same as CODE. */ - enum tree_code lhs_code = code; - enum tree_code rhs_code = code; - /* And these are the types of the expressions. */ - tree lhs_type = type; - tree rhs_type = type; - int save = 0; - - if (TREE_CODE (cond) != COND_EXPR - && TREE_CODE_CLASS (code) == '<') - return NULL_TREE; - - if (TREE_CODE (arg) == COND_EXPR - && count_cond (cond, 25) + count_cond (arg, 25) > 25) - return NULL_TREE; - if (TREE_SIDE_EFFECTS (arg) - && (lang_hooks.decls.global_bindings_p () != 0 - || CONTAINS_PLACEHOLDER_P (arg))) + /* This transformation is only worthwhile if we don't have to wrap + arg in a SAVE_EXPR, and the operation can be simplified on atleast + one of the branches once its pushed inside the COND_EXPR. */ + if (!TREE_CONSTANT (arg)) return NULL_TREE; - if (cond_first_p) - { - true_rhs = false_rhs = &arg; - true_lhs = &true_value; - false_lhs = &false_value; - } - else - { - true_lhs = false_lhs = &arg; - true_rhs = &true_value; - false_rhs = &false_value; - } - if (TREE_CODE (cond) == COND_EXPR) { test = TREE_OPERAND (cond, 0); @@ -4881,28 +4786,11 @@ fold_binary_op_with_conditional_arg (enum tree_code code, tree type, false_value = TREE_OPERAND (cond, 2); /* If this operand throws an expression, then it does not make sense to try to perform a logical or arithmetic operation - involving it. Instead of building `a + throw 3' for example, - we simply build `a, throw 3'. */ + involving it. */ if (VOID_TYPE_P (TREE_TYPE (true_value))) - { - if (! cond_first_p) - { - lhs_code = COMPOUND_EXPR; - lhs_type = void_type_node; - } - else - lhs = true_value; - } + lhs = true_value; if (VOID_TYPE_P (TREE_TYPE (false_value))) - { - if (! cond_first_p) - { - rhs_code = COMPOUND_EXPR; - rhs_type = void_type_node; - } - else - rhs = false_value; - } + rhs = false_value; } else { @@ -4912,60 +4800,15 @@ fold_binary_op_with_conditional_arg (enum tree_code code, tree type, false_value = fold_convert (testtype, integer_zero_node); } - /* If ARG is complex we want to make sure we only evaluate it once. Though - this is only required if it is volatile, it might be more efficient even - if it is not. However, if we succeed in folding one part to a constant, - we do not need to make this SAVE_EXPR. Since we do this optimization - primarily to see if we do end up with constant and this SAVE_EXPR - interferes with later optimizations, suppressing it when we can is - important. - - If we are not in a function, we can't make a SAVE_EXPR, so don't try to - do so. Don't try to see if the result is a constant if an arm is a - COND_EXPR since we get exponential behavior in that case. */ - - if (saved_expr_p (arg)) - save = 1; - else if (lhs == 0 && rhs == 0 - && !TREE_CONSTANT (arg) - && lang_hooks.decls.global_bindings_p () == 0 - && ((TREE_CODE (arg) != VAR_DECL && TREE_CODE (arg) != PARM_DECL) - || TREE_SIDE_EFFECTS (arg))) - { - if (TREE_CODE (true_value) != COND_EXPR) - lhs = fold (build (lhs_code, lhs_type, *true_lhs, *true_rhs)); - - if (TREE_CODE (false_value) != COND_EXPR) - rhs = fold (build (rhs_code, rhs_type, *false_lhs, *false_rhs)); - - if ((lhs == 0 || ! TREE_CONSTANT (lhs)) - && (rhs == 0 || !TREE_CONSTANT (rhs))) - { - arg = save_expr (arg); - lhs = rhs = 0; - save = saved_expr_p (arg); - } - } - if (lhs == 0) - lhs = fold (build (lhs_code, lhs_type, *true_lhs, *true_rhs)); + lhs = fold (cond_first_p ? build2 (code, type, true_value, arg) + : build2 (code, type, arg, true_value)); if (rhs == 0) - rhs = fold (build (rhs_code, rhs_type, *false_lhs, *false_rhs)); - - test = fold (build (COND_EXPR, type, test, lhs, rhs)); - - /* If ARG involves a SAVE_EXPR, we need to ensure it is evaluated - ahead of the COND_EXPR we made. Otherwise we would have it only - evaluated in one branch, with the other branch using the result - but missing the evaluation code. Beware that the save_expr call - above might not return a SAVE_EXPR, so testing the TREE_CODE - of ARG is not enough to decide here. */ - if (save) - return build (COMPOUND_EXPR, type, - fold_convert (void_type_node, arg), - strip_compound_expr (test, arg)); - else - return fold_convert (type, test); + rhs = fold (cond_first_p ? build2 (code, type, false_value, arg) + : build2 (code, type, arg, false_value)); + + test = fold (build3 (COND_EXPR, type, test, lhs, rhs)); + return fold_convert (type, test); } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c716a323162..9a9b2daaa81 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2004-05-20 Roger Sayle + + PR middle-end/3074 + * gcc.dg/pr3074-1.c: New test case. + * gcc.dg/sequence-pt-1.c: Remove an XFAIL. + 2004-05-20 Falk Hueffner PR other/15526 diff --git a/gcc/testsuite/gcc.dg/pr3074-1.c b/gcc/testsuite/gcc.dg/pr3074-1.c new file mode 100644 index 00000000000..c2258d57bb1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr3074-1.c @@ -0,0 +1,10 @@ +/* PR middle-end/3074 */ +/* { dg-do compile } */ +/* { dg-options "-Wall" } */ + +void foo() +{ + int a; + 5 * (a == 1) | (a == 2); /* { dg-warning "no effect" "no effect" } */ +} + diff --git a/gcc/testsuite/gcc.dg/sequence-pt-1.c b/gcc/testsuite/gcc.dg/sequence-pt-1.c index 29f809ca064..3b9214233cd 100644 --- a/gcc/testsuite/gcc.dg/sequence-pt-1.c +++ b/gcc/testsuite/gcc.dg/sequence-pt-1.c @@ -56,7 +56,7 @@ foo (int a, int b, int n, int p, int *ptr, struct s *sptr, ap[a+=1] += a++; /* { dg-warning "undefined" "sequence point warning" } */ a = a++, b = a; /* { dg-warning "undefined" "sequence point warning" } */ b = a, a = a++; /* { dg-warning "undefined" "sequence point warning" } */ - a = (b++ ? n : a) + b; /* { dg-warning "undefined" "sequence point warning" { xfail *-*-* } } */ + a = (b++ ? n : a) + b; /* { dg-warning "undefined" "sequence point warning" } */ b ? a = a++ : a; /* { dg-warning "undefined" "sequence point warning" } */ b && (a = a++); /* { dg-warning "undefined" "sequence point warning" } */ (a = a++) && b; /* { dg-warning "undefined" "sequence point warning" } */ diff --git a/gcc/tree.c b/gcc/tree.c index 791cc221349..2d1513c98ec 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -1432,15 +1432,6 @@ skip_simple_arithmetic (tree expr) return inner; } -/* Return TRUE if EXPR is a SAVE_EXPR or wraps simple arithmetic around a - SAVE_EXPR. Return FALSE otherwise. */ - -bool -saved_expr_p (tree expr) -{ - return TREE_CODE (skip_simple_arithmetic (expr)) == SAVE_EXPR; -} - /* Arrange for an expression to be expanded multiple independent times. This is useful for cleanup actions, as the backend can expand them multiple times in different places. */ diff --git a/gcc/tree.h b/gcc/tree.h index 991c9fe86c9..ef33d010657 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -3177,11 +3177,6 @@ extern tree save_expr (tree); extern tree skip_simple_arithmetic (tree); -/* Return TRUE if EXPR is a SAVE_EXPR or wraps simple arithmetic around a - SAVE_EXPR. Return FALSE otherwise. */ - -extern bool saved_expr_p (tree); - /* Returns the index of the first non-tree operand for CODE, or the number of operands if all are trees. */