[llvm-dev] llvm intrinsics/libc/libm question

mats petersson via llvm-dev
Tue, 07 Jun 2016 16:42:29 -0000

Note that the C standard [no, I can't remember the exact section/paragraph]
says that "you should not use the names of existing functions in
<std*.h>,
<math.h>, <memory.h> and <string.h> [probably a few others
too] for your
own functions - the result of that is undefined" [I'm paraphrasing the
spec]. In other words, functions listed by the standard as part of those
header files are reserved functions, and if you use, for example, `acos` as
a function name, it's not well-defined what the compiler will do. In this
case, the compiler will think that it knows what `acos` does when it's
declared but not defined before the call. If it's defined as well as
declared before the use of it, the compiler actually knows what the
function does, and thus knows that it's not "standard `acos`". But
the
compiler could also produce an error or do other things in this case.

So, expecting clang + LLVM to handle this "correctly" (whatever you
believe
is correct) is perhaps a bit of wishful thinking.

It would of course be nice to have a warning saying "redeclaration of acos,
which is a library function". But as far as I see, the compiler is doing
what is within the spec.

--
Mats



On 7 June 2016 at 17:23, Ahmed Bougacha via llvm-dev <
llvm-dev at lists.llvm.org> wrote:

> On Tue, Jun 7, 2016 at 8:03 AM, Ryan Taylor via llvm-dev
> <llvm-dev at lists.llvm.org> wrote:
> > I'm trying to figure out exactly how the intrinsics/libc/libm work
in
> llvm.
>
> Intrinsics are basically "lesser" instructions that aren't
guaranteed
> to have first-class support (e.g., work on all targets). They are
> specified in the LangRef.
>
> Target intrinsics are similar to generic intrinsics, but are
> specifically only available on one target. They are (intentionally
> under-) specified in the various Intrinsics<Target>.td files.
>
> Some functions (libc, libm, and a few others) are recognized as having
> well-defined behavior for the target platform;  this information is in
> TargetLibraryInfo.
>
> > For example, this code return user defined function:
> >
> >
> > float acos(float x, float y)
> > {
> >     return x+y;
> > }
> >
> > float a;
> > void foo(float b, float c)
> > {
> >  a = acos(b, c);
> > }
> >
> >
> > But this code returns llvm.intrinsic:
> >
> >
> > float acos(float, float);
> >
> > float a;
> > void foo(float b, float c)
> > {
> >  a = acos(b, c);
> > }
> >
> > float acos(float x, float y)
> > {
> >  return x+y;
> > }
> >
> > What is the expected behavior here?
>
> I don't see how they can behave differently.  What IR are you seeing?
>
> > Also, there are certain "standard C library functions"
included in LLVM
> that
> > I'd like to remove without modifying core code, is this possible?
>
> If you're using clang: -fno-builtin=acos is what you're looking
for.
>
> If you're using llvm: when setting up your pass pipeline, you should
> create an instance of TargetLibraryInfo (an example is in
> tools/opt/opt.cpp), and either use:
> - setUnavailable(LibFunc::acos): this marks acos as
"unavailable",
> preventing optimizations from making assumptions about its behavior.
> Equivalent to clang -fno-builtin-acos
> - disableAllFunctions(): this marks all known functions as
> unavailable.  Equivalent to clang -fno-builtin
>
> > I'm also curious how LLVM handles pure functions in regards to
> > optimizations. For example, libm functions such as acos.
>
> Note that I don't think libm functions are pure on most platform,
> because they can modify errno (-ffast-math/-fno-math-errno disables
> that, though).
>
> > It appears that X86
> > doesn't have acos as an intrinsic and instead just calls a
function "tail
> > call @acos...", is this still able to be optimized.
>
> Yes, because TLI knows about the name 'acos'.  However, the
prototype
> needs to be reasonably correct ('double @acos(double)'), but
isn't in
> your example.  (Specifically, ConstantFolding checks that @acos only
> has one operand, but yours has two.)
>
> > I see the hardcoded
> > 'name' lookup for 'acos' in ConstantFolding.cpp. It
doesn't appear that
> if
> > you slightly change the name from 'acos' to say
'XXX_acos' in your libm
> > it'll still be optimized?
>
> Correct, it won't be.
>
> It's possible to make that happen with a few patches, but there has
> been no need for that yet:
>
> - replace the various calls to TLI::has() or
> TLI::getLibFunc(StringRef, Func&) with TLI::getLibFunc(Function&,
> Func&).  Any of the former are probably hiding bugs related to
> incorrect prototypes
>
> - teach TLI::getLibFunc to check function availability using the
> custom name instead of always checking the standard name.  Again, this
> is (arguably) hiding bugs, where we recognize the standard name even
> though it's not what the target uses
>
> - fix canConstantFoldCallTo to pass it TLI or maybe remove it entirely
> (it's always used before ConstantFoldCall, which does check TLI)
>
> - tell TLI that 'acos' is available with name 'XXX_acos'
for your target
>
> -Ahmed
>
> > Thanks,
> >
> > Ryan
> >
> > _______________________________________________
> > LLVM Developers mailing list
> > llvm-dev at lists.llvm.org
> > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
> >
> _______________________________________________
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20160607/95b54324/attachment.html>