This is the mail archive of the gcc@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]

More on addressof: how to fix the backends that use them?


Hi,

Before we can even consider removing addresof, there still
are two backends that build ADDRESSOF rtxes: alpha and ia64.

For example, alpha.c uses it as follows:

/* Return or create a pseudo containing the gp value for the current
   function.  Needed only if TARGET_LD_BUGGY_LDGP.  */

rtx
alpha_gp_save_rtx (void)
{
  rtx r = get_hard_reg_initial_val (DImode, 29);
  if (GET_CODE (r) != MEM)
    r = gen_mem_addressof (r, NULL_TREE, /*rescan=*/true);
  return r;
}

What can this code be replaced with such that it does not
create an ADDRESSOF?

I've attached an updated version of Honza's patch from some time
ago (http://gcc.gnu.org/ml/gcc-patches/2004-02/msg01417.html) for
those who are interested.

Gr.
Steven

Index: function.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/function.c,v
retrieving revision 1.518
diff -c -3 -p -r1.518 function.c
*** function.c	20 May 2004 17:37:02 -0000	1.518
--- function.c	1 Jun 2004 21:28:11 -0000
*************** static int contains (rtx, varray_type);
*** 264,280 ****
  #ifdef HAVE_return
  static void emit_return_into_block (basic_block, rtx);
  #endif
- static void put_addressof_into_stack (rtx, htab_t);
- static bool purge_addressof_1 (rtx *, rtx, int, int, int, htab_t);
- static void purge_single_hard_subreg_set (rtx);
  #if defined(HAVE_epilogue) && defined(INCOMING_RETURN_ADDR_RTX)
  static rtx keep_stack_depressed (rtx);
  #endif
- static int is_addressof (rtx *, void *);
- static hashval_t insns_for_mem_hash (const void *);
- static int insns_for_mem_comp (const void *, const void *);
- static int insns_for_mem_walk (rtx *, void *);
- static void compute_insns_for_mem (rtx, rtx, htab_t);
  static void prepare_function_start (tree);
  static void do_clobber_return_reg (rtx, void *);
  static void do_use_return_reg (rtx, void *);
--- 264,272 ----
*************** static void set_insn_locators (rtx, int)
*** 285,293 ****
  /* Pointer to chain of `struct function' for containing functions.  */
  struct function *outer_function_chain;
  
- /* List of insns that were postponed by purge_addressof_1.  */
- static rtx postponed_insns;
- 
  /* Given a function decl for a containing function,
     return the `struct function' for it.  */
  
--- 277,282 ----
*************** put_var_into_stack (tree decl, int resca
*** 1368,1374 ****
    enum machine_mode promoted_mode, decl_mode;
    struct function *function = 0;
    tree context;
-   bool can_use_addressof_p;
    bool volatile_p = TREE_CODE (decl) != SAVE_EXPR && TREE_THIS_VOLATILE (decl);
    bool used_p = (TREE_USED (decl)
  	       || (TREE_CODE (decl) != SAVE_EXPR && DECL_INITIAL (decl) != 0));
--- 1357,1362 ----
*************** put_var_into_stack (tree decl, int resca
*** 1414,1455 ****
        decl_mode = promoted_mode = GET_MODE (reg);
      }
  
-   /* If this variable lives in the current function and we don't need to put it
-      in the stack for the sake of setjmp or the non-locality, try to keep it in
-      a register until we know we actually need the address.  */
-   can_use_addressof_p
-     = (function == 0
-        && ! (TREE_CODE (decl) != SAVE_EXPR && DECL_NONLOCAL (decl))
-        && optimize > 0
-        /* FIXME make it work for promoted modes too */
-        && decl_mode == promoted_mode
- #ifdef NON_SAVING_SETJMP
-        && ! (NON_SAVING_SETJMP && current_function_calls_setjmp)
- #endif
-        );
- 
-   /* If we can't use ADDRESSOF, make sure we see through one we already
-      generated.  */
-   if (! can_use_addressof_p
-       && GET_CODE (reg) == MEM
-       && GET_CODE (XEXP (reg, 0)) == ADDRESSOF)
-     reg = XEXP (XEXP (reg, 0), 0);
- 
    /* Now we should have a value that resides in one or more pseudo regs.  */
  
    if (GET_CODE (reg) == REG)
      {
!       if (can_use_addressof_p)
! 	gen_mem_addressof (reg, decl, rescan);
!       else
! 	put_reg_into_stack (function, reg, TREE_TYPE (decl), decl_mode,
! 			    0, volatile_p, used_p, false, 0);
! 
! 	  /* If this was previously a MEM but we've removed the ADDRESSOF,
! 	     set this address into that MEM so we always use the same
! 	     rtx for this variable.  */
! 	  if (orig_reg != reg && GET_CODE (orig_reg) == MEM)
! 	    XEXP (orig_reg, 0) = XEXP (reg, 0);
      }
    else if (GET_CODE (reg) == CONCAT)
      {
--- 1402,1413 ----
        decl_mode = promoted_mode = GET_MODE (reg);
      }
  
    /* Now we should have a value that resides in one or more pseudo regs.  */
  
    if (GET_CODE (reg) == REG)
      {
!       put_reg_into_stack (function, reg, TREE_TYPE (decl), decl_mode,
! 			  0, volatile_p, used_p, false, 0);
      }
    else if (GET_CODE (reg) == CONCAT)
      {
*************** static int cfa_offset;
*** 2916,3557 ****
  #define ARG_POINTER_CFA_OFFSET(FNDECL) FIRST_PARM_OFFSET (FNDECL)
  #endif
  
- /* Build up a (MEM (ADDRESSOF (REG))) rtx for a register REG that just
-    had its address taken.  DECL is the decl or SAVE_EXPR for the
-    object stored in the register, for later use if we do need to force
-    REG into the stack.  REG is overwritten by the MEM like in
-    put_reg_into_stack.  RESCAN is true if previously emitted
-    instructions must be rescanned and modified now that the REG has
-    been transformed.  */
- 
- rtx
- gen_mem_addressof (rtx reg, tree decl, int rescan)
- {
-   rtx r = gen_rtx_ADDRESSOF (Pmode, gen_reg_rtx (GET_MODE (reg)),
- 			     REGNO (reg), decl);
- 
-   /* Calculate this before we start messing with decl's RTL.  */
-   HOST_WIDE_INT set = decl ? get_alias_set (decl) : 0;
- 
-   /* If the original REG was a user-variable, then so is the REG whose
-      address is being taken.  Likewise for unchanging.  */
-   REG_USERVAR_P (XEXP (r, 0)) = REG_USERVAR_P (reg);
-   RTX_UNCHANGING_P (XEXP (r, 0)) = RTX_UNCHANGING_P (reg);
- 
-   PUT_CODE (reg, MEM);
-   MEM_VOLATILE_P (reg) = 0;
-   MEM_ATTRS (reg) = 0;
-   XEXP (reg, 0) = r;
- 
-   if (decl)
-     {
-       tree type = TREE_TYPE (decl);
-       enum machine_mode decl_mode
- 	= (DECL_P (decl) ? DECL_MODE (decl) : TYPE_MODE (TREE_TYPE (decl)));
-       rtx decl_rtl = (TREE_CODE (decl) == SAVE_EXPR ? SAVE_EXPR_RTL (decl)
- 		      : DECL_RTL_IF_SET (decl));
- 
-       PUT_MODE (reg, decl_mode);
- 
-       /* Clear DECL_RTL momentarily so functions below will work
- 	 properly, then set it again.  */
-       if (DECL_P (decl) && decl_rtl == reg)
- 	SET_DECL_RTL (decl, 0);
- 
-       set_mem_attributes (reg, decl, 1);
-       set_mem_alias_set (reg, set);
- 
-       if (DECL_P (decl) && decl_rtl == reg)
- 	SET_DECL_RTL (decl, reg);
- 
-       if (rescan
- 	  && (TREE_USED (decl) || (DECL_P (decl) && DECL_INITIAL (decl) != 0)))
- 	fixup_var_refs (reg, GET_MODE (reg), TYPE_UNSIGNED (type), reg, 0);
-     }
-   else if (rescan)
-     {
-       /* This can only happen during reload.  Clear the same flag bits as
- 	 reload.  */
-       RTX_UNCHANGING_P (reg) = 0;
-       MEM_IN_STRUCT_P (reg) = 0;
-       MEM_SCALAR_P (reg) = 0;
- 
-       fixup_var_refs (reg, GET_MODE (reg), 0, reg, 0);
-     }
- 
-   return reg;
- }
- 
- /* If DECL has an RTL that is an ADDRESSOF rtx, put it into the stack.  */
- 
- void
- flush_addressof (tree decl)
- {
-   if ((TREE_CODE (decl) == PARM_DECL || TREE_CODE (decl) == VAR_DECL)
-       && DECL_RTL (decl) != 0
-       && GET_CODE (DECL_RTL (decl)) == MEM
-       && GET_CODE (XEXP (DECL_RTL (decl), 0)) == ADDRESSOF
-       && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == REG)
-     put_addressof_into_stack (XEXP (DECL_RTL (decl), 0), 0);
- }
- 
- /* Force the register pointed to by R, an ADDRESSOF rtx, into the stack.  */
- 
- static void
- put_addressof_into_stack (rtx r, htab_t ht)
- {
-   tree decl, type;
-   bool volatile_p, used_p;
- 
-   rtx reg = XEXP (r, 0);
- 
-   if (GET_CODE (reg) != REG)
-     abort ();
- 
-   decl = ADDRESSOF_DECL (r);
-   if (decl)
-     {
-       type = TREE_TYPE (decl);
-       volatile_p = (TREE_CODE (decl) != SAVE_EXPR
- 		    && TREE_THIS_VOLATILE (decl));
-       used_p = (TREE_USED (decl)
- 		|| (DECL_P (decl) && DECL_INITIAL (decl) != 0));
-     }
-   else
-     {
-       type = NULL_TREE;
-       volatile_p = false;
-       used_p = true;
-     }
- 
-   put_reg_into_stack (0, reg, type, GET_MODE (reg), ADDRESSOF_REGNO (r),
- 		      volatile_p, used_p, false, ht);
- }
- 
- /* List of replacements made below in purge_addressof_1 when creating
-    bitfield insertions.  */
- static rtx purge_bitfield_addressof_replacements;
- 
- /* List of replacements made below in purge_addressof_1 for patterns
-    (MEM (ADDRESSOF (REG ...))).  The key of the list entry is the
-    corresponding (ADDRESSOF (REG ...)) and value is a substitution for
-    the all pattern.  List PURGE_BITFIELD_ADDRESSOF_REPLACEMENTS is not
-    enough in complex cases, e.g. when some field values can be
-    extracted by usage MEM with narrower mode.  */
- static rtx purge_addressof_replacements;
- 
- /* Helper function for purge_addressof.  See if the rtx expression at *LOC
-    in INSN needs to be changed.  If FORCE, always put any ADDRESSOFs into
-    the stack.  If the function returns FALSE then the replacement could not
-    be made.  If MAY_POSTPONE is true and we would not put the addressof
-    to stack, postpone processing of the insn.  */
- 
- static bool
- purge_addressof_1 (rtx *loc, rtx insn, int force, int store, int may_postpone,
- 		   htab_t ht)
- {
-   rtx x;
-   RTX_CODE code;
-   int i, j;
-   const char *fmt;
-   bool result = true;
-   bool libcall = false;
- 
-   /* Re-start here to avoid recursion in common cases.  */
-  restart:
- 
-   x = *loc;
-   if (x == 0)
-     return true;
- 
-   /* Is this a libcall?  */
-   if (!insn)
-     libcall = REG_NOTE_KIND (*loc) == REG_RETVAL;
- 
-   code = GET_CODE (x);
- 
-   /* If we don't return in any of the cases below, we will recurse inside
-      the RTX, which will normally result in any ADDRESSOF being forced into
-      memory.  */
-   if (code == SET)
-     {
-       result = purge_addressof_1 (&SET_DEST (x), insn, force, 1,
- 				  may_postpone, ht);
-       result &= purge_addressof_1 (&SET_SRC (x), insn, force, 0,
- 				   may_postpone, ht);
-       return result;
-     }
-   else if (code == ADDRESSOF)
-     {
-       rtx sub, insns;
- 
-       if (GET_CODE (XEXP (x, 0)) != MEM)
- 	put_addressof_into_stack (x, ht);
- 
-       /* We must create a copy of the rtx because it was created by
- 	 overwriting a REG rtx which is always shared.  */
-       sub = copy_rtx (XEXP (XEXP (x, 0), 0));
-       if (validate_change (insn, loc, sub, 0)
- 	  || validate_replace_rtx (x, sub, insn))
- 	return true;
- 
-       start_sequence ();
- 
-       /* If SUB is a hard or virtual register, try it as a pseudo-register.
- 	 Otherwise, perhaps SUB is an expression, so generate code to compute
- 	 it.  */
-       if (GET_CODE (sub) == REG && REGNO (sub) <= LAST_VIRTUAL_REGISTER)
- 	sub = copy_to_reg (sub);
-       else
- 	sub = force_operand (sub, NULL_RTX);
- 
-       if (! validate_change (insn, loc, sub, 0)
- 	  && ! validate_replace_rtx (x, sub, insn))
- 	abort ();
- 
-       insns = get_insns ();
-       end_sequence ();
-       emit_insn_before (insns, insn);
-       return true;
-     }
- 
-   else if (code == MEM && GET_CODE (XEXP (x, 0)) == ADDRESSOF && ! force)
-     {
-       rtx sub = XEXP (XEXP (x, 0), 0);
- 
-       if (GET_CODE (sub) == MEM)
- 	sub = adjust_address_nv (sub, GET_MODE (x), 0);
-       else if (GET_CODE (sub) == REG
- 	       && (MEM_VOLATILE_P (x) || GET_MODE (x) == BLKmode))
- 	;
-       else if (GET_CODE (sub) == REG && GET_MODE (x) != GET_MODE (sub))
- 	{
- 	  int size_x, size_sub;
- 
- 	  if (may_postpone)
- 	    {
- 	      /* Postpone for now, so that we do not emit bitfield arithmetics
- 		 unless there is some benefit from it.  */
- 	      if (!postponed_insns || XEXP (postponed_insns, 0) != insn)
- 		postponed_insns = alloc_INSN_LIST (insn, postponed_insns);
- 	      return true;
- 	    }
- 
- 	  if (!insn)
- 	    {
- 	      /* When processing REG_NOTES look at the list of
- 		 replacements done on the insn to find the register that X
- 		 was replaced by.  */
- 	      rtx tem;
- 
- 	      for (tem = purge_bitfield_addressof_replacements;
- 		   tem != NULL_RTX;
- 		   tem = XEXP (XEXP (tem, 1), 1))
- 		if (rtx_equal_p (x, XEXP (tem, 0)))
- 		  {
- 		    *loc = XEXP (XEXP (tem, 1), 0);
- 		    return true;
- 		  }
- 
- 	      /* See comment for purge_addressof_replacements.  */
- 	      for (tem = purge_addressof_replacements;
- 		   tem != NULL_RTX;
- 		   tem = XEXP (XEXP (tem, 1), 1))
- 		if (rtx_equal_p (XEXP (x, 0), XEXP (tem, 0)))
- 		  {
- 		    rtx z = XEXP (XEXP (tem, 1), 0);
- 
- 		    if (GET_MODE (x) == GET_MODE (z)
- 			|| (GET_CODE (XEXP (XEXP (tem, 1), 0)) != REG
- 			    && GET_CODE (XEXP (XEXP (tem, 1), 0)) != SUBREG))
- 		      abort ();
- 
- 		    /* It can happen that the note may speak of things
- 		       in a wider (or just different) mode than the
- 		       code did.  This is especially true of
- 		       REG_RETVAL.  */
- 
- 		    if (GET_CODE (z) == SUBREG && SUBREG_BYTE (z) == 0)
- 		      z = SUBREG_REG (z);
- 
- 		    if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD
- 			&& (GET_MODE_SIZE (GET_MODE (x))
- 			    > GET_MODE_SIZE (GET_MODE (z))))
- 		      {
- 			/* This can occur as a result in invalid
- 			   pointer casts, e.g. float f; ...
- 			   *(long long int *)&f.
- 			   ??? We could emit a warning here, but
- 			   without a line number that wouldn't be
- 			   very helpful.  */
- 			z = gen_rtx_SUBREG (GET_MODE (x), z, 0);
- 		      }
- 		    else
- 		      z = gen_lowpart (GET_MODE (x), z);
- 
- 		    *loc = z;
- 		    return true;
- 		  }
- 
- 	      /* When we are processing the REG_NOTES of the last instruction
- 		 of a libcall, there will be typically no replacements
- 		 for that insn; the replacements happened before, piecemeal
- 		 fashion.  OTOH we are not interested in the details of
- 		 this for the REG_EQUAL note, we want to know the big picture,
- 		 which can be succinctly described with a simple SUBREG.
- 		 Note that removing the REG_EQUAL note is not an option
- 		 on the last insn of a libcall, so we must do a replacement.  */
- 
- 	      /* In compile/990107-1.c:7 compiled at -O1 -m1 for sh-elf,
- 		 we got
- 		 (mem:DI (addressof:SI (reg/v:DF 160) 159 0x401c8510)
- 		 [0 S8 A32]), which can be expressed with a simple
- 		 same-size subreg  */
- 	      if ((GET_MODE_SIZE (GET_MODE (x))
- 		   <= GET_MODE_SIZE (GET_MODE (sub)))
- 		  /* Again, invalid pointer casts (as in
- 		     compile/990203-1.c) can require paradoxical
- 		     subregs.  */
- 		  || (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD
- 		      && (GET_MODE_SIZE (GET_MODE (x))
- 			  > GET_MODE_SIZE (GET_MODE (sub)))
- 		      && libcall))
- 		{
- 		  *loc = gen_rtx_SUBREG (GET_MODE (x), sub, 0);
- 		  return true;
- 		}
- 	      /* ??? Are there other cases we should handle?  */
- 
- 	      /* Sometimes we may not be able to find the replacement.  For
- 		 example when the original insn was a MEM in a wider mode,
- 		 and the note is part of a sign extension of a narrowed
- 		 version of that MEM.  Gcc testcase compile/990829-1.c can
- 		 generate an example of this situation.  Rather than complain
- 		 we return false, which will prompt our caller to remove the
- 		 offending note.  */
- 	      return false;
- 	    }
- 
- 	  size_x = GET_MODE_BITSIZE (GET_MODE (x));
- 	  size_sub = GET_MODE_BITSIZE (GET_MODE (sub));
- 
- 	  /* Do not frob unchanging MEMs.  If a later reference forces the
- 	     pseudo to the stack, we can wind up with multiple writes to
- 	     an unchanging memory, which is invalid.  */
- 	  if (RTX_UNCHANGING_P (x) && size_x != size_sub)
- 	    ;
- 
- 	  /* Don't even consider working with paradoxical subregs,
- 	     or the moral equivalent seen here.  */
- 	  else if (size_x <= size_sub
- 	           && int_mode_for_mode (GET_MODE (sub)) != BLKmode)
- 	    {
- 	      /* Do a bitfield insertion to mirror what would happen
- 		 in memory.  */
- 
- 	      rtx val, seq;
- 
- 	      if (store)
- 		{
- 		  rtx p = PREV_INSN (insn);
- 
- 		  start_sequence ();
- 		  val = gen_reg_rtx (GET_MODE (x));
- 		  if (! validate_change (insn, loc, val, 0))
- 		    {
- 		      /* Discard the current sequence and put the
- 			 ADDRESSOF on stack.  */
- 		      end_sequence ();
- 		      goto give_up;
- 		    }
- 		  seq = get_insns ();
- 		  end_sequence ();
- 		  emit_insn_before (seq, insn);
- 		  compute_insns_for_mem (p ? NEXT_INSN (p) : get_insns (),
- 					 insn, ht);
- 
- 		  start_sequence ();
- 		  store_bit_field (sub, size_x, 0, GET_MODE (x),
- 				   val, GET_MODE_SIZE (GET_MODE (sub)));
- 
- 		  /* Make sure to unshare any shared rtl that store_bit_field
- 		     might have created.  */
- 		  unshare_all_rtl_again (get_insns ());
- 
- 		  seq = get_insns ();
- 		  end_sequence ();
- 		  p = emit_insn_after (seq, insn);
- 		  if (NEXT_INSN (insn))
- 		    compute_insns_for_mem (NEXT_INSN (insn),
- 					   p ? NEXT_INSN (p) : NULL_RTX,
- 					   ht);
- 		}
- 	      else
- 		{
- 		  rtx p = PREV_INSN (insn);
- 
- 		  start_sequence ();
- 		  val = extract_bit_field (sub, size_x, 0, 1, NULL_RTX,
- 					   GET_MODE (x), GET_MODE (x),
- 					   GET_MODE_SIZE (GET_MODE (sub)));
- 
- 		  if (! validate_change (insn, loc, val, 0))
- 		    {
- 		      /* Discard the current sequence and put the
- 			 ADDRESSOF on stack.  */
- 		      end_sequence ();
- 		      goto give_up;
- 		    }
- 
- 		  seq = get_insns ();
- 		  end_sequence ();
- 		  emit_insn_before (seq, insn);
- 		  compute_insns_for_mem (p ? NEXT_INSN (p) : get_insns (),
- 					 insn, ht);
- 		}
- 
- 	      /* Remember the replacement so that the same one can be done
- 		 on the REG_NOTES.  */
- 	      purge_bitfield_addressof_replacements
- 		= gen_rtx_EXPR_LIST (VOIDmode, x,
- 				     gen_rtx_EXPR_LIST
- 				     (VOIDmode, val,
- 				      purge_bitfield_addressof_replacements));
- 
- 	      /* We replaced with a reg -- all done.  */
- 	      return true;
- 	    }
- 	}
- 
-       else if (validate_change (insn, loc, sub, 0))
- 	{
- 	  /* Remember the replacement so that the same one can be done
- 	     on the REG_NOTES.  */
- 	  if (GET_CODE (sub) == REG || GET_CODE (sub) == SUBREG)
- 	    {
- 	      rtx tem;
- 
- 	      for (tem = purge_addressof_replacements;
- 		   tem != NULL_RTX;
- 		   tem = XEXP (XEXP (tem, 1), 1))
- 		if (rtx_equal_p (XEXP (x, 0), XEXP (tem, 0)))
- 		  {
- 		    XEXP (XEXP (tem, 1), 0) = sub;
- 		    return true;
- 		  }
- 	      purge_addressof_replacements
- 		= gen_rtx_EXPR_LIST (VOIDmode, XEXP (x, 0),
- 				     gen_rtx_EXPR_LIST (VOIDmode, sub,
- 							purge_addressof_replacements));
- 	      return true;
- 	    }
- 	  goto restart;
- 	}
-     }
- 
-  give_up:
-   /* Scan all subexpressions.  */
-   fmt = GET_RTX_FORMAT (code);
-   for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
-     {
-       if (*fmt == 'e')
- 	result &= purge_addressof_1 (&XEXP (x, i), insn, force, 0,
- 				     may_postpone, ht);
-       else if (*fmt == 'E')
- 	for (j = 0; j < XVECLEN (x, i); j++)
- 	  result &= purge_addressof_1 (&XVECEXP (x, i, j), insn, force, 0,
- 				       may_postpone, ht);
-     }
- 
-   return result;
- }
- 
- /* Return a hash value for K, a REG.  */
- 
- static hashval_t
- insns_for_mem_hash (const void *k)
- {
-   /* Use the address of the key for the hash value.  */
-   struct insns_for_mem_entry *m = (struct insns_for_mem_entry *) k;
-   return htab_hash_pointer (m->key);
- }
- 
- /* Return nonzero if K1 and K2 (two REGs) are the same.  */
- 
- static int
- insns_for_mem_comp (const void *k1, const void *k2)
- {
-   struct insns_for_mem_entry *m1 = (struct insns_for_mem_entry *) k1;
-   struct insns_for_mem_entry *m2 = (struct insns_for_mem_entry *) k2;
-   return m1->key == m2->key;
- }
- 
- struct insns_for_mem_walk_info
- {
-   /* The hash table that we are using to record which INSNs use which
-      MEMs.  */
-   htab_t ht;
- 
-   /* The INSN we are currently processing.  */
-   rtx insn;
- 
-   /* Zero if we are walking to find ADDRESSOFs, one if we are walking
-      to find the insns that use the REGs in the ADDRESSOFs.  */
-   int pass;
- };
- 
- /* Called from compute_insns_for_mem via for_each_rtx.  If R is a REG
-    that might be used in an ADDRESSOF expression, record this INSN in
-    the hash table given by DATA (which is really a pointer to an
-    insns_for_mem_walk_info structure).  */
- 
- static int
- insns_for_mem_walk (rtx *r, void *data)
- {
-   struct insns_for_mem_walk_info *ifmwi
-     = (struct insns_for_mem_walk_info *) data;
-   struct insns_for_mem_entry tmp;
-   tmp.insns = NULL_RTX;
- 
-   if (ifmwi->pass == 0 && *r && GET_CODE (*r) == ADDRESSOF
-       && GET_CODE (XEXP (*r, 0)) == REG)
-     {
-       void **e;
-       tmp.key = XEXP (*r, 0);
-       e = htab_find_slot (ifmwi->ht, &tmp, INSERT);
-       if (*e == NULL)
- 	{
- 	  *e = ggc_alloc (sizeof (tmp));
- 	  memcpy (*e, &tmp, sizeof (tmp));
- 	}
-     }
-   else if (ifmwi->pass == 1 && *r && GET_CODE (*r) == REG)
-     {
-       struct insns_for_mem_entry *ifme;
-       tmp.key = *r;
-       ifme = htab_find (ifmwi->ht, &tmp);
- 
-       /* If we have not already recorded this INSN, do so now.  Since
- 	 we process the INSNs in order, we know that if we have
- 	 recorded it it must be at the front of the list.  */
-       if (ifme && (!ifme->insns || XEXP (ifme->insns, 0) != ifmwi->insn))
- 	ifme->insns = gen_rtx_EXPR_LIST (VOIDmode, ifmwi->insn,
- 					 ifme->insns);
-     }
- 
-   return 0;
- }
- 
- /* Walk the INSNS, until we reach LAST_INSN, recording which INSNs use
-    which REGs in HT.  */
- 
- static void
- compute_insns_for_mem (rtx insns, rtx last_insn, htab_t ht)
- {
-   rtx insn;
-   struct insns_for_mem_walk_info ifmwi;
-   ifmwi.ht = ht;
- 
-   for (ifmwi.pass = 0; ifmwi.pass < 2; ++ifmwi.pass)
-     for (insn = insns; insn != last_insn; insn = NEXT_INSN (insn))
-       if (INSN_P (insn))
- 	{
- 	  ifmwi.insn = insn;
- 	  for_each_rtx (&insn, insns_for_mem_walk, &ifmwi);
- 	}
- }
- 
- /* Helper function for purge_addressof called through for_each_rtx.
-    Returns true iff the rtl is an ADDRESSOF.  */
- 
- static int
- is_addressof (rtx *rtl, void *data ATTRIBUTE_UNUSED)
- {
-   return GET_CODE (*rtl) == ADDRESSOF;
- }
- 
- /* Eliminate all occurrences of ADDRESSOF from INSNS.  Elide any remaining
-    (MEM (ADDRESSOF)) patterns, and force any needed registers into the
-    stack.  */
- 
- void
- purge_addressof (rtx insns)
- {
-   rtx insn, tmp;
-   htab_t ht;
- 
-   /* When we actually purge ADDRESSOFs, we turn REGs into MEMs.  That
-      requires a fixup pass over the instruction stream to correct
-      INSNs that depended on the REG being a REG, and not a MEM.  But,
-      these fixup passes are slow.  Furthermore, most MEMs are not
-      mentioned in very many instructions.  So, we speed up the process
-      by pre-calculating which REGs occur in which INSNs; that allows
-      us to perform the fixup passes much more quickly.  */
-   ht = htab_create_ggc (1000, insns_for_mem_hash, insns_for_mem_comp, NULL);
-   compute_insns_for_mem (insns, NULL_RTX, ht);
- 
-   postponed_insns = NULL;
- 
-   for (insn = insns; insn; insn = NEXT_INSN (insn))
-     if (INSN_P (insn))
-       {
- 	if (! purge_addressof_1 (&PATTERN (insn), insn,
- 				 asm_noperands (PATTERN (insn)) > 0, 0, 1, ht))
- 	  /* If we could not replace the ADDRESSOFs in the insn,
- 	     something is wrong.  */
- 	  abort ();
- 
- 	if (! purge_addressof_1 (&REG_NOTES (insn), NULL_RTX, 0, 0, 0, ht))
- 	  {
- 	    /* If we could not replace the ADDRESSOFs in the insn's notes,
- 	       we can just remove the offending notes instead.  */
- 	    rtx note;
- 
- 	    for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
- 	      {
- 		/* If we find a REG_RETVAL note then the insn is a libcall.
- 		   Such insns must have REG_EQUAL notes as well, in order
- 		   for later passes of the compiler to work.  So it is not
- 		   safe to delete the notes here, and instead we abort.  */
- 		if (REG_NOTE_KIND (note) == REG_RETVAL)
- 		  abort ();
- 		if (for_each_rtx (&note, is_addressof, NULL))
- 		  remove_note (insn, note);
- 	      }
- 	  }
-       }
- 
-   /* Process the postponed insns.  */
-   while (postponed_insns)
-     {
-       insn = XEXP (postponed_insns, 0);
-       tmp = postponed_insns;
-       postponed_insns = XEXP (postponed_insns, 1);
-       free_INSN_LIST_node (tmp);
- 
-       if (! purge_addressof_1 (&PATTERN (insn), insn,
- 			       asm_noperands (PATTERN (insn)) > 0, 0, 0, ht))
- 	abort ();
-     }
- 
-   /* Clean up.  */
-   purge_bitfield_addressof_replacements = 0;
-   purge_addressof_replacements = 0;
- 
-   /* REGs are shared.  purge_addressof will destructively replace a REG
-      with a MEM, which creates shared MEMs.
- 
-      Unfortunately, the children of put_reg_into_stack assume that MEMs
-      referring to the same stack slot are shared (fixup_var_refs and
-      the associated hash table code).
- 
-      So, we have to do another unsharing pass after we have flushed any
-      REGs that had their address taken into the stack.
- 
-      It may be worth tracking whether or not we converted any REGs into
-      MEMs to avoid this overhead when it is not needed.  */
-   unshare_all_rtl_again (get_insns ());
- }
  
  /* Convert a SET of a hard subreg to a set of the appropriate hard
     register.  A subroutine of purge_hard_subreg_sets.  */
--- 2874,2879 ----
Index: passes.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/passes.c,v
retrieving revision 2.17
diff -c -3 -p -r2.17 passes.c
*** passes.c	30 May 2004 18:32:27 -0000	2.17
--- passes.c	1 Jun 2004 21:28:11 -0000
*************** enum dump_file_index
*** 138,144 ****
    DFI_jump,
    DFI_null,
    DFI_cse,
-   DFI_addressof,
    DFI_gcse,
    DFI_loop,
    DFI_bypass,
--- 138,143 ----
*************** static struct dump_file_info dump_file_t
*** 192,198 ****
    { "jump",	'j', 0, 0, 0 },
    { "null",	'u', 0, 0, 0 },
    { "cse",	's', 0, 0, 0 },
-   { "addressof", 'F', 0, 0, 0 },
    { "gcse",	'G', 1, 0, 0 },
    { "loop",	'L', 1, 0, 0 },
    { "bypass",   'G', 1, 0, 0 }, /* Yes, duplicate enable switch.  */
--- 191,196 ----
*************** rest_of_handle_cfg (tree decl, rtx insns
*** 989,1008 ****
    close_dump_file (DFI_cfg, print_rtl_with_bb, insns);
  }
  
- /* Purge addressofs.  */
- static void
- rest_of_handle_addressof (tree decl, rtx insns)
- {
-   open_dump_file (DFI_addressof, decl);
- 
-   purge_addressof (insns);
-   if (optimize && purge_all_dead_edges (0))
-     delete_unreachable_blocks ();
-   reg_scan (insns, max_reg_num (), 1);
- 
-   close_dump_file (DFI_addressof, print_rtl, insns);
- }
- 
  /* Perform jump bypassing and control flow optimizations.  */
  static void
  rest_of_handle_jump_bypass (tree decl, rtx insns)
--- 987,992 ----
*************** rest_of_compilation (tree decl)
*** 1561,1568 ****
    if (optimize > 0)
      rest_of_handle_cse (decl, insns);
  
-   rest_of_handle_addressof (decl, insns);
- 
    ggc_collect ();
  
    if (optimize > 0)
--- 1545,1550 ----
Index: rtl.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/rtl.h,v
retrieving revision 1.477
diff -c -3 -p -r1.477 rtl.h
*** rtl.h	28 May 2004 06:27:31 -0000	1.477
--- rtl.h	1 Jun 2004 21:28:12 -0000
*************** extern rtx simplify_replace_rtx (rtx, rt
*** 1774,1782 ****
  extern rtx simplify_rtx (rtx);
  extern rtx avoid_constant_pool_reference (rtx);
  
- /* In function.c  */
- extern rtx gen_mem_addressof (rtx, tree, int);
- 
  /* In regclass.c  */
  extern enum machine_mode choose_hard_reg_mode (unsigned int, unsigned int,
  					       bool);
--- 1774,1779 ----
*************** extern int sibcall_epilogue_contains (rt
*** 2249,2255 ****
  extern void preserve_rtl_expr_result (rtx);
  extern void mark_temp_addr_taken (rtx);
  extern void update_temp_slot_address (rtx, rtx);
- extern void purge_addressof (rtx);
  extern void purge_hard_subreg_sets (rtx);
  
  /* In stmt.c */
--- 2246,2251 ----
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.503
diff -c -3 -p -r1.503 tree.h
*** tree.h	30 May 2004 18:32:31 -0000	1.503
--- tree.h	1 Jun 2004 21:28:12 -0000
*************** extern void allocate_struct_function (tr
*** 3538,3544 ****
  extern void init_function_start (tree);
  extern void assign_parms (tree);
  extern void put_var_into_stack (tree, int);
- extern void flush_addressof (tree);
  extern void setjmp_vars_warning (tree);
  extern void setjmp_args_warning (void);
  extern void init_temp_slots (void);
--- 3538,3543 ----

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