RFR(S): C2: Disallow definition split on MachCopySpill nodes
Nils Eliasson
nils.eliasson at oracle.com
Mon Jan 28 15:15:17 UTC 2019
Hi,
We have a problem that we sometimes hit an assert in reg_split.cpp.
https://bugs.openjdk.java.net/browse/JDK-8087128
http://cr.openjdk.java.net/~neliasso/8087128/webrev.01/
We have a block that looks like this:
1262: # B1264 B1263 <- N7283 Freq: 0,0927179
7282 Region === 7282 1704 [[ 7282 1702 1715 ]]
11500 MemToRegSpillCopy === _ 11190 [[ 9184 ]]
Oop:com/sun/tools/javac/$
9184 DefinitionSpillCopy === _ 11500 [[ 9185 1702 11503
11505 ]] Oop:$
11501 MemToRegSpillCopy === _ 9169 [[ 11665 11506 11504
11502 ]] Oop$
11645 MemToRegSpillCopy === _ 9167 [[ 9182 ]]
Oop:com/sun/tools/javac/c$
9182 DefinitionSpillCopy === _ 11645 [[ 1702 11646 11647
11648 ]] Oop$
1715 checkCastPP === 7282 1716 [[ 1702 ]]
java/util/HashMap$TreeNode:NotN$
9185 BoundSpillCopy === _ 9184 [[ 1702 ]]
Oop:com/sun/tools/javac/code/Symb$
11665 RegToMemSpillCopy === _ 11501 [[ 1702 ]]
Oop:com/sun/tools/javac/$
1702 CallStaticJavaDirect === 7282 185 182 16 0 1715 187
9185 11665 $
1703 MachProj === 1702 [[]] #10006/fat
11501 "MemToRegSpillCopy" has one use in this block, "11665
RegToMemSpillCopy", and three uses in other blocks. The use "11665
RegToMemSpillCopy" is used by "1702 CallStaticJavaDirect".
We hit the assert when processing 11501 in PhaseChaitin::Split.
We are in the "Handle DEFS" section of the split routine. We only get
here if the live range has been marked as spilled when the coloring have
ran out of colors. There are two code paths, one default, where we just
record the def and updates the side tables, and one where we do a
definition split on the live range. This split is guarded by several
conditions. In this case we get here by having a register mask that is
only regs (UP) and by being in a high pressure region. Everything seems
ok, so why don't we end up with MachSpillCopies here more often?
Also - one of the 4 uses is in this block (11655) and it's a reg-to-mem
already. It doesn't make much sense to add even more spills here. Why
does this happen?
UseFPUForSpilling added a restriction to coalesing - it skips coalescing
when the two live ranges have different pressure. The reason for this is
that with FPU spilling, the possible extra spilling is for "free". (I
can't find any documentation on benchmarks where this is beneficial
though.) The downside is that we get longer spill chains like:
DefSpill-memToReg-RegToMem-MemToReg, that doesn't collapse, because of
pressure changes. This may cause the live ranges defined by
memToReg-nodes to become spilled, and if we are in a high-pressure
region - we hit the assert.
So my conclusion is that nothing is really wrong. Everything still works
without the assert. The spill-chains are unnecessary long, but only
because we have chosen to restrict the coalescing. But we shouldn't
split the spill-nodes even more. In the next iteration the coalescing
within the block will have reduced the chains, and later a proper
coloring will be found.
My solution is that we prevent the MachSpillCopies (only Mem-To-Regs can
end up here) from being split again. This is ok - because this is
exactly what would have happened if we would have been in a low pressure
region.
I have done some measurements and it doesn't increase the number of
spill-iterations.
Regards,
Nils
More information about the hotspot-compiler-dev
mailing list