This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH, rtl-optimization]: Fix PR 38879, Unaligned access via AND can alias smaller objects
- From: Uros Bizjak <ubizjak at gmail dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Tue, 20 Jan 2009 20:42:00 +0100
- Subject: [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,