rtl.h (STRING_POOL_ADDRESS_P): Rename to DEFERRED_CONSTANT_P.
authorZack Weinberg <zack@gcc.gnu.org>
Mon, 5 May 2003 21:57:54 +0000 (21:57 +0000)
committerZack Weinberg <zack@gcc.gnu.org>
Mon, 5 May 2003 21:57:54 +0000 (21:57 +0000)
* rtl.h (STRING_POOL_ADDRESS_P): Rename to DEFERRED_CONSTANT_P.
* varasm.c (struct varasm_status): Add deferred_constants field.
(n_deferred_strings): Delete variable.
(n_deferred_constants): New #define.
(struct constant_descriptor_tree): Kill next and label fields.
(const_hash_table, MAX_HASH_TABLE): Delete.
(const_desc_htab): New static variable.
(const_hash): Rename const_desc_hash, and make it fit the
hashtab.h interface.
(const_desc_eq): New.
(const_hash_1, compare_constant): Const-ify arguments.
(build_constant_desc): Set DEFERRED_CONSTANT_P on all new
SYMBOL_REFs.  Clarify comments.  Don't set desc->label.
(output_constant_def): Do the lookup/insert using the
hashtab.h interface.  Don't muck with n_deferred_constants or
DEFERRED_CONSTANT_P here.
Always call maybe_output_constant_def_contents.
(maybe_output_constant_def_contents): Take a pointer to the
descriptor, not the EXP and RTL separately.  Return
immediately if this constant is not deferred.  Defer output of
everything, except writable string constants.  Update
n_deferred_constants here.
(output_constant_def_contents): Now takes just one argument,
an rtx.  Clear DEFERRED_CONSTANT_P here.
(mark_constant_pool): Update for rename of n_deferred_strings.
(mark_constant): Don't clear DEFERRED_CONSTANT_P here.

(init_varasm_status): Clear p->deferred_constants.
(init_varasm_once): Call htab_create_ggc for const_desc_htab.

* gcc.dg/const-elim-1.c, gcc.dg/const-elim-2.c: New testcases.

From-SVN: r66505

gcc/ChangeLog
gcc/rtl.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/const-elim-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/const-elim-2.c [new file with mode: 0644]
gcc/varasm.c

index ed14f650c0df9708e864c6bde6b8023c0be6caf6..6ba41bdceb1e94839a940396f1b69be47bddf76a 100644 (file)
@@ -1,3 +1,35 @@
+2003-05-05  Zack Weinberg  <zack@codesourcery.com>
+
+       * rtl.h (STRING_POOL_ADDRESS_P): Rename to DEFERRED_CONSTANT_P.
+       * varasm.c (struct varasm_status): Add deferred_constants field.
+       (n_deferred_strings): Delete variable.
+       (n_deferred_constants): New #define.
+       (struct constant_descriptor_tree): Kill next and label fields.
+       (const_hash_table, MAX_HASH_TABLE): Delete.
+       (const_desc_htab): New static variable.
+       (const_hash): Rename const_desc_hash, and make it fit the
+       hashtab.h interface.
+       (const_desc_eq): New.
+       (const_hash_1, compare_constant): Const-ify arguments.
+       (build_constant_desc): Set DEFERRED_CONSTANT_P on all new
+       SYMBOL_REFs.  Clarify comments.  Don't set desc->label.
+       (output_constant_def): Do the lookup/insert using the
+       hashtab.h interface.  Don't muck with n_deferred_constants or
+       DEFERRED_CONSTANT_P here.
+       Always call maybe_output_constant_def_contents.
+       (maybe_output_constant_def_contents): Take a pointer to the
+       descriptor, not the EXP and RTL separately.  Return
+       immediately if this constant is not deferred.  Defer output of
+       everything, except writable string constants.  Update
+       n_deferred_constants here.
+       (output_constant_def_contents): Now takes just one argument,
+       an rtx.  Clear DEFERRED_CONSTANT_P here.
+       (mark_constant_pool): Update for rename of n_deferred_strings.
+       (mark_constant): Don't clear DEFERRED_CONSTANT_P here.
+
+       (init_varasm_status): Clear p->deferred_constants.
+       (init_varasm_once): Call htab_create_ggc for const_desc_htab.
+
 2003-05-05  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
        * builtins.c (expand_builtin_stpcpy): Only expand when the length
@@ -5,9 +37,9 @@
 
 2003-05-05  Aldy Hernandez  <aldyh@redhat.com>
 
-        * testsuite/gcc.c-torture/compile/simd-6.c: New.
+       * testsuite/gcc.c-torture/compile/simd-6.c: New.
 
-        * c-typeck.c (digest_init): Handle arrays of vector constants.
+       * c-typeck.c (digest_init): Handle arrays of vector constants.
 
 2003-05-05  Jakub Jelinek  <jakub@redhat.com>
 
 
 2003-05-05  Aldy Hernandez  <aldyh@redhat.com>
 
-        * testsuite/gcc.dg/20030505.c: New.
+       * testsuite/gcc.dg/20030505.c: New.
 
-        * c-typeck.c (convert_for_assignment): Opaque pointers can
-        interconvert.
+       * c-typeck.c (convert_for_assignment): Opaque pointers can
+       interconvert.
 
-        * config/rs6000/rs6000.c: New global opaque_p_V2SI_type_node.
-        (rs6000_init_builtins): Initialize opaque_p_V2SI_type_node.
-        (spe_init_builtins): Rename all pv2si_type_node to
-        opaque_p_V2SI_type_node.
-        Remove declaration of pv2si_type_node.
-        (is_ev64_opaque_type): Accept opaque pointers.
+       * config/rs6000/rs6000.c: New global opaque_p_V2SI_type_node.
+       (rs6000_init_builtins): Initialize opaque_p_V2SI_type_node.
+       (spe_init_builtins): Rename all pv2si_type_node to
+       opaque_p_V2SI_type_node.
+       Remove declaration of pv2si_type_node.
+       (is_ev64_opaque_type): Accept opaque pointers.
 
 2003-05-05  Geoffrey Keating  <geoffk@apple.com>
 
        (rs6000_generate_compare): Use flag_finite_math_only.
        (rs6000_emit_cmove): Handle UNLE.  Support UNEQ under -ffast-math.
        Use HONOR_* rather than flag_unsafe_math_optimizations.  Correct
-       UNGE and GT cases.  Handle UNEQ and LTGT when ! HONOR_NANS.  
+       UNGE and GT cases.  Handle UNEQ and LTGT when ! HONOR_NANS.
 
        * toplev.c (check_global_declarations): Suppress not-used warning
        for volatile variables.
 
 2003-05-05  Olivier Hainque  <hainque@act-europe.fr>
 
-        * expr.c (expand_expr, case BIT_FIELD_REF): Refine the test forcing
-        usage of bitfield instructions for mode1 != BLKmode, only ignoring
-        SLOW_UNALIGNED_ACCESS if the field is not byte aligned. 
-        (store_field): Likewise.
+       * expr.c (expand_expr, case BIT_FIELD_REF): Refine the test forcing
+       usage of bitfield instructions for mode1 != BLKmode, only ignoring
+       SLOW_UNALIGNED_ACCESS if the field is not byte aligned.
+       (store_field): Likewise.
 
 2003-05-05  Aldy Hernandez  <aldyh@redhat.com>
 
-        * config/rs6000/rs6000.c (rs6000_expand_binop_builtin): Add
-        evsubifw to builtins accepting 5-bit unsigned constants.
-        (easy_vector_constant): Return if V1DImode.  Fix typo.
+       * config/rs6000/rs6000.c (rs6000_expand_binop_builtin): Add
+       evsubifw to builtins accepting 5-bit unsigned constants.
+       (easy_vector_constant): Return if V1DImode.  Fix typo.
 
 2003-05-05  Aldy Hernandez  <aldyh@redhat.com>
 
-        * config/rs6000/spe.h: Revert licensing change from last patch.
+       * config/rs6000/spe.h: Revert licensing change from last patch.
 
 2003-05-05  DJ Delorie  <dj@redhat.com>
 
 2003-05-05  Zdenek Dvorak  <rakdver@atrey.karlin.mff.cuni.cz>
 
        * libgcov.c (__gcov_merge_add): Do not use gcov_type when inhibit_libc
-       is defined.     
+       is defined.
 
 2003-05-04  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
index bc6f3929298bc1d096cfbd3a9bfaaf1cbf6e0918..eab41e2918e1e4a2deb54087cf0b177f64393fd6 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -1234,10 +1234,11 @@ do {                                            \
 #define CONSTANT_POOL_ADDRESS_P(RTX)                                   \
   (RTL_FLAG_CHECK1("CONSTANT_POOL_ADDRESS_P", (RTX), SYMBOL_REF)->unchanging)
 
-/* 1 if RTX is a symbol_ref that addresses this function's string constant
-   pool  */
-#define STRING_POOL_ADDRESS_P(RTX)                                     \
-  (RTL_FLAG_CHECK1("STRING_POOL_ADDRESS_P", (RTX), SYMBOL_REF)->frame_related)
+/* 1 if RTX is a symbol_ref that addresses a value in the file's constant
+   pool which has not yet been output.  This information is private to
+   varasm.c.  */
+#define DEFERRED_CONSTANT_P(RTX)                                       \
+  (RTL_FLAG_CHECK1("DEFERRED_CONSTANT_P", (RTX), SYMBOL_REF)->frame_related)
 
 /* Used if RTX is a symbol_ref, for machine-specific purposes.  */
 #define SYMBOL_REF_FLAG(RTX)                                           \
index 90eb31bd8c38e0d6549331e9c5e5fd129b2b24f1..05b06a0b5f8e3eacda4dab5c2098ea7a2ec9bb00 100644 (file)
@@ -1,3 +1,7 @@
+2003-05-05  Zack Weinberg  <zack@codesourcery.com>
+
+       * gcc.dg/const-elim-1.c, gcc.dg/const-elim-2.c: New testcases.
+
 2003-05-05  Jakub Jelinek  <jakub@redhat.com>
 
        * gcc.c-torture/execute/string-opt-18.c (main): Add 3 new tests.
diff --git a/gcc/testsuite/gcc.dg/const-elim-1.c b/gcc/testsuite/gcc.dg/const-elim-1.c
new file mode 100644 (file)
index 0000000..b704408
--- /dev/null
@@ -0,0 +1,48 @@
+/* Verify that constants in memory, referenced only by dead code,
+   are not emitted to the object file.
+   FIXME: Not presently possible to apply -pedantic to code with
+   complex constants in it.  The __extension__ should shut up the
+   warning but doesn't.  (Hard to fix -- the lexer is not aware of
+   the parser's state.)  */
+
+/* { dg-do compile } */
+/* { dg-options "-O2 -std=c99" } */
+/* { dg-final { scan-assembler-not "LC" } } */
+
+#define I (__extension__ 1.0iF)
+
+struct S { int a; double b[2]; void *c; };
+
+extern void use_str(const char *);
+extern void use_S(const struct S *);
+extern void use_cplx(__complex__ double);
+
+static inline int
+returns_23(void) { return 23; }
+
+void
+test1(void)
+{
+       if (returns_23() == 23)
+               return;
+
+       use_str("waltz, nymph, for quick jigs vex bud");
+       use_S(&(const struct S){12, {3.1415, 2.1828}, 0 });
+       use_cplx(3.1415 + 2.1828*I);
+}
+
+void
+test2(void)
+{
+       const char *str = "pack my box with five dozen liquor jugs";
+       const struct S S = { 23, { 1.414, 1.618 }, 0 };
+       const __complex__ double cplx = 1.414 + 1.618*I;
+
+       if (returns_23() == 23)
+               return;
+
+       use_str(str);
+       use_S(&S);
+       use_cplx(cplx);
+}
+
diff --git a/gcc/testsuite/gcc.dg/const-elim-2.c b/gcc/testsuite/gcc.dg/const-elim-2.c
new file mode 100644 (file)
index 0000000..ce55ba1
--- /dev/null
@@ -0,0 +1,10 @@
+/* The string constant in this test case should be emitted exactly once.  */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler-times "hi there" 1 } } */
+
+static inline int returns_23() { return 23; }
+
+const char *test1(void) { if (returns_23()) return 0; return "hi there"; }
+const char *test2(void) { return "hi there"; }
+const char *test3(void) { return "hi there"; }
index a813546666cbe7f4bd58fd84c0b42447d732bc75..1e17a0696516a8d54cc478d9f66a77a89f438c4d 100644 (file)
@@ -96,6 +96,10 @@ struct varasm_status GTY(())
   /* Current offset in constant pool (does not include any machine-specific
      header).  */
   HOST_WIDE_INT x_pool_offset;
+
+  /* Number of tree-constants deferred during the expansion of this
+     function.  */
+  unsigned int deferred_constants;
 };
 
 #define const_rtx_hash_table (cfun->varasm->x_const_rtx_hash_table)
@@ -103,6 +107,7 @@ struct varasm_status GTY(())
 #define first_pool (cfun->varasm->x_first_pool)
 #define last_pool (cfun->varasm->x_last_pool)
 #define pool_offset (cfun->varasm->x_pool_offset)
+#define n_deferred_constants (cfun->varasm->deferred_constants)
 
 /* Number for making the label on the next
    constant that is stored in memory.  */
@@ -138,12 +143,12 @@ static HOST_WIDE_INT const_alias_set;
 static const char *strip_reg_name      PARAMS ((const char *));
 static int contains_pointers_p         PARAMS ((tree));
 static void decode_addr_const          PARAMS ((tree, struct addr_const *));
-static unsigned int const_hash         PARAMS ((tree));
-static unsigned int const_hash_1       PARAMS ((tree));
-static int compare_constant            PARAMS ((tree, tree));
+static hashval_t const_desc_hash       PARAMS ((const void *));
+static int const_desc_eq               PARAMS ((const void *, const void *));
+static hashval_t const_hash_1          PARAMS ((const tree));
+static int compare_constant            PARAMS ((const tree, const 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 output_constant_def_contents  PARAMS ((rtx));
 static void decode_rtx_const           PARAMS ((enum machine_mode, rtx,
                                               struct rtx_const *));
 static unsigned int const_hash_rtx     PARAMS ((enum machine_mode, rtx));
@@ -2143,12 +2148,6 @@ struct rtx_const GTY(())
 
 struct constant_descriptor_tree GTY(())
 {
-  /* More constant_descriptors with the same hash code.  */
-  struct constant_descriptor_tree *next;
-
-  /* The label of the constant.  */
-  const char *label;
-
   /* A MEM for the constant.  */
   rtx rtl;
 
@@ -2156,28 +2155,28 @@ struct constant_descriptor_tree GTY(())
   tree value;
 };
 
-#define MAX_HASH_TABLE 1009
-static GTY(()) struct constant_descriptor_tree *
-  const_hash_table[MAX_HASH_TABLE];
+static GTY((param_is (struct constant_descriptor_tree)))
+     htab_t const_desc_htab;
 
 static struct constant_descriptor_tree * build_constant_desc PARAMS ((tree));
-static unsigned int n_deferred_strings = 0;
+static void maybe_output_constant_def_contents
+    PARAMS ((struct constant_descriptor_tree *, int));
 
 /* Compute a hash code for a constant expression.  */
 
-static unsigned int
-const_hash (exp)
-     tree exp;
+static hashval_t
+const_desc_hash (ptr)
+     const void *ptr;
 {
-  return const_hash_1 (exp) % MAX_HASH_TABLE;
+  return const_hash_1 (((struct constant_descriptor_tree *)ptr)->value);
 }
 
-static unsigned int
+static hashval_t
 const_hash_1 (exp)
-     tree exp;
+     const tree exp;
 {
   const char *p;
-  unsigned int hi;
+  hashval_t hi;
   int len, i;
   enum tree_code code = TREE_CODE (exp);
 
@@ -2198,7 +2197,6 @@ const_hash_1 (exp)
       p = TREE_STRING_POINTER (exp);
       len = TREE_STRING_LENGTH (exp);
       break;
-
     case COMPLEX_CST:
       return (const_hash_1 (TREE_REALPART (exp)) * 5
              + const_hash_1 (TREE_IMAGPART (exp)));
@@ -2272,13 +2270,23 @@ const_hash_1 (exp)
   return hi;
 }
 
+/* Wrapper of compare_constant, for the htab interface.  */
+static int
+const_desc_eq (p1, p2)
+     const void *p1;
+     const void *p2;
+{
+  return compare_constant (((struct constant_descriptor_tree *)p1)->value,
+                          ((struct constant_descriptor_tree *)p2)->value);
+}
+
 /* Compare t1 and t2, and return 1 only if they are known to result in
    the same bit pattern on output.  */
 
 static int
 compare_constant (t1, t2)
-     tree t1;
-     tree t2;
+     const tree t1;
+     const tree t2;
 {
   enum tree_code typecode;
 
@@ -2531,11 +2539,18 @@ build_constant_desc (exp)
   /* 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.  */
+     information.  This call might invalidate our local variable
+     SYMBOL; we can't use it afterward.  */
+
   (*targetm.encode_section_info) (exp, rtl, true);
 
+  /* Descriptors start out deferred; this simplifies the logic in
+     maybe_output_constant_def_contents.  However, we do not bump
+     n_deferred_constants here, because we don't know if we're inside
+     a function and have an n_deferred_constants to bump.  */
+  DEFERRED_CONSTANT_P (XEXP (rtl, 0)) = 1;
+
   desc->rtl = rtl;
-  desc->label = XSTR (XEXP (desc->rtl, 0), 0);
 
   return desc;
 }
@@ -2548,8 +2563,8 @@ build_constant_desc (exp)
    Otherwise, output such a constant in memory
    and generate an rtx for it.
 
-   If DEFER is nonzero, the output of string constants can be deferred
-   and output only if referenced in the function after all optimizations.
+   If DEFER is nonzero, this constant can be deferred and output only
+   if referenced in the function after all optimizations.
 
    The const_hash_table records which constants already have label strings.  */
 
@@ -2558,70 +2573,64 @@ output_constant_def (exp, defer)
      tree exp;
      int defer;
 {
-  int hash;
   struct constant_descriptor_tree *desc;
+  struct constant_descriptor_tree key;
+  void **loc;
 
-  /* 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;
+  /* Look up EXP in the table of constant descriptors.  If we didn't find
+     it, create a new one.  */
+  key.value = exp;
+  loc = htab_find_slot (const_desc_htab, &key, INSERT);
 
+  desc = *loc;
   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)))
-    {
-      /* This string is currently deferred but we need to output it
-        now; mark it no longer deferred.  */
-      STRING_POOL_ADDRESS_P (XEXP (desc->rtl, 0)) = 0;
-      n_deferred_strings--;
-      maybe_output_constant_def_contents (exp, desc->rtl, 0);
+      *loc = desc;
     }
 
+  maybe_output_constant_def_contents (desc, defer);
   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.  */
+/* Subroutine of output_constant_def: Decide whether or not we need to
+   output the constant DESC now, and if so, do it.  */
 static void
-maybe_output_constant_def_contents (exp, rtl, defer)
-     tree exp;
-     rtx rtl;
+maybe_output_constant_def_contents (desc, defer)
+     struct constant_descriptor_tree *desc;
      int defer;
 {
+  rtx symbol = XEXP (desc->rtl, 0);
+
   if (flag_syntax_only)
     return;
 
-  /* Is this a string constant that can be deferred?  */
-  if (defer && TREE_CODE (exp) == STRING_CST && !flag_writable_strings)
+  if (!DEFERRED_CONSTANT_P (symbol))
+    /* Already output; don't do it again.  */
+    return;
+
+  /* The only constants that cannot safely be deferred, assuming the
+     context allows it, are strings under flag_writable_strings.  */
+  if (defer && (TREE_CODE (desc->value) != STRING_CST
+               || !flag_writable_strings))
     {
-      STRING_POOL_ADDRESS_P (XEXP (rtl, 0)) = 1;
-      n_deferred_strings++;
+      if (cfun)
+       n_deferred_constants++;
       return;
     }
 
-  output_constant_def_contents (exp, XSTR (XEXP (rtl, 0), 0));
+  output_constant_def_contents (symbol);
 }
 
-/* Now output assembler code to define the label for EXP,
-   and follow it with the data of EXP.  */
+/* We must output the constant data referred to by SYMBOL; do so.  */
 
 static void
-output_constant_def_contents (exp, label)
-     tree exp;
-     const char *label;
+output_constant_def_contents (symbol)
+     rtx symbol;
 {
+  tree exp = SYMBOL_REF_DECL (symbol);
+  const char *label = XSTR (symbol, 0);
+
   /* Make sure any other constants whose addresses appear in EXP
      are assigned label numbers.  */
   int reloc = output_addressed_constants (exp);
@@ -2632,6 +2641,9 @@ output_constant_def_contents (exp, label)
   align = CONSTANT_ALIGNMENT (exp, align);
 #endif
 
+  /* We are no longer deferring this constant.  */
+  DEFERRED_CONSTANT_P (symbol) = 0;
+
   if (IN_NAMED_SECTION (exp))
     named_section (exp, NULL, reloc);
   else
@@ -2715,6 +2727,7 @@ init_varasm_status (f)
 
   p->x_first_pool = p->x_last_pool = 0;
   p->x_pool_offset = 0;
+  p->deferred_constants = 0;
 }
 \f
 
@@ -3329,8 +3342,8 @@ output_constant_pool (fnname, fndecl)
 }
 
 /* Look through the instructions for this function, and mark all the
-   entries in the constant pool which are actually being used.
-   Emit used deferred strings.  */
+   entries in the constant pool which are actually being used.  Emit
+   deferred constants which have indeed been used.  */
 
 static void
 mark_constant_pool ()
@@ -3339,7 +3352,7 @@ mark_constant_pool ()
   rtx link;
   struct pool_constant *pool;
 
-  if (first_pool == 0 && n_deferred_strings == 0)
+  if (first_pool == 0 && n_deferred_constants == 0)
     return;
 
   for (pool = first_pool; pool; pool = pool->next)
@@ -3453,11 +3466,10 @@ mark_constant (current_rtx, data)
          else
            return -1;
        }
-      else if (STRING_POOL_ADDRESS_P (x))
+      else if (DEFERRED_CONSTANT_P (x))
        {
-         STRING_POOL_ADDRESS_P (x) = 0;
-         n_deferred_strings--;
-         output_constant_def_contents (SYMBOL_REF_DECL (x), XSTR (x, 0));
+         n_deferred_constants--;
+         output_constant_def_contents (x);
        }
     }
   return 0;
@@ -4544,6 +4556,8 @@ init_varasm_once ()
 {
   in_named_htab = htab_create_ggc (31, in_named_entry_hash,
                                   in_named_entry_eq, NULL);
+  const_desc_htab = htab_create_ggc (1009, const_desc_hash,
+                                    const_desc_eq, NULL);
 
   const_alias_set = new_alias_set ();
 }