https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86979

--- Comment #13 from Andrey Belevantsev <abel at gcc dot gnu.org> ---
So now I understand, finally. We move up an sp decrement and are supposed to
check that sp is available on the paths that are not touched by the move. There
are several successors of the move target block so the checking code is special
(and was the same there since day 1 of sel-sched).  The code checks, for each
successor block, the expressions that are present in the merged availability
set at the end of target block but are not present in the successor block set. 
Such expressions are marked as having unavailable target registers.

In this case for one successor block there happens to be another fence, and
that fence set has the copy of the sp decrement instruction. So it is not
detected as being unavailable. What _should_ have happened is that the
successor block with another fence should have been marked as ineligible
successor (we don't move along that path), so the av set against which we're
checking has to be NULL.  The fix is just to have that properly accounted for.

The patch is below, and I wouldn't be surprised if it fixes more PRs than this
one.

diff --git a/gcc/sel-sched.c b/gcc/sel-sched.c
index 315f2c0c0ab..2053694b196 100644
--- a/gcc/sel-sched.c
+++ b/gcc/sel-sched.c
@@ -2820,10 +2820,12 @@ compute_av_set_at_bb_end (insn_t insn, ilist_t p, int
ws)
     FOR_EACH_VEC_ELT (sinfo->succs_ok, is, succ)
       {
         basic_block succ_bb = BLOCK_FOR_INSN (succ);
+       av_set_t av_succ = (is_ineligible_successor (succ, p)
+                           ? NULL
+                           : BB_AV_SET (succ_bb));

         gcc_assert (BB_LV_SET_VALID_P (succ_bb));
-        mark_unavailable_targets (av1, BB_AV_SET (succ_bb),
-                                  BB_LV_SET (succ_bb));
+        mark_unavailable_targets (av1, av_succ, BB_LV_SET (succ_bb));
       }

   /* Finally, check liveness restrictions on paths leaving the region.  */

Reply via email to