public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* RFA: init_one_libfunc vs. target_reinit
@ 2008-06-26 21:24 Richard Sandiford
  2008-06-27 22:51 ` Mark Mitchell
  0 siblings, 1 reply; 2+ messages in thread
From: Richard Sandiford @ 2008-06-26 21:24 UTC (permalink / raw)
  To: gcc-patches

Following on from:

  http://gcc.gnu.org/ml/gcc-patches/2008-06/msg01700.html

this is another patch aimed at making:

  ...switch to a new subtarget...
  target_reinit ();
  ...switch back to the old subtarget...
  target_reinit ();

a no-op.

target_reinit calls init_optabs, which in turn uses init_one_libfunc to
set up various library functions.  The problem is that init_one_libfunc
creates a new decl each time it is called, causing the sequence above
to change both the DECL_UID and SYMBOL_REF of something like
memcpy_libfunc.

The libfunc decls themselves aren't particularly important; we just
use their SYMBOL_REFs.  However, allocating DECL_UIDs affects every
decl created after that, leading to spurious differences in the names
of nested functions.

This patch uses a hashtable to make sure that set_one_libfunc uses
the same decl and symbol for a given name.  I realise that this
will in theory add extra set-up overhead to targets that don't
use target_reinit, but the number of libfuncs is actually pretty small.

I wondered about conditionialising the hashtable code on a
"reinitialising?" predicate, but the first init_optabs would then
behave differently from subsequent init_optabs if two libfuncs
happen to share the same external routine.

Also, I believe function-specific-branch makes more use of target_reinit,
so I hope this sort of thing will be of general use than just MIPS.

Tested on mipsisa64-elfoabi and x86_64-linux-gnu.  OK to install?

Richard


gcc/
	* optabs.c (libfunc_decls): New variable.
	(libfunc_decl_hash, libfunc_decl_eq): New functions.
	(init_one_libfunc): Reuse decls and SYMBOL_REFs when asked
	for the same function twice.

Index: gcc/optabs.c
===================================================================
--- gcc/optabs.c	2008-06-24 21:27:58.000000000 +0100
+++ gcc/optabs.c	2008-06-24 21:30:14.000000000 +0100
@@ -5984,28 +5984,58 @@ gen_satfractuns_conv_libfunc (convert_op
   gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
 }
 
+/* A table of previously-created libfuncs, hashed by name.  */
+static GTY ((param_is (union tree_node))) htab_t libfunc_decls;
+
+/* Hashtable callbacks for libfunc_decls.  */
+
+static hashval_t
+libfunc_decl_hash (const void *entry)
+{
+  return htab_hash_string (IDENTIFIER_POINTER (DECL_NAME ((tree) entry)));
+}
+
+static int
+libfunc_decl_eq (const void *entry1, const void *entry2)
+{
+  return DECL_NAME ((tree) entry1) == (tree) entry2;
+}
+
 rtx
 init_one_libfunc (const char *name)
 {
-  rtx symbol;
-
-  /* Create a FUNCTION_DECL that can be passed to
-     targetm.encode_section_info.  */
-  /* ??? We don't have any type information except for this is
-     a function.  Pretend this is "int foo()".  */
-  tree decl = build_decl (FUNCTION_DECL, get_identifier (name),
-			  build_function_type (integer_type_node, NULL_TREE));
-  DECL_ARTIFICIAL (decl) = 1;
-  DECL_EXTERNAL (decl) = 1;
-  TREE_PUBLIC (decl) = 1;
-
-  symbol = XEXP (DECL_RTL (decl), 0);
-
-  /* Zap the nonsensical SYMBOL_REF_DECL for this.  What we're left with
-     are the flags assigned by targetm.encode_section_info.  */
-  SET_SYMBOL_REF_DECL (symbol, 0);
+  tree id, decl;
+  void **slot;
+  hashval_t hash;
+
+  if (libfunc_decls == NULL)
+    libfunc_decls = htab_create_ggc (37, libfunc_decl_hash,
+				     libfunc_decl_eq, NULL);
+
+  /* See if we have already created a libfunc decl for this function.  */
+  id = get_identifier (name);
+  hash = htab_hash_string (name);
+  slot = htab_find_slot_with_hash (libfunc_decls, id, hash, INSERT);
+  decl = (tree) *slot;
+  if (decl == NULL)
+    {
+      /* Create a new decl, so that it can be passed to
+	 targetm.encode_section_info.  */
+      /* ??? We don't have any type information except for this is
+	 a function.  Pretend this is "int foo()".  */
+      decl = build_decl (FUNCTION_DECL, get_identifier (name),
+			 build_function_type (integer_type_node, NULL_TREE));
+      DECL_ARTIFICIAL (decl) = 1;
+      DECL_EXTERNAL (decl) = 1;
+      TREE_PUBLIC (decl) = 1;
+
+      /* Zap the nonsensical SYMBOL_REF_DECL for this.  What we're left with
+	 are the flags assigned by targetm.encode_section_info.  */
+      SET_SYMBOL_REF_DECL (XEXP (DECL_RTL (decl), 0), NULL);
 
-  return symbol;
+      *slot = decl;
+    }
+  return XEXP (DECL_RTL (decl), 0);
 }
 
 /* Call this to reset the function entry for one optab (OPTABLE) in mode

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

* Re: RFA: init_one_libfunc vs. target_reinit
  2008-06-26 21:24 RFA: init_one_libfunc vs. target_reinit Richard Sandiford
@ 2008-06-27 22:51 ` Mark Mitchell
  0 siblings, 0 replies; 2+ messages in thread
From: Mark Mitchell @ 2008-06-27 22:51 UTC (permalink / raw)
  To: gcc-patches, rdsandiford

Richard Sandiford wrote:

> 
> gcc/
> 	* optabs.c (libfunc_decls): New variable.
> 	(libfunc_decl_hash, libfunc_decl_eq): New functions.
> 	(init_one_libfunc): Reuse decls and SYMBOL_REFs when asked
> 	for the same function twice.

OK.

-- 
Mark Mitchell
CodeSourcery
mark@codesourcery.com
(650) 331-3385 x713

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

end of thread, other threads:[~2008-06-27 22:46 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-06-26 21:24 RFA: init_one_libfunc vs. target_reinit Richard Sandiford
2008-06-27 22:51 ` Mark Mitchell

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).