RFR: 8278228: C2: Improve identical back-to-back if elimination
Roland Westrelin
roland at openjdk.java.net
Fri Dec 17 14:01:38 UTC 2021
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.
-------------
Commit messages:
- more
- more
- more
- more
- exps
Changes: https://git.openjdk.java.net/jdk/pull/6882/files
Webrev: https://webrevs.openjdk.java.net/?repo=jdk&pr=6882&range=00
Issue: https://bugs.openjdk.java.net/browse/JDK-8278228
Stats: 157 lines in 8 files changed: 121 ins; 15 del; 21 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