On Sat, Nov 10, 2012 at 10:38:55AM -0800, H.J. Lu wrote: > On Sat, Nov 10, 2012 at 6:41 AM, Paolo Bonzini <bonz...@gnu.org> wrote: > > Il 10/11/2012 07:44, H.J. Lu ha scritto: > >> Hi, > >> > >> In > >> > >> (insn 19 17 20 2 (set (reg:TI 85 [ *_15 ]) > >> (mem:TI (zero_extend:DI (reg:SI 82)) [0 *_15+0 S16 A32])) x.i:29 61 > >> {*movti_internal_rex64} > >> (expr_list:REG_DEAD (reg:SI 82) > >> (expr_list:REG_EQUIV (mem/c:TI (plus:DI (reg/f:DI 20 frame) > >> (const_int -16 [0xfffffffffffffff0])) [0 sym+0 S16 > >> A64]) > >> > >> we fail to see (mem:TI (zero_extend:DI (reg:SI 82))) is offsettable. > >> This patch adds ZERO_EXTEND support to adjust_address_1 and > >> offsettable_address_addr_space_p. Tested on Linux/x32. OK to install? > > > > Is there any reason why SIGN_EXTEND should be handled differently? > > (Just asking, I don't know this code well). > > > > I don't have a testcase to show that we will generate SIGN_EXTEND > for offsettable address. I can add an assert of GET_CODE != SIGN_EXTEND. > >
This patch also handles SIGN_EXTEND. Tested on Linux/x32. OK to install? Thanks. H.J. --- gcc/ 2012-11-10 H.J. Lu <hongjiu...@intel.com> PR middle-end/55247 PR middle-end/55259 * emit-rtl.c (adjust_address_1): Handle ZERO_EXTEND and SIGN_EXTEND. * recog.c (offsettable_address_addr_space_p): Likewise. * config/i386/i386.md (*movti_internal_rex64): Remove "!" from riF->o alternative. gcc/testsuite/ 2012-11-10 H.J. Lu <hongjiu...@intel.com> PR middle-end/55247 PR middle-end/55259 * gcc.target/i386/pr55247-2.c: New file. diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 2598a1f..243ab4e 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -1874,7 +1874,7 @@ (const_string "OI")))]) (define_insn "*movti_internal_rex64" - [(set (match_operand:TI 0 "nonimmediate_operand" "=!r ,!o ,x,x ,m") + [(set (match_operand:TI 0 "nonimmediate_operand" "=!r ,o ,x,x ,m") (match_operand:TI 1 "general_operand" "riFo,riF,C,xm,x"))] "TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1]))" { diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index 95bbfa7..22065f5 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -2100,6 +2100,8 @@ adjust_address_1 (rtx memref, enum machine_mode mode, HOST_WIDE_INT offset, if (adjust_address) { + rtx x; + /* If MEMREF is a LO_SUM and the offset is within the alignment of the object, we can merge it into the LO_SUM. */ if (GET_MODE (memref) != BLKmode && GET_CODE (addr) == LO_SUM @@ -2109,6 +2111,20 @@ adjust_address_1 (rtx memref, enum machine_mode mode, HOST_WIDE_INT offset, addr = gen_rtx_LO_SUM (address_mode, XEXP (addr, 0), plus_constant (address_mode, XEXP (addr, 1), offset)); + /* We permute zero/sign-extension and addition operation only if + converting the constant does not change it. */ + else if ((GET_CODE (addr) == ZERO_EXTEND + || GET_CODE (addr) == SIGN_EXTEND) + && (x = GEN_INT (offset), + x == convert_memory_address_addr_space (address_mode, + x, + attrs.addrspace))) + { + enum rtx_code code = GET_CODE (addr); + addr = XEXP (addr, 0); + addr = plus_constant (GET_MODE (addr), addr, offset); + addr = gen_rtx_fmt_e (code, address_mode, addr); + } else addr = plus_constant (address_mode, addr, offset); } diff --git a/gcc/recog.c b/gcc/recog.c index ee68e30..a916ef6 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -1934,15 +1934,22 @@ int offsettable_address_addr_space_p (int strictp, enum machine_mode mode, rtx y, addr_space_t as) { - enum rtx_code ycode = GET_CODE (y); + enum rtx_code ycode; rtx z; - rtx y1 = y; + rtx y1; rtx *y2; int (*addressp) (enum machine_mode, rtx, addr_space_t) = (strictp ? strict_memory_address_addr_space_p : memory_address_addr_space_p); unsigned int mode_sz = GET_MODE_SIZE (mode); + /* Allow zero-extended or sign-extended address. */ + if (GET_CODE (y) == ZERO_EXTEND || GET_CODE (y) == SIGN_EXTEND) + y = XEXP (y, 0); + + ycode = GET_CODE (y); + y1 = y; + if (CONSTANT_ADDRESS_P (y)) return 1; diff --git a/gcc/testsuite/gcc.target/i386/pr55247-2.c b/gcc/testsuite/gcc.target/i386/pr55247-2.c new file mode 100644 index 0000000..d91b504 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr55247-2.c @@ -0,0 +1,37 @@ +/* { dg-do compile { target { ! { ia32 } } } } */ +/* { dg-require-effective-target maybe_x32 } */ +/* { dg-options "-O2 -mx32 -mtune=generic -maddress-mode=long" } */ + +typedef unsigned int uint32_t; +typedef uint32_t Elf32_Word; +typedef uint32_t Elf32_Addr; +typedef struct { + Elf32_Word st_name; + Elf32_Addr st_value; + Elf32_Word st_size; + unsigned char st_other; +} Elf32_Sym; +typedef struct { + Elf32_Word r_info; +} +Elf32_Rela; +typedef struct { + union { + Elf32_Addr d_ptr; + } + d_un; +} Elf32_Dyn; +struct link_map { + Elf32_Dyn *l_info[34]; +}; +extern void symbind32 (Elf32_Sym *); +void +_dl_profile_fixup (struct link_map *l, Elf32_Word reloc_arg) +{ + const Elf32_Sym *const symtab = (const void *) l->l_info[6]->d_un.d_ptr; + const Elf32_Rela *const reloc = (const void *) (l->l_info[23]->d_un.d_ptr + reloc_arg * sizeof (Elf32_Rela)); + Elf32_Sym sym = symtab[(reloc->r_info) >> 8]; + symbind32 (&sym); +} + +/* { dg-final { scan-assembler-not "%xmm\[0-9\]" } } */