This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug target/24232] [4.1 Regression] ICE: segmentation fault in sched-ebb.c:220 add_missing_bbs



------- Comment #11 from wilson at gcc dot gnu dot org  2005-10-12 02:52 -------
My earlier guess was correct.  It is a problem with the
sched_insn_condition_mutex_p code.  Also, there is the problem that the code
for handling serialization points for dependencies is confused.

sched-deps creates dependencies for a jump_insn by making it a serialization
point.  It is added to last_pending_memory_flush.  This insn will depend on all
previous instructions that use memory, and the previous memory flush insn.  All
following instructions that use memory will depend on this insn.  This
effectively serializes insn dependencies at this point.

The code that fails looks like this
   (jump_insn ... (eq p6 0) ...)
   (note ... NOTE_INSN_LOOP_BEG)
   (cond_exec (eq p8 0) ...)
   (jump_insn ... (ne p8 0) ...)

The first jump_insn goes in last_pending_memory_flush because it is a
serialization point for dependencies.

An instruction immediately after a LOOP_BEG note is treated as a serialization
point, so we can preserve reg_n_refs info.  So we create a dependency from the
cond_exec to the jump_insn, remove the jump_insn from
last_pending_memory_flush, and then put the cond_exec in
last_pending_memory_flush.

The second jump is another another serialization point, but it is mutex on the
cond_exec insn, so we don't create any dependencies.  And now we have a
problem, because the the second jump insn has no dependencies, there is nothing
to prevent it from being scheduled before the first jump insn.  This would
result in bad code, but fortunately (so to speak) we ICE before we finish
because this corrupts the basic block info.

So there are two problems here.

The first problem is that we aren't handling serialization points correctly. 
We must always create a dependency for a serialization point, even if the two
instructions are mutex.  Otherwise, it will not function correctly as a
serialization point.  Thus there must be a dependency between the second jump
insn and the cond_exec.

The second problem is that the current code tries to create a list of
serialization points, which makes no sense.  Since all instructions before the
last serialization point depend on the last serialization point, there is no
point in keeping track of more than one of them.  Only the last one is useful. 
However, the code is trying to maintain a list of branch instructions as our
serialization points.  This can not work.  While it does make some sense to
keep a list of branch insns for the purposes of handling dependencies, it does
not make sense to also make them serialization points.  The code is trying to
use last_pending_memory_flush for too different incompatible purposes.

I've got a patch that fixes this, though I am not entirely happy with it.  I
added a "uncond" argument to add_dependence_list so I can force dependencies to
be emitted for last_pending_memory_flush.  I also removed the code that was
handling last_pending_memory_flush as if it was a list.  It is not possible for
this to be a list and still work correctly as a serialization point.  In
theory, this makes the field pending_flush_length obsolete.  Unfortunately,
sched-rgn.c is using it in a strange way I don't understand.  It is trying to
concatenate lists of last_pending_memory_flush, but we can never have more than
one from sched-deps.c's point of view.  I left it alone.  Maybe this does work
if you call sched-dep separately for individual basic blocks.  Another downside
to my patch is that it creates more serialization points than is necessary or
ideal, but this can't be fixed without more work.

Ideally, the code for handling jump_insns should be a separate list from
last_pending_memory_flush.  Just like we have a list of pending reads and a
list for pending writes, we can have a list for pending jump_insns.  And then
when we need a serialization point for real, because the lists got too big or
whatever, then we use last_pending_memory_flush, and there is only ever one
entry in last_pending_memory_flush.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=24232


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]