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>