From 08c172429c5986e2e7798afd80ab000cc5b9dbd8 Mon Sep 17 00:00:00 2001 From: bonzini Date: Thu, 26 May 2005 08:12:35 +0000 Subject: [PATCH] 2005-05-26 Paolo Bonzini * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@100197 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 5 +++++ gcc/df.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 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 + + * 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 PR target/21716 diff --git a/gcc/df.c b/gcc/df.c index ad7852c..339f2c9 100644 --- a/gcc/df.c +++ b/gcc/df.c @@ -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, diff --git a/gcc/df.h b/gcc/df.h index 60f6030..4382081 100644 --- a/gcc/df.h +++ b/gcc/df.h @@ -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); -- 2.7.4