Handling of built-in functions

Hi,

I'm trying to add support in my back end for certain functions that are seen as built-in by the target. Some of these functions can be implemented in a) LLVM, and some in b) the native target language.

My approach to case a) is to write the built-in function implementation in C, compile it to LLVM using Clang, link it to the module that uses it and finally add a pass to inline it. The last two steps can be made inside a ModulePass. The definition of TargetMachine allows for any pass manager deriving form BasicPass to be passed to AddPassesToEmitFile. However, I see that llc uses a FunctionPassManager for all the passes. A (module)PassManager is used only if the target implements AddPassesToEmitWholeFile but the comments on the base class discourage this path. Am I approaching the problem the wrong way?

I haven't worked much on case b) but my idea was to use a similar approach but instead of writing the built-in function implementation in straight C an asm block would be used to insert the code. Does this make sense?

Thanks,
Javier

Hello,

Just wondering if anyone had ideas on this and I apologize if bumps are frowned upon.

Thanks,
Javier

Hi Javier,

I'm not the right person to answer your question, but since no one
else took it: I believe this is a situation where the backend would
typically emit a call the the compiler's runtime library (e.g.,
libgcc).

While it isn't currently completely wired up, we do have our own
compiler runtime library available under the compiler-rt project in
the LLVM repo.

- Daniel

Hi Daniel,

Thanks for the reply. If I understand correctly, your suggestion is to have the backend call a library that handles the built-in functions. Would the calls need to be lowered and redirected (e.g. by a big switch statement or a jump table) to the corresponding function in the library?

Thanks,
Javier

I don't see why. Your compiler would just do a declare and then a
call, and your runtime function gets called.

The issue is that there is no runtime function. I'm not sure we're in the
same page but just in case we aren't I'm trying to provide support for
built-in functions at compilation time. Some functions can be expressed in
LLVM and others only in the target language. For the first group I'm trying
to inline the implementation in a module pass added in addPassesToEmitFile.
For the second I'm thinking of using an asm node to insert the
implementation.

My first question was if the approach is correct; the second was how to add
the module pass if addPassesToEmitFile gets a FunctionPAssManager from otp.

Thanks,
Javier

I don't see why. Your compiler would just do a declare and then a
call, and your runtime function gets called.

Hi Daniel,

Thanks for the reply. If I understand correctly, your suggestion is to
have
the backend call a library that handles the built-in functions. Would

the

The last sentence should have llc instead of opt.

The issue is that there is no runtime function. I'm not sure we're in the
same page but just in case we aren't I'm trying to provide support for
built-in functions at compilation time. Some functions can be expressed

in

LLVM and others only in the target language. For the first group I'm

trying

to inline the implementation in a module pass added in

addPassesToEmitFile.

For the second I'm thinking of using an asm node to insert the
implementation.

My first question was if the approach is correct; the second was how to

add

the module pass if addPassesToEmitFile gets a FunctionPassManager from

llc.

Thanks,
Javier

I don't see why. Your compiler would just do a declare and then a
call, and your runtime function gets called.

Hi Daniel,

Thanks for the reply. If I understand correctly, your suggestion is to
have
the backend call a library that handles the built-in functions. Would

the

calls need to be lowered and redirected (e.g. by a big switch statement
or a
jump table) to the corresponding function in the library?

Thanks,
Javier

Hi Javier,

I'm not the right person to answer your question, but since no one
else took it: I believe this is a situation where the backend would
typically emit a call the the compiler's runtime library (e.g.,
libgcc).

While it isn't currently completely wired up, we do have our own
compiler runtime library available under the compiler-rt project in
the LLVM repo.

- Daniel

Hi,

I'm trying to add support in my back end for certain functions that are
seen as built-in by the target. Some of these functions can be
implemented in a) LLVM, and some in b) the native target language.

My approach to case a) is to write the built-in function implementation
in C, compile it to LLVM using Clang, link it to the module that uses

it

and finally add a pass to inline it. The last two steps can be made
inside a ModulePass. The definition of TargetMachine allows for any

pass

manager deriving form BasicPass to be passed to AddPassesToEmitFile.
However, I see that llc uses a FunctionPassManager for all the passes.

A

(module)PassManager is used only if the target implements
AddPassesToEmitWholeFile but the comments on the base class discourage
this path. Am I approaching the problem the wrong way?

I haven't worked much on case b) but my idea was to use a similar
approach but instead of writing the built-in function implementation in
straight C an asm block would be used to insert the code. Does this

make

If you add an ASM node, you won't be able to JIT the result. I don't
know if you care about that or not, but ASM nodes aren't supported by
the execution engine.

(If you do want to JIT, you could always dump the machine code to
memory and link its location to a global using
ExecutionEngine::addGlobalMapping), and then JIT whatever needs to
call it. Obviously, it won't get inlined if you do that.)

One of the standard opt passes should inline the first group for you
if you mark your function with the alwaysinline attribute.

I don't need to JIT the result, what I'm generating is a .s with the kernel
in the target language.

I've successfully used opt to inline the functions. The issue is that llc,
unlike opt, doesn't have a PassManager and I get an error if I try to add a
module pass to a FunctionPassManager. The function addPassesToEmitFile can
take a PassManager but the implementation of llc only uses a
FunctionPassManager. How can I add the inlining pass in this case?

Thanks,
Javier

If you add an ASM node, you won't be able to JIT the result. I don't
know if you care about that or not, but ASM nodes aren't supported by
the execution engine.

(If you do want to JIT, you could always dump the machine code to
memory and link its location to a global using
ExecutionEngine::addGlobalMapping), and then JIT whatever needs to
call it. Obviously, it won't get inlined if you do that.)

One of the standard opt passes should inline the first group for you
if you mark your function with the alwaysinline attribute.

The issue is that there is no runtime function. I'm not sure we're in

the

same page but just in case we aren't I'm trying to provide support for
built-in functions at compilation time. Some functions can be expressed
in
LLVM and others only in the target language. For the first group I'm
trying
to inline the implementation in a module pass added in
addPassesToEmitFile.
For the second I'm thinking of using an asm node to insert the
implementation.

My first question was if the approach is correct; the second was how to
add
the module pass if addPassesToEmitFile gets a FunctionPAssManager from
otp.

Thanks,
Javier

I don't see why. Your compiler would just do a declare and then a
call, and your runtime function gets called.

Hi Daniel,

Thanks for the reply. If I understand correctly, your suggestion is to
have
the backend call a library that handles the built-in functions. Would

the

calls need to be lowered and redirected (e.g. by a big switch

statement

or a
jump table) to the corresponding function in the library?

Thanks,
Javier

Hi Javier,

I'm not the right person to answer your question, but since no one
else took it: I believe this is a situation where the backend would
typically emit a call the the compiler's runtime library (e.g.,
libgcc).

While it isn't currently completely wired up, we do have our own
compiler runtime library available under the compiler-rt project in
the LLVM repo.

- Daniel

Hi,

I'm trying to add support in my back end for certain functions that

are

seen as built-in by the target. Some of these functions can be
implemented in a) LLVM, and some in b) the native target language.

My approach to case a) is to write the built-in function

implementation

in C, compile it to LLVM using Clang, link it to the module that uses
it
and finally add a pass to inline it. The last two steps can be made
inside a ModulePass. The definition of TargetMachine allows for any
pass
manager deriving form BasicPass to be passed to AddPassesToEmitFile.
However, I see that llc uses a FunctionPassManager for all the passes.
A
(module)PassManager is used only if the target implements
AddPassesToEmitWholeFile but the comments on the base class discourage
this path. Am I approaching the problem the wrong way?

I haven't worked much on case b) but my idea was to use a similar
approach but instead of writing the built-in function implementation

in