<div dir="ltr"><div dir="ltr">Regarding interpreter restart/uncommon_trap, for this kind of problem, the compiler has a better chance when it does not bind them to a precise bytecode restart location right from the start of the compilation. The branches can then be reordered and eliminated to achieve what you want.<br><div><br></div><div>For example with Graal, on your code i get:</div><div><br></div><div>  # {method} {0x00007f442685e318} 'f' '(I)I' in 'Test'</div></div><div dir="ltr"><div dir="ltr">  # parm0:    rsi       = int</div></div><div dir="ltr"><div dir="ltr"><div><div>  #           [sp+0x20]  (sp of caller)</div><div>  0x00007f44288d2ba0: mov    qword ptr [rsp-0x14000],rax</div><div>  0x00007f44288d2ba8: sub    rsp,0x18</div><div>  0x00007f44288d2bac: mov    qword ptr [rsp+0x10],rbp</div><div>  0x00007f44288d2bb1: cmp    esi,0x2</div><div>  0x00007f44288d2bb4: jne    0x00007f44288d2bca</div><div>  0x00007f44288d2bba: mov    eax,0x3</div><div>  0x00007f44288d2bbf: add    rsp,0x18</div><div>  0x00007f44288d2bc3: test   dword ptr [rip+0x1a8d743d],eax  ; {poll_return}</div><div>  0x00007f44288d2bc9: ret    </div><div>  0x00007f44288d2bca: mov    dword ptr [r15+0x8],0xffffffed</div><div>  0x00007f44288d2bd2: mov    qword ptr [r15+0x10],r12</div><div>  0x00007f44288d2bd6: call   0x00007f4428047341  ; OopMap{off=59}</div><div>                                                ;*iload_0 {reexecute=1 rethrow=0 return_oop=0}</div><div>                                                ; - Test::f@0 (line 10)</div><div>                                                ;   {runtime_call}</div></div><div><br></div><div>Which is more or less what you wanted modulo frame setup/tear down and poll_return. In this deopt case, execution restarts at bci 0 (it re-executes the method from the start). In general it would re-execute from the last side-effect.</div></div></div><div dir="ltr"><div dir="ltr"><div><br></div><div> Gilles</div></div></div><br><div class="gmail_quote"><div dir="ltr">On Fri, Jun 5, 2015 at 2:35 AM Vitaly Davidovich <<a href="mailto:vitalyd@gmail.com">vitalyd@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><p dir="ltr">Ok I see the complication with the restart in interpreter (I think that's what Remi was saying as well).  I suspect that most checks will tend to not have side effects (bad practice), but of course there may be some and for more complex scenarios sufficient inlining would need to occur.  For simple cases however, it's a pity since the VM has enough info and deopt ability to do this safely.  The real case i had was checks against enum constants, but the int example is just as good.</p>
<p dir="ltr">As for switch, I didn't try it this time but we had a thread on here a few months back where I was complaining about the switch not handling the same type of scenario, and John Rose mentioned it's a known issue with switches (i.e. no profile based optimization) :).  In addition, I find some of the switch codegen suboptimal (e.g. same cmp performed back to back with just a different jump after).  So I then tried if/else chain given that's supposedly profiled, and it is but apparently the codegen isn't what I thought it would be.  I was basically hoping for a single class CHA-like analysis for branches :).</p>
<p dir="ltr">sent from my phone</p>
<div class="gmail_quote">On Jun 4, 2015 8:15 PM, "Vladimir Kozlov" <<a href="mailto:vladimir.kozlov@oracle.com" target="_blank">vladimir.kozlov@oracle.com</a>> wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Uncommon traps are bound to bytecode. If we hit uncommon trap, for example, for (x == 1) test then after deoptimization Interpreter will execute only 'return 2;'. If generated code as you suggested we need to bind uncommon trap to the BCI of the first (x == 0) check so it will be executed in Interpreter after deoptimization.<br>
<br>
So it is not simple optimization but doable for cases like this (integer checks).<br>
<br>
Did you tried 'switch' instead?<br>
<br>
Regards,<br>
Vladimir<br>
<br>
On 6/4/15 4:44 PM, Vitaly Davidovich wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
By the way, the context for this example is the following.  Suppose you<br>
have a class with such a method.  This class is then used in different<br>
java processes such that in each instance only one of those branches is<br>
ever taken and the other compares have no side effects.  Ideally, the<br>
compiled code would favor that fast path, which may not be the first arm<br>
of the if/else chain.<br>
<br>
On Thu, Jun 4, 2015 at 7:42 PM, Vitaly Davidovich <<a href="mailto:vitalyd@gmail.com" target="_blank">vitalyd@gmail.com</a><br>
<mailto:<a href="mailto:vitalyd@gmail.com" target="_blank">vitalyd@gmail.com</a>>> wrote:<br>
<br>
    Thanks for the response Vladimir.  In this case though, can the JIT<br>
    not see that the cmp bytecodes of non-taken branches have no side<br>
    effects and remove them altogether? Is that just deemed not worth<br>
    the cost or is there something fundamental I'm missing here?<br>
<br>
    On Thu, Jun 4, 2015 at 7:36 PM, Vladimir Kozlov<br>
    <<a href="mailto:vladimir.kozlov@oracle.com" target="_blank">vladimir.kozlov@oracle.com</a> <mailto:<a href="mailto:vladimir.kozlov@oracle.com" target="_blank">vladimir.kozlov@oracle.com</a>>> wrote:<br>
<br>
        VM does not profiling values. We profiling branches.<br>
        When C2 construct control flow graph it follows bytecode. And it<br>
        can't eliminate cmp code based only on branch profiling.<br>
        Profiling still shows that all cmp bytecodes are always executed<br>
        - only branches are not taken. We would eliminate tests if they<br>
        were on non taken branch.<br>
        We generate uncommon traps for branches which were not taken<br>
        based on profiling.<br>
<br>
        Vladimir<br>
<br>
<br>
        On 6/4/15 4:20 PM, Vitaly Davidovich wrote:<br>
<br>
            Hi,<br>
<br>
            Suppose you have a method like this:<br>
<br>
            private static int f(final int x) {<br>
                      if (x == 0)<br>
                          return 1;<br>
                      else if (x == 1)<br>
                          return 2;<br>
                      else if (x == 2)<br>
                          return 3;<br>
                      return 4;<br>
<br>
                  }<br>
<br>
            If I then call it with x=2 always, the generated asm is not<br>
            what I<br>
            expect (8u40 with C2 compiler)<br>
<br>
                # parm0:    rsi       = int<br>
                #           [sp+0x30]  (sp of caller)<br>
                0x00007fcc5970c520: mov    %eax,-0x14000(%rsp)<br>
                0x00007fcc5970c527: push   %rbp<br>
                0x00007fcc5970c528: sub    $0x20,%rsp<br>
              ;*synchronization entry<br>
<br>
                0x00007fcc5970c52c: test   %esi,%esi<br>
                0x00007fcc5970c52e: je     0x00007fcc5970c55d  ;*ifne<br>
<br>
                0x00007fcc5970c530: cmp    $0x1,%esi<br>
                0x00007fcc5970c533: je     0x00007fcc5970c571  ;*if_icmpne<br>
<br>
                0x00007fcc5970c535: cmp    $0x2,%esi<br>
                0x00007fcc5970c538: jne    0x00007fcc5970c54b  ;*if_icmpne<br>
<br>
                0x00007fcc5970c53a: mov    $0x3,%eax<br>
                0x00007fcc5970c53f: add    $0x20,%rsp<br>
                0x00007fcc5970c543: pop    %rbp<br>
                0x00007fcc5970c544: test   %eax,0x5e0dab6(%rip)300000<br>
                 #<br>
            0x00007fcc5f51a000<br>
                                                              ;<br>
              {poll_return}<br>
                0x00007fcc5970c54a: retq<br>
            <snip><br>
<br>
            It's checking the if conditions in order, and then jumps to<br>
            some runtime<br>
            calls (I'm assuming that's for deopt to restore pruned<br>
            branches? Cause I<br>
            don't see anything that returns 1 or 2 otherwise).  Why is<br>
            this code not<br>
            favoring x=2? I'd have thought this code would be something<br>
            like (after<br>
            epilogue):<br>
<br>
            cmp $0x2, %esi<br>
            jne <deopt_or_other_cases><br>
            mov $0x3, %eax<br>
            retq<br>
<br>
            Thanks<br>
<br>
<br>
<br>
</blockquote>
</blockquote></div>
</blockquote></div></div>