OSDN Git Service

* reorg.c (try_merge_delay_insns): Account for resources referenced
authorlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 30 Sep 1998 18:01:38 +0000 (18:01 +0000)
committerlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 30 Sep 1998 18:01:38 +0000 (18:01 +0000)
        in each instruction in INSN's delay list before trying to eliminate
        useless instructions.  Similarly when looking at a trial insn's delay
        slots.
        * reorg.c (check_annul_list_true_false): New function.
        (steal_delay_list_from_{target,fallthrough}): Call it and also
        refine tests for when we may annul if already filled a slot.
        (fill_slots_from_thread): Likewise.
        (delete_from_delay_slot): Return newly-created thread.
        (try_merge_delay_isns): Use its new return value.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@22685 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/reorg.c

index 81faece..44721e7 100644 (file)
@@ -1,3 +1,17 @@
+Wed Sep 30 18:43:32 1998  Herman ten Brugge <Haj.Ten.Brugge@net.HCC.nl> 
+
+       * reorg.c (try_merge_delay_insns): Account for resources referenced
+       in each instruction in INSN's delay list before trying to eliminate
+       useless instructions.  Similarly when looking at a trial insn's delay
+       slots.
+
+        * reorg.c (check_annul_list_true_false): New function.
+        (steal_delay_list_from_{target,fallthrough}): Call it and also
+        refine tests for when we may annul if already filled a slot.
+        (fill_slots_from_thread): Likewise.
+        (delete_from_delay_slot): Return newly-created thread.
+        (try_merge_delay_isns): Use its new return value.
+
 Wed Sep 30 18:29:26 1998  Jeffrey A Law  (law@cygnus.com)
 
        * loop.c (check_dbra_loop): Use a vanilla loop reversal if the biv is
index cd0b614..7b1b017 100644 (file)
@@ -234,7 +234,7 @@ static int insn_sets_resource_p PROTO((rtx, struct resources *, int));
 static rtx find_end_label      PROTO((void));
 static rtx emit_delay_sequence PROTO((rtx, rtx, int));
 static rtx add_to_delay_list   PROTO((rtx, rtx));
-static void delete_from_delay_slot PROTO((rtx));
+static rtx delete_from_delay_slot PROTO((rtx));
 static void delete_scheduled_jump PROTO((rtx));
 static void note_delay_statistics PROTO((int, int));
 static rtx optimize_skip       PROTO((rtx));
@@ -1011,7 +1011,7 @@ add_to_delay_list (insn, delay_list)
 /* Delete INSN from the delay slot of the insn that it is in.  This may
    produce an insn without anything in its delay slots.  */
 
-static void
+static rtx
 delete_from_delay_slot (insn)
      rtx insn;
 {
@@ -1060,6 +1060,8 @@ delete_from_delay_slot (insn)
 
   /* Show we need to fill this insn again.  */
   obstack_ptr_grow (&unfilled_slots_obstack, trial);
+
+  return trial;
 }
 \f
 /* Delete INSN, a JUMP_INSN.  If it is a conditional jump, we must track down
@@ -1624,6 +1626,31 @@ redirect_with_delay_list_safe_p (jump, newlabel, delay_list)
   return (li == NULL);
 }
 
+/* DELAY_LIST is a list of insns that have already been placed into delay
+   slots.  See if all of them have the same annulling status as ANNUL_TRUE_P.
+   If not, return 0; otherwise return 1.  */
+
+static int
+check_annul_list_true_false (annul_true_p, delay_list)
+     int annul_true_p;
+     rtx delay_list;
+{
+  rtx temp, trial;
+
+  if (delay_list)
+    {
+      for (temp = delay_list; temp; temp = XEXP (temp, 1))
+        {
+          rtx trial = XEXP (temp, 0);
+          if ((annul_true_p && INSN_FROM_TARGET_P (trial))
+             || (!annul_true_p && !INSN_FROM_TARGET_P (trial)))
+           return 0;
+        }
+    }
+  return 1;
+}
+
 \f
 /* INSN branches to an insn whose pattern SEQ is a SEQUENCE.  Given that
    the condition tested by INSN is CONDITION and the resources shown in
@@ -1714,9 +1741,15 @@ steal_delay_list_from_target (insn, condition, seq, delay_list,
               || (! insn_sets_resource_p (trial, other_needed, 0)
                   && ! may_trap_p (PATTERN (trial)))))
          ? eligible_for_delay (insn, total_slots_filled, trial, flags)
-         : (must_annul = 1,
-            eligible_for_annul_false (insn, total_slots_filled, trial, flags)))
+         : (must_annul || (delay_list == NULL && new_delay_list == NULL))
+            && (must_annul = 1,
+                check_annul_list_true_false (0, delay_list)
+                && check_annul_list_true_false (0, new_delay_list)
+                && eligible_for_annul_false (insn, total_slots_filled,
+                                             trial, flags)))
        {
+         if (must_annul)
+           used_annul = 1;
          temp = copy_rtx (trial);
          INSN_FROM_TARGET_P (temp) = 1;
          new_delay_list = add_to_delay_list (temp, new_delay_list);
@@ -1735,7 +1768,8 @@ steal_delay_list_from_target (insn, condition, seq, delay_list,
   /* Add any new insns to the delay list and update the count of the
      number of slots filled.  */
   *pslots_filled = total_slots_filled;
-  *pannul_p = must_annul;
+  if (used_annul)
+    *pannul_p = 1;
 
   if (delay_list == 0)
     return new_delay_list;
@@ -1765,6 +1799,8 @@ steal_delay_list_from_fallthrough (insn, condition, seq,
 {
   int i;
   int flags;
+  int must_annul = *pannul_p;
+  int used_annul = 0;
 
   flags = get_jump_flags (insn, JUMP_LABEL (insn));
 
@@ -1798,14 +1834,17 @@ steal_delay_list_from_fallthrough (insn, condition, seq,
          continue;
        }
 
-      if (! *pannul_p
+      if (! must_annul
          && ((condition == const_true_rtx
               || (! insn_sets_resource_p (trial, other_needed, 0)
                   && ! may_trap_p (PATTERN (trial)))))
          ? eligible_for_delay (insn, *pslots_filled, trial, flags)
-         : (*pannul_p = 1,
-            eligible_for_annul_true (insn, *pslots_filled, trial, flags)))
+         : (must_annul || delay_list == NULL) && (must_annul = 1,
+            check_annul_list_true_false (1, delay_list)
+            && eligible_for_annul_true (insn, *pslots_filled, trial, flags)))
        {
+         if (must_annul)
+           used_annul = 1;
          delete_from_delay_slot (trial);
          delay_list = add_to_delay_list (trial, delay_list);
 
@@ -1816,8 +1855,11 @@ steal_delay_list_from_fallthrough (insn, condition, seq,
        break;
     }
 
+  if (used_annul)
+    *pannul_p = 1;
   return delay_list;
 }
+
 \f
 /* Try merging insns starting at THREAD which match exactly the insns in
    INSN's delay list.
@@ -1849,13 +1891,15 @@ try_merge_delay_insns (insn, thread)
   CLEAR_RESOURCE (&set);
 
   /* If this is not an annulling branch, take into account anything needed in
-     NEXT_TO_MATCH.  This prevents two increments from being incorrectly
+     INSN's delay slot.  This prevents two increments from being incorrectly
      folded into one.  If we are annulling, this would be the correct
      thing to do.  (The alternative, looking at things set in NEXT_TO_MATCH
      will essentially disable this optimization.  This method is somewhat of
      a kludge, but I don't see a better way.)  */
   if (! annul_p)
-    mark_referenced_resources (next_to_match, &needed, 1);
+    for (i = 1 ; i < num_slots ; i++)
+      if (XVECEXP (PATTERN (insn), 0, i))
+        mark_referenced_resources (XVECEXP (PATTERN (insn), 0, i), &needed, 1);
 
   for (trial = thread; !stop_search_p (trial, 1); trial = next_trial)
     {
@@ -1904,8 +1948,6 @@ try_merge_delay_insns (insn, thread)
            break;
 
          next_to_match = XVECEXP (PATTERN (insn), 0, slot_number);
-         if (! annul_p)
-           mark_referenced_resources (next_to_match, &needed, 1);
        }
 
       mark_set_resources (trial, &set, 0, 1);
@@ -1941,8 +1983,12 @@ try_merge_delay_insns (insn, thread)
            {
              if (! annul_p)
                {
+                 rtx new;
+
                  update_block (dtrial, thread);
-                 delete_from_delay_slot (dtrial);
+                 new = delete_from_delay_slot (dtrial);
+                 if (INSN_DELETED_P (thread))
+                   thread = new;
                  INSN_FROM_TARGET_P (next_to_match) = 0;
                }
              else
@@ -1954,6 +2000,12 @@ try_merge_delay_insns (insn, thread)
 
              next_to_match = XVECEXP (PATTERN (insn), 0, slot_number);
            }
+         else
+           {
+             /* Keep track of the set/referenced resources for 
+              mark_set_resources (dtrial, &set, 0, 1);
+              mark_referenced_resources (dtrial, &needed, 1);
+           }
        }
     }
 
@@ -1968,8 +2020,12 @@ try_merge_delay_insns (insn, thread)
        {
          if (GET_MODE (merged_insns) == SImode)
            {
+             rtx new;
+
              update_block (XEXP (merged_insns, 0), thread);
-             delete_from_delay_slot (XEXP (merged_insns, 0));
+             new = delete_from_delay_slot (XEXP (merged_insns, 0));
+             if (INSN_DELETED_P (thread))
+               thread = new;
            }
          else
            {
@@ -3600,9 +3656,10 @@ fill_slots_from_thread (insn, condition, thread, opposite_thread, likely,
          /* There are two ways we can win:  If TRIAL doesn't set anything
             needed at the opposite thread and can't trap, or if it can
             go into an annulled delay slot.  */
-         if (condition == const_true_rtx
-             || (! insn_sets_resource_p (trial, &opposite_needed, 1)
-                 && ! may_trap_p (pat)))
+         if (!must_annul
+             && (condition == const_true_rtx
+                 || (! insn_sets_resource_p (trial, &opposite_needed, 1)
+                     && ! may_trap_p (pat))))
            {
              old_trial = trial;
              trial = try_split (pat, trial, 0);
@@ -3630,9 +3687,11 @@ fill_slots_from_thread (insn, condition, thread, opposite_thread, likely,
              if (thread == old_trial)
                thread = trial;
              pat = PATTERN (trial);
-             if ((thread_if_true
-                  ? eligible_for_annul_false (insn, *pslots_filled, trial, flags)
-                  : eligible_for_annul_true (insn, *pslots_filled, trial, flags)))
+             if ((must_annul || delay_list == NULL) && (thread_if_true
+                  ? check_annul_list_true_false (0, delay_list)
+                    && eligible_for_annul_false (insn, *pslots_filled, trial, flags)
+                  : check_annul_list_true_false (1, delay_list)
+                    && eligible_for_annul_true (insn, *pslots_filled, trial, flags)))
                {
                  rtx temp;