This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Add some REG_POINTER flags during ix86 memcpy/memset expansion (PR target/65504)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Jan Hubicka <hubicka at ucw dot cz>, Uros Bizjak <ubizjak at gmail dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Mon, 23 Mar 2015 16:07:38 +0100
- Subject: [PATCH] Add some REG_POINTER flags during ix86 memcpy/memset expansion (PR target/65504)
- Authentication-results: sourceware.org; auth=none
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
As expand_set_or_movmem_prologue_epilogue_by_misaligned_moves uses
src = src - (adjusted_dest - dest)
without proper REG_POINTER flags the aliasing code is very easily confused
on what is really a pointer and what is not - as REG_POINTER was used
after forwprop only on dest, but not on anything else, aliasing code thinks
that the memcpy reads dest based memory, when it really reads src based
memory (in the testcase frame pointer based in the end, but CSE did not see
it through).
Fixed by marking pseudos that must hold pointers with REG_POINTER during
the expansion. Bootstrapped/regtested on x86_64-linux and i686-linux, ok
for trunk?
2015-03-23 Jakub Jelinek <jakub@redhat.com>
PR target/65504
* config/i386/i386.c (ix86_copy_addr_to_reg): Set REG_POINTER
on the pseudo.
(expand_set_or_movmem_prologue_epilogue_by_misaligned_moves): Set
REG_POINTER on *destptr after adjusting it for prologue size.
* gfortran.dg/pr65504.f90: New test.
--- gcc/config/i386/i386.c.jj 2015-03-23 08:47:53.000000000 +0100
+++ gcc/config/i386/i386.c 2015-03-23 13:38:40.573983052 +0100
@@ -23457,12 +23457,19 @@ counter_mode (rtx count_exp)
static rtx
ix86_copy_addr_to_reg (rtx addr)
{
+ rtx reg;
if (GET_MODE (addr) == Pmode || GET_MODE (addr) == VOIDmode)
- return copy_addr_to_reg (addr);
+ {
+ reg = copy_addr_to_reg (addr);
+ REG_POINTER (reg) = 1;
+ return reg;
+ }
else
{
gcc_assert (GET_MODE (addr) == DImode && Pmode == SImode);
- return gen_rtx_SUBREG (SImode, copy_to_mode_reg (DImode, addr), 0);
+ reg = copy_to_mode_reg (DImode, addr);
+ REG_POINTER (reg) = 1;
+ return gen_rtx_SUBREG (SImode, reg, 0);
}
}
@@ -24354,6 +24361,8 @@ expand_set_or_movmem_prologue_epilogue_b
*destptr = expand_simple_binop (GET_MODE (*destptr), PLUS, *destptr,
GEN_INT (prolog_size),
NULL_RTX, 1, OPTAB_DIRECT);
+ if (REG_P (*destptr) && REG_P (saveddest) && REG_POINTER (saveddest))
+ REG_POINTER (*destptr) = 1;
*destptr = expand_simple_binop (GET_MODE (*destptr), AND, *destptr,
GEN_INT (-desired_align),
*destptr, 1, OPTAB_DIRECT);
@@ -24363,8 +24372,8 @@ expand_set_or_movmem_prologue_epilogue_b
saveddest, 1, OPTAB_DIRECT);
/* Adjust srcptr and count. */
if (!issetmem)
- *srcptr = expand_simple_binop (GET_MODE (*srcptr), MINUS, *srcptr, saveddest,
- *srcptr, 1, OPTAB_DIRECT);
+ *srcptr = expand_simple_binop (GET_MODE (*srcptr), MINUS, *srcptr,
+ saveddest, *srcptr, 1, OPTAB_DIRECT);
*count = expand_simple_binop (GET_MODE (*count), PLUS, *count,
saveddest, *count, 1, OPTAB_DIRECT);
/* We copied at most size + prolog_size. */
--- gcc/testsuite/gfortran.dg/pr65504.f90.jj 2015-03-23 13:39:44.050945860 +0100
+++ gcc/testsuite/gfortran.dg/pr65504.f90 2015-03-23 13:39:57.707722713 +0100
@@ -0,0 +1,28 @@
+! PR target/65504
+! { dg-do run }
+
+program pr65504
+ implicit none
+ type :: T
+ character (len=256) :: a
+ character (len=256) :: b
+ end type T
+ type (T) :: c
+ type (T) :: d
+ c = foo ("test")
+ d = foo ("test")
+ if (trim(c%b) .ne. "foo") call abort
+ contains
+ type (T) function foo (x) result (v)
+ character(len=*), intent(in) :: x
+ select case (x)
+ case ("test")
+ v%b = 'foo'
+ case ("bazx")
+ v%b = 'barx'
+ case default
+ print *, "unknown"
+ stop
+ end select
+ end function foo
+end program pr65504
Jakub