summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndy Ayers <andya@microsoft.com>2016-06-09 17:08:39 -0700
committerGitHub <noreply@github.com>2016-06-09 17:08:39 -0700
commitf2eff33c3b5131248f0b9b428b5850e0cfc568bb (patch)
treef867889354a0c96ab60063de69860ff10e2715ce /src
parent713956f3a691026af775ebdf08f7651d682d4ed0 (diff)
parentaed87099a2f5b70676b7bacf18f696d772b862b9 (diff)
downloadcoreclr-f2eff33c3b5131248f0b9b428b5850e0cfc568bb.tar.gz
coreclr-f2eff33c3b5131248f0b9b428b5850e0cfc568bb.tar.bz2
coreclr-f2eff33c3b5131248f0b9b428b5850e0cfc568bb.zip
Merge pull request #5661 from AndyAyersMS/FirstDraftProfitablityModel
Inliner: implement profitabily side of the ModelPolicy
Diffstat (limited to 'src')
-rw-r--r--src/jit/inlinepolicy.cpp96
-rw-r--r--src/jit/inlinepolicy.h2
2 files changed, 89 insertions, 9 deletions
diff --git a/src/jit/inlinepolicy.cpp b/src/jit/inlinepolicy.cpp
index d63f065580..c5beaa5f2c 100644
--- a/src/jit/inlinepolicy.cpp
+++ b/src/jit/inlinepolicy.cpp
@@ -1141,6 +1141,7 @@ DiscretionaryPolicy::DiscretionaryPolicy(Compiler* compiler, bool isPrejitRoot)
, m_ThrowCount(0)
, m_CallCount(0)
, m_ModelCodeSizeEstimate(0)
+ , m_PerCallInstructionEstimate(0)
{
// Empty
}
@@ -1535,6 +1536,11 @@ void DiscretionaryPolicy::DetermineProfitability(CORINFO_METHOD_INFO* methodInfo
// model for actual inlining.
EstimateCodeSize();
+ // Estimate peformance impact. This is just for model
+ // evaluation purposes -- we'll still use the legacy policy's
+ // model for actual inlining.
+ EstimatePerformanceImpact();
+
// Delegate to LegacyPolicy for the rest
LegacyPolicy::DetermineProfitability(methodInfo);
}
@@ -1692,6 +1698,33 @@ void DiscretionaryPolicy::EstimateCodeSize()
}
//------------------------------------------------------------------------
+// EstimatePeformanceImpact: produce performance estimates based on
+// observations.
+//
+// Notes:
+// Attempts to predict the per-call savings in instructions executed.
+//
+// A negative value indicates the doing the inline will save instructions
+// and likely time.
+
+void DiscretionaryPolicy::EstimatePerformanceImpact()
+{
+ // Performance estimate based on GLMNET model.
+ // R=0.24, RMSE=16.1, MAE=8.9.
+ double perCallSavingsEstimate =
+ -7.35
+ + (m_CallsiteFrequency == InlineCallsiteFrequency::BORING ? 0.76 : 0)
+ + (m_CallsiteFrequency == InlineCallsiteFrequency::LOOP ? -2.02 : 0)
+ + (m_ArgType[0] == CORINFO_TYPE_CLASS ? 3.51 : 0)
+ + (m_ArgType[3] == CORINFO_TYPE_BOOL ? 20.7 : 0)
+ + (m_ArgType[4] == CORINFO_TYPE_CLASS ? 0.38 : 0)
+ + (m_ReturnType == CORINFO_TYPE_CLASS ? 2.32 : 0);
+
+ // Scaled up and reported as an integer value.
+ m_PerCallInstructionEstimate = (int) (SIZE_SCALE * perCallSavingsEstimate);
+}
+
+//------------------------------------------------------------------------
// CodeSizeEstimate: estimated code size impact of the inline
//
// Return Value:
@@ -1866,12 +1899,19 @@ ModelPolicy::ModelPolicy(Compiler* compiler, bool isPrejitRoot)
//
// Arguments:
// methodInfo -- method info for the callee
+//
+// Notes:
+// There are currently two parameters that are ad-hoc: the
+// per-call-site weight and the size/speed threshold. Ideally this
+// policy would have just one tunable parameter, the threshold,
+// which describes how willing we are to trade size for speed.
void ModelPolicy::DetermineProfitability(CORINFO_METHOD_INFO* methodInfo)
{
// Do some homework
MethodInfoObservations(methodInfo);
EstimateCodeSize();
+ EstimatePerformanceImpact();
// Preliminary inline model.
//
@@ -1899,18 +1939,56 @@ void ModelPolicy::DetermineProfitability(CORINFO_METHOD_INFO* methodInfo)
}
else
{
- // This is a very crude profitability model, based on what
- // the LegacyPolicy does. It will be updated over time.
- m_Multiplier = DetermineMultiplier();
- double benefit = SIZE_SCALE * (m_Multiplier / m_ModelCodeSizeEstimate);
- double threshold = 0.25;
+ // We estimate that this inline will increase code size. Only
+ // inline if the performance win is sufficiently large to
+ // justify bigger code.
+
+ // First compute the number of instruction executions saved
+ // via inlining per call to the callee per byte of code size
+ // impact.
+ //
+ // The per call instruction estimate is negative if the inline
+ // will reduce instruction count. Flip the sign here to make
+ // positive be better and negative worse.
+ double perCallBenefit = -((double) m_PerCallInstructionEstimate / (double) m_ModelCodeSizeEstimate);
+
+ // Now estimate the local call frequency.
+ //
+ // Todo: use IBC data, or a better local profile estimate, or
+ // try and incorporate this into the model. For instance if we
+ // tried to predict the benefit per call to the root method
+ // then the model would have to incorporate the local call
+ // frequency, somehow.
+ double callSiteWeight = 1.0;
+
+ if ((m_CallsiteFrequency == InlineCallsiteFrequency::LOOP) ||
+ (m_CallsiteFrequency == InlineCallsiteFrequency::HOT))
+ {
+ callSiteWeight = 8.0;
+ }
+
+ // Determine the estimated number of instructions saved per
+ // call to the root method per byte of code size impact. This
+ // is our benefit figure of merit.
+ double benefit = callSiteWeight * perCallBenefit;
+
+ // Compare this to the threshold, and inline if greater.
+ //
+ // The threshold is interpretable as a size/speed tradeoff:
+ // the value of 0.2 below indicates we'll allow inlines that
+ // grow code by as many as 5 bytes to save 1 instruction
+ // execution (per call to the root method).
+ double threshold = 0.20;
bool shouldInline = (benefit > threshold);
JITLOG_THIS(m_RootCompiler,
- (LL_INFO100000,
- "Inline %s profitable: benefit=%g (mult=%g / size=%d)\n",
- shouldInline ? "is" : "is not",
- benefit, m_Multiplier, (double) m_ModelCodeSizeEstimate / SIZE_SCALE));
+ (LL_INFO100000,
+ "Inline %s profitable: benefit=%g (weight=%g, percall=%g, size=%g)\n",
+ shouldInline ? "is" : "is not",
+ benefit, callSiteWeight,
+ (double) m_PerCallInstructionEstimate / SIZE_SCALE,
+ (double) m_ModelCodeSizeEstimate / SIZE_SCALE));
+
if (!shouldInline)
{
// Fail the inline
diff --git a/src/jit/inlinepolicy.h b/src/jit/inlinepolicy.h
index 3965b8df87..7f254cadab 100644
--- a/src/jit/inlinepolicy.h
+++ b/src/jit/inlinepolicy.h
@@ -238,6 +238,7 @@ protected:
void ComputeOpcodeBin(OPCODE opcode);
void EstimateCodeSize();
+ void EstimatePerformanceImpact();
void MethodInfoObservations(CORINFO_METHOD_INFO* methodInfo);
enum { MAX_ARGS = 6 };
@@ -279,6 +280,7 @@ protected:
unsigned m_ThrowCount;
unsigned m_CallCount;
int m_ModelCodeSizeEstimate;
+ int m_PerCallInstructionEstimate;
};
// ModelPolicy is an experimental policy that uses the results