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]

PATCH: fix gcc.c-torture/execute/930126-1.c on m68k


Hi,

Above test case exposes a problem on m68k with misaligned integers on the
stack. When the function is inlined the structure is still copied on the
stack. The inlined function prepares the return value on the stack:

(insn/i 30 28 31 (set (zero_extract:SI (mem/s:QI (plus:SI (reg/f:SI 14 %a6)
                    (const_int -7 [0xfffffff9])) 1)
            (const_int 32 [0x20])
            (const_int 0 [0x0]))
        (const_double (cc0:CC) -839970252 [0xcdef1234] 0 [0x0] 0 [0x0])) 279 {*m68k.md:5277} (nil)
    (nil))

and then copies it back:

(insn/i 32 31 33 (set (mem/s:SI (symbol_ref:SI ("i.0")) 1)
        (mem/s:SI (plus:SI (reg/f:SI 14 %a6)
                (const_int -8 [0xfffffff8])) 1)) 29 {*m68k.md:976} (nil)
    (nil))

(insn/i 33 32 36 (set (mem/s:QI (const:SI (plus:SI (symbol_ref:SI ("i.0"))
                    (const_int 4 [0x4]))) 1)
        (mem/s:QI (plus:SI (reg/f:SI 14 %a6)
                (const_int -4 [0xfffffffc])) 1)) 36 {*m68k.md:1054} (nil)
    (nil))

After postreload insn 33 is gone.

The problem is cselib_invalidate_rtx is called with the first set and
strips away zero_extract, this causes the original machine mode to be
lost. cselib_invalidate_rtx calls write_dependence_p (through
cselib_invalidate_mem -> cselib_invalidate_mem_1 ->
cselib_mem_conflict_p -> anti_dependence) and write_dependence_p doesn't
know about the original machine and returns a wrong value. The patch
below basically propagates the correct machine mode to write_dependence_p.
I also changed the prototype of output_dependence, so it corresponds to
anti_dependence and true_dependence. The change in write_dependence_p
corresponds to what already exists in anti_dependence, so that VOIDmode
results in the old behavior.

BTW it's possible that sched_analyze_1 needs the same fix: it strips away
zero_extract/sign_extract and calls anti_dependence/output_dependence.

I've tested the patch on linux-m68k and linux-i686. The patch also applies
to 3.1 except that the changes to simplify-rtx.c have to be applied to
cselib.c.

bye, Roman

2001-07-20  Roman Zippel  <zippel@linux-m68k.org>

	* alias.c (write_dependence_p, anti_dependence,
	output_dependence): add machine mode argument
	* flow.c (insn_dead_p, invalidate_mems_from_set, mark_used_regs):
	Likewise
	* rtl.h: Likewise
	* sched-deps.c (sched_analyze_1): Likewise
	* simplify-rtx.c (cselib_mem_conflict_p, cselib_invalidate_mem):
	Likewise
	* simplify-rtx.c (cselib_invalidate_rtx): save original machine
	mode from sign_extract/zero_extract

Index: alias.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/alias.c,v
retrieving revision 1.115.4.5
diff -u -r1.115.4.5 alias.c
--- alias.c	2001/05/12 20:32:21	1.115.4.5
+++ alias.c	2001/07/17 00:50:37
@@ -104,7 +104,8 @@
 static rtx fixed_scalar_and_varying_struct_p PARAMS ((rtx, rtx, rtx, rtx,
 						      int (*) (rtx, int)));
 static int aliases_everything_p         PARAMS ((rtx));
-static int write_dependence_p           PARAMS ((rtx, rtx, int));
+static int write_dependence_p           PARAMS ((rtx, rtx,
+						 enum machine_mode, int));
 static int nonlocal_mentioned_p         PARAMS ((rtx));

 static int loop_p                       PARAMS ((void));
@@ -1769,9 +1770,10 @@
    (or, if WRITEP is non-zero, a write to) MEM.  */

 static int
-write_dependence_p (mem, x, writep)
+write_dependence_p (mem, x, x_mode, writep)
      rtx mem;
      rtx x;
+     enum machine_mode x_mode;
      int writep;
 {
   rtx x_addr, mem_addr;
@@ -1794,6 +1796,9 @@
   if (! writep && RTX_UNCHANGING_P (mem))
     return 0;

+  if (x_mode == VOIDmode)
+    x_mode = GET_MODE (x);
+
   x_addr = get_addr (XEXP (x, 0));
   mem_addr = get_addr (XEXP (mem, 0));

@@ -1806,7 +1811,7 @@
 	return 0;
     }

-  if (! base_alias_check (x_addr, mem_addr, GET_MODE (x),
+  if (! base_alias_check (x_addr, mem_addr, x_mode,
 			  GET_MODE (mem)))
     return 0;

@@ -1814,7 +1819,7 @@
   mem_addr = canon_rtx (mem_addr);

   if (!memrefs_conflict_p (SIZE_FOR_MODE (mem), mem_addr,
-			   SIZE_FOR_MODE (x), x_addr, 0))
+			   GET_MODE_SIZE(x_mode), x_addr, 0))
     return 0;

   fixed_scalar
@@ -1828,21 +1833,23 @@
 /* Anti dependence: X is written after read in MEM takes place.  */

 int
-anti_dependence (mem, x)
+anti_dependence (mem, x, x_mode)
      rtx mem;
+     enum machine_mode x_mode;
      rtx x;
 {
-  return write_dependence_p (mem, x, /*writep=*/0);
+  return write_dependence_p (mem, x, x_mode, /*writep=*/0);
 }

 /* Output dependence: X is written after store in MEM takes place.  */

 int
-output_dependence (mem, x)
+output_dependence (mem, x, x_mode)
      register rtx mem;
+     enum machine_mode x_mode;
      register rtx x;
 {
-  return write_dependence_p (mem, x, /*writep=*/1);
+  return write_dependence_p (mem, x, x_mode, /*writep=*/1);
 }

 /* Returns non-zero if X mentions something which is not
Index: flow.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/flow.c,v
retrieving revision 1.374.2.13
diff -u -r1.374.2.13 flow.c
--- flow.c	2001/06/06 07:32:24	1.374.2.13
+++ flow.c	2001/07/17 00:50:47
@@ -4146,7 +4146,7 @@
 	     rtx_equal_p does not check the alias set or flags, we also
 	     must have the potential for them to conflict (anti_dependence). */
 	  for (temp = pbi->mem_set_list; temp != 0; temp = XEXP (temp, 1))
-	    if (anti_dependence (r, XEXP (temp, 0)))
+	    if (anti_dependence (r, XEXP (temp, 0), VOIDmode))
 	      {
 		rtx mem = XEXP (temp, 0);

@@ -4412,7 +4412,7 @@
     {
       next = XEXP (temp, 1);
       if ((GET_CODE (exp) == MEM
-	   && output_dependence (XEXP (temp, 0), exp))
+	   && output_dependence (XEXP (temp, 0), exp, VOIDmode))
 	  || (GET_CODE (exp) == REG
 	      && reg_overlap_mentioned_p (exp, XEXP (temp, 0))))
 	{
@@ -5726,7 +5726,7 @@
 	      while (temp)
 		{
 		  next = XEXP (temp, 1);
-		  if (anti_dependence (XEXP (temp, 0), x))
+		  if (anti_dependence (XEXP (temp, 0), x, VOIDmode))
 		    {
 		      /* Splice temp out of the list.  */
 		      if (prev)
Index: rtl.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/rtl.h,v
retrieving revision 1.240.4.4
diff -u -r1.240.4.4 rtl.h
--- rtl.h	2001/05/13 21:36:15	1.240.4.4
+++ rtl.h	2001/07/17 00:50:59
@@ -2000,8 +2000,8 @@
 extern int true_dependence		PARAMS ((rtx, enum machine_mode, rtx,
 						int (*)(rtx, int)));
 extern int read_dependence		PARAMS ((rtx, rtx));
-extern int anti_dependence		PARAMS ((rtx, rtx));
-extern int output_dependence		PARAMS ((rtx, rtx));
+extern int anti_dependence		PARAMS ((rtx, rtx, enum machine_mode));
+extern int output_dependence		PARAMS ((rtx, rtx, enum machine_mode));
 extern void mark_constant_function	PARAMS ((void));
 extern void init_alias_once		PARAMS ((void));
 extern void init_alias_analysis		PARAMS ((void));
Index: sched-deps.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/sched-deps.c,v
retrieving revision 1.9.4.2
diff -u -r1.9.4.2 sched-deps.c
--- sched-deps.c	2001/05/20 20:05:25	1.9.4.2
+++ sched-deps.c	2001/07/17 00:50:59
@@ -690,7 +690,7 @@
 	  pending_mem = deps->pending_read_mems;
 	  while (pending)
 	    {
-	      if (anti_dependence (XEXP (pending_mem, 0), dest))
+	      if (anti_dependence (XEXP (pending_mem, 0), dest, VOIDmode))
 		add_dependence (insn, XEXP (pending, 0), REG_DEP_ANTI);

 	      pending = XEXP (pending, 1);
@@ -701,7 +701,7 @@
 	  pending_mem = deps->pending_write_mems;
 	  while (pending)
 	    {
-	      if (output_dependence (XEXP (pending_mem, 0), dest))
+	      if (output_dependence (XEXP (pending_mem, 0), dest, VOIDmode))
 		add_dependence (insn, XEXP (pending, 0), REG_DEP_OUTPUT);

 	      pending = XEXP (pending, 1);
Index: simplify-rtx.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/simplify-rtx.c,v
retrieving revision 1.41.2.3
diff -u -r1.41.2.3 simplify-rtx.c
--- simplify-rtx.c	2001/04/05 00:52:19	1.41.2.3
+++ simplify-rtx.c	2001/07/17 00:51:03
@@ -125,9 +125,9 @@
 static rtx cselib_subst_to_values	PARAMS ((rtx));
 static void cselib_invalidate_regno	PARAMS ((unsigned int,
 						 enum machine_mode));
-static int cselib_mem_conflict_p	PARAMS ((rtx, rtx));
+static int cselib_mem_conflict_p	PARAMS ((rtx, enum machine_mode, rtx));
 static int cselib_invalidate_mem_1	PARAMS ((void **, void *));
-static void cselib_invalidate_mem	PARAMS ((rtx));
+static void cselib_invalidate_mem	PARAMS ((rtx, enum machine_mode));
 static void cselib_invalidate_rtx	PARAMS ((rtx, rtx, void *));
 static void cselib_record_set		PARAMS ((rtx, cselib_val *,
 						 cselib_val *));
@@ -3059,8 +3059,9 @@
    Return whether this change will invalidate VAL.  */

 static int
-cselib_mem_conflict_p (mem_base, val)
+cselib_mem_conflict_p (mem_base, mem_mode, val)
      rtx mem_base;
+     enum machine_mode mem_mode;
      rtx val;
 {
   enum rtx_code code;
@@ -3085,7 +3086,7 @@
     case MEM:
       if (GET_MODE (mem_base) == BLKmode
 	  || GET_MODE (val) == BLKmode
-	  || anti_dependence (val, mem_base))
+	  || anti_dependence (val, mem_base, mem_mode))
 	return 1;

       /* The address may contain nested MEMs.  */
@@ -3100,12 +3101,12 @@
     {
       if (fmt[i] == 'e')
 	{
-	  if (cselib_mem_conflict_p (mem_base, XEXP (val, i)))
+	  if (cselib_mem_conflict_p (mem_base, mem_mode, XEXP (val, i)))
 	    return 1;
 	}
       else if (fmt[i] == 'E')
 	for (j = 0; j < XVECLEN (val, i); j++)
-	  if (cselib_mem_conflict_p (mem_base, XVECEXP (val, i, j)))
+	  if (cselib_mem_conflict_p (mem_base, mem_mode, XVECEXP (val, i, j)))
 	    return 1;
     }

@@ -3114,6 +3115,11 @@

 /* For the value found in SLOT, walk its locations to determine if any overlap
    INFO (which is a MEM rtx).  */
+struct cselib_invalidate_info
+{
+  enum machine_mode mode;
+  rtx exp;
+};

 static int
 cselib_invalidate_mem_1 (slot, info)
@@ -3121,7 +3127,7 @@
      void *info;
 {
   cselib_val *v = (cselib_val *) *slot;
-  rtx mem_rtx = (rtx) info;
+  struct cselib_invalidate_info *i = (struct cselib_invalidate_info *)info;
   struct elt_loc_list **p = &v->locs;
   int had_locs = v->locs != 0;

@@ -3134,7 +3140,7 @@
       /* MEMs may occur in locations only at the top level; below
 	 that every MEM or REG is substituted by its VALUE.  */
       if (GET_CODE (x) != MEM
-	  || ! cselib_mem_conflict_p (mem_rtx, x))
+	  || ! cselib_mem_conflict_p (i->exp, i->mode, x))
 	{
 	  p = &(*p)->next;
 	  continue;
@@ -3170,10 +3176,14 @@
    instruction, MEM_RTX is (mem:BLK const0_rtx).  */

 static void
-cselib_invalidate_mem (mem_rtx)
+cselib_invalidate_mem (mem_rtx, mem_mode)
      rtx mem_rtx;
+     enum machine_mode mem_mode;
 {
-  htab_traverse (hash_table, cselib_invalidate_mem_1, mem_rtx);
+  struct cselib_invalidate_info info;
+  info.exp = mem_rtx;
+  info.mode = mem_mode;
+  htab_traverse (hash_table, cselib_invalidate_mem_1, &info);
 }

 /* Invalidate DEST, which is being assigned to or clobbered.  The second and
@@ -3181,11 +3191,18 @@
    note_stores; they are ignored.  */

 static void
-cselib_invalidate_rtx (dest, ignore, data)
+cselib_invalidate_rtx (dest, set, data)
      rtx dest;
-     rtx ignore ATTRIBUTE_UNUSED;
+     rtx set;
      void *data ATTRIBUTE_UNUSED;
 {
+  enum machine_mode dest_mode = GET_MODE (dest);
+  if (set && GET_CODE(set) == SET)
+    {
+      if (GET_CODE (SET_DEST (set)) == SIGN_EXTRACT
+	   || GET_CODE (SET_DEST (set)) == ZERO_EXTRACT)
+	dest_mode = GET_MODE (SET_DEST (set));
+    }
   while (GET_CODE (dest) == STRICT_LOW_PART || GET_CODE (dest) == SIGN_EXTRACT
 	 || GET_CODE (dest) == ZERO_EXTRACT || GET_CODE (dest) == SUBREG)
     dest = XEXP (dest, 0);
@@ -3193,7 +3210,7 @@
   if (GET_CODE (dest) == REG)
     cselib_invalidate_regno (REGNO (dest), GET_MODE (dest));
   else if (GET_CODE (dest) == MEM)
-    cselib_invalidate_mem (dest);
+    cselib_invalidate_mem (dest, dest_mode);

   /* Some machines don't define AUTO_INC_DEC, but they still use push
      instructions.  We need to catch that case here in order to
@@ -3358,7 +3375,7 @@
 	  cselib_invalidate_regno (i, VOIDmode);

       if (! CONST_CALL_P (insn))
-	cselib_invalidate_mem (callmem);
+	cselib_invalidate_mem (callmem, VOIDmode);
     }

   cselib_record_sets (insn);


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