This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR middle-end/7847
- From: Eric Botcazou <ebotcazou at libertysurf dot fr>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 28 Nov 2003 09:15:57 +0100
- Subject: [PATCH] Fix PR middle-end/7847
Hi,
This is an old PR on SPARC (and Alpha), whose testcase fails at runtime
because of an unaligned memory access.
The code is expand_expr:normal_inner_ref (line 7065 and below) has special
provisions for dealing with unaligned references (line 7198 and below) but
it doesn't trigger for the testcase.
Here's the sequence of events:
- the block is entered line 7065 with 'd->dsi_pack.sml_agli.data[i].address',
- it is decoded by get_inner_reference which gives a non-zero offset and
SImode access mode (bitsize == 32),
- the result 'tem' is recursively expanded by expand_expr into a (mem:BLK).
Were this MEM kept unchanged until the emitting code, I think everything
would be fine. But it is caught by the optimization line 7156, which turns
it into a (mem:SI) with 16-bit alignment (according to CVS history, this
optimization was added to help the loop optimizer).
Now the code for handling unaligned references line 7198 only tests the
alignments of 'tem' and 'mode', which are now irrelevant (and are both equal
to 32 for the testcase). So the codepath is not taken.
The proposed fix is to teach this code to look into the alignment of 'op0'
and 'mode1' too, when op0 is a MEM. I've also removed a redundant check and
moved a comment, because its current location is IMHO confusing
Bootstrapped/regtested on sparc64-sun-solaris2.9 and sparc-sun-solaris2.8
(mainline except Ada). Ok for mainline?
2003-11-28 Eric Botcazou <ebotcazou@libertysurf.fr>
PR middle-end/7847
* expr.c (expand_expr) [normal_inner_ref]: When 'offset' is non-zero,
do not recheck that 'op0' is a MEM. Move comment. When testing for
unaligned objects, take also into account the alignment of 'op0' and
'mode1' if 'op0' is a MEM.
2003-11-28 Eric Botcazou <ebotcazou@libertysurf.fr>
* gcc.dg/unaligned-1.c: New test.
--
Eric Botcazou
Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.604
diff -u -p -r1.604 expr.c
--- expr.c 21 Nov 2003 06:52:22 -0000 1.604
+++ expr.c 26 Nov 2003 17:20:33 -0000
@@ -7153,10 +7153,9 @@ expand_expr (tree exp, rtx target, enum
offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
#endif
- /* A constant address in OP0 can have VOIDmode, we must not try
- to call force_reg for that case. Avoid that case. */
- if (GET_CODE (op0) == MEM
- && GET_MODE (op0) == BLKmode
+ if (GET_MODE (op0) == BLKmode
+ /* A constant address in OP0 can have VOIDmode, we must
+ not try to call force_reg in that case. */
&& GET_MODE (XEXP (op0, 0)) != VOIDmode
&& bitsize != 0
&& (bitpos % bitsize) == 0
@@ -7213,7 +7212,10 @@ expand_expr (tree exp, rtx target, enum
fetch it as a bit field. */
|| (mode1 != BLKmode
&& (((TYPE_ALIGN (TREE_TYPE (tem)) < GET_MODE_ALIGNMENT (mode)
- || (bitpos % GET_MODE_ALIGNMENT (mode) != 0))
+ || (bitpos % GET_MODE_ALIGNMENT (mode) != 0)
+ || (GET_CODE (op0) == MEM
+ && (MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (mode1)
+ || (bitpos % GET_MODE_ALIGNMENT (mode1) != 0))))
&& ((modifier == EXPAND_CONST_ADDRESS
|| modifier == EXPAND_INITIALIZER)
? STRICT_ALIGNMENT
/* PR middle-end/7847 */
/* Originator: <jk@tools.de> */
/* { dg-do run } */
/* This used to fail on SPARC at runtime because of
an unaligned memory access. */
typedef char int8_t;
typedef short int16_t;
typedef int int32_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef struct {
uint32_t address;
uint16_t size;
} __attribute__ ((packed)) sml_agl_data_t;
typedef struct {
sml_agl_data_t data[9];
} __attribute__ ((packed)) sml_agli_t;
typedef struct {
sml_agli_t sml_agli;
} __attribute__ ((packed)) dsi_t;
typedef struct {
int a;
dsi_t dsi_pack;
} dvd_priv_t;
int dvd_read_sector(dvd_priv_t *d, unsigned char* data)
{
int i, skip=0;
for (i=0; i < 9; i++)
if ((skip=d->dsi_pack.sml_agli.data[i].address) != 0)
break;
return skip;
}
int main(void)
{
static dvd_priv_t dvd_priv;
dvd_read_sector(&dvd_priv, 0);
return 0;
}