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] Fix PR61010


This fixes an endless recursion in folding that appears because
we are inconsistent in how we treat X & CST canonicalization
if we can omit some bits in CST.  The following patch makes
the two places that do this consistent.

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

Richard.

2014-04-30  Richard Biener  <rguenther@suse.de>

	PR middle-end/61010
	* fold-const.c (fold_binary_loc): Consistently avoid
	canonicalizing X & CST away from a CST that is the mask
	of a mode.

	* gcc.dg/torture/pr61010.c: New testcase.

Index: gcc/fold-const.c
===================================================================
*** gcc/fold-const.c	(revision 209928)
--- gcc/fold-const.c	(working copy)
*************** fold_binary_loc (location_t loc,
*** 11426,11432 ****
  	{
  	  double_int c1, c2, c3, msk;
  	  int width = TYPE_PRECISION (type), w;
- 	  bool try_simplify = true;
  
  	  c1 = tree_to_double_int (TREE_OPERAND (arg0, 1));
  	  c2 = tree_to_double_int (arg1);
--- 11426,11431 ----
*************** fold_binary_loc (location_t loc,
*** 11463,11482 ****
  		}
  	    }
  
! 	  /* If X is a tree of the form (Y * K1) & K2, this might conflict
! 	     with that optimization from the BIT_AND_EXPR optimizations.
! 	     This could end up in an infinite recursion.  */
! 	  if (TREE_CODE (TREE_OPERAND (arg0, 0)) == MULT_EXPR
! 	      && TREE_CODE (TREE_OPERAND (TREE_OPERAND (arg0, 0), 1))
! 	                    == INTEGER_CST)
! 	  {
! 	    tree t = TREE_OPERAND (TREE_OPERAND (arg0, 0), 1);
! 	    double_int masked = mask_with_tz (type, c3, tree_to_double_int (t));
! 
! 	    try_simplify = (masked != c1);
! 	  }
! 
! 	  if (try_simplify && c3 != c1)
  	    return fold_build2_loc (loc, BIT_IOR_EXPR, type,
  				    fold_build2_loc (loc, BIT_AND_EXPR, type,
  						     TREE_OPERAND (arg0, 0),
--- 11462,11468 ----
  		}
  	    }
  
! 	  if (c3 != c1)
  	    return fold_build2_loc (loc, BIT_IOR_EXPR, type,
  				    fold_build2_loc (loc, BIT_AND_EXPR, type,
  						     TREE_OPERAND (arg0, 0),
*************** fold_binary_loc (location_t loc,
*** 11866,11881 ****
  	  && TREE_CODE (arg0) == MULT_EXPR
  	  && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
  	{
  	  double_int masked
! 	    = mask_with_tz (type, tree_to_double_int (arg1),
  	                    tree_to_double_int (TREE_OPERAND (arg0, 1)));
  
  	  if (masked.is_zero ())
  	    return omit_two_operands_loc (loc, type, build_zero_cst (type),
  	                                  arg0, arg1);
! 	  else if (masked != tree_to_double_int (arg1))
! 	    return fold_build2_loc (loc, code, type, op0,
! 	                            double_int_to_tree (type, masked));
  	}
  
        /* For constants M and N, if M == (1LL << cst) - 1 && (N & M) == M,
--- 11852,11876 ----
  	  && TREE_CODE (arg0) == MULT_EXPR
  	  && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
  	{
+ 	  double_int darg1 = tree_to_double_int (arg1);
  	  double_int masked
! 	    = mask_with_tz (type, darg1,
  	                    tree_to_double_int (TREE_OPERAND (arg0, 1)));
  
  	  if (masked.is_zero ())
  	    return omit_two_operands_loc (loc, type, build_zero_cst (type),
  	                                  arg0, arg1);
! 	  else if (masked != darg1)
! 	    {
! 	      /* Avoid the transform if arg1 is a mask of some
! 	         mode which allows further optimizations.  */
! 	      int pop = darg1.popcount ();
! 	      if (!(pop >= BITS_PER_UNIT
! 		    && exact_log2 (pop) != -1
! 		    && double_int::mask (pop) == darg1))
! 		return fold_build2_loc (loc, code, type, op0,
! 					double_int_to_tree (type, masked));
! 	    }
  	}
  
        /* For constants M and N, if M == (1LL << cst) - 1 && (N & M) == M,
Index: gcc/testsuite/gcc.dg/torture/pr61010.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr61010.c	(revision 0)
--- gcc/testsuite/gcc.dg/torture/pr61010.c	(working copy)
***************
*** 0 ****
--- 1,8 ----
+ /* { dg-do compile } */
+ 
+ int main (void)
+ {
+   int a = 0;
+   unsigned b = (a * 64 & 192) | 63U;
+   return 0;
+ }


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