summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/jit/inline.h22
-rw-r--r--src/jit/inlinepolicy.cpp77
-rw-r--r--src/jit/inlinepolicy.h24
-rw-r--r--src/jit/jitconfigvalues.h1
-rw-r--r--tests/src/JIT/jit64/regress/ddb/87766/ddb87766.cs8
5 files changed, 124 insertions, 8 deletions
diff --git a/src/jit/inline.h b/src/jit/inline.h
index d0eaf42735..19c3e2d09a 100644
--- a/src/jit/inline.h
+++ b/src/jit/inline.h
@@ -656,7 +656,7 @@ public:
InlineResult* inlineResult);
// Compiler associated with this strategy
- Compiler* GetCompiler()
+ Compiler* GetCompiler() const
{
return m_Compiler;
}
@@ -665,23 +665,35 @@ public:
InlineContext* GetRootContext();
// Get IL size for maximum allowable inline
- unsigned GetMaxInlineILSize()
+ unsigned GetMaxInlineILSize() const
{
return m_MaxInlineSize;
}
// Get depth of maximum allowable inline
- unsigned GetMaxInlineDepth()
+ unsigned GetMaxInlineDepth() const
{
return m_MaxInlineDepth;
}
- // Number of successful inlines into the root.
- unsigned GetInlineCount()
+ // Number of successful inlines into the root
+ unsigned GetInlineCount() const
{
return m_InlineCount;
}
+ // Return the current code size estimate for this method
+ int GetCurrentSizeEstimate() const
+ {
+ return m_CurrentSizeEstimate;
+ }
+
+ // Return the initial code size estimate for this method
+ int GetInitialSizeEstimate() const
+ {
+ return m_InitialSizeEstimate;
+ }
+
// Inform strategy that there's a new inline candidate.
void NoteCandidate();
diff --git a/src/jit/inlinepolicy.cpp b/src/jit/inlinepolicy.cpp
index 9615bdcfb5..73e22d4530 100644
--- a/src/jit/inlinepolicy.cpp
+++ b/src/jit/inlinepolicy.cpp
@@ -43,6 +43,14 @@ InlinePolicy* InlinePolicy::GetPolicy(Compiler* compiler, bool isPrejitRoot)
#if defined(DEBUG) || defined(INLINE_DATA)
+ // Optionally install the SizePolicy.
+ bool useSizePolicy = JitConfig.JitInlinePolicySize() != 0;
+
+ if (useSizePolicy)
+ {
+ return new (compiler, CMK_Inlining) SizePolicy(compiler, isPrejitRoot);
+ }
+
// Optionally install the FullPolicy.
bool useFullPolicy = JitConfig.JitInlinePolicyFull() != 0;
@@ -1948,4 +1956,73 @@ void FullPolicy::DetermineProfitability(CORINFO_METHOD_INFO* methodInfo)
return;
}
+//------------------------------------------------------------------------/
+// SizePolicy: construct a new SizePolicy
+//
+// Arguments:
+// compiler -- compiler instance doing the inlining (root compiler)
+// isPrejitRoot -- true if this compiler is prejitting the root method
+
+SizePolicy::SizePolicy(Compiler* compiler, bool isPrejitRoot)
+ : DiscretionaryPolicy(compiler, isPrejitRoot)
+{
+ // Empty
+}
+
+//------------------------------------------------------------------------
+// DetermineProfitability: determine if this inline is profitable
+//
+// Arguments:
+// methodInfo -- method info for the callee
+
+void SizePolicy::DetermineProfitability(CORINFO_METHOD_INFO* methodInfo)
+{
+ // Do some homework
+ MethodInfoObservations(methodInfo);
+ EstimateCodeSize();
+
+ // Does this inline increase the estimated size beyond
+ // the original size estimate?
+ const InlineStrategy* strategy = m_RootCompiler->m_inlineStrategy;
+ const int initialSize = strategy->GetInitialSizeEstimate();
+ const int currentSize = strategy->GetCurrentSizeEstimate();
+ const int newSize = currentSize + m_ModelCodeSizeEstimate;
+
+ if (newSize <= initialSize)
+ {
+ // Estimated size impact is acceptable, so inline here.
+ JITLOG_THIS(m_RootCompiler,
+ (LL_INFO100000,
+ "Inline profitable, root size estimate %d is less than initial size %d\n",
+ newSize / SIZE_SCALE, initialSize / SIZE_SCALE));
+
+ if (m_IsPrejitRoot)
+ {
+ SetCandidate(InlineObservation::CALLEE_IS_SIZE_DECREASING_INLINE);
+ }
+ else
+ {
+ SetCandidate(InlineObservation::CALLSITE_IS_SIZE_DECREASING_INLINE);
+ }
+ }
+ else
+ {
+ // Estimated size increase is too large, so no inline here.
+ //
+ // Note that we ought to reconsider this inline if we make
+ // room in the budget by inlining a bunch of size decreasing
+ // inlines after this one. But for now, we won't do this.
+ if (m_IsPrejitRoot)
+ {
+ SetNever(InlineObservation::CALLEE_NOT_PROFITABLE_INLINE);
+ }
+ else
+ {
+ SetFailure(InlineObservation::CALLSITE_NOT_PROFITABLE_INLINE);
+ }
+ }
+
+ return;
+}
+
#endif // defined(DEBUG) || defined(INLINE_DATA)
diff --git a/src/jit/inlinepolicy.h b/src/jit/inlinepolicy.h
index eb019d446b..31a686e52f 100644
--- a/src/jit/inlinepolicy.h
+++ b/src/jit/inlinepolicy.h
@@ -19,6 +19,7 @@
// DiscretionaryPolicy - legacy variant with uniform size policy
// ModelPolicy - policy based on statistical modelling
// FullPolicy - inlines everything up to size and depth limits
+// SizePolicy - tries not to increase method sizes
#ifndef _INLINE_POLICY_H_
#define _INLINE_POLICY_H_
@@ -307,7 +308,7 @@ class FullPolicy : public DiscretionaryPolicy
{
public:
- // Construct a ModelPolicy
+ // Construct a FullPolicy
FullPolicy(Compiler* compiler, bool isPrejitRoot);
// Policy determinations
@@ -317,6 +318,27 @@ public:
const char* GetName() const override { return "FullPolicy"; }
};
+// SizePolicy is an experimental policy that will inline as much
+// as possible without increasing the (estimated) method size.
+//
+// It may be useful down the road as a policy to use for methods
+// that are rarely executed (eg class constructors).
+
+class SizePolicy : public DiscretionaryPolicy
+{
+public:
+
+ // Construct a SizePolicy
+ SizePolicy(Compiler* compiler, bool isPrejitRoot);
+
+ // Policy determinations
+ void DetermineProfitability(CORINFO_METHOD_INFO* methodInfo) override;
+
+ // Miscellaneous
+ const char* GetName() const override { return "SizePolicy"; }
+};
+
+
#endif // defined(DEBUG) || defined(INLINE_DATA)
#endif // _INLINE_POLICY_H_
diff --git a/src/jit/jitconfigvalues.h b/src/jit/jitconfigvalues.h
index cbf676d413..cb4724dee0 100644
--- a/src/jit/jitconfigvalues.h
+++ b/src/jit/jitconfigvalues.h
@@ -197,6 +197,7 @@ CONFIG_INTEGER(JitInlineLimit, W("JitInlineLimit"), -1)
CONFIG_INTEGER(JitInlinePolicyDiscretionary, W("JitInlinePolicyDiscretionary"), 0)
CONFIG_INTEGER(JitInlinePolicyModel, W("JitInlinePolicyModel"), 0)
CONFIG_INTEGER(JitInlinePolicyFull, W("JitInlinePolicyFull"), 0)
+CONFIG_INTEGER(JitInlinePolicySize, W("JitInlinePolicySize"), 0)
CONFIG_STRING(JitNoInlineRange, W("JitNoInlineRange"))
#endif // defined(DEBUG) || defined(INLINE_DATA)
diff --git a/tests/src/JIT/jit64/regress/ddb/87766/ddb87766.cs b/tests/src/JIT/jit64/regress/ddb/87766/ddb87766.cs
index 445026c5e0..a33bf86b92 100644
--- a/tests/src/JIT/jit64/regress/ddb/87766/ddb87766.cs
+++ b/tests/src/JIT/jit64/regress/ddb/87766/ddb87766.cs
@@ -2,23 +2,27 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-
using System;
+using System.Runtime.CompilerServices;
public class VInline
{
private int _fi1;
private int _fi2;
+
public VInline(int ival)
{
_fi1 = ival;
_fi2 = 0;
}
- [System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
private void GetI1(ref int i)
{
i = _fi1;
}
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public int Accumulate(int a)
{
int i = 0;