EmitDeoptimize, EmitForignCall "createOutOfBoundsException"

Thomas Wuerthinger thomas.wuerthinger at oracle.com
Fri Jul 5 05:36:25 PDT 2013


Can you send a link to the IGV graphs? You can use File=>Export to create an XML file for the currently loaded graphs.

Thanks, thomas

On Jul 3, 2013, at 7:15 PM, "Deneau, Tom" <tom.deneau at amd.com> wrote:

> I noticed that if I have the same structure where the compiled method
> inlines a leaf method but the leaf method is small enough (I used
> the IntSquaredTest), then the resulting LIR that is handed to the backend
> has only deopt nodes, no ForeignCall nodes.
> 
> Looking at the igv graphs for the "smaller" leaf node inline,
> I can see that right after inlining the ForeignCall
> nodes (to CreateOutOfBoundsException) are still there, 
> but they become FixedGuard nodes after the  DeadCodeElimination phase.
> And then later, after Guard Lowering phase, they become deopt nodes.
> 
> Whereas for the "larger" leaf node inline case, the ForeignCall nodes
> never become FixedGuard nodes.  Not sure why they are treated differently
> in this case.
> 
> -- Tom
> 
> 
> 
> -----Original Message-----
> From: graal-dev-bounces at openjdk.java.net [mailto:graal-dev-bounces at openjdk.java.net] On Behalf Of Deneau, Tom
> Sent: Wednesday, July 03, 2013 10:42 AM
> To: Gilles Duboscq
> Cc: graal-dev at openjdk.java.net
> Subject: RE: EmitDeoptimize, EmitForignCall "createOutOfBoundsException"
> 
> Gilles --
> 
> Asking my question from another angle, if we do have to consume the foreignCall to createOutOfBoundsException and effectively ignore it, is there something we can do from our side that will not upset the control flow graph and  register allocation invariants of the original LIR?
> 
> -- Tom
> 
> 
> From: Deneau, Tom
> Sent: Wednesday, July 03, 2013 9:25 AM
> To: 'Gilles Duboscq'
> Cc: graal-dev at openjdk.java.net
> Subject: RE: EmitDeoptimize, EmitForignCall "createOutOfBoundsException"
> 
> Gilles --
> 
> It is strange that profiling would show that out of bounds exceptions were thrown on that path, I am quite sure that such exceptions are not being thrown when this code is run from the java side.  I also don't understand how profiling would show such exceptions in case #2 but not in case #1
> 
> case #1, compile this "run" method
> 
>    public static void run(float[] inxyz, float[] outxyz, float[] invxyz, float[] outvxyz, int gid) {
>         .. fairly large leaf routine, over 300 nodes
>     }
> 
> case #2, compile this "run" method
> 
>    public static void run(float[] inxyz, float[] outxyz, float[] invxyz, float[] outvxyz, int gid) {
>          updateBody(inxyz, outxyz, invxyz, outvxyz, gid);
>     }
> 
>    public static void updateBody(float[] inxyz, float[] outxyz, float[] invxyz, float[] outvxyz, int gid) {
>           .. same contents as "run" method in case #1
>     }
> 
> Your answer about the register allocation invariants with foreign call makes since.  So since we cannot yet handle the foreign call for this target, is there a flag that will force the LIR to emit a Deoptimization node (which we are able to effectively ignore) rather than a foreign call node when the purpose of the foreign call node is to create an OutOfBounds exception?
> 
> -- Tom
> 
> 
> From: gilwooden at gmail.com [mailto:gilwooden at gmail.com] On Behalf Of Gilles Duboscq
> Sent: Wednesday, July 03, 2013 3:51 AM
> To: Deneau, Tom
> Cc: graal-dev at openjdk.java.net
> Subject: Re: EmitDeoptimize, EmitForignCall "createOutOfBoundsException"
> 
> 
> For your first question, the profile seems to be the key: this path through the "create..." foreign call should only appear if profiling shows that array out of bounds exceptions are actually thrown at this position.
> In this case the exception handling is done in the compiled code: it will create the exception object with that foreign call and the execution will be diverted to any  catch handler that the compiler could find.
> 
> Otherwise, if profile shows that no exception is thrown, the compiler assumes it can leave the exception handling out. A deoptimization will be used to go back to the interpreter if that assumption proved to be incorrect.
> 
> A deoptimization is – like a return – a control flow sink, it ends the execution of the current compilation unit. The foreign call on the other end is not a control flow sink.
> If you replace a foreign call with a return during LIR generation I can see how later stages such as register allocation can get confused.
> In general, it is not a good idea to modify the control flow graph during LIR generation, many of invariants of the algorithms working on the LIR will fail.
> 
> When compiling for such a target I suppose that you want to stick to deoptimization to handle cases that are not supported by this execution environment.
> On 2 Jul 2013 20:03, "Tom Deneau" <tom.deneau at amd.com<mailto:tom.deneau at amd.com>> wrote:
> Here is the background for my visualizer question:
> 
> We have a junit test (part of the webrev) called StaticNBodyTest and the HSAIL backend is able
> to compile the fairly large run method without problem.
> 
> Now to test inlining decisions, I moved the logic to a separate updateBody method, and had the
> run method (the target of the compile) call the updateBody method.  By default, updateBody has too
> many nodes to be inlined, but I raised the MaximumInliningSize and now graal does indeed inline it.
> 
> With the inlining completed, the HSAILLirGenerator is now passed several emitForeignCall requests
> with the target being "createOutOfBoundsException".  Yet in the original StaticNBodyTest (same code,
> just not behind a second layer of method call), there were no emitForeignCall requests.
> Instead there were emitDeoptimize requests for the path taken when an array index was out of bounds.
> 
> Question 1: Why would there be emitDeoptimize in one case, and emitForeignCall after inlining?
> 
> As a followup question...
> 
> We have not decided how to handle exceptions yet in the HSAIL backend, so the emitDeoptimize request
> is turned into a request to return early from the HSAIL kernel.   With this strategy, code generation
> completes.
> 
> However, if I use similar logic with the emitForeignCall request, i.e. just generate a return,
> or even just ignore the ForeignCall request completely, I hit the following error later in the codegen:
> 
> java.lang.AssertionError: using fixed register that is not defined in this block
>        at com.oracle.graal.compiler.alloc.LinearScan.verifyInput(LinearScan.java:791)
> 
> Question 2: Why would this register assertion occur when emitForeignCall is replaced by a return, but not when emitDeoptimize
> is similarly replaced by a return?
> 
> -- Tom Deneau
> 
> 
> 
> 
> -----Original Message-----
> From: graal-dev-bounces at openjdk.java.net<mailto:graal-dev-bounces at openjdk.java.net> [mailto:graal-dev-bounces at openjdk.java.net<mailto:graal-dev-bounces at openjdk.java.net>] On Behalf Of Deneau, Tom
> Sent: Tuesday, July 02, 2013 11:53 AM
> To: graal-dev at openjdk.java.net<mailto:graal-dev at openjdk.java.net>
> Subject: mx igv or mx gv commands
> 
> When I try to use
>   mx igv &
> 
> as described on the wiki page, I get the splash screen for the visualize but then it dies.
> Similarly with mx gv &
> 
> Is there some other command that must be run first before using these?
> 
> -- Tom
> 



More information about the graal-dev mailing list