Hi,
While teaching dce.c on the dataflow-branch to delete noop-moves,
I noticed that most noop moves are produced by reload. It inserts
duplicate insns for some reloads, postreload turns the duplicate
reload into a simple reg-reg move (but the lhs and rhs are the same
register of course), and then dce.c removes these moves because
they are noop-moves.
Example:
Before reload we just have some variable, ivtmp.46, in a pseudo:
(insn 45 43 47 6 (set (reg:SI 62 [ D.1617 ])
(reg:SI 63 [ ivtmp.46 ])) 40 {*movsi_1} (nil)
(nil))
After reload we have this:
(insn 45 43 102 6 (set (reg:SI 4 si [orig:62 D.1617 ] [62])
(mem/c:SI (plus:SI (reg/f:SI 6 bp)
(const_int -16 [0xfffffffffffffff0])) [0 ivtmp.46+0 S4 A8])) 40
{*movsi_1} (nil)
(nil))
(insn 102 45 47 6 (set (reg:SI 4 si [orig:62 D.1617 ] [62])
(mem/c:SI (plus:SI (reg/f:SI 6 bp)
(const_int -16 [0xfffffffffffffff0])) [0 ivtmp.46+0 S4 A8])) 40
{*movsi_1} (nil)
(nil))
Note, that these insns are identical.
After postreload it looks like this:
(insn 45 43 102 6 (set (reg:SI 4 si [orig:62 D.1617 ] [62])
(mem/c:SI (plus:SI (reg/f:SI 6 bp)
(const_int -16 [0xfffffffffffffff0])) [0 ivtmp.46+0 S4 A8])) 40
{*movsi_1} (nil)
(nil))
(insn 102 45 47 6 (set (reg:SI 4 si [orig:62 D.1617 ] [62])
(reg:SI 4 si [orig:62 D.1617 ] [62])) 40 {*movsi_1} (nil)
(nil))
Then on the dataflow-branch, dce removes insn 102. On mainline,
flow2 takes care of that.
Test case for ix86 is this:
/* This is reduced from count_reg_usage in cse.c.
Compile with gcc -S -march=i686 -m32 -O -fno-tree-ch t.c -da
and look at the .greg and .postreload RTL dumps.
With "gcc (GCC) 4.2.0 20060225 (experimental)", look for insn 45
and insn 102. */
typedef struct rtvec_def
{
unsigned num_elem;
struct rtx_def *elem[1];
} *rtvec;
typedef struct rtx_def
{
struct rtvec_def *rtvec[1];
} *rtx;
extern int rtx_length[];
void
foo (rtx x, const char c, int code)
{
int i, j;
for (i = (rtx_length[code]) - 1; i >= 0; i--)
{
if (c == 'e')
asm volatile ("":::"0", "1", "2", "3", "4", "5");
else if (c == 'E')
for (j = x->rtvec[i]->num_elem - 1; j >= 0; j--)
foo (x->rtvec[i]->elem[j], c, code);
}
}
I don't understand reload at all. Could someone help me figure out why
we have two identical insns there? We produce hundreds of basically
dead insns like this, and we need post-reload passes to clean them up.
So if we can avoid emitting the second, redundant insn, that'd be a win.
Gr.
Steven