RFR: 8278228: C2: Improve identical back-to-back if elimination [v5]

Roland Westrelin roland at openjdk.java.net
Fri Jan 7 12:37:39 UTC 2022


> C2 has had the ability to optimize:
> 
> (1)
> 
> if (some_condition) {
>   // body 1
> } else {
>   // body 2
> }
> if (some_condition) {
>   // body 3
> } else {
>   // body 4
> }
> 
> into:
> 
> (4)
> 
> if (some_condition) {
>   // body 1
>   // body 3
> } else {
>   // body 2
>   // body 4
> }
> 
> for a while.
> 
> This is achieved by the intermediate step:
> 
> (2)
> 
> if (some_condition) {
>   // body 1
>   some_condition2 = true;
> } else {
>   // body 2
>   some_condition2 = false;
> }
> if (some_condition2) {
>   // body 3
> } else {
>   // body 4
> }
> 
> which then allows the use of the exiting split if optimization. As a
> result, the graph is transformed to:
> 
> (3)
> 
> if (some_condition) {
>   // body 1
>   some_condition2 = true;
>   if (some_condition2) {
>     body3: // a Region here
>     // body3
>   } else {
>     goto body4;
>   }
> } else {
>   // body 2
>   some_condition2 = false;
>   if (some_condition2) {
>     goto body3;
>   } else {
>     body4:  // another Region here
>     // body4;
>   }
> }
> 
> and finally to (4) above.
> 
> Recently, 8275610 has shown that this can break if some_condition is a
> null check. If, say, body 3 has a control dependent CastPP, then when
> body 1 and body 3 are merged, the CastPP of body 3 doesn't become
> control dependent on the dominating if (because in step (2), the
> CastPP hides behind a Region). As a result, the CastPP loses its
> dependency on the null check.
> 
> After discussing this with Christian, it seemed this was caused by the
> way this transformation relies on split if: having custom code that
> wouldn't create Regions at body3 and body4 that are then optimized out
> would solve the problem. Anyway, after looking at the split if code,
> trying to figure out how to tease it apart in smaller steps and
> reusing some of them to build a new transformation, it seemed too
> complicated. So instead, I propose reusing split if in a slightly
> different way:
> 
> skip step (2) but perform split if anyway to obtain:
> 
> if (some_condition) {
>   // body 1
>   if (some_condition) {
>     body3: // Region1
>     // CastPP is here, control dependent on Region1
>     // body3
>   } else {
>     goto body4;
>   }
> } else {
>   // body 2
>  if (some_condition) {
>     goto body3;
>   } else {
>     body4:  // Region2
>     // body4;
>   }
> }
> 
> - A CastPP node would still be behind a Region. So next step, is to push
> control dependent nodes through Region1 and Region2:
> 
> if (some_condition) {
>   // body 1
>   if (some_condition) {
>     // A CastPP here
>     body3: // Region1
>     // body3
>   } else {
>     goto body4;
>   }
> } else {
>   // body 2
>  if (some_condition) {
>     // A CastPP here
>     goto body3;
>   } else {
>     body4:  // Region2
>     // body4;
>   }
> }
> 
> - And then call dominated_by() to optimize the dominated:
> 
> if (some_condition) {
> 
> in both branches of the dominating if (some_condition) {. That also
> causes the CastPP to become dependent on the dominating if.

Roland Westrelin has updated the pull request incrementally with one additional commit since the last revision:

  review

-------------

Changes:
  - all: https://git.openjdk.java.net/jdk/pull/6882/files
  - new: https://git.openjdk.java.net/jdk/pull/6882/files/a7a58a7c..6a6716cc

Webrevs:
 - full: https://webrevs.openjdk.java.net/?repo=jdk&pr=6882&range=04
 - incr: https://webrevs.openjdk.java.net/?repo=jdk&pr=6882&range=03-04

  Stats: 1 line in 1 file changed: 0 ins; 1 del; 0 mod
  Patch: https://git.openjdk.java.net/jdk/pull/6882.diff
  Fetch: git fetch https://git.openjdk.java.net/jdk pull/6882/head:pull/6882

PR: https://git.openjdk.java.net/jdk/pull/6882


More information about the hotspot-compiler-dev mailing list