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