Hi!

We don't want to move /f instructions across jumps in either direction,
sched_analyze_insn has code for that by adding the insn into
sched_before_next_jump list and by adding anti dependence against
pending_jump_insns.  That works fine, as long as we don't flush the
dependency lists, flush_pending_lists will flush them and just add the
insn that was flushed into last_pending_memory_flush.

For frame related insns, we are looking solely for deps->pending_jump_insns
and thus if we've flushed, we miss anti dependency against insn that has
anti dependencies against jumps.

The following patch fixes it by also adding an anti dependency against 
last_pending_memory_flush insn if any.

Bootstrapped on {x86_64,i686,powerpc64le,powerpc64}-linux and regtested
on the first 3, with powerpc64-linux regtest -m32/-m64 still pending,
ok for trunk if it passes even there?

I believe this matches what we do elsewhere, but just in case it would look
too costly (as it could add dependencies also in cases where there weren't
any pending jump insns, just insns using memory and too many dependencies
for them), there might be another option like have a flag in deps whether
in the bb/ebb we've ever added something into pending_jump_insns and
only do the newly added call if that bool is true.  Or tweak
flush_pending_lists, such that if deps->pending_jump_insns used to be
non-empty then add at the end the insn in question to
deps->pending_jump_insns in addition to deps->last_pending_memory_flush,
and tweak the:
          if (deps->pending_flush_length++ >= MAX_PENDING_LIST_LENGTH)
            flush_pending_lists (deps, insn, true, true);
          else
            deps->pending_jump_insns
              = alloc_INSN_LIST (insn, deps->pending_jump_insns);
so that it would for the case when calling flush_pending_lists also
do the else part if before the flush_pending_lists pending_jump_insns used
to be non-empty.

2018-01-30  Jakub Jelinek  <ja...@redhat.com>

        PR rtl-optimization/83986
        * sched-deps.c (sched_analyze_insn): For frame related insns, add anti
        dependence against last_pending_memory_flush in addition to
        pending_jump_insns.

        * gcc.dg/pr83986.c: New test.

--- gcc/sched-deps.c.jj 2018-01-27 07:27:51.723937094 +0100
+++ gcc/sched-deps.c    2018-01-30 13:09:16.891173722 +0100
@@ -2922,6 +2922,8 @@ sched_analyze_insn (struct deps_desc *de
        = alloc_INSN_LIST (insn, deps->sched_before_next_jump);
 
       /* Make sure epilogue insn is scheduled after preceding jumps.  */
+      add_dependence_list (insn, deps->last_pending_memory_flush, 1,
+                          REG_DEP_ANTI, true);
       add_dependence_list (insn, deps->pending_jump_insns, 1, REG_DEP_ANTI,
                           true);
     }
--- gcc/testsuite/gcc.dg/pr83986.c.jj   2018-01-30 13:34:13.254828800 +0100
+++ gcc/testsuite/gcc.dg/pr83986.c      2018-01-30 13:33:55.973832214 +0100
@@ -0,0 +1,14 @@
+/* PR rtl-optimization/83986 */
+/* { dg-do compile } */
+/* { dg-options "-g -O2 -fsched2-use-superblocks -funwind-tables --param 
max-pending-list-length=1" } */
+
+int v;
+
+int
+foo (int x)
+{
+  v &= !!v && !!x;
+  if (v != 0)
+    foo (0);
+  return 0;
+}

        Jakub

Reply via email to