OSDN Git Service

* pa/pa.c (remove_useless_addtr_insns): New function.
authorlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 2 Oct 1996 17:42:18 +0000 (17:42 +0000)
committerlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 2 Oct 1996 17:42:18 +0000 (17:42 +0000)
        (pa_reorg): Delete code to remove useless add,tr insns.
        Instead call remove_useless_addtr_insns.
        (output_function_prologue): Call remove_useless_addtr_insns
        to catch any add,tr insns created by reorg.

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

gcc/config/pa/pa.c

index 5944770..9080f97 100644 (file)
@@ -1966,6 +1966,157 @@ output_ascii (file, p, size)
     }
   fputs ("\"\n", file);
 }
+
+/* Try to rewrite floating point comparisons & branches to avoid
+   useless add,tr insns.
+
+   CHECK_NOTES is nonzero if we should examine REG_DEAD notes
+   to see if FPCC is dead.  CHECK_NOTES is nonzero for the
+   first attempt to remove useless add,tr insns.  It is zero
+   for the second pass as reorg sometimes leaves bogus REG_DEAD
+   notes lying around.
+
+   When CHECK_NOTES is zero we can only eliminate add,tr insns
+   when there's a 1:1 correspondence between fcmp and ftest/fbranch
+   instructions.  */
+void
+remove_useless_addtr_insns (insns, check_notes)
+     rtx insns;
+     int check_notes;
+{
+  rtx insn;
+  int all;
+  static int pass = 0;
+
+  /* This is fairly cheap, so always run it when optimizing.  */
+  if (optimize > 0)
+    {
+      int fcmp_count = 0;
+      int fbranch_count = 0;
+
+      /* Walk all the insns in this function looking for fcmp & fbranch
+        instructions.  Keep track of how many of each we find.  */
+      insns = get_insns ();
+      for (insn = insns; insn; insn = next_insn (insn))
+       {
+         rtx tmp;
+
+         /* Ignore anything that isn't an INSN or a JUMP_INSN.  */
+         if (GET_CODE (insn) != INSN && GET_CODE (insn) != JUMP_INSN)
+           continue;
+
+         tmp = PATTERN (insn);
+
+         /* It must be a set.  */
+         if (GET_CODE (tmp) != SET)
+           continue;
+
+         /* If the destination is CCFP, then we've found an fcmp insn.  */
+         tmp = SET_DEST (tmp);
+         if (GET_CODE (tmp) == REG && REGNO (tmp) == 0)
+           {
+             fcmp_count++;
+             continue;
+           }
+           
+         tmp = PATTERN (insn);
+         /* If this is an fbranch instruction, bump the fbranch counter.  */
+         if (GET_CODE (tmp) == SET
+             && SET_DEST (tmp) == pc_rtx
+             && GET_CODE (SET_SRC (tmp)) == IF_THEN_ELSE
+             && GET_CODE (XEXP (SET_SRC (tmp), 0)) == NE
+             && GET_CODE (XEXP (XEXP (SET_SRC (tmp), 0), 0)) == REG
+             && REGNO (XEXP (XEXP (SET_SRC (tmp), 0), 0)) == 0)
+           {
+             fbranch_count++;
+             continue;
+           }
+       }
+
+
+      /* Find all floating point compare + branch insns.  If possible,
+        reverse the comparison & the branch to avoid add,tr insns.  */
+      for (insn = insns; insn; insn = next_insn (insn))
+       {
+         rtx tmp, next;
+
+         /* Ignore anything that isn't an INSN.  */
+         if (GET_CODE (insn) != INSN)
+           continue;
+
+         tmp = PATTERN (insn);
+
+         /* It must be a set.  */
+         if (GET_CODE (tmp) != SET)
+           continue;
+
+         /* The destination must be CCFP, which is register zero.  */
+         tmp = SET_DEST (tmp);
+         if (GET_CODE (tmp) != REG || REGNO (tmp) != 0)
+           continue;
+
+         /* INSN should be a set of CCFP.
+
+            See if the result of this insn is used in a reversed FP
+            conditional branch.  If so, reverse our condition and
+            the branch.  Doing so avoids useless add,tr insns.  */
+         next = next_insn (insn);
+         while (next)
+           {
+             /* Jumps, calls and labels stop our search.  */
+             if (GET_CODE (next) == JUMP_INSN
+                 || GET_CODE (next) == CALL_INSN
+                 || GET_CODE (next) == CODE_LABEL)
+               break;
+
+             /* As does another fcmp insn.  */
+             if (GET_CODE (next) == INSN
+                 && GET_CODE (PATTERN (next)) == SET
+                 && GET_CODE (SET_DEST (PATTERN (next))) == REG
+                 && REGNO (SET_DEST (PATTERN (next))) == 0)
+               break;
+
+             next = next_insn (next);
+           }
+
+         /* Is NEXT_INSN a branch?  */
+         if (next
+             && GET_CODE (next) == JUMP_INSN)
+           {
+             rtx pattern = PATTERN (next);
+
+             /* If it a reversed fp conditional branch (eg uses add,tr)
+                and CCFP dies, then reverse our conditional and the branch
+                to avoid the add,tr.  */
+             if (GET_CODE (pattern) == SET
+                 && SET_DEST (pattern) == pc_rtx
+                 && GET_CODE (SET_SRC (pattern)) == IF_THEN_ELSE
+                 && GET_CODE (XEXP (SET_SRC (pattern), 0)) == NE
+                 && GET_CODE (XEXP (XEXP (SET_SRC (pattern), 0), 0)) == REG
+                 && REGNO (XEXP (XEXP (SET_SRC (pattern), 0), 0)) == 0
+                 && GET_CODE (XEXP (SET_SRC (pattern), 1)) == PC
+                 && (fcmp_count == fbranch_count
+                     || (check_notes
+                         && find_regno_note (next, REG_DEAD, 0))))
+               {
+                 /* Reverse the branch.  */
+                 tmp = XEXP (SET_SRC (pattern), 1);
+                 XEXP (SET_SRC (pattern), 1) = XEXP (SET_SRC (pattern), 2);
+                 XEXP (SET_SRC (pattern), 2) = tmp;
+                 INSN_CODE (next) = -1;
+
+                 /* Reverse our condition.  */
+                 tmp = PATTERN (insn);
+                 PUT_CODE (XEXP (tmp, 1),
+                           reverse_condition (GET_CODE (XEXP (tmp, 1))));
+               }
+           }
+       }
+    }
+
+  pass = !pass;
+
+}
 \f
 /* You may have trouble believing this, but this is the HP-PA stack
    layout.  Wow.
@@ -2233,6 +2384,8 @@ output_function_prologue (file, size)
     }
   else
     total_code_bytes = -1;
+
+  remove_useless_addtr_insns (get_insns (), 0);
 }
 
 void
@@ -5494,87 +5647,7 @@ pa_reorg (insns)
 {
   rtx insn;
 
-  /* This is fairly cheap, so always run it if optimizing.  */
-  if (optimize > 0)
-    {
-      /* Find all floating point compare + branch insns.  If possible,
-        reverse the comparison & the branch to avoid add,tr insns.  */
-      insns = get_insns ();
-      for (insn = insns; insn; insn = NEXT_INSN (insn))
-       {
-         rtx tmp, next_insn;
-
-         /* Ignore anything that isn't an INSN.  */
-         if (GET_CODE (insn) != INSN)
-           continue;
-
-         tmp = PATTERN (insn);
-
-         /* It must be a set.  */
-         if (GET_CODE (tmp) != SET)
-           continue;
-
-         /* The destination must be CCFP, which is register zero.  */
-         tmp = SET_DEST (tmp);
-         if (GET_CODE (tmp) != REG || REGNO (tmp) != 0)
-           continue;
-
-         /* INSN should be a set of CCFP.
-
-            See if the result of this insn is used in a reversed FP
-            conditional branch.  If so, reverse our condition and
-            the branch.  Doing so avoids useless add,tr insns.  */
-         next_insn = NEXT_INSN (insn);
-         while (next_insn)
-           {
-             /* Jumps, calls and labels stop our search.  */
-             if (GET_CODE (next_insn) == JUMP_INSN
-                 || GET_CODE (next_insn) == CALL_INSN
-                 || GET_CODE (next_insn) == CODE_LABEL)
-               break;
-
-             /* As does another fcmp insn.  */
-             if (GET_CODE (next_insn) == INSN
-                 && GET_CODE (PATTERN (next_insn)) == SET
-                 && GET_CODE (SET_DEST (PATTERN (next_insn))) == REG
-                 && REGNO (SET_DEST (PATTERN (next_insn))) == 0)
-               break;
-
-             next_insn = NEXT_INSN (next_insn);
-           }
-
-         /* Is NEXT_INSN a branch?  */
-         if (next_insn
-             && GET_CODE (next_insn) == JUMP_INSN)
-           {
-             rtx pattern = PATTERN (next_insn);
-
-             /* If it a reversed fp conditional branch (eg uses add,tr)
-                and CCFP dies, then reverse our conditional and the branch
-                to avoid the add,tr.  */
-             if (GET_CODE (pattern) == SET
-                 && SET_DEST (pattern) == pc_rtx
-                 && GET_CODE (SET_SRC (pattern)) == IF_THEN_ELSE
-                 && GET_CODE (XEXP (SET_SRC (pattern), 0)) == NE
-                 && GET_CODE (XEXP (XEXP (SET_SRC (pattern), 0), 0)) == REG
-                 && REGNO (XEXP (XEXP (SET_SRC (pattern), 0), 0)) == 0
-                 && GET_CODE (XEXP (SET_SRC (pattern), 1)) == PC
-                 && find_regno_note (next_insn, REG_DEAD, 0))
-               {
-                 /* Reverse the branch.  */
-                 tmp = XEXP (SET_SRC (pattern), 1);
-                 XEXP (SET_SRC (pattern), 1) = XEXP (SET_SRC (pattern), 2);
-                 XEXP (SET_SRC (pattern), 2) = tmp;
-                 INSN_CODE (next_insn) = -1;
-
-                 /* Reverse our condition.  */
-                 tmp = PATTERN (insn);
-                 PUT_CODE (XEXP (tmp, 1),
-                           reverse_condition (GET_CODE (XEXP (tmp, 1))));
-               }
-           }
-       }
-    }
+  remove_useless_addtr_insns (insns, 1);
 
   /* This is fairly cheap, so always run it if optimizing.  */
   if (optimize > 0)