output_constant_def reorg

Zack Weinberg zack@codesourcery.com
Sun Apr 27 03:50:00 GMT 2003


Continuing in baby steps towards elimination of TREE_CST_RTL, this
patch reorganizes and splits up output_constant_def, making it much
easier to comprehend the internal logic.  There are four changes of
behavior:

- output_addressed_constants is only called if the constant is itself
  about to be output.  Due to the early return if TREE_CST_RTL is set,
  this actually makes little difference.

- code inspection indicates that STRING_POOL_ADDRESS_P is true if and
  only if the symbol in question has an entry in the deferred_string
  hash table, so we make that be an invariant enforced by ENABLE_CHECKING 
  assertions.

- output_constant_def_contents now uses ASM_OUTPUT_LABEL on the
  already-generated label from the SYMBOL_REF instead of calling
  asm_out.internal_label.  I checked that no definition of
  asm_out.internal_label does anything unusual with "LC" internal
  labels.

- TREE_CST_RTL is now undefined when encode_section_info is called.
  (This is already documented to be the case.)

Bootstrapped i686-linux with no change whatsoever in testsuite status,
and no measurable performance difference.

I suspect we could now get rid of the deferred_string table by
pointing SYMBOL_REF_DECL to the tree for the constant, but that's for
a separate patch.

zw

        * varasm.c (output_constant_def): Split out two new static
        functions, build_constant_desc and maybe_output_constant_def_contents.
        Restructure for comprehensibility.  Don't call
        output_addressed_constants.  Treat defstr being non-NULL for
        STRING_POOL_ADDRESS_P constants as an invariant.
        (struct deferred_string): Remove labelno field.
        (output_constant_def_contents): Kill labelno argument.  Call
        output_addressed_constants here.  Use ASM_OUTPUT_LABEL, not
        asm_out.internal_label.
        (mark_constant): Update call to output_constant_def_contents.
        Treat defstr being non-NULL for STRING_POOL_ADDRESS_P
        constants as an invariant.

===================================================================
Index: varasm.c
*** varasm.c	20 Apr 2003 22:43:59 -0000	1.342
--- varasm.c	27 Apr 2003 03:30:04 -0000
*************** static unsigned int const_hash		PARAMS (
*** 142,148 ****
  static unsigned int const_hash_1	PARAMS ((tree));
  static int compare_constant		PARAMS ((tree, tree));
  static tree copy_constant		PARAMS ((tree));
! static void output_constant_def_contents  PARAMS ((tree, int, int));
  static void decode_rtx_const		PARAMS ((enum machine_mode, rtx,
  					       struct rtx_const *));
  static unsigned int const_hash_rtx	PARAMS ((enum machine_mode, rtx));
--- 142,149 ----
  static unsigned int const_hash_1	PARAMS ((tree));
  static int compare_constant		PARAMS ((tree, tree));
  static tree copy_constant		PARAMS ((tree));
! static void maybe_output_constant_def_contents PARAMS ((tree, rtx, int));
! static void output_constant_def_contents  PARAMS ((tree, const char *));
  static void decode_rtx_const		PARAMS ((enum machine_mode, rtx,
  					       struct rtx_const *));
  static unsigned int const_hash_rtx	PARAMS ((enum machine_mode, rtx));
*************** struct constant_descriptor_tree GTY(())
*** 2164,2169 ****
--- 2165,2172 ----
  static GTY(()) struct constant_descriptor_tree *
    const_hash_table[MAX_HASH_TABLE];
  
+ static struct constant_descriptor_tree * build_constant_desc PARAMS ((tree));
+ 
  /* We maintain a hash table of STRING_CST values.  Unless we are asked to force
     out a string constant, we defer output of the constants until we know
     they are actually used.  This will be if something takes its address or if
*************** struct deferred_string GTY(())
*** 2175,2181 ****
  {
    const char *label;
    tree exp;
-   int labelno;
  };
  
  static GTY ((param_is (struct deferred_string))) htab_t const_str_htab;
--- 2178,2183 ----
*************** copy_constant (exp)
*** 2533,2538 ****
--- 2535,2585 ----
      }
  }
  
+ /* Subroutine of output_constant_def:
+    No constant equal to EXP is known to have been output.
+    Make a constant descriptor to enter EXP in the hash table.
+    Assign the label number and construct RTL to refer to the
+    constant's location in memory.
+    Caller is responsible for updating the hash table.  */
+ 
+ static struct constant_descriptor_tree *
+ build_constant_desc (exp)
+      tree exp;
+ {
+   rtx symbol;
+   rtx rtl;
+   char label[256];
+   int labelno;
+   struct constant_descriptor_tree *desc;
+ 
+   desc = ggc_alloc (sizeof (*desc));
+   desc->value = copy_constant (exp);
+ 
+   /* Create a string containing the label name, in LABEL.  */
+   labelno = const_labelno++;
+   ASM_GENERATE_INTERNAL_LABEL (label, "LC", labelno);
+ 
+   /* We have a symbol name; construct the SYMBOL_REF and the MEM.  */
+   symbol = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (label));
+   SYMBOL_REF_FLAGS (symbol) = SYMBOL_FLAG_LOCAL;
+ 
+   rtl = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (exp)), symbol);
+   set_mem_attributes (rtl, exp, 1);
+   set_mem_alias_set (rtl, 0);
+   set_mem_alias_set (rtl, const_alias_set);
+ 
+   /* Set flags or add text to the name to record information, such as
+      that it is a local symbol.  If the name is changed, the macro
+      ASM_OUTPUT_LABELREF will have to know how to strip this
+      information.  */
+   (*targetm.encode_section_info) (exp, rtl, true);
+ 
+   desc->rtl = rtl;
+   desc->label = XSTR (XEXP (desc->rtl, 0), 0);
+ 
+   return desc;
+ }
+ 
  /* Return an rtx representing a reference to constant data in memory
     for the constant expression EXP.
  
*************** output_constant_def (exp, defer)
*** 2554,2565 ****
  {
    int hash;
    struct constant_descriptor_tree *desc;
-   struct deferred_string **defstr;
-   char label[256];
-   int reloc;
-   int found = 1;
-   int labelno = -1;
-   rtx rtl;
  
    /* We can't just use the saved RTL if this is a deferred string constant
       and we are not to defer anymore.  */
--- 2601,2606 ----
*************** output_constant_def (exp, defer)
*** 2567,2699 ****
        && (defer || !STRING_POOL_ADDRESS_P (XEXP (TREE_CST_RTL (exp), 0))))
      return TREE_CST_RTL (exp);
  
-   /* Make sure any other constants whose addresses appear in EXP
-      are assigned label numbers.  */
- 
-   reloc = output_addressed_constants (exp);
- 
    /* Compute hash code of EXP.  Search the descriptors for that hash code
       to see if any of them describes EXP.  If yes, the descriptor records
       the label number already assigned.  */
  
    hash = const_hash (exp);
- 
    for (desc = const_hash_table[hash]; desc; desc = desc->next)
      if (compare_constant (exp, desc->value))
        break;
  
    if (desc == 0)
      {
!       rtx symbol;
! 
!       /* No constant equal to EXP is known to have been output.
! 	 Make a constant descriptor to enter EXP in the hash table.
! 	 Assign the label number and record it in the descriptor for
! 	 future calls to this function to find.  */
! 
!       /* Create a string containing the label name, in LABEL.  */
!       labelno = const_labelno++;
!       ASM_GENERATE_INTERNAL_LABEL (label, "LC", labelno);
! 
!       desc = ggc_alloc (sizeof (*desc));
        desc->next = const_hash_table[hash];
-       desc->label = ggc_strdup (label);
-       desc->value = copy_constant (exp);
        const_hash_table[hash] = desc;
  
!       /* We have a symbol name; construct the SYMBOL_REF and the MEM.  */
!       symbol = gen_rtx_SYMBOL_REF (Pmode, desc->label);
!       SYMBOL_REF_FLAGS (symbol) = SYMBOL_FLAG_LOCAL;
! 
!       rtl = desc->rtl = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (exp)), symbol);
  
!       set_mem_attributes (rtl, exp, 1);
!       set_mem_alias_set (rtl, 0);
!       set_mem_alias_set (rtl, const_alias_set);
  
!       found = 0;
      }
-   else
-     rtl = desc->rtl;
  
!   if (TREE_CODE (exp) != INTEGER_CST)
!     TREE_CST_RTL (exp) = rtl;
  
!   /* Optionally set flags or add text to the name to record information
!      such as that it is a function name.  If the name is changed, the macro
!      ASM_OUTPUT_LABELREF will have to know how to strip this information.  */
!   /* A previously-processed constant would already have section info
!      encoded in it.  */
!   if (! found)
!     {
!       (*targetm.encode_section_info) (exp, rtl, true);
  
!       desc->rtl = rtl;
!       desc->label = XSTR (XEXP (desc->rtl, 0), 0);
!     }
  
!   if (found && !defer && STRING_POOL_ADDRESS_P (XEXP (rtl, 0)))
      {
        defstr = (struct deferred_string **)
! 	htab_find_slot_with_hash (const_str_htab, desc->label,
! 				  STRHASH (desc->label), NO_INSERT);
        if (defstr)
  	{
! 	  /* If the string is currently deferred but we need to output it now,
! 	     remove it from deferred string hash table.  */
! 	  found = 0;
! 	  labelno = (*defstr)->labelno;
! 	  STRING_POOL_ADDRESS_P (XEXP (rtl, 0)) = 0;
! 	  htab_clear_slot (const_str_htab, (void **) defstr);
! 	}
!     }
  
!   /* If this is the first time we've seen this particular constant,
!      output it.  Do no output if -fsyntax-only.  */
!   if (! found && ! flag_syntax_only)
!     {
!       if (!defer || TREE_CODE (exp) != STRING_CST
! 	  || flag_writable_strings)
! 	output_constant_def_contents (exp, reloc, labelno);
!       else
! 	{
! 	  defstr = (struct deferred_string **)
! 	    htab_find_slot_with_hash (const_str_htab, desc->label,
! 				      STRHASH (desc->label), INSERT);
! 	  if (!defstr)
! 	    output_constant_def_contents (exp, reloc, labelno);
! 	  else
! 	    {
! 	      struct deferred_string *p;
  
! 	      p = (struct deferred_string *)
! 		ggc_alloc (sizeof (struct deferred_string));
  
! 	      p->exp = desc->value;
! 	      p->label = desc->label;
! 	      p->labelno = labelno;
! 	      *defstr = p;
! 	      STRING_POOL_ADDRESS_P (XEXP (rtl, 0)) = 1;
! 	    }
  	}
      }
  
!   return rtl;
  }
  
  /* Now output assembler code to define the label for EXP,
     and follow it with the data of EXP.  */
  
  static void
! output_constant_def_contents (exp, reloc, labelno)
       tree exp;
!      int reloc;
!      int labelno;
  {
!   int align;
  
    /* Align the location counter as required by EXP's data type.  */
!   align = TYPE_ALIGN (TREE_TYPE (exp));
  #ifdef CONSTANT_ALIGNMENT
    align = CONSTANT_ALIGNMENT (exp, align);
  #endif
--- 2608,2709 ----
        && (defer || !STRING_POOL_ADDRESS_P (XEXP (TREE_CST_RTL (exp), 0))))
      return TREE_CST_RTL (exp);
  
    /* Compute hash code of EXP.  Search the descriptors for that hash code
       to see if any of them describes EXP.  If yes, the descriptor records
       the label number already assigned.  */
  
    hash = const_hash (exp);
    for (desc = const_hash_table[hash]; desc; desc = desc->next)
      if (compare_constant (exp, desc->value))
        break;
  
    if (desc == 0)
      {
!       desc = build_constant_desc (exp);
        desc->next = const_hash_table[hash];
        const_hash_table[hash] = desc;
  
!       maybe_output_constant_def_contents (exp, desc->rtl, defer);
!     }
!   else if (!defer && STRING_POOL_ADDRESS_P (XEXP (desc->rtl, 0)))
!     {
!       /* If the string is currently deferred but we need to output it
! 	 now, remove it from the deferred string hash table.  */
!       struct deferred_string **defstr;
  
!       defstr = (struct deferred_string **)
! 	htab_find_slot_with_hash (const_str_htab, desc->label,
! 				  STRHASH (desc->label), NO_INSERT);
! #ifdef ENABLE_CHECKING
!       if (!defstr)
! 	abort ();
! #endif
  
!       STRING_POOL_ADDRESS_P (XEXP (desc->rtl, 0)) = 0;
!       htab_clear_slot (const_str_htab, (void **) defstr);
!       maybe_output_constant_def_contents (exp, desc->rtl, 0);
      }
  
!   TREE_CST_RTL (exp) = desc->rtl;
!   return desc->rtl;
! }
  
! /* Subroutine of output_constant_def:
!    Decide whether or not to defer the output of EXP, which can be
!    accesed through rtl RTL, and either do the output or record EXP in
!    the table of deferred strings.  */
! static void
! maybe_output_constant_def_contents (exp, rtl, defer)
!      tree exp;
!      rtx rtl;
!      int defer;
! {
!   const char *label;
  
!   if (flag_syntax_only)
!     return;
  
!   label = XSTR (XEXP (rtl, 0), 0);
! 
!   if (defer && TREE_CODE (exp) == STRING_CST && !flag_writable_strings)
      {
+       struct deferred_string **defstr;
        defstr = (struct deferred_string **)
! 	htab_find_slot_with_hash (const_str_htab, label,
! 				  STRHASH (label), INSERT);
        if (defstr)
  	{
! 	  struct deferred_string *p;
  
! 	  p = (struct deferred_string *)
! 	    ggc_alloc (sizeof (struct deferred_string));
  
! 	  p->exp = exp;
! 	  p->label = label;
  
! 	  *defstr = p;
! 	  STRING_POOL_ADDRESS_P (XEXP (rtl, 0)) = 1;
! 	  return;
  	}
      }
  
!   output_constant_def_contents (exp, label);
  }
  
  /* Now output assembler code to define the label for EXP,
     and follow it with the data of EXP.  */
  
  static void
! output_constant_def_contents (exp, label)
       tree exp;
!      const char *label;
  {
!   /* Make sure any other constants whose addresses appear in EXP
!      are assigned label numbers.  */
!   int reloc = output_addressed_constants (exp);
  
    /* Align the location counter as required by EXP's data type.  */
!   int align = TYPE_ALIGN (TREE_TYPE (exp));
  #ifdef CONSTANT_ALIGNMENT
    align = CONSTANT_ALIGNMENT (exp, align);
  #endif
*************** output_constant_def_contents (exp, reloc
*** 2709,2715 ****
      }
  
    /* Output the label itself.  */
!   (*targetm.asm_out.internal_label) (asm_out_file, "LC", labelno);
  
    /* Output the value of EXP.  */
    output_constant (exp,
--- 2719,2725 ----
      }
  
    /* Output the label itself.  */
!   ASM_OUTPUT_LABEL (asm_out_file, label);
  
    /* Output the value of EXP.  */
    output_constant (exp,
*************** mark_constant (current_rtx, data)
*** 3521,3539 ****
  	}
        else if (STRING_POOL_ADDRESS_P (x))
  	{
! 	  struct deferred_string **defstr;
  
  	  defstr = (struct deferred_string **)
  	    htab_find_slot_with_hash (const_str_htab, XSTR (x, 0),
  				      STRHASH (XSTR (x, 0)), NO_INSERT);
! 	  if (defstr)
! 	    {
! 	      struct deferred_string *p = *defstr;
  
! 	      STRING_POOL_ADDRESS_P (x) = 0;
! 	      output_constant_def_contents (p->exp, 0, p->labelno);
! 	      htab_clear_slot (const_str_htab, (void **) defstr);
! 	    }
  	}
      }
    return 0;
--- 3531,3550 ----
  	}
        else if (STRING_POOL_ADDRESS_P (x))
  	{
! 	  struct deferred_string *p, **defstr;
  
  	  defstr = (struct deferred_string **)
  	    htab_find_slot_with_hash (const_str_htab, XSTR (x, 0),
  				      STRHASH (XSTR (x, 0)), NO_INSERT);
! #ifdef ENABLE_CHECKING
! 	  if (!defstr)
! 	    abort ();
! #endif
  
! 	  p = *defstr;
! 	  STRING_POOL_ADDRESS_P (x) = 0;
! 	  output_constant_def_contents (p->exp, p->label);
! 	  htab_clear_slot (const_str_htab, (void **) defstr);
  	}
      }
    return 0;



More information about the Gcc-patches mailing list