From 0207fa9006aa57843f99eb17abb0a04c4cc42b8f Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Sun, 11 Nov 2012 21:52:49 +0000 Subject: [PATCH] re PR rtl-optimization/55247 (internal compiler error: Max. number of generated reload insns per insn is achieved (90)) PR rtl-optimization/55247 PR middle-end/55259 * emit-rtl.c (adjust_address_1): If POINTERS_EXTEND_UNSIGNED > 0, handle ZERO_EXTEND. * recog.c (offsettable_address_addr_space_p): Likewise. From-SVN: r193415 --- gcc/ChangeLog | 9 ++++++++ gcc/emit-rtl.c | 20 ++++++++++++++--- gcc/recog.c | 12 ++++++++++ gcc/testsuite/ChangeLog | 6 +++++ gcc/testsuite/gcc.target/i386/pr55247-2.c | 37 +++++++++++++++++++++++++++++++ 5 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr55247-2.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 51b4ed6..58d401c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2012-11-11 Eric Botcazou + H.J. Lu + + PR rtl-optimization/55247 + PR middle-end/55259 + * emit-rtl.c (adjust_address_1): If POINTERS_EXTEND_UNSIGNED > 0, + handle ZERO_EXTEND. + * recog.c (offsettable_address_addr_space_p): Likewise. + 2012-11-11 Steven Bosscher PR middle-end/55263 diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index 95bbfa7..f39d861 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -2071,10 +2071,12 @@ adjust_address_1 (rtx memref, enum machine_mode mode, HOST_WIDE_INT offset, rtx new_rtx; enum machine_mode address_mode; int pbits; - struct mem_attrs attrs, *defattrs; + struct mem_attrs attrs = *get_mem_attrs (memref), *defattrs; unsigned HOST_WIDE_INT max_align; - - attrs = *get_mem_attrs (memref); +#ifdef POINTERS_EXTEND_UNSIGNED + enum machine_mode pointer_mode + = targetm.addr_space.pointer_mode (attrs.addrspace); +#endif /* If there are no changes, just return the original memory reference. */ if (mode == GET_MODE (memref) && !offset @@ -2109,6 +2111,18 @@ 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)); +#ifdef POINTERS_EXTEND_UNSIGNED + /* If MEMREF is a ZERO_EXTEND from pointer_mode and the offset is valid + in that mode, we merge it into the ZERO_EXTEND. We take advantage of + the fact that pointers are not allowed to overflow. */ + else if (POINTERS_EXTEND_UNSIGNED > 0 + && GET_CODE (addr) == ZERO_EXTEND + && GET_MODE (XEXP (addr, 0)) == pointer_mode + && trunc_int_for_mode (offset, pointer_mode) == offset) + addr = gen_rtx_ZERO_EXTEND (address_mode, + plus_constant (pointer_mode, + XEXP (addr, 0), offset)); +#endif else addr = plus_constant (address_mode, addr, offset); } diff --git a/gcc/recog.c b/gcc/recog.c index ee68e30..47e7f75 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -1942,6 +1942,9 @@ offsettable_address_addr_space_p (int strictp, enum machine_mode mode, rtx y, (strictp ? strict_memory_address_addr_space_p : memory_address_addr_space_p); unsigned int mode_sz = GET_MODE_SIZE (mode); +#ifdef POINTERS_EXTEND_UNSIGNED + enum machine_mode pointer_mode = targetm.addr_space.pointer_mode (as); +#endif if (CONSTANT_ADDRESS_P (y)) return 1; @@ -1991,6 +1994,15 @@ offsettable_address_addr_space_p (int strictp, enum machine_mode mode, rtx y, z = gen_rtx_LO_SUM (GET_MODE (y), XEXP (y, 0), plus_constant (GET_MODE (y), XEXP (y, 1), mode_sz - 1)); +#ifdef POINTERS_EXTEND_UNSIGNED + /* Likewise for a ZERO_EXTEND from pointer_mode. */ + else if (POINTERS_EXTEND_UNSIGNED > 0 + && GET_CODE (y) == ZERO_EXTEND + && GET_MODE (XEXP (y, 0)) == pointer_mode) + z = gen_rtx_ZERO_EXTEND (GET_MODE (y), + plus_constant (pointer_mode, XEXP (y, 0), + mode_sz - 1)); +#endif else z = plus_constant (GET_MODE (y), y, mode_sz - 1); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index deaf75c..b8d7da3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2012-11-11 H.J. Lu + + PR middle-end/55247 + PR middle-end/55259 + * gcc.target/i386/pr55247-2.c: New file. + 2012-11-11 Steven Bosscher PR middle-end/55263 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\]" } } */ -- 2.7.4