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]

PATH: reorg.c improve optimize_skip (second try)


Hello,

This is the second time I am trying to send this patch. Could some one
review this patch?

Text from last patch:
I generated some new code for reorg.c to handle targets with more than
1 delay slot. Currently only the c4x (3 delay slots) has these. I know
some one who is working on the sharc port (2 delay slots) for gcc that
also uses these patches.
I optimized the routine optimize_skip to handle more than 1 delay slot.
The routine is only called for empty delay lists. We cannot generate
a skip insn if we allready have some delay insns in the delay list
because we could annul them.
We also do not return any insns from optimize_skip is we could not
find a skip. We do this because we only checked for annul_true/annul_false
and not for normal delay insns. Normal delay insns are prefered because
they allways execute in the delay list.

	Herman.

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

        * reorg.c (optimize_skip) Handle targets with more than 1 delay slot.


--- reorg.c.org	Mon Jul 31 17:48:33 2000
+++ reorg.c	Mon Jul 31 17:48:42 2000
@@ -190,7 +190,7 @@ static rtx delete_from_delay_slot	PARAMS
 static void delete_scheduled_jump	PARAMS ((rtx));
 static void note_delay_statistics	PARAMS ((int, int));
 #if defined(ANNUL_IFFALSE_SLOTS) || defined(ANNUL_IFTRUE_SLOTS)
-static rtx optimize_skip		PARAMS ((rtx));
+static rtx optimize_skip		PARAMS ((rtx, int, int *));
 #endif
 static int get_jump_flags		PARAMS ((rtx, rtx));
 static int rare_destination		PARAMS ((rtx));
@@ -692,83 +692,145 @@ note_delay_statistics (slots_filled, ind
       L1:	      L1:
 	Bra L2		Bra L2
 
-   INSN is a JUMP_INSN.
-
-   This should be expanded to skip over N insns, where N is the number
-   of delay slots required.  */
+   INSN is a JUMP_INSN. */
 
 static rtx
-optimize_skip (insn)
+optimize_skip (insn, slots_to_fill, slots_filled)
      register rtx insn;
+     int slots_to_fill;
+     int *slots_filled;
 {
   register rtx trial = next_nonnote_insn (insn);
-  rtx next_trial = next_active_insn (trial);
+  rtx next_trial;
+  rtx list;
+  rtx next_active;
   rtx delay_list = 0;
-  rtx target_label;
-  int flags;
+  int slot;
+  int flags = get_jump_flags (insn, JUMP_LABEL (insn));
 
-  flags = get_jump_flags (insn, JUMP_LABEL (insn));
+  for (slot = 0; slot < slots_to_fill ; slot++, trial = next_trial)
+    {
+      next_trial = next_nonnote_insn (trial);
 
-  if (trial == 0
-      || GET_CODE (trial) != INSN
-      || GET_CODE (PATTERN (trial)) == SEQUENCE
-      || recog_memoized (trial) < 0
-      || (! eligible_for_annul_false (insn, 0, trial, flags)
-	  && ! eligible_for_annul_true (insn, 0, trial, flags)))
-    return 0;
+      if (trial == 0
+          || GET_CODE (trial) != INSN
+          || GET_CODE (PATTERN (trial)) == SEQUENCE
+          || recog_memoized (trial) < 0
+          || (! eligible_for_annul_false (insn, slot, trial, flags)
+	      && ! eligible_for_annul_true (insn, slot, trial, flags)))
+        return 0;
 
-  /* There are two cases where we are just executing one insn (we assume
-     here that a branch requires only one insn; this should be generalized
-     at some point):  Where the branch goes around a single insn or where
-     we have one insn followed by a branch to the same label we branch to.
-     In both of these cases, inverting the jump and annulling the delay
-     slot give the same effect in fewer insns.  */
-  if ((next_trial == next_active_insn (JUMP_LABEL (insn))
-       && ! (next_trial == 0 && current_function_epilogue_delay_list != 0))
-      || (next_trial != 0
-	  && GET_CODE (next_trial) == JUMP_INSN
-	  && JUMP_LABEL (insn) == JUMP_LABEL (next_trial)
-	  && (simplejump_p (next_trial)
-	      || GET_CODE (PATTERN (next_trial)) == RETURN)))
-    {
-      if (eligible_for_annul_false (insn, 0, trial, flags))
-	{
-	  if (invert_jump (insn, JUMP_LABEL (insn), 1))
-	    INSN_FROM_TARGET_P (trial) = 1;
-	  else if (! eligible_for_annul_true (insn, 0, trial, flags))
-	    return 0;
-	}
+      /* The trial is a valid annul_true or annul_false insn so add to
+	 the delay_list.  */
+      delay_list = add_to_delay_list (trial, delay_list);
+
+      /* There are two cases where we can generate a skip insn (we assume
+         here that a branch requires only one insn; this should be generalized
+         at some point):  Where the branch goes around a single insn or where
+         we have one insn followed by a branch to the same label we branch to.
+         In both of these cases, inverting the jump and annulling the delay
+         slot give the same effect in fewer insns.  */
+
+      next_active = next_active_insn (trial);
+      if ((next_active == next_active_insn (JUMP_LABEL (insn))
+	  && ! (next_active == 0 && current_function_epilogue_delay_list != 0))
+          || (next_active != 0
+	      && GET_CODE (next_active) == JUMP_INSN
+	      && JUMP_LABEL (insn) == JUMP_LABEL (next_active)
+	      && (simplejump_p (next_active)
+	          || GET_CODE (PATTERN (next_active)) == RETURN)))
+        {
+	  /* Check if all insns in the list are allowed for annul_false.  */
+	  for (slot = 0, list = delay_list; list; list = XEXP (list, 1))
+	    if (!eligible_for_annul_false (insn, slot++, XEXP (list, 0),
+					   flags))
+		break;
 
-      delay_list = add_to_delay_list (trial, NULL_RTX);
-      next_trial = next_active_insn (trial);
-      update_block (trial, trial);
-      delete_insn (trial);
-
-      /* Also, if we are targeting an unconditional
-	 branch, thread our jump to the target of that branch.  Don't
-	 change this into a RETURN here, because it may not accept what
-	 we have in the delay slot.  We'll fix this up later.  */
-      if (next_trial && GET_CODE (next_trial) == JUMP_INSN
-	  && (simplejump_p (next_trial)
-	      || GET_CODE (PATTERN (next_trial)) == RETURN))
-	{
-	  target_label = JUMP_LABEL (next_trial);
-	  if (target_label == 0)
-	    target_label = find_end_label ();
-
-	  /* Recompute the flags based on TARGET_LABEL since threading
-	     the jump to TARGET_LABEL may change the direction of the
-	     jump (which may change the circumstances in which the
-	     delay slot is nullified).  */
-	  flags = get_jump_flags (insn, target_label);
-	  if (eligible_for_annul_true (insn, 0, trial, flags))
-	    reorg_redirect_jump (insn, target_label);
-	}
+	  if (!list)
+	    {
+	      /* All insns did match annul_false. Now try to invert
+	         the jump. */
+	      if (invert_jump (insn, JUMP_LABEL (insn), 1), 1)
+		{
+		  /* If we did invert the jump we have found a valid skip and
+		     have to mark all insns in the list. The insns should only
+		     be executed if the branch is taken.  */
+		  for (list = delay_list; list; list = XEXP (list, 1))
+	            INSN_FROM_TARGET_P (XEXP (list, 0)) = 1;
+		}
+	      else
+		{
+	          /* If we could not invert the jump check if all insns in
+		     the list are allowed for annul_true.
+		     Fail if some do not match.  */
+	          for (slot = 0, list = delay_list; list; list = XEXP (list, 1))
+	            if (!eligible_for_annul_true (insn, slot++, XEXP (list, 0),
+					          flags))
+	              return 0;
+		}
+	    }
+	  else
+	    {
+	      /* If not all insns match annul_false. Check if all insns
+		 in the list are allowed for annul_true.
+	         Fail if some do not match.  */
+	      for (slot = 0, list = delay_list; list; list = XEXP (list, 1))
+	        if (!eligible_for_annul_true (insn, slot++, XEXP (list, 0),
+					      flags))
+	          return 0;
+	    }
 
-      INSN_ANNULLED_BRANCH_P (insn) = 1;
+	  /* We found a valid list. Delete the insns.  */
+	  for (list = delay_list; list; list = XEXP (list, 1))
+	    {
+	      rtx tmp = XEXP (list, 0);
+
+              update_block (tmp, tmp);
+              delete_insn (tmp);
+              (*slots_filled)++;
+	    }
+	
+          /* Also, if we are targeting an unconditional
+	     branch, thread our jump to the target of that branch.  Don't
+	     change this into a RETURN here, because it may not accept what
+	     we have in the delay slot.  We'll fix this up later.  */
+          if (next_active && GET_CODE (next_active) == JUMP_INSN
+	      && (simplejump_p (next_active)
+	          || GET_CODE (PATTERN (next_active)) == RETURN))
+	    {
+	      rtx target_label = JUMP_LABEL (next_active);
+	      if (target_label == 0)
+	        target_label = find_end_label ();
+
+	      /* Recompute the flags based on TARGET_LABEL since threading
+	         the jump to TARGET_LABEL may change the direction of the
+	         jump (which may change the circumstances in which the
+	         delay slot is nullified).  */
+	      flags = get_jump_flags (insn, target_label);
+	      for (slot = 0, trial = delay_list;
+		   trial; 
+		   slot++, trial = XEXP (trial, 1))
+	        {
+	          rtx tmp = XEXP (trial, 0);
+
+		  if (INSN_FROM_TARGET_P (tmp)
+		      || !eligible_for_annul_true (insn, slot, tmp, flags))
+		    break;
+		}
+	      if (!trial)
+	        reorg_redirect_jump (insn, target_label);
+	    }
+
+          INSN_ANNULLED_BRANCH_P (insn) = 1;
+	  return delay_list;
+	}
     }
 
-  return delay_list;
+  /* We can not return the delay list if we did not generate a skip.
+     We did only test for annulling branches and not for normal
+     delay insns. First trying the normal delay insns is better because
+     they allways execute in the delay slot.  */
+  return 0;
 }
 #endif
 
@@ -2178,14 +2277,16 @@ fill_simple_delay_slots (non_jumps_p)
 
       /* Try to optimize case of jumping around a single insn.  */
 #if defined(ANNUL_IFFALSE_SLOTS) || defined(ANNUL_IFTRUE_SLOTS)
+      /* Only call optimize_skip when the current delay list is empty.
+	 If we allready had insns in the delay list we could not
+	 use a skip insn because we could annul all the insns in the
+         delay list.  */
       if (slots_filled != slots_to_fill
 	  && delay_list == 0
 	  && GET_CODE (insn) == JUMP_INSN 
 	  && (condjump_p (insn) || condjump_in_parallel_p (insn)))
 	{
-	  delay_list = optimize_skip (insn);
-	  if (delay_list)
-	    slots_filled += 1;
+	  delay_list = optimize_skip (insn, slots_to_fill, &slots_filled);
 	}
 #endif
 

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