<div dir="ltr"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><span style="font-size:12.8px">The CPU's profiling has a much shorter time scale:  It collects information (many times) over the course of a single loop.  The JVM's profiling has a long time scale, usually the whole application execution.  If a loop has bursty behavior (high short-span correlation) the CPU can predict branches very well, even though the JVM sees just noise.</span></blockquote><div><br></div><div>That's a good point.  This almost implies that branches within loops shouldn't even use JVM collected profiles -- just emit a branch -- since software doesn't model the hardware as well (and even if it attempted, it would be a moving target with many different targets). </div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Jan 6, 2016 at 12:22 PM, John Rose <span dir="ltr"><<a href="mailto:john.r.rose@oracle.com" target="_blank">john.r.rose@oracle.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><span class="">On Jan 6, 2016, at 6:45 AM, Vitaly Davidovich <<a href="mailto:vitalyd@gmail.com" target="_blank">vitalyd@gmail.com</a>> wrote:<br><div><blockquote type="cite"><br><div><div style="font-family:Helvetica;font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><span style="font-size:12.8px">Basically, if the cost of branch misprediction is higher than waiting for both inputs to cmov to be available, then cmov is better.  For very predictable branches, cmov is a loss (as we've already established in this thread) and I think always will be (i.e. cpu vendors seem to be putting more and more smarts into branch prediction instead).</span></div><div style="font-family:Helvetica;font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><span style="font-size:12.8px"><br></span></div><blockquote style="font-family:Helvetica;font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex" class="gmail_quote"><span style="font-size:12.8px">Yes, that was me not understanding the underlying branch profiling mechanisms.</span></blockquote><div style="font-family:Helvetica;font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><br></div><div style="font-family:Helvetica;font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">Actually, that question of mine was more aimed at John who said we should do something special for loops with max/min accumulators :). </div></div></blockquote></div><br></span><div>Buried in the bug comments is the following insight:  Branch profiling by the JVM is different from branch profiling by the CPU, and the difference is significant for the specific use case of an accumulated max (or min).</div><div><br></div><div>The CPU's profiling has a much shorter time scale:  It collects information (many times) over the course of a single loop.  The JVM's profiling has a long time scale, usually the whole application execution.  If a loop has bursty behavior (high short-span correlation) the CPU can predict branches very well, even though the JVM sees just noise.</div><div><br></div><div>(Fun fact:  The JVM could also profile auto-correlation and other statistics, but we have avoided doing this so far.)</div><div><br></div><div>So, usually, the branch profiling done in software by the JVM (interpreter or profiled tier) gives enough information to predict what the CPU will experience.  In this very special case (a = max(a, x) for loop-varying x), almost all inputs "settle down" to an almost 100% branch profile, in favor of 'a'.  For random data, you expect to find your max half way through the loop.  That means that the second half of the loop can be speculated as "a = a" instead of "a = max(a, x)".</div><div><br></div><div>This, in turn, can be detected in the JIT by pattern-matching locally on the max node, to see if it is of the form phi = max(phi, x).</div><div><br></div><div>Fair enough?</div><span class="HOEnZb"><font color="#888888"><div><br></div><div>— John</div></font></span></div></blockquote></div><br></div>