aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRoger Sayle <roger@eyesopen.com>2004-05-20 22:08:46 +0000
committerRoger Sayle <sayle@gcc.gnu.org>2004-05-20 22:08:46 +0000
commitf4085d4c0b2c20282d8197507f6ffb35522aa2e6 (patch)
tree9c22a0479f3c3304c61163c2b0ebb309c08513d1 /gcc
parent3adf6cadbbfe23b96f8e53780ae5f1bc28f01077 (diff)
downloadgcc-f4085d4c0b2c20282d8197507f6ffb35522aa2e6.zip
gcc-f4085d4c0b2c20282d8197507f6ffb35522aa2e6.tar.gz
gcc-f4085d4c0b2c20282d8197507f6ffb35522aa2e6.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog12
-rw-r--r--gcc/fold-const.c185
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.dg/pr3074-1.c10
-rw-r--r--gcc/testsuite/gcc.dg/sequence-pt-1.c2
-rw-r--r--gcc/tree.c9
-rw-r--r--gcc/tree.h5
7 files changed, 43 insertions, 186 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 18cbee3..bc2efca 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,15 @@
+2004-05-20 Roger Sayle <roger@eyesopen.com>
+
+ 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 <pinskia@physics.uc.edu>
* common.opt (ftree-loop-optimize): Remove.
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index ecdc126..03f0cdc 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 c716a32..9a9b2da 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2004-05-20 Roger Sayle <roger@eyesopen.com>
+
+ 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 <falk@debian.org>
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 0000000..c2258d5
--- /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 29f809c..3b92142 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 791cc22..2d1513c 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 991c9fe..ef33d01 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. */