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

Ahmed Bougacha via llvm-dev
Tue, 07 Jun 2016 16:23:23 -0000

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
>