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] 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;
}

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