use of org.graalvm.compiler.phases.common.CanonicalizerPhase in project graal by oracle.
the class MacroNode method lowerReplacement.
/**
* Applies {@linkplain LoweringPhase lowering} to a replacement graph.
*
* @param replacementGraph a replacement (i.e., snippet or method substitution) graph
*/
@SuppressWarnings("try")
protected StructuredGraph lowerReplacement(final StructuredGraph replacementGraph, LoweringTool tool) {
final PhaseContext c = new PhaseContext(tool.getMetaAccess(), tool.getConstantReflection(), tool.getConstantFieldProvider(), tool.getLowerer(), tool.getReplacements(), tool.getStampProvider());
if (!graph().hasValueProxies()) {
new RemoveValueProxyPhase().apply(replacementGraph);
}
GuardsStage guardsStage = graph().getGuardsStage();
if (!guardsStage.allowsFloatingGuards()) {
new GuardLoweringPhase().apply(replacementGraph, null);
if (guardsStage.areFrameStatesAtDeopts()) {
new FrameStateAssignmentPhase().apply(replacementGraph);
}
}
DebugContext debug = replacementGraph.getDebug();
try (DebugContext.Scope s = debug.scope("LoweringSnippetTemplate", replacementGraph)) {
new LoweringPhase(new CanonicalizerPhase(), tool.getLoweringStage()).apply(replacementGraph, c);
} catch (Throwable e) {
throw debug.handle(e);
}
return replacementGraph;
}
use of org.graalvm.compiler.phases.common.CanonicalizerPhase in project graal by oracle.
the class CompileQueue method doInlineTrivial.
@SuppressWarnings("try")
private void doInlineTrivial(DebugContext debug, final HostedMethod method) {
/*
* Make a copy of the graph to avoid concurrency problems. Graph manipulations are not
* thread safe, and another thread can concurrently inline this method.
*/
final StructuredGraph graph = (StructuredGraph) method.compilationInfo.getGraph().copy(debug);
try (DebugContext.Scope s = debug.scope("InlineTrivial", graph, method, this)) {
try {
try (Indent in = debug.logAndIndent("do inline trivial in %s", method)) {
boolean inlined = false;
for (Invoke invoke : graph.getInvokes()) {
if (invoke.useForInlining()) {
inlined |= tryInlineTrivial(graph, invoke, !inlined);
}
}
if (inlined) {
Providers providers = runtimeConfig.lookupBackend(method).getProviders();
new CanonicalizerPhase().apply(graph, new PhaseContext(providers));
/*
* Publish the new graph, it can be picked up immediately by other threads
* trying to inline this method.
*/
method.compilationInfo.setGraph(graph);
checkTrivial(method);
inliningProgress = true;
}
}
} catch (Throwable ex) {
GraalError error = ex instanceof GraalError ? (GraalError) ex : new GraalError(ex);
error.addContext("method: " + method.format("%r %H.%n(%p)"));
throw error;
}
} catch (Throwable e) {
throw debug.handle(e);
}
}
use of org.graalvm.compiler.phases.common.CanonicalizerPhase in project graal by oracle.
the class MethodTypeFlowBuilder method parse.
@SuppressWarnings("try")
private boolean parse() {
OptionValues options = bb.getOptions();
DebugContext debug = DebugContext.create(options, new GraalDebugHandlersFactory(bb.getProviders().getSnippetReflection()));
try (Indent indent = debug.logAndIndent("parse graph %s", method)) {
boolean needParsing = false;
graph = method.buildGraph(debug, method, bb.getProviders(), Purpose.ANALYSIS);
if (graph == null) {
InvocationPlugin plugin = bb.getProviders().getGraphBuilderPlugins().getInvocationPlugins().lookupInvocation(method);
if (plugin != null && !plugin.inlineOnly()) {
Bytecode code = new ResolvedJavaMethodBytecode(method);
graph = new SubstrateIntrinsicGraphBuilder(options, debug, bb.getProviders().getMetaAccess(), bb.getProviders().getConstantReflection(), bb.getProviders().getConstantFieldProvider(), bb.getProviders().getStampProvider(), code).buildGraph(plugin);
}
}
if (graph == null) {
if (!method.hasBytecodes()) {
return false;
}
needParsing = true;
graph = new StructuredGraph.Builder(options, debug).method(method).build();
}
try (DebugContext.Scope s = debug.scope("ClosedWorldAnalysis", graph, method, this)) {
// enable this logging to get log output in compilation passes
try (Indent indent2 = debug.logAndIndent("parse graph phases")) {
if (needParsing) {
GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault(bb.getProviders().getGraphBuilderPlugins()).withEagerResolving(true).withUnresolvedIsError(PointstoOptions.UnresolvedIsError.getValue(bb.getOptions())).withNodeSourcePosition(true).withBytecodeExceptionMode(BytecodeExceptionMode.CheckAll);
bb.getHostVM().createGraphBuilderPhase(bb.getProviders(), config, OptimisticOptimizations.NONE, null).apply(graph);
}
} catch (PermanentBailoutException ex) {
bb.getUnsupportedFeatures().addMessage(method.format("%H.%n(%p)"), method, ex.getLocalizedMessage(), null, ex);
return false;
}
// Register used types and fields before canonicalization can optimize them.
registerUsedElements(bb, graph, methodFlow);
new CanonicalizerPhase().apply(graph, new PhaseContext(bb.getProviders()));
// Do it again after canonicalization changed type checks and field accesses.
registerUsedElements(bb, graph, methodFlow);
} catch (Throwable e) {
throw debug.handle(e);
}
}
return true;
}
use of org.graalvm.compiler.phases.common.CanonicalizerPhase in project graal by oracle.
the class RuntimeStrengthenStampsPhase method processMethod.
@SuppressWarnings("try")
private void processMethod(CallTreeNode node, Deque<CallTreeNode> worklist, BigBang bb) {
AnalysisMethod method = node.implementationMethod;
assert method.isImplementationInvoked();
if (node.graph == null) {
if (method.getAnnotation(Fold.class) != null || method.getAnnotation(NodeIntrinsic.class) != null) {
VMError.shouldNotReachHere("Parsing method annotated with @Fold or @NodeIntrinsic: " + method.format("%H.%n(%p)"));
}
boolean parse = false;
DebugContext debug = bb.getDebug();
StructuredGraph graph = method.buildGraph(debug, method, hostedProviders, Purpose.PREPARE_RUNTIME_COMPILATION);
if (graph == null) {
if (!method.hasBytecodes()) {
return;
}
parse = true;
graph = new StructuredGraph.Builder(debug.getOptions(), debug, AllowAssumptions.YES).method(method).build();
}
try (DebugContext.Scope scope = debug.scope("RuntimeCompile", graph)) {
if (parse) {
RuntimeGraphBuilderPhase builderPhase = new RuntimeGraphBuilderPhase(hostedProviders.getMetaAccess(), hostedProviders.getStampProvider(), hostedProviders.getConstantReflection(), hostedProviders.getConstantFieldProvider(), graphBuilderConfig, optimisticOpts, null, hostedProviders.getWordTypes(), deoptimizeOnExceptionPredicate, node);
builderPhase.apply(graph);
}
if (graph.getNodes(StackValueNode.TYPE).isNotEmpty()) {
/*
* Stack allocated memory is not seen by the deoptimization code, i.e., it is
* not copied in case of deoptimization. Also, pointers to it can be used for
* arbitrary address arithmetic, so we would not know how to update derived
* pointers into stack memory during deoptimization. Therefore, we cannot allow
* methods that allocate stack memory for runtime compilation. To remove this
* limitation, we would need to change how we handle stack allocated memory in
* Graal.
*/
return;
}
PhaseContext phaseContext = new PhaseContext(hostedProviders);
new CanonicalizerPhase().apply(graph, phaseContext);
new ConvertDeoptimizeToGuardPhase().apply(graph, phaseContext);
graphEncoder.prepare(graph);
node.graph = graph;
} catch (Throwable ex) {
debug.handle(ex);
}
}
assert node.graph != null;
List<MethodCallTargetNode> callTargets = node.graph.getNodes(MethodCallTargetNode.TYPE).snapshot();
callTargets.sort((t1, t2) -> Integer.compare(t1.invoke().bci(), t2.invoke().bci()));
for (MethodCallTargetNode targetNode : callTargets) {
AnalysisMethod targetMethod = (AnalysisMethod) targetNode.targetMethod();
AnalysisMethod callerMethod = (AnalysisMethod) targetNode.invoke().stateAfter().getMethod();
InvokeTypeFlow invokeFlow = callerMethod.getTypeFlow().getOriginalMethodFlows().getInvoke(targetNode.invoke().bci());
if (invokeFlow == null) {
continue;
}
Collection<AnalysisMethod> allImplementationMethods = invokeFlow.getCallees();
/*
* Eventually we want to remove all invokes that are unreachable, i.e., have no
* implementation. But the analysis is iterative, and we don't know here if we have
* already reached the fixed point. So we only collect unreachable invokes here, and
* remove them after the analysis has finished.
*/
if (allImplementationMethods.size() == 0) {
node.unreachableInvokes.add(targetNode.invoke());
} else {
node.unreachableInvokes.remove(targetNode.invoke());
}
List<AnalysisMethod> implementationMethods = new ArrayList<>();
for (AnalysisMethod implementationMethod : allImplementationMethods) {
/* Filter out all the implementation methods that have already been processed. */
if (!methods.containsKey(implementationMethod)) {
implementationMethods.add(implementationMethod);
}
}
if (implementationMethods.size() > 0) {
/* Sort to make printing order and method discovery order deterministic. */
implementationMethods.sort((m1, m2) -> m1.format("%H.%n(%p)").compareTo(m2.format("%H.%n(%p)")));
String sourceReference = buildSourceReference(targetNode.invoke().stateAfter());
for (AnalysisMethod implementationMethod : implementationMethods) {
CallTreeNode calleeNode = new CallTreeNode(implementationMethod, targetMethod, node, node.level + 1, sourceReference);
if (includeCalleePredicate.includeCallee(calleeNode, implementationMethods)) {
assert !methods.containsKey(implementationMethod);
methods.put(implementationMethod, calleeNode);
worklist.add(calleeNode);
node.children.add(calleeNode);
objectReplacer.createMethod(implementationMethod);
}
/*
* We must compile all methods which may be called. It may be the case that a
* call target does not reach the compile queue by default, e.g. if it is
* inlined at image generation but not at runtime compilation.
*/
CompilationInfoSupport.singleton().registerForcedCompilation(implementationMethod);
}
}
}
}
use of org.graalvm.compiler.phases.common.CanonicalizerPhase in project graal by oracle.
the class CompareCanonicalizerTest method getCanonicalizedGraph.
private StructuredGraph getCanonicalizedGraph(String name) {
StructuredGraph graph = parseEager(name, AllowAssumptions.YES);
new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
return graph;
}
Aggregations