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 PR43007


We no longer shorten the division in

unsigned int apply_frontend_param (unsigned int spi_bias)
{
  static const int ppm = 8000;
  spi_bias /= 1000ULL + ppm/1000;
  return spi_bias;
}

because the C frontend now folds in the ppm constant early and
presents convert_to_integer with something it does not handle,
(long long unsigned int) spi_bias / 1008 vs. the previous
(long long unsigned int) spi_bias / ((long long unsigned int) ((int) ppm /
1000) + 1000)

The following patch fixes this.

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

Richard.

2010-02-10  Richard Guenther  <rguenther@suse.de>

	PR c/43007
	* tree.c (get_unwidened): Handle constants.
	* convert.c (convert_to_integer): Handle TRUNC_DIV_EXPR.

	* gcc.c-torture/execute/20100209-1.c: New testcase.
	* gcc.dg/fold-div-3.c: Likewise.

Index: gcc/tree.c
===================================================================
--- gcc/tree.c	(revision 156620)
+++ gcc/tree.c	(working copy)
@@ -7623,6 +7623,14 @@ get_unwidened (tree op, tree for_type)
 	}
     }
 
+  /* If we finally reach a constant see if it fits in for_type and
+     in that case convert it.  */
+  if (for_type
+      && TREE_CODE (win) == INTEGER_CST
+      && TREE_TYPE (win) != for_type
+      && int_fits_type_p (win, for_type))
+    win = fold_convert (for_type, win);
+
   return win;
 }
 
Index: gcc/testsuite/gcc.c-torture/execute/20100209-1.c
===================================================================
--- gcc/testsuite/gcc.c-torture/execute/20100209-1.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/20100209-1.c	(revision 0)
@@ -0,0 +1,12 @@
+int bar(int foo)
+{
+  return (int)(((unsigned long long)(long long)foo) / 8);
+}
+extern void abort (void);
+int main()
+{
+  if (sizeof (long long) > sizeof (int)
+      && bar(-1) != -1)
+    abort ();
+  return 0;
+}
Index: gcc/testsuite/gcc.dg/fold-div-3.c
===================================================================
--- gcc/testsuite/gcc.dg/fold-div-3.c	(revision 0)
+++ gcc/testsuite/gcc.dg/fold-div-3.c	(revision 0)
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-original" } */
+
+unsigned int
+apply_frontend_param (unsigned int spi_bias)
+{
+  static const int ppm = 8000;
+  spi_bias /= 1000ULL + ppm/1000;
+  return spi_bias;
+}
+
+/* Make sure we perform the division in the narrower type.  */
+
+/* { dg-final { scan-tree-dump "spi_bias = spi_bias / 1008;" "original" } } */
+/* { dg-final { cleanup-tree-dump "original" } } */
Index: gcc/convert.c
===================================================================
*** gcc/convert.c	(revision 156620)
--- gcc/convert.c	(working copy)
*************** convert_to_integer (tree type, tree expr
*** 673,678 ****
--- 673,703 ----
  	    }
  	  break;
  
+ 	case TRUNC_DIV_EXPR:
+ 	  {
+ 	    tree arg0 = get_unwidened (TREE_OPERAND (expr, 0), type);
+ 	    tree arg1 = get_unwidened (TREE_OPERAND (expr, 1), type);
+ 
+ 	    /* Don't distribute unless the output precision is at least as big
+ 	       as the actual inputs and it has the same signedness.  */
+ 	    if (outprec >= TYPE_PRECISION (TREE_TYPE (arg0))
+ 		&& outprec >= TYPE_PRECISION (TREE_TYPE (arg1))
+ 		/* If signedness of arg0 and arg1 don't match,
+ 		   we can't necessarily find a type to compare them in.  */
+ 		&& (TYPE_UNSIGNED (TREE_TYPE (arg0))
+ 		    == TYPE_UNSIGNED (TREE_TYPE (arg1)))
+ 		/* Do not change the sign of the division.  */
+ 		&& (TYPE_UNSIGNED (TREE_TYPE (expr))
+ 		    == TYPE_UNSIGNED (TREE_TYPE (arg0)))
+ 		/* Either require unsigned division or a division by
+ 		   a constant that is not -1.  */
+ 		&& (TYPE_UNSIGNED (TREE_TYPE (arg0))
+ 		    || (TREE_CODE (arg1) == INTEGER_CST
+ 			&& !integer_all_onesp (arg1))))
+ 	      goto trunc1;
+ 	    break;
+ 	  }
+ 
  	case MAX_EXPR:
  	case MIN_EXPR:
  	case MULT_EXPR:


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