diff mbox

Avoid recursion in fold

Message ID alpine.LSU.2.11.1410231504210.9891@zhemvz.fhfr.qr
State New
Headers show

Commit Message

Richard Biener Oct. 23, 2014, 1:10 p.m. UTC
On match-and-simplify branch I run into a recursion folding

 (bool_var & 1) == 0

via !(bool_var & 1) to

 (bool_var & 1) == 0

The appearant recursion prevention (well, not documented as such)
in fold_truth_not_expr doesn't work because we still fold its
result via the various fold_convert calls which on the branch
results in folding (T)((bool_var & 1) == 0) to
(bool_var & 1) == 0 with type T (thus folding that comparison
again).

The fix is simple as TRUTH_NOT_EXPR does not need to have the
same type as its opearand (see fold_truth_not_expr for an existing
example).  Simply avoid all the excessive conversions and build
it with the desired type in the first place.

Btw, the simplification match-and-simplify has but fold-const.c
on trunk has not (yet) which triggers this is

 (simplify
   (convert (eq @0 @1))
   (if (TREE_CODE (type) == BOOLEAN_TYPE)
    (cmp @0 @1))

which folds of comparisons to bool into the comparison itself
(that's from forwprop).

Bootstrap and regtest running on x86_64-unknown-linux-gnu.

Richard.

2014-10-23  Richard Biener  <rguenther@suse.de>

	* fold-const.c (fold_truth_not_expr): Take type as argument.
	(fold_unary_loc): Pass type to fold_truth_not_expr, remove
	redundant conversion.
	(fold_binary_loc): Build TRUTH_NOT_EXPR with the desired type
	directly.
diff mbox

Patch

Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c	(revision 216549)
+++ gcc/fold-const.c	(working copy)
@@ -3125,9 +3125,8 @@  omit_two_operands_loc (location_t loc, t
    problems with the dominator optimizer.  */
 
 static tree
-fold_truth_not_expr (location_t loc, tree arg)
+fold_truth_not_expr (location_t loc, tree type, tree arg)
 {
-  tree type = TREE_TYPE (arg);
   enum tree_code code = TREE_CODE (arg);
   location_t loc1, loc2;
 
@@ -8108,10 +8107,7 @@  fold_unary_loc (location_t loc, enum tre
 	 and its values must be 0 or 1.
 	 ("true" is a fixed value perhaps depending on the language,
 	 but we don't handle values other than 1 correctly yet.)  */
-      tem = fold_truth_not_expr (loc, arg0);
-      if (!tem)
-	return NULL_TREE;
-      return fold_convert_loc (loc, type, tem);
+      return fold_truth_not_expr (loc, type, arg0);
 
     case REALPART_EXPR:
       if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE)
@@ -12628,16 +12624,12 @@  fold_binary_loc (location_t loc,
       /* bool_var != 1 becomes !bool_var. */
       if (TREE_CODE (TREE_TYPE (arg0)) == BOOLEAN_TYPE && integer_onep (arg1)
           && code == NE_EXPR)
-        return fold_convert_loc (loc, type,
-				 fold_build1_loc (loc, TRUTH_NOT_EXPR,
-						  TREE_TYPE (arg0), arg0));
+        return fold_build1_loc (loc, TRUTH_NOT_EXPR, type, arg0);
 
       /* bool_var == 0 becomes !bool_var. */
       if (TREE_CODE (TREE_TYPE (arg0)) == BOOLEAN_TYPE && integer_zerop (arg1)
           && code == EQ_EXPR)
-        return fold_convert_loc (loc, type,
-				 fold_build1_loc (loc, TRUTH_NOT_EXPR,
-						  TREE_TYPE (arg0), arg0));
+        return fold_build1_loc (loc, TRUTH_NOT_EXPR, type, arg0);
 
       /* !exp != 0 becomes !exp */
       if (TREE_CODE (arg0) == TRUTH_NOT_EXPR && integer_zerop (arg1)