via llvm-dev
2017-Mar-31 06:27 UTC
[llvm-dev] How to write the same things as `opt` command in C++ API
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>
Craig Topper via llvm-dev
2017-Mar-31 06:50 UTC
[llvm-dev] How to write the same things as `opt` command in C++ API
I believe calling pm_builder.populateModulePassManager(pm); will cause a bunch of passes to be ran as if you had ran 'opt -O2'. What do you get if you run 'opt-3.8 -S -O2 main.ll'? ~Craig On Thu, Mar 30, 2017 at 11:27 PM, via llvm-dev <llvm-dev at lists.llvm.org> wrote:> 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 > > _______________________________________________ > 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/20170330/d27f79b5/attachment.html>
via llvm-dev
2017-Mar-31 06:57 UTC
[llvm-dev] How to write the same things as `opt` command in C++ API
Thank you very much your fast response!
When typed 'opt-3.8 -S -O2 main.ll', I got:
; ModuleID = 'main.ll'
; Function Attrs: norecurse nounwind readnone
define i32 @main() #0 {
entrypoint:
ret i32 undef
}
attributes #0 = { norecurse nounwind readnone }
This result is the same as my C++ code.
I'm not sure my use of `llvm::legacyPassManeger` and
`llvm::PassManagerBuilder`. To write inlining in C++, I explored in llvm's
Github and other repositories which use LLVM, then I wrote the C++ code.
I'd like to be taught the correct use.
Sincerely,
Ryo
2017年3月31日(金) 15:50 Craig Topper <craig.topper at gmail.com>:
> I believe calling pm_builder.populateModulePassManager(pm); will cause a
> bunch of passes to be ran as if you had ran 'opt -O2'. What do you
get if
> you run 'opt-3.8 -S -O2 main.ll'?
>
> ~Craig
>
> On Thu, Mar 30, 2017 at 11:27 PM, via llvm-dev <llvm-dev at
lists.llvm.org>
> wrote:
>
> 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
>
> _______________________________________________
> 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/20170331/52b0de81/attachment.html>