]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/combine-stack-adj.c
PR fortran/95090 - ICE: identifier overflow
[thirdparty/gcc.git] / gcc / combine-stack-adj.c
index 20cd59ad08329e9f4f834bfc01d6f9ccc4485283..281166bf6955aa69056b0c3a9126e233b5a5555b 100644 (file)
@@ -1,5 +1,5 @@
 /* Combine stack adjustments.
-   Copyright (C) 1987-2017 Free Software Foundation, Inc.
+   Copyright (C) 1987-2020 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -70,9 +70,10 @@ static rtx single_set_for_csa (rtx_insn *);
 static void free_csa_reflist (struct csa_reflist *);
 static struct csa_reflist *record_one_stack_ref (rtx_insn *, rtx *,
                                                 struct csa_reflist *);
-static int try_apply_stack_adjustment (rtx_insn *, struct csa_reflist *,
-                                      HOST_WIDE_INT, HOST_WIDE_INT);
-static void combine_stack_adjustments_for_block (basic_block);
+static bool try_apply_stack_adjustment (rtx_insn *, struct csa_reflist *,
+                                       HOST_WIDE_INT, HOST_WIDE_INT,
+                                       bitmap, rtx_insn *);
+static void combine_stack_adjustments_for_block (basic_block, bitmap);
 
 
 /* Main entry point for stack adjustment combination.  */
@@ -81,9 +82,12 @@ static void
 combine_stack_adjustments (void)
 {
   basic_block bb;
+  bitmap live = BITMAP_ALLOC (&reg_obstack);
 
   FOR_EACH_BB_FN (bb, cfun)
-    combine_stack_adjustments_for_block (bb);
+    combine_stack_adjustments_for_block (bb, live);
+
+  BITMAP_FREE (live);
 }
 
 /* Recognize a MEM of the form (sp) or (plus sp const).  */
@@ -208,6 +212,7 @@ no_unhandled_cfa (rtx_insn *insn)
       case REG_CFA_SET_VDRAP:
       case REG_CFA_WINDOW_SAVE:
       case REG_CFA_FLUSH_QUEUE:
+      case REG_CFA_TOGGLE_RA_MANGLE:
        return false;
       }
 
@@ -218,18 +223,60 @@ no_unhandled_cfa (rtx_insn *insn)
    as each of the memories and stack references in REFLIST.  Return true
    on success.  */
 
-static int
+static bool
 try_apply_stack_adjustment (rtx_insn *insn, struct csa_reflist *reflist,
-                           HOST_WIDE_INT new_adjust, HOST_WIDE_INT delta)
+                           HOST_WIDE_INT new_adjust, HOST_WIDE_INT delta,
+                           bitmap live, rtx_insn *other_insn)
 {
   struct csa_reflist *ml;
   rtx set;
+  bool remove_equal = false;
 
   set = single_set_for_csa (insn);
   if (MEM_P (SET_DEST (set)))
     validate_change (insn, &SET_DEST (set),
                     replace_equiv_address (SET_DEST (set), stack_pointer_rtx),
                     1);
+  else if (REG_P (SET_SRC (set)))
+    {
+      if (other_insn == NULL_RTX || live == NULL)
+       return false;
+      rtx other_set = single_set_for_csa (other_insn);
+      if (SET_DEST (other_set) != stack_pointer_rtx
+         || GET_CODE (SET_SRC (other_set)) != PLUS
+         || XEXP (SET_SRC (other_set), 0) != stack_pointer_rtx
+         || !CONST_INT_P (XEXP (SET_SRC (other_set), 1)))
+       return false;
+      if (PATTERN (other_insn) != other_set)
+       {
+         if (GET_CODE (PATTERN (other_insn)) != PARALLEL)
+           return false;
+         int i;
+         rtx p = PATTERN (other_insn);
+         for (i = 0; i < XVECLEN (p, 0); ++i)
+           {
+             rtx this_rtx = XVECEXP (p, 0, i);
+             if (this_rtx == other_set)
+               continue;
+             if (GET_CODE (this_rtx) != CLOBBER)
+               return false;
+             if (!REG_P (XEXP (this_rtx, 0))
+                 || !HARD_REGISTER_P (XEXP (this_rtx, 0)))
+               return false;
+             unsigned int end_regno = END_REGNO (XEXP (this_rtx, 0));
+             for (unsigned int regno = REGNO (XEXP (this_rtx, 0));
+                  regno < end_regno; ++regno)
+               if (bitmap_bit_p (live, regno))
+                 return false;
+           }
+       }
+      validate_change (insn, &PATTERN (insn), copy_rtx (PATTERN (other_insn)),
+                      1);
+      set = single_set_for_csa (insn);
+      validate_change (insn, &XEXP (SET_SRC (set), 1), GEN_INT (new_adjust),
+                      1);
+      remove_equal = true;
+    }
   else
     validate_change (insn, &XEXP (SET_SRC (set), 1), GEN_INT (new_adjust), 1);
 
@@ -255,10 +302,12 @@ try_apply_stack_adjustment (rtx_insn *insn, struct csa_reflist *reflist,
       for (ml = reflist; ml ; ml = ml->next)
        ml->sp_offset -= delta;
 
-      return 1;
+      if (remove_equal)
+       remove_reg_equal_equiv_notes (insn);
+      return true;
     }
   else
-    return 0;
+    return false;
 }
 
 /* For non-debug insns, record all stack memory references in INSN
@@ -488,16 +537,21 @@ force_move_args_size_note (basic_block bb, rtx_insn *prev, rtx_insn *insn)
 /* Subroutine of combine_stack_adjustments, called for each basic block.  */
 
 static void
-combine_stack_adjustments_for_block (basic_block bb)
+combine_stack_adjustments_for_block (basic_block bb, bitmap live)
 {
   HOST_WIDE_INT last_sp_adjust = 0;
   rtx_insn *last_sp_set = NULL;
   rtx_insn *last2_sp_set = NULL;
+  bitmap last_sp_live = NULL;
   struct csa_reflist *reflist = NULL;
+  bitmap copy = NULL;
   rtx_insn *insn, *next;
   rtx set;
   bool end_of_block = false;
 
+  bitmap_copy (live, DF_LR_IN (bb));
+  df_simulate_initialize_forwards (bb, live);
+
   for (insn = BB_HEAD (bb); !end_of_block ; insn = next)
     {
       end_of_block = insn == BB_END (bb);
@@ -507,25 +561,49 @@ combine_stack_adjustments_for_block (basic_block bb)
        continue;
 
       set = single_set_for_csa (insn);
+      if (set && find_reg_note (insn, REG_STACK_CHECK, NULL_RTX))
+       set = NULL_RTX;
       if (set)
        {
          rtx dest = SET_DEST (set);
          rtx src = SET_SRC (set);
+         HOST_WIDE_INT this_adjust = 0;
 
          /* Find constant additions to the stack pointer.  */
          if (dest == stack_pointer_rtx
              && GET_CODE (src) == PLUS
              && XEXP (src, 0) == stack_pointer_rtx
              && CONST_INT_P (XEXP (src, 1)))
+           this_adjust = INTVAL (XEXP (src, 1));
+         /* Or such additions turned by postreload into a store of
+            equivalent register.  */
+         else if (dest == stack_pointer_rtx
+                  && REG_P (src)
+                  && REGNO (src) != STACK_POINTER_REGNUM)
+           if (rtx equal = find_reg_note (insn, REG_EQUAL, NULL_RTX))
+             if (GET_CODE (XEXP (equal, 0)) == PLUS
+                 && XEXP (XEXP (equal, 0), 0) == stack_pointer_rtx
+                 && CONST_INT_P (XEXP (XEXP (equal, 0), 1)))
+               this_adjust = INTVAL (XEXP (XEXP (equal, 0), 1));
+
+         if (this_adjust)
            {
-             HOST_WIDE_INT this_adjust = INTVAL (XEXP (src, 1));
-
              /* If we've not seen an adjustment previously, record
                 it now and continue.  */
              if (! last_sp_set)
                {
                  last_sp_set = insn;
                  last_sp_adjust = this_adjust;
+                 if (REG_P (src))
+                   {
+                     if (copy == NULL)
+                       copy = BITMAP_ALLOC (&reg_obstack);
+                     last_sp_live = copy;
+                     bitmap_copy (last_sp_live, live);
+                   }
+                 else
+                   last_sp_live = NULL;
+                 df_simulate_one_insn_forwards (bb, insn, live);
                  continue;
                }
 
@@ -536,7 +614,7 @@ combine_stack_adjustments_for_block (basic_block bb)
                 Also we need to be careful to not move stack pointer
                 such that we create stack accesses outside the allocated
                 area.  We can combine an allocation into the first insn,
-                or a deallocation into the second insn.  We can not
+                or a deallocation into the second insn.  We cannot
                 combine an allocation followed by a deallocation.
 
                 The only somewhat frequent occurrence of the later is when
@@ -557,13 +635,16 @@ combine_stack_adjustments_for_block (basic_block bb)
                      && try_apply_stack_adjustment (last_sp_set, reflist,
                                                     last_sp_adjust
                                                     + this_adjust,
-                                                    this_adjust))
+                                                    this_adjust,
+                                                    last_sp_live,
+                                                    insn))
                    {
                      /* It worked!  */
                      maybe_move_args_size_note (last_sp_set, insn, false);
                      maybe_merge_cfa_adjust (last_sp_set, insn, false);
                      delete_insn (insn);
                      last_sp_adjust += this_adjust;
+                     last_sp_live = NULL;
                      continue;
                    }
                }
@@ -574,10 +655,12 @@ combine_stack_adjustments_for_block (basic_block bb)
                       ? last_sp_adjust >= 0 : last_sp_adjust <= 0)
                {
                  if (no_unhandled_cfa (last_sp_set)
+                     && !REG_P (src)
                      && try_apply_stack_adjustment (insn, reflist,
                                                     last_sp_adjust
                                                     + this_adjust,
-                                                    -last_sp_adjust))
+                                                    -last_sp_adjust,
+                                                    NULL, NULL))
                    {
                      /* It worked!  */
                      maybe_move_args_size_note (insn, last_sp_set, true);
@@ -585,8 +668,10 @@ combine_stack_adjustments_for_block (basic_block bb)
                      delete_insn (last_sp_set);
                      last_sp_set = insn;
                      last_sp_adjust += this_adjust;
+                     last_sp_live = NULL;
                      free_csa_reflist (reflist);
                      reflist = NULL;
+                     df_simulate_one_insn_forwards (bb, insn, live);
                      continue;
                    }
                }
@@ -609,6 +694,16 @@ combine_stack_adjustments_for_block (basic_block bb)
              reflist = NULL;
              last_sp_set = insn;
              last_sp_adjust = this_adjust;
+             if (REG_P (src))
+               {
+                 if (copy == NULL)
+                   copy = BITMAP_ALLOC (&reg_obstack);
+                 last_sp_live = copy;
+                 bitmap_copy (last_sp_live, live);
+               }
+             else
+               last_sp_live = NULL;
+             df_simulate_one_insn_forwards (bb, insn, live);
              continue;
            }
 
@@ -619,11 +714,11 @@ combine_stack_adjustments_for_block (basic_block bb)
          if (MEM_P (dest)
              && ((STACK_GROWS_DOWNWARD
                   ? (GET_CODE (XEXP (dest, 0)) == PRE_DEC
-                     && last_sp_adjust
-                        == (HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (dest)))
+                     && known_eq (last_sp_adjust,
+                                  GET_MODE_SIZE (GET_MODE (dest))))
                   : (GET_CODE (XEXP (dest, 0)) == PRE_INC
-                     && last_sp_adjust
-                        == -(HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (dest))))
+                     && known_eq (-last_sp_adjust,
+                                  GET_MODE_SIZE (GET_MODE (dest)))))
                  || ((STACK_GROWS_DOWNWARD
                       ? last_sp_adjust >= 0 : last_sp_adjust <= 0)
                      && GET_CODE (XEXP (dest, 0)) == PRE_MODIFY
@@ -638,7 +733,8 @@ combine_stack_adjustments_for_block (basic_block bb)
              && !reg_mentioned_p (stack_pointer_rtx, src)
              && memory_address_p (GET_MODE (dest), stack_pointer_rtx)
              && try_apply_stack_adjustment (insn, reflist, 0,
-                                            -last_sp_adjust))
+                                            -last_sp_adjust,
+                                            NULL, NULL))
            {
              if (last2_sp_set)
                maybe_move_args_size_note (last2_sp_set, last_sp_set, false);
@@ -649,13 +745,17 @@ combine_stack_adjustments_for_block (basic_block bb)
              reflist = NULL;
              last_sp_set = NULL;
              last_sp_adjust = 0;
+             last_sp_live = NULL;
+             df_simulate_one_insn_forwards (bb, insn, live);
              continue;
            }
        }
 
-      if (!CALL_P (insn) && last_sp_set
-         && record_stack_refs (insn, &reflist))
-       continue;
+      if (!CALL_P (insn) && last_sp_set && record_stack_refs (insn, &reflist))
+       {
+         df_simulate_one_insn_forwards (bb, insn, live);
+         continue;
+       }
 
       /* Otherwise, we were not able to process the instruction.
         Do not continue collecting data across such a one.  */
@@ -673,7 +773,10 @@ combine_stack_adjustments_for_block (basic_block bb)
          last2_sp_set = NULL;
          last_sp_set = NULL;
          last_sp_adjust = 0;
+         last_sp_live = NULL;
        }
+
+      df_simulate_one_insn_forwards (bb, insn, live);
     }
 
   if (last_sp_set && last_sp_adjust == 0)
@@ -684,6 +787,8 @@ combine_stack_adjustments_for_block (basic_block bb)
 
   if (reflist)
     free_csa_reflist (reflist);
+  if (copy)
+    BITMAP_FREE (copy);
 }
 \f
 static unsigned int