Skip to content

Commit

Permalink
add Builder pattern to ControlFlowGraph
Browse files Browse the repository at this point in the history
  • Loading branch information
wirthi committed Nov 6, 2023
1 parent 5cfb880 commit cf0c238
Show file tree
Hide file tree
Showing 25 changed files with 127 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,22 +44,22 @@ public void stringEquals(StringEquals s) {

@Benchmark
public void cfgCompute1(StringEquals s) {
ControlFlowGraph.compute(s.graph, true, false, false, false);
ControlFlowGraph.newBuilder(s.graph).connectBlocks(true).computeLoops(false).computeDominators(false).computePostdominators(false).computeFrequency(true).build();
}

@Benchmark
public void cfgCompute2(StringEquals s) {
ControlFlowGraph.compute(s.graph, true, true, false, false);
ControlFlowGraph.newBuilder(s.graph).connectBlocks(true).computeLoops(true).computeDominators(false).computePostdominators(false).computeFrequency(true).build();
}

@Benchmark
public void cfgCompute3(StringEquals s) {
ControlFlowGraph.compute(s.graph, true, true, true, false);
ControlFlowGraph.newBuilder(s.graph).connectBlocks(true).computeLoops(true).computeDominators(true).computePostdominators(false).computeFrequency(true).build();
}

@Benchmark
public void cfgCompute4(StringEquals s) {
ControlFlowGraph.compute(s.graph, true, true, true, true);
ControlFlowGraph.newBuilder(s.graph).connectBlocks(true).computeLoops(true).computeDominators(true).computePostdominators(true).computeFrequency(true).build();
}

public static int[] intersectionSnippet(int[] in1, int[] in2) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@
import java.lang.reflect.Field;
import java.lang.reflect.Method;

import org.openjdk.jmh.annotations.Level;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;

import jdk.graal.compiler.api.replacements.SnippetReflectionProvider;
import jdk.graal.compiler.api.test.Graal;
import jdk.graal.compiler.code.CompilationResult;
Expand Down Expand Up @@ -78,12 +84,6 @@
import jdk.graal.compiler.phases.tiers.TargetProvider;
import jdk.graal.compiler.phases.util.Providers;
import jdk.graal.compiler.runtime.RuntimeProvider;
import org.openjdk.jmh.annotations.Level;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;

import jdk.vm.ci.code.CodeCacheProvider;
import jdk.vm.ci.code.RegisterConfig;
import jdk.vm.ci.code.TargetDescription;
Expand Down Expand Up @@ -393,7 +393,8 @@ protected DebugContext getGraphDebug() {
}

private static ControlFlowGraph deepCopy(ControlFlowGraph cfg) {
return ControlFlowGraph.compute(cfg.graph, true, true, true, true, true, true);
return ControlFlowGraph.newBuilder(cfg.graph).backendBlocks(true).connectBlocks(true).computeFrequency(true).computeLoops(true).computeDominators(true).computePostdominators(
true).build();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ protected void checkLowTierGraph(StructuredGraph graph) {
Assert.assertEquals("LoopBeginNode count", 1, loopBeginNodes.count());

LoopBeginNode loopBeginNode = loopBeginNodes.first();
Assert.assertEquals("loop frequency of " + loopBeginNode, 128, ControlFlowGraph.compute(graph, false, false, false, false).localLoopFrequency(loopBeginNode), 0);
ControlFlowGraph cfg = ControlFlowGraph.newBuilder(graph).computeFrequency(true).build();
Assert.assertEquals("loop frequency of " + loopBeginNode, 128, cfg.localLoopFrequency(loopBeginNode), 0);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ private void test(String snippet, int rootExits, int nestedExits, int innerExits
StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
DebugContext debug = graph.getDebug();
debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph");
ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, true);
ControlFlowGraph cfg = ControlFlowGraph.newBuilder(graph).connectBlocks(true).computeLoops(true).computeDominators(true).computePostdominators(true).computeFrequency(true).build();

Assert.assertEquals(3, cfg.getLoops().size());
Loop<HIRBlock> rootLoop = cfg.getLoops().get(0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,8 @@ private void prepareGraphForLoopFrequencies(StructuredGraph g, HighTierContext h
private static void assertFrequency(StructuredGraph g, int iterations) {
NodeIterable<LoopBeginNode> loopBeginNodes = g.getNodes(LoopBeginNode.TYPE);
LoopBeginNode loopBeginNode = loopBeginNodes.first();
Assert.assertEquals("loop frequency of " + loopBeginNode, iterations, ControlFlowGraph.compute(g, false, false, false, false).localLoopFrequency(loopBeginNode), 0);
ControlFlowGraph cfg = ControlFlowGraph.newBuilder(g).computeFrequency(true).build();
Assert.assertEquals("loop frequency of " + loopBeginNode, iterations, cfg.localLoopFrequency(loopBeginNode), 0);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ protected VoidState cloneState(VoidState oldState) {
return voidState;
}
};
ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, false);
ControlFlowGraph cfg = ControlFlowGraph.newBuilder(graph).connectBlocks(true).computeLoops(true).computeDominators(true).computeFrequency(true).build();
ReentrantBlockIterator.apply(closure, cfg.getStartBlock());
// schedule for IGV
SchedulePhase.runWithoutContextOptimizations(graph);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ public void testSingleSplit() {
g.start().setNext(s);

g.getDebug().dump(DebugContext.VERY_DETAILED_LEVEL, g, "after build");
ControlFlowGraph.compute(g, true, true, true, true);
ControlFlowGraph.newBuilder(g).connectBlocks(true).computeLoops(true).computeDominators(true).computePostdominators(true).computeFrequency(true).build();
}

static int singleLoop(int end) {
Expand All @@ -144,7 +144,7 @@ static int singleLoop(int end) {
public void testSingleSplitLoop() {
StructuredGraph g = parseEager(getResolvedJavaMethod("singleLoop"), AllowAssumptions.NO);
g.getDebug().dump(DebugContext.VERY_DETAILED_LEVEL, g, "after build");
ControlFlowGraph.compute(g, true, true, true, true);
ControlFlowGraph.newBuilder(g).connectBlocks(true).computeLoops(true).computeDominators(true).computePostdominators(true).computeFrequency(true).build();
}

static int foo(int a, int b) {
Expand Down Expand Up @@ -214,7 +214,7 @@ public void testImplies() {

dumpGraph(graph);

ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, true);
ControlFlowGraph cfg = ControlFlowGraph.newBuilder(graph).connectBlocks(true).computeLoops(true).computeDominators(true).computePostdominators(true).computeFrequency(true).build();

HIRBlock[] blocks = cfg.getBlocks();
// check number of blocks
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ protected final void testPartialEscapeAnalysis(String snippet, boolean removeIde
Assert.assertTrue("partial escape analysis should have removed all NewInstanceNode allocations", graph.getNodes().filter(NewInstanceNode.class).isEmpty());
Assert.assertTrue("partial escape analysis should have removed all NewArrayNode allocations", graph.getNodes().filter(NewArrayNode.class).isEmpty());

ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, false, false);
ControlFlowGraph cfg = ControlFlowGraph.newBuilder(graph).connectBlocks(true).computeLoops(true).computeFrequency(true).build();
double frequencySum = 0;
int materializeCount = 0;
for (CommitAllocationNode materialize : graph.getNodes().filter(CommitAllocationNode.class)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public void testLoopConditionProfile() {

List<LoopBeginNode> loopBegins = graph.getNodes().filter(LoopBeginNode.class).snapshot();
Assert.assertEquals(loopBegins.toString(), 1, loopBegins.size());
ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, false, false, false);
ControlFlowGraph cfg = ControlFlowGraph.newBuilder(graph).connectBlocks(true).computeFrequency(true).build();
for (LoopBeginNode loopBegin : loopBegins) {
Assert.assertEquals("Expected loop frequency", 10.0, cfg.localLoopFrequency(loopBegin), 0.01);
}
Expand All @@ -131,7 +131,7 @@ public void testPrepareLoopForAOT() {

List<LoopBeginNode> loopBegins = graph.getNodes().filter(LoopBeginNode.class).snapshot();
Assert.assertEquals(loopBegins.toString(), 1, loopBegins.size());
ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, false, false, false);
ControlFlowGraph cfg = ControlFlowGraph.newBuilder(graph).connectBlocks(true).computeFrequency(true).build();
for (LoopBeginNode loopBegin : loopBegins) {
Assert.assertEquals("Expected loop frequency", 2.0, cfg.localLoopFrequency(loopBegin), 0.01);
}
Expand Down Expand Up @@ -267,7 +267,7 @@ public void testPropagateInjectedProfile(boolean twoEnds, boolean trueContinue)

List<LoopBeginNode> loopBegins = graph.getNodes().filter(LoopBeginNode.class).snapshot();
Assert.assertEquals(loopBegins.toString(), 1, loopBegins.size());
ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, false, false, false);
ControlFlowGraph cfg = ControlFlowGraph.newBuilder(graph).connectBlocks(true).computeFrequency(true).build();
for (LoopBeginNode loopBegin : loopBegins) {
Assert.assertEquals("Expected loop frequency", 10.0, cfg.localLoopFrequency(loopBegin), 0.01);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,18 +116,14 @@ public interface RecursiveVisitor<V> {
void exit(HIRBlock b, V value);
}

public static ControlFlowGraph computeForSchedule(StructuredGraph graph) {
return compute(graph, true, true, true, true, true, false);
}
private static final MemUseTrackerKey CFG_MEMORY = DebugContext.memUseTracker("CFGComputation");

public static ControlFlowGraph compute(StructuredGraph graph, boolean connectBlocks, boolean computeLoops, boolean computeDominators, boolean computePostdominators) {
return compute(graph, connectBlocks, true, computeLoops, computeDominators, computePostdominators);
public static ControlFlowGraphBuilder newBuilder(StructuredGraph structuredGraph) {
return new ControlFlowGraphBuilder(structuredGraph);
}

private static final MemUseTrackerKey CFG_MEMORY = DebugContext.memUseTracker("CFGComputation");

public static ControlFlowGraph compute(StructuredGraph graph, boolean connectBlocks, boolean computeFrequency, boolean computeLoops, boolean computeDominators, boolean computePostdominators) {
return compute(graph, false, connectBlocks, computeFrequency, computeLoops, computeDominators, computePostdominators);
public static ControlFlowGraph computeForSchedule(StructuredGraph graph) {
return compute(graph, true, true, true, true, true, false);
}

/**
Expand All @@ -141,7 +137,7 @@ public static ControlFlowGraph compute(StructuredGraph graph, boolean connectBlo
* @param computePostdominators
*/
@SuppressWarnings("try")
public static ControlFlowGraph compute(StructuredGraph graph, boolean backendBlocks, boolean connectBlocks, boolean computeFrequency, boolean computeLoops, boolean computeDominators,
static ControlFlowGraph compute(StructuredGraph graph, boolean backendBlocks, boolean connectBlocks, boolean computeFrequency, boolean computeLoops, boolean computeDominators,
boolean computePostdominators) {

try (DebugCloseable c = CFG_MEMORY.start(graph.getDebug())) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.graal.compiler.nodes.cfg;

import jdk.graal.compiler.nodes.StructuredGraph;

public class ControlFlowGraphBuilder {
private final StructuredGraph structuredGraph;
private boolean backendBlocks;
private boolean connectBlocks;
private boolean computeFrequency;
private boolean computeLoops;
private boolean computeDominators;
private boolean computePostdominators;

public ControlFlowGraphBuilder(StructuredGraph structuredGraph) {
this.structuredGraph = structuredGraph;
}

public ControlFlowGraphBuilder backendBlocks(boolean backendBlocks) {
this.backendBlocks = backendBlocks;
return this;
}

public ControlFlowGraphBuilder connectBlocks(boolean connectBlocks) {
this.connectBlocks = connectBlocks;
return this;
}

public ControlFlowGraphBuilder computeFrequency(boolean computeFrequency) {
this.computeFrequency = computeFrequency;
return this;
}

public ControlFlowGraphBuilder computeLoops(boolean computeLoops) {
this.computeLoops = computeLoops;
return this;
}

public ControlFlowGraphBuilder computeDominators(boolean computeDominators) {
this.computeDominators = computeDominators;
return this;
}

public ControlFlowGraphBuilder computePostdominators(boolean computePostdominators) {
this.computePostdominators = computePostdominators;
return this;
}

public ControlFlowGraph build() {
return ControlFlowGraph.compute(structuredGraph, backendBlocks, connectBlocks, computeFrequency, computeLoops, computeDominators, computePostdominators);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ protected LoopsData(final StructuredGraph graph, ControlFlowGraph preComputedCFG
DebugContext debug = graph.getDebug();
if (preComputedCFG == null) {
try (DebugContext.Scope s = debug.scope("ControlFlowGraph")) {
this.cfg = ControlFlowGraph.compute(graph, true, true, true, true);
this.cfg = ControlFlowGraph.newBuilder(graph).connectBlocks(true).computeLoops(true).computeDominators(true).computePostdominators(true).computeFrequency(true).build();
} catch (Throwable e) {
throw debug.handle(e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ protected void run(StructuredGraph graph, CoreProviders context) {
final BoxNode boxUsageOnBoxedVal = (BoxNode) usage;
if (boxUsageOnBoxedVal.getBoxingKind() == box.getBoxingKind()) {
if (cfg == null) {
cfg = ControlFlowGraph.compute(graph, true, true, true, false);
cfg = ControlFlowGraph.newBuilder(graph).connectBlocks(true).computeLoops(true).computeDominators(true).computeFrequency(true).build();
}
if (graph.isNew(before, boxUsageOnBoxedVal) || graph.isNew(before, box)) {
continue boxedValUsageLoop;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,11 @@
import java.util.List;
import java.util.Optional;

import jdk.graal.compiler.phases.BasePhase;
import jdk.graal.compiler.phases.schedule.SchedulePhase;
import org.graalvm.collections.EconomicMap;
import org.graalvm.collections.EconomicSet;
import org.graalvm.collections.Equivalence;
import org.graalvm.collections.MapCursor;

import jdk.graal.compiler.core.common.cfg.BlockMap;
import jdk.graal.compiler.core.common.type.ArithmeticOpTable;
import jdk.graal.compiler.core.common.type.ArithmeticOpTable.BinaryOp;
Expand Down Expand Up @@ -101,7 +100,8 @@
import jdk.graal.compiler.options.Option;
import jdk.graal.compiler.options.OptionKey;
import jdk.graal.compiler.options.OptionType;

import jdk.graal.compiler.phases.BasePhase;
import jdk.graal.compiler.phases.schedule.SchedulePhase;
import jdk.vm.ci.meta.DeoptimizationAction;
import jdk.vm.ci.meta.SpeculationLog.Speculation;
import jdk.vm.ci.meta.TriState;
Expand Down Expand Up @@ -181,7 +181,8 @@ protected void run(StructuredGraph graph, CoreProviders context) {
NodeMap<HIRBlock> nodeToBlock = null;
ControlFlowGraph cfg = null;
if (fullSchedule) {
cfg = ControlFlowGraph.compute(graph, true, true, true, true, true, true);
cfg = ControlFlowGraph.newBuilder(graph).backendBlocks(true).connectBlocks(true).computeFrequency(true).computeLoops(true).computeDominators(true).computePostdominators(
true).build();
if (moveGuards && Options.MoveGuardsUpwards.getValue(graph.getOptions())) {
cfg.visitDominatorTree(new MoveGuardsUpwards(), graph.isBeforeStage(StageFlag.VALUE_PROXY_REMOVAL));
}
Expand All @@ -194,7 +195,7 @@ protected void run(StructuredGraph graph, CoreProviders context) {
blockToNodes = r.getBlockToNodesMap();
nodeToBlock = r.getNodeToBlockMap();
} else {
cfg = ControlFlowGraph.compute(graph, true, true, true, true);
cfg = ControlFlowGraph.newBuilder(graph).connectBlocks(true).computeLoops(true).computeDominators(true).computePostdominators(true).computeFrequency(true).build();
nodeToBlock = cfg.getNodeToBlock();
blockToNodes = getBlockToNodes(cfg);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ protected void run(StructuredGraph graph, MidTierContext context) {
}
// There is more than one deopt, create a merge
if (cfg == null) {
cfg = ControlFlowGraph.compute(graph, true, true, false, false);
cfg = ControlFlowGraph.newBuilder(graph).connectBlocks(true).computeLoops(true).computeFrequency(true).build();
}
try (DebugCloseable position = first.withNodeSourcePosition()) {
AbstractMergeNode merge = graph.add(new MergeNode());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ protected void run(StructuredGraph graph, CoreProviders context) {
EconomicMap<LoopBeginNode, EconomicSet<LocationIdentity>> modifiedInLoops = null;
if (graph.hasLoops()) {
modifiedInLoops = EconomicMap.create(Equivalence.IDENTITY);
ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, false, false);
ControlFlowGraph cfg = ControlFlowGraph.newBuilder(graph).connectBlocks(true).computeLoops(true).computeFrequency(true).build();
for (Loop<?> l : cfg.getLoops()) {
HIRLoop loop = (HIRLoop) l;
processLoop(loop, modifiedInLoops);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public Optional<NotApplicable> notApplicableTo(GraphState graphState) {

@Override
protected void run(StructuredGraph graph) {
ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, false, false, false);
ControlFlowGraph cfg = ControlFlowGraph.newBuilder(graph).connectBlocks(true).computeFrequency(true).build();
for (AbstractBeginNode beginNode : graph.getNodes(AbstractBeginNode.TYPE)) {
if (hasPotentialUnsafeAccess(cfg, beginNode)) {
graph.getDebug().log(DebugContext.VERBOSE_LEVEL, "Adding speculation fence at %s because of unguarded fixed access", beginNode);
Expand Down
Loading

0 comments on commit cf0c238

Please sign in to comment.