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

            Bug ID: 60651
           Summary: Mode switching instructions are sometimes emitted in
                    the wrong order
           Product: gcc
           Version: 4.9.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: rtl-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: amylaar at gcc dot gnu.org
            Target: epiphany-*-*

As dicussed at
http://forums.parallella.org/viewtopic.php?f=13&t=1053&sid=2d28ee29b5dd3c591d947074f46ac752&p=6654#p6654,
this code:

int a;
int c;

void __attribute__((interrupt))
misc_handler (void) {
   a*= c;
}

Is compiled into code that uses an uninitialized register.
As it turns out, the interrupt attribute is actually a red herring (as long as
you use the default of (-mfp-mode=caller).
The problem is that, after emitting the mask-loading instruction, mode
switching emits the mode switch to the caller's mode which uses that mask
*before* the load of the mask, thus using the register uninitialized.
The mask loading instruction, thus rendered useless, is later deleted.

The things with lcm is that we have an algorithm that can be a bit expensive,
but we can process multiple entities at almost no extra cost.
The epiphany needs to load constants to do its mode switching; these constants
can be anticipated further up in the dominance graph.  This can be modelled
as having a different entity for each mask needed, the need for which is
indicated at the same point as the mode switch itself.  Because the mask
load entities are not subject to transparency issues (except in the unfortunate
case of abnormal edges), lcm can move the loads up in suitable dominator
positions.
The modes priorities on the epiphany are also such that the mask loads have a
mode with the same or higher priority as the mask uses.
Also, the mask loads have lowered numbered entities than the mask uses.
As the lcm part of optimize_mode_switching inserts, for each priority, the
mode setting in ascending order of entities, and insert_insn_on_edge
appends to the currently registered sequence, this works find there.
The segment-based code also preserves entity order when inserting before an
instruction.
However, when inserting after a basic block head, later inserted mode
switch instructions end up prior to ones earlier inserted into the insn
stream.
To preserve the order, in the case of an initially empty basic block,
what we have to do is append the new instructions at the end of the basic
block.

Reply via email to