This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[dataflow RFA] Remove DF_SUBREGS scanning flag
- From: Paolo Bonzini <paolo dot bonzini at lu dot unisi dot ch>
- To: Kenneth Zadeck <zadeck at naturalbridge dot com>, Zdenek Dvorak <rakdver at atrey dot karlin dot mff dot cuni dot cz>, GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Fri, 20 Oct 2006 10:20:39 +0200
- Subject: [dataflow RFA] Remove DF_SUBREGS scanning flag
As mentioned in Kenny's other e-mail, this patch removes the DF_SUBREGS
scanning flag. The flag allows the caller to see all subregs; by
default df would only show word-extraction subregs and strip all the
others. After this patch, all subregs are visible.
The DF_SUBREGS flag only affects the way the ->reg and ->loc fields are
filled, so it is useless on passes that don't look at these fields.
These are the schedulers (and ddg.c) and sign-extension elimination.
Such passes used to specify DF_SUBREGS, Kenny just removed it because
there was no behavioral change. This patch reverts their dataflow info
to what it was before Kenny's patch, but again without behavioral changes.
fwprop needed DF_SUBREGS, now it achieves the goal without passing it.
Nothing spectacular here, either.
The more interesting ones are loop optimizations, and the dataflow
scanning itself. In fact all the passes were more or less ready to
handle subregs because *some* subregs were already returned by df, as I
said. Therefore, the changes are rather simple there.
web is already distinguishing DF_REF_REG and DF_REF_REAL_REG, so it
accepts the new subregs correctly.
For dataflow, I actually found a couple of places where DF_REF_REAL_LOC
was "inlined" in the code. In one case, I replaced DF_REF_LOC with
DF_REF_REAL_LOC.
In two other cases (when dealing with REG_DEAD/REG_UNUSED notes for
multiword hard registers), DF_REF_LOC is used to create the
REG_DEAD/REG_UNUSED notes. I believe that in this case we will not see
a subreg, but on the other hand I don't see any harm if we see one. So
I left DF_REF_LOC there.
For loop optimizations, loop-invariant.c analyzes uses and just needs to
always see the REG and never the enclosing SUBREG. This is easily done
with DF_REF_REAL_LOC. It was already doing the same -- this patch is
just a cleanup for that case.
loop-iv.c dealt with subregs like this:
rtx reg = DF_REF_REG (def);
...
set = single_set (insn);
if (!set || SET_DEST (set) != reg)
return false;
This shows why the old behavior without DF_SUBREGS is pretty much
broken. We get the DEF (which is not artificial, it is taken from an
insn), and it may not be the SET_DEST of the insn! From my analysis,
this actually happened when the SET_DEST was a subreg, but I'm CCing
Zdenek in case this rings a bell. After this patch, we have this code
which is more clear:
rtx reg = DF_REF_REG (def);
...
if (!REG_P (reg))
return false;
set = single_set (insn);
if (!set)
return false;
gcc_assert (SET_DEST (set) == reg);
This simply rejects all subregs, and is able to perform a consistency
check on the dataflow info.
I will apply the patch sometime next week (I have to rebootstrap/retest
after Kenny's changes) if I don't hear from anybody, and will prepare a
backport to mainline when 4.3 opens. I'll bootstrap/test with web
enabled at -O2. Does it looks ok?
Paolo
2006-10-20 Paolo Bonzini <bonzinI@gnu.rg>
* ddg.c (add_deps_for_def, add_deps_for_use): Use accessor macros.
* df.h (DF_REF_STRIPPED, DF_SUBREGS): Remove.
* df-core.c: Don't document scanning flags.
* df-scan.c (df_ref_record): Always behave as if DF_SUBREGS was set.
* df-problems.c (df_lr_bb_local_compute): Strip SUBREGs with
DF_REF_REAL_REG.
(df_chain_start_dump): Don't dump DF_REF_STRIPPED.
(df_create_unused_note, df_ri_bb_compute): Don't "inline"
DF_REF_REAL_LOC.
* fwprop.c (fwprop_init): Do not pass DF_SUBREGS.
* loop-invariant.c (record_use): Don't strip SUBREGs.
(record_uses): Do it here with DF_REF_REAL_LOC.
* loop-iv.c (iv_analyze_def): Only allow REGs. Replace previous
way to check for SUBREGs with an assertion.
Index: fwprop.c
===================================================================
--- fwprop.c (revision 117899)
+++ fwprop.c (working copy)
@@ -919,7 +919,7 @@ fwprop_init (void)
/* Now set up the dataflow problem (we only want use-def chains) and
put the dataflow solver to work. */
- df = df_init (DF_SUBREGS + DF_UD_CHAIN, DF_EQ_NOTES);
+ df = df_init (DF_UD_CHAIN, DF_EQ_NOTES);
df_chain_add_problem (df);
df_analyze (df);
}
Index: ddg.c
===================================================================
--- ddg.c (revision 117899)
+++ ddg.c (working copy)
@@ -265,7 +265,7 @@ add_deps_for_def (ddg_ptr g, struct df *
/* Check if there are uses after RD. */
for (i = src_node->cuid + 1; i < g->num_nodes; i++)
- if (df_find_use (df, g->nodes[i].insn, rd->reg))
+ if (df_find_use (df, g->nodes[i].insn, DF_REF_REG (rd)))
return;
dest_node = get_node_of_insn (g, def->insn);
@@ -298,7 +298,7 @@ add_deps_for_use (ddg_ptr g, struct df *
/* Make sure there are no defs after USE. */
for (i = use_node->cuid + 1; i < g->num_nodes; i++)
- if (df_find_def (df, g->nodes[i].insn, use->reg))
+ if (df_find_def (df, g->nodes[i].insn, DF_REF_REG (use)))
return;
/* We must not add ANTI dep when there is an intra-loop TRUE dep in
the opposite direction. If the first_def reaches the USE then there is
Index: df-scan.c
===================================================================
--- df-scan.c (revision 117899)
+++ df-scan.c (working copy)
@@ -1156,22 +1156,6 @@ df_ref_record (struct dataflow *dflow, r
gcc_assert (REG_P (reg) || GET_CODE (reg) == SUBREG);
- /* For the reg allocator we are interested in some SUBREG rtx's, but not
- all. Notably only those representing a word extraction from a multi-word
- reg. As written in the docu those should have the form
- (subreg:SI (reg:M A) N), with size(SImode) > size(Mmode).
- XXX Is that true? We could also use the global word_mode variable. */
- if ((df->permanent_flags & DF_SUBREGS) == 0
- && GET_CODE (reg) == SUBREG
- && (GET_MODE_SIZE (GET_MODE (reg)) < GET_MODE_SIZE (word_mode)
- || GET_MODE_SIZE (GET_MODE (reg))
- >= GET_MODE_SIZE (GET_MODE (SUBREG_REG (reg)))))
- {
- loc = &SUBREG_REG (reg);
- reg = *loc;
- ref_flags |= DF_REF_STRIPPED;
- }
-
regno = REGNO (GET_CODE (reg) == SUBREG ? SUBREG_REG (reg) : reg);
if (regno < FIRST_PSEUDO_REGISTER)
{
Index: df-core.c
===================================================================
--- df-core.c (revision 117899)
+++ df-core.c (working copy)
@@ -63,11 +63,6 @@ DF_INIT simply creates a poor man's obje
passed to all the dataflow routines. df_finish destroys this object
and frees up any allocated memory.
-There are three flags that can be passed to df_init, each of these
-flags controls the scanning of the rtl:
-
-DF_SUBREGS return subregs rather than the inner reg.
-
DF_ADD_PROBLEM adds a problem, defined by an instance to struct
df_problem, to the set of problems solved in this instance of df. All
Index: df.h
===================================================================
--- df.h (revision 117899)
+++ df.h (working copy)
@@ -76,11 +76,6 @@ enum df_ref_flags
independent. */
DF_REF_READ_WRITE = 1,
- /* This flag is set, if we stripped the subreg from the reference.
- In this case we must make conservative guesses, at what the
- outer mode was. */
- DF_REF_STRIPPED = 2,
-
/* If this flag is set, this is not a real definition/use, but an
artificial one created to model always live registers, eh uses, etc. */
DF_REF_ARTIFICIAL = 4,
@@ -311,14 +306,12 @@ struct df_link
enum df_permanent_flags
{
- /* Scanning flags. */
- DF_SUBREGS = 1, /* Return subregs rather than the inner reg. */
/* Flags that control the building of chains. */
- DF_DU_CHAIN = 2, /* Build DU chains. */
- DF_UD_CHAIN = 4, /* Build UD chains. */
+ DF_DU_CHAIN = 1, /* Build DU chains. */
+ DF_UD_CHAIN = 2, /* Build UD chains. */
/* Flag to control the building of register info. */
- DF_RI_LIFE = 8, /* Build register info. */
- DF_RI_SETJMP = 16 /* Build pseudos that cross setjmp info. */
+ DF_RI_LIFE = 4, /* Build register info. */
+ DF_RI_SETJMP = 8 /* Build pseudos that cross setjmp info. */
};
enum df_changeable_flags
Index: loop-invariant.c
===================================================================
--- loop-invariant.c (revision 117899)
+++ loop-invariant.c (working copy)
@@ -673,8 +673,6 @@ record_use (struct def *def, rtx *use, r
{
struct use *u = XNEW (struct use);
- if (GET_CODE (*use) == SUBREG)
- use = &SUBREG_REG (*use);
gcc_assert (REG_P (*use));
u->pos = use;
@@ -834,7 +832,7 @@ record_uses (rtx insn)
{
inv = invariant_for_use (use);
if (inv)
- record_use (inv->def, DF_REF_LOC (use), DF_REF_INSN (use));
+ record_use (inv->def, DF_REF_REAL_LOC (use), DF_REF_INSN (use));
}
}
Index: loop-iv.c
===================================================================
--- loop-iv.c (revision 117899)
+++ loop-iv.c (working copy)
@@ -1043,10 +1043,14 @@ iv_analyze_def (struct df_ref *def, stru
iv->base = NULL_RTX;
iv->step = NULL_RTX;
+ if (!REG_P (reg))
+ return false;
+
set = single_set (insn);
- if (!set || SET_DEST (set) != reg)
+ if (!set)
return false;
+ gcc_assert (SET_DEST (set) == reg);
rhs = find_reg_equal_equiv_note (insn);
if (rhs)
rhs = XEXP (rhs, 0);
Index: df-problems.c
===================================================================
--- df-problems.c (revision 117899)
+++ df-problems.c (working copy)
@@ -1577,8 +1577,9 @@ df_lr_bb_local_compute (struct dataflow
&& dregno < FIRST_PSEUDO_REGISTER)
{
unsigned int i;
+ enum machine_mode mode = GET_MODE (DF_REF_REAL_REG (def));
unsigned int end = dregno
- + hard_regno_nregs[dregno][GET_MODE (DF_REF_REG (def))] - 1;
+ + hard_regno_nregs[dregno][mode] - 1;
for (i = dregno; i <= end; ++i)
regs_asm_clobbered[i] = 1;
}
@@ -3450,8 +3451,6 @@ df_chain_start_dump (struct dataflow *df
DF_REF_REGNO (use));
if (use->flags & DF_REF_READ_WRITE)
fprintf (file, "read/write ");
- if (use->flags & DF_REF_STRIPPED)
- fprintf (file, "stripped ");
if (use->flags & DF_REF_IN_NOTE)
fprintf (file, "note ");
df_chain_dump (DF_REF_CHAIN (use), file);
@@ -3845,8 +3844,7 @@ df_create_unused_note (basic_block bb, r
&& (!bitmap_bit_p (artificial_uses, dregno))
&& (!df_ignore_stack_reg (dregno)))
{
- rtx reg = GET_CODE (*DF_REF_LOC (def)) == SUBREG ?
- SUBREG_REG (*DF_REF_LOC (def)) : *DF_REF_LOC (def);
+ rtx reg = *DF_REF_REAL_LOC (def);
rtx note = alloc_EXPR_LIST (REG_UNUSED, reg, REG_NOTES (insn));
REG_NOTES (insn) = note;
#ifdef REG_DEAD_DEBUGGING
@@ -4053,8 +4051,7 @@ df_ri_bb_compute (struct dataflow *dflow
&& (!(DF_REF_FLAGS (use) & DF_REF_READ_WRITE))
&& (!df_ignore_stack_reg (uregno)))
{
- rtx reg = GET_CODE (*DF_REF_LOC (use)) == SUBREG ?
- SUBREG_REG (*DF_REF_LOC (use)) : *DF_REF_LOC (use);
+ rtx reg = *DF_REF_REAL_LOC (use);
rtx note = alloc_EXPR_LIST (REG_DEAD, reg, REG_NOTES (insn));
REG_NOTES (insn) = note;
if (df->permanent_flags & DF_RI_LIFE)