<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">
Hi all,<br class="">
<br class="">
I’ve recently been working with the loop analysis pass and functionality when developing my own transformation pass, and came across something with the LoopInfo class and LoopAnalysisWrapper that I would appreciate some clarity on.<br class="">
<br class="">
Principally, I’m interested in caching the results of LoopInfoWrapperPass::runOnFunction as I routinely need to look at and pick apart the loops within a given set of user-defined Functions in the input bytecode.<br class="">
<br class="">
To get the LoopInfo for a given Function, the following Lambda is used for brevity:<br class="">
auto GetLI = [&](Function& F) -> LoopInfo & {<br class="">
    return getAnalysis<LoopInfoWrapperPass>(F).getLoopInfo();<br class="">
};<br class="">
<br class="">
Due to the copy semantics of the LoopInfo class being implicitly deleted and the above LoopBase behaviour, I use std::move to add this LoopInfo object as a value in a map, with the pointer to the Function as the key. I found a need to do this as, if I were
 to call getAnalysis<LoopInfoWrapperPass.(…) multiple times in the same scope, all of the references and loop information changes in each LoopInfo object, e.g.:
<div class=""><br class="">
</div>
<div class="">LoopInfo& LoopsForF = GetLI(*FunctionF);</div>
<div class="">LoopInfo& LoopsForG = GetLI(*FunctionG);</div>
<div class=""><br class="">
</div>
<div class="">The LoopInfo objects are the same, or, at least, the information within in (same BasicBlock reference, same number of sub loops etc.) The LoopsForF object changes. <span style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0);" class="">As far as
 I’ve read and ascertained, this is because LoopInfoWrapperPass and LoopInfo are optimised for memory and speed. LoopInfoWrapperPass stores a LoopInfo result object</span><span style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0);" class=""> </span><span style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0);" class="">that
 it reassigns during each call to its runOnFunction method. This releases the contents of the </span><span style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0);" class="">BumpPtrAllocator memory in LoopInfo (in</span><span style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0);" class=""> </span><span style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0);" class="">LoopInfoBase)
 for the new function's loop information to be stored within, hence why they would be the same.</span><br class="">
<div class="">
<div class=""><br class="">
</div>
<div class=""><br class="">
</div>
<div class="">Calling std::move seems to work up until I try to reference and utilise the LoopInfo, as in the following pseudocode example:<br class="">
<br class="">
std::map<Function*, LoopInfo> Cache;<br class="">
for (Function* Fn : getFunctions()) {<br class="">
    if (Cache.find(Fn) == Cache.end()) {<br class="">
        Cache.emplace(Fn, std::move(GetLI(*Fn)));<br class="">
    }<br class="">
<br class="">
    ScalarEvolution& SE = GetSE(*Fn);<br class="">
    // We assume at least one loop in function body<br class="">
    auto TopMostLoops = Cache[Fn].getTopLevelLoops();<br class="">
    Loop* FirstLoop = TopMostLoops[0];<br class="">
<br class="">
    PHINode* IV = FirstLoop->getInductionVariable(SE);</div>
<div class="">    // ...<br class="">
}<br class="">
<br class="">
In the above code, getInductionVariable fails, stating "LV: PHI is a recurrence with respect to an outer loop”. However, if I reference the LoopInfo object directly in the body of the for loop (e.g. LoopInfo& LI = GetLI(*Fn) and replace instances of Cache[Fn]
 with LI) then the getInductionVariable call succeeds and returns the appropriate PHINode. std::move - the only way to transfer/retain the result - seems to change the LoopInfo that is returned, making it invalid?</div>
<div class=""><br class="">
<div class=""><br class="">
</div>
<div class="">So a few questions I have are:</div>
<div class="">
<ol class="MailOutline">
<li class="">Is this expected or unusual behaviour?</li><li class="">Does one just need to call getAnalysis<LoopInfoWrapperPass>(…) every time they need it (due to the memory optimisations) or is there something wrong with my logic above that is preventing the example from working?</li><li class="">Are there any similar uses in the codebase (other passes or such) that require storing loop information? I’ve not been able to find any.</li></ol>
<div class=""><br class="">
</div>
</div>
<div class=""><br class="">
</div>
<div class="">I appreciate any and all input to help clarify this issue.</div>
<div class=""><br class="">
</div>
<div class=""><br class="">
</div>
<div class="">Thanks for your time,</div>
<div class="">Andrew L-S</div>
<div class=""><br class="">
</div>
<div class=""><br class="">
</div>
<div class=""><br class="">
</div>
<div class=""><br class="">
</div>
<div class=""><br class="">
</div>
<div class=""><br class="">
</div>
<div class=""><br class="">
</div>
<div class=""><br class="">
</div>
<div class=""><br class="">
</div>
<div class=""><br class="">
</div>
</div>
</div>
</div>
</body>
</html>