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][committed] Fix PR34027 missed folding of n - (n / X) * X


This fixes the code-size regression in PR34027 (2nd try).  I split this
particular case into a folding of a /[fl] b to a / b for unsigned a and
the folding of n +- (n / X) * X' where only handling TRUNC_DIV_EXPR made
me less headaches ;)

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to mainline.

Richard.

2007-11-11  Richard Guenther  <rguenther@suse.de>

	PR middle-end/34027
	* fold-const.c (fold_binary): Fold n - (n / m) * m to n % m.
	(fold_binary): Fold unsinged FLOOR_DIV_EXPR to TRUNC_DIV_EXPR.

	* gcc.dg/pr34027-1.c: New testcase.
	* gcc.dg/pr34027-2.c: Likewise.

Index: fold-const.c
===================================================================
*** fold-const.c	(revision 130076)
--- fold-const.c	(working copy)
*************** fold_binary (enum tree_code code, tree t
*** 9653,9658 ****
--- 9653,9673 ----
  		  return omit_one_operand (type, t1, arg0);
  		}
  	    }
+ 
+ 	  /* X + (X / CST) * -CST is X % CST.  */
+ 	  if (TREE_CODE (arg1) == MULT_EXPR
+ 	      && TREE_CODE (TREE_OPERAND (arg1, 0)) == TRUNC_DIV_EXPR
+ 	      && operand_equal_p (arg0,
+ 				  TREE_OPERAND (TREE_OPERAND (arg1, 0), 0), 0))
+ 	    {
+ 	      tree cst0 = TREE_OPERAND (TREE_OPERAND (arg1, 0), 1);
+ 	      tree cst1 = TREE_OPERAND (arg1, 1);
+ 	      tree sum = fold_binary (PLUS_EXPR, TREE_TYPE (cst1), cst1, cst0);
+ 	      if (sum && integer_zerop (sum))
+ 		return fold_convert (type,
+ 				     fold_build2 (TRUNC_MOD_EXPR,
+ 						  TREE_TYPE (arg0), arg0, cst0));
+ 	    }
  	}
  
        /* Handle (A1 * C1) + (A2 * C2) with A1, A2 or C1, C2 being the
*************** fold_binary (enum tree_code code, tree t
*** 10061,10066 ****
--- 10076,10094 ----
  	  && integer_all_onesp (arg0))
  	return fold_build1 (BIT_NOT_EXPR, type, op1);
  
+ 
+       /* X - (X / CST) * CST is X % CST.  */
+       if (INTEGRAL_TYPE_P (type)
+ 	  && TREE_CODE (arg1) == MULT_EXPR
+ 	  && TREE_CODE (TREE_OPERAND (arg1, 0)) == TRUNC_DIV_EXPR
+ 	  && operand_equal_p (arg0,
+ 			      TREE_OPERAND (TREE_OPERAND (arg1, 0), 0), 0)
+ 	  && operand_equal_p (TREE_OPERAND (TREE_OPERAND (arg1, 0), 1),
+ 			      TREE_OPERAND (arg1, 1), 0))
+ 	return fold_convert (type,
+ 			     fold_build2 (TRUNC_MOD_EXPR, TREE_TYPE (arg0),
+ 					  arg0, TREE_OPERAND (arg1, 1)));
+ 
        if (! FLOAT_TYPE_P (type))
  	{
  	  if (integer_zerop (arg0))
Index: testsuite/gcc.dg/pr34027-1.c
===================================================================
*** testsuite/gcc.dg/pr34027-1.c	(revision 0)
--- testsuite/gcc.dg/pr34027-1.c	(revision 0)
***************
*** 0 ****
--- 1,12 ----
+ /* { dg-do compile } */
+ /* { dg-options "-Os -fdump-tree-optimized" } */
+ 
+ unsigned long foobar(unsigned long ns)
+ {
+   while(ns >= 10000L)
+     ns -= 10000L;
+   return ns;
+ }
+ 
+ /* { dg-final { scan-tree-dump "ns % 10000" "optimized" } } */
+ /* { dg-final { cleanup-tree-dump "optimized" } } */
Index: testsuite/gcc.dg/pr34027-2.c
===================================================================
*** testsuite/gcc.dg/pr34027-2.c	(revision 0)
--- testsuite/gcc.dg/pr34027-2.c	(revision 0)
***************
*** 0 ****
--- 1,10 ----
+ /* { dg-do compile } */
+ /* { dg-options "-fdump-tree-gimple" } */
+ 
+ long foo(long n, long m)
+ {
+   return n - (n / m) * m;
+ }
+ 
+ /* { dg-final { scan-tree-dump "n % m" "gimple" } } */
+ /* { dg-final { cleanup-tree-dump "gimple" } } */
Index: fold-const.c
===================================================================
*** fold-const.c	(revision 130076)
--- fold-const.c	(working copy)
*************** fold_binary (enum tree_code code, tree t
*** 11221,11226 ****
--- 11299,11312 ----
  				  fold_convert (type, arg0), sh_cnt);
  	    }
  	}
+ 
+       /* For unsigned integral types, FLOOR_DIV_EXPR is the same as
+ 	 TRUNC_DIV_EXPR.  Rewrite into the latter in this case.  */
+       if (INTEGRAL_TYPE_P (type)
+ 	  && TYPE_UNSIGNED (type)
+ 	  && code == FLOOR_DIV_EXPR)
+ 	return fold_build2 (TRUNC_DIV_EXPR, type, op0, op1);
+ 
        /* Fall thru */
  
      case ROUND_DIV_EXPR:


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