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