This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] PR14752: Remove premature folding from C/C++ front-end
- From: Roger Sayle <roger at eyesopen dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 27 Feb 2006 21:40:03 -0700 (MST)
- Subject: [PATCH] PR14752: Remove premature folding from C/C++ front-end
The following patch resolves PR middle-end/14752, now that all of the
necessary mechanics have been added to fold-const.c. Unfortunately,
it turns out that the reason Kazu's original testcase wasn't being
optimized is because the C family front-ends were producing valid but
non-canonical trees and missing optimization opportunities by attempting
a number of constant folding transformations early in
c_common_truthvalue_conversion.
For example, the BIT_AND_EXPR case, was building an unfolded NOP_EXPR
if the second operand was the constant one, resulting in trees of the
form (T)(X & 1), where the rest of fold is expecting (T)X & 1. Calling
fold_build1 or fold_convert would have fixed this. However, as shown
by PR21137, there are some optimizations that apply to "(X & 1) != 0"
but that don't apply to "(X & 1)". Making the "!= 0" in the
truthvalue conversion visible to the middle-end improves things.
Interestingly, the BIT_XOR_EXPR optimization, until recently was only
performed in c_common_truthvalue_conversion, but this has recently been
added to fold to resolve PR middle-end/23673.
The following patch removes some transformations from the C/C++/ObjC
front-ends, allowing them to be performed by the middle-end (which
now does a better job). The result is that removing these duplicate
lines of code, allows the test case below to pass!
The following patch has been tested on x86_64-unknown-linux-gnu with
a full "make bootstrap", all default languages, and regression tested
with a top-level "make -k check" with no new failures.
Ok for mainline?
2006-02-27 Roger Sayle <roger@eyesopen.com>
PR middle-end/14752
* c-common.c (c_common_truthvalue_conversion) <MINUS_EXPR,
BIT_XOR_EXPR, BIT_AND_EXPR>: Delete. Let fold optimize these
cases via the construction of "expr != 0".
* gcc.dg/fold-eqandshift-2.c: New test case.
Index: c-common.c
===================================================================
*** c-common.c (revision 111486)
--- c-common.c (working copy)
*************** c_common_truthvalue_conversion (tree exp
*** 2537,2573 ****
return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0));
break;
- case MINUS_EXPR:
- /* Perhaps reduce (x - y) != 0 to (x != y). The expressions
- aren't guaranteed to the be same for modes that can represent
- infinity, since if x and y are both +infinity, or both
- -infinity, then x - y is not a number.
-
- Note that this transformation is safe when x or y is NaN.
- (x - y) is then NaN, and both (x - y) != 0 and x != y will
- be false. */
- if (HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (TREE_OPERAND (expr, 0)))))
- break;
- /* Fall through.... */
- case BIT_XOR_EXPR:
- /* This and MINUS_EXPR can be changed into a comparison of the
- two objects. */
- if (TREE_TYPE (TREE_OPERAND (expr, 0))
- == TREE_TYPE (TREE_OPERAND (expr, 1)))
- return fold_build2 (NE_EXPR, truthvalue_type_node,
- TREE_OPERAND (expr, 0), TREE_OPERAND (expr, 1));
- return fold_build2 (NE_EXPR, truthvalue_type_node,
- TREE_OPERAND (expr, 0),
- fold_convert (TREE_TYPE (TREE_OPERAND (expr, 0)),
- TREE_OPERAND (expr, 1)));
-
- case BIT_AND_EXPR:
- if (integer_onep (TREE_OPERAND (expr, 1))
- && TREE_TYPE (expr) != truthvalue_type_node)
- /* Using convert here would cause infinite recursion. */
- return build1 (NOP_EXPR, truthvalue_type_node, expr);
- break;
-
case MODIFY_EXPR:
if (!TREE_NO_WARNING (expr))
warning (OPT_Wparentheses,
--- 2537,2542 ----
/* PR middle-end/14752 */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-original" } */
void bar (void);
void foo (unsigned int a)
{
if ((a >> 2) & 1)
bar ();
}
void baz (unsigned int b)
{
if ((~b >> 2) & 1)
bar ();
}
/* { dg-final { scan-tree-dump-times "\\(a \& 4\\) != 0" 1 "original" } } */
/* { dg-final { scan-tree-dump-times "\\(b \& 4\\) == 0" 1 "original" } } */
/* { dg-final { cleanup-tree-dump "original" } } */
Roger
--