public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* Bad code generated by inter-block scheduling
@ 2004-09-22 18:52 Ulrich Weigand
  2004-09-22 21:36 ` Jeffrey A Law
  0 siblings, 1 reply; 5+ messages in thread
From: Ulrich Weigand @ 2004-09-22 18:52 UTC (permalink / raw)
  To: gcc

Hello,

current mainline miscompiles gcc.c-torture/execute/loop-14.c with -Os
due to what I believe to be a bug in inter-block scheduling in sched-rgn.c.

The test case is:

void f(int *a)
{
  int i;

  for (i=3; --i;)
    a[i] = 42 / i;
}

which gets transformed into (before scheduling):

basic block 0:
  reg51 = 3
  reg61 = 42
  reg66 = a + 12
  goto basic block 2

basic block 1:
  reg62 = reg61 divmod reg50       [*]
  mem(reg66) = subreg(reg62)
  fall through to basic block 2

basic block 2:
  reg50 = reg51 - 1
  reg51 = reg50
  reg66 = reg66 - 4
  if (reg50 != 0) goto basic block 1

Now, interblock scheduling goes and moves the divmod instruction [*]
into basic block 2.  This causes a division by zero to happen at
runtime.

While sched-rgn.c correctly detects that [*] is an insn that may
trap, it ignores this fact, because it considers this move to be
a regular interblock motion, *not* a speculative motion, i.e. it
thinks the divmod instruction would have been executed in any case
even before the move, so trapping doesn't matter.

The task of distiguishing between interblock and speculative motion
is done using the notion of 'potential-split-edges', as computed
by compute_dom_prob_ps in sched-rgn.c.  As I understand this code,
it looks for (generalized versions of) situations like this:

      [A]
     /   \
  [B]     [C]

If it finds such an edge A -> C, then a move from B to A would be
speculative, else it is a regular interblock motion.

Now, in this particular case, we obviously *do* have exactly that
situation, with [A] = bb2, [B] = bb 1, [C] = exit block.

However, the data structures available to compute_dom_prob_ps simply
do not contain the 'bb2 -> exit' edge in the first place!  This is
because where the private structures in sched-rgn.c are built
(build_control_flow), all edges leading to the exit block are 
completely ignored:

  nr_edges = 0;
  for (i = 0; i < num_edges; i++)
    {
      edge e = INDEX_EDGE (edge_list, i);

      if (e->dest != EXIT_BLOCK_PTR
          && e->src != ENTRY_BLOCK_PTR)
        new_edge (e->src->index, e->dest->index);
    }

From what I see from the revision histories, the behaviour apparently
has been the same since forever, so I don't know why this suddenly
shows up as a problem ...

Simply adding entry/exit edges to the sched-rgn.c tables is not completely
trivial due to the negative block index numbers; several global arrays in
sched-rgn.c are indexed by block number.  Any suggestions how to fix this?

Thanks,
Ulrich

-- 
  Dr. Ulrich Weigand
  weigand@informatik.uni-erlangen.de

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2004-09-24 15:29 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-09-22 18:52 Bad code generated by inter-block scheduling Ulrich Weigand
2004-09-22 21:36 ` Jeffrey A Law
2004-09-24  1:21   ` [PATCH] " Ulrich Weigand
2004-09-24  6:46     ` Jeffrey A Law
2004-09-24 18:16       ` Ulrich Weigand

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).