<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""></div><div class=""><br class=""></div><div class="">I kept visiting only binary operators for now, but added a ‘TODO’ there. I’ll address it in later patches, since it looks like 1) it can be done incrementally if we just add insn-visitors one by one, 2) if we decide to reuse code from inlining (I prefer this option), then It’ll be an independent and probably big effort for refactoring this code first.</div><div class=""><br class=""></div><div class="">As for the grammar fixes, everything should be fixed now, thank you for pointing me to them! Also, I feel like variables and options names that I used are also not ideal - if you have better ideas for them, please let me know.</div><div class=""><br class=""></div><div class="">Is it ok to commit the first patch?</div><div class=""><br class=""></div><div class="">As for the second patch - I implemented a new metrics as you suggested (minimal percent of removed instructions instead of ‘bonus’ for each removed instruction). However, I think we need to have a hign (absolute) threshold as well here: even if we optimize 50% of instructions, we don’t want to unroll a loop with 10^6 iterations - we’ll never finish compiling the current routine otherwise. I don’t plan to commit the second part in the current state, but still post it to get a feedback.</div><div class=""><br class=""></div><div class="">Thanks,</div><div class="">Michael</div><div class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Feb 2, 2015, at 9:38 PM, Hal Finkel <<a href="mailto:hfinkel@anl.gov" class="">hfinkel@anl.gov</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">----- Original Message -----</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">From: "Michael Zolotukhin" <<a href="mailto:mzolotukhin@apple.com" class="">mzolotukhin@apple.com</a>><br class="">To: "Hal J. Finkel" <<a href="mailto:hfinkel@anl.gov" class="">hfinkel@anl.gov</a>><br class="">Cc: "Commit Messages and Patches for LLVM" <<a href="mailto:llvm-commits@cs.uiuc.edu" class="">llvm-commits@cs.uiuc.edu</a>><br class="">Sent: Monday, February 2, 2015 7:25:30 PM<br class="">Subject: Re: [RFC] Heuristic for complete loop unrolling<br class=""><br class=""><br class="">Hi Hal,<br class=""><br class="">Please find a new version attached. I broke it into two parts: the<br class="">first one is the implementation of new heuristic, and the second is<br class="">for adjusting cost model.<br class=""><br class="">1. 0001-Implement-new-heuristic-for-complete-loop-unrolling.patch<br class=""><br class="">I added a new class UnrollAnalyzer (like InlineAnalyzer), that<br class="">estimates possible optimization effects of complete-unrolling. Now<br class="">we simulate inst-simplify by visiting all users of loads that might<br class="">become constant, and then we simulate DCE, which also might perform<br class="">significant clean-ups here. The counted number of optimized<br class="">instruction then returned for further consideration (in this patch<br class="">we just add it to threshold - that’s a conservative way of treating<br class="">it, since after the mentioned optimizations we still should be under<br class="">the threshold).<br class=""><br class="">2. 0002-Use-estimated-number-of-optimized-insns-in-unroll-th.patch<br class=""><br class="">In this patch we use more aggressive strategy in choosing threshold.<br class="">My idea here is that we can go beyond the default threshold if we<br class="">can significantly optimize the unrolled body, but we still should be<br class="">in reasonable limits. Let’s look at examples to illustrate it<br class="">better:<br class="">a) DefaultThreshold=150, LoopSize=50, IterationsNumber=5,<br class="">UnrolledLoopSize=50*5=250,<br class="">NumberOfPotentiallyOptimizedInstructions=90<br class="">In this case after unroll we would get 250 instructions, and after<br class="">inst-simplify+DCE, we’ll go down to 160 instructions. Though it’s<br class="">still bigger than DefaultThreshold, I think we do want to unroll<br class="">here, since it would speed up this part by ~90/250=36%.<br class=""><br class=""><br class="">b) DefaultThreshold=150, LoopSize=1000, IterationsNumber=1000,<br class="">UnrolledLoopSize=1000*1000,<br class="">NumberOfPotentiallyOptimizedInstructions=500. The absolute number of<br class="">optimized instructions in this example is bigger than in the<br class="">previous one, but we don’t want to unroll here, because the<br class="">resultant code would be huge, and we’d only save<br class="">500/(1000*1000)=0.05% instructions.<br class=""><br class=""><br class="">To handle both situations, I suggest only unroll if we can optimize<br class="">significant portion of the loop body, e.g. if after unrolling we can<br class="">remove N% of code. We might want to have an absolute upper limit for<br class="">final code size too (i.e. even if we optimize 50% of instructions,<br class="">don’t unroll loop with 10^8 iterations), but for now I decided to<br class="">add only one new parameter to avoid over-complicating things.<br class=""><br class=""><br class="">In the patch I use weight for optimized instruction (yep, like in the<br class="">previous patch, but here it’s more meaningful), which is essentially<br class="">equivalent to a ratio between original and removed code size.<br class=""></blockquote><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">I'm not particularly keen on this bonus parameter, but do like the percentage reduction test you've outlined. Can you please implement that instead?</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""><br class="">My testing is still in progress and probably I’ll do some tuning<br class="">later, the current default value (10) was taken almost at random.<br class=""><br class="">Do these patches look better?<br class=""><br class=""></blockquote><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Yes, much better. A few comments on the first:</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">+      // variable. Now it's time if it corresponds to a global constant global</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">+      // (in which case we can eliminate the load), or not.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">... time to see if ...</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">+// This class is used to get an estimate of optimization effect that we could</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">optimization effect -> the optimization effects</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">+// get from complete loop unrolling. It comes from the fact that some loads</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">+// might be replaced with a concrete constant values and that could trigger a</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">+// chain of instruction simplifications.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">a concrete -> concrete [remove 'a']</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">+  bool visitInstruction(Instruction &I) { return false; };</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">+  bool visitBinaryOperator(BinaryOperator &I) {</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Visiting binary operators is good, but we should also visit ICmp, FCmp, GetElementPtr, Trunc, ZExt, SExt, FPTrunc, FPExt, FPToUI, FPToSI, UIToFP, SIToFP, BitCast, Select, ExtractElement, InsertElement, ShuffleVector, ExtractValue, InsertValue. It might be easier to just do this from the visitInstruction callback.<span class="Apple-converted-space"> </span></span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">+    unsigned ElemSize = CDS->getElementType()->getPrimitiveSizeInBits() / 8U;</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">+    unsigned Start = StartC.getLimitedValue();</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">+    unsigned Step = StepC.getLimitedValue();</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">+</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">+    unsigned Index = (Start + Step * Iteration) / ElemSize;</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">+</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">+    Constant *CV = CDS->getElementAsConstant(Index);</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">I think you need to guard here against out-of-bounds accesses (we should simply return nullptr and not assert or segfault from the OOB access to the CDS.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">+  // Visit all loads the loop L, and for those that after complete loop</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">+  // unrolling would have a constant address and it will point to from a known</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">... that, after complete loop unrolling, would ... [add commas]</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">also</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">it will point to from a known -> it will point to a known [remove 'from']</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">+// This routine estimates this optimization effect and return number of</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">+// instructions, that potentially might be optimized away.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">return number -> returns the number</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">+  // iterations here. To limit ourselves here, we check only first 1000</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">+  // iterations, and then scale the found number, if necessary.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">+  unsigned IterationsNumberForEstimate = std::min(1000u, TripCount);</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Don't embed 1000 here; make this a cl::opt.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">With these changes, the first patch LGTM.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Thanks again,</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Hal</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class="">Thanks,<br class="">Michael<br class=""><br class=""><br class=""><br class=""><br class=""><br class=""><br class=""><br class="">On Jan 26, 2015, at 11:50 AM, Michael Zolotukhin <<br class=""><a href="mailto:mzolotukhin@apple.com" class="">mzolotukhin@apple.com</a> > wrote:<br class=""><br class=""><br class=""><br class=""><br class=""><br class=""><br class="">On Jan 25, 2015, at 6:06 AM, Hal Finkel < <a href="mailto:hfinkel@anl.gov" class="">hfinkel@anl.gov</a> > wrote:<br class=""><br class="">----- Original Message -----<br class=""><br class=""><br class="">From: "Michael Zolotukhin" < <a href="mailto:mzolotukhin@apple.com" class="">mzolotukhin@apple.com</a> ><br class="">To: "Hal Finkel" < <a href="mailto:hfinkel@anl.gov" class="">hfinkel@anl.gov</a> ><br class="">Cc: "Arnold Schwaighofer" < <a href="mailto:aschwaighofer@apple.com" class="">aschwaighofer@apple.com</a> >, "Commit<br class="">Messages and Patches for LLVM"<br class="">< <a href="mailto:llvm-commits@cs.uiuc.edu" class="">llvm-commits@cs.uiuc.edu</a> ><br class="">Sent: Sunday, January 25, 2015 1:20:18 AM<br class="">Subject: Re: [RFC] Heuristic for complete loop unrolling<br class=""><br class=""><br class="">On Jan 24, 2015, at 12:38 PM, Hal Finkel < <a href="mailto:hfinkel@anl.gov" class="">hfinkel@anl.gov</a> > wrote:<br class=""><br class="">----- Original Message -----<br class=""><br class=""><br class="">From: "Michael Zolotukhin" < <a href="mailto:mzolotukhin@apple.com" class="">mzolotukhin@apple.com</a> ><br class="">To: "Hal Finkel" < <a href="mailto:hfinkel@anl.gov" class="">hfinkel@anl.gov</a> ><br class="">Cc: "Arnold Schwaighofer" < <a href="mailto:aschwaighofer@apple.com" class="">aschwaighofer@apple.com</a> >, "Commit<br class="">Messages and Patches for LLVM"<br class="">< <a href="mailto:llvm-commits@cs.uiuc.edu" class="">llvm-commits@cs.uiuc.edu</a> ><br class="">Sent: Saturday, January 24, 2015 2:26:03 PM<br class="">Subject: Re: [RFC] Heuristic for complete loop unrolling<br class=""><br class=""><br class="">Hi Hal,<br class=""><br class=""><br class="">Thanks for the review! Please see my comments inline.<br class=""><br class=""><br class=""><br class=""><br class="">On Jan 24, 2015, at 6:44 AM, Hal Finkel < <a href="mailto:hfinkel@anl.gov" class="">hfinkel@anl.gov</a> > wrote:<br class=""><br class="">[moving patch review to llvm-commits]<br class=""><br class="">+static bool CanEliminateLoadFrom(Value *V) {<br class=""><br class="">+ if (Constant *C = dyn_cast<Constant>(V)) {<br class=""><br class="">+ if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C))<br class=""><br class="">+ if (GV->isConstant() && GV->hasDefinitiveInitializer())<br class=""><br class=""><br class="">Why are you casting to a Constant, and then to a GlobalVariable, and<br class="">then checking GV->isConstant()? There seems to be unnecessary<br class="">redundancy here ;)<br class="">Indeed:)<br class=""><br class=""><br class=""><br class=""><br class="">+ return GV->getInitializer();<br class=""><br class="">+ }<br class=""><br class="">+ return false;<br class=""><br class="">+}<br class=""><br class="">+static unsigned ApproximateNumberOfEliminatedInstruction(const Loop<br class="">*L,<br class=""><br class="">+ ScalarEvolution &SE) {<br class=""><br class="">This function seems mis-named. For one thing, it is not counting the<br class="">number of instructions potentially eliminated, but the number of<br class="">loads. Eliminating the loads might have lead to further constant<br class="">propagation, and really calculating the number of eliminated<br class="">instructions would require estimating that effect, right?<br class="">That’s right. But I’d rather change the function name, than add such<br class="">calculations, since it’ll look very-very narrow targeted, and I<br class="">worry that we might start to lose some cases as well. How about<br class="">‘NumberOfConstantFoldedLoads’?<br class=""><br class=""><br class="">Sounds good to me.<br class=""><br class=""><br class=""><br class=""><br class=""><br class=""><br class=""><br class="">if (TripCount && Count == TripCount) {<br class=""><br class="">- if (Threshold != NoThreshold && UnrolledSize > Threshold) {<br class=""><br class="">+ if (Threshold != NoThreshold && UnrolledSize > Threshold + 20 *<br class="">ElimInsns) {<br class=""><br class=""><br class="">20, huh? Is this a heuristic for constant propagation? It feels like<br class="">we should be able to do better than this.<br class="">Yep, that’s a parameter of the heuristic. Counting each ‘constant'<br class="">load as 1 is too conservative and doesn’t give much here,<br class=""><br class="">Understood.<br class=""><br class=""><br class=""><br class="">but since<br class="">we don’t actually count number of eliminated instructions we need<br class="">some estimate for it. This estimate is really rough, since in some<br class="">cases we can eliminate the entire loop body, while in the others we<br class="">can’t eliminate anything.<br class=""><br class="">I think that we might as well estimate it. Once we know the loads<br class="">that unrolling will constant fold, put them into a SmallPtrSet S.<br class="">Then, use a worklist-based iteration of the uses of instructions in<br class="">S. For each use that has operands that are all either constants, or<br class="">in S, queue them and keep going. Make sure you walk breadth first<br class="">(not depth first) so that you capture things will multiple feeder<br class="">loads properly. As you do this, count the number of instructions<br class="">that will be constant folded (keeping a Visited set in the usual way<br class="">so you don't over-count). This will be an estimate, but should be a<br class="">very accurate one, and can be done without any heuristic parameters<br class="">(and you still only visit a linear number of instructions, so should<br class="">not be too expensive).<br class="">The biggest gain comes not from expressions buf[0]*buf[3], which can<br class="">be constant folded when buf[0] and buf[3] are substituted with<br class="">constants, but from x*buf[0], when buf[0] turns out to be 0, or 1.<br class="">I.e. we don’t constant-fold it, but we simplify the expression based<br class="">on the particular value. I.e. the original convolution test is in<br class="">some sense equivalent to the following code:<br class="">const int a[] = [0, 1, 5, 1, 0];<br class="">int *b;<br class="">for(i = 0; i < 100; i ++) {<br class="">for(j = 0; j < 5; j++)<br class="">b[i] += b[i+j]*a[j];<br class="">}<br class=""><br class=""><br class="">Complete unrolling will give us:<br class=""><br class="">for(i = 0; i < 100; i ++) {<br class="">b[i] += b[i]*a[0];<br class=""><br class="">b[i] += b[i+1]*a[1];<br class=""><br class="">b[i] += b[i+2]*a[2];<br class=""><br class="">b[i] += b[i+3]*a[3];<br class=""><br class="">b[i] += b[i+4]*a[4];<br class="">}<br class=""><br class=""><br class="">After const-prop we’ll get:<br class=""><br class="">for(i = 0; i < 100; i ++) {<br class="">b[i] += b[i]*0;<br class=""><br class="">b[i] += b[i+1]*1;<br class=""><br class="">b[i] += b[i+2]*5;<br class=""><br class="">b[i] += b[i+3]*1;<br class=""><br class="">b[i] += b[i+4]*0;<br class="">}<br class="">And after simplification:<br class=""><br class="">for(i = 0; i < 100; i ++) {<br class="">b[i] += b[i+1];<br class=""><br class=""><br class="">b[i] += b[i+2]*5;<br class=""><br class="">b[i] += b[i+3];<br class=""><br class="">}<br class=""><br class=""><br class="">As you can see, we actually folded nothing here, but rather we<br class="">simplified more than a half of instructions. But it’s hard to<br class="">predict, which optimizations will be enabled by exact values<br class="">replaced loads<br class=""><br class="">Agreed.<br class=""><br class="">- i.e. of course we can check it, but it would be too<br class=""><br class=""><br class="">optimization-specific in my opinion.<br class=""><br class="">I understand your point, but I think using one magic number is<br class="">swinging the pendulum too far in the other direction.<br class=""><br class=""><br class=""><br class="">Thus, I decided to use some<br class="">number (20 in the current patch) which represents some average<br class="">profitability of replacing a load with constant. I think I should<br class="">get rid of this magic number though, and replace it with some<br class="">target-specific parameter (that’ll help to address Owen’s<br class="">suggestions).<br class=""><br class="">Using a target-specific cost (or costs) is a good idea, but having<br class="">target-specific magic numbers is going to be a mess. Different loops<br class="">will unroll, or not, for fairly arbitrary reasons, on different<br class="">targets. This is a heuristic, that I understand, and you won't be<br class="">able to exactly predict all possible later simplifications enabled<br class="">by the unrolling. However, the fact that you currently need a large<br class="">per-instruction boost factor, like 20, I think, means that the model<br class="">is too coarse.<br class=""><br class="">Maybe it would not be unreasonable to start from the other side: If<br class="">we first located loads that could be constant folded, and determined<br class="">the values those loads would actually take, and then simplified the<br class="">loop instructions based on those values, we'd get a pretty good<br class="">estimate. This is essentially what the code in<br class="">lib/Analysis/IPA/InlineCost.cpp does when computing the inlining<br class="">cost savings, and I think we could use the same technique here.<br class="">Admittedly, the inline cost analysis is relatively expensive, but<br class="">I'd think we could impose a reasonable size cutoff to limit the<br class="">overall expense for the case of full unrolling -- for this, maybe<br class="">the boost factor of 20 is appropriate -- and would also address<br class="">Owen's point, as far as I can tell, because like the inline cost<br class="">analysis, we can use TTI to compute the target-specific cost of<br class="">GEPs, etc. Ideally, we could refactor the ICA a little bit, and<br class="">re-use the code in there directly for this purpose. This way we can<br class="">limit the number of places in which we compute similar kinds of<br class="">heuristic simplification costs.<br class="">Hi Hal,<br class=""><br class=""><br class="">Thanks for the comments. I think that’s a good idea, and I’ll try<br class="">that out. If that doesn’t lead to over-complicated implementation,<br class="">I’d like it much better than having a magic number. I’ll prepare a<br class="">new patch soon.<br class=""><br class=""><br class="">Thanks,<br class="">Michael<br class=""><br class=""><br class=""><br class=""><br class=""><br class="">-Hal<br class=""><br class=""><br class=""><br class=""><br class=""><br class="">Thanks,<br class="">Michael<br class=""><br class=""><br class=""><br class=""><br class=""><br class="">-Hal<br class=""><br class=""><br class=""><br class=""><br class=""><br class="">I’d really appreciate a feedback on how to model this in a better<br class="">way.<br class=""><br class=""><br class="">Thanks,<br class="">Michael<br class=""><br class=""><br class=""><br class=""><br class="">Thanks again,<br class="">Hal<br class=""><br class="">----- Original Message -----<br class=""><br class=""><br class="">From: "Michael Zolotukhin" < <a href="mailto:mzolotukhin@apple.com" class="">mzolotukhin@apple.com</a> ><br class="">To: "LLVM Developers Mailing List ( <a href="mailto:llvmdev@cs.uiuc.edu" class="">llvmdev@cs.uiuc.edu</a> )" <<br class=""><a href="mailto:llvmdev@cs.uiuc.edu" class="">llvmdev@cs.uiuc.edu</a> ><br class="">Cc: "Hal J. Finkel" < <a href="mailto:hfinkel@anl.gov" class="">hfinkel@anl.gov</a> >, "Arnold Schwaighofer" <<br class=""><a href="mailto:aschwaighofer@apple.com" class="">aschwaighofer@apple.com</a> ><br class="">Sent: Friday, January 23, 2015 2:05:11 PM<br class="">Subject: [RFC] Heuristic for complete loop unrolling<br class=""><br class=""><br class=""><br class="">Hi devs,<br class=""><br class="">Recently I came across an interesting testcase that LLVM failed to<br class="">optimize well. The test does some image processing, and as a part of<br class="">it, it traverses all the pixels and computes some value basing on<br class="">the adjacent pixels. So, the hot part looks like this:<br class=""><br class="">for(y = 0..height) {<br class="">for (x = 0..width) {<br class="">val = 0<br class="">for (j = 0..5) {<br class="">for (i = 0..5) {<br class="">val += img[x+i,y+j] * weight[i,j]<br class="">}<br class="">}<br class="">}<br class="">}<br class=""><br class="">And ‘weight' is just a constant matrix with some coefficients.<br class=""><br class="">If we unroll the two internal loops (with tripcount 5), then we can<br class="">replace weight[i,j] with concrete constant values. In this<br class="">particular case, many of the coefficients are actually 0 or 1, which<br class="">enables huge code simplifications later on. But currently we unroll<br class="">only the innermost one, because unrolling both of them will exceed<br class="">the threshold.<br class=""><br class="">When deciding whether to unroll or not, we currently look only at the<br class="">instruction count of the loop. My proposal is to, on top of that,<br class="">check if we can enable any later optimizations by unrolling - in<br class="">this case by replacing a load with a constant. Similar to what we do<br class="">in inlining heuristics, we can estimate how many instructions would<br class="">be potentially eliminated after unrolling and adjust our threshold<br class="">with this value.<br class=""><br class="">I can imagine that it might be also useful for computations,<br class="">involving sparse constant matrixes (like identity matrix).<br class=""><br class="">The attached patch implements this feature, and with it we handle the<br class="">original testcase well.<br class=""><br class=""><br class=""><br class=""><br class=""><br class="">Does it look good? Of course, any ideas, suggestions and other<br class="">feedback are welcome!<br class=""><br class=""><br class="">Thanks,<br class="">Michael<br class=""><br class="">--<br class="">Hal Finkel<br class="">Assistant Computational Scientist<br class="">Leadership Computing Facility<br class="">Argonne National Laboratory<br class=""><br class=""><br class="">--<br class="">Hal Finkel<br class="">Assistant Computational Scientist<br class="">Leadership Computing Facility<br class="">Argonne National Laboratory<br class=""><br class=""><br class="">--<br class="">Hal Finkel<br class="">Assistant Computational Scientist<br class="">Leadership Computing Facility<br class="">Argonne National Laboratory<br class="">_______________________________________________<br class="">llvm-commits mailing list<br class=""><a href="mailto:llvm-commits@cs.uiuc.edu" class="">llvm-commits@cs.uiuc.edu</a><br class="">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits<br class=""><br class=""></blockquote><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">--<span class="Apple-converted-space"> </span></span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Hal Finkel</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Assistant Computational Scientist</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Leadership Computing Facility</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Argonne National Laboratory</span></div></blockquote></div><br class=""></div></body></html>