public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* RFC: PR rtl-optimization/52876: Sign extend 32 to 64bit then clear upper 32bits fails O1 or higher
@ 2012-04-05 18:48 H.J. Lu
  2012-04-10 14:49 ` H.J. Lu
  2012-04-11 14:21 ` Richard Sandiford
  0 siblings, 2 replies; 5+ messages in thread
From: H.J. Lu @ 2012-04-05 18:48 UTC (permalink / raw)
  To: gcc-patches; +Cc: ebotcazou

Hi,

CSE turns (reg:DI 64)

(insn 6 3 7 2 (set (reg:DI 64)
        (sign_extend:DI (subreg/u:SI (reg/v/f:DI 63 [ addr ]) 0))) x.i:6 122
{*extendsidi2_rex64} (nil))

into (reg/f:DI 64 [ addr ]).  But nonzero_bits1 in rtlanal.c has

#if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend)
      /* If pointers extend unsigned and this is a pointer in Pmode, say that
         all the bits above ptr_mode are known to be zero.  */
      /* As we do not know which address space the pointer is refering to,
         we can do this only if the target does not support different pointer
         or address modes depending on the address space.  */
      if (target_default_pointer_address_modes_p ()
          && POINTERS_EXTEND_UNSIGNED && GET_MODE (x) == Pmode
          && REG_POINTER (x))
        nonzero &= GET_MODE_MASK (ptr_mode);
#endif

Setting REG_POINTER with incompatible pointer sign extension is wrong.
This patch adds a bool parameter to set_reg_attrs_from_value to
indicate if a register can be marked as a pointer.  Does it look OK?

Thanks.


H.J.
---
gcc/

2012-04-05  H.J. Lu  <hongjiu.lu@intel.com>

	PR rtl-optimization/52876
	* emit-rtl.c (set_reg_attrs_from_value): Add a bool parameter
	to indicate if a register can be a pointer.
	(gen_reg_rtx_and_attrs): Pass true to set_reg_attrs_from_value.
	(set_reg_attrs_for_parm): Likewise.

	* emit-rtl.h (set_reg_attrs_from_value): Add a bool parameter.

	* reginfo.c (reg_scan_mark_refs): Pass false to
	set_reg_attrs_from_value with incompatible pointer sign
	extension.

gcc/testsuite

2012-04-05  H.J. Lu  <hongjiu.lu@intel.com>

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

diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 8d7d441..791ff5c 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -967,7 +967,7 @@ adjust_reg_mode (rtx reg, enum machine_mode mode)
    have different modes, REG is a (possibly paradoxical) lowpart of X.  */
 
 void
-set_reg_attrs_from_value (rtx reg, rtx x)
+set_reg_attrs_from_value (rtx reg, rtx x, bool can_be_reg_pointer)
 {
   int offset;
 
@@ -983,14 +983,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)));
     }
 }
@@ -1002,7 +1002,7 @@ rtx
 gen_reg_rtx_and_attrs (rtx x)
 {
   rtx reg = gen_reg_rtx (GET_MODE (x));
-  set_reg_attrs_from_value (reg, x);
+  set_reg_attrs_from_value (reg, x, true);
   return reg;
 }
 
@@ -1013,7 +1013,7 @@ void
 set_reg_attrs_for_parm (rtx parm_rtx, rtx mem)
 {
   if (REG_P (parm_rtx))
-    set_reg_attrs_from_value (parm_rtx, mem);
+    set_reg_attrs_from_value (parm_rtx, mem, true);
   else if (GET_CODE (parm_rtx) == PARALLEL)
     {
       /* Check for a NULL entry in the first slot, used to indicate that the
diff --git a/gcc/emit-rtl.h b/gcc/emit-rtl.h
index bc91193..2f259ef 100644
--- a/gcc/emit-rtl.h
+++ b/gcc/emit-rtl.h
@@ -63,7 +63,7 @@ extern rtx copy_insn_1 (rtx);
 extern rtx copy_insn (rtx);
 extern rtx gen_int_mode (HOST_WIDE_INT, enum machine_mode);
 extern rtx emit_copy_of_insn_after (rtx, rtx);
-extern void set_reg_attrs_from_value (rtx, rtx);
+extern void set_reg_attrs_from_value (rtx, rtx, bool);
 extern void set_reg_attrs_for_parm (rtx, rtx);
 extern void set_reg_attrs_for_decl_rtl (tree t, rtx x);
 extern void adjust_reg_mode (rtx, enum machine_mode);
diff --git a/gcc/reginfo.c b/gcc/reginfo.c
index 6353126..585d7a8 100644
--- a/gcc/reginfo.c
+++ b/gcc/reginfo.c
@@ -1224,14 +1224,24 @@ reg_scan_mark_refs (rtx x, rtx insn)
       if (REG_P (dest) && !REG_ATTRS (dest))
 	{
 	  rtx src = SET_SRC (x);
+	  bool can_be_reg_pointer = true;
 
 	  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);
+	    {
+#if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend)
+	      if ((GET_CODE (src) == SIGN_EXTEND
+		   && POINTERS_EXTEND_UNSIGNED)
+		  || (GET_CODE (src) != SIGN_EXTEND
+		      && ! POINTERS_EXTEND_UNSIGNED))
+		can_be_reg_pointer = false;
+#endif
+	      src = XEXP (src, 0);
+	    }
 
-	  set_reg_attrs_from_value (dest, src);
+	  set_reg_attrs_from_value (dest, src, can_be_reg_pointer);
 	}
 
       /* ... fall through ...  */
diff --git a/gcc/testsuite/gcc.target/i386/pr52876.c b/gcc/testsuite/gcc.target/i386/pr52876.c
new file mode 100644
index 0000000..6d5e47a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr52876.c
@@ -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;
+}

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: RFC: PR rtl-optimization/52876: Sign extend 32 to 64bit then clear upper 32bits fails O1 or higher
  2012-04-05 18:48 RFC: PR rtl-optimization/52876: Sign extend 32 to 64bit then clear upper 32bits fails O1 or higher H.J. Lu
@ 2012-04-10 14:49 ` H.J. Lu
  2012-04-11 14:21 ` Richard Sandiford
  1 sibling, 0 replies; 5+ messages in thread
From: H.J. Lu @ 2012-04-10 14:49 UTC (permalink / raw)
  To: Eric Botcazou, Richard Sandiford; +Cc: gcc-patches

On Thu, Apr 5, 2012 at 11:48 AM, H.J. Lu <hongjiu.lu@intel.com> wrote:
> Hi,
>
> CSE turns (reg:DI 64)
>
> (insn 6 3 7 2 (set (reg:DI 64)
>        (sign_extend:DI (subreg/u:SI (reg/v/f:DI 63 [ addr ]) 0))) x.i:6 122
> {*extendsidi2_rex64} (nil))
>
> into (reg/f:DI 64 [ addr ]).  But nonzero_bits1 in rtlanal.c has
>
> #if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend)
>      /* If pointers extend unsigned and this is a pointer in Pmode, say that
>         all the bits above ptr_mode are known to be zero.  */
>      /* As we do not know which address space the pointer is refering to,
>         we can do this only if the target does not support different pointer
>         or address modes depending on the address space.  */
>      if (target_default_pointer_address_modes_p ()
>          && POINTERS_EXTEND_UNSIGNED && GET_MODE (x) == Pmode
>          && REG_POINTER (x))
>        nonzero &= GET_MODE_MASK (ptr_mode);
> #endif
>
> Setting REG_POINTER with incompatible pointer sign extension is wrong.
> This patch adds a bool parameter to set_reg_attrs_from_value to
> indicate if a register can be marked as a pointer.  Does it look OK?
>
> Thanks.
>
>
> H.J.
> ---
> gcc/
>
> 2012-04-05  H.J. Lu  <hongjiu.lu@intel.com>
>
>        PR rtl-optimization/52876
>        * emit-rtl.c (set_reg_attrs_from_value): Add a bool parameter
>        to indicate if a register can be a pointer.
>        (gen_reg_rtx_and_attrs): Pass true to set_reg_attrs_from_value.
>        (set_reg_attrs_for_parm): Likewise.
>
>        * emit-rtl.h (set_reg_attrs_from_value): Add a bool parameter.
>
>        * reginfo.c (reg_scan_mark_refs): Pass false to
>        set_reg_attrs_from_value with incompatible pointer sign
>        extension.
>
> gcc/testsuite
>
> 2012-04-05  H.J. Lu  <hongjiu.lu@intel.com>
>
>        PR rtl-optimization/52876
>        * gcc.target/i386/pr52876.c: New.
>
> diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
> index 8d7d441..791ff5c 100644
> --- a/gcc/emit-rtl.c
> +++ b/gcc/emit-rtl.c
> @@ -967,7 +967,7 @@ adjust_reg_mode (rtx reg, enum machine_mode mode)
>    have different modes, REG is a (possibly paradoxical) lowpart of X.  */
>
>  void
> -set_reg_attrs_from_value (rtx reg, rtx x)
> +set_reg_attrs_from_value (rtx reg, rtx x, bool can_be_reg_pointer)
>  {
>   int offset;
>
> @@ -983,14 +983,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)));
>     }
>  }
> @@ -1002,7 +1002,7 @@ rtx
>  gen_reg_rtx_and_attrs (rtx x)
>  {
>   rtx reg = gen_reg_rtx (GET_MODE (x));
> -  set_reg_attrs_from_value (reg, x);
> +  set_reg_attrs_from_value (reg, x, true);
>   return reg;
>  }
>
> @@ -1013,7 +1013,7 @@ void
>  set_reg_attrs_for_parm (rtx parm_rtx, rtx mem)
>  {
>   if (REG_P (parm_rtx))
> -    set_reg_attrs_from_value (parm_rtx, mem);
> +    set_reg_attrs_from_value (parm_rtx, mem, true);
>   else if (GET_CODE (parm_rtx) == PARALLEL)
>     {
>       /* Check for a NULL entry in the first slot, used to indicate that the
> diff --git a/gcc/emit-rtl.h b/gcc/emit-rtl.h
> index bc91193..2f259ef 100644
> --- a/gcc/emit-rtl.h
> +++ b/gcc/emit-rtl.h
> @@ -63,7 +63,7 @@ extern rtx copy_insn_1 (rtx);
>  extern rtx copy_insn (rtx);
>  extern rtx gen_int_mode (HOST_WIDE_INT, enum machine_mode);
>  extern rtx emit_copy_of_insn_after (rtx, rtx);
> -extern void set_reg_attrs_from_value (rtx, rtx);
> +extern void set_reg_attrs_from_value (rtx, rtx, bool);
>  extern void set_reg_attrs_for_parm (rtx, rtx);
>  extern void set_reg_attrs_for_decl_rtl (tree t, rtx x);
>  extern void adjust_reg_mode (rtx, enum machine_mode);
> diff --git a/gcc/reginfo.c b/gcc/reginfo.c
> index 6353126..585d7a8 100644
> --- a/gcc/reginfo.c
> +++ b/gcc/reginfo.c
> @@ -1224,14 +1224,24 @@ reg_scan_mark_refs (rtx x, rtx insn)
>       if (REG_P (dest) && !REG_ATTRS (dest))
>        {
>          rtx src = SET_SRC (x);
> +         bool can_be_reg_pointer = true;
>
>          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);
> +           {
> +#if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend)
> +             if ((GET_CODE (src) == SIGN_EXTEND
> +                  && POINTERS_EXTEND_UNSIGNED)
> +                 || (GET_CODE (src) != SIGN_EXTEND
> +                     && ! POINTERS_EXTEND_UNSIGNED))
> +               can_be_reg_pointer = false;
> +#endif
> +             src = XEXP (src, 0);
> +           }
>
> -         set_reg_attrs_from_value (dest, src);
> +         set_reg_attrs_from_value (dest, src, can_be_reg_pointer);
>        }
>
>       /* ... fall through ...  */
> diff --git a/gcc/testsuite/gcc.target/i386/pr52876.c b/gcc/testsuite/gcc.target/i386/pr52876.c
> new file mode 100644
> index 0000000..6d5e47a
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr52876.c
> @@ -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;
> +}

PING.

-- 
H.J.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: RFC: PR rtl-optimization/52876: Sign extend 32 to 64bit then clear upper 32bits fails O1 or higher
  2012-04-05 18:48 RFC: PR rtl-optimization/52876: Sign extend 32 to 64bit then clear upper 32bits fails O1 or higher H.J. Lu
  2012-04-10 14:49 ` H.J. Lu
@ 2012-04-11 14:21 ` Richard Sandiford
  2012-04-11 17:21   ` H.J. Lu
  1 sibling, 1 reply; 5+ messages in thread
From: Richard Sandiford @ 2012-04-11 14:21 UTC (permalink / raw)
  To: H.J. Lu; +Cc: gcc-patches, ebotcazou

"H.J. Lu" <hongjiu.lu@intel.com> writes:
> Hi,
>
> CSE turns (reg:DI 64)
>
> (insn 6 3 7 2 (set (reg:DI 64)
>         (sign_extend:DI (subreg/u:SI (reg/v/f:DI 63 [ addr ]) 0))) x.i:6 122
> {*extendsidi2_rex64} (nil))
>
> into (reg/f:DI 64 [ addr ]).  But nonzero_bits1 in rtlanal.c has
>
> #if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend)
>       /* If pointers extend unsigned and this is a pointer in Pmode, say that
>          all the bits above ptr_mode are known to be zero.  */
>       /* As we do not know which address space the pointer is refering to,
>          we can do this only if the target does not support different pointer
>          or address modes depending on the address space.  */
>       if (target_default_pointer_address_modes_p ()
>           && POINTERS_EXTEND_UNSIGNED && GET_MODE (x) == Pmode
>           && REG_POINTER (x))
>         nonzero &= GET_MODE_MASK (ptr_mode);
> #endif
>
> Setting REG_POINTER with incompatible pointer sign extension is wrong.
> This patch adds a bool parameter to set_reg_attrs_from_value to
> indicate if a register can be marked as a pointer.  Does it look OK?
>
> Thanks.
>
>
> H.J.
> ---
> gcc/
>
> 2012-04-05  H.J. Lu  <hongjiu.lu@intel.com>
>
> 	PR rtl-optimization/52876
> 	* emit-rtl.c (set_reg_attrs_from_value): Add a bool parameter
> 	to indicate if a register can be a pointer.
> 	(gen_reg_rtx_and_attrs): Pass true to set_reg_attrs_from_value.
> 	(set_reg_attrs_for_parm): Likewise.
>
> 	* emit-rtl.h (set_reg_attrs_from_value): Add a bool parameter.
>
> 	* reginfo.c (reg_scan_mark_refs): Pass false to
> 	set_reg_attrs_from_value with incompatible pointer sign
> 	extension.

Regardless of how it is currently used, I think gen_reg_rtx_and_attrs
(another caller to set_reg_attrs_from_value) is supposed to be a fairly
general function.  So rather than apply a fix specific to regscan,
I think it would be cleaner to redefine set_reg_attrs_from_value as
taking an arbitrary value.  The whole while loop:

	  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);

would then move to set_reg_attrs_from_value, and the "can be pointer"
thing hidden there.  The regscan code would just be:

      if (REG_P (dest) && !REG_ATTRS (dest))
	set_reg_attrs_from_value (dest, src);

Richard

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: RFC: PR rtl-optimization/52876: Sign extend 32 to 64bit then clear upper 32bits fails O1 or higher
  2012-04-11 14:21 ` Richard Sandiford
@ 2012-04-11 17:21   ` H.J. Lu
  2012-04-11 18:53     ` Richard Sandiford
  0 siblings, 1 reply; 5+ messages in thread
From: H.J. Lu @ 2012-04-11 17:21 UTC (permalink / raw)
  To: gcc-patches, ebotcazou, rdsandiford

[-- Attachment #1: Type: text/plain, Size: 3411 bytes --]

On Wed, Apr 11, 2012 at 7:21 AM, Richard Sandiford
<rdsandiford@googlemail.com> wrote:
> "H.J. Lu" <hongjiu.lu@intel.com> writes:
>> Hi,
>>
>> CSE turns (reg:DI 64)
>>
>> (insn 6 3 7 2 (set (reg:DI 64)
>>         (sign_extend:DI (subreg/u:SI (reg/v/f:DI 63 [ addr ]) 0))) x.i:6 122
>> {*extendsidi2_rex64} (nil))
>>
>> into (reg/f:DI 64 [ addr ]).  But nonzero_bits1 in rtlanal.c has
>>
>> #if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend)
>>       /* If pointers extend unsigned and this is a pointer in Pmode, say that
>>          all the bits above ptr_mode are known to be zero.  */
>>       /* As we do not know which address space the pointer is refering to,
>>          we can do this only if the target does not support different pointer
>>          or address modes depending on the address space.  */
>>       if (target_default_pointer_address_modes_p ()
>>           && POINTERS_EXTEND_UNSIGNED && GET_MODE (x) == Pmode
>>           && REG_POINTER (x))
>>         nonzero &= GET_MODE_MASK (ptr_mode);
>> #endif
>>
>> Setting REG_POINTER with incompatible pointer sign extension is wrong.
>> This patch adds a bool parameter to set_reg_attrs_from_value to
>> indicate if a register can be marked as a pointer.  Does it look OK?
>>
>> Thanks.
>>
>>
>> H.J.
>> ---
>> gcc/
>>
>> 2012-04-05  H.J. Lu  <hongjiu.lu@intel.com>
>>
>>       PR rtl-optimization/52876
>>       * emit-rtl.c (set_reg_attrs_from_value): Add a bool parameter
>>       to indicate if a register can be a pointer.
>>       (gen_reg_rtx_and_attrs): Pass true to set_reg_attrs_from_value.
>>       (set_reg_attrs_for_parm): Likewise.
>>
>>       * emit-rtl.h (set_reg_attrs_from_value): Add a bool parameter.
>>
>>       * reginfo.c (reg_scan_mark_refs): Pass false to
>>       set_reg_attrs_from_value with incompatible pointer sign
>>       extension.
>
> Regardless of how it is currently used, I think gen_reg_rtx_and_attrs
> (another caller to set_reg_attrs_from_value) is supposed to be a fairly
> general function.  So rather than apply a fix specific to regscan,
> I think it would be cleaner to redefine set_reg_attrs_from_value as
> taking an arbitrary value.  The whole while loop:
>
>          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);
>
> would then move to set_reg_attrs_from_value, and the "can be pointer"
> thing hidden there.  The regscan code would just be:
>
>      if (REG_P (dest) && !REG_ATTRS (dest))
>        set_reg_attrs_from_value (dest, src);
>
> Richard

Here is the updated patch to change set_reg_attrs_from_value to
take arbitrary value and check incompatible pointer sign
extension.  OK for trunk if there are no regressions on Linux/x86-64?

Thanks.


-- 
H.J.
---
gcc/

2012-04-10  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.

gcc/testsuite

2012-04-10  H.J. Lu  <hongjiu.lu@intel.com>

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

[-- Attachment #2: gcc-pr52876-2.patch --]
[-- Type: application/octet-stream, Size: 2735 bytes --]

gcc/

2012-04-10  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.

gcc/testsuite

2012-04-10  H.J. Lu  <hongjiu.lu@intel.com>

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

diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 8d7d441..a58be4e 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -970,6 +970,7 @@ void
 set_reg_attrs_from_value (rtx reg, rtx x)
 {
   int offset;
+  bool can_be_reg_pointer;
 
   /* Hard registers can be reused for multiple purposes within the same
      function, so setting REG_ATTRS, REG_POINTER and REG_POINTER_ALIGN
@@ -977,20 +978,36 @@ set_reg_attrs_from_value (rtx reg, rtx x)
   if (HARD_REGISTER_P (reg))
     return;
 
+  /* Don't call mark_reg_pointer for incompatible pointer sign
+     extension.  */
+  can_be_reg_pointer = true;
+  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);
+    }
+
   offset = byte_lowpart_offset (GET_MODE (reg), GET_MODE (x));
   if (MEM_P (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)));
     }
 }
diff --git a/gcc/reginfo.c b/gcc/reginfo.c
index 6353126..f3a08f5 100644
--- a/gcc/reginfo.c
+++ b/gcc/reginfo.c
@@ -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 ...  */
 

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: RFC: PR rtl-optimization/52876: Sign extend 32 to 64bit then clear upper 32bits fails O1 or higher
  2012-04-11 17:21   ` H.J. Lu
@ 2012-04-11 18:53     ` Richard Sandiford
  0 siblings, 0 replies; 5+ messages in thread
From: Richard Sandiford @ 2012-04-11 18:53 UTC (permalink / raw)
  To: H.J. Lu; +Cc: gcc-patches, ebotcazou

"H.J. Lu" <hjl.tools@gmail.com> writes:
> Here is the updated patch to change set_reg_attrs_from_value to
> take arbitrary value and check incompatible pointer sign
> extension.  OK for trunk if there are no regressions on Linux/x86-64?

The new code ought to go before the HARD_REGISTER_P check, not after it.
OK with that change, thanks.

Richard

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2012-04-11 18:53 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-04-05 18:48 RFC: PR rtl-optimization/52876: Sign extend 32 to 64bit then clear upper 32bits fails O1 or higher H.J. Lu
2012-04-10 14:49 ` H.J. Lu
2012-04-11 14:21 ` Richard Sandiford
2012-04-11 17:21   ` H.J. Lu
2012-04-11 18:53     ` Richard Sandiford

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).