rtl.h (insns_safe_to_move_p): New function.
authorMark Mitchell <mark@codesourcery.com>
Sun, 19 Sep 1999 16:04:01 +0000 (16:04 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Sun, 19 Sep 1999 16:04:01 +0000 (16:04 +0000)
* rtl.h (insns_safe_to_move_p): New function.
* loop.c (find_and_verify_loops): Use it.
* rtlanal.c (insns_safe_to_move_p): Define it.

From-SVN: r29509

gcc/ChangeLog
gcc/loop.c
gcc/rtl.h
gcc/rtlanal.c
gcc/testsuite/g++.old-deja/g++.eh/crash1.C [new file with mode: 0644]

index 5a57dd51872addc842811b623984f5e6b3dcd8b6..a8ff106d887243b5a94f8501e98b75db06d1f013 100644 (file)
@@ -1,3 +1,9 @@
+Sun Sep 19 09:03:40 1999  Mark Mitchell  <mark@codesourcery.com>
+
+       * rtl.h (insns_safe_to_move_p): New function.
+       * loop.c (find_and_verify_loops): Use it.
+       * rtlanal.c (insns_safe_to_move_p): Define it.
+
 Sat Sep 18 16:01:18 1999  Alexandre Oliva  <oliva@lsd.ic.unicamp.br>
 
        * config/i386/sol2.h (CPP_SPEC): Support -[p]threads
index dcff6850fbdd5affd7c2e11959de20a6a55cf9dd..cc278dce84844c8a20361f0ab8759ded9efd761f 100644 (file)
@@ -2779,6 +2779,7 @@ find_and_verify_loops (f)
          {
            rtx p;
            rtx our_next = next_real_insn (insn);
+           rtx last_insn_to_move = NEXT_INSN (insn);
            int dest_loop;
            int outer_loop = -1;
 
@@ -2830,7 +2831,11 @@ find_and_verify_loops (f)
                && INSN_UID (JUMP_LABEL (p)) != 0
                && condjump_p (p)
                && ! simplejump_p (p)
-               && next_real_insn (JUMP_LABEL (p)) == our_next)
+               && next_real_insn (JUMP_LABEL (p)) == our_next
+               /* If it's not safe to move the sequence, then we
+                  mustn't try.  */
+               && insns_safe_to_move_p (p, NEXT_INSN (insn), 
+                                        &last_insn_to_move))
              {
                rtx target
                  = JUMP_LABEL (insn) ? JUMP_LABEL (insn) : get_last_insn ();
@@ -2885,11 +2890,13 @@ find_and_verify_loops (f)
 
                       /* Include the BARRIER after INSN and copy the
                          block after LOC.  */
-                      new_label = squeeze_notes (new_label, NEXT_INSN (insn));
-                      reorder_insns (new_label, NEXT_INSN (insn), loc);
+                      new_label = squeeze_notes (new_label, 
+                                                 last_insn_to_move);
+                      reorder_insns (new_label, last_insn_to_move, loc);
 
                       /* All those insns are now in TARGET_LOOP_NUM.  */
-                      for (q = new_label; q != NEXT_INSN (NEXT_INSN (insn));
+                      for (q = new_label; 
+                           q != NEXT_INSN (last_insn_to_move);
                            q = NEXT_INSN (q))
                         uid_loop_num[INSN_UID (q)] = target_loop_num;
 
index 59043eadaeaec83b4ff664af5fc922ac7b4ca974..94790a6e19e9010ebc9810b945e73a72e036947c 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -1130,6 +1130,7 @@ extern int for_each_rtx                 PROTO((rtx *, rtx_function, void *));
 extern rtx regno_use_in                        PROTO((int, rtx));
 extern int auto_inc_p                  PROTO((rtx));
 extern void remove_node_from_expr_list PROTO((rtx, rtx *));
+extern int insns_safe_to_move_p         PROTO((rtx, rtx, rtx *));
 
 /* flow.c */
 
index d1b23222ad7986a25880dae465ce49ffd7adb12d..b02be3e2e53cfd22009ea608ee37f3045d047b60 100644 (file)
@@ -2293,3 +2293,73 @@ auto_inc_p (x)
     }
   return 0;
 }
+
+/* Return 1 if the sequence of instructions beginning with FROM and up
+   to and including TO is safe to move.  If NEW_TO is non-NULL, and
+   the sequence is not already safe to move, but can be easily
+   extended to a sequence which is safe, then NEW_TO will point to the
+   end of the extended sequence.  */
+
+int
+insns_safe_to_move_p (from, to, new_to)
+     rtx from;
+     rtx to;
+     rtx *new_to;
+{
+  int eh_region_count = 0;
+  int past_to_p = 0;
+  rtx r = from;
+
+  while (r)
+    {
+      if (GET_CODE (r) == NOTE)
+       {
+         switch (NOTE_LINE_NUMBER (r))
+           {
+           case NOTE_INSN_EH_REGION_BEG:
+             ++eh_region_count;
+             break;
+
+           case NOTE_INSN_EH_REGION_END:
+             if (eh_region_count == 0)
+               /* This sequence of instructions contains the end of
+                  an exception region, but not he beginning.  Moving
+                  it will cause chaos.  */
+               return 0;
+
+             --eh_region_count;
+             break;
+
+           default:
+             break;
+           }
+       }
+      else if (past_to_p)
+       /* If we've passed TO, and we see a non-note instruction, we
+          can't extend the sequence to a movable sequence.  */
+       return 0;
+
+      if (r == to)
+       {
+         if (!new_to)
+           /* It's OK to move the sequence if there were matched sets of
+              exception region notes.  */
+           return eh_region_count == 0;
+         
+         past_to_p = 1;
+       }
+
+      /* It's OK to move the sequence if there were matched sets of
+        exception region notes.  */
+      if (past_to_p && eh_region_count == 0)
+       {
+         *new_to = r;
+         return 1;
+       }
+
+      /* Go to the next instruction.  */
+      r = NEXT_INSN (r);
+    }
+  
+  return 0;
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.eh/crash1.C b/gcc/testsuite/g++.old-deja/g++.eh/crash1.C
new file mode 100644 (file)
index 0000000..6ba4d08
--- /dev/null
@@ -0,0 +1,22 @@
+// Build don't link:
+// Special g++ Options: -O1 -fno-inline-functions
+
+struct A
+{
+  ~A ();
+};
+
+bool foo ();
+
+int i;
+int j;
+
+A bar ()
+{
+  for (i = 0; i < 1; ++i)
+    if (j)
+      {
+       A tmp;
+       return tmp;
+      }
+}