varasm.c (struct deferred_string): New structure.
authorJakub Jelinek <jakub@redhat.com>
Tue, 14 Nov 2000 17:37:19 +0000 (18:37 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 14 Nov 2000 17:37:19 +0000 (18:37 +0100)
* 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

gcc/ChangeLog
gcc/expr.c
gcc/rtl.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/20000801-4.c
gcc/varasm.c

index 7f01f9e33c0128ddd92bfa4742ef31ce5cbcbe48..e0dd9f7e968add6e5136d7dff748654b6d7f697e 100644 (file)
@@ -1,3 +1,22 @@
+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>
 
        * optabs.c (expand_complex_ab):: Use overflow-trapping optabs for
index b28db7f67b8cc3b8bd10b9d1239bbaab54422b3d..35ccf0359a9a0446c6ae9e9dd65cda2a212b2ddc 100644 (file)
@@ -6143,7 +6143,7 @@ expand_expr (exp, target, tmode, modifier)
     case COMPLEX_CST:
     case STRING_CST:
       if (! TREE_CST_RTL (exp))
-       output_constant_def (exp);
+       output_constant_def (exp, 1);
 
       /* TREE_CST_RTL probably contains a constant address.
         On RISC machines where a constant address isn't valid,
@@ -6456,7 +6456,7 @@ expand_expr (exp, target, tmode, modifier)
                        && ! mostly_zeros_p (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
              && modifier != EXPAND_INITIALIZER
index b25c8abee807eae98cd8419426fc32a6d13ba689..762226cd3d49a5d97276599920a24660eec4450e 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -168,7 +168,9 @@ typedef struct rtx_def
      either changing how we compute the frame address or saving and
      restoring registers in the prologue and epilogue.
      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;
 
   /* 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];
 /* 1 in a SYMBOL_REF if it addresses this function's constants pool.  */
 #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.  */
 #define SYMBOL_REF_FLAG(RTX) ((RTX)->volatil)
 
@@ -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_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 union tree_node *make_tree      PARAMS ((union tree_node *, rtx));
 
index 16e51fde621b63eb8a954896693ae0c5c99e23be..ab2666689a4a0a7931863d1a7e6b507ec55ce725 100644 (file)
@@ -1,3 +1,8 @@
+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>
 
        * gcc.dg/wtr-label-1.c, gcc.dg/990214-1.c: Add semicolons after
index 06d2ffbf271f118d8be47e03b6db7668f1600e24..dd6227d05fb9a427e9254e06a36830cf9ff569dc 100644 (file)
@@ -14,11 +14,14 @@ foo (void)
   return 0 == s[1];
 }
 
+char *t;
+
 int
 main (void)
 {
   {
     char s[] = "x";
+    t = s;
   }
   if (foo ())
     exit (0);
index b4a8c2e976e2a187c44c0865244f5708ffa3a426..0fc4ea8aa4a370dcf6721f55725b68ea0a73a8a4 100644 (file)
@@ -44,6 +44,7 @@ Boston, MA 02111-1307, USA.  */
 #include "dbxout.h"
 #include "sdbout.h"
 #include "obstack.h"
+#include "hashtab.h"
 #include "c-pragma.h"
 #include "ggc.h"
 #include "tm_p.h"
@@ -185,6 +186,11 @@ static void asm_output_aligned_bss PARAMS ((FILE *, tree, const char *,
 #endif /* BSS_SECTION_ASM_OP */
 static void mark_pool_constant          PARAMS ((struct pool_constant *));
 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));
 \f
 static enum in_section { no_section, in_text, in_data, in_named
@@ -2342,6 +2348,17 @@ struct constant_descriptor
 #define MAX_HASH_TABLE 1009
 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.  */
 
 static void 
@@ -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.  */
 
 static int
@@ -3056,18 +3125,25 @@ copy_constant (exp)
    Otherwise, output such a constant in memory (or defer it for later)
    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 const_hash_table records which constants already have label strings.  */
 
 rtx
-output_constant_def (exp)
+output_constant_def (exp, defer)
      tree exp;
+     int defer;
 {
   register int hash;
   register struct constant_descriptor *desc;
+  struct deferred_string **defstr;
   char label[256];
   int reloc;
   int found = 1;
+  int after_function = 0;
+  int labelno = -1;
 
   if (TREE_CST_RTL (exp))
     return TREE_CST_RTL (exp);
@@ -3095,7 +3171,8 @@ output_constant_def (exp)
         future calls to this function to find.  */
          
       /* 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->next = const_hash_table[hash];
@@ -3121,18 +3198,34 @@ output_constant_def (exp)
   ENCODE_SECTION_INFO (exp);
 #endif
 
+#ifdef CONSTANT_AFTER_FUNCTION_P
+  if (current_function_decl != 0
+      && CONSTANT_AFTER_FUNCTION_P (exp))
+    after_function = 1;
+#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)
     {
-      int after_function = 0;
-
-#ifdef CONSTANT_AFTER_FUNCTION_P
-      if (current_function_decl != 0
-         && CONSTANT_AFTER_FUNCTION_P (exp))
-       after_function = 1;
-#endif
-
       if (defer_addressed_constants_flag || after_function)
        {
          struct deferred_constant *p;
@@ -3140,7 +3233,7 @@ output_constant_def (exp)
 
          p->exp = copy_constant (exp);
          p->reloc = reloc;
-         p->labelno = const_labelno++;
+         p->labelno = labelno;
          if (after_function)
            {
              p->next = after_function_constants;
@@ -3156,8 +3249,30 @@ output_constant_def (exp)
        {
          /* Do no output if -fsyntax-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 ()
   register rtx insn;
   struct pool_constant *pool;
 
-  if (first_pool == 0)
+  if (first_pool == 0 && htab_elements (const_str_htab) == 0)
     return;
 
   for (pool = first_pool; pool; pool = pool->next)
@@ -3867,6 +3982,22 @@ mark_constants (x)
     {
       if (CONSTANT_POOL_ADDRESS_P (x))
        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;
     }
   /* Never search inside a CONST_DOUBLE, because CONST_DOUBLE_MEM may be
@@ -3943,7 +4074,7 @@ output_addressed_constants (exp)
            || TREE_CODE (constant) == CONSTRUCTOR)
          /* No need to do anything here
             for addresses of variables or functions.  */
-         output_constant_def (constant);
+         output_constant_def (constant, 0);
       }
       reloc = 1;
       break;
@@ -4757,8 +4888,12 @@ make_decl_one_only (decl)
 void
 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],
                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);
 }