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: problem with basic block reorder and reorg (correct version)


Hello,

I had a problem with the new basic block reorder pass combined with reorg.
When I compile the next program:

typedef struct {
         int fd;
         unsigned char* buf;
         unsigned char* pos;
         unsigned char* buff_stop;
         unsigned int flags;
         int index;
} FILE;
int
ungetc(int _c, register FILE *_fp)
{
   if(_fp->fd == -1) return ((-1));
   if(_c == (-1) || (_fp->pos < _fp->buf)) return ((-1));
   if((((_fp)->flags) & (0x0040)))
   {
      (((_fp)->flags) &= ~(0x0020));
      (((_fp)->flags) |= (0x0010));
   }
   if(_fp->buf == 0 && !(((_fp)->flags) & (0x0004)))
      if(setvbuf(_fp, 0, (((_fp)->flags) & (0x0001 | 0x0002 | 0x0004)), 256) == (-1)) return ((-1));
   *(--_fp->pos) = (unsigned char)_c;
   (((_fp)->flags) |= (0x0800));
   (((_fp)->flags) &= ~(0x0200));
   if(!_fp->buff_stop) _fp->buff_stop = _fp->buf;
   return ((unsigned char)_c);
}

on the c4x target. The return insn at the end is missing. This happens
in the reorg pass. Here we check if there is a return insn at the end
of the code in the function find_end_label. If we can not find one we
try to insert a new one. This inserting fails because the return insn
on the c4x can only be used when under certain conditions.
The real return insn is moved by the new basic block reorder pass and is
not present at the end of the code anymore. I modified the reorg code
to search for the new location of the return insn.
I did check if this could happen on other targets. The conditions that
trigger this are:
- HAVE_return must be present and it must be conditional
- HAVE_epilogue must be present
- define_delay must be present
If I did this correctly then the c4x, mips, pa and sh have the same
conditions present. The code above only triggers the bug on the c4x.
Other test programs are probably needed to trigger this bug on the
other targets. 

My previous patch was at the wrong place and did not include a header.
I also found a new problem that is also coverred by this patch. This
new problem showed up while running the torture tests. find_end_label
can generate a new label that invalidates the optimazation in function
relax_delay_slots. Needless to say that this patch passes the torture
tests.
Looks like I need more coffee.

	Herman.

2000-09-03 Herman A.J. ten Brugge <Haj.Ten.Brugge@net.HCC.nl>

	* reorg.c (find_end_label): If the basic block reorder pass moves the
	return insn to some other place try to locate it again and put our
	end_of_function_label there.
	* reorg.c (relax_delay_slots): Check if find_end_label created a
	new label that invalidates the current optimazation.


--- reorg.c.org	Sun Sep  3 19:15:28 2000
+++ reorg.c	Sun Sep  3 20:09:25 2000
@@ -375,22 +375,42 @@ find_end_label ()
     end_of_function_label = insn;
   else
     {
-      /* Otherwise, make a new label and emit a RETURN and BARRIER,
-	 if needed.  */
       end_of_function_label = gen_label_rtx ();
       LABEL_NUSES (end_of_function_label) = 0;
-      emit_label (end_of_function_label);
-#ifdef HAVE_return
-      if (HAVE_return)
-	{
-	  /* The return we make may have delay slots too.  */
-	  rtx insn = gen_return ();
-	  insn = emit_jump_insn (insn);
-	  emit_barrier ();
-          if (num_delay_slots (insn) > 0)
-	    obstack_ptr_grow (&unfilled_slots_obstack, insn);
+      /* If the basic block reorder pass moves the return insn to
+	 some other place try to locate it again and put our
+	 end_of_function_label there.  */
+      while (insn && ! (GET_CODE (insn) == JUMP_INSN
+		        && (GET_CODE (PATTERN (insn)) == RETURN)))
+	insn = PREV_INSN (insn);
+      if (insn)
+	{
+	  insn = PREV_INSN (insn);
+
+      	  /* Put the label before an USE insns that may proceed the
+	     RETURN insn.  */
+      	  while (GET_CODE (insn) == USE)
+	    insn = PREV_INSN (insn);
+
+      	  emit_label_after (end_of_function_label, insn);
 	}
+      else
+	{
+          /* Otherwise, make a new label and emit a RETURN and BARRIER,
+	     if needed.  */
+          emit_label (end_of_function_label);
+#ifdef HAVE_return
+          if (HAVE_return)
+	    {
+	      /* The return we make may have delay slots too.  */
+	      rtx insn = gen_return ();
+	      insn = emit_jump_insn (insn);
+	      emit_barrier ();
+              if (num_delay_slots (insn) > 0)
+	        obstack_ptr_grow (&unfilled_slots_obstack, insn);
+	    }
 #endif
+	}
     }
 
   /* Show one additional use for this label so it won't go away until
@@ -3322,7 +3342,9 @@ relax_delay_slots (first)
 	  if (label == 0)
 	    label = find_end_label ();
 
-	  if (redirect_with_delay_slots_safe_p (delay_insn, label, insn))
+	  /* find_end_label can generate a new label. Check this first.  */
+	  if (no_labels_between_p (insn, next)
+	      && redirect_with_delay_slots_safe_p (delay_insn, label, insn))
 	    {
 	      /* Be careful how we do this to avoid deleting code or labels
 		 that are momentarily dead.  See similar optimization in

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