compiled leaf method vs. inlined method bounds check

Gilles Duboscq duboscq at ssw.jku.at
Wed Dec 4 12:04:25 PST 2013


Yes at least for arguments ("Locals") of the method.


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

>  I think the HSAILPhase was copied from some early PTX backend, although
> I see there is still also a PTXPhase that does the same thing.
>
> Does this just mark each object node in the graph as non-null, and thus
> eliminate null check code?
>
>
>
>
>
>     private static class HSAILPhase extends Phase {
>
>         @Override
>
>         protected void run(StructuredGraph graph) {
>
>             for (LocalNode local : graph.getNodes(LocalNode.class)) {
>
>                 if (local.stamp() instanceof ObjectStamp) {
>
>
> local.setStamp(StampFactory.declaredNonNull(((ObjectStamp)
> local.stamp()).type()));
>
>                 }
>
>             }
>
>         }
>
>     }
>
>
>
>
>
> *From:* Gilles Duboscq [mailto:gilwooden at gmail.com]
> *Sent:* Wednesday, December 04, 2013 1:22 PM
>
> *To:* Deneau, Tom
> *Cc:* graal-dev at openjdk.java.net
> *Subject:* Re: compiled leaf method vs. inlined method bounds check
>
>
>
>
>
>
>
> 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