This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: Incorrect DFA scheduling of output dependency.
Daniel Towner wrote:
Vlad, et al.,
I was wrong here. The instruction sequence is actually a data
(read-after-write) dependency, not an output dependency
(write-after-write). However, the relevent portion of the scheduler
dump is as follows:
(note 82 147 64 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
(insn:TI 64 82 150 2 (set (reg/v:HI 4 R4 [orig:25 rdIndex ] [25])
(const_int 0 [0x0])) 15 {movhi} (nil)
(nil))
(note 150 64 133 2 NOTE_INSN_LOOP_END)
(insn 133 150 135 2 (set (reg:HI 5 R5 [33])
(ashift:HI (reg/v:HI 4 R4 [orig:25 rdIndex ] [25])
(const_int 2 [0x2]))) 48 {ashlhi3}
(insn_list:REG_DEP_ANTI 64 (nil))
(expr_list:REG_EQUAL (ashift:HI (reg/v:HI 4 R4 [orig:25 rdIndex ]
[25])
(const_int 2 [0x2]))
(nil)))
Does this state that insn 133 is anti-dependent on insn 64?
I've discovered that the anti-dependency is inserted by sched_analyze.
It occurs because of the NOTE_INSN_LOOP_END between the two
instructions above. This note introduces a move barrier between the
instructions, which is intended to prevent the two instructions being
reordered. Currently, this barrier is represented by making the second
instruction anti-dependent upon the first. For most processors, I
guess that such a dependency works as expected, but a VLIW machine is
able to emit such instructions in a single cycle, resulting in an
incorrect schedule. It feels like this should be a true dependency,
but the relevent code seems to make a distinction between a true
dependency (a TRUE_BARRIER) and a order dependency (a MOVE_BARRIER).
What sort of dependency should actually be inserted here?
Please try the following patch if it works for you, I could commit it
into the main line. It should solve the problem of generation of
incorrect schedule for VLIW. But the problem of generation of not
optimal schedule will still exist because the first insn after the
barrier behaves as one setting and using all registers.
Vlad
Vladimir Makarov <vmakarov@redhat.com>
* sched-deps.c (sched_analyze_insn): Use more accurate dependence
type for the first insn after MOVE_BARRIER.
Index: sched-deps.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/sched-deps.c,v
retrieving revision 1.65.2.1.2.1
diff -c -p -r1.65.2.1.2.1 sched-deps.c
*** sched-deps.c 20 May 2004 13:01:49 -0000 1.65.2.1.2.1
--- sched-deps.c 7 Dec 2004 22:09:08 -0000
*************** sched_analyze_insn (struct deps *deps, r
*** 965,977 ****
EXECUTE_IF_SET_IN_REG_SET (&deps->reg_last_in_use, 0, i,
{
struct deps_reg *reg_last = &deps->reg_last[i];
add_dependence_list (insn, reg_last->uses, REG_DEP_ANTI);
! add_dependence_list
! (insn, reg_last->sets,
! reg_pending_barrier == TRUE_BARRIER ? 0 : REG_DEP_ANTI);
! add_dependence_list
! (insn, reg_last->clobbers,
! reg_pending_barrier == TRUE_BARRIER ? 0 : REG_DEP_ANTI);
});
}
else
--- 965,980 ----
EXECUTE_IF_SET_IN_REG_SET (&deps->reg_last_in_use, 0, i,
{
struct deps_reg *reg_last = &deps->reg_last[i];
+ enum reg_note dep_type;
+
add_dependence_list (insn, reg_last->uses, REG_DEP_ANTI);
! dep_type = (reg_pending_barrier == TRUE_BARRIER
! ? 0 : REGNO_REG_SET_P (reg_pending_uses, i)
! ? 0 : (REGNO_REG_SET_P (reg_pending_set, i)
! || REGNO_REG_SET_P (reg_pending_clobber, i))
! ? REG_DEP_OUTPUT : REG_DEP_ANTI);
! add_dependence_list (insn, reg_last->sets, dep_type);
! add_dependence_list (insn, reg_last->clobbers, dep_type);
});
}
else
*************** sched_analyze_insn (struct deps *deps, r
*** 979,992 ****
EXECUTE_IF_SET_IN_REG_SET (&deps->reg_last_in_use, 0, i,
{
struct deps_reg *reg_last = &deps->reg_last[i];
add_dependence_list_and_free (insn, ®_last->uses,
REG_DEP_ANTI);
! add_dependence_list_and_free
! (insn, ®_last->sets,
! reg_pending_barrier == TRUE_BARRIER ? 0 : REG_DEP_ANTI);
! add_dependence_list_and_free
! (insn, ®_last->clobbers,
! reg_pending_barrier == TRUE_BARRIER ? 0 : REG_DEP_ANTI);
reg_last->uses_length = 0;
reg_last->clobbers_length = 0;
});
--- 982,999 ----
EXECUTE_IF_SET_IN_REG_SET (&deps->reg_last_in_use, 0, i,
{
struct deps_reg *reg_last = &deps->reg_last[i];
+ enum reg_note dep_type;
+
add_dependence_list_and_free (insn, ®_last->uses,
REG_DEP_ANTI);
! dep_type = (reg_pending_barrier == TRUE_BARRIER
! ? 0 : REGNO_REG_SET_P (reg_pending_uses, i)
! ? 0 : (REGNO_REG_SET_P (reg_pending_set, i)
! || REGNO_REG_SET_P (reg_pending_clobber, i))
! ? REG_DEP_OUTPUT : REG_DEP_ANTI);
! add_dependence_list_and_free (insn, ®_last->sets, dep_type);
! add_dependence_list_and_free (insn, ®_last->clobbers,
! dep_type),
reg_last->uses_length = 0;
reg_last->clobbers_length = 0;
});