[llvm-dev] How to write the same things as `opt` command in C++ API
via llvm-dev
llvm-dev at lists.llvm.org
Thu Mar 30 23:27:47 PDT 2017
Hi, I'm Ryo Ota. I'm using LLVM 3.8.1. I have a quesion about inlining
function in C++ API.
I'd like to inline some functions in a module in the same way as `opt
-inline` command. But my C++ code didn't work what I want to do.
For example, by using `opt -inline` command,`main.ll` is converted into the
`inlined.ll`(`opt` command worked what I want to do)
[main.ll (Not inlined)]
; ModuleID = 'my module'
define private i32 @a() {
entry:
%c = call i32 @c()
ret i32 %c
}
define private i32 @b() {
entry:
%a = call i32 @a()
%b = call i32 @b() ; key-point (infinite-recursive)
%res = add i32 %a, %b
ret i32 %res
}
define private i32 @c() {
entry:
ret i32 2
}
define i32 @main() {
entrypoint:
%b = call i32 @b()
ret i32 %b
}
[inlined.ll] Made by `opt-3.8 -S -inline main.ll > inlined.ll` command
define private i32 @b() {
entry:
%b = call i32 @b()
%res = add i32 2, %b ; a is inlined. (a == c, c == 2)
ret i32 %res
}
define i32 @main() {
entrypoint:
%b = call i32 @b()
ret i32 %b
}
`opt` command worked what I want to do. But my C++ doesn't work like
`opt` command. The following code is my C++ code, which didn't work I
what to do. My code has `undef`. `inlined.ll` doen't have `undef`.
@main returns @b(). But below code, @main returns undef. I think @b
has a infinite-recursive call. But I don't want it to dump `undef`.
Could you tell me how to stop inlining of `undef`?
[output of C++ doe]
; ModuleID = 'my module'
; Function Attrs: norecurse nounwind readnone
define i32 @main() #0 {
entrypoint:
ret i32 undef
}
attributes #0 = { norecurse nounwind readnone }
[C++ code]
/// @brief context
llvm::LLVMContext context;
/// @brief module
std::unique_ptr<llvm::Module> module =
llvm::make_unique<llvm::Module>("my module", context);
llvm::PassManagerBuilder pm_builder;
llvm::legacy::PassManager pm;
pm_builder.Inliner = llvm::createFunctionInliningPass();
pm_builder.populateModulePassManager(pm);
/// @brief Create function type (void) => i32
llvm::FunctionType *commonfuncType =
llvm::FunctionType::get(llvm::Type::getInt32Ty(context), {}, false);
/// @brief Create a function (define i32 a())
llvm::Function *aFun =
llvm::Function::Create(commonfuncType, llvm::Function::PrivateLinkage,
"a", module.get());
/// @brief Create a function (define i32 b())
llvm::Function *bFun =
llvm::Function::Create(commonfuncType, llvm::Function::PrivateLinkage,
"b", module.get());
/// @brief Create a function (define i32 c())
llvm::Function *cFun =
llvm::Function::Create(commonfuncType, llvm::Function::PrivateLinkage,
"c", module.get());
// Body of the `a` function
{
/// @brief Set entry label
llvm::BasicBlock *block = llvm::BasicBlock::Create(context, "entry", aFun);
/// @brief builder
llvm::IRBuilder<> builder(block);
builder.SetInsertPoint(block);
llvm::CallInst *cCall = builder.CreateCall(cFun, {}, "c");
llvm::Value *res = cCall;
builder.CreateRet(res);
llvm::verifyFunction(*aFun);
}
// Body of the `b` function
{
/// @brief Set entry label
llvm::BasicBlock *block = llvm::BasicBlock::Create(context, "entry", bFun);
/// @brief builder
llvm::IRBuilder<> builder(block);
builder.SetInsertPoint(block);
llvm::CallInst *aCall = builder.CreateCall(aFun, {}, "a");
llvm::CallInst *cCall = builder.CreateCall(bFun, {}, "c");
llvm::Value *res = builder.CreateAdd(aCall, cCall, "res");
builder.CreateRet(res);
llvm::verifyFunction(*bFun);
}
// Body of the `c` function
{
/// @brief Set entry label
llvm::BasicBlock *block = llvm::BasicBlock::Create(context, "entry", cFun);
/// @brief builder
llvm::IRBuilder<> builder(block);
builder.SetInsertPoint(block);
llvm::Value *res =
llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), 2);
builder.CreateRet(res);
llvm::verifyFunction(*cFun);
}
/// @brief Start of Main function
{
llvm::FunctionType *const func_type =
llvm::FunctionType::get(llvm::Type::getInt32Ty(context), false);
llvm::Function *const main_func =
llvm::Function::Create(func_type, llvm::Function::ExternalLinkage,
"main",
module.get());
llvm::BasicBlock *const entry = llvm::BasicBlock::Create(context,
"entrypoint", main_func);
llvm::IRBuilder<> builder(entry);
builder.SetInsertPoint(entry);
llvm::CallInst *bCall = builder.CreateCall(bFun, {}, "b");
builder.CreateRet(bCall);
llvm::verifyFunction(*main_func);
}
pm.run(*module);
module->dump();
if you comment-outed `pm.run(*module);` you have the following output.
define private i32 @a() {
entry:
%c = call i32 @c()
ret i32 %c
}
define private i32 @b() {
entry:
%a = call i32 @a()
%c = call i32 @b()
%res = add i32 %a, %c
ret i32 %res
}
define private i32 @c() {
entry:
ret i32 2
}
define i32 @main() {
entrypoint:
%b = call i32 @b()
ret i32 %b
}
Sincerely,
Ryo
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20170331/292ae43c/attachment.html>
More information about the llvm-dev
mailing list