Commit bd7cf17e by Jakub Jelinek Committed by Jakub Jelinek

varasm.c (struct deferred_string): New structure.

	* varasm.c (struct deferred_string): New structure.
	(const_str_htab): New variable.
	(STRHASH): New macro.
	(mark_const_str_htab_1, mark_const_str_htab, const_str_htab_hash,
	constr_str_htab_eq, const_str_htab_del): New functions.
	(output_constant_def): Add DEFER argument, defer string
	constants until mark_constant_pool time if requested.
	(mark_constant_pool): Walk the insn chain even if const_str_htab is
	not empty.
	(mark_constants): If a SYMBOL_REF for deferred string is found,
	output it and remove from hash table.
	(output_addressed_constants): Set DEFER to 0 in call to
	output_constant_def.
	* rtl.h (STRING_POOL_ADDRESS_P): Define.
	(output_constant_def): Adjust prototype.
	* expr.c (expand_expr): Set DEFER to 1 in call to output_constant_def.

	* gcc.c-torture/execute/20000801-4.c: Make sure the second string is
	output.

From-SVN: r37459
parent 10e927ef
2000-11-14 Jakub Jelinek <jakub@redhat.com>
* varasm.c (struct deferred_string): New structure.
(const_str_htab): New variable.
(STRHASH): New macro.
(mark_const_str_htab_1, mark_const_str_htab, const_str_htab_hash,
constr_str_htab_eq, const_str_htab_del): New functions.
(output_constant_def): Add DEFER argument, defer string
constants until mark_constant_pool time if requested.
(mark_constant_pool): Walk the insn chain even if const_str_htab is
not empty.
(mark_constants): If a SYMBOL_REF for deferred string is found,
output it and remove from hash table.
(output_addressed_constants): Set DEFER to 0 in call to
output_constant_def.
* rtl.h (STRING_POOL_ADDRESS_P): Define.
(output_constant_def): Adjust prototype.
* expr.c (expand_expr): Set DEFER to 1 in call to output_constant_def.
2000-11-14 Chandrakala Chavva <cchavva@redhat.com> 2000-11-14 Chandrakala Chavva <cchavva@redhat.com>
* optabs.c (expand_complex_ab):: Use overflow-trapping optabs for * optabs.c (expand_complex_ab):: Use overflow-trapping optabs for
......
...@@ -6143,7 +6143,7 @@ expand_expr (exp, target, tmode, modifier) ...@@ -6143,7 +6143,7 @@ expand_expr (exp, target, tmode, modifier)
case COMPLEX_CST: case COMPLEX_CST:
case STRING_CST: case STRING_CST:
if (! TREE_CST_RTL (exp)) if (! TREE_CST_RTL (exp))
output_constant_def (exp); output_constant_def (exp, 1);
/* TREE_CST_RTL probably contains a constant address. /* TREE_CST_RTL probably contains a constant address.
On RISC machines where a constant address isn't valid, On RISC machines where a constant address isn't valid,
...@@ -6456,7 +6456,7 @@ expand_expr (exp, target, tmode, modifier) ...@@ -6456,7 +6456,7 @@ expand_expr (exp, target, tmode, modifier)
&& ! mostly_zeros_p (exp)))) && ! mostly_zeros_p (exp))))
|| (modifier == EXPAND_INITIALIZER && TREE_CONSTANT (exp))) || (modifier == EXPAND_INITIALIZER && TREE_CONSTANT (exp)))
{ {
rtx constructor = output_constant_def (exp); rtx constructor = output_constant_def (exp, 1);
if (modifier != EXPAND_CONST_ADDRESS if (modifier != EXPAND_CONST_ADDRESS
&& modifier != EXPAND_INITIALIZER && modifier != EXPAND_INITIALIZER
......
...@@ -168,7 +168,9 @@ typedef struct rtx_def ...@@ -168,7 +168,9 @@ typedef struct rtx_def
either changing how we compute the frame address or saving and either changing how we compute the frame address or saving and
restoring registers in the prologue and epilogue. restoring registers in the prologue and epilogue.
1 in a MEM if the MEM refers to a scalar, rather than a member of 1 in a MEM if the MEM refers to a scalar, rather than a member of
an aggregate. */ an aggregate.
1 in a SYMBOL_REF if it addresses something in the per-function
constant string pool. */
unsigned frame_related : 1; unsigned frame_related : 1;
/* The first element of the operands of this rtx. /* The first element of the operands of this rtx.
...@@ -904,6 +906,9 @@ extern const char * const note_insn_name[NOTE_INSN_MAX - NOTE_INSN_BIAS]; ...@@ -904,6 +906,9 @@ extern const char * const note_insn_name[NOTE_INSN_MAX - NOTE_INSN_BIAS];
/* 1 in a SYMBOL_REF if it addresses this function's constants pool. */ /* 1 in a SYMBOL_REF if it addresses this function's constants pool. */
#define CONSTANT_POOL_ADDRESS_P(RTX) ((RTX)->unchanging) #define CONSTANT_POOL_ADDRESS_P(RTX) ((RTX)->unchanging)
/* 1 in a SYMBOL_REF if it addresses this function's string constant pool. */
#define STRING_POOL_ADDRESS_P(RTX) ((RTX)->frame_related)
/* Flag in a SYMBOL_REF for machine-specific purposes. */ /* Flag in a SYMBOL_REF for machine-specific purposes. */
#define SYMBOL_REF_FLAG(RTX) ((RTX)->volatil) #define SYMBOL_REF_FLAG(RTX) ((RTX)->volatil)
...@@ -1587,7 +1592,7 @@ extern rtx gen_rtx_MEM PARAMS ((enum machine_mode, rtx)); ...@@ -1587,7 +1592,7 @@ extern rtx gen_rtx_MEM PARAMS ((enum machine_mode, rtx));
extern rtx find_next_ref PARAMS ((rtx, rtx)); extern rtx find_next_ref PARAMS ((rtx, rtx));
extern rtx *find_single_use PARAMS ((rtx, rtx, rtx *)); extern rtx *find_single_use PARAMS ((rtx, rtx, rtx *));
extern rtx output_constant_def PARAMS ((union tree_node *)); extern rtx output_constant_def PARAMS ((union tree_node *, int));
extern rtx immed_real_const PARAMS ((union tree_node *)); extern rtx immed_real_const PARAMS ((union tree_node *));
extern union tree_node *make_tree PARAMS ((union tree_node *, rtx)); extern union tree_node *make_tree PARAMS ((union tree_node *, rtx));
......
2000-11-14 Jakub Jelinek <jakub@redhat.com>
* gcc.c-torture/execute/20000801-4.c: Make sure the second string is
output.
2000-11-13 Joseph S. Myers <jsm28@cam.ac.uk> 2000-11-13 Joseph S. Myers <jsm28@cam.ac.uk>
* gcc.dg/wtr-label-1.c, gcc.dg/990214-1.c: Add semicolons after * gcc.dg/wtr-label-1.c, gcc.dg/990214-1.c: Add semicolons after
......
...@@ -14,11 +14,14 @@ foo (void) ...@@ -14,11 +14,14 @@ foo (void)
return 0 == s[1]; return 0 == s[1];
} }
char *t;
int int
main (void) main (void)
{ {
{ {
char s[] = "x"; char s[] = "x";
t = s;
} }
if (foo ()) if (foo ())
exit (0); exit (0);
......
...@@ -44,6 +44,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -44,6 +44,7 @@ Boston, MA 02111-1307, USA. */
#include "dbxout.h" #include "dbxout.h"
#include "sdbout.h" #include "sdbout.h"
#include "obstack.h" #include "obstack.h"
#include "hashtab.h"
#include "c-pragma.h" #include "c-pragma.h"
#include "ggc.h" #include "ggc.h"
#include "tm_p.h" #include "tm_p.h"
...@@ -185,6 +186,11 @@ static void asm_output_aligned_bss PARAMS ((FILE *, tree, const char *, ...@@ -185,6 +186,11 @@ static void asm_output_aligned_bss PARAMS ((FILE *, tree, const char *,
#endif /* BSS_SECTION_ASM_OP */ #endif /* BSS_SECTION_ASM_OP */
static void mark_pool_constant PARAMS ((struct pool_constant *)); static void mark_pool_constant PARAMS ((struct pool_constant *));
static void mark_const_hash_entry PARAMS ((void *)); static void mark_const_hash_entry PARAMS ((void *));
static int mark_const_str_htab_1 PARAMS ((void **, void *));
static void mark_const_str_htab PARAMS ((void *));
static hashval_t const_str_htab_hash PARAMS ((const void *x));
static int const_str_htab_eq PARAMS ((const void *x, const void *y));
static void const_str_htab_del PARAMS ((void *));
static void asm_emit_uninitialised PARAMS ((tree, const char*, int, int)); static void asm_emit_uninitialised PARAMS ((tree, const char*, int, int));
static enum in_section { no_section, in_text, in_data, in_named static enum in_section { no_section, in_text, in_data, in_named
...@@ -2342,6 +2348,17 @@ struct constant_descriptor ...@@ -2342,6 +2348,17 @@ struct constant_descriptor
#define MAX_HASH_TABLE 1009 #define MAX_HASH_TABLE 1009
static struct constant_descriptor *const_hash_table[MAX_HASH_TABLE]; static struct constant_descriptor *const_hash_table[MAX_HASH_TABLE];
#define STRHASH(x) ((hashval_t)((long)(x) >> 3))
struct deferred_string
{
char *label;
tree exp;
int labelno;
};
static htab_t const_str_htab;
/* Mark a const_hash_table descriptor for GC. */ /* Mark a const_hash_table descriptor for GC. */
static void static void
...@@ -2358,6 +2375,58 @@ mark_const_hash_entry (ptr) ...@@ -2358,6 +2375,58 @@ mark_const_hash_entry (ptr)
} }
} }
/* Mark the hash-table element X (which is really a pointer to an
struct deferred_string *). */
static int
mark_const_str_htab_1 (x, data)
void **x;
void *data ATTRIBUTE_UNUSED;
{
ggc_mark_tree (((struct deferred_string *) *x)->exp);
return 1;
}
/* Mark a const_str_htab for GC. */
static void
mark_const_str_htab (htab)
void *htab;
{
htab_traverse (*((htab_t *) htab), mark_const_str_htab_1, NULL);
}
/* Returns a hash code for X (which is a really a
struct deferred_string *). */
static hashval_t
const_str_htab_hash (x)
const void *x;
{
return STRHASH (((struct deferred_string *) x)->label);
}
/* Returns non-zero if the value represented by X (which is really a
struct deferred_string *) is the same as that given by Y
(which is really a char *). */
static int
const_str_htab_eq (x, y)
const void *x;
const void *y;
{
return (((struct deferred_string *) x)->label == (char *) y);
}
/* Delete the hash table entry dfsp. */
static void
const_str_htab_del (dfsp)
void *dfsp;
{
free (dfsp);
}
/* Compute a hash code for a constant expression. */ /* Compute a hash code for a constant expression. */
static int static int
...@@ -3056,18 +3125,25 @@ copy_constant (exp) ...@@ -3056,18 +3125,25 @@ copy_constant (exp)
Otherwise, output such a constant in memory (or defer it for later) Otherwise, output such a constant in memory (or defer it for later)
and generate an rtx for it. and generate an rtx for it.
If DEFER is non-zero, the output of string constants can be deferred
and output only if referenced in the function after all optimizations.
The TREE_CST_RTL of EXP is set up to point to that rtx. The TREE_CST_RTL of EXP is set up to point to that rtx.
The const_hash_table records which constants already have label strings. */ The const_hash_table records which constants already have label strings. */
rtx rtx
output_constant_def (exp) output_constant_def (exp, defer)
tree exp; tree exp;
int defer;
{ {
register int hash; register int hash;
register struct constant_descriptor *desc; register struct constant_descriptor *desc;
struct deferred_string **defstr;
char label[256]; char label[256];
int reloc; int reloc;
int found = 1; int found = 1;
int after_function = 0;
int labelno = -1;
if (TREE_CST_RTL (exp)) if (TREE_CST_RTL (exp))
return TREE_CST_RTL (exp); return TREE_CST_RTL (exp);
...@@ -3095,7 +3171,8 @@ output_constant_def (exp) ...@@ -3095,7 +3171,8 @@ output_constant_def (exp)
future calls to this function to find. */ future calls to this function to find. */
/* Create a string containing the label name, in LABEL. */ /* Create a string containing the label name, in LABEL. */
ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno); labelno = const_labelno++;
ASM_GENERATE_INTERNAL_LABEL (label, "LC", labelno);
desc = record_constant (exp); desc = record_constant (exp);
desc->next = const_hash_table[hash]; desc->next = const_hash_table[hash];
...@@ -3121,18 +3198,34 @@ output_constant_def (exp) ...@@ -3121,18 +3198,34 @@ output_constant_def (exp)
ENCODE_SECTION_INFO (exp); ENCODE_SECTION_INFO (exp);
#endif #endif
/* If this is the first time we've seen this particular constant,
output it (or defer its output for later). */
if (! found)
{
int after_function = 0;
#ifdef CONSTANT_AFTER_FUNCTION_P #ifdef CONSTANT_AFTER_FUNCTION_P
if (current_function_decl != 0 if (current_function_decl != 0
&& CONSTANT_AFTER_FUNCTION_P (exp)) && CONSTANT_AFTER_FUNCTION_P (exp))
after_function = 1; after_function = 1;
#endif #endif
if (found
&& STRING_POOL_ADDRESS_P (XEXP (desc->rtl, 0))
&& (!defer || defer_addressed_constants_flag || after_function))
{
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 (desc->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 (or defer its output for later). */
if (! found)
{
if (defer_addressed_constants_flag || after_function) if (defer_addressed_constants_flag || after_function)
{ {
struct deferred_constant *p; struct deferred_constant *p;
...@@ -3140,7 +3233,7 @@ output_constant_def (exp) ...@@ -3140,7 +3233,7 @@ output_constant_def (exp)
p->exp = copy_constant (exp); p->exp = copy_constant (exp);
p->reloc = reloc; p->reloc = reloc;
p->labelno = const_labelno++; p->labelno = labelno;
if (after_function) if (after_function)
{ {
p->next = after_function_constants; p->next = after_function_constants;
...@@ -3156,8 +3249,30 @@ output_constant_def (exp) ...@@ -3156,8 +3249,30 @@ output_constant_def (exp)
{ {
/* Do no output if -fsyntax-only. */ /* Do no output if -fsyntax-only. */
if (! flag_syntax_only) if (! flag_syntax_only)
output_constant_def_contents (exp, reloc, const_labelno); {
++const_labelno; if (TREE_CODE (exp) != STRING_CST
|| !defer
|| flag_writable_strings
|| (defstr = (struct deferred_string **)
htab_find_slot_with_hash (const_str_htab,
desc->label,
STRHASH (desc->label),
INSERT)) == NULL)
output_constant_def_contents (exp, reloc, labelno);
else
{
struct deferred_string *p;
p = (struct deferred_string *)
xmalloc (sizeof (struct deferred_string));
p->exp = copy_constant (exp);
p->label = desc->label;
p->labelno = labelno;
*defstr = p;
STRING_POOL_ADDRESS_P (XEXP (desc->rtl, 0)) = 1;
}
}
} }
} }
...@@ -3806,7 +3921,7 @@ mark_constant_pool () ...@@ -3806,7 +3921,7 @@ mark_constant_pool ()
register rtx insn; register rtx insn;
struct pool_constant *pool; struct pool_constant *pool;
if (first_pool == 0) if (first_pool == 0 && htab_elements (const_str_htab) == 0)
return; return;
for (pool = first_pool; pool; pool = pool->next) for (pool = first_pool; pool; pool = pool->next)
...@@ -3867,6 +3982,22 @@ mark_constants (x) ...@@ -3867,6 +3982,22 @@ mark_constants (x)
{ {
if (CONSTANT_POOL_ADDRESS_P (x)) if (CONSTANT_POOL_ADDRESS_P (x))
find_pool_constant (cfun, x)->mark = 1; find_pool_constant (cfun, x)->mark = 1;
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; return;
} }
/* Never search inside a CONST_DOUBLE, because CONST_DOUBLE_MEM may be /* Never search inside a CONST_DOUBLE, because CONST_DOUBLE_MEM may be
...@@ -3943,7 +4074,7 @@ output_addressed_constants (exp) ...@@ -3943,7 +4074,7 @@ output_addressed_constants (exp)
|| TREE_CODE (constant) == CONSTRUCTOR) || TREE_CODE (constant) == CONSTRUCTOR)
/* No need to do anything here /* No need to do anything here
for addresses of variables or functions. */ for addresses of variables or functions. */
output_constant_def (constant); output_constant_def (constant, 0);
} }
reloc = 1; reloc = 1;
break; break;
...@@ -4757,8 +4888,12 @@ make_decl_one_only (decl) ...@@ -4757,8 +4888,12 @@ make_decl_one_only (decl)
void void
init_varasm_once () init_varasm_once ()
{ {
const_str_htab = htab_create (128, const_str_htab_hash, const_str_htab_eq,
const_str_htab_del);
ggc_add_root (const_hash_table, MAX_HASH_TABLE, sizeof const_hash_table[0], ggc_add_root (const_hash_table, MAX_HASH_TABLE, sizeof const_hash_table[0],
mark_const_hash_entry); mark_const_hash_entry);
ggc_add_root (&const_str_htab, 1, sizeof const_str_htab,
mark_const_str_htab);
ggc_add_string_root (&in_named_name, 1); ggc_add_string_root (&in_named_name, 1);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment