public inbox for fortran@gcc.gnu.org
 help / color / mirror / Atom feed
From: Andrew Benson <abenson@carnegiescience.edu>
To: Richard Biener <richard.guenther@gmail.com>
Cc: "fortran@gcc.gnu.org" <fortran@gcc.gnu.org>
Subject: Re: Optimization of add_dt_to_dt_list() in resolve.c
Date: Tue, 29 May 2018 20:25:00 -0000	[thread overview]
Message-ID: <2946507.05iJNWrpSJ@andrew-precision-3520> (raw)
In-Reply-To: <CAFiYyc3Y=buF5GQomZmoXnvBTZera16dtL5mchBoB-63rNi68g@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 4317 bytes --]

Yes - definitely possible to remove gfc_dt_list entirely - new patch is 
attached.

Thanks,
Andrew

On Monday, May 28, 2018 11:54:41 AM PDT Richard Biener wrote:
> On Fri, May 25, 2018 at 11:54 PM Andrew Benson <abenson@carnegiescience.edu>
> wrote:
> > Richard:
> > 
> > Thanks for the suggestion. I changed my patch (new version attached) so
> 
> that
> 
> > there's a *dt_next in gfc_symbol, which is now used to construct the
> > (circular) linked list. There were a couple places where I had to change
> 
> the
> 
> > order in which clean up of symbols and derived type lists were done -
> 
> it's now
> 
> > necessary to free the derived type list before its associated symbols
> 
> (since
> 
> > the symbols carry the links for the derived type list).
> 
> Hmm, it still has the indirection via gfc_dt_list.  I think it should be
> possible
> to do away with gfc_dt_list objects alltogether by no doing
> sym->dt_next->derived
> but sym->derived thus
> 
> @@ -1611,6 +1611,9 @@ typedef struct gfc_symbol
> 
>     /* Link to corresponding association-list if this is an associate name.
>   */
>     struct gfc_association_list *assoc;
> +
> +  /* Link to next entry in derived type list */
> +  gfc_symbol *dt_next;
>   }
>   gfc_symbol;
> 
> that means for example gfc_free_dt_list can be simply removed.  The
> gfc_derived_types global would then point to the first derived type
> directly.
> 
> Richard.
> 
> > This passes "make check-fortran" and seems to retain the speed-up from my
> > original patch.
> > 
> > Thanks,
> > Andrew
> > 
> > On Friday, May 25, 2018 9:06:22 AM PDT Richard Biener wrote:
> > > On Fri, May 25, 2018 at 12:53 AM Andrew Benson <
> 
> abenson@carnegiescience.edu>
> 
> > > wrote:
> > > > I've been attempting to track down some of the causes of very long
> 
> compile
> 
> > > > times for files which use modules that contain a large number of
> 
> symbols.
> 
> > > The
> > > 
> > > > worst case offender in my code takes around 12 minutes to compile.
> > > > 
> > > > After profiling f951 for this source file it turns out that the
> 
> majority
> 
> > > of the
> > > 
> > > > time is spent in add_dt_to_dt_list() in resolve.c. In cases where the
> > > 
> > > number
> > > 
> > > > of symbols imported becomes very large (~10,000 in some cases in this
> > > 
> > > code),
> > > 
> > > > the O(N) search in this function becomes inefficient.
> > > > 
> > > > A simple optimization for this problem seems to be to just have the
> > > 
> > > gfc_symbol
> > > 
> > > > struct include a pointer back to the corresponding entry in the
> > > > gfc_derived_types list. It's then fast to check if a symbol is
> 
> already on
> 
> > > that
> > > 
> > > > list by checking if this pointer is non-null. (It could just as
> 
> easily be
> 
> > > an
> > > 
> > > > int in gfc_symbol which indicates if the symbol is already added to
> 
> the
> 
> > > list -
> > > 
> > > > I don't know if having a pointer to the list entry is useful for any
> 
> other
> 
> > > > reason.)
> > > > 
> > > > With this change in place compile times are much faster - my worst
> 
> case
> 
> > > > offender now takes just under 1 minute to compile.
> > > > 
> > > > My patch is attached. I freely admit that I have only a very shallow
> > > > understanding of the inner workings of the compiler, so I would not be
> > > > surprised if there are good reasons not to do this. I did "make
> > > 
> > > check-fortran"
> > > 
> > > > and did not see any failures. If any one wants to try this out and/or
> > > 
> > > provide
> > > 
> > > > any feedback I'd be happy to hear it.
> > > 
> > > It looks like it would be cheaper to simply embed gtc_dt_list *next in
> > > gfc_symbol?
> > > (in case a gfc_symbol can be only on one gfc_dt_list which your patch
> > > assumes as well)
> > > 
> > > Richard.
> > > 
> > > > Thanks,
> > > > Andrew
> > > > 
> > > > --
> 
> > > > * Andrew Benson:
> http://users.obs.carnegiescience.edu/abenson/contact.html
> 
> > > > * Galacticus: https://bitbucket.org/abensonca/galacticus
> > 
> > --
> > 
> > * Andrew Benson: http://users.obs.carnegiescience.edu/abenson/contact.html
> > 
> > * Galacticus: https://bitbucket.org/abensonca/galacticus


-- 

* Andrew Benson: http://users.obs.carnegiescience.edu/abenson/contact.html

* Galacticus: https://bitbucket.org/abensonca/galacticus

[-- Attachment #2: patch.diff --]
[-- Type: text/x-patch, Size: 8423 bytes --]

Index: gcc/fortran/gfortran.h
===================================================================
--- gcc/fortran/gfortran.h	(revision 260682)
+++ gcc/fortran/gfortran.h	(working copy)
@@ -1611,6 +1611,9 @@ typedef struct gfc_symbol
 
   /* Link to corresponding association-list if this is an associate name.  */
   struct gfc_association_list *assoc;
+
+  /* Link to next entry in derived type list */
+  struct gfc_symbol *dt_next;
 }
 gfc_symbol;
 
@@ -1712,19 +1715,9 @@ typedef struct gfc_symtree
 }
 gfc_symtree;
 
-/* A linked list of derived types in the namespace.  */
-typedef struct gfc_dt_list
-{
-  struct gfc_symbol *derived;
-  struct gfc_dt_list *next;
-}
-gfc_dt_list;
+/* A list of all derived types.  */
+extern gfc_symbol *gfc_derived_types;
 
-#define gfc_get_dt_list() XCNEW (gfc_dt_list)
-
-  /* A list of all derived types.  */
-  extern gfc_dt_list *gfc_derived_types;
-
 typedef struct gfc_oacc_routine_name
 {
   struct gfc_symbol *sym;
@@ -1809,7 +1802,7 @@ typedef struct gfc_namespace
 
   gfc_charlen *cl_list;
 
-  gfc_dt_list *derived_types;
+  gfc_symbol *derived_types;
 
   int save_all, seen_save, seen_implicit_none;
 
Index: gcc/fortran/parse.c
===================================================================
--- gcc/fortran/parse.c	(revision 260682)
+++ gcc/fortran/parse.c	(working copy)
@@ -6047,7 +6047,7 @@ add_global_program (void)
 static void
 resolve_all_program_units (gfc_namespace *gfc_global_ns_list)
 {
-  gfc_free_dt_list ();
+  gfc_derived_types = NULL;
   gfc_current_ns = gfc_global_ns_list;
   for (; gfc_current_ns; gfc_current_ns = gfc_current_ns->sibling)
     {
Index: gcc/fortran/resolve.c
===================================================================
--- gcc/fortran/resolve.c	(revision 260682)
+++ gcc/fortran/resolve.c	(working copy)
@@ -2504,7 +2504,7 @@ resolve_global_procedure (gfc_symbol *sym, locus *
       /* Resolve the gsymbol namespace if needed.  */
       if (!gsym->ns->resolved)
 	{
-	  gfc_dt_list *old_dt_list;
+	  gfc_symbol *old_dt_list;
 
 	  /* Stash away derived types so that the backend_decls do not
 	     get mixed up.  */
@@ -13435,16 +13435,17 @@ resolve_typebound_procedures (gfc_symbol* derived)
 static void
 add_dt_to_dt_list (gfc_symbol *derived)
 {
-  gfc_dt_list *dt_list;
 
-  for (dt_list = gfc_derived_types; dt_list; dt_list = dt_list->next)
-    if (derived == dt_list->derived)
-      return;
-
-  dt_list = gfc_get_dt_list ();
-  dt_list->next = gfc_derived_types;
-  dt_list->derived = derived;
-  gfc_derived_types = dt_list;
+  if (!derived->dt_next) {
+    if (gfc_derived_types) {
+      derived->dt_next = gfc_derived_types->dt_next;
+      gfc_derived_types->dt_next = derived;
+    } else {
+      derived->dt_next = derived;
+    }
+    gfc_derived_types = derived;
+  }
+  
 }
 
 
Index: gcc/fortran/symbol.c
===================================================================
--- gcc/fortran/symbol.c	(revision 260682)
+++ gcc/fortran/symbol.c	(working copy)
@@ -107,7 +107,7 @@ gfc_namespace *gfc_global_ns_list;
 
 gfc_gsymbol *gfc_gsym_root = NULL;
 
-gfc_dt_list *gfc_derived_types;
+gfc_symbol *gfc_derived_types;
 
 static gfc_undo_change_set default_undo_chgset_var = { vNULL, vNULL, NULL };
 static gfc_undo_change_set *latest_undo_chgset = &default_undo_chgset_var;
@@ -3119,6 +3119,7 @@ gfc_new_symbol (const char *name, gfc_namespace *n
   p->common_block = NULL;
   p->f2k_derived = NULL;
   p->assoc = NULL;
+  p->dt_next = NULL;
   p->fn_result_spec = 0;
 
   return p;
@@ -3878,23 +3879,6 @@ free_sym_tree (gfc_symtree *sym_tree)
 }
 
 
-/* Free the derived type list.  */
-
-void
-gfc_free_dt_list (void)
-{
-  gfc_dt_list *dt, *n;
-
-  for (dt = gfc_derived_types; dt; dt = n)
-    {
-      n = dt->next;
-      free (dt);
-    }
-
-  gfc_derived_types = NULL;
-}
-
-
 /* Free the gfc_equiv_info's.  */
 
 static void
@@ -4080,7 +4064,7 @@ gfc_symbol_done_2 (void)
       gfc_free_namespace (gfc_current_ns);
       gfc_current_ns = NULL;
     }
-  gfc_free_dt_list ();
+  gfc_derived_types = NULL;
 
   enforce_single_undo_checkpoint ();
   free_undo_change_set_data (*latest_undo_chgset);
@@ -4343,7 +4327,7 @@ gfc_get_gsymbol (const char *name)
 static gfc_symbol *
 get_iso_c_binding_dt (int sym_id)
 {
-  gfc_dt_list *dt_list;
+  gfc_symbol *dt_list;
 
   dt_list = gfc_derived_types;
 
@@ -4350,15 +4334,17 @@ get_iso_c_binding_dt (int sym_id)
   /* Loop through the derived types in the name list, searching for
      the desired symbol from iso_c_binding.  Search the parent namespaces
      if necessary and requested to (parent_flag).  */
-  while (dt_list != NULL)
-    {
-      if (dt_list->derived->from_intmod != INTMOD_NONE
-	  && dt_list->derived->intmod_sym_id == sym_id)
-        return dt_list->derived;
+  if (dt_list) {
+    while (dt_list->dt_next != gfc_derived_types)
+      {
+	if (dt_list->from_intmod != INTMOD_NONE
+	    && dt_list->intmod_sym_id == sym_id)
+	  return dt_list;
+	
+	dt_list = dt_list->dt_next;
+      }
+  }
 
-      dt_list = dt_list->next;
-    }
-
   return NULL;
 }
 
@@ -4762,11 +4748,13 @@ generate_isocbinding_symbol (const char *mod_name,
       if (tmp_sym->attr.flavor == FL_DERIVED
 	  && !get_iso_c_binding_dt (tmp_sym->intmod_sym_id))
 	{
-	  gfc_dt_list *dt_list;
-	  dt_list = gfc_get_dt_list ();
-	  dt_list->derived = tmp_sym;
-	  dt_list->next = gfc_derived_types;
-  	  gfc_derived_types = dt_list;
+	  if (gfc_derived_types) {
+	    tmp_sym->dt_next = gfc_derived_types->dt_next;
+	    gfc_derived_types->dt_next = tmp_sym;
+	  } else {
+	    tmp_sym->dt_next = tmp_sym;
+	  }
+	  gfc_derived_types = tmp_sym;
         }
 
       return tmp_symtree;
@@ -4874,7 +4862,6 @@ generate_isocbinding_symbol (const char *mod_name,
       case ISOCBINDING_FUNPTR:
 	{
 	  gfc_symbol *dt_sym;
-	  gfc_dt_list **dt_list_ptr = NULL;
 	  gfc_component *tmp_comp = NULL;
 
 	  /* Generate real derived type.  */
@@ -4936,18 +4923,14 @@ generate_isocbinding_symbol (const char *mod_name,
 	  dt_sym->ts.u.derived = dt_sym;
 
 	  /* Add the symbol created for the derived type to the current ns.  */
-	  dt_list_ptr = &(gfc_derived_types);
-	  while (*dt_list_ptr != NULL && (*dt_list_ptr)->next != NULL)
-	    dt_list_ptr = &((*dt_list_ptr)->next);
-
-	  /* There is already at least one derived type in the list, so append
-	     the one we're currently building for c_ptr or c_funptr.  */
-	  if (*dt_list_ptr != NULL)
-	    dt_list_ptr = &((*dt_list_ptr)->next);
-	  (*dt_list_ptr) = gfc_get_dt_list ();
-	  (*dt_list_ptr)->derived = dt_sym;
-	  (*dt_list_ptr)->next = NULL;
-
+	  if (gfc_derived_types) {
+	    dt_sym->dt_next = gfc_derived_types->dt_next;
+	    gfc_derived_types->dt_next = dt_sym;
+	  } else {
+	    dt_sym->dt_next = dt_sym;
+	  }
+	  gfc_derived_types = dt_sym;
+      	  
 	  gfc_add_component (dt_sym, "c_address", &tmp_comp);
 	  if (tmp_comp == NULL)
 	    gcc_unreachable ();
Index: gcc/fortran/trans-types.c
===================================================================
--- gcc/fortran/trans-types.c	(revision 260682)
+++ gcc/fortran/trans-types.c	(working copy)
@@ -2534,7 +2534,7 @@ gfc_get_derived_type (gfc_symbol * derived, int co
   bool got_canonical = false;
   bool unlimited_entity = false;
   gfc_component *c;
-  gfc_dt_list *dt;
+  gfc_symbol *dt;
   gfc_namespace *ns;
   tree tmp;
   bool coarray_flag;
@@ -2599,13 +2599,18 @@ gfc_get_derived_type (gfc_symbol * derived, int co
 	   ns->translated && !got_canonical;
 	   ns = ns->sibling)
 	{
-	  dt = ns->derived_types;
-	  for (; dt && !canonical; dt = dt->next)
-	    {
-	      gfc_copy_dt_decls_ifequal (dt->derived, derived, true);
-	      if (derived->backend_decl)
-		got_canonical = true;
-	    }
+	  if (ns->derived_types) {
+	    dt = ns->derived_types;
+	    for (;;)
+	      {
+		gfc_copy_dt_decls_ifequal (dt, derived, true);
+		if (derived->backend_decl)
+		  got_canonical = true;
+		if (dt->dt_next == ns->derived_types)
+		  break;
+		dt = dt->dt_next;
+	      }
+	  }
 	}
     }
 
@@ -2867,9 +2872,16 @@ copy_derived_types:
 	}
     }
 
-  for (dt = gfc_derived_types; dt; dt = dt->next)
-    gfc_copy_dt_decls_ifequal (derived, dt->derived, false);
-
+  if (gfc_derived_types) {
+    dt = gfc_derived_types;
+    for (;;)
+      {
+	gfc_copy_dt_decls_ifequal (derived, dt, false);
+	if (dt->dt_next == gfc_derived_types)
+	  break;
+	dt = dt->dt_next;
+      }
+  }
   return derived->backend_decl;
 }
 

  reply	other threads:[~2018-05-29 20:25 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-05-24 22:53 Andrew Benson
2018-05-25  7:06 ` Richard Biener
2018-05-25  7:13   ` Richard Biener
2018-05-25 21:54   ` Andrew Benson
2018-05-28  9:54     ` Richard Biener
2018-05-29 20:25       ` Andrew Benson [this message]
2018-05-30  9:44         ` Richard Biener
2018-05-30 17:01           ` Andrew Benson
2018-05-30 18:25             ` Steve Kargl
2018-05-30 18:37               ` Andrew Benson
2018-05-30 20:43         ` Janus Weil
2018-05-30 22:22           ` Andrew Benson
2018-05-31  8:56             ` Janus Weil
2018-05-31 18:04               ` Andrew Benson
2018-06-01  6:14                 ` Janus Weil
2018-06-11 18:45                   ` Steve Kargl
2018-06-11 19:22                     ` Andrew Benson
2018-06-14  5:15                     ` Andrew Benson
2018-06-15  0:12                       ` Steve Kargl
2018-06-15  7:59                         ` Andrew Benson
2018-07-11  2:33                         ` Andrew Benson
2018-07-20 16:29                           ` Andrew Benson
2018-07-20 18:59                             ` Janus Weil
2018-07-20 19:02                               ` Andrew Benson
2018-07-20 19:10                                 ` Janus Weil
2018-07-20 20:04                                   ` Janus Weil
2018-07-20 20:22                                     ` Andrew Benson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=2946507.05iJNWrpSJ@andrew-precision-3520 \
    --to=abenson@carnegiescience.edu \
    --cc=fortran@gcc.gnu.org \
    --cc=richard.guenther@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).