This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch][df] RFC: Separate DF_REF flags for REG_EQUAL and REG_EQUIV notes


Hi,

My new cprop pass bombed on the first bootstrap I tried when it
replaced a reference in a REG_EQUIV note.  This happened because I
have replaced gcse.c:find_used_regs() with a walk-and-sort of the
DF_INSN_USES and DF_INSN_EQ_USES.  Fine, as long as you don't replace
anything in a REG_EQUIV note.

Unfortunately, you can't tell from a DF_REF in the DF_INSN_EQ_USES
whether it was in a REG_EQUAL or a REG_EQUIV note.

It turns out fwprop also has trouble with this.  It will prefer a use
in a REG_EQUIV note over the SET_SRC of a single_set insn.  I can't
think of a test case to make this fail, but it seems to me we never
want to propagate into a REG_EQUIV note.

The attached patch therefore splits DF_REF_IN_NOTE into separate flags
for the REG_EQUAL and REG_EQUIV case.

Does this look reasonable (for GCC 4.4 after testing etc.)?

Gr.
Steven
	* df.h (DF_REF_IN_NOTE): Replace with DF_REF_IN_EQUAL_NOTE and
	DF_REF_IN_EQUIV_NOTE.  Update all other flags.  Make DF_REF_IN_NOTE
	a define.
	* df-scan.c (df_notes_rescan): Split the REG_EQUAL and REG_EQUIV
	cases.  Add the appropriate DF_REF_IN_ flag.
	(df_insn_refs_collect): Likewise.
	* fwprop.c (try_fwprop_subst): Call update_df with the proper
	DF_REF_IN_ flag (always DF_REF_IN_EQUAL_NOTE).
	(forward_propagate_and_simplify): Only pick up note values from
	REG_EQUAL notes.  Use DF_REF_IN_EQUAL_NOTE to detect this, avoid
	calling dinf_reg_note.  Simplify.
	(forward_propagate_into): Only pick up a pattern from REG_EQUAL notes,
	ignore REG_EQUIV notes.
	* ddg.c (add_cross_iteration_register_deps): Update comment.

Index: fwprop.c
===================================================================
*** fwprop.c	(revision 130602)
--- fwprop.c	(working copy)
*************** try_fwprop_subst (struct df_ref *use, rt
*** 743,751 ****
            if (!CONSTANT_P (new))
  	    {
  	      update_df (insn, loc, DF_INSN_USES (def_insn),
! 			 type, DF_REF_IN_NOTE);
  	      update_df (insn, loc, DF_INSN_EQ_USES (def_insn),
! 			 type, DF_REF_IN_NOTE);
  	    }
  	}
      }
--- 743,751 ----
            if (!CONSTANT_P (new))
  	    {
  	      update_df (insn, loc, DF_INSN_USES (def_insn),
! 			 type, DF_REF_IN_EQUAL_NOTE);
  	      update_df (insn, loc, DF_INSN_EQ_USES (def_insn),
! 			 type, DF_REF_IN_EQUAL_NOTE);
  	    }
  	}
      }
*************** forward_propagate_and_simplify (struct d
*** 854,872 ****
        loc = &SET_DEST (use_set);
        set_reg_equal = false;
      }
!   else
      {
!       rtx note = find_reg_note (use_insn, REG_EQUAL, NULL_RTX);
!       if (DF_REF_FLAGS (use) & DF_REF_IN_NOTE)
! 	loc = &XEXP (note, 0);
!       else
! 	loc = &SET_SRC (use_set);
! 
        /* Do not replace an existing REG_EQUAL note if the insn is not
  	 recognized.  Either we're already replacing in the note, or
  	 we'll separately try plugging the definition in the note and
  	 simplifying.  */
!       set_reg_equal = (note == NULL_RTX);
      }
  
    if (GET_MODE (*loc) == VOIDmode)
--- 854,872 ----
        loc = &SET_DEST (use_set);
        set_reg_equal = false;
      }
!   else if (DF_REF_FLAGS (use) & DF_REF_IN_EQUAL_NOTE)
      {
!       loc = &XEXP (note, 0);
        /* Do not replace an existing REG_EQUAL note if the insn is not
  	 recognized.  Either we're already replacing in the note, or
  	 we'll separately try plugging the definition in the note and
  	 simplifying.  */
!       set_reg_equal = false;
!     }
!   else
!     {
!       loc = &SET_SRC (use_set);
!       set_reg_equal true;
      }
  
    if (GET_MODE (*loc) == VOIDmode)
*************** forward_propagate_into (struct df_ref *u
*** 916,922 ****
  
    /* Check if the use is still present in the insn!  */
    use_insn = DF_REF_INSN (use);
!   if (DF_REF_FLAGS (use) & DF_REF_IN_NOTE)
      parent = find_reg_note (use_insn, REG_EQUAL, NULL_RTX);
    else
      parent = PATTERN (use_insn);
--- 916,922 ----
  
    /* Check if the use is still present in the insn!  */
    use_insn = DF_REF_INSN (use);
!   if (DF_REF_FLAGS (use) & DF_REF_IN_EQUAL_NOTE)
      parent = find_reg_note (use_insn, REG_EQUAL, NULL_RTX);
    else
      parent = PATTERN (use_insn);
Index: ddg.c
===================================================================
*** ddg.c	(revision 130602)
--- ddg.c	(working copy)
*************** add_cross_iteration_register_deps (ddg_p
*** 268,274 ****
        if (BLOCK_FOR_INSN (use_insn) != g->bb)
  	continue;
  
!       /* ??? Do not handle uses with DF_REF_IN_NOTE notes.  */
        use_node = get_node_of_insn (g, use_insn);
        gcc_assert (use_node);
        has_use_in_bb_p = true;
--- 268,274 ----
        if (BLOCK_FOR_INSN (use_insn) != g->bb)
  	continue;
  
!       /* ??? Do not handle uses with appear in REG_{EQUAL,EQUIV} notes.  */
        use_node = get_node_of_insn (g, use_insn);
        gcc_assert (use_node);
        has_use_in_bb_p = true;
Index: df-scan.c
===================================================================
*** df-scan.c	(revision 130602)
--- df-scan.c	(working copy)
*************** df_notes_rescan (rtx insn)
*** 2058,2067 ****
  	  switch (REG_NOTE_KIND (note))
  	    {
  	    case REG_EQUIV:
  	    case REG_EQUAL:
  	      df_uses_record (&collection_rec,
  			      &XEXP (note, 0), DF_REF_REG_USE,
! 			      bb, insn, DF_REF_IN_NOTE);
  	    default:
  	      break;
  	    }
--- 2058,2074 ----
  	  switch (REG_NOTE_KIND (note))
  	    {
  	    case REG_EQUIV:
+ 	      df_uses_record (&collection_rec,
+ 			      &XEXP (note, 0), DF_REF_REG_USE,
+ 			      bb, insn, DF_REF_IN_EQUIV_NOTE);
+ 	      break;
+ 
  	    case REG_EQUAL:
  	      df_uses_record (&collection_rec,
  			      &XEXP (note, 0), DF_REF_REG_USE,
! 			      bb, insn, DF_REF_IN_EQUAL_NOTE);
! 	      break;
! 
  	    default:
  	      break;
  	    }
*************** df_insn_refs_collect (struct df_collecti
*** 3161,3170 ****
        switch (REG_NOTE_KIND (note))
          {
          case REG_EQUIV:
          case REG_EQUAL:
            df_uses_record (collection_rec,
                            &XEXP (note, 0), DF_REF_REG_USE,
!                           bb, insn, DF_REF_IN_NOTE);
            break;
          case REG_NON_LOCAL_GOTO:
            /* The frame ptr is used by a non-local goto.  */
--- 3168,3181 ----
        switch (REG_NOTE_KIND (note))
          {
          case REG_EQUIV:
+           df_uses_record (collection_rec,
+                           &XEXP (note, 0), DF_REF_REG_USE,
+                           bb, insn, DF_REF_IN_EQUIV_NOTE);
+           break;
          case REG_EQUAL:
            df_uses_record (collection_rec,
                            &XEXP (note, 0), DF_REF_REG_USE,
!                           bb, insn, DF_REF_IN_EQUAL_NOTE);
            break;
          case REG_NON_LOCAL_GOTO:
            /* The frame ptr is used by a non-local goto.  */
Index: df.h
===================================================================
*** df.h	(revision 130602)
--- df.h	(working copy)
*************** enum df_ref_flags
*** 78,107 ****
         bottom of the block.  This is never set for regular refs.  */
      DF_REF_AT_TOP = 1 << 1,
  
!     /* This flag is set if the use is inside a REG_EQUAL or REG_EQUIV
!        note.  */
!     DF_REF_IN_NOTE = 1 << 2,
  
      /* This bit is true if this ref can make regs_ever_live true for
         this regno.  */
!     DF_HARD_REG_LIVE = 1 << 3,
! 
  
      /* This flag is set if this ref is a partial use or def of the
         associated register.  */
!     DF_REF_PARTIAL = 1 << 4,
      
      /* Read-modify-write refs generate both a use and a def and
         these are marked with this flag to show that they are not
         independent.  */
!     DF_REF_READ_WRITE = 1 << 5,
  
      /* This flag is set if this ref, generally a def, may clobber the
         referenced register.  This is generally only set for hard
         registers that cross a call site.  With better information
         about calls, some of these could be changed in the future to
         DF_REF_MUST_CLOBBER.  */
!     DF_REF_MAY_CLOBBER = 1 << 6,
  
      /* This flag is set if this ref, generally a def, is a real
         clobber. This is not currently set for registers live across a
--- 78,108 ----
         bottom of the block.  This is never set for regular refs.  */
      DF_REF_AT_TOP = 1 << 1,
  
!     /* This flag is set if the use is inside a REG_EQUAL note.  */
!     DF_REF_IN_EQUAL_NOTE = 1 << 2,
! 
!     /* This flag is set if the use is inside a REG_EQUIV note.  */
!     DF_REF_IN_EQUIV_NOTE = 1 << 3,
  
      /* This bit is true if this ref can make regs_ever_live true for
         this regno.  */
!     DF_HARD_REG_LIVE = 1 << 4,
  
      /* This flag is set if this ref is a partial use or def of the
         associated register.  */
!     DF_REF_PARTIAL = 1 << 5,
      
      /* Read-modify-write refs generate both a use and a def and
         these are marked with this flag to show that they are not
         independent.  */
!     DF_REF_READ_WRITE = 1 << 6,
  
      /* This flag is set if this ref, generally a def, may clobber the
         referenced register.  This is generally only set for hard
         registers that cross a call site.  With better information
         about calls, some of these could be changed in the future to
         DF_REF_MUST_CLOBBER.  */
!     DF_REF_MAY_CLOBBER = 1 << 7,
  
      /* This flag is set if this ref, generally a def, is a real
         clobber. This is not currently set for registers live across a
*************** enum df_ref_flags
*** 112,144 ****
         clobber is to a subreg.  So in order to tell if the clobber
         wipes out the entire register, it is necessary to also check
         the DF_REF_PARTIAL flag.  */
!     DF_REF_MUST_CLOBBER = 1 << 7,
  
  
      /* This flag is set if this ref is inside a pre/post modify.  */
!     DF_REF_PRE_POST_MODIFY = 1 << 8,
  
      /* This flag is set if the ref contains a ZERO_EXTRACT or SIGN_EXTRACT.  */
!     DF_REF_EXTRACT = 1 << 9,
  
      /* This flag is set if the ref contains a STRICT_LOWER_PART.  */
!     DF_REF_STRICT_LOWER_PART = 1 << 10,
  
      /* This flag is set if the ref contains a SUBREG.  */
!     DF_REF_SUBREG = 1 << 11,
  
  
      /* This bit is true if this ref is part of a multiword hardreg.  */
!     DF_REF_MW_HARDREG = 1 << 12,
  
      /* This flag is set if this ref is a usage of the stack pointer by
         a function call.  */
!     DF_REF_CALL_STACK_USAGE = 1 << 13,
  
      /* This flag is used for verification of existing refs. */
!     DF_REF_REG_MARKER = 1 << 14
    };
  
  /* The possible ordering of refs within the df_ref_info.  */
  enum df_ref_order
    {
--- 113,150 ----
         clobber is to a subreg.  So in order to tell if the clobber
         wipes out the entire register, it is necessary to also check
         the DF_REF_PARTIAL flag.  */
!     DF_REF_MUST_CLOBBER = 1 << 8,
  
  
      /* This flag is set if this ref is inside a pre/post modify.  */
!     DF_REF_PRE_POST_MODIFY = 1 << 9,
  
      /* This flag is set if the ref contains a ZERO_EXTRACT or SIGN_EXTRACT.  */
!     DF_REF_EXTRACT = 1 << 10,
  
      /* This flag is set if the ref contains a STRICT_LOWER_PART.  */
!     DF_REF_STRICT_LOWER_PART = 1 << 11,
  
      /* This flag is set if the ref contains a SUBREG.  */
!     DF_REF_SUBREG = 1 << 12,
  
  
      /* This bit is true if this ref is part of a multiword hardreg.  */
!     DF_REF_MW_HARDREG = 1 << 13,
  
      /* This flag is set if this ref is a usage of the stack pointer by
         a function call.  */
!     DF_REF_CALL_STACK_USAGE = 1 << 14,
  
      /* This flag is used for verification of existing refs. */
!     DF_REF_REG_MARKER = 1 << 15
    };
  
+ /* It is usually only interesting to know whether a DF_REF is in a note.
+    This define provides a short cut so that the two flags don't have to
+    be "or"-ed everywhere.  */
+ #define DF_REF_IN_NOTE (DF_REF_IN_EQUAL_NOTE | DF_REF_IN_RQUIV_NOTE)
+ 
  /* The possible ordering of refs within the df_ref_info.  */
  enum df_ref_order
    {

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]