public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Re: [PCH] constant pools rewrite
@ 2002-02-19 14:06 Joern Rennecke
  0 siblings, 0 replies; 7+ messages in thread
From: Joern Rennecke @ 2002-02-19 14:06 UTC (permalink / raw)
  To: Richard.Earnshaw; +Cc: gcc-patches

> The SH code came first; the original implementation on the ARM was a copy 
> I made of that.  Since then the ARM variant has been re-written at least a 
> couple of times.  The current incarnation should be fairly MI and supports 
> both forward and back-ward relative loads, merging of common entries, 
> hiding of pools behind branches (when possible) and sorting of the entries 
> to increase the degree of freedom of location of the pool when some 
> instructions have a more limited range than others.

> It would be an interesting project to see if that code could be cleaned up 
> and made into an completely MI file that was used by the other ports 
> requiring this sort of constant pool.

It would be quite some task to extend the current arm implementation to
fir the SH:
The SH port allows linker relaxation to change a constant load & register
indirect function call to be changed into a pc-relative function call if
the callee is in range; in that case, the constant pool entry is deleted.
Hence we most be able to keep track of constant pool entries that might be
deleted by linker relaxations.
SH3E and SH4 don't allow offsets in memory accesses to load floating point
registers; hence, the address is first loaded into r0. This load can be shared
for consecutive floating point loads without intervening r0 usage, by using
post-increment addressing.
Moreover, the SH code has to deal with exotic conditions where a mova
might get out of range by careless placement of the constant table, and
ones where the mova gets out of range no matter what, and must be fixed
up.
And, finally, labels and barriers come with different alignments, and we
have to keep track of their contribution to the code size, and we want to
prefer barriers with larger alignment to place to constant pools after them.

-- 
--------------------------
SuperH
2430 Aztec West / Almondsbury / BRISTOL / BS32 4AQ
T:+44 1454 462330

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PCH] constant pools rewrite
  2002-02-18 21:44 ` Jim Wilson
@ 2002-02-19  3:52   ` Richard Earnshaw
  0 siblings, 0 replies; 7+ messages in thread
From: Richard Earnshaw @ 2002-02-19  3:52 UTC (permalink / raw)
  To: Jim Wilson; +Cc: Geoffrey Keating, gcc-patches, Richard.Earnshaw


> Some targets have limited register sets and limited addressing modes.  Thumb
> and mips16 are good examples of this.  It is so difficult to reach a per
> file constant pool that it is impractical.  You have to use per function
> constant pools, and you have to make sure that the constant pools go in the
> same section as the function.  In some cases, not even this is good enough,
> because if the function is too big, you won't be able to reach it unless
> it is inline.  Again, thumb and mips16 have this problem.  Since the generic
> constant pool code doesn't support inline constant pools, the arm and mips
> backends need their own code.  I don't remember which came first, but I'm
> pretty sure one was originally a copy of the other.  They have probably
> diverged since then.  There may be other targets with a copy of this code 
> also.


The SH code came first; the original implementation on the ARM was a copy 
I made of that.  Since then the ARM variant has been re-written at least a 
couple of times.  The current incarnation should be fairly MI and supports 
both forward and back-ward relative loads, merging of common entries, 
hiding of pools behind branches (when possible) and sorting of the entries 
to increase the degree of freedom of location of the pool when some 
instructions have a more limited range than others.

It would be an interesting project to see if that code could be cleaned up 
and made into an completely MI file that was used by the other ports 
requiring this sort of constant pool.

R.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PCH] constant pools rewrite
  2002-02-18  9:57 Geoffrey Keating
  2002-02-18 10:07 ` Joseph S. Myers
  2002-02-18 16:32 ` Richard Henderson
@ 2002-02-18 21:44 ` Jim Wilson
  2002-02-19  3:52   ` Richard Earnshaw
  2 siblings, 1 reply; 7+ messages in thread
From: Jim Wilson @ 2002-02-18 21:44 UTC (permalink / raw)
  To: Geoffrey Keating; +Cc: gcc-patches

>- Work out why the RTX constant pool is per-function, when the tree
>  constant pool is per-file.

Suppose that every function gets put into its own section, and then the
linker drops 90% of the sections as unused.  This can happen for C++ code
that automatically uses .gnu.linkonce sections.  This can happen for other
code if -ffunction-sections is used.  With per function constant pools,
it is obvious which ones to keep and drop.  With a per file constant pool,
you have to keep everything.  This can result in larger executables.  That
will likely be rare, but it is a tradeoff to keep in mind.

There are other similar cases, for instance, inline functions.  If an inline
function needs a constant pool entry, then it would be nice to only emit
it if the inline function is used, either via inlining or via a static
copy of it.  This is easier to control with per function constant pools.

There was also an issue with nested function, though it may not be relevant
anymore.  Nested functions used to be on their own obstack, which was freed
at the end of the current function, and hence we could not put any rtl from
a nested function into a per file constant pool, it had to be in a per function
constant pool.

>- Work out why the ARM backend has its own constant pool handling, and
>  merge that functionality back into the middle-end.  I'm sure lots of
>  ports could benefit from it.

Some targets have limited register sets and limited addressing modes.  Thumb
and mips16 are good examples of this.  It is so difficult to reach a per
file constant pool that it is impractical.  You have to use per function
constant pools, and you have to make sure that the constant pools go in the
same section as the function.  In some cases, not even this is good enough,
because if the function is too big, you won't be able to reach it unless
it is inline.  Again, thumb and mips16 have this problem.  Since the generic
constant pool code doesn't support inline constant pools, the arm and mips
backends need their own code.  I don't remember which came first, but I'm
pretty sure one was originally a copy of the other.  They have probably
diverged since then.  There may be other targets with a copy of this code also.

Jim


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PCH] constant pools rewrite
  2002-02-18 16:32 ` Richard Henderson
@ 2002-02-18 18:56   ` Geoff Keating
  0 siblings, 0 replies; 7+ messages in thread
From: Geoff Keating @ 2002-02-18 18:56 UTC (permalink / raw)
  To: rth; +Cc: gcc-patches

> Date: Mon, 18 Feb 2002 16:19:47 -0800
> From: Richard Henderson <rth@redhat.com>
> Cc: gcc-patches@gcc.gnu.org
> Mail-Followup-To: Richard Henderson <rth@redhat.com>,
> 	Geoffrey Keating <geoffk@cygnus.com>, gcc-patches@gcc.gnu.org
> Content-Disposition: inline
> User-Agent: Mutt/1.2.5.1i
> 
> On Mon, Feb 18, 2002 at 09:09:57AM -0800, Geoffrey Keating wrote:
> > Some future work, which I don't have time for right now but which
> > might be interesting for someone in the future:
> 
> Given that you poked at this at all, I think it is a mistake
> that you didn't simply rip out all of the rtx_const nonsense.
> This is left over from when we had per-function obstacks, and
> should be irrelevant with GC.

You know, now that I look at it, you're right; it should all go.
(At least I removed the much more horrible stuff for trees.)

> > - Work out why the RTX constant pool is per-function, when the tree
> >   constant pool is per-file.  If (as I suspect) there's no real
> >   reason, make the RTX constant pool per-file.  Delete the code in the
> >   rs6000 backend that creates its own per-file RTX constant pool.
> 
> Because some ports ...
> 
> > - Work out why the ARM backend has its own constant pool handling, and
> >   merge that functionality back into the middle-end.  I'm sure lots of
> >   ports could benefit from it.
> 
> ... require constant pools *within* the function, so that 
> they can address them with 8-bit pc-relative relocs.
> 
> See arm, mcore, sh, s390 to name a few.

I am enlightened.

> But for everyone else, we should indeed be using per-file pools.

Well, something for future work.  I think a bit more design would be
helpful here, there's a bunch of things that would be nice to do with
constant pools that we don't do (or do only for some port but not in
all the places where it would be helpful).

-- 
- Geoffrey Keating <geoffk@geoffk.org> <geoffk@redhat.com>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PCH] constant pools rewrite
  2002-02-18  9:57 Geoffrey Keating
  2002-02-18 10:07 ` Joseph S. Myers
@ 2002-02-18 16:32 ` Richard Henderson
  2002-02-18 18:56   ` Geoff Keating
  2002-02-18 21:44 ` Jim Wilson
  2 siblings, 1 reply; 7+ messages in thread
From: Richard Henderson @ 2002-02-18 16:32 UTC (permalink / raw)
  To: Geoffrey Keating; +Cc: gcc-patches

On Mon, Feb 18, 2002 at 09:09:57AM -0800, Geoffrey Keating wrote:
> Some future work, which I don't have time for right now but which
> might be interesting for someone in the future:

Given that you poked at this at all, I think it is a mistake
that you didn't simply rip out all of the rtx_const nonsense.
This is left over from when we had per-function obstacks, and
should be irrelevant with GC.

> - Work out why the RTX constant pool is per-function, when the tree
>   constant pool is per-file.  If (as I suspect) there's no real
>   reason, make the RTX constant pool per-file.  Delete the code in the
>   rs6000 backend that creates its own per-file RTX constant pool.

Because some ports ...

> - Work out why the ARM backend has its own constant pool handling, and
>   merge that functionality back into the middle-end.  I'm sure lots of
>   ports could benefit from it.

... require constant pools *within* the function, so that 
they can address them with 8-bit pc-relative relocs.

See arm, mcore, sh, s390 to name a few.

But for everyone else, we should indeed be using per-file pools.


r~

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PCH] constant pools rewrite
  2002-02-18  9:57 Geoffrey Keating
@ 2002-02-18 10:07 ` Joseph S. Myers
  2002-02-18 16:32 ` Richard Henderson
  2002-02-18 21:44 ` Jim Wilson
  2 siblings, 0 replies; 7+ messages in thread
From: Joseph S. Myers @ 2002-02-18 10:07 UTC (permalink / raw)
  To: Geoffrey Keating; +Cc: gcc-patches

On Mon, 18 Feb 2002, Geoffrey Keating wrote:

> Some future work, which I don't have time for right now but which
> might be interesting for someone in the future:

Can you add these to the projects list projects/index.html?

-- 
Joseph S. Myers
jsm28@cam.ac.uk

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PCH] constant pools rewrite
@ 2002-02-18  9:57 Geoffrey Keating
  2002-02-18 10:07 ` Joseph S. Myers
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Geoffrey Keating @ 2002-02-18  9:57 UTC (permalink / raw)
  To: gcc-patches


This patch rewrites the way varasm.c handles the constant pools.

I won't go into all the horrible things I found.  I will merely note
that compare_constant_1 had this code:

-		  if (memcmp ((char *) &TREE_PURPOSE (link), p,
-			    sizeof TREE_PURPOSE (link)))
-		    return 0;

which is comparing two tree pointers.  The pointer at *(tree *)p is
not marked for GC and, as far as I can see, is not guaranteed to be
saved by anything else.  So this test could theoretically succeed even
though the nodes are not the same, given the right combination of
ggc_alloc and ggc_collect calls, which would cause a silent
code-generation error.  I doubt this has ever happened, since all the
requirements are very rare, but the possibility was there.

Some future work, which I don't have time for right now but which
might be interesting for someone in the future:

- Sort out which of these routines belongs to which of the two
  constant-pool implementations and separate them in the file.

- Work out why the RTX constant pool is per-function, when the tree
  constant pool is per-file.  If (as I suspect) there's no real
  reason, make the RTX constant pool per-file.  Delete the code in the
  rs6000 backend that creates its own per-file RTX constant pool.

- Work out why the ARM backend has its own constant pool handling, and
  merge that functionality back into the middle-end.  I'm sure lots of
  ports could benefit from it.

Tested on i686-linux with --enable-checking=tree,misc,gc,gcac.

-- 
Geoff Keating <geoffk@redhat.com>

===File ~/patches/pchbranch-constpool.patch=================
Index: ChangeLog
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ChangeLog,v
retrieving revision 1.12690.2.5
diff -p -u -p -r1.12690.2.5 ChangeLog
--- ChangeLog	2002/02/17 01:12:55	1.12690.2.5
+++ ChangeLog	2002/02/18 03:56:52
@@ -1,3 +1,33 @@
+2002-02-15  Geoffrey Keating  <geoffk@redhat.com>
+
+	* varasm.c: Don't include obstack.h.
+	(struct varasm_status): x_const_rtx_hash_table is a hash of rtxes.
+	(struct rtx_const): Give substructures names, improve formatting.
+	(struct constant_descriptor): Delete.
+	(struct constant_descriptor_tree): New, based on constant_descriptor.
+	(const_hash_table): Is a hash table of trees.
+	(mark_const_hash_entry): Is used for hashes of trees.  Mark
+	constant_descriptor_tree structure.
+	(mark_const_str_htab_1): Mark deferred_string structure.
+	(compare_constant): Rewrite to compare trees.
+	(compare_constant_1): Delete.
+	(record_constant): Delete.
+	(record_constant_1): Delete.
+	(output_constant_def): Use struct constant_descriptor_tree.
+	Don't duplicate trees twice.
+	(struct constant_descriptor_rtx): New.
+	(struct pool_constant): Used for rtx constants.
+	(init_varasm_status): Update for change to struct varasm_status.
+	(mark_varasm_status): Likewise.
+	(free_varasm_status): Delete.
+	(compare_constant_rtx): Rewrite to handle constant_descriptor_rtx.
+	(record_constant_rtx): Likewise.
+	(mem_for_const_double): Update to use struct constant_descriptor_rtx.
+	(force_const_mem): Likewise.
+	* Makefile.in (varasm.o): Doesn't depend on obstack.h.
+	* function.c (free_after_compilation): Don't use free_varasm_status.
+	* function.h: Don't prototype free_varasm_status.
+
 2002-02-16  Geoffrey Keating  <geoffk@redhat.com>
 
 	* ggc-common.c (ggc_realloc): New function.
Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.822.2.1
diff -p -u -p -r1.822.2.1 Makefile.in
--- Makefile.in	2002/02/13 23:34:50	1.822.2.1
+++ Makefile.in	2002/02/18 03:56:53
@@ -1369,7 +1369,7 @@ errors.o : errors.c $(GCONFIG_H) $(SYSTE
 	$(CC) -c $(ALL_CFLAGS) -DGENERATOR_FILE $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
 
 varasm.o : varasm.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) flags.h \
-   function.h $(EXPR_H) hard-reg-set.h $(REGS_H) $(OBSTACK_H) \
+   function.h $(EXPR_H) hard-reg-set.h $(REGS_H) \
    output.h c-pragma.h toplev.h xcoffout.h debug.h $(GGC_H) $(TM_P_H) \
    $(HASHTAB_H) $(TARGET_H) langhooks.h
 function.o : function.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
Index: function.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/function.c,v
retrieving revision 1.341.4.3
diff -p -u -p -r1.341.4.3 function.c
--- function.c	2002/02/17 01:13:04	1.341.4.3
+++ function.c	2002/02/18 03:56:55
@@ -438,7 +438,7 @@ free_after_compilation (f)
   free_eh_status (f);
   f->expr = NULL;
   f->emit = NULL;
-  free_varasm_status (f);
+  f->varasm = NULL;
 
   if (free_machine_status)
     (*free_machine_status) (f);
Index: function.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/function.h,v
retrieving revision 1.75.4.2
diff -p -u -p -r1.75.4.2 function.h
--- function.h	2002/02/17 01:13:04	1.75.4.2
+++ function.h	2002/02/18 03:56:55
@@ -586,7 +586,6 @@ extern void free_after_parsing		PARAMS (
 extern void free_after_compilation	PARAMS ((struct function *));
 
 extern void init_varasm_status		PARAMS ((struct function *));
-extern void free_varasm_status		PARAMS ((struct function *));
 extern void free_eh_status		PARAMS ((struct function *));
 
 extern rtx get_first_block_beg		PARAMS ((void));
Index: varasm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/varasm.c,v
retrieving revision 1.243.2.2
diff -p -u -p -r1.243.2.2 varasm.c
--- varasm.c	2002/02/14 19:35:35	1.243.2.2
+++ varasm.c	2002/02/18 03:56:56
@@ -39,7 +39,6 @@ Software Foundation, 59 Temple Place - S
 #include "output.h"
 #include "real.h"
 #include "toplev.h"
-#include "obstack.h"
 #include "hashtab.h"
 #include "c-pragma.h"
 #include "ggc.h"
@@ -65,11 +64,8 @@ Software Foundation, 59 Temple Place - S
 const char *first_global_object_name;
 const char *weak_global_object_name;
 
-extern struct obstack permanent_obstack;
-#define obstack_chunk_alloc xmalloc
-
 struct addr_const;
-struct constant_descriptor;
+struct constant_descriptor_rtx;
 struct rtx_const;
 struct pool_constant;
 
@@ -85,11 +81,12 @@ struct varasm_status
      This pool of constants is reinitialized for each function
      so each function gets its own constants-pool that comes right before
      it.  */
-  struct constant_descriptor **x_const_rtx_hash_table;
+  struct constant_descriptor_rtx ** x_const_rtx_hash_table;
   struct pool_constant **x_const_rtx_sym_hash_table;
 
   /* Pointers to first and last constant in pool.  */
-  struct pool_constant *x_first_pool, *x_last_pool;
+  struct pool_constant *x_first_pool;
+  struct pool_constant *x_last_pool;
 
   /* Current offset in constant pool (does not include any machine-specific
      header).  */
@@ -142,20 +139,16 @@ static const char *strip_reg_name	PARAMS
 static int contains_pointers_p		PARAMS ((tree));
 static void decode_addr_const		PARAMS ((tree, struct addr_const *));
 static int const_hash			PARAMS ((tree));
-static int compare_constant		PARAMS ((tree,
-					       struct constant_descriptor *));
-static const unsigned char *compare_constant_1  PARAMS ((tree, const unsigned char *));
-static struct constant_descriptor *record_constant PARAMS ((tree));
-static void record_constant_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 int const_hash_rtx		PARAMS ((enum machine_mode, rtx));
-static int compare_constant_rtx		PARAMS ((enum machine_mode, rtx,
-					       struct constant_descriptor *));
-static struct constant_descriptor *record_constant_rtx PARAMS ((enum machine_mode,
-							      rtx));
+static int compare_constant_rtx	
+  PARAMS ((enum machine_mode, rtx, struct constant_descriptor_rtx *));
+static struct constant_descriptor_rtx * record_constant_rtx 
+  PARAMS ((enum machine_mode, rtx));
 static struct pool_constant *find_pool_constant PARAMS ((struct function *, rtx));
 static void mark_constant_pool		PARAMS ((void));
 static void mark_constants		PARAMS ((rtx));
@@ -2387,42 +2380,38 @@ struct rtx_const
 {
   ENUM_BITFIELD(kind) kind : 16;
   ENUM_BITFIELD(machine_mode) mode : 16;
-  union {
+  union rtx_const_un {
     union real_extract du;
     struct addr_const addr;
-    struct {HOST_WIDE_INT high, low;} di;
+    struct rtx_const_u_di { 
+      HOST_WIDE_INT high;
+      HOST_WIDE_INT low; 
+    } di;
   } un;
 };
 
 /* Uniquize all constants that appear in memory.
    Each constant in memory thus far output is recorded
-   in `const_hash_table' with a `struct constant_descriptor'
-   that contains a polish representation of the value of
-   the constant.
-
-   We cannot store the trees in the hash table
-   because the trees may be temporary.  */
+   in `const_hash_table'.  */
 
-struct constant_descriptor
+struct constant_descriptor_tree
 {
-  struct constant_descriptor *next;
+  /* 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;
-  /* Make sure the data is reasonably aligned.  */
-  union
-  {
-    unsigned char contents[1];
-#ifdef HAVE_LONG_DOUBLE
-    long double d;
-#else
-    double d;
-#endif
-  } u;
+
+  /* The value of the constant.  */
+  tree value;
 };
 
 #define HASHBITS 30
 #define MAX_HASH_TABLE 1009
-static struct constant_descriptor *const_hash_table[MAX_HASH_TABLE];
+static struct constant_descriptor_tree *const_hash_table[MAX_HASH_TABLE];
 
 /* 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
@@ -2446,11 +2435,14 @@ static void
 mark_const_hash_entry (ptr)
      void *ptr;
 {
-  struct constant_descriptor *desc = * (struct constant_descriptor **) ptr;
+  struct constant_descriptor_tree *desc;
+  desc = * (struct constant_descriptor_tree **) ptr;
 
   while (desc)
     {
+      ggc_mark (desc);
       ggc_mark_rtx (desc->rtl);
+      ggc_mark_tree (desc->value);
       desc = desc->next;
     }
 }
@@ -2463,6 +2455,7 @@ mark_const_str_htab_1 (x, data)
      void **x;
      void *data ATTRIBUTE_UNUSED;
 {
+  ggc_mark (*x);
   ggc_mark_tree (((struct deferred_string *) *x)->exp);
   return 1;
 }
@@ -2504,7 +2497,7 @@ static void
 const_str_htab_del (dfsp)
     void *dfsp;
 {
-  free (dfsp);
+  /* No-op.  */
 }
 
 /* Compute a hash code for a constant expression.  */
@@ -2625,457 +2618,158 @@ const_hash (exp)
   hi %= MAX_HASH_TABLE;
   return hi;
 }
-\f
-/* Compare a constant expression EXP with a constant-descriptor DESC.
-   Return 1 if DESC describes a constant with the same value as EXP.  */
-
-static int
-compare_constant (exp, desc)
-     tree exp;
-     struct constant_descriptor *desc;
-{
-  return 0 != compare_constant_1 (exp, desc->u.contents);
-}
 
-/* Compare constant expression EXP with a substring P of a constant descriptor.
-   If they match, return a pointer to the end of the substring matched.
-   If they do not match, return 0.
+/* Compare t1 and t2, and return 1 only if they are known to result in
+   the same bit pattern on output.  */
 
-   Since descriptors are written in polish prefix notation,
-   this function can be used recursively to test one operand of EXP
-   against a subdescriptor, and if it succeeds it returns the
-   address of the subdescriptor for the next operand.  */
-
-static const unsigned char *
-compare_constant_1 (exp, p)
-     tree exp;
-     const unsigned char *p;
-{
-  const unsigned char *strp;
-  int len;
-  enum tree_code code = TREE_CODE (exp);
-
-  if (code != (enum tree_code) *p++)
+static int
+compare_constant (t1, t2)
+     tree t1;
+     tree t2;
+{
+  enum tree_code typecode;
+
+  if (t1 == NULL_TREE)
+    return t2 == NULL_TREE;
+  if (t2 == NULL_TREE)
     return 0;
 
-  /* Either set STRP, P and LEN to pointers and length to compare and exit the
-     switch, or return the result of the comparison.  */
+  if (TREE_CODE (t1) != TREE_CODE (t2))
+    return 0;
 
-  switch (code)
+  switch (TREE_CODE (t1))
     {
     case INTEGER_CST:
       /* Integer constants are the same only if the same width of type.  */
-      if (*p++ != TYPE_PRECISION (TREE_TYPE (exp)))
+      if (TYPE_PRECISION (TREE_TYPE (t1)) != TYPE_PRECISION (TREE_TYPE (t2)))
 	return 0;
-
-      strp = (unsigned char *) &TREE_INT_CST (exp);
-      len = sizeof TREE_INT_CST (exp);
-      break;
+      return tree_int_cst_equal (t1, t2);
 
     case REAL_CST:
       /* Real constants are the same only if the same width of type.  */
-      if (*p++ != TYPE_PRECISION (TREE_TYPE (exp)))
+      if (TYPE_PRECISION (TREE_TYPE (t1)) != TYPE_PRECISION (TREE_TYPE (t2)))
 	return 0;
 
-      strp = (unsigned char *) &TREE_REAL_CST (exp);
-      len = sizeof TREE_REAL_CST (exp);
-      break;
+      return REAL_VALUES_IDENTICAL (TREE_REAL_CST (t1), TREE_REAL_CST (t2));
 
     case STRING_CST:
       if (flag_writable_strings)
 	return 0;
 
-      if ((enum machine_mode) *p++ != TYPE_MODE (TREE_TYPE (exp)))
+      if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2)))
 	return 0;
 
-      strp = (const unsigned char *) TREE_STRING_POINTER (exp);
-      len = TREE_STRING_LENGTH (exp);
-      if (memcmp ((char *) &TREE_STRING_LENGTH (exp), p,
-		  sizeof TREE_STRING_LENGTH (exp)))
-	return 0;
-
-      p += sizeof TREE_STRING_LENGTH (exp);
-      break;
+      return (TREE_STRING_LENGTH (t1) == TREE_STRING_LENGTH (t2)
+	      && ! memcmp (TREE_STRING_POINTER (t1), TREE_STRING_POINTER (t2),
+			 TREE_STRING_LENGTH (t1)));
 
     case COMPLEX_CST:
-      p = compare_constant_1 (TREE_REALPART (exp), p);
-      if (p == 0)
-	return 0;
+      return (compare_constant (TREE_REALPART (t1), TREE_REALPART (t2))
+	      && compare_constant (TREE_IMAGPART (t1), TREE_IMAGPART (t2)));
 
-      return compare_constant_1 (TREE_IMAGPART (exp), p);
-
     case CONSTRUCTOR:
-      if (TREE_CODE (TREE_TYPE (exp)) == SET_TYPE)
-	{
-	  int xlen = len = int_size_in_bytes (TREE_TYPE (exp));
-	  unsigned char *tmp = (unsigned char *) alloca (len);
-
-	  get_set_constructor_bytes (exp, tmp, len);
-	  strp = (unsigned char *) tmp;
-	  if (memcmp ((char *) &xlen, p, sizeof xlen))
-	    return 0;
+      typecode = TREE_CODE (TREE_TYPE (t1));
+      if (typecode != TREE_CODE (TREE_TYPE (t2)))
+	return 0;
 
-	  p += sizeof xlen;
-	  break;
-	}
-      else
+      if (typecode == SET_TYPE)
 	{
-	  tree link;
-	  int length = list_length (CONSTRUCTOR_ELTS (exp));
-	  tree type;
-	  enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
-	  int have_purpose = 0;
+	  int len = int_size_in_bytes (TREE_TYPE (t2));
+	  unsigned char *tmp1, *tmp2;
 
-	  for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
-	    if (TREE_PURPOSE (link))
-	      have_purpose = 1;
-
-	  if (memcmp ((char *) &length, p, sizeof length))
+	  if (int_size_in_bytes (TREE_TYPE (t1)) != len)
 	    return 0;
 
-	  p += sizeof length;
+	  tmp1 = (unsigned char *) alloca (len);
+	  tmp2 = (unsigned char *) alloca (len);
 
-	  /* For record constructors, insist that the types match.
-	     For arrays, just verify both constructors are for arrays.
-	     Then insist that either both or none have any TREE_PURPOSE
-	     values.  */
-	  if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE)
-	    type = TREE_TYPE (exp);
-	  else
-	    type = 0;
-
-	  if (memcmp ((char *) &type, p, sizeof type))
+	  if (get_set_constructor_bytes (t1, tmp1, len) != NULL_TREE)
+	    return 0;
+	  if (get_set_constructor_bytes (t2, tmp2, len) != NULL_TREE)
 	    return 0;
+	  
+	  return memcmp (tmp1, tmp2, len) != 0;
+	}
+      else
+	{
+	  tree l1, l2;
 
-	  if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE)
+	  if (typecode == ARRAY_TYPE)
 	    {
-	      if (memcmp ((char *) &mode, p, sizeof mode))
+	      HOST_WIDE_INT size_1 = int_size_in_bytes (TREE_TYPE (t1));
+	      /* For arrays, check that the sizes all match.  */
+	      if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2))
+		  || size_1 == -1
+		  || size_1 != int_size_in_bytes (TREE_TYPE (t2)))
 		return 0;
-
-	      p += sizeof mode;
 	    }
-
-	  p += sizeof type;
-
-	  if (memcmp ((char *) &have_purpose, p, sizeof have_purpose))
-	    return 0;
-
-	  p += sizeof have_purpose;
-
-	  /* For arrays, insist that the size in bytes match.  */
-	  if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE)
+	  else
 	    {
-	      HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
-
-	      if (memcmp ((char *) &size, p, sizeof size))
+	      /* For record and union constructors, require exact type
+                 equality.  */
+	      if (TREE_TYPE (t1) != TREE_TYPE (t2))
 		return 0;
-
-	      p += sizeof size;
 	    }
 
-	  for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
+	  for (l1 = CONSTRUCTOR_ELTS (t1), l2 = CONSTRUCTOR_ELTS (l2);
+	       l1 && l2;
+	       l1 = TREE_CHAIN (l1), l2 = TREE_CHAIN (l2))
 	    {
-	      if (TREE_VALUE (link))
+	      /* Check that each value is the same... */
+	      if (! compare_constant (TREE_VALUE (l1), TREE_VALUE (l2)))
+		return 0;
+	      /* ... and that they apply to the same fields!  */
+	      if (typecode == ARRAY_TYPE)
 		{
-		  if ((p = compare_constant_1 (TREE_VALUE (link), p)) == 0)
+		  if (! compare_constant (TREE_PURPOSE (l1),
+					  TREE_PURPOSE (l2)))
 		    return 0;
 		}
 	      else
 		{
-		  tree zero = 0;
-
-		  if (memcmp ((char *) &zero, p, sizeof zero))
+		  if (TREE_PURPOSE (l1) != TREE_PURPOSE (l2))
 		    return 0;
-
-		  p += sizeof zero;
-		}
-
-	      if (TREE_PURPOSE (link)
-		  && TREE_CODE (TREE_PURPOSE (link)) == FIELD_DECL)
-		{
-		  if (memcmp ((char *) &TREE_PURPOSE (link), p,
-			    sizeof TREE_PURPOSE (link)))
-		    return 0;
-
-		  p += sizeof TREE_PURPOSE (link);
 		}
-	      else if (TREE_PURPOSE (link))
-		{
-		  if ((p = compare_constant_1 (TREE_PURPOSE (link), p)) == 0)
-		    return 0;
-		}
-	      else if (have_purpose)
-		{
-		  int zero = 0;
-
-		  if (memcmp ((char *) &zero, p, sizeof zero))
-		    return 0;
-
-		  p += sizeof zero;
-		}
 	    }
-
-	  return p;
+	  
+	  return l1 == NULL_TREE && l2 == NULL_TREE;
 	}
 
     case ADDR_EXPR:
       {
-	struct addr_const value;
-
-	decode_addr_const (exp, &value);
-	strp = (unsigned char *) &value.offset;
-	len = sizeof value.offset;
-	/* Compare the offset.  */
-	while (--len >= 0)
-	  if (*p++ != *strp++)
-	    return 0;
+	struct addr_const value1, value2;
 
-	/* Compare symbol name.  */
-	strp = (const unsigned char *) XSTR (value.base, 0);
-	len = strlen ((const char *) strp) + 1;
+	decode_addr_const (t1, &value1);
+	decode_addr_const (t2, &value2);
+	return (value1.offset == value2.offset
+		&& strcmp (XSTR (value1.base, 0), XSTR (value2.base, 0)) == 0);
       }
-      break;
 
     case PLUS_EXPR:
     case MINUS_EXPR:
     case RANGE_EXPR:
-      p = compare_constant_1 (TREE_OPERAND (exp, 0), p);
-      if (p == 0)
-	return 0;
+      return (compare_constant (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0))
+	      && compare_constant(TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1)));
 
-      return compare_constant_1 (TREE_OPERAND (exp, 1), p);
-
     case NOP_EXPR:
     case CONVERT_EXPR:
     case NON_LVALUE_EXPR:
-      return compare_constant_1 (TREE_OPERAND (exp, 0), p);
+      return compare_constant (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
 
     default:
       {
-	tree new = (*lang_hooks.expand_constant) (exp);
-
-	if (new != exp)
-          return compare_constant_1 (new, p);
+	tree nt1, nt2;
+	nt1 = (*lang_hooks.expand_constant) (t1);
+	nt2 = (*lang_hooks.expand_constant) (t2);
+	if (nt1 != t1 || nt2 != t2)
+	  return compare_constant (nt1, nt2);
 	else
 	  return 0;
       }
     }
-
-  /* Compare constant contents.  */
-  while (--len >= 0)
-    if (*p++ != *strp++)
-      return 0;
-
-  return p;
-}
-\f
-/* Construct a constant descriptor for the expression EXP.
-   It is up to the caller to enter the descriptor in the hash table.  */
-
-static struct constant_descriptor *
-record_constant (exp)
-     tree exp;
-{
-  struct constant_descriptor *next = 0;
-  char *label = 0;
-  rtx rtl = 0;
-  int pad;
-
-  /* Make a struct constant_descriptor.  The first three pointers will
-     be filled in later.  Here we just leave space for them.  */
-
-  obstack_grow (&permanent_obstack, (char *) &next, sizeof next);
-  obstack_grow (&permanent_obstack, (char *) &label, sizeof label);
-  obstack_grow (&permanent_obstack, (char *) &rtl, sizeof rtl);
-
-  /* Align the descriptor for the data payload.  */
-  pad = (offsetof (struct constant_descriptor, u)
-	 - offsetof(struct constant_descriptor, rtl)
-	 - sizeof(next->rtl));
-  if (pad > 0)
-    obstack_blank (&permanent_obstack, pad);
-
-  record_constant_1 (exp);
-  return (struct constant_descriptor *) obstack_finish (&permanent_obstack);
-}
-
-/* Add a description of constant expression EXP
-   to the object growing in `permanent_obstack'.
-   No need to return its address; the caller will get that
-   from the obstack when the object is complete.  */
-
-static void
-record_constant_1 (exp)
-     tree exp;
-{
-  const unsigned char *strp;
-  int len;
-  enum tree_code code = TREE_CODE (exp);
-
-  obstack_1grow (&permanent_obstack, (unsigned int) code);
-
-  switch (code)
-    {
-    case INTEGER_CST:
-      obstack_1grow (&permanent_obstack, TYPE_PRECISION (TREE_TYPE (exp)));
-      strp = (unsigned char *) &TREE_INT_CST (exp);
-      len = sizeof TREE_INT_CST (exp);
-      break;
-
-    case REAL_CST:
-      obstack_1grow (&permanent_obstack, TYPE_PRECISION (TREE_TYPE (exp)));
-      strp = (unsigned char *) &TREE_REAL_CST (exp);
-      len = sizeof TREE_REAL_CST (exp);
-      break;
-
-    case STRING_CST:
-      if (flag_writable_strings)
-	return;
-
-      obstack_1grow (&permanent_obstack, TYPE_MODE (TREE_TYPE (exp)));
-      strp = (const unsigned char *) TREE_STRING_POINTER (exp);
-      len = TREE_STRING_LENGTH (exp);
-      obstack_grow (&permanent_obstack, (char *) &TREE_STRING_LENGTH (exp),
-		    sizeof TREE_STRING_LENGTH (exp));
-      break;
-
-    case COMPLEX_CST:
-      record_constant_1 (TREE_REALPART (exp));
-      record_constant_1 (TREE_IMAGPART (exp));
-      return;
-
-    case CONSTRUCTOR:
-      if (TREE_CODE (TREE_TYPE (exp)) == SET_TYPE)
-	{
-	  int nbytes = int_size_in_bytes (TREE_TYPE (exp));
-	  obstack_grow (&permanent_obstack, &nbytes, sizeof (nbytes));
-	  obstack_blank (&permanent_obstack, nbytes);
-	  get_set_constructor_bytes
-	    (exp, (unsigned char *) permanent_obstack.next_free-nbytes,
-	     nbytes);
-	  return;
-	}
-      else
-	{
-	  tree link;
-	  int length = list_length (CONSTRUCTOR_ELTS (exp));
-	  enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
-	  tree type;
-	  int have_purpose = 0;
-
-	  for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
-	    if (TREE_PURPOSE (link))
-	      have_purpose = 1;
-
-	  obstack_grow (&permanent_obstack, (char *) &length, sizeof length);
-
-	  /* For record constructors, insist that the types match.
-	     For arrays, just verify both constructors are for arrays
-	     of the same mode.  Then insist that either both or none
-	     have any TREE_PURPOSE values.  */
-	  if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE)
-	    type = TREE_TYPE (exp);
-	  else
-	    type = 0;
-
-	  obstack_grow (&permanent_obstack, (char *) &type, sizeof type);
-	  if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE)
-	    obstack_grow (&permanent_obstack, &mode, sizeof mode);
-
-	  obstack_grow (&permanent_obstack, (char *) &have_purpose,
-			sizeof have_purpose);
-
-	  /* For arrays, insist that the size in bytes match.  */
-	  if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE)
-	    {
-	      HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
-	      obstack_grow (&permanent_obstack, (char *) &size, sizeof size);
-	    }
-
-	  for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
-	    {
-	      if (TREE_VALUE (link))
-		record_constant_1 (TREE_VALUE (link));
-	      else
-		{
-		  tree zero = 0;
-
-		  obstack_grow (&permanent_obstack,
-				(char *) &zero, sizeof zero);
-		}
-
-	      if (TREE_PURPOSE (link)
-		  && TREE_CODE (TREE_PURPOSE (link)) == FIELD_DECL)
-		obstack_grow (&permanent_obstack,
-			      (char *) &TREE_PURPOSE (link),
-			      sizeof TREE_PURPOSE (link));
-	      else if (TREE_PURPOSE (link))
-		record_constant_1 (TREE_PURPOSE (link));
-	      else if (have_purpose)
-		{
-		  int zero = 0;
-
-		  obstack_grow (&permanent_obstack,
-				(char *) &zero, sizeof zero);
-		}
-	    }
-	}
-      return;
-
-    case ADDR_EXPR:
-      {
-	struct addr_const value;
-
-	decode_addr_const (exp, &value);
-	/* Record the offset.  */
-	obstack_grow (&permanent_obstack,
-		      (char *) &value.offset, sizeof value.offset);
-
-	switch (GET_CODE (value.base))
-	  {
-	  case SYMBOL_REF:
-	    /* Record the symbol name.  */
-	    obstack_grow (&permanent_obstack, XSTR (value.base, 0),
-			  strlen (XSTR (value.base, 0)) + 1);
-	    break;
-	  case LABEL_REF:
-	    /* Record the address of the CODE_LABEL.  It may not have
-	       been emitted yet, so it's UID may be zero.  But pointer
-	       identity is good enough.  */
-	    obstack_grow (&permanent_obstack, &XEXP (value.base, 0),
-			  sizeof (rtx));
-	    break;
-	  default:
-	    abort ();
-	  }
-      }
-      return;
-
-    case PLUS_EXPR:
-    case MINUS_EXPR:
-    case RANGE_EXPR:
-      record_constant_1 (TREE_OPERAND (exp, 0));
-      record_constant_1 (TREE_OPERAND (exp, 1));
-      return;
-
-    case NOP_EXPR:
-    case CONVERT_EXPR:
-    case NON_LVALUE_EXPR:
-      record_constant_1 (TREE_OPERAND (exp, 0));
-      return;
-
-    default:
-      {
-	tree new = (*lang_hooks.expand_constant) (exp);
-
-	if (new != exp)
-          record_constant_1 (new);
-	return;
-      }
-    }
 
-  /* Record constant contents.  */
-  obstack_grow (&permanent_obstack, strp, len);
+  /* Should not get here.  */
+  abort ();
 }
 \f
 /* Record a list of constant expressions that were passed to
@@ -3147,9 +2841,8 @@ output_after_function_constants ()
   after_function_constants = 0;
 }
 
-/* Make a copy of the whole tree structure for a constant.
-   This handles the same types of nodes that compare_constant
-   and record_constant handle.  */
+/* Make a copy of the whole tree structure for a constant.  This
+   handles the same types of nodes that compare_constant handles.  */
 
 static tree
 copy_constant (exp)
@@ -3229,7 +2922,7 @@ output_constant_def (exp, defer)
      int defer;
 {
   int hash;
-  struct constant_descriptor *desc;
+  struct constant_descriptor_tree *desc;
   struct deferred_string **defstr;
   char label[256];
   int reloc;
@@ -3238,7 +2931,7 @@ output_constant_def (exp, defer)
   int labelno = -1;
   rtx rtl;
 
-  /* We can't just use the saved RTL if this is a defererred string constant
+  /* We can't just use the saved RTL if this is a deferred string constant
      and we are not to defer anymode.  */
   if (TREE_CODE (exp) != INTEGER_CST && TREE_CST_RTL (exp)
       && (defer || !STRING_POOL_ADDRESS_P (XEXP (TREE_CST_RTL (exp), 0))))
@@ -3256,7 +2949,7 @@ output_constant_def (exp, defer)
   hash = const_hash (exp) % MAX_HASH_TABLE;
 
   for (desc = const_hash_table[hash]; desc; desc = desc->next)
-    if (compare_constant (exp, desc))
+    if (compare_constant (exp, desc->value))
       break;
 
   if (desc == 0)
@@ -3270,9 +2963,10 @@ output_constant_def (exp, defer)
       labelno = const_labelno++;
       ASM_GENERATE_INTERNAL_LABEL (label, "LC", labelno);
 
-      desc = record_constant (exp);
+      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.  */
@@ -3340,7 +3034,7 @@ output_constant_def (exp, defer)
 	    = (struct deferred_constant *)
 	      xmalloc (sizeof (struct deferred_constant));
 
-	  p->exp = copy_constant (exp);
+	  p->exp = desc->value;
 	  p->reloc = reloc;
 	  p->labelno = labelno;
 	  if (after_function)
@@ -3373,9 +3067,9 @@ output_constant_def (exp, defer)
 		  struct deferred_string *p;
 
 		  p = (struct deferred_string *)
-		      xmalloc (sizeof (struct deferred_string));
+		      ggc_alloc (sizeof (struct deferred_string));
 
-		  p->exp = copy_constant (exp);
+		  p->exp = desc->value;
 		  p->label = desc->label;
 		  p->labelno = labelno;
 		  *defstr = p;
@@ -3439,6 +3133,26 @@ output_constant_def_contents (exp, reloc
 
 }
 \f
+/* Used in the hash tables to avoid outputting the same constant
+   twice.  Unlike 'struct constant_descriptor_tree', RTX constants
+   are output once per function, not once per file; there seems
+   to be no reason for the difference.  */
+
+struct constant_descriptor_rtx 
+{
+  /* More constant_descriptors with the same hash code.  */
+  struct constant_descriptor_rtx *next;
+
+  /* The label of the constant.  */
+  const char *label;
+
+  /* A MEM for the constant.  */
+  rtx rtl;
+
+  /* The value of the constant.  */
+  struct rtx_const value;
+};
+
 /* Structure to represent sufficient information about a constant so that
    it can be output when the constant pool is output, so that function
    integration can be done, and to simplify handling on machines that reference
@@ -3446,8 +3160,9 @@ output_constant_def_contents (exp, reloc
 
 struct pool_constant
 {
-  struct constant_descriptor *desc;
-  struct pool_constant *next, *next_sym;
+  struct constant_descriptor_rtx *desc;
+  struct pool_constant *next;
+  struct pool_constant *next_sym;
   rtx constant;
   enum machine_mode mode;
   int labelno;
@@ -3472,9 +3187,9 @@ init_varasm_status (f)
   p = (struct varasm_status *) ggc_alloc (sizeof (struct varasm_status));
   f->varasm = p;
   p->x_const_rtx_hash_table
-    = ((struct constant_descriptor **)
+    = ((struct constant_descriptor_rtx **)
        ggc_alloc_cleared (MAX_RTX_HASH_TABLE
-			  * sizeof (struct constant_descriptor *)));
+			  * sizeof (struct constant_descriptor_rtx *)));
   p->x_const_rtx_sym_hash_table
     = ((struct pool_constant **)
        ggc_alloc_cleared (MAX_RTX_HASH_TABLE
@@ -3506,45 +3221,25 @@ void
 mark_varasm_status (p)
      struct varasm_status *p;
 {
+  int i;
+  
   if (p == NULL)
     return;
 
   ggc_mark (p);
   ggc_mark (p->x_const_rtx_hash_table);
-  ggc_mark (p->x_const_rtx_sym_hash_table);
-  mark_pool_constant (p->x_first_pool);
-  ggc_mark_rtx (p->x_const_double_chain);
-}
-
-/* Clear out all parts of the state in F that can safely be discarded
-   after the function has been compiled, to let garbage collection
-   reclaim the memory.  */
-
-void
-free_varasm_status (f)
-     struct function *f;
-{
-  struct varasm_status *p;
-  int i;
-
-  p = f->varasm;
-
-  /* Clear out the hash tables.  */
-  for (i = 0; i < MAX_RTX_HASH_TABLE; ++i)
+  for (i = 0; i < MAX_RTX_HASH_TABLE; i++)
     {
-      struct constant_descriptor *cd;
-
-      cd = p->x_const_rtx_hash_table[i];
-      while (cd)
+      struct constant_descriptor_rtx *l;
+      for (l = p->x_const_rtx_hash_table[i]; l; l = l->next)
 	{
-	  struct constant_descriptor *next = cd->next;
-
-	  free (cd);
-	  cd = next;
+	  ggc_mark (l);
+	  ggc_mark_rtx (l->rtl);
 	}
     }
-
-  f->varasm = NULL;
+  ggc_mark (p->x_const_rtx_sym_hash_table);
+  mark_pool_constant (p->x_first_pool);
+  ggc_mark_rtx (p->x_const_double_chain);
 }
 \f
 
@@ -3700,39 +3395,28 @@ static int
 compare_constant_rtx (mode, x, desc)
      enum machine_mode mode;
      rtx x;
-     struct constant_descriptor *desc;
+     struct constant_descriptor_rtx *desc;
 {
-  int *p = (int *) desc->u.contents;
-  int *strp;
-  int len;
   struct rtx_const value;
 
   decode_rtx_const (mode, x, &value);
-  strp = (int *) &value;
-  len = sizeof value / sizeof (int);
 
   /* Compare constant contents.  */
-  while (--len >= 0)
-    if (*p++ != *strp++)
-      return 0;
-
-  return 1;
+  return memcmp (&value, &desc->value, sizeof (struct rtx_const)) == 0;
 }
 
 /* Construct a constant descriptor for the rtl-expression X.
    It is up to the caller to enter the descriptor in the hash table.  */
 
-static struct constant_descriptor *
+static struct constant_descriptor_rtx *
 record_constant_rtx (mode, x)
      enum machine_mode mode;
      rtx x;
 {
-  struct constant_descriptor *ptr;
+  struct constant_descriptor_rtx *ptr;
 
-  ptr = ((struct constant_descriptor *)
-	 xcalloc (1, (offsetof (struct constant_descriptor, u)
-		      + sizeof (struct rtx_const))));
-  decode_rtx_const (mode, x, (struct rtx_const *) ptr->u.contents);
+  ptr = (struct constant_descriptor_rtx *) ggc_alloc (sizeof (*ptr));
+  decode_rtx_const (mode, x, &ptr->value);
 
   return ptr;
 }
@@ -3745,7 +3429,7 @@ mem_for_const_double (x)
      rtx x;
 {
   enum machine_mode mode = GET_MODE (x);
-  struct constant_descriptor *desc;
+  struct constant_descriptor_rtx *desc;
 
   for (desc = const_rtx_hash_table[const_hash_rtx (mode, x)]; desc;
        desc = desc->next)
@@ -3764,7 +3448,7 @@ force_const_mem (mode, x)
      rtx x;
 {
   int hash;
-  struct constant_descriptor *desc;
+  struct constant_descriptor_rtx *desc;
   char label[256];
   rtx def;
   struct pool_constant *pool;
============================================================

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2002-02-19 20:33 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-02-19 14:06 [PCH] constant pools rewrite Joern Rennecke
  -- strict thread matches above, loose matches on Subject: below --
2002-02-18  9:57 Geoffrey Keating
2002-02-18 10:07 ` Joseph S. Myers
2002-02-18 16:32 ` Richard Henderson
2002-02-18 18:56   ` Geoff Keating
2002-02-18 21:44 ` Jim Wilson
2002-02-19  3:52   ` Richard Earnshaw

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).