This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Another linker performance issue


> static bfd_boolean
> pe_undef_alias_cdecl_match (struct bfd_link_hash_entry *h, void *inf)
> {
>   int sl;
>   char *string = inf;
>   const char *hs = h->root.string;
> 
>   sl = strlen (string);
>   if (h->type == bfd_link_hash_undefined
>       && ((*hs == '@' && (!pe_details->underscored || *string == '_')
> 	   && strncmp (hs + 1, string + (pe_details->underscored != 0),
> 		       sl - (pe_details->underscored != 0)) == 0)
> 	  || strncmp (hs, string, sl) == 0)
>       && h->root.string[sl] == '@')
>     {
>       found_sym = h;
>       return FALSE;
>     }
>   return TRUE;
> }
> 
> static struct bfd_link_hash_entry *
> pe_find_cdecl_alias_match (char *name)
> {
>   found_sym = 0;
>   bfd_link_hash_traverse (link_info.hash, pe_undef_alias_cdecl_match,
> 			  (char *) name);
>   return sym;
> }


> In fact we traverse the hash table, looking for all symbols for a
> matching alias! For big applications this is not a proper
> implementation.

Even if there is no progress in choosing a better global strategy
for finding alias matches, the programmer can help the compiler generate
better code.  20% better is only 20%, but that's one minute
in this case.

Make two parametric subroutines, one for  (pe_details->underscored == 0)
and one for  (pe_details->underscored != 0) .  Check bfd_link_hash_undefined
before computing strlen().  Use the characteristic value of a comparison
operation to simplify code and avoid branching.  Use 'const' as much as
possible.

[Does the original code have a bug when it checks
(h->root.string[sl] == '@') even if (*hs == '@') ?
The index [sl] looks suspicious in that case.]

-----
static bfd_boolean
pe_undef_alias_cdecl_match (struct bfd_link_hash_entry const *const h,
    void const *const inf)
{
  if (h->type == bfd_link_hash_undefined) {
      char const *const hs = h->root.string;
      char const *const string = inf;
      int const sl = strlen (string);
      if (0 == strncmp (hs + ('@' == hs[0]), string, sl)
      &&  hs[sl] == '@') {
        found_sym = h;
        return FALSE;
      }
    }
  }
  return TRUE;
}

/* Note trailing underscore in subroutine name below. */
static bfd_boolean
pe_undef_alias_cdecl_match_ (struct bfd_link_hash_entry const *const h,
    void const *const inf)
{
  if (h->type == bfd_link_hash_undefined) {
      char const *const hs = h->root.string;
      char const *const string = inf;
      int const sl = strlen (string);
      if ('_' == string[0]
      &&  0 == strncmp (hs + ('@' == hs[0]), 1+ string, -1+ sl)
      &&  hs[sl] == '@') {
        found_sym = h;
        return FALSE;
      }
    }
  }
  return TRUE;
}

static struct bfd_link_hash_entry *
pe_find_cdecl_alias_match (char *name)
{
  found_sym = 0;
  if (pe_details->underscored)
    bfd_link_hash_traverse (link_info.hash, pe_undef_alias_cdecl_match_,
			    (char *) name);
  else
    bfd_link_hash_traverse (link_info.hash, pe_undef_alias_cdecl_match,
			    (char *) name);
  return sym;
}
-----

-- 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]