[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