OSDN Git Service

2005-05-26 Paolo Bonzini <bonzini@gnu.org>
authorbonzini <bonzini@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 26 May 2005 08:12:35 +0000 (08:12 +0000)
committerbonzini <bonzini@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 26 May 2005 08:12:35 +0000 (08:12 +0000)
* 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
gcc/df.c
gcc/df.h

index dbf8fc4..3c79b2a 100644 (file)
@@ -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
index ad7852c..339f2c9 100644 (file)
--- 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,
index 60f6030..4382081 100644 (file)
--- 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);