Inliner: updates to random inlining (dotnet/coreclr#8088)
authorAndy Ayers <andya@microsoft.com>
Sat, 12 Nov 2016 03:52:24 +0000 (19:52 -0800)
committerGitHub <noreply@github.com>
Sat, 12 Nov 2016 03:52:24 +0000 (19:52 -0800)
Cache the random state on the InlineStrategy instead of on the compiler
instance so that the state is reinitialized and private to each jit request.
That way the random policy evaluations made compiling one method won't
alter the evaluations for subsequent methods. This should make it somewhat
easier to do A/B comparisons under jit stress when changing the jit.

Make it possible to enable the RandomPolicy outside of stress. This may
prove useful in various randomized inline performance studies or as
a simple stress mode on its own.

Random state seed is built from an external seed value (via JitStress or
JitInlinePolicyRandom) and an internal seed value (method hash), so that
random sequences potentially differ for each method but are deterministic
across runs and changes to the jit.

Commit migrated from https://github.com/dotnet/coreclr/commit/7697dec7db3e34239ffa33d8867de12f7176e415

src/coreclr/src/jit/compiler.cpp
src/coreclr/src/jit/compiler.h
src/coreclr/src/jit/inline.cpp
src/coreclr/src/jit/inline.h
src/coreclr/src/jit/inlinepolicy.cpp
src/coreclr/src/jit/inlinepolicy.h
src/coreclr/src/jit/jitconfigvalues.h

index c5f8016..8c7e14d 100644 (file)
@@ -1913,10 +1913,6 @@ void Compiler::compInit(ArenaAllocator* pAlloc, InlineInfo* inlineInfo)
     SIMDVectorHandle  = nullptr;
 #endif
 
-#ifdef DEBUG
-    inlRNG = nullptr;
-#endif
-
     compUsesThrowHelper = false;
 }
 
index cd5da25..60a92ce 100644 (file)
@@ -7820,10 +7820,6 @@ public:
 #endif
     }
 
-#ifdef DEBUG
-    CLRRandom* inlRNG;
-#endif
-
     //--------------------- Info about the procedure --------------------------
 
     struct Info
index aa1b55d..ced8380 100644 (file)
@@ -747,6 +747,7 @@ InlineStrategy::InlineStrategy(Compiler* compiler)
     , m_HasForceViaDiscretionary(false)
 #if defined(DEBUG) || defined(INLINE_DATA)
     , m_MethodXmlFilePosition(0)
+    , m_Random(nullptr)
 #endif // defined(DEBUG) || defined(INLINE_DATA)
 
 {
@@ -1596,6 +1597,47 @@ void InlineStrategy::FinalizeXml(FILE* file)
     ReplayPolicy::FinalizeXml();
 }
 
+//------------------------------------------------------------------------
+// GetRandom: setup or access random state
+//
+// Return Value:
+//    New or pre-existing random state.
+//
+// Notes:
+//    Random state is kept per jit compilation request. Seed is partially
+//    specified externally (via stress or policy setting) and partially
+//    specified internally via method hash.
+
+CLRRandom* InlineStrategy::GetRandom()
+{
+    if (m_Random == nullptr)
+    {
+        int externalSeed = 0;
+        if (m_Compiler->compRandomInlineStress())
+        {
+            externalSeed = getJitStressLevel();
+        }
+
+        int randomPolicyFlag = JitConfig.JitInlinePolicyRandom();
+        if (randomPolicyFlag != 0)
+        {
+            externalSeed = randomPolicyFlag;
+        }
+
+        int internalSeed = m_Compiler->info.compMethodHash();
+
+        assert(externalSeed != 0);
+        assert(internalSeed != 0);
+
+        int seed = externalSeed ^ internalSeed;
+
+        m_Random = new (m_Compiler, CMK_Inlining) CLRRandom();
+        m_Random->Init(seed);
+    }
+
+    return m_Random;
+}
+
 #endif // defined(DEBUG) || defined(INLINE_DATA)
 
 //------------------------------------------------------------------------
index 2bc483c..3de62e6 100644 (file)
@@ -820,6 +820,9 @@ public:
         m_MethodXmlFilePosition = val;
     }
 
+    // Set up or access random state (for use by RandomPolicy)
+    CLRRandom* GetRandom();
+
 #endif // defined(DEBUG) || defined(INLINE_DATA)
 
     // Some inline limit values
@@ -884,7 +887,8 @@ private:
     bool           m_HasForceViaDiscretionary;
 
 #if defined(DEBUG) || defined(INLINE_DATA)
-    long m_MethodXmlFilePosition;
+    long       m_MethodXmlFilePosition;
+    CLRRandom* m_Random;
 #endif // defined(DEBUG) || defined(INLINE_DATA)
 };
 
index c67b32c..a909845 100644 (file)
@@ -30,13 +30,12 @@ InlinePolicy* InlinePolicy::GetPolicy(Compiler* compiler, bool isPrejitRoot)
 #ifdef DEBUG
 
     // Optionally install the RandomPolicy.
-    bool useRandomPolicy = compiler->compRandomInlineStress();
+    const bool useRandomPolicyForStress = compiler->compRandomInlineStress();
+    const bool useRandomPolicy          = (JitConfig.JitInlinePolicyRandom() != 0);
 
-    if (useRandomPolicy)
+    if (useRandomPolicyForStress || useRandomPolicy)
     {
-        unsigned seed = getJitStressLevel();
-        assert(seed != 0);
-        return new (compiler, CMK_Inlining) RandomPolicy(compiler, isPrejitRoot, seed);
+        return new (compiler, CMK_Inlining) RandomPolicy(compiler, isPrejitRoot);
     }
 
 #endif // DEBUG
@@ -974,7 +973,7 @@ bool EnhancedLegacyPolicy::PropagateNeverToRuntime() const
     return propagate;
 }
 
-#ifdef DEBUG
+#if defined(DEBUG) || defined(INLINE_DATA)
 
 //------------------------------------------------------------------------
 // RandomPolicy: construct a new RandomPolicy
@@ -982,9 +981,8 @@ bool EnhancedLegacyPolicy::PropagateNeverToRuntime() const
 // Arguments:
 //    compiler -- compiler instance doing the inlining (root compiler)
 //    isPrejitRoot -- true if this compiler is prejitting the root method
-//    seed -- seed value for the random number generator
 
-RandomPolicy::RandomPolicy(Compiler* compiler, bool isPrejitRoot, unsigned seed)
+RandomPolicy::RandomPolicy(Compiler* compiler, bool isPrejitRoot)
     : LegalPolicy(isPrejitRoot)
     , m_RootCompiler(compiler)
     , m_Random(nullptr)
@@ -992,19 +990,7 @@ RandomPolicy::RandomPolicy(Compiler* compiler, bool isPrejitRoot, unsigned seed)
     , m_IsForceInline(false)
     , m_IsForceInlineKnown(false)
 {
-    // If necessary, setup and seed the random state.
-    if (compiler->inlRNG == nullptr)
-    {
-        compiler->inlRNG = new (compiler, CMK_Inlining) CLRRandom();
-
-        unsigned hash = m_RootCompiler->info.compMethodHash();
-        assert(hash != 0);
-        assert(seed != 0);
-        int hashSeed = static_cast<int>(hash ^ seed);
-        compiler->inlRNG->Init(hashSeed);
-    }
-
-    m_Random = compiler->inlRNG;
+    m_Random = compiler->m_inlineStrategy->GetRandom();
 }
 
 //------------------------------------------------------------------------
@@ -1211,7 +1197,7 @@ void RandomPolicy::DetermineProfitability(CORINFO_METHOD_INFO* methodInfo)
     }
 }
 
-#endif // DEBUG
+#endif // defined(DEBUG) || defined(INLINE_DATA)
 
 #ifdef _MSC_VER
 // Disable warning about new array member initialization behavior
index 4b1e55e..c010a98 100644 (file)
@@ -198,7 +198,7 @@ protected:
     bool m_IsNoReturnKnown : 1;
 };
 
-#ifdef DEBUG
+#if defined(DEBUG) || defined(INLINE_DATA)
 
 // RandomPolicy implements a policy that inlines at random.
 // It is mostly useful for stress testing.
@@ -207,7 +207,7 @@ class RandomPolicy : public LegalPolicy
 {
 public:
     // Construct a RandomPolicy
-    RandomPolicy(Compiler* compiler, bool isPrejitRoot, unsigned seed);
+    RandomPolicy(Compiler* compiler, bool isPrejitRoot);
 
     // Policy observations
     void NoteSuccess() override;
@@ -247,7 +247,7 @@ private:
     bool       m_IsForceInlineKnown : 1;
 };
 
-#endif // DEBUG
+#endif // defined(DEBUG) || defined(INLINE_DATA)
 
 // DiscretionaryPolicy is a variant of the enhanced legacy policy.  It
 // differs in that there is no ALWAYS_INLINE class, there is no IL
index f53de13..7f6b421 100644 (file)
@@ -256,6 +256,8 @@ CONFIG_INTEGER(JitInlineLimit, W("JitInlineLimit"), -1)
 CONFIG_INTEGER(JitInlinePolicyDiscretionary, W("JitInlinePolicyDiscretionary"), 0)
 CONFIG_INTEGER(JitInlinePolicyFull, W("JitInlinePolicyFull"), 0)
 CONFIG_INTEGER(JitInlinePolicySize, W("JitInlinePolicySize"), 0)
+CONFIG_INTEGER(JitInlinePolicyRandom, W("JitInlinePolicyRandom"), 0) // nozero enables; value is the external random
+                                                                     // seed
 CONFIG_INTEGER(JitInlinePolicyReplay, W("JitInlinePolicyReplay"), 0)
 CONFIG_STRING(JitNoInlineRange, W("JitNoInlineRange"))
 CONFIG_STRING(JitInlineReplayFile, W("JitInlineReplayFile"))