Skip to content

Commit 6c324eb

Browse files
committed
[GR-65873] More aggressive CFG caching
PullRequest: graal/21091
2 parents c922de8 + e9a31b0 commit 6c324eb

File tree

27 files changed

+341
-154
lines changed

27 files changed

+341
-154
lines changed

compiler/src/jdk.graal.compiler.microbenchmarks/src/jdk/graal/compiler/microbenchmarks/lir/GraalCompilerState.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ protected DebugContext getGraphDebug() {
393393
}
394394

395395
private static ControlFlowGraph deepCopy(ControlFlowGraph cfg) {
396-
return ControlFlowGraph.newBuilder(cfg.graph).backendBlocks(true).connectBlocks(true).computeFrequency(true).computeLoops(true).computeDominators(true).computePostdominators(
396+
return ControlFlowGraph.newBuilder(cfg.graph).modifiableBlocks(true).connectBlocks(true).computeFrequency(true).computeLoops(true).computeDominators(true).computePostdominators(
397397
true).build();
398398
}
399399

compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/GraphScheduleTest.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,14 @@
2626

2727
import java.util.List;
2828

29+
import org.junit.Assert;
30+
2931
import jdk.graal.compiler.graph.Node;
3032
import jdk.graal.compiler.graph.NodeMap;
3133
import jdk.graal.compiler.nodes.StructuredGraph;
3234
import jdk.graal.compiler.nodes.StructuredGraph.ScheduleResult;
3335
import jdk.graal.compiler.nodes.cfg.HIRBlock;
3436
import jdk.graal.compiler.phases.schedule.SchedulePhase;
35-
import org.junit.Assert;
3637

3738
public class GraphScheduleTest extends GraalCompilerTest {
3839

@@ -50,7 +51,7 @@ protected void assertOrderedAfterLastSchedule(StructuredGraph graph, Node a, Nod
5051
}
5152

5253
protected void assertOrderedAfterSchedule(ScheduleResult ibp, Node a, Node b) {
53-
NodeMap<HIRBlock> nodeToBlock = ibp.getCFG().getNodeToBlock();
54+
NodeMap<HIRBlock> nodeToBlock = ibp.getNodeToBlockMap();
5455
HIRBlock bBlock = nodeToBlock.get(b);
5556
HIRBlock aBlock = nodeToBlock.get(a);
5657

compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/MemoryScheduleTest.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -641,7 +641,7 @@ private void assertReadWithinAllReturnBlocks(ScheduleResult schedule, boolean wi
641641
int withRead = 0;
642642
int returnBlocks = 0;
643643
for (ReturnNode returnNode : graph.getNodes(ReturnNode.TYPE)) {
644-
HIRBlock block = schedule.getCFG().getNodeToBlock().get(returnNode);
644+
HIRBlock block = schedule.getNodeToBlockMap().get(returnNode);
645645
for (Node node : schedule.getBlockToNodesMap().get(block)) {
646646
if (node instanceof FloatingReadNode) {
647647
withRead++;
@@ -667,7 +667,7 @@ private static void assertReadAndWriteInSameBlock(ScheduleResult schedule, boole
667667
StructuredGraph graph = schedule.getCFG().graph;
668668
FloatingReadNode read = graph.getNodes().filter(FloatingReadNode.class).first();
669669
WriteNode write = graph.getNodes().filter(WriteNode.class).first();
670-
assertTrue(!(inSame ^ schedule.getCFG().blockFor(read) == schedule.getCFG().blockFor(write)));
670+
assertTrue(!(inSame ^ schedule.blockFor(read) == schedule.blockFor(write)));
671671
}
672672

673673
private static void assertReadBeforeAllWritesInStartBlock(ScheduleResult schedule) {
@@ -712,6 +712,11 @@ private ScheduleResult getFinalSchedule(final String snippet, final TestMode mod
712712
graph.clearAllStateAfterForTestingOnly();
713713
// disable state split verification
714714
graph.getGraphState().setAfterFSA();
715+
if (graph.hasLoops() && graph.isLastCFGValid()) {
716+
// CFGLoops are computed differently after FSA, see CFGLoop#getLoopExits(). The
717+
// cached cfg needs to have its loop information invalidated.
718+
graph.getLastCFG().invalidateLoopInformation();
719+
}
715720
}
716721
debug.dump(DebugContext.BASIC_LEVEL, graph, "after removal of framestates");
717722

compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/SchedulingTest.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626

2727
import java.util.List;
2828

29+
import org.junit.Test;
30+
2931
import jdk.graal.compiler.graph.Node;
3032
import jdk.graal.compiler.graph.NodeMap;
3133
import jdk.graal.compiler.nodes.FrameState;
@@ -39,7 +41,6 @@
3941
import jdk.graal.compiler.nodes.util.GraphUtil;
4042
import jdk.graal.compiler.phases.schedule.SchedulePhase;
4143
import jdk.graal.compiler.phases.schedule.SchedulePhase.SchedulingStrategy;
42-
import org.junit.Test;
4344

4445
public class SchedulingTest extends GraphScheduleTest {
4546

@@ -65,7 +66,7 @@ public void testValueProxyInputs() {
6566
SchedulePhase schedulePhase = new SchedulePhase(SchedulingStrategy.LATEST);
6667
schedulePhase.apply(graph, getDefaultHighTierContext());
6768
ScheduleResult schedule = graph.getLastSchedule();
68-
NodeMap<HIRBlock> nodeToBlock = schedule.getCFG().getNodeToBlock();
69+
NodeMap<HIRBlock> nodeToBlock = schedule.getNodeToBlockMap();
6970
assertTrue(graph.getNodes().filter(LoopExitNode.class).count() == 1);
7071
LoopExitNode loopExit = graph.getNodes().filter(LoopExitNode.class).first();
7172
List<Node> list = schedule.nodesFor(nodeToBlock.get(loopExit));

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/GraalOptions.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,4 +350,7 @@ public final class GraalOptions {
350350

351351
@Option(help = "Enables target-specific lowering and legalization of SIMD operations. Required for SIMD code generation.", type = OptionType.Debug)
352352
public static final OptionKey<Boolean> TargetVectorLowering = new OptionKey<>(true);
353+
354+
@Option(help = "Enables caching of data structures like control flow graph or schedule across compiler phases.", type = OptionType.Debug)
355+
public static final OptionKey<Boolean> CacheCompilerDataStructures = new OptionKey<>(true);
353356
}

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/gen/LIRCompilerBackend.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ private static LIRGenerationResult emitLIR0(Backend backend,
171171
* LIRGeneration may have changed the CFG, so in case a schedule is needed afterward
172172
* we make sure it will be recomputed.
173173
*/
174-
graph.clearLastSchedule();
174+
graph.clearLastCFG();
175175
return result;
176176
} catch (Throwable e) {
177177
throw debug.handle(e);

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/graph/Graph.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,11 @@ public enum NodeEvent {
669669
*/
670670
INPUT_CHANGED,
671671

672+
/**
673+
* A node's control flow edge (i.e., predecessor or any successor) has changed.
674+
*/
675+
CONTROL_FLOW_CHANGED,
676+
672677
/**
673678
* A node's {@linkplain Node#usages() usages} count dropped to zero.
674679
*/
@@ -737,6 +742,9 @@ public abstract static class NodeEventListener {
737742
*/
738743
final void event(NodeEvent e, Node node) {
739744
switch (e) {
745+
case CONTROL_FLOW_CHANGED:
746+
controlFlowChanged(node);
747+
break;
740748
case INPUT_CHANGED:
741749
inputChanged(node);
742750
break;
@@ -773,7 +781,17 @@ public void changed(NodeEvent e, Node node) {
773781
}
774782

775783
/**
776-
* Notifies this listener about a change in a node's inputs.
784+
* Notifies this listener about a change in a node's control flow edges, i.e., its
785+
* predecessor or any of its successor edges.
786+
*
787+
* @param node a node who has had its predecessor or one of its successors changed
788+
*/
789+
public void controlFlowChanged(Node node) {
790+
}
791+
792+
/**
793+
* Notifies this listener about a change in a node's inputs (successor or predecessor edges
794+
* not included).
777795
*
778796
* @param node a node who has had one of its inputs changed
779797
*/

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/graph/Node.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -819,9 +819,9 @@ protected void updatePredecessor(Node oldSuccessor, Node newSuccessor) {
819819
if (newSuccessor != null) {
820820
assertTrue(newSuccessor.predecessor == null, "unexpected non-null predecessor in new successor (%s): %s, this=%s", newSuccessor, newSuccessor.predecessor, this);
821821
newSuccessor.predecessor = this;
822-
maybeNotifyInputChanged(newSuccessor);
822+
maybeNotifyControlFlowChanged(newSuccessor);
823823
}
824-
maybeNotifyInputChanged(this);
824+
maybeNotifyControlFlowChanged(this);
825825
}
826826
}
827827

@@ -1261,9 +1261,17 @@ public void replaceAtUsages(Node replacement, InputType... inputTypes) {
12611261
}
12621262
}
12631263

1264+
private void maybeNotifyControlFlowChanged(Node node) {
1265+
if (graph != null) {
1266+
assert !graph.isFrozen() : "Frozen graph must not change!";
1267+
graph.fireNodeEvent(Graph.NodeEvent.CONTROL_FLOW_CHANGED, node);
1268+
graph.edgeModificationCount++;
1269+
}
1270+
}
1271+
12641272
private void maybeNotifyInputChanged(Node node) {
12651273
if (graph != null) {
1266-
assert !graph.isFrozen();
1274+
assert !graph.isFrozen() : "Frozen graph must not change!";
12671275
graph.fireNodeEvent(Graph.NodeEvent.INPUT_CHANGED, node);
12681276
graph.edgeModificationCount++;
12691277
}
@@ -1276,7 +1284,7 @@ private void maybeNotifyInputChanged(Node node) {
12761284
*/
12771285
public void maybeNotifyZeroUsages(Node node) {
12781286
if (graph != null && node.isAlive()) {
1279-
assert !graph.isFrozen();
1287+
assert !graph.isFrozen() : "Frozen graph must not change!";
12801288
graph.fireNodeEvent(Graph.NodeEvent.ZERO_USAGES, node);
12811289
}
12821290
}

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/graph/NodeMap.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,12 @@ private void checkAndGrow(Node node) {
6767
assert check(node);
6868
}
6969

70+
public void growToSize(int newSize) {
71+
if (newSize > this.values.length) {
72+
this.values = Arrays.copyOf(values, Math.max(MIN_REALLOC_SIZE, newSize));
73+
}
74+
}
75+
7076
@Override
7177
public boolean isEmpty() {
7278
throw new UnsupportedOperationException("isEmpty() is not supported for performance reasons");

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/loop/phases/LoopTransformations.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
import jdk.graal.compiler.nodes.calc.AddNode;
7474
import jdk.graal.compiler.nodes.calc.CompareNode;
7575
import jdk.graal.compiler.nodes.calc.ConditionalNode;
76+
import jdk.graal.compiler.nodes.cfg.ControlFlowGraph;
7677
import jdk.graal.compiler.nodes.extended.OpaqueNode;
7778
import jdk.graal.compiler.nodes.extended.SwitchNode;
7879
import jdk.graal.compiler.nodes.loop.CountedLoopInfo;
@@ -496,6 +497,7 @@ private static void setSingleVisitedLoopFrequencySplitProbability(AbstractBeginN
496497
* if the given loop exit is the only exit of the loop.
497498
*/
498499
public static void adaptCountedLoopExitProbability(AbstractBeginNode lex, double newExitCheckFrequency) {
500+
invalidateCFGFrequencies(lex.graph().getLastCFG());
499501
double probability = 1.0D - 1.0D / newExitCheckFrequency;
500502
if (probability <= 0D) {
501503
setSingleVisitedLoopFrequencySplitProbability(lex);
@@ -506,6 +508,12 @@ public static void adaptCountedLoopExitProbability(AbstractBeginNode lex, double
506508
ifNode.setTrueSuccessorProbability(BranchProbabilityData.injected(probability, trueSucc));
507509
}
508510

511+
private static void invalidateCFGFrequencies(ControlFlowGraph cfg) {
512+
if (cfg != null) {
513+
cfg.invalidateFrequencies();
514+
}
515+
}
516+
509517
public static class PreMainPostResult {
510518
private final LoopBeginNode preLoop;
511519
private final LoopBeginNode mainLoop;

0 commit comments

Comments
 (0)