re PR target/12900 (g++ ICE in rtl_verify_flow_info_1)
authorEric Botcazou <ebotcazou@libertysurf.fr>
Thu, 27 Nov 2003 06:36:52 +0000 (07:36 +0100)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Thu, 27 Nov 2003 06:36:52 +0000 (06:36 +0000)
PR target/12900
* reg-stack (move_for_stack_reg): New prototype.  Return
whether a control flow insn was deleted.
(subst_stack_regs_pat): Likewise, using the information provided
by move_for_stack_reg.
(subst_stack_regs): Likewise, using the information provided
by subst_stack_regs_pat.
(convert_regs_1): Record whether a control flow insn was deleted,
using the information provided by subst_stack_regs.  Purge dead
edges only if a control flow insn was deleted.

From-SVN: r73977

gcc/ChangeLog
gcc/reg-stack.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/opt/reg-stack4.C [new file with mode: 0644]

index f68c34b8c57811a2db678148c931cc3313dbae6c..419e698e57c31087271b5f738c9a179a36d4450f 100644 (file)
@@ -1,3 +1,16 @@
+2003-11-27  Eric Botcazou  <ebotcazou@libertysurf.fr>
+
+       PR target/12900
+       * reg-stack (move_for_stack_reg): New prototype.  Return
+       whether a control flow insn was deleted.
+       (subst_stack_regs_pat): Likewise, using the information provided
+       by move_for_stack_reg.
+       (subst_stack_regs): Likewise, using the information provided
+       by subst_stack_regs_pat.
+       (convert_regs_1): Record whether a control flow insn was deleted,
+       using the information provided by subst_stack_regs.  Purge dead
+       edges only if a control flow insn was deleted.
+
 2003-11-27  Eric Botcazou  <ebotcazou@libertysurf.fr>
 
        PR middle-end/8028
index 08d26f60c32669422c3e179157c1f82f73ef78d2..fd9bdea96fb6181740ae91e09319c4b08bb4b89a 100644 (file)
@@ -249,13 +249,13 @@ static void remove_regno_note (rtx, enum reg_note, unsigned int);
 static int get_hard_regnum (stack, rtx);
 static rtx emit_pop_insn (rtx, stack, rtx, enum emit_where);
 static void emit_swap_insn (rtx, stack, rtx);
-static void move_for_stack_reg (rtx, stack, rtx);
+static bool move_for_stack_reg (rtx, stack, rtx);
 static int swap_rtx_condition_1 (rtx);
 static int swap_rtx_condition (rtx);
 static void compare_for_stack_reg (rtx, stack, rtx);
-static void subst_stack_regs_pat (rtx, stack, rtx);
+static bool subst_stack_regs_pat (rtx, stack, rtx);
 static void subst_asm_stack_regs (rtx, stack);
-static void subst_stack_regs (rtx, stack);
+static bool subst_stack_regs (rtx, stack);
 static void change_stack (rtx, stack, stack, enum emit_where);
 static int convert_regs_entry (void);
 static void convert_regs_exit (void);
@@ -1028,15 +1028,17 @@ emit_swap_insn (rtx insn, stack regstack, rtx reg)
 }
 \f
 /* Handle a move to or from a stack register in PAT, which is in INSN.
-   REGSTACK is the current stack.  */
+   REGSTACK is the current stack.  Return whether a control flow insn
+   was deleted in the process.  */
 
-static void
+static bool
 move_for_stack_reg (rtx insn, stack regstack, rtx pat)
 {
   rtx *psrc =  get_true_reg (&SET_SRC (pat));
   rtx *pdest = get_true_reg (&SET_DEST (pat));
   rtx src, dest;
   rtx note;
+  bool control_flow_insn_deleted = false;
 
   src = *psrc; dest = *pdest;
 
@@ -1066,21 +1068,17 @@ move_for_stack_reg (rtx insn, stack regstack, rtx pat)
             If so, just pop the src.  */
 
          if (find_regno_note (insn, REG_UNUSED, REGNO (dest)))
+           emit_pop_insn (insn, regstack, src, EMIT_AFTER);
+         else
            {
-             emit_pop_insn (insn, regstack, src, EMIT_AFTER);
-
-             delete_insn (insn);
-             return;
+             regstack->reg[i] = REGNO (dest);
+             SET_HARD_REG_BIT (regstack->reg_set, REGNO (dest));
+             CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (src));
            }
 
-         regstack->reg[i] = REGNO (dest);
-
-         SET_HARD_REG_BIT (regstack->reg_set, REGNO (dest));
-         CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (src));
-
+         control_flow_insn_deleted |= control_flow_insn_p (insn);
          delete_insn (insn);
-
-         return;
+         return control_flow_insn_deleted;
        }
 
       /* The source reg does not die.  */
@@ -1095,8 +1093,9 @@ move_for_stack_reg (rtx insn, stack regstack, rtx pat)
          if (find_regno_note (insn, REG_UNUSED, REGNO (dest)))
            emit_pop_insn (insn, regstack, dest, EMIT_AFTER);
 
+         control_flow_insn_deleted |= control_flow_insn_p (insn);
          delete_insn (insn);
-         return;
+         return control_flow_insn_deleted;
        }
 
       /* The destination ought to be dead.  */
@@ -1165,6 +1164,8 @@ move_for_stack_reg (rtx insn, stack regstack, rtx pat)
     }
   else
     abort ();
+
+  return control_flow_insn_deleted;
 }
 \f
 /* Swap the condition on a branch, if there is one.  Return true if we
@@ -1376,12 +1377,14 @@ compare_for_stack_reg (rtx insn, stack regstack, rtx pat_src)
 }
 \f
 /* Substitute new registers in PAT, which is part of INSN.  REGSTACK
-   is the current register layout.  */
+   is the current register layout.  Return whether a control flow insn
+   was deleted in the process.  */
 
-static void
+static bool
 subst_stack_regs_pat (rtx insn, stack regstack, rtx pat)
 {
   rtx *dest, *src;
+  bool control_flow_insn_deleted = false;
 
   switch (GET_CODE (pat))
     {
@@ -1393,7 +1396,7 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat)
          && find_regno_note (insn, REG_DEAD, REGNO (*src)))
        {
          emit_pop_insn (insn, regstack, *src, EMIT_AFTER);
-         return;
+         return control_flow_insn_deleted;
        }
       /* ??? Uninitialized USE should not happen.  */
       else if (get_hard_regnum (regstack, *src) == -1)
@@ -1443,7 +1446,7 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat)
                                       FP_MODE_REG (REGNO (*dest), SFmode),
                                       nan);
                    PATTERN (insn) = pat;
-                   move_for_stack_reg (insn, regstack, pat);
+                   control_flow_insn_deleted |= move_for_stack_reg (insn, regstack, pat);
                  }
                if (! note && COMPLEX_MODE_P (GET_MODE (*dest))
                    && get_hard_regnum (regstack, FP_MODE_REG (REGNO (*dest), DFmode)) == -1)
@@ -1452,7 +1455,7 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat)
                                       FP_MODE_REG (REGNO (*dest) + 1, SFmode),
                                       nan);
                    PATTERN (insn) = pat;
-                   move_for_stack_reg (insn, regstack, pat);
+                   control_flow_insn_deleted |= move_for_stack_reg (insn, regstack, pat);
                  }
              }
          }
@@ -1475,7 +1478,7 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat)
                && (GET_CODE (*src) == REG || GET_CODE (*src) == MEM
                    || GET_CODE (*src) == CONST_DOUBLE)))
          {
-           move_for_stack_reg (insn, regstack, pat);
+           control_flow_insn_deleted |= move_for_stack_reg (insn, regstack, pat);
            break;
          }
 
@@ -1879,6 +1882,8 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat)
     default:
       break;
     }
+
+  return control_flow_insn_deleted;
 }
 \f
 /* Substitute hard regnums for any stack regs in INSN, which has
@@ -2176,12 +2181,14 @@ subst_asm_stack_regs (rtx insn, stack regstack)
 /* Substitute stack hard reg numbers for stack virtual registers in
    INSN.  Non-stack register numbers are not changed.  REGSTACK is the
    current stack content.  Insns may be emitted as needed to arrange the
-   stack for the 387 based on the contents of the insn.  */
+   stack for the 387 based on the contents of the insn.  Return whether
+   a control flow insn was deleted in the process.  */
 
-static void
+static bool
 subst_stack_regs (rtx insn, stack regstack)
 {
   rtx *note_link, note;
+  bool control_flow_insn_deleted = false;
   int i;
 
   if (GET_CODE (insn) == CALL_INSN)
@@ -2222,25 +2229,27 @@ subst_stack_regs (rtx insn, stack regstack)
             Any REG_UNUSED notes will be handled by subst_asm_stack_regs.  */
 
          subst_asm_stack_regs (insn, regstack);
-         return;
+         return control_flow_insn_deleted;
        }
 
       if (GET_CODE (PATTERN (insn)) == PARALLEL)
        for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
          {
            if (stack_regs_mentioned_p (XVECEXP (PATTERN (insn), 0, i)))
-             subst_stack_regs_pat (insn, regstack,
-                                   XVECEXP (PATTERN (insn), 0, i));
+             control_flow_insn_deleted
+               |= subst_stack_regs_pat (insn, regstack,
+                                        XVECEXP (PATTERN (insn), 0, i));
          }
       else
-       subst_stack_regs_pat (insn, regstack, PATTERN (insn));
+       control_flow_insn_deleted
+         |= subst_stack_regs_pat (insn, regstack, PATTERN (insn));
     }
 
   /* subst_stack_regs_pat may have deleted a no-op insn.  If so, any
      REG_UNUSED will already have been dealt with, so just return.  */
 
   if (GET_CODE (insn) == NOTE || INSN_DELETED_P (insn))
-    return;
+    return control_flow_insn_deleted;
 
   /* If there is a REG_UNUSED note on a stack register on this insn,
      the indicated reg must be popped.  The REG_UNUSED note is removed,
@@ -2256,6 +2265,8 @@ subst_stack_regs (rtx insn, stack regstack)
       }
     else
       note_link = &XEXP (note, 1);
+
+  return control_flow_insn_deleted;
 }
 \f
 /* Change the organization of the stack so that it fits a new basic
@@ -2638,6 +2649,7 @@ convert_regs_1 (FILE *file, basic_block block)
   int deleted, inserted, reg;
   rtx insn, next;
   edge e, beste = NULL;
+  bool control_flow_insn_deleted = false;
 
   inserted = 0;
   deleted = 0;
@@ -2726,8 +2738,7 @@ convert_regs_1 (FILE *file, basic_block block)
                       INSN_UID (insn));
              print_stack (file, &regstack);
            }
-         subst_stack_regs (insn, &regstack);
-         deleted |= (GET_CODE (insn) == NOTE || INSN_DELETED_P (insn));
+         control_flow_insn_deleted |= subst_stack_regs (insn, &regstack);
        }
     }
   while (next);
@@ -2766,8 +2777,7 @@ convert_regs_1 (FILE *file, basic_block block)
          set = gen_rtx_SET (VOIDmode, FP_MODE_REG (reg, SFmode),
                             nan);
          insn = emit_insn_after (set, insn);
-         subst_stack_regs (insn, &regstack);
-         deleted |= (GET_CODE (insn) == NOTE || INSN_DELETED_P (insn));
+         control_flow_insn_deleted |= subst_stack_regs (insn, &regstack);
        }
     }
   
@@ -2777,12 +2787,18 @@ convert_regs_1 (FILE *file, basic_block block)
      called at the end of convert_regs.  The order in which we process the
      blocks ensures that we never delete an already processed edge.
 
+     Note that, at this point, the CFG may have been damaged by the emission
+     of instructions after an abnormal call, which moves the basic block end
+     (and is the reason why we call fixup_abnormal_edges later).  So we must
+     be sure that the trapping insn has been deleted before trying to purge
+     dead edges, otherwise we risk purging valid edges.
+
      ??? We are normally supposed not to delete trapping insns, so we pretend
      that the insns deleted above don't actually trap.  It would have been
      better to detect this earlier and avoid creating the EH edge in the first
      place, still, but we don't have enough information at that time.  */
 
-  if (deleted)
+  if (control_flow_insn_deleted)
     purge_dead_edges (block);
 
   /* Something failed if the stack lives don't match.  If we had malformed
index 20faca0c1f57c830f7596f9d047790cdf8c8aff4..1f516a1e7964ab23cc7b946eeaafbb236afc9cfb 100644 (file)
@@ -1,3 +1,7 @@
+2003-11-27  Eric Botcazou  <ebotcazou@libertysurf.fr>
+
+       * g++.dg/opt/reg-stack4.C: New test.
+
 2003-11-27  Eric Botcazou  <ebotcazou@libertysurf.fr>
 
        * gcc.dg/builtin-apply2.c: New test.
diff --git a/gcc/testsuite/g++.dg/opt/reg-stack4.C b/gcc/testsuite/g++.dg/opt/reg-stack4.C
new file mode 100644 (file)
index 0000000..7b461d8
--- /dev/null
@@ -0,0 +1,29 @@
+// PR target/12900
+// Origin: <snyder@fnal.gov>
+
+// This used to fail on x86 because the reg-stack pass
+// deleted a valid edge.
+
+// { dg-do compile }
+// { dg-options "-mtune=i586 -O2" { target i?86-*-* } }
+
+struct array {
+  double data;
+  virtual ~array();
+};
+
+double glob;
+double ext1(double);
+int nmuons;
+
+void track_match()
+{
+  array vecdca;
+  if (glob < 10) return;
+  double p = glob*5;
+  double phi = vecdca.data;
+  ext1 (vecdca.data-glob);
+  ext1 (phi*2);
+  if (1 < p)
+    ++nmuons; 
+}