RFC : Approach to handle Allocation Merges in C2 Scalar Replacement
Liu, Xin
xxinliu at amazon.com
Mon Apr 4 23:09:39 UTC 2022
hi, Cesar
I am trying to catch up your conversation. Allow me to repeat the
problem. You are improving NonEscape but NSR objects, tripped by
merging. The typical form is like the example from "Control Flow
Merges".
https://cr.openjdk.java.net/~cslucas/escape-analysis/EscapeAnalysis.html
Those two JavaObjects in your example 'escapeAnalysisFails' are NSR
because they intertwine and will hinder split_unique_types. In Ivanov's
approach, we insert an explicit selector to split JOs at uses. Because
uses are separate, we then can proceed with split_unique_types() for
them individually. (please correct me if I misunderstand here)
here is the original control flow.
B0--
o1 = new MyPair(0,0)
cond
----
| \
| B1--------------------
| | o2 = new MyPair(x, y)
| -----------------------
| /
B2-------------
o3 = phi(o1, o2)
x = o3.x;
---------------
here is after?
B0--
o1 = new MyPair(0,0)
cond
----
| \
| B1--------------------
| | o2 = new MyPair(x, y)
| -----------------------
| /
B2-------------
selector = phi(o1, o2)
cmp(select, 0)
---------------
| \
-------- --------
x1 = o1.x| x2 = o2.x
--------- -------
| /
---------------
x3 = phi(x1, x2)
---------------
Besides the fixed form Load/Store(PHI(base1, base2), ADDP), I'd like to
report that C2 sometimes insert CastPP in between. Object
'Integer(65536)' in the following example is also non-escape but NSR.
there's a CastPP to make sure the object is not NULL. The more general
case is that the object is returned from a inlined function called.
public class MergingAlloc {
...
public static Integer zero = Integer.valueOf(0);
public static int testBoxingObject(boolean cond) {
Integer i = zero;
if (cond) {
i = new Integer(65536);
}
return i; // i.intValue();
}
public static void main(String[] args) {
MyPair p = new MyPair(0, 0);
escapeAnalysisFails(true, 1, 0);
testBoxingObject(true);
}
}
I though that LoadNode::split_through_phi() should split the LoadI of
i.intValue() in the Iterative GVN before Escape Analysis but current
it's not. I wonder if it's possible to make
LoadNode::split_through_phi() or PhaseIdealLoop::split_thru_phi() more
general. if so, it will fit better in C2 design. i.e. we evolve code in
local scope. In this case, splitting through a phi node of multiple
objects is beneficial when the result disambiguate memories.
In your example, ideally split_through_phi() should be able to produce
simpler code. currently, split_through_phi only works for load node and
there are a few constraints.
B0-------------
o1 = new MyPair(0,0)
x1 = o1.x
cond
----------------
| \
| B1--------------------
| | o2 = new MyPair(x, y)
| | x2 = o2.x;
| -----------------------
| /
-------------
x3 = phi(x1, x2)
---------------
thanks,
--lx
More information about the hotspot-compiler-dev
mailing list