Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 24 Mar 2005 20:45:53 +1100 (EST)
From:      Bruce Evans <bde@zeta.org.au>
To:        Vinod Kashyap <vkashyap@amcc.com>
Cc:        freebsd-amd64@freebsd.org
Subject:   Re: undefined reference to `memset'
Message-ID:  <20050324194817.N97600@delplex.bde.org>
In-Reply-To: <20050324182524.J97436@delplex.bde.org>
References:  <IDTR9T00.LMF@hadar.amcc.com> <20050324182524.J97436@delplex.bde.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Thu, 24 Mar 2005, Bruce Evans wrote:

> On Wed, 23 Mar 2005, Vinod Kashyap wrote:
>
>> If any kernel module has the following, or a similar line in it:
>> -----
>> char x[100] = {0};
>> -----
>> building of the GENERIC kernel on FreeBSD 5 -STABLE for amd64
>> as of 03/19/05, fails with the following message at the time of linking:
>> "undefined reference to `memset'".
>> ...
> ...
>> Anyone knows what's happening?
>
> gcc is expecting that memset() is in the library, but the FreeBSD kernel
> is freestanding and happens not to have memset() in its library.

As to why gcc calls memset() on amd64's but not on i386's:
- gcc-3.3.3 doesn't call memset() on amd64's either.
- gcc-3.4.2 on amd64's calls memset() starting with an array size of
   65.  It uses mov[qlwb] for sizes up to 16, then stos[qlwb] up to
   size 64.  gcc-3.3.3 on i386's uses mov[lwb] for sizes up to 8,
   then stos[lwb] for all larger sizes.
- the relevant change seems to be:

% Index: i386.c
% ===================================================================
% RCS file: /home/ncvs/src/contrib/gcc/config/i386/i386.c,v
% retrieving revision 1.20
% retrieving revision 1.21
% diff -u -2 -r1.20 -r1.21
% --- i386.c	19 Jun 2004 20:40:00 -0000	1.20
% +++ i386.c	28 Jul 2004 04:47:35 -0000	1.21
% @@ -437,26 +502,36 @@
% ...
% +const int x86_rep_movl_optimal = m_386 | m_PENT | m_PPRO | m_K6;
% ...

Note that rep_movl is considered optimal on i386's but not on amd64's.

% @@ -10701,6 +11427,10 @@
%        /* In case we don't know anything about the alignment, default to
%           library version, since it is usually equally fast and result in
% -         shorter code.  */
% -      if (!TARGET_INLINE_ALL_STRINGOPS && align < UNITS_PER_WORD)
% +         shorter code.
% +
% +	 Also emit call when we know that the count is large and call overhead
% +	 will not be important.  */
% +      if (!TARGET_INLINE_ALL_STRINGOPS
% +	  && (align < UNITS_PER_WORD || !TARGET_REP_MOVL_OPTIMAL))
%  	return 0;
%

TARGET_REP_MOVL_OPTIMAL is x86_rep_movl_optimal modulo a mask.  It is
zero for amd64's, so 0 is returned for amd64's here unless you use -mfoo
to set TARGET_INLINE_ALL_STRINGOPS.  Returning 0 gives the library call
instead of a stringop.

This is in i386_expand_clrstr().  There is an identical change in
i386_expand_movstr() that gives library calls to memcpy() for (at
least) copying structs.

Bruce



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20050324194817.N97600>