0

I am building an IR module using the IRBuilder, and I want to be able to call libc functions from inside this module (For the most part math functions like atan that don't have intrinsics).

I think I need to add them using getOrInsertLibFunc , is that correct? This requires me to have a TargetLibraryInfo instance.

How do I obtain one, and is there an example anywhere that inserts the library function and shows how to create a call to it using the IRBuilder?

Note that I know how to create an external link to the std::atan function that is available in C++, but I specifically want to insert a llvm::LibFunc since I think the LLVM function passes are better able to reason about its behaviour.

(Interestingly, the function passes I use will convert a sin(x)/cos(x) (intrinsics) to a tan(x), but I don't know how insert tan (not an intrinsic) myself.)

Edit: I got the following to work ("data" is just my own struct where I keep around pointers):

auto triple = llvm::sys::getDefaultTargetTriple();
data->libinfoimpl = std::make_unique<llvm::TargetLibraryInfoImpl>(llvm::Triple(triple));
data->libinfo     = std::make_unique<llvm::TargetLibraryInfo>(*data->libinfoimpl);
auto doubleTy = llvm::Type::getDoubleTy(*data->context);
llvm::FunctionType *fun_type = llvm::FunctionType::get(doubleTy, {doubleTy}, false);

llvm::getOrInsertLibFunc(data->module.get(), *data->libinfo, llvm::LibFunc_tan, fun_type);

And insert the function call using

auto fun = data->module->getFunction("tan");
result = data->builder->CreateCall(fun, arg);

Not sure if this is the ideal way to do it, but it works. If anybody knows a better way, please let me know!

Edit again: I have a follow-up question: If I create a call to tan(atan(x)) the optimizer knows that it should just return x, but for some reason it still creates the call to atan() (but not to tan). Why does this happen, and can I make it not call atan? Example:

%res = tail call fast double @atan(double %arg)
store double %arg, ptr %state_vars, align 8

I.e. it calls atan on arg, but it does not use the result %res, so why wasn't that call optimized away?

  • If you have solved your problem, please post it as an actual answer. – Some programmer dude Aug 25 '22 at 15:13
  • And for new questions, please post a new question (which can reference this one). Please take some time to read [the help pages](http://stackoverflow.com/help), take the SO [tour], read [ask], as well as [this question checklist](https://codeblog.jonskeet.uk/2012/11/24/stack-overflow-question-checklist/). – Some programmer dude Aug 25 '22 at 15:29
  • The way you're inserting the calls using getOrInsertLibFunc is correct. Just be aware that, in the context of an LLVM Pass, the TargetLibraryInfo is an analysis you would get from the PassManager. Also, be aware that the target triple you are using to initialize your TargetLibraryInfoImpl must match the triple of the module you're working on. – jmmartinez Aug 29 '22 at 07:45
  • For the later question "I.e. it calls atan on arg, but it does not use the result %res, so why wasn't that call optimized away?". The optimization that you want should be done if you pass `-ffast-math` flag to the compiler (https://godbolt.org/z/sPbnq6fro vs https://godbolt.org/z/1Ezq9aT9W). To know more, please refer to https://stackoverflow.com/questions/7420665/what-does-gccs-ffast-math-actually-do . – jmmartinez Aug 29 '22 at 07:53
  • @jmmartinez Thank you for the reply! I also noticed that clang does it correctly. I am building my own jit compiler. I did set builder->setFastMathFlags(llvm::FastMathFlags::getFast()); on the IRbuilder, and I also process the module using a ModulePassManager constructed using pb.buildPerModuleDefaultPipeline(llvm::OptimizationLevel::O2) where pb is a PassBuilder . I'm not sure how to set more fast math flags than I already do. – Magnus Dahler Norling Aug 29 '22 at 09:27
  • @MagnusDahlerNorling I see. I don't know the exact answer but I have a few pointers to give you. I checked clang's code for `-ffast-math` and it seems it sets up several flags (see `setFPPreciseEnabled` at https://clang.llvm.org/doxygen/LangOptions_8h_source.html#l00821). Some of these flags affect some attributes in floating point instructions (https://llvm.org/docs/LangRef.html#fast-math-flags) while others as function attributes (some are listed here https://clang.llvm.org/doxygen/CGCall_8cpp_source.html#l01857). – jmmartinez Aug 29 '22 at 11:34
  • Also, if you're using an `IRBuilder` to emit instructions, you could set the `FastMathFlags` once with `setFastMathFlags`: https://llvm.org/doxygen/classllvm_1_1IRBuilderBase.html#a6370e29617c71c8081bbbc68d6058403 – jmmartinez Aug 29 '22 at 11:36

0 Answers0