This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[patch] Fix unaligned accesses generated by IVOPTS
- From: Eric Botcazou <ebotcazou at adacore dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: DJ Delorie <dj at redhat dot com>
- Date: Mon, 26 Apr 2010 09:47:56 +0200
- Subject: [patch] Fix unaligned accesses generated by IVOPTS
Hi,
this is the bug discussed at http://gcc.gnu.org/ml/gcc/2010-04/msg00178.html
As reported by DJ, IVOPTS can generate unaligned accesses on strict alignment
machines because may_be_unaligned_p overlooks the variable part of the offset
in the reference it is passed. The attached C testcase raises a SIGBUS on
SPARC/Solaris at -O2 with all 4.x versions I tested (4.1, 4.3, 4.5, 4.6) but
not with 3.4 so this is an old regression.
Bootstrapped/regtested on SPARC/Solaris and SPARC64/Solaris. OK for mainline
and for which branches?
2010-04-26 Eric Botcazou <ebotcazou@adacore.com>
* tree-ssa-loop-ivopts.c (may_be_unaligned_p): Check the alignment of
the variable part of the offset as well. Use highest_pow2_factor for
all alignment checks.
2010-04-26 DJ Delorie <dj@redhat.com>
* gcc.c-torture/execute/20100426-1.c: New test.
--
Eric Botcazou
Index: tree-ssa-loop-ivopts.c
===================================================================
--- tree-ssa-loop-ivopts.c (revision 158675)
+++ tree-ssa-loop-ivopts.c (working copy)
@@ -1537,16 +1537,18 @@ may_be_unaligned_p (tree ref, tree step)
if (mode != BLKmode)
{
- double_int mul;
- tree al = build_int_cst (TREE_TYPE (step),
- GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT);
+ unsigned mode_align = GET_MODE_ALIGNMENT (mode);
- if (base_align < GET_MODE_ALIGNMENT (mode)
- || bitpos % GET_MODE_ALIGNMENT (mode) != 0
- || bitpos % BITS_PER_UNIT != 0)
+ if (base_align < mode_align
+ || (bitpos % mode_align) != 0
+ || (bitpos % BITS_PER_UNIT) != 0)
return true;
- if (!constant_multiple_of (step, al, &mul))
+ if (toffset
+ && (highest_pow2_factor (toffset) * BITS_PER_UNIT) < mode_align)
+ return true;
+
+ if ((highest_pow2_factor (step) * BITS_PER_UNIT) < mode_align)
return true;
}
/* This used to generate unaligned accesses at -O2 because of IVOPTS. */
struct packed_struct
{
struct packed_struct1
{
unsigned char cc11;
unsigned char cc12;
} __attribute__ ((packed)) pst1;
struct packed_struct2
{
unsigned char cc21;
unsigned char cc22;
unsigned short ss[104];
unsigned char cc23[13];
} __attribute__ ((packed)) pst2[4];
} __attribute__ ((packed));
typedef struct
{
int ii;
struct packed_struct buf;
} info_t;
static unsigned short g;
static void __attribute__((noinline))
dummy (unsigned short s)
{
g = s;
}
static int
foo (info_t *info)
{
int i, j;
for (i = 0; i < info->buf.pst1.cc11; i++)
for (j = 0; j < info->buf.pst2[i].cc22; j++)
dummy (info->buf.pst2[i].ss[j]);
return 0;
}
int main(void)
{
info_t info;
info.buf.pst1.cc11 = 2;
info.buf.pst2[0].cc22 = info.buf.pst2[1].cc22 = 8;
return foo (&info);
}