]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Improve reload code generation by ignoring init insns for reloads.
authorBernd Schmidt <bernds@codesourcery.com>
Wed, 21 May 2014 09:29:34 +0000 (09:29 +0000)
committerBernd Schmidt <bernds@gcc.gnu.org>
Wed, 21 May 2014 09:29:34 +0000 (09:29 +0000)
     * reload1.c (remove_init_insns, will_delete_init_insn_p): New static
     functions.
     (reload, calculate_needs_all_insns, reload_as_needed): Use them.

From-SVN: r210685

gcc/ChangeLog
gcc/reload1.c

index ac9558695f2d88b5d4c546c9086e9c3b778ffbb4..bfa1ec7eb63d4eb63d6c157d37ededb157ede5e1 100644 (file)
 
 2014-05-19  Bernd Schmidt  <bernds@codesourcery.com>
 
+       * reload1.c (remove_init_insns, will_delete_init_insn_p): New static
+       functions.
+       (reload, calculate_needs_all_insns, reload_as_needed): Use them.
+
        * simplify-rtx.c (simplify_unary_operation_1): Use CONST_INT_P in
        shift simplification where it was intended.
 
index 3d735eeeec97ef1d53a335cf5d0e2cc8087f2604..9daafa45097fc16714b10db6ef463900e2255dec 100644 (file)
@@ -686,6 +686,65 @@ static int failure;
 /* Temporary array of pseudo-register number.  */
 static int *temp_pseudo_reg_arr;
 
+/* If a pseudo has no hard reg, delete the insns that made the equivalence.
+   If that insn didn't set the register (i.e., it copied the register to
+   memory), just delete that insn instead of the equivalencing insn plus
+   anything now dead.  If we call delete_dead_insn on that insn, we may
+   delete the insn that actually sets the register if the register dies
+   there and that is incorrect.  */
+static void
+remove_init_insns ()
+{
+  for (int i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
+    {
+      if (reg_renumber[i] < 0 && reg_equiv_init (i) != 0)
+       {
+         rtx list;
+         for (list = reg_equiv_init (i); list; list = XEXP (list, 1))
+           {
+             rtx equiv_insn = XEXP (list, 0);
+
+             /* If we already deleted the insn or if it may trap, we can't
+                delete it.  The latter case shouldn't happen, but can
+                if an insn has a variable address, gets a REG_EH_REGION
+                note added to it, and then gets converted into a load
+                from a constant address.  */
+             if (NOTE_P (equiv_insn)
+                 || can_throw_internal (equiv_insn))
+               ;
+             else if (reg_set_p (regno_reg_rtx[i], PATTERN (equiv_insn)))
+               delete_dead_insn (equiv_insn);
+             else
+               SET_INSN_DELETED (equiv_insn);
+           }
+       }
+    }
+}
+
+/* Return true if remove_init_insns will delete INSN.  */
+static bool
+will_delete_init_insn_p (rtx insn)
+{
+  rtx set = single_set (insn);
+  if (!set || !REG_P (SET_DEST (set)))
+    return false;
+  unsigned regno = REGNO (SET_DEST (set));
+
+  if (can_throw_internal (insn))
+    return false;
+
+  if (regno < FIRST_PSEUDO_REGISTER || reg_renumber[regno] >= 0)
+    return false;
+
+  for (rtx list = reg_equiv_init (regno); list; list = XEXP (list, 1))
+    {
+      rtx equiv_insn = XEXP (list, 0);
+      if (equiv_insn == insn)
+       return true;
+    }
+  return false;
+}
+
 /* Main entry point for the reload pass.
 
    FIRST is the first insn of the function being compiled.
@@ -993,37 +1052,7 @@ reload (rtx first, int global)
       if (ep->can_eliminate)
        mark_elimination (ep->from, ep->to);
 
-  /* If a pseudo has no hard reg, delete the insns that made the equivalence.
-     If that insn didn't set the register (i.e., it copied the register to
-     memory), just delete that insn instead of the equivalencing insn plus
-     anything now dead.  If we call delete_dead_insn on that insn, we may
-     delete the insn that actually sets the register if the register dies
-     there and that is incorrect.  */
-
-  for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
-    {
-      if (reg_renumber[i] < 0 && reg_equiv_init (i) != 0)
-       {
-         rtx list;
-         for (list = reg_equiv_init (i); list; list = XEXP (list, 1))
-           {
-             rtx equiv_insn = XEXP (list, 0);
-
-             /* If we already deleted the insn or if it may trap, we can't
-                delete it.  The latter case shouldn't happen, but can
-                if an insn has a variable address, gets a REG_EH_REGION
-                note added to it, and then gets converted into a load
-                from a constant address.  */
-             if (NOTE_P (equiv_insn)
-                 || can_throw_internal (equiv_insn))
-               ;
-             else if (reg_set_p (regno_reg_rtx[i], PATTERN (equiv_insn)))
-               delete_dead_insn (equiv_insn);
-             else
-               SET_INSN_DELETED (equiv_insn);
-           }
-       }
-    }
+  remove_init_insns ();
 
   /* Use the reload registers where necessary
      by generating move instructions to move the must-be-register
@@ -1484,14 +1513,9 @@ calculate_needs_all_insns (int global)
          rtx old_notes = REG_NOTES (insn);
          int did_elimination = 0;
          int operands_changed = 0;
-         rtx set = single_set (insn);
 
          /* Skip insns that only set an equivalence.  */
-         if (set && REG_P (SET_DEST (set))
-             && reg_renumber[REGNO (SET_DEST (set))] < 0
-             && (reg_equiv_constant (REGNO (SET_DEST (set)))
-                 || (reg_equiv_invariant (REGNO (SET_DEST (set)))))
-                     && reg_equiv_init (REGNO (SET_DEST (set))))
+         if (will_delete_init_insn_p (insn))
            continue;
 
          /* If needed, eliminate any eliminable registers.  */
@@ -4586,6 +4610,9 @@ reload_as_needed (int live_known)
       rtx old_prev = PREV_INSN (insn);
 #endif
 
+      if (will_delete_init_insn_p (insn))
+       continue;
+
       /* If we pass a label, copy the offsets from the label information
         into the current offsets of each elimination.  */
       if (LABEL_P (insn))