On Thu, Apr 5, 2012 at 11:48 AM, H.J. Lu <hongjiu...@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...@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...@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.