Patchwork Fix *DIV_EXPR folding on 32-bit HWI (PR middle-end/46019)

login
register
mail settings
Submitter Jakub Jelinek
Date Oct. 14, 2010, 9:37 p.m.
Message ID <20101014213717.GB18103@tyan-ft48-01.lab.bos.redhat.com>
Download mbox | patch
Permalink /patch/67869/
State New
Headers show

Comments

Jakub Jelinek - Oct. 14, 2010, 9:37 p.m.
Hi!

integer_pow2p can return true even for large constants that
have TREE_INT_CST_LOW zero, but some bit set in TREE_INT_CST_HIGH
(either for 32-bit HWI and long long, or I guess for TImode on 64-bit HWI).

Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux,
ok for trunk/4.5/4.4?

2010-10-14  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/46019
	* fold-const.c (fold_binary_loc): If integer_pow2p has
	TREE_INT_CST_LOW zero, look at TREE_INT_CST_HIGH.

	* gcc.c-torture/execute/pr46019.c: New test.


	Jakub
Richard Henderson - Oct. 14, 2010, 9:49 p.m.
On 10/14/2010 02:37 PM, Jakub Jelinek wrote:
> 	PR middle-end/46019
> 	* fold-const.c (fold_binary_loc): If integer_pow2p has
> 	TREE_INT_CST_LOW zero, look at TREE_INT_CST_HIGH.
> 
> 	* gcc.c-torture/execute/pr46019.c: New test.

Ok.


r~

Patch

--- gcc/fold-const.c.jj	2010-10-07 19:45:22.000000000 +0200
+++ gcc/fold-const.c	2010-10-14 19:13:37.000000000 +0200
@@ -11611,7 +11611,13 @@  fold_binary_loc (location_t loc,
 	  if (integer_pow2p (sval) && tree_int_cst_sgn (sval) > 0)
 	    {
 	      tree sh_cnt = TREE_OPERAND (arg1, 1);
-	      unsigned long pow2 = exact_log2 (TREE_INT_CST_LOW (sval));
+	      unsigned long pow2;
+
+	      if (TREE_INT_CST_LOW (sval))
+		pow2 = exact_log2 (TREE_INT_CST_LOW (sval));
+	      else
+		pow2 = exact_log2 (TREE_INT_CST_HIGH (sval))
+		       + HOST_BITS_PER_WIDE_INT;
 
 	      if (strict_overflow_p)
 		fold_overflow_warning (("assuming signed overflow does not "
--- gcc/testsuite/gcc.c-torture/execute/pr46019.c.jj	2010-10-14 19:18:23.000000000 +0200
+++ gcc/testsuite/gcc.c-torture/execute/pr46019.c	2010-10-14 18:53:39.000000000 +0200
@@ -0,0 +1,14 @@ 
+/* PR middle-end/46019 */
+
+extern void abort (void);
+
+int
+main (void)
+{
+  unsigned long long l = 0x40000000000ULL;
+  int n;
+  for (n = 0; n < 8; n++)
+    if (l / (0x200000000ULL << n) != (0x200 >> n))
+      abort ();
+  return 0;
+}