RFC: PR rtl-optimization/52876: Sign extend 32 to 64bit then clear upper 32bits fails O1 or higher

H.J. Lu hjl.tools@gmail.com
Tue Apr 10 14:49:00 GMT 2012


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.



More information about the Gcc-patches mailing list