OSDN Git Service

PR rtl-opt/49994
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 12 Aug 2011 21:00:00 +0000 (21:00 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 12 Aug 2011 21:00:00 +0000 (21:00 +0000)
        * sched-init.h (struct deps_desc): Add sched_before_next_jump.
        * sched-deps.c (init_deps): Clear it.
        (deps_analyze_insn): Consume it.
        (sched_analyze_insn): Fill it.

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

gcc/ChangeLog
gcc/sched-deps.c
gcc/sched-int.h
gcc/testsuite/gcc.dg/pr49994-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr49994-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr49994-3.c [new file with mode: 0644]

index 91d3f18..3aa3a5d 100644 (file)
@@ -1,3 +1,11 @@
+2011-08-12  Richard Henderson  <rth@redhat.com>
+
+       PR rtl-opt/49994
+       * sched-init.h (struct deps_desc): Add sched_before_next_jump.
+       * sched-deps.c (init_deps): Clear it.
+       (deps_analyze_insn): Consume it.
+       (sched_analyze_insn): Fill it.
+
 2011-08-12  Ramana Radhakrishnan  <ramana.radhakrishnan@linaro.org>
 
         PR target/48328
 2011-08-12  Ramana Radhakrishnan  <ramana.radhakrishnan@linaro.org>
 
         PR target/48328
index 2961cca..ed592c8 100644 (file)
@@ -2696,6 +2696,18 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
     add_dependence_list (insn, deps->last_function_call_may_noreturn,
                         1, REG_DEP_ANTI);
 
     add_dependence_list (insn, deps->last_function_call_may_noreturn,
                         1, REG_DEP_ANTI);
 
+  /* We must avoid creating a situation in which two successors of the
+     current block have different unwind info after scheduling.  If at any
+     point the two paths re-join this leads to incorrect unwind info.  */
+  /* ??? There are certain situations involving a forced frame pointer in
+     which, with extra effort, we could fix up the unwind info at a later
+     CFG join.  However, it seems better to notice these cases earlier
+     during prologue generation and avoid marking the frame pointer setup
+     as frame-related at all.  */
+  if (RTX_FRAME_RELATED_P (insn))
+    deps->sched_before_next_jump
+      = alloc_INSN_LIST (insn, deps->sched_before_next_jump);
+
   if (code == COND_EXEC)
     {
       sched_analyze_2 (deps, COND_EXEC_TEST (x), insn);
   if (code == COND_EXEC)
     {
       sched_analyze_2 (deps, COND_EXEC_TEST (x), insn);
@@ -3302,12 +3314,11 @@ deps_analyze_insn (struct deps_desc *deps, rtx insn)
   if (NONDEBUG_INSN_P (insn))
     sched_get_condition_with_rev (insn, NULL);
 
   if (NONDEBUG_INSN_P (insn))
     sched_get_condition_with_rev (insn, NULL);
 
-  if (NONJUMP_INSN_P (insn) || DEBUG_INSN_P (insn) || JUMP_P (insn))
+  if (JUMP_P (insn))
     {
       /* Make each JUMP_INSN (but not a speculative check)
          a scheduling barrier for memory references.  */
       if (!deps->readonly
     {
       /* Make each JUMP_INSN (but not a speculative check)
          a scheduling barrier for memory references.  */
       if (!deps->readonly
-          && JUMP_P (insn)
           && !(sel_sched_p ()
                && sel_insn_is_speculation_check (insn)))
         {
           && !(sel_sched_p ()
                && sel_insn_is_speculation_check (insn)))
         {
@@ -3326,6 +3337,15 @@ deps_analyze_insn (struct deps_desc *deps, rtx insn)
            }
         }
 
            }
         }
 
+      /* For each insn which shouldn't cross a jump, add a dependence.  */
+      add_dependence_list_and_free (deps, insn,
+                                   &deps->sched_before_next_jump, 1,
+                                   REG_DEP_ANTI);
+
+      sched_analyze_insn (deps, PATTERN (insn), insn);
+    }
+  else if (NONJUMP_INSN_P (insn) || DEBUG_INSN_P (insn))
+    {
       sched_analyze_insn (deps, PATTERN (insn), insn);
     }
   else if (CALL_P (insn))
       sched_analyze_insn (deps, PATTERN (insn), insn);
     }
   else if (CALL_P (insn))
@@ -3571,6 +3591,7 @@ init_deps (struct deps_desc *deps, bool lazy_reg_last)
   deps->last_function_call = 0;
   deps->last_function_call_may_noreturn = 0;
   deps->sched_before_next_call = 0;
   deps->last_function_call = 0;
   deps->last_function_call_may_noreturn = 0;
   deps->sched_before_next_call = 0;
+  deps->sched_before_next_jump = 0;
   deps->in_post_call_group_p = not_post_call;
   deps->last_debug_insn = 0;
   deps->last_reg_pending_barrier = NOT_A_BARRIER;
   deps->in_post_call_group_p = not_post_call;
   deps->last_debug_insn = 0;
   deps->last_reg_pending_barrier = NOT_A_BARRIER;
index 1e5c71e..6797397 100644 (file)
@@ -496,6 +496,9 @@ struct deps_desc
      scheduling is done.  */
   rtx sched_before_next_call;
 
      scheduling is done.  */
   rtx sched_before_next_call;
 
+  /* Similarly, a list of insns which should not cross a branch.  */
+  rtx sched_before_next_jump;
+
   /* Used to keep post-call pseudo/hard reg movements together with
      the call.  */
   enum post_call_group in_post_call_group_p;
   /* Used to keep post-call pseudo/hard reg movements together with
      the call.  */
   enum post_call_group in_post_call_group_p;
diff --git a/gcc/testsuite/gcc.dg/pr49994-1.c b/gcc/testsuite/gcc.dg/pr49994-1.c
new file mode 100644 (file)
index 0000000..9024661
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-Os -fsched2-use-superblocks -g" } */
+
+void x (int a)
+{
+  __label__ xlab;
+  void y (int b)
+  {
+    switch (b)
+      {
+      case 1:
+       goto xlab;
+      case 2:
+       goto xlab;
+      }
+  }
+  y (a);
+xlab:;
+}
diff --git a/gcc/testsuite/gcc.dg/pr49994-2.c b/gcc/testsuite/gcc.dg/pr49994-2.c
new file mode 100644 (file)
index 0000000..92764fe
--- /dev/null
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fno-omit-frame-pointer -fschedule-insns2 -fsched2-use-superblocks -g" } */
+
+int
+bar (int i)
+{
+  while (i)
+    if (i)
+      return i;
+}
+
+void
+foo ()
+{
+  bar (0);
+}
diff --git a/gcc/testsuite/gcc.dg/pr49994-3.c b/gcc/testsuite/gcc.dg/pr49994-3.c
new file mode 100644 (file)
index 0000000..874db96
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fsched2-use-superblocks -g" } */
+
+void *
+foo (int offset)
+{
+  switch (offset)
+    {
+    case 0:
+      return __builtin_return_address (0);
+    case 1:
+      return __builtin_return_address (1);
+    case 2:
+      return __builtin_return_address (2);
+    case 3:
+      return __builtin_return_address (3);
+    case 4:
+      return __builtin_return_address (4);
+    }
+  return 0;
+}