[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