This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Add some REG_POINTER flags during ix86 memcpy/memset expansion (PR target/65504)


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]