diff options
author | Paolo Bonzini <bonzini@gnu.org> | 2005-05-26 08:12:35 +0000 |
---|---|---|
committer | Paolo Bonzini <bonzini@gcc.gnu.org> | 2005-05-26 08:12:35 +0000 |
commit | 57a95bc48d07fcd237553acf979f2e340590ed48 (patch) | |
tree | de741b09a4c6275ce287d076d0076ab1b43d2a63 | |
parent | 383898f7654cd9e2db0586fa2ff18ec933a61a81 (diff) | |
download | gcc-57a95bc48d07fcd237553acf979f2e340590ed48.zip gcc-57a95bc48d07fcd237553acf979f2e340590ed48.tar.gz gcc-57a95bc48d07fcd237553acf979f2e340590ed48.tar.bz2 |
df.h (DF_SUBREGS, [...]): New.
2005-05-26 Paolo Bonzini <bonzini@gnu.org>
* df.h (DF_SUBREGS, df_local_def_available_p, df_insn_modified_p): New.
* df.c (DF_SUBREGS, df_local_def_available_p, df_insn_modified_p): New.
From-SVN: r100197
-rw-r--r-- | gcc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/df.c | 61 | ||||
-rw-r--r-- | gcc/df.h | 11 |
3 files changed, 71 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index dbf8fc4..3c79b2a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2005-05-26 Paolo Bonzini <bonzini@gnu.org> + + * df.h (DF_SUBREGS, df_local_def_available_p, df_insn_modified_p): New. + * df.c (DF_SUBREGS, df_local_def_available_p, df_insn_modified_p): New. + 2005-05-26 Jakub Jelinek <jakub@redhat.com> PR target/21716 @@ -820,7 +820,8 @@ df_ref_record (struct df *df, rtx reg, rtx *loc, rtx insn, 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 (GET_CODE (reg) == SUBREG + if ((df->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))))) @@ -2675,6 +2676,20 @@ df_insn_modify (struct df *df, basic_block bb, rtx insn) will just get ignored. */ } +/* Check if INSN was marked as changed. Of course the correctness of + the information depends on whether the instruction was really modified + at the time df_insn_modify was called. */ +bool +df_insn_modified_p (struct df *df, rtx insn) +{ + unsigned int uid; + + uid = INSN_UID (insn); + return (df->insns_modified + && uid < df->insn_size + && bitmap_bit_p (df->insns_modified, uid)); +} + typedef struct replace_args { rtx match; @@ -3237,6 +3252,48 @@ df_bb_regs_lives_compare (struct df *df, basic_block bb, rtx reg1, rtx reg2) } +/* Return true if the definition DEF, which is in the same basic + block as USE, is available at USE. So DEF may as well be + dead, in which case using it will extend its live range. */ +bool +df_local_def_available_p (struct df *df, struct ref *def, struct ref *use) +{ + struct df_link *link; + int def_luid = DF_INSN_LUID (df, DF_REF_INSN (def)); + int in_bb = 0; + unsigned int regno = REGNO (def->reg); + basic_block bb; + + /* The regs must be local to BB. */ + gcc_assert (DF_REF_BB (def) == DF_REF_BB (use)); + bb = DF_REF_BB (def); + + /* This assumes that the reg-def list is ordered such that for any + BB, the first def is found first. However, since the BBs are not + ordered, the first def in the chain is not necessarily the first + def in the function. */ + for (link = df->regs[regno].defs; link; link = link->next) + { + struct ref *this_def = link->ref; + if (DF_REF_BB (this_def) == bb) + { + int this_luid = DF_INSN_LUID (df, DF_REF_INSN (this_def)); + /* Do nothing with defs coming before DEF. */ + if (this_luid > def_luid) + return this_luid > DF_INSN_LUID (df, DF_REF_INSN (use)); + + in_bb = 1; + } + else if (in_bb) + /* DEF was the last in its basic block. */ + return 1; + } + + /* DEF was the last in the function. */ + return 1; +} + + /* Return last use of REGNO within BB. */ struct ref * df_bb_regno_last_use_find (struct df *df, basic_block bb, unsigned int regno) @@ -3304,7 +3361,7 @@ df_bb_regno_last_def_find (struct df *df, basic_block bb, unsigned int regno) return last_def; } -/* Return first use of REGNO inside INSN within BB. */ +/* Return last use of REGNO inside INSN within BB. */ static struct ref * df_bb_insn_regno_last_use_find (struct df *df, basic_block bb ATTRIBUTE_UNUSED, rtx insn, @@ -38,6 +38,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #define DF_ALL 255 #define DF_HARD_REGS 1024 /* Mark hard registers. */ #define DF_EQUIV_NOTES 2048 /* Mark uses present in EQUIV/EQUAL notes. */ +#define DF_SUBREGS 4096 /* Return subregs rather than the inner reg. */ enum df_ref_type {DF_REF_REG_DEF, DF_REF_REG_USE, DF_REF_REG_MEM_LOAD, DF_REF_REG_MEM_STORE}; @@ -207,11 +208,9 @@ struct df_map ((DF)->regs[REGNUM].uses ? (DF)->regs[REGNUM].uses->ref : 0) #define DF_REGNO_FIRST_BB(DF, REGNUM) \ -(DF_REGNO_FIRST_DEF (DF, REGNUM) \ -? DF_REF_BB (DF_REGNO_FIRST_DEF (DF, REGNUM)) : 0) +((DF)->regs[REGNUM].defs ? DF_REF_BB ((DF)->regs[REGNUM].defs->ref) : 0) #define DF_REGNO_LAST_BB(DF, REGNUM) \ -(DF_REGNO_LAST_USE (DF, REGNUM) \ -? DF_REF_BB (DF_REGNO_LAST_USE (DF, REGNUM)) : 0) +((DF)->regs[REGNUM].uses ? DF_REF_BB ((DF)->regs[REGNUM].uses->ref) : 0) /* Macros to access the elements within the insn_info structure table. */ @@ -235,6 +234,8 @@ extern void df_dump (struct df *, int, FILE *); /* Functions to modify insns. */ +extern bool df_insn_modified_p (struct df *, rtx); + extern void df_insn_modify (struct df *, basic_block, rtx); extern rtx df_insn_delete (struct df *, basic_block, rtx); @@ -280,6 +281,8 @@ extern int df_bb_reg_live_end_p (struct df *, basic_block, rtx); extern int df_bb_regs_lives_compare (struct df *, basic_block, rtx, rtx); +extern bool df_local_def_available_p (struct df *, struct ref *, struct ref *); + extern rtx df_bb_single_def_use_insn_find (struct df *, basic_block, rtx, rtx); extern struct ref *df_bb_regno_last_use_find (struct df *, basic_block, unsigned int); |