<div dir="ltr">Hi, I'm Ryo Ota. I'm using LLVM 3.8.1. I have a quesion about inlining function in C++ API.<div><br></div><div>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.</div><div><br></div><div>For example, by using `opt -inline` command,`main.ll` is converted into the `inlined.ll`(<span style="font-family:menlo;font-size:9pt">`opt` command worked wh</span><span style="font-family:menlo;font-size:9pt">at I want to do</span>)</div><div><br></div><div>[main.ll (Not inlined)]</div><div><pre style="font-family:menlo;font-size:9pt"><span style="color:rgb(128,128,128);font-style:italic">; ModuleID = 'my module'<br></span><span style="color:rgb(128,128,128);font-style:italic"><br></span><span style="color:rgb(0,0,128);font-weight:bold">define private </span>i32 @a() {<br><span style="font-weight:bold">entry:<br></span><span style="font-weight:bold"> </span>%c <span style="color:rgb(0,0,128);font-weight:bold">= call </span>i32 @c()<br> <span style="color:rgb(0,0,128);font-weight:bold">ret </span>i32 %c<br>}<br><br><span style="color:rgb(0,0,128);font-weight:bold">define private </span>i32 @b() {<br><span style="font-weight:bold">entry:<br></span><span style="font-weight:bold"> </span>%a <span style="color:rgb(0,0,128);font-weight:bold">= call </span>i32 @a()<br> %b <span style="color:rgb(0,0,128);font-weight:bold">= call </span>i32 @b() <span style="color:rgb(128,128,128);font-style:italic">; key-point (infinite-recursive)<br></span><span style="color:rgb(128,128,128);font-style:italic"> </span>%res <span style="color:rgb(0,0,128);font-weight:bold">= add </span>i32 %a, %b<br> <span style="color:rgb(0,0,128);font-weight:bold">ret </span>i32 %res<br>}<br><br><span style="color:rgb(0,0,128);font-weight:bold">define private </span>i32 @c() {<br><span style="font-weight:bold">entry:<br></span><span style="font-weight:bold"> </span><span style="color:rgb(0,0,128);font-weight:bold">ret </span>i32 <span style="color:rgb(0,0,255)">2<br></span>}<br><br><span style="color:rgb(0,0,128);font-weight:bold">define </span>i32 @main() {<br><span style="font-weight:bold">entrypoint:<br></span><span style="font-weight:bold"> </span>%b <span style="color:rgb(0,0,128);font-weight:bold">= call </span>i32 @b()<br> <span style="color:rgb(0,0,128);font-weight:bold">ret </span>i32 %b<br></pre><pre style="font-family:menlo;font-size:9pt"><span style="font-size:9pt">}</span><span style="font-family:sans-serif;font-size:small"> </span><br></pre><pre style="font-family:menlo;font-size:9pt"><span style="font-family:sans-serif;font-size:small"><br></span></pre><pre style="font-family:menlo;font-size:9pt"><span style="font-family:sans-serif;font-size:small"><br></span></pre><pre style="font-family:menlo;font-size:9pt"><span style="font-family:sans-serif;font-size:small">[inlined.ll] Made by `</span><span style="font-size:11px">opt-3.8 -S -inline main.ll > inlined.ll</span><span style="font-family:sans-serif;font-size:small">` command</span></pre><pre style="font-family:menlo;font-size:9pt"><span style="color:rgb(0,0,128);font-weight:bold">define private </span>i32 @b() {<br><span style="font-weight:bold">entry:<br></span><span style="font-weight:bold"> </span>%b <span style="color:rgb(0,0,128);font-weight:bold">= call </span>i32 @b()<br> %res <span style="color:rgb(0,0,128);font-weight:bold">= add </span>i32 <span style="color:rgb(0,0,255)">2</span>, %b <span style="color:rgb(128,128,128);font-style:italic">; a is inlined. (a == c, c == 2) <br></span><span style="color:rgb(128,128,128);font-style:italic"> </span><span style="color:rgb(0,0,128);font-weight:bold">ret </span>i32 %res<br>}<br><br><span style="color:rgb(0,0,128);font-weight:bold">define </span>i32 @main() {<br><span style="font-weight:bold">entrypoint:<br></span><span style="font-weight:bold"> </span>%b <span style="color:rgb(0,0,128);font-weight:bold">= call </span>i32 @b()<br> <span style="color:rgb(0,0,128);font-weight:bold">ret </span>i32 %b<br><span style="font-size:9pt">}</span><br></pre><pre style="font-family:menlo;font-size:9pt"><span style="font-size:9pt"><br></span></pre><pre style="font-family:menlo;font-size:9pt"><span style="font-size:9pt"><br></span></pre><pre style="font-family:menlo;font-size:9pt"><span style="font-size:9pt">`opt` command worked wh</span><span style="font-size:9pt">at 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`.</span></pre><pre style="font-family:menlo;font-size:9pt"><span style="font-size:9pt">@main returns @b(). But below code, @main returns undef. </span><span style="font-size:9pt">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`?</span></pre><pre style="font-family:menlo;font-size:9pt"><div><br></div><div><br></div><div><br></div><div><br></div></pre><pre style="font-family:menlo;font-size:9pt">[output of C++ doe]</pre><pre style="font-family:menlo;font-size:9pt">; ModuleID = 'my module'
; Function Attrs: norecurse nounwind readnone
define i32 @main() #0 {
entrypoint:
ret i32 undef
}
attributes #0 = { norecurse nounwind readnone }<br></pre><pre style="font-family:menlo;font-size:9pt"><br></pre><pre style="font-family:menlo;font-size:9pt"><br></pre><pre style="font-family:menlo;font-size:9pt">[C++ code]</pre><pre style="font-family:menlo;font-size:9pt"><span style="color:rgb(128,128,128);font-style:italic">/// @brief context<br></span><span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">LLVMContext </span>context;<br><span style="color:rgb(128,128,128);font-style:italic">/// @brief module<br></span><span style="color:rgb(0,128,128)">std</span>::<span style="color:rgb(0,128,128)">unique_ptr</span><<span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">Module</span>> module = <span style="color:rgb(0,128,128)">llvm</span>::make_unique<<span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">Module</span>>(<span style="color:rgb(0,128,0);font-weight:bold">"my module"</span>, context);<br><br><span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">PassManagerBuilder </span>pm_builder;<br><br><span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">legacy</span>::<span style="color:rgb(0,128,128)">PassManager </span>pm;<br><br>pm_builder.<span style="color:rgb(102,14,122)">Inliner </span>= <span style="color:rgb(0,128,128)">llvm</span>::createFunctionInliningPass();<br><br>pm_builder.populateModulePassManager(pm);<br><br><br><span style="color:rgb(128,128,128);font-style:italic">/// @brief Create function type (void) => i32<br></span><span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">FunctionType </span>*commonfuncType = <span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">FunctionType</span>::get(<span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">Type</span>::getInt32Ty(context), {}, <span style="color:rgb(0,0,128);font-weight:bold">false</span>);<br><br><span style="color:rgb(128,128,128);font-style:italic">/// @brief Create a function (define i32 a())<br></span><span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">Function </span>*aFun = <span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">Function</span>::Create(commonfuncType, <span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">Function</span>::<span style="color:rgb(102,14,122);font-weight:bold;font-style:italic">PrivateLinkage</span>, <span style="color:rgb(0,128,0);font-weight:bold">"a"</span>, module.get());<br><span style="color:rgb(128,128,128);font-style:italic">/// @brief Create a function (define i32 b())<br></span><span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">Function </span>*bFun = <span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">Function</span>::Create(commonfuncType, <span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">Function</span>::<span style="color:rgb(102,14,122);font-weight:bold;font-style:italic">PrivateLinkage</span>, <span style="color:rgb(0,128,0);font-weight:bold">"b"</span>, module.get());<br><span style="color:rgb(128,128,128);font-style:italic">/// @brief Create a function (define i32 c())<br></span><span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">Function </span>*cFun = <span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">Function</span>::Create(commonfuncType, <span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">Function</span>::<span style="color:rgb(102,14,122);font-weight:bold;font-style:italic">PrivateLinkage</span>, <span style="color:rgb(0,128,0);font-weight:bold">"c"</span>, module.get());<br><br><br><br><span style="color:rgb(128,128,128);font-style:italic">// Body of the `a` function<br></span>{<br> <span style="color:rgb(128,128,128);font-style:italic">/// @brief Set entry label<br></span><span style="color:rgb(128,128,128);font-style:italic"> </span><span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">BasicBlock </span>*block = <span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">BasicBlock</span>::Create(context, <span style="color:rgb(0,128,0);font-weight:bold">"entry"</span>, aFun);<br> <span style="color:rgb(128,128,128);font-style:italic">/// @brief builder<br></span><span style="color:rgb(128,128,128);font-style:italic"> </span><span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">IRBuilder</span><> builder(block);<br> builder.SetInsertPoint(block);<br><br> <span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">CallInst </span>*cCall = builder.CreateCall(cFun, {}, <span style="color:rgb(0,128,0);font-weight:bold">"c"</span>);<br><br> <span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">Value </span>*res = cCall;<br><br><br> builder.CreateRet(res);<br> <span style="color:rgb(0,128,128)">llvm</span>::verifyFunction(*aFun);<br>}<br><br><span style="color:rgb(128,128,128);font-style:italic">// Body of the `b` function<br></span>{<br> <span style="color:rgb(128,128,128);font-style:italic">/// @brief Set entry label<br></span><span style="color:rgb(128,128,128);font-style:italic"> </span><span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">BasicBlock </span>*block = <span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">BasicBlock</span>::Create(context, <span style="color:rgb(0,128,0);font-weight:bold">"entry"</span>, bFun);<br> <span style="color:rgb(128,128,128);font-style:italic">/// @brief builder<br></span><span style="color:rgb(128,128,128);font-style:italic"> </span><span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">IRBuilder</span><> builder(block);<br> builder.SetInsertPoint(block);<br><br><br> <span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">CallInst </span>*aCall = builder.CreateCall(aFun, {}, <span style="color:rgb(0,128,0);font-weight:bold">"a"</span>);<br> <span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">CallInst </span>*cCall = builder.CreateCall(bFun, {}, <span style="color:rgb(0,128,0);font-weight:bold">"c"</span>);<br><br> <span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">Value </span>*res = builder.CreateAdd(aCall, cCall, <span style="color:rgb(0,128,0);font-weight:bold">"res"</span>);<br><br><br> builder.CreateRet(res);<br> <span style="color:rgb(0,128,128)">llvm</span>::verifyFunction(*bFun);<br>}<br><br><span style="color:rgb(128,128,128);font-style:italic">// Body of the `c` function<br></span>{<br> <span style="color:rgb(128,128,128);font-style:italic">/// @brief Set entry label<br></span><span style="color:rgb(128,128,128);font-style:italic"> </span><span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">BasicBlock </span>*block = <span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">BasicBlock</span>::Create(context, <span style="color:rgb(0,128,0);font-weight:bold">"entry"</span>, cFun);<br> <span style="color:rgb(128,128,128);font-style:italic">/// @brief builder<br></span><span style="color:rgb(128,128,128);font-style:italic"> </span><span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">IRBuilder</span><> builder(block);<br> builder.SetInsertPoint(block);<br><br><br> <span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">Value </span>*res = <span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">ConstantInt</span>::get(<span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">Type</span>::getInt32Ty(context), <span style="color:rgb(0,0,255)">2</span>);<br><br> builder.CreateRet(res);<br> <span style="color:rgb(0,128,128)">llvm</span>::verifyFunction(*cFun);<br>}<br><br><br><span style="color:rgb(128,128,128);font-style:italic">/// @brief Start of Main function<br></span>{<br> <span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">FunctionType </span>*<span style="color:rgb(0,0,128);font-weight:bold">const </span>func_type = <span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">FunctionType</span>::get(<span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">Type</span>::getInt32Ty(context), <span style="color:rgb(0,0,128);font-weight:bold">false</span>);<br> <span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">Function </span>*<span style="color:rgb(0,0,128);font-weight:bold">const </span>main_func = <span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">Function</span>::Create(func_type, <span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">Function</span>::<span style="color:rgb(102,14,122);font-weight:bold;font-style:italic">ExternalLinkage</span>, <span style="color:rgb(0,128,0);font-weight:bold">"main"</span>,<br> module.get());<br> <span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">BasicBlock </span>*<span style="color:rgb(0,0,128);font-weight:bold">const </span>entry = <span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">BasicBlock</span>::Create(context, <span style="color:rgb(0,128,0);font-weight:bold">"entrypoint"</span>, main_func);<br> <span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">IRBuilder</span><> builder(entry);<br><br> builder.SetInsertPoint(entry);<br><br> <span style="color:rgb(0,128,128)">llvm</span>::<span style="color:rgb(0,128,128)">CallInst </span>*bCall = builder.CreateCall(bFun, {}, <span style="color:rgb(0,128,0);font-weight:bold">"b"</span>);<br> builder.CreateRet(bCall);<br><br> <span style="color:rgb(0,128,128)">llvm</span>::verifyFunction(*main_func);<br>}<br><br>pm.run(<span style="color:rgb(0,128,128)">*</span>module);<br><br>module<span style="color:rgb(0,128,128)">-></span>dump();</pre><pre style="font-family:menlo;font-size:9pt"><br></pre><pre style="font-family:menlo;font-size:9pt"><br></pre><pre style="font-family:menlo;font-size:9pt"><br></pre><pre style="font-family:menlo;font-size:9pt">if you comment-outed `<span style="font-size:9pt">pm.run(</span><span style="font-size:9pt;color:rgb(0,128,128)">*</span><span style="font-size:9pt">module);</span><span style="font-size:9pt">` you have the following output.</span></pre><pre style="font-family:menlo;font-size:9pt"><span style="font-size:9pt"><br></span></pre><pre style="font-family:menlo;font-size:9pt">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
}
</pre><div><br></div><pre style="font-family:menlo;font-size:9pt"><span style="font-family:sans-serif;font-size:small"><br></span></pre><pre style="font-family:menlo;font-size:9pt"><br></pre></div><div>Sincerely,</div><div>Ryo</div></div>