public inbox for java-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Jeff Law <law@redhat.com>
To: "roger@nextmovesoftware.com" <roger@nextmovesoftware.com>,
	       java-patches@gcc.gnu.org, gcc-patches@gcc.gnu.org
Subject: Re: [JAVA PATCH] Enable more array bounds check elimination
Date: Wed, 13 Jul 2016 20:07:00 -0000	[thread overview]
Message-ID: <e59d05c5-5ce6-f6b9-4fa5-acbf2465199d@redhat.com> (raw)
In-Reply-To: <4F362C11-3DAA-4A9A-AEAB-089C20B3590C@nextmovesoftware.com>

On 02/22/2016 11:10 AM, roger@nextmovesoftware.com wrote:
>
> It has been a while since my last contribution.  The following patch allows GCC's optimizers
> to more aggressively eliminate and optimize java array bounds checks.  The results are
> quite impressive, for example producing a 26% performance improvement on the sieve.java
> benchmark given at http://keithlea.com/javabench/ on x86_64-pc-linux-gnu, reducing the
> runtime for 1 million iterations from 31.5 seconds on trunk, to 25.0s with this patch, in fact
> eliminating all array bounds checks.  This is close to the 22.3s of an equivalent C/C++
> implementation, and significantly closes the gap to Java HotSpot(TM) JIT at 23.0 seconds.
>
> The approach is to provide sufficient information in the gimple generated by the gcj front-end
> to allow the optimizers to do their thing.  For array allocations of constant length, I propose
> generating an additional (cheap) write to the array length field returned from _Jv_NewPrimArray,
> which is then sufficient to allow this value to propagate throughout the optimizers.
>
> This is probably best explained by a simple example.  Consider the array initializer below:
Thanks.  The example helped a lot.

At a very high level, you should be aware of a general belief that GCJ's 
life is limited.  There's been various calls to deprecate it.  So 
spending a lot of time optimizing GCJ's output may not be the best use 
of your skills :-)

>
> With the patch below, we now generate the much more informative .004t.gimple for this:
>
>     D.926 = _Jv_NewPrimArray (&_Jv_intClass, 3);
>     D.926->length = 3;
Essentially you're just storing back into the result the length that 
we'd passed to the allocator.  Cute.  Good to see that all the work 
we've done to propagate the RHS of that kind of statement into uses has 
paid off.

Presumably there's no reasonable way this could fail (like you're 
getting objects from a readonly part of memory), or the result gets used 
in some other thread which changes its size prior to the re-storing of 
the initial size?


>
>
> Achieving this result required two minor tweaks.   The first is to allow the array length constant
> to reach the newarray call, by allowing constants to remain on the quickstack.  This allows the
> call to _Jv_NewPrimArray to have a constant integer argument instead of the opaque #slot#0#0.
> Then in the code that constructs the call to _Jv_NewPrimArray we wrap it in a COMPOUND_EXPR
> allowing us to insert the superfluous, but helpful, write to the length field.
>
> Whilst working on this improvement I also noticed that the array bounds checks we were
> initially generating could also be improved.  Currently, an array bound check in 004t.gimple
> looks like:
>
>     D.925 = MEM[(struct int[] *)_ref_1_4.6].length;
>     D.926 = (unsigned int) D.925;
>     if (_slot_2_5.9 >= D.926) goto <D.927>; else goto <D.921>;
>     <D.927>:
>     _Jv_ThrowBadArrayIndex (_slot_2_5.8);
>     if (0 != 0) goto <D.928>; else goto <D.921>;
>     <D.928>:
>     iftmp.7 = 1;
>     goto <D.922>;
>     <D.921>:
>     iftmp.7 = 0;
>     <D.922>:
>
> Notice the unnecessary "0 != 0" and the dead assignments to iftmp.7 (which is unused).
FWIW, we're generally moving away from optimization in the language 
front-ends -- in particular folding, which you introduce in this patch 
on the array index.  Given the trajectory of GCJ I'm not going to worry 
about it though.


>
> With the patch below, we now not only avoid this conditional but also use __builtin_expect
> to inform the compiler that throwing an BadArrayIndex exception is typically unlikely.  i.e.
Sounds like a good thing as well.

>
>     D.930 = MEM[(struct int[] *)_ref_1_4.4].length;
>     D.931 = D.930 <= 1;
>     D.932 = __builtin_expect (D.931, 0);
>     if (D.932 != 0) goto <D.933>; else goto <D.934>;
>     <D.933>:
>     _Jv_ThrowBadArrayIndex (0);
>     <D.934>:
>
>
> The following patch has been tested on x86_64-pc-linux-gnu with a full make bootstrap
> and make check, with no new failures/regressions.
>
> Please let me know what you think (for stage 1 once it reopens)?
>
> Roger
> --
> Roger Sayle, Ph.D.
> CEO and founder
> NextMove Software Limited
> Registered in England No. 07588305
> Registered Office: Innovation Centre (Unit 23), Cambridge Science Park, Cambridge CB4 0EY
>
> 2016-02-21  Roger Sayle  <roger@nextmovesoftware.com>
>
> 	* expr.c (push_value): Only call flush_quick_stack for non-constant
> 	arguments.
> 	(build_java_throw_out_of_bounds_exception): No longer wrap calls
> 	to _Jv_ThowBadArrayIndex in a COMPOUND_EXPR as no longer needed.
> 	(java_check_reference): Annotate COND_EXPR with __builtin_expect
> 	to indicate that calling _Jv_ThrowNullPointerException is unlikely.
> 	(build_java_arrayaccess): Construct an unlikely COND_EXPR instead
> 	of a TRUTH_ANDIF_EXPR in a COMPOUND_EXPR.  Only generate array
> 	index MULT_EXPR when size_exp is not unity.
> 	(build_array_length_annotation): When optimizing, generate a write
> 	to the allocated array's length field to expose constant lengths
> 	to GCC's optimizers.
> 	(build_newarray): Call new build_array_length_annotation.
> 	(build_anewarray): Likewise.
Looks generally OK.  There's a whitespace nit in the call to build3 in 
build_java_arrayaccess (missing space between the function name and open 
paren).

I think this is OK for trunk after fixing the whitespace nit.

jeff


  parent reply	other threads:[~2016-07-13 20:07 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-02-22 18:10 roger
2016-02-22 18:13 ` Andrew Haley
2016-02-22 18:18 ` Jeff Law
2016-07-13 20:07 ` Jeff Law [this message]
2016-07-14 17:12   ` Andrew Hughes
2016-07-14 17:43     ` Andrew Haley
2016-02-22 23:02 Roger Sayle
2016-02-23  9:56 ` Andrew Haley
2016-02-23 17:45   ` Andrew Hughes
2016-02-24  1:11     ` Roger Sayle
2016-02-24  3:23       ` Andrew Hughes
2016-02-24  9:53       ` Andrew Haley

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=e59d05c5-5ce6-f6b9-4fa5-acbf2465199d@redhat.com \
    --to=law@redhat.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=java-patches@gcc.gnu.org \
    --cc=roger@nextmovesoftware.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).