This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Folding (a ? b : c) op d
- From: Marc Glisse <marc dot glisse at inria dot fr>
- To: gcc-patches at gcc dot gnu dot org
- Cc: ebotcazou at adacore dot com
- Date: Sat, 29 Jun 2013 09:02:31 +0200 (CEST)
- Subject: Folding (a ? b : c) op d
Hello,
this patch changes the test deciding whether to fold "op d" with both
branches in (a ? b : c) op d. I don't know if the new test is right, it
gives what I expect on the new testcase, but I may have missed important
cases. Cc: Eric for comments as the author of the previous conditions.
Passes bootstrap+testsuite on x86_64-unknown-linux-gnu.
2013-06-29 Marc Glisse <marc.glisse@inria.fr>
PR tree-optimization/57755
gcc/
* fold-const.c (fold_binary_op_with_conditional_arg): Change
condition under which the transformation is performed.
gcc/testsuite/
* gcc.dg/pr57755.c: New testcase.
* gcc.dg/binop-notand1a.c: Remove xfail.
* gcc.dg/binop-notand4a.c: Likewise.
--
Marc Glisse
Index: fold-const.c
===================================================================
--- fold-const.c (revision 200556)
+++ fold-const.c (working copy)
@@ -6097,26 +6097,33 @@ constant_boolean_node (bool value, tree
given here), it is the second argument. TYPE is the type of the
original expression. Return NULL_TREE if no simplification is
possible. */
static tree
fold_binary_op_with_conditional_arg (location_t loc,
enum tree_code code,
tree type, tree op0, tree op1,
tree cond, tree arg, int cond_first_p)
{
- tree cond_type = cond_first_p ? TREE_TYPE (op0) : TREE_TYPE (op1);
- tree arg_type = cond_first_p ? TREE_TYPE (op1) : TREE_TYPE (op0);
+ /* ??? This transformation is only worthwhile if we don't have
+ to wrap ARG in a SAVE_EXPR. */
+ if (TREE_SIDE_EFFECTS (arg))
+ return NULL_TREE;
+
+ /* Avoid exponential recursion. */
+ static int depth = 0;
+ if (depth > 1)
+ return NULL_TREE;
+
tree test, true_value, false_value;
tree lhs = NULL_TREE;
tree rhs = NULL_TREE;
- enum tree_code cond_code = COND_EXPR;
if (TREE_CODE (cond) == COND_EXPR
|| TREE_CODE (cond) == VEC_COND_EXPR)
{
test = TREE_OPERAND (cond, 0);
true_value = TREE_OPERAND (cond, 1);
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. */
@@ -6126,54 +6133,49 @@ fold_binary_op_with_conditional_arg (loc
rhs = false_value;
}
else
{
tree testtype = TREE_TYPE (cond);
test = cond;
true_value = constant_boolean_node (true, testtype);
false_value = constant_boolean_node (false, testtype);
}
- if (TREE_CODE (TREE_TYPE (test)) == VECTOR_TYPE)
- cond_code = VEC_COND_EXPR;
-
- /* This transformation is only worthwhile if we don't have to wrap ARG
- in a SAVE_EXPR and the operation can be simplified without recursing
- on at least one of the branches once its pushed inside the COND_EXPR. */
- if (!TREE_CONSTANT (arg)
- && (TREE_SIDE_EFFECTS (arg)
- || TREE_CODE (arg) == COND_EXPR || TREE_CODE (arg) == VEC_COND_EXPR
- || TREE_CONSTANT (true_value) || TREE_CONSTANT (false_value)))
- return NULL_TREE;
+ tree cond_type = cond_first_p ? TREE_TYPE (op0) : TREE_TYPE (op1);
+ tree arg_type = cond_first_p ? TREE_TYPE (op1) : TREE_TYPE (op0);
arg = fold_convert_loc (loc, arg_type, arg);
+ ++depth;
if (lhs == 0)
{
true_value = fold_convert_loc (loc, cond_type, true_value);
if (cond_first_p)
lhs = fold_build2_loc (loc, code, type, true_value, arg);
else
lhs = fold_build2_loc (loc, code, type, arg, true_value);
}
if (rhs == 0)
{
false_value = fold_convert_loc (loc, cond_type, false_value);
if (cond_first_p)
rhs = fold_build2_loc (loc, code, type, false_value, arg);
else
rhs = fold_build2_loc (loc, code, type, arg, false_value);
}
+ --depth;
/* Check that we have simplified at least one of the branches. */
- if (!TREE_CONSTANT (arg) && !TREE_CONSTANT (lhs) && !TREE_CONSTANT (rhs))
+ if (!TREE_CONSTANT (lhs) && !TREE_CONSTANT (rhs))
return NULL_TREE;
+ enum tree_code cond_code = VECTOR_TYPE_P (TREE_TYPE (test))
+ ? VEC_COND_EXPR : COND_EXPR;
return fold_build3_loc (loc, cond_code, type, test, lhs, rhs);
}
/* Subroutine of fold() that checks for the addition of +/- 0.0.
If !NEGATE, return true if ADDEND is +/-0.0 and, for all X of type
TYPE, X + ADDEND is the same as X. If NEGATE, return true if X -
ADDEND is the same as X.
Index: testsuite/gcc.dg/binop-notand1a.c
===================================================================
--- testsuite/gcc.dg/binop-notand1a.c (revision 200556)
+++ testsuite/gcc.dg/binop-notand1a.c (working copy)
@@ -1,13 +1,14 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-optimized" } */
int
foo (char a, unsigned short b)
{
return (a & !a) | (b & !b);
}
/* As long as comparisons aren't boolified and casts from boolean-types
- aren't preserved, the folding of X & !X to zero fails. */
-/* { dg-final { scan-tree-dump-times "return 0" 1 "optimized" { xfail *-*-* } } } */
+ aren't preserved, the direct folding of X & !X to zero fails.
+ However, fold_binary_op_with_conditional_arg undirectly helps it. */
+/* { dg-final { scan-tree-dump-times "return 0" 1 "optimized" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
Index: testsuite/gcc.dg/binop-notand4a.c
===================================================================
--- testsuite/gcc.dg/binop-notand4a.c (revision 200556)
+++ testsuite/gcc.dg/binop-notand4a.c (working copy)
@@ -1,13 +1,14 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-optimized" } */
int
foo (unsigned char a, _Bool b)
{
return (!a & a) | (b & !b);
}
/* As long as comparisons aren't boolified and casts from boolean-types
- aren't preserved, the folding of X & !X to zero fails. */
-/* { dg-final { scan-tree-dump-times "return 0" 1 "optimized" { xfail *-*-* } } } */
+ aren't preserved, the direct folding of X & !X to zero fails.
+ However, fold_binary_op_with_conditional_arg undirectly helps it. */
+/* { dg-final { scan-tree-dump-times "return 0" 1 "optimized" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
Index: testsuite/gcc.dg/pr57755.c
===================================================================
--- testsuite/gcc.dg/pr57755.c (revision 0)
+++ testsuite/gcc.dg/pr57755.c (revision 0)
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-original" } */
+
+int f(int a,int b){
+ return (((a<=3)?-1:0)&((b<=2)?-1:0))!=0;
+}
+
+unsigned g(unsigned a,unsigned b,unsigned c){
+ return ((a<b)?a:c)*3/42+1;
+}
+
+unsigned h(unsigned a,unsigned b){
+ return ((a<=42)?b:0)&b;
+}
+
+/* { dg-final { scan-tree-dump "return a <= 3 && b <= 2;" "original" } } */
+/* { dg-final { scan-tree-dump-times "/ 42" 1 "original" } } */
+/* { dg-final { scan-tree-dump "return a <= 42 \\\? NON_LVALUE_EXPR <b> : 0;" "original" } } */
+/* { dg-final { cleanup-tree-dump "original" } } */
Property changes on: testsuite/gcc.dg/pr57755.c
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision URL
Added: svn:eol-style
+ native