Check for incompatible pointer sign extension
authorH.J. Lu <hongjiu.lu@intel.com>
Wed, 11 Apr 2012 19:31:45 +0000 (19:31 +0000)
committerH.J. Lu <hjl@gcc.gnu.org>
Wed, 11 Apr 2012 19:31:45 +0000 (12:31 -0700)
gcc/

PR rtl-optimization/52876
* emit-rtl.c (set_reg_attrs_from_value): Handle arbitrary value.
Don't call mark_reg_pointer for incompatible pointer sign
extension.

* reginfo.c (reg_scan_mark_refs): Call set_reg_attrs_from_value
directly.

gcc/testsuite

PR rtl-optimization/52876
* gcc.target/i386/pr52876.c: New.

From-SVN: r186351

gcc/ChangeLog
gcc/emit-rtl.c
gcc/reginfo.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr52876.c [new file with mode: 0644]

index 9ea90db7e62c858ea1f7a18c1fd18a9617cf47cc..f3fcfca006de4da5daa12f6c8d2f5e232b0dbde1 100644 (file)
@@ -1,3 +1,13 @@
+2012-04-11  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR rtl-optimization/52876
+       * emit-rtl.c (set_reg_attrs_from_value): Handle arbitrary value.
+       Don't call mark_reg_pointer for incompatible pointer sign
+       extension.
+
+       * reginfo.c (reg_scan_mark_refs): Call set_reg_attrs_from_value 
+       directly.
+
 2012-04-11  Bernd Schmidt  <bernds@codesourcery.com>
 
        * fold-const.c (fold_unary_loc): Use GET_MODE_PRECISION for
index 8d7d4417d59c94952928d946fbb3385232adafeb..9da585c35a77a0780be3df4a104f1aa283ebceaa 100644 (file)
@@ -970,6 +970,22 @@ void
 set_reg_attrs_from_value (rtx reg, rtx x)
 {
   int offset;
+  bool can_be_reg_pointer = true;
+
+  /* Don't call mark_reg_pointer for incompatible pointer sign
+     extension.  */
+  while (GET_CODE (x) == SIGN_EXTEND
+        || GET_CODE (x) == ZERO_EXTEND
+        || GET_CODE (x) == TRUNCATE
+        || (GET_CODE (x) == SUBREG && subreg_lowpart_p (x)))
+    {
+#if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend)
+      if ((GET_CODE (x) == SIGN_EXTEND && POINTERS_EXTEND_UNSIGNED)
+         || (GET_CODE (x) != SIGN_EXTEND && ! POINTERS_EXTEND_UNSIGNED))
+       can_be_reg_pointer = false;
+#endif
+      x = XEXP (x, 0);
+    }
 
   /* Hard registers can be reused for multiple purposes within the same
      function, so setting REG_ATTRS, REG_POINTER and REG_POINTER_ALIGN
@@ -983,14 +999,14 @@ set_reg_attrs_from_value (rtx reg, rtx x)
       if (MEM_OFFSET_KNOWN_P (x))
        REG_ATTRS (reg) = get_reg_attrs (MEM_EXPR (x),
                                         MEM_OFFSET (x) + offset);
-      if (MEM_POINTER (x))
+      if (can_be_reg_pointer && MEM_POINTER (x))
        mark_reg_pointer (reg, 0);
     }
   else if (REG_P (x))
     {
       if (REG_ATTRS (x))
        update_reg_offset (reg, x, offset);
-      if (REG_POINTER (x))
+      if (can_be_reg_pointer && REG_POINTER (x))
        mark_reg_pointer (reg, REGNO_POINTER_ALIGN (REGNO (x)));
     }
 }
index 635312655bcd0d95da19cfd8d86044518f44b09f..f3a08f523c20c2457f52f4a9176ad75ca2b3abb4 100644 (file)
@@ -1222,17 +1222,7 @@ reg_scan_mark_refs (rtx x, rtx insn)
       /* If this is setting a register from a register or from a simple
         conversion of a register, propagate REG_EXPR.  */
       if (REG_P (dest) && !REG_ATTRS (dest))
-       {
-         rtx src = SET_SRC (x);
-
-         while (GET_CODE (src) == SIGN_EXTEND
-                || GET_CODE (src) == ZERO_EXTEND
-                || GET_CODE (src) == TRUNCATE
-                || (GET_CODE (src) == SUBREG && subreg_lowpart_p (src)))
-           src = XEXP (src, 0);
-
-         set_reg_attrs_from_value (dest, src);
-       }
+       set_reg_attrs_from_value (dest, SET_SRC (x));
 
       /* ... fall through ...  */
 
index 7a764f4caa39b6372111b26080e8e63b1e4b6fdf..1a22457a1406ca92a60bbc417fe3e5257b4365ce 100644 (file)
@@ -1,3 +1,8 @@
+2012-04-11  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR rtl-optimization/52876
+       * gcc.target/i386/pr52876.c: New.
+
 2012-04-11  Bernd Schmidt  <bernds@codesourcery.com>
 
        * gcc.dg/c99-const-expr-9.c (old_offsetof): Insert a cast to
diff --git a/gcc/testsuite/gcc.target/i386/pr52876.c b/gcc/testsuite/gcc.target/i386/pr52876.c
new file mode 100644 (file)
index 0000000..6d5e47a
--- /dev/null
@@ -0,0 +1,25 @@
+/* { dg-do run { target { x32 } } } */
+/* { dg-options "-O2 -mx32 -maddress-mode=long" } */
+
+extern void abort (void);
+
+long long li;
+
+long long 
+__attribute__ ((noinline))
+testfunc (void* addr)
+{
+  li = (long long)(int)addr;
+  li &= 0xffffffff;
+  return li;
+}
+
+int main (void)
+{
+  volatile long long rv_test;
+  rv_test = testfunc((void*)0x87651234);
+  if (rv_test != 0x87651234ULL)
+    abort ();
+
+  return 0;
+}