[llvm-dev] How to write the same things as `opt` command in C++ API
via llvm-dev
llvm-dev at lists.llvm.org
Fri Mar 31 00:09:26 PDT 2017
You are right!
> I believe calling pm_builder.populateModulePassManager(pm); will cause a
bunch of passes to be ran as if you had ran 'opt -O2'
I modified like this:
// llvm::PassManagerBuilder pm_builder; // (deleted)
llvm::legacy::PassManager pm;
// pm_builder.populateModulePassManager(pm); // (deleted)
pm.add(llvm::createFunctionInliningPass()); // (added)
Then, my code worked the same result of `opt -inline`.
[output]
; ModuleID = 'my module'
define private i32 @b() {
entry:
%c = call i32 @b()
%res = add i32 2, %c
ret i32 %res
}
define i32 @main() {
entrypoint:
%b = call i32 @b()
ret i32 %b
}
Thank you,
Ryo
2017年3月31日(金) 15:57 <nwtgck at gmail.com>:
> 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/73ca3242/attachment-0001.html>
More information about the llvm-dev
mailing list