package org.graalvm.compiler.hotspot.phases.aot;
import static org.graalvm.compiler.core.common.GraalOptions.InlineEverything;
import static org.graalvm.compiler.core.common.GraalOptions.TrivialInliningSize;
import java.util.Map;
import org.graalvm.compiler.core.common.GraalOptions;
import org.graalvm.compiler.nodes.Invoke;
import org.graalvm.compiler.nodes.spi.Replacements;
import org.graalvm.compiler.options.Option;
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionType;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.common.inlining.InliningUtil;
import org.graalvm.compiler.phases.common.inlining.info.InlineInfo;
import org.graalvm.compiler.phases.common.inlining.policy.GreedyInliningPolicy;
import org.graalvm.compiler.phases.common.inlining.policy.InliningPolicy;
import org.graalvm.compiler.phases.common.inlining.walker.MethodInvocation;
import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
public class AOTInliningPolicy extends GreedyInliningPolicy {
public static class Options {
@Option(help = "", type = OptionType.Expert)
public static final OptionKey<Double> AOTInliningDepthToSizeRate = new OptionKey<>(2.5);
@Option(help = "", type = OptionType.Expert)
public static final OptionKey<Integer> AOTInliningSizeMaximum = new OptionKey<>(300);
@Option(help = "", type = OptionType.Expert)
public static final OptionKey<Integer> AOTInliningSizeMinimum = new OptionKey<>(50);
}
public AOTInliningPolicy(Map<Invoke, Double> hints) {
super(hints);
}
protected double maxInliningSize(int inliningDepth, OptionValues options) {
return Math.max(Options.AOTInliningSizeMaximum.getValue(options) / (inliningDepth * Options.AOTInliningDepthToSizeRate.getValue(options)), Options.AOTInliningSizeMinimum.getValue(options));
}
@Override
public Decision isWorthInlining(Replacements replacements, MethodInvocation invocation, InlineInfo calleeInfo, int inliningDepth, boolean fullyProcessed) {
OptionValues options = calleeInfo.graph().getOptions();
final boolean isTracing = GraalOptions.TraceInlining.getValue(options) || calleeInfo.graph().getDebug().hasCompilationListener();
final InlineInfo info = invocation.callee();
for (int i = 0; i < info.numberOfMethods(); ++i) {
HotSpotResolvedObjectType t = (HotSpotResolvedObjectType) info.methodAt(i).getDeclaringClass();
if (t.getFingerprint() == 0) {
return InliningPolicy.Decision.NO.withReason(isTracing, "missing fingerprint");
}
}
final double probability = invocation.probability();
final double relevance = invocation.relevance();
if (InlineEverything.getValue(options)) {
InliningUtil.traceInlinedMethod(info, inliningDepth, fullyProcessed, "inline everything");
return InliningPolicy.Decision.YES.withReason(isTracing, "inline everything");
}
if (isIntrinsic(replacements, info)) {
InliningUtil.traceInlinedMethod(info, inliningDepth, fullyProcessed, "intrinsic");
return InliningPolicy.Decision.YES.withReason(isTracing, "intrinsic");
}
if (info.shouldInline()) {
InliningUtil.traceInlinedMethod(info, inliningDepth, fullyProcessed, "forced inlining");
return InliningPolicy.Decision.YES.withReason(isTracing, "forced inlining");
}
double inliningBonus = getInliningBonus(info);
int nodes = info.determineNodeCount();
if (nodes < TrivialInliningSize.getValue(options) * inliningBonus) {
InliningUtil.traceInlinedMethod(info, inliningDepth, fullyProcessed, "trivial (relevance=%f, probability=%f, bonus=%f, nodes=%d)", relevance, probability, inliningBonus, nodes);
return InliningPolicy.Decision.YES.withReason(isTracing, "trivial (relevance=%f, probability=%f, bonus=%f, nodes=%d)", relevance, probability, inliningBonus, nodes);
}
double maximumNodes = computeMaximumSize(relevance, (int) (maxInliningSize(inliningDepth, options) * inliningBonus));
if (nodes <= maximumNodes) {
InliningUtil.traceInlinedMethod(info, inliningDepth, fullyProcessed, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d <= %f)", relevance, probability, inliningBonus,
nodes, maximumNodes);
return InliningPolicy.Decision.YES.withReason(isTracing, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d <= %f)", relevance, probability, inliningBonus,
nodes, maximumNodes);
}
InliningUtil.traceNotInlinedMethod(info, inliningDepth, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d > %f)", relevance, probability, inliningBonus, nodes, maximumNodes);
return InliningPolicy.Decision.NO.withReason(isTracing, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d > %f)", relevance, probability, inliningBonus, nodes, maximumNodes);
}
}