Patchwork PR56799

login
register
mail settings
Submitter Jeff Law
Date April 3, 2013, 7:18 p.m.
Message ID <515C8088.1040908@redhat.com>
Download mbox | patch
Permalink /patch/233573/
State New
Headers show

Comments

Jeff Law - April 3, 2013, 7:18 p.m.
Per Richi's suggestions I tweaked the recent tree-ssa-dom.c equivalence 
code to use int_fits_type_p rather than creating a new integer node and 
verifying it had the same value as the old node.

At the time I dropped the TYPE_PRECISION check as I thought it was 
redundant with the int_fits_type_p tests.  However int_fits_type_p only 
checks for a widening precision if it can't prove the constant fits 
within the bounds of the new type.

Thus we could record an equivalence after a narrowing conversion, which 
is wrong in this particular case.

Fixed by adding the TYPE_PRECISION checks back.

Bootstrapped & regression tested on x86_64-unknown-linux-gnu.  Installed.

Patch

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 1e25a82..a3b60c9 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@ 
+2013-04-03  Jeff Law  <law@redhat.com>
+
+	PR tree-optimization/56799
+        * tree-ssa-dom.c (record_equivalences_from_incoming_edge): Bring
+	back test for widening conversion erroneously dropped in prior
+	change.
+
 2013-04-03  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
 
 	PR target/56809
@@ -896,6 +903,7 @@ 
 	* config/tilegx/tilepro.h (PROFILE_BEFORE_PROLOGUE): Define.
 
 2013-03-25  Jeff Law  <law@redhat.com>
+
         * tree-ssa-dom.c (record_equivalences_from_incoming_edge): Add missing
         check for INTEGRAL_TYPE_P that was missing due to checking in
 	wrong version of prior patch.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 2cc5fa8..dc0b745 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@ 
+2013-04-03  Jeff Law  <law@redhat.com>
+
+	PR tree-optimization/56799
+	* gcc.c-torture/execute/pr56799.c: New test.
+
 2013-04-03  Paolo Carlini  <paolo.carlini@oracle.com>
 
 	PR c++/56815
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr56799.c b/gcc/testsuite/gcc.c-torture/execute/pr56799.c
new file mode 100644
index 0000000..d9ee26b
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr56799.c
@@ -0,0 +1,43 @@ 
+
+#include <stdio.h>
+typedef struct { int x; int y;} S;
+extern int foo(S*);
+int hi = 0, lo = 0;
+
+int main()
+{
+  S a;
+  int r;
+  a.x = (int) 0x00010000;
+  a.y = 1;
+  r = foo (&a);
+  if (r == 2 && lo==0 && hi==1)
+    {
+      exit (0);
+    }
+  abort ();
+}
+
+typedef unsigned short u16;
+
+__attribute__ ((noinline)) int foo (S* ptr)
+{
+  int a = ptr->x;
+  int c = 0;
+  u16 b = (u16) a;
+  if (b != 0)
+  {
+    lo = 1;
+    c += ptr->y;
+  }
+  b = a >> 16;
+  if (b != 0)
+  {
+    hi = 1;
+    c+= ptr->y;
+  }
+  c += ptr->y;
+  return c;
+}
+
+     
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
index 29d2bb4..d98a646 100644
--- a/gcc/tree-ssa-dom.c
+++ b/gcc/tree-ssa-dom.c
@@ -1151,9 +1151,15 @@  record_equivalences_from_incoming_edge (basic_block bb)
 		{
 		  tree old_rhs = gimple_assign_rhs1 (defstmt);
 
-		  /* If the constant is in the range of the type of OLD_RHS,
-		     then convert the constant and record the equivalence.  */
+		  /* If the conversion widens the original value and
+		     the constant is in the range of the type of OLD_RHS,
+		     then convert the constant and record the equivalence. 
+
+		     Note that int_fits_type_p does not check the precision
+		     if the upper and lower bounds are OK.  */
 		  if (INTEGRAL_TYPE_P (TREE_TYPE (old_rhs))
+		      && (TYPE_PRECISION (TREE_TYPE (lhs))
+			  > TYPE_PRECISION (TREE_TYPE (old_rhs)))
 		      && int_fits_type_p (rhs, TREE_TYPE (old_rhs)))
 		    {
 		      tree newval = fold_convert (TREE_TYPE (old_rhs), rhs);