fix and improvements to commoning of barriers during loop optimizations

Roman Kennke rkennke at redhat.com
Wed Aug 24 11:07:19 UTC 2016


Hi Roland,

this is great!

For the sake of readability I would replace:

+    n->set_req(0, NULL);

with

n->set_req(ShenandoahBarrierNode::Control)

or something similar.

For Shenandoah-specific snippets in shared code, we need to think about
how to eventually convince upstream people ;-)

Other than that, please commit!

Roman


Am Mittwoch, den 24.08.2016, 10:21 +0200 schrieb Roland Westrelin:
> http://cr.openjdk.java.net/~roland/shenandoah/loopopts-commoning-v2/w
> ebrev.00/
> 
> In a previous change, I moved the optimization that replaces one
> barrier
> with a write barrier if they share the same memory from gvn to loop
> optimizations because the initial optimization would not keep the
> memory
> graph consistent and it was easier to fix the memory graph during
> loop
> optimizations:
> 
> http://hg.openjdk.java.net/shenandoah/jdk9/hotspot/rev/93aa873d631e
> 
> It turns out that that change wasn't sufficient and the memory graph
> can
> still become inconsistent (which could lead to a load barrier
> bypassing
> a write barrier in some rare cases):
> 
> - Because the code in PhaseIdealLoop::get_late_ctrl() that finds anti
>   dependences is conservative, a write barrier that has load uses can
> be
>   assigned a control where all paths from the control don't use the
>   barrier's memory projection. To fix that, I had to set the control
> of
>   the write barrier at parse time and I clear it at the end of
>   optimizations so scheduling can freely move the barrier around.
> 
> - When moving a write barrier up in the control graph, some region
> that
>   the barrier now dominates may not have a memory phi so the code
> can't
>   add a use for the barrier's memory projection on those paths. I
> fixed
>   it by adding logic to add phis to those regions. I also added code
> to
>   verify that a write barrier can indeed be moved to a new location
>   without breaking the memory graph.
> 
> I also extended that optimization pass so it finds more candidate
> pair
> of barriers to common. Previously the barriers had to share a memory
> edge so with this for instance:
> 
> if (flag) {
>     a.f = v;
> } else {
>     notinlined();
>     a.f = 0x42;
> }
> 
> 2 write barriers would have been kept. With the new code, a write
> barrier can be moved up if it makes another barrier be optimized out
> as
> long as the write barrier doesn't move in a loop.
> 
> I also added an option, ShenandoahDontIncreaseWBFreq that optimizes
> pair
> of barriers only if they don't cause write barriers to move to a more
> frequent code path. So this:
> 
> if (flag) {
>     a.f = v;
> } else {
>     a.f = 0x42;
> }
> 
> would result in a single barrier but not this:
> 
> if (flag1) {
>     a.f = v;
> } else {
>     if (flag2) {
>         a.f = 0x42;
>     }
> }
> 
> I don't know whether that option is useful or not but I suppose it's
> nice to have to experiment. It's now on by default mostly because
> this
> new code I'm proposing is tricky to get right and having it on
> restrict
> how much commoning is happening. I would like to do some more testing
> before I feel comfortable having it off.
> 
> Roland.
> 


More information about the shenandoah-dev mailing list