<div dir="ltr">Thanks Vladimir!</div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Nov 20, 2015 at 10:44 AM, Vladimir Ivanov <span dir="ltr"><<a href="mailto:vladimir.x.ivanov@oracle.com" target="_blank">vladimir.x.ivanov@oracle.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Me too. I'd expect that IfNode::search_identical() handles that, but evidently it doesn't. Filed JDK-8143542 [1] to track the problem.<br>
<br>
Thanks for the report!<br>
<br>
Best regards,<br>
Vladimir Ivanov<br>
<br>
[1] <a href="https://bugs.openjdk.java.net/browse/JDK-8143542" rel="noreferrer" target="_blank">https://bugs.openjdk.java.net/browse/JDK-8143542</a><div><div class="h5"><br>
<br>
On 11/20/15 4:19 PM, Vitaly Davidovich wrote:<br>
</div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="h5">
Hi Vladimir,<br>
<br>
Yes, this is exactly it -- "halfway to desired shape" is a great<br>
description.<br>
<br>
The motivating example, from which I extracted this small illustrative<br>
one, is wrapping an instance of some interface and providing a<br>
different/narrowed view on top of it; the wrapped interface object has<br>
strong profile towards one type, with a very small occurrence of it<br>
being null.  After wrapping it, the wrapper is then used to invoke<br>
another method in the following manner:<br>
<br>
Wrapper w = ...;<br>
callAnotherMethod(w.value(), w.value2(), w.value3(), w.value4()...);<br>
<br>
Each of these valueX() methods internally does that null check.  I<br>
wanted to see if the JIT would effectively transform that chain into:<br>
<br>
if (w.i != null) {<br>
     callAnotherMethod(<no repeated null checks, just call into the<br>
interface methods>);<br>
} else {<br>
    callAnotherMethod(<use the null value branches from all those<br>
accessors>);<br>
}<br>
<br>
After the above transformation and knowing that there's a single<br>
receiver type (when it's not null) with very simple code backing the<br>
interface methods, I was checking if the interface calls were<br>
devirtualized.  What I found was a bit surprising, which warranted this<br>
email :).<br>
<br>
Would it be difficult to enhance this?<br>
<br>
Thanks<br>
<br>
<br>
On Fri, Nov 20, 2015 at 7:54 AM, Vladimir Ivanov<br></div></div><div><div class="h5">
<<a href="mailto:vladimir.x.ivanov@oracle.com" target="_blank">vladimir.x.ivanov@oracle.com</a> <mailto:<a href="mailto:vladimir.x.ivanov@oracle.com" target="_blank">vladimir.x.ivanov@oracle.com</a>>> wrote:<br>
<br>
    It looks like C2 stops halfway to desired shape.<br>
    The load is commoned, but repeated null check is not eliminated.<br>
<br>
    Final IR shape looks like:<br>
       w = Load this._w<br>
<br>
       If (w == NULL) deopt<br>
<br>
       i = Load w._i<br>
<br>
       If (i != NULL) {<br>
         If (!i instanceof C) deopt<br>
       } v1 = Phi(T:1,F:-1);<br>
<br>
       If (i != NULL) {<br>
         If (!i instanceof C) deopt<br>
       } v2 = Phi(T:2,F:-1)<br>
<br>
       return v1+v2<br>
<br>
    The next transformation would be:<br>
       w = Load this._w<br>
       If (w == NULL) deopt<br>
       i = Load w._i<br>
       If (i != NULL) {<br>
         If (!i instanceof C) deopt<br>
         If (!i instanceof C) deopt<br>
       } v1 = Phi(T:1,F:-1)<br>
         v2 = Phi(T:2,F:-1)<br>
       return v1+v2<br>
<br>
    And finally:<br>
       w = Load this._w<br>
       If (w == NULL) deopt<br>
       i = Load w._i<br>
       If (i != NULL) {<br>
         If (!i instanceof C) deopt<br>
       } v1 = Phi(T:1,F:-1)<br>
         v2 = Phi(T:2,F:-1)<br>
       return i1+i2;<br>
<br>
    Best regards,<br>
    Vladimir Ivanov<br>
<br>
    On 11/20/15 5:29 AM, John Rose wrote:<br>
<br>
        On Nov 19, 2015, at 2:58 PM, Vitaly Davidovich<br>
        <<a href="mailto:vitalyd@gmail.com" target="_blank">vitalyd@gmail.com</a> <mailto:<a href="mailto:vitalyd@gmail.com" target="_blank">vitalyd@gmail.com</a>><br></div></div><span class="">
        <mailto:<a href="mailto:vitalyd@gmail.com" target="_blank">vitalyd@gmail.com</a> <mailto:<a href="mailto:vitalyd@gmail.com" target="_blank">vitalyd@gmail.com</a>>>> wrote:<br>
<br>
<br>
                     return _w.value() + _w.value2();<br>
<br>
<br>
        Which is (ignoring non-taken null branches):<br>
<br>
                  return _w._i.value() + _w._i.value2();<br>
<br>
        There are two independent fetches of _w._i in the bytecode.<br>
        The machine code is treating them as independent, where<br>
        we would want the optimizer to use a common value.<br>
<br>
        The machine code is optimistic that _w._i is always a C,<br>
        but it appears to be leaving open the possibility that some<br>
        activity not tracked by the JIT could store some other C2 <: I.<br>
<br>
        What happens at 0x00007ff5f82e00f9?  Does it de-opt,<br>
        or does it merge back into 0x00007ff5f82e00b2?  In the<br>
        latter case, the JIT cannot assume that _w._i is a C.<br>
<br>
        So, it could be a failure to de-opt, or it could be some<br>
        fluff in the IR which is preventing the two _w._i from<br>
        commoning.  Or something else.<br>
<br>
        — John<br>
<br>
<br>
</span></blockquote>
</blockquote></div><br></div>