This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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
--


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]