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, rtl-optimization]: Fix PR 38879, Unaligned access via AND can alias smaller objects


Hello!

Attached patch fixes PR rtl-optimization/38879. The problem is, when a variable is stored with an unaligned write, using aligned DImode access through AND address. Scheduler has not recognized that this store can alias subsequent SImode write, so it allowed SImode write to pass DImode write to the same address.

The exact problem is shown in detail in the PR [1].

There already is the code that handles AND access to different _symbols_, but it was assumed that references to the addresses on stack never alias. This is not true for unaligned access, when address is accessed via offseted aligned access in wider mode. Attached patch extends this code to also handle register-based access.

2009-01-20 Uros Bizjak <ubizjak@gmail.com>

   PR rtl-optimization/38879
   * alias.c (base_alias_check): Unaligned access via AND address can
   alias all surrounding object types except those with sizes equal
   or wider than the size of unaligned access.

Patch was bootstrapped and regression tested on x86_64-pc-linux-gnu {,-m32} and alphaev56-unknown-linux-gnu, where it fixes

FAIL: gfortran.fortran-torture/execute/intrinsic_len.f90 execution, -O2 -fomit-frame-pointer -finline-functions -funroll-loops

OK for 4.4 and 4.3?

[1] http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38879

Uros.
Index: alias.c
===================================================================
--- alias.c	(revision 143523)
+++ alias.c	(working copy)
@@ -1522,26 +1522,27 @@ base_alias_check (rtx x, rtx y, enum mac
   if (rtx_equal_p (x_base, y_base))
     return 1;
 
-  /* The base addresses of the read and write are different expressions.
-     If they are both symbols and they are not accessed via AND, there is
-     no conflict.  We can bring knowledge of object alignment into play
-     here.  For example, on alpha, "char a, b;" can alias one another,
-     though "char a; long b;" cannot.  */
+  /* The base addresses are different expressions.  If they are not accessed
+     via AND, there is no conflict.  We can bring knowledge of object
+     alignment into play here.  For example, on alpha, "char a, b;" can
+     alias one another, though "char a; long b;" cannot.  AND addesses may
+     implicitly alias surrounding objects; i.e. unaligned access in DImode
+     via AND address can alias all surrounding object types except those
+     with aligment 8 or higher.  */
+  if (GET_CODE (x) == AND && GET_CODE (y) == AND)
+    return 1;
+  if (GET_CODE (x) == AND
+      && (GET_CODE (XEXP (x, 1)) != CONST_INT
+	  || (int) GET_MODE_UNIT_SIZE (y_mode) < -INTVAL (XEXP (x, 1))))
+    return 1;
+  if (GET_CODE (y) == AND
+      && (GET_CODE (XEXP (y, 1)) != CONST_INT
+	  || (int) GET_MODE_UNIT_SIZE (x_mode) < -INTVAL (XEXP (y, 1))))
+    return 1;
+
+  /* Differing symbols not accessed via AND never alias.  */
   if (GET_CODE (x_base) != ADDRESS && GET_CODE (y_base) != ADDRESS)
-    {
-      if (GET_CODE (x) == AND && GET_CODE (y) == AND)
-	return 1;
-      if (GET_CODE (x) == AND
-	  && (GET_CODE (XEXP (x, 1)) != CONST_INT
-	      || (int) GET_MODE_UNIT_SIZE (y_mode) < -INTVAL (XEXP (x, 1))))
-	return 1;
-      if (GET_CODE (y) == AND
-	  && (GET_CODE (XEXP (y, 1)) != CONST_INT
-	      || (int) GET_MODE_UNIT_SIZE (x_mode) < -INTVAL (XEXP (y, 1))))
-	return 1;
-      /* Differing symbols never alias.  */
-      return 0;
-    }
+    return 0;
 
   /* If one address is a stack reference there can be no alias:
      stack references using different base registers do not alias,

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