compiled leaf method vs. inlined method bounds check

Gilles Duboscq gilwooden at gmail.com
Wed Dec 4 11:22:15 PST 2013


On Wed, Dec 4, 2013 at 7:07 PM, Tom Deneau <tom.deneau at amd.com> wrote:

>  Gilles or others --
>
>
>
> Still trying to understand this topic…
>
> I made a test case where I just compile a simple method that inlines
> another method, no profiling.
>
>
>
>    // compile this one
>
>     public int intFromArrayLonger(int[] ary, int idx) {
>
>         return intFromArrayLongerInner(ary, idx + 7);
>
>     }
>
>
>
>     public int intFromArrayLongerInner(int[] ary, int idx) {
>
>         return ary[idx + 3];
>
>     }
>
>
>
>
>
> I ran that compiling for the HSAIL backend and then in a separate run for
> the AMD64 backend.
>
> In the HSAIL case, I see the Deopt NotCompiledExceptionHandler, whereas
> the AMD64 case has the Deopt BoundsCheckException
>
>
>
> I put the igv graphs up at
> http://cr.openjdk.java.net/~tdeneau/graal-webrevs/inline-example.xml
> (the xml has the graphs from both backends)
>
> Maybe someone can take a look
>
>
>
> A couple of questions from the early phases of these graphs:
>
> ·         why is the graph after bytecode parsing of the inner method so
> different in the two cases?
>
in HSAILCompilationResult.java line 174, you can see the GraphBuilder used
there is configured without any optimistic assumptions
(OptimisticOptimizations.NONE). This means there will be explicit exception
edge for everything.
This also explains the difference for the Deopt reason.

>  ·         What is the phase called after bytecode parsing called HSAIL?
>
It's com.oracle.graal.hotspot.hsail.HSAILCompilationResult.HSAILPhase. it's
added in HSAILCompilationResult.java line 174.


>
>
> -- Tom
>
>
>
>
>
> *From:* gilwooden at gmail.com [mailto:gilwooden at gmail.com] *On Behalf Of *Gilles
> Duboscq
> *Sent:* Thursday, November 21, 2013 5:27 AM
>
> *To:* Deneau, Tom
> *Cc:* graal-dev at openjdk.java.net
> *Subject:* Re: compiled leaf method vs. inlined method bounds check
>
>
>
> Hello Tom,
>
>
>
> sorry for the delayed answer.
>
>
>
> I did the tests and i can not reproduce the behaviour you are seeing if no
> exception is ever thrown.
>
> However i can easily reproduce it if the first method (the one containing
> the array accesses) has already thrown an exception while the second one
> (the one containing the call) has never seen an exception flow through the
> call.
>
> In this case the second method assumes no exception can never flow through
> the call but when it inline the call, it sees that it actually needs to
> handle exceptions, in this case you get that
> NotCompiledExceptionHandler reason.
>
>
>
> I used this to test:
>
>
>
> public class ArrayTest extends JTTTest {
>
>     static int[] array = {1, 2, 3};
>
>
>
>     @Test
>
>     public void test0() throws Throwable {
>
>         run(new int[3], array, array, 0);
>
>         runTest("callRun", new int[3], array, array, 0);
>
>     }
>
>
>
>     @Test
>
>     public void test1() throws Throwable {
>
>         run(new int[3], array, array, 3);
>
>         runTest("callRun", new int[3], array, array, 0);
>
>     }
>
>
>
>     @Test
>
>     public void test2() throws Throwable {
>
>         callRun(new int[3], array, array, 3);
>
>         runTest("callRun", new int[3], array, array, 0);
>
>     }
>
>
>
>     public static void run(int[] out, int[] ina, int[] inb, int gid) {
>
>         out[gid] = ina[gid] + inb[gid];
>
>     }
>
>
>
>     public static void callRun(int[] out, int[] ina, int[] inb, int gid) {
>
>         run(out, ina, inb, gid);
>
>     }
>
> }
>
>
>
> In the first case (test0) i get the inlined call an
> the BoundsCheckException reason.
>
> In the second case (test1) i get the inlined call and the
> NotCompiledExceptionHandler reason.
>
> In the thrid case (test2) i get the full exception handling.
>
> Note that you need to run these separately if you don't want profile
> pollution.
>
>
>
> -Gilles
>
>
>
> On Wed, Nov 13, 2013 at 1:22 AM, Tom Deneau <tom.deneau at amd.com> wrote:
>
> Gilles --
>
>
>
> OK, we have a simple existing test in
> com.oracle.graal.compiler.hsail.test.IntAddTest which adds ints from two
> arrays putting the result in a third output array
>
>     public static void run(int[] out, int[] ina, int[] inb, int gid) {
>
>         out[gid] = ina[gid] + inb[gid];
>
>     }
>
>
>
> Here is the hsail code:.  (Note that we don't really handle the
> DeoptimizeNode but just print a comment based on the reason).
>
>
>
> version 0:95: $full : $large;
>
> // static method HotSpotMethod<IntAddTest.run(int[], int[], int[],
> int)>
>
> kernel &run (
>
>                 kernarg_u64 %_arg0,
>
>                 kernarg_u64 %_arg1,
>
>                 kernarg_u64 %_arg2
>
>                 ) {
>
>                 ld_kernarg_u64  $d0, [%_arg0];
>
>                 ld_kernarg_u64  $d1, [%_arg1];
>
>                 ld_kernarg_u64  $d2, [%_arg2];
>
>                 workitemabsid_u32 $s0, 0;
>
>
>
> @L0:
>
>                 ld_global_s32 $s1, [$d0 + 12];
>
>                 cmp_ge_b1_u32 $c0, $s0, $s1;
>
>                 cbr $c0, @L7;
>
> @L1:
>
>                 ld_global_s32 $s1, [$d2 + 12];
>
>                 cmp_ge_b1_u32 $c0, $s0, $s1;
>
>                 cbr $c0, @L7;
>
> @L2:
>
>                 ld_global_s32 $s1, [$d1 + 12];
>
>                 cmp_ge_b1_u32 $c0, $s0, $s1;
>
>                 cbr $c0, @L7;
>
> @L3:
>
>                 cvt_s64_s32 $d3, $s0;
>
>                 mul_s64 $d3, $d3, 4;
>
>                 add_u64 $d1, $d1, $d3;
>
>                 ld_global_s32 $s1, [$d1 + 16];
>
>                 cvt_s64_s32 $d1, $s0;
>
>                 mul_s64 $d1, $d1, 4;
>
>                 add_u64 $d2, $d2, $d1;
>
>                 ld_global_s32 $s2, [$d2 + 16];
>
>                 add_s32 $s2, $s2, $s1;
>
>                 cvt_s64_s32 $d1, $s0;
>
>                 mul_s64 $d1, $d1, 4;
>
>                 add_u64 $d0, $d0, $d1;
>
>                 st_global_s32 $s2, [$d0 + 16];
>
>                 ret;
>
> @L7:
>
>                 // Deoptimization for BoundsCheckException would occur here
>
>                 ret;
>
> };
>
>
>
>
>
> Then I made a new test where the run method just basically called the
> original IntAddTest.run
>
>     public static void run(int[] out, int[] ina, int[] inb, int gid) {
>
>         IntAddTest.run(out, ina, inb, gid);
>
>     }
>
>
>
> We compile with InlineEverything set.  We got this almost identical hsail
> code except for the deoptimization reason.  (In this case, there is no call
> to createOutOfBoundsException but I have seen it in larger test cases).
> Note that in either case, no exceptions would have occurred when profiling.
>
>
>
> version 0:95: $full : $large;
>
> // static method HotSpotMethod<IntAddInlineTest.run(int[], int[], int[],
> int)>
>
> kernel &run (
>
>                 kernarg_u64 %_arg0,
>
>                 kernarg_u64 %_arg1,
>
>                 kernarg_u64 %_arg2
>
>                 ) {
>
>                 ld_kernarg_u64  $d0, [%_arg0];
>
>                 ld_kernarg_u64  $d1, [%_arg1];
>
>                 ld_kernarg_u64  $d2, [%_arg2];
>
>                 workitemabsid_u32 $s0, 0;
>
>
>
> @L0:
>
>                 ld_global_s32 $s1, [$d0 + 12];
>
>                 cmp_ge_b1_u32 $c0, $s0, $s1;
>
>                 cbr $c0, @L7;
>
> @L1:
>
>                 ld_global_s32 $s1, [$d2 + 12];
>
>                 cmp_ge_b1_u32 $c0, $s0, $s1;
>
>                 cbr $c0, @L7;
>
> @L2:
>
>                 ld_global_s32 $s1, [$d1 + 12];
>
>                 cmp_ge_b1_u32 $c0, $s0, $s1;
>
>                 cbr $c0, @L7;
>
> @L3:
>
>                 cvt_s64_s32 $d3, $s0;
>
>                 mul_s64 $d3, $d3, 4;
>
>                 add_u64 $d1, $d1, $d3;
>
>                 ld_global_s32 $s1, [$d1 + 16];
>
>                 cvt_s64_s32 $d1, $s0;
>
>                 mul_s64 $d1, $d1, 4;
>
>                 add_u64 $d2, $d2, $d1;
>
>                 ld_global_s32 $s2, [$d2 + 16];
>
>                 add_s32 $s2, $s2, $s1;
>
>                 cvt_s64_s32 $d1, $s0;
>
>                 mul_s64 $d1, $d1, 4;
>
>                 add_u64 $d0, $d0, $d1;
>
>                 st_global_s32 $s2, [$d0 + 16];
>
>                 ret;
>
> @L7:
>
>                 // Deoptimization for NotCompiledExceptionHandler would
> occur here
>
>                 ret;
>
> };
>
>
>
>
>
> *From:* gilwooden at gmail.com [mailto:gilwooden at gmail.com] *On Behalf Of *Gilles
> Duboscq
> *Sent:* Tuesday, November 12, 2013 5:56 PM
> *To:* Deneau, Tom
> *Cc:* graal-dev at openjdk.java.net
> *Subject:* Re: compiled leaf method vs. inlined method bounds check
>
>
>
> Can you maybe show us the snippets you used and how you ran them?
>
> The second scenario you describe usually happen if an
> ArrayIndexOutOfBoundsException has already been thrown at the array access
> you're looking at.
>
> When compiling an array access, Graal will look at the profile and if it
> shows that exceptions are thrown there, it will compile in the exception
> branch (in your case the exception branch ends up into an other deopt for
> some reason). If profiling shows no exception has been thrown there, it
> will leave out the exception branch and will only place a which deoptimizes
> in case an exception needs to be thrown.
>
>
>
> This should have nothing to do with inlining. When doings tests about
> that, be carefull not to pollute the profile for the second test with the
> first one.
>
> You can change the bahviour of graal reagrding these things using
> the UseExceptionProbabilityForOperations flag.
>
>
>
> -Gilles
>
>
>
> On Tue, Nov 12, 2013 at 11:49 PM, Tom Deneau <tom.deneau at amd.com> wrote:
>
> I've noticed that if the graph I am compiling is simply a leaf method
> which accesses an array, the target of a failing bounds check is a
> DeoptimizeNode with reason=BoundsCheckException, action=InvalidateReprofile
>
> But if the method that is accessing the array is being inlined into
> another method, the target of the failing bounds check is a ForeignCall to
> createOutOfBoundsException followed by a branch to a DeoptimizeNode with
> reason=NotCompiledExceptionHandler, action=InvalidateRecompile.
>
> Can someone explain this difference?
>
> -- Tom
>
>
>
>
>


More information about the graal-dev mailing list