LLVM Bugzilla is read-only and represents the historical archive of all LLVM issues filled before November 26, 2021. Use github to submit LLVM bugs

Bug 9795 - Regression: can't compile Valgrind with 2.9 whereas 2.8 was OK
Summary: Regression: can't compile Valgrind with 2.9 whereas 2.8 was OK
Status: RESOLVED INVALID
Alias: None
Product: clang
Classification: Unclassified
Component: -New Bugs (show other bugs)
Version: 2.9
Hardware: All All
: P normal
Assignee: Unassigned Clang Bugs
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-04-25 16:04 PDT by jseward
Modified: 2011-04-25 16:51 PDT (History)
2 users (show)

See Also:
Fixed By Commit(s):


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description jseward 2011-04-25 16:04:00 PDT
I can't build a working Valgrind using clang-2.9, whereas I could
using clang-2.8.  I think this is due to an idiom recognition pass in
LLVM spotting a loop that can be turned into a call to memset().
Here's the deal:

Valgrind tool executables (the big files "valgrind-amd64-darwin", etc)
are statically linked and completely freestanding; we do not link in
any of libc nor libgcc.  That means we have our own mini-libc.  The
reasons for this aren't relevant here.

So for example we have our own memset (omitting the vectorised loops):

  void* vgPlain_memset ( void *destV, Int c, SizeT sz )
  {
     Char* d = (Char*)destV;
     while (sz >= 1) {
        d[0] = c;
        d++;
        sz--;
     }
     return destV;
  }

When built by gcc, gcc would sometimes insert calls to memset() for
whatever reason.  Since we are completely freestanding, these cause
the link to fail, so we insert a hook that routes through to the
above function:

  void* memset(void *s, int c, SizeT n) {
     return vgPlain_memset(s,c,n);
  }

With gcc that all works fine.  But clang comes along, recognises
the vgPlain_memset loop as a memset idiom, and converts it into
a call to memset().  Infinite recursion leading to segfault.  Bah!

Below is the assembly for vgPlain_memset.  Note the absence of a
loop, plus the call to memset().

This is happening at -O2 and -O.  I have to back off to -O0 to
stop it happening.  That's obviously undesirable.  How can I 
selectively disable this idiom recognition pass?

000000003802f9b0 <vgPlain_memset>:
    3802f9b0:   53                      push   %rbx
    3802f9b1:   48 85 d2                test   %rdx,%rdx
    3802f9b4:   48 89 fb                mov    %rdi,%rbx
    3802f9b7:   74 0c                   je     3802f9c5 <vgPlain_memset+0x15>
    3802f9b9:   40 0f b6 f6             movzbl %sil,%esi
    3802f9bd:   48 89 df                mov    %rbx,%rdi
    3802f9c0:   e8 3b 50 00 00          callq  38034a00 <memset>
    3802f9c5:   48 89 d8                mov    %rbx,%rax
    3802f9c8:   5b                      pop    %rbx
    3802f9c9:   c3                      retq
Comment 1 Chris Lattner 2011-04-25 16:08:26 PDT
Hi Julian,

Building with -fno-builtin or -ffree-standing should disable it.  Does this work for you?

-Chris
Comment 2 Chris Lattner 2011-04-25 16:08:43 PDT
-ffreestanding that is.
Comment 3 jseward 2011-04-25 16:21:04 PDT
(In reply to comment #2)
> -ffreestanding that is.

Wow, that's quick :)  -ffreestanding produces something that works.
Thanks!  I didn't test -fno-builtin on the assumption that it removes all
the __builtin_blah stuff, and we rely on some of that.
Comment 4 Chris Lattner 2011-04-25 16:51:47 PDT
Great, happy to help.  This should work with GCC also, FWIW.