summaryrefslogtreecommitdiff
path: root/src/jit/compiler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/jit/compiler.cpp')
-rw-r--r--src/jit/compiler.cpp126
1 files changed, 86 insertions, 40 deletions
diff --git a/src/jit/compiler.cpp b/src/jit/compiler.cpp
index 01c7f8d6a7..14b2abafb6 100644
--- a/src/jit/compiler.cpp
+++ b/src/jit/compiler.cpp
@@ -73,9 +73,9 @@ inline bool _our_GetThreadCycles(unsigned __int64* cycleOut)
inline bool _our_GetThreadCycles(unsigned __int64* cycleOut)
{
- uint64_t cycles;
- asm volatile("rdtsc" : "=A"(cycles));
- *cycleOut = cycles;
+ uint32_t hi, lo;
+ __asm__ __volatile__("rdtsc" : "=a"(lo), "=d"(hi));
+ *cycleOut = (static_cast<unsigned __int64>(hi) << 32) | static_cast<unsigned __int64>(lo);
return true;
}
@@ -2296,7 +2296,6 @@ void Compiler::compSetProcessor()
#ifdef FEATURE_AVX_SUPPORT
// COMPlus_EnableAVX can be used to disable using AVX if available on a target machine.
- // Note that FEATURE_AVX_SUPPORT is not enabled for ctpjit
opts.compCanUseAVX = false;
if (!jitFlags.IsSet(JitFlags::JIT_FLAG_PREJIT) && jitFlags.IsSet(JitFlags::JIT_FLAG_USE_AVX2))
{
@@ -2471,7 +2470,8 @@ void Compiler::compInitOptions(JitFlags* jitFlags)
opts.jitFlags = jitFlags;
opts.compFlags = CLFLG_MAXOPT; // Default value is for full optimization
- if (jitFlags->IsSet(JitFlags::JIT_FLAG_DEBUG_CODE) || jitFlags->IsSet(JitFlags::JIT_FLAG_MIN_OPT))
+ if (jitFlags->IsSet(JitFlags::JIT_FLAG_DEBUG_CODE) || jitFlags->IsSet(JitFlags::JIT_FLAG_MIN_OPT) ||
+ jitFlags->IsSet(JitFlags::JIT_FLAG_TIER0))
{
opts.compFlags = CLFLG_MINOPT;
}
@@ -2496,7 +2496,8 @@ void Compiler::compInitOptions(JitFlags* jitFlags)
//
// If the EE sets SPEED_OPT we will optimize for speed at the expense of code size
//
- else if (jitFlags->IsSet(JitFlags::JIT_FLAG_SPEED_OPT))
+ else if (jitFlags->IsSet(JitFlags::JIT_FLAG_SPEED_OPT) ||
+ (jitFlags->IsSet(JitFlags::JIT_FLAG_TIER1) && !jitFlags->IsSet(JitFlags::JIT_FLAG_MIN_OPT)))
{
opts.compCodeOpt = FAST_CODE;
assert(!jitFlags->IsSet(JitFlags::JIT_FLAG_SIZE_OPT));
@@ -3031,13 +3032,31 @@ void Compiler::compInitOptions(JitFlags* jitFlags)
setUsesSIMDTypes(false);
#endif // FEATURE_SIMD
- if (compIsForInlining() || compIsForImportOnly())
+ if (compIsForImportOnly())
{
return;
}
+
+#if FEATURE_TAILCALL_OPT
+ // By default opportunistic tail call optimization is enabled.
+ // Recognition is done in the importer so this must be set for
+ // inlinees as well.
+ opts.compTailCallOpt = true;
+#endif // FEATURE_TAILCALL_OPT
+
+ if (compIsForInlining())
+ {
+ return;
+ }
+
// The rest of the opts fields that we initialize here
// should only be used when we generate code for the method
// They should not be used when importing or inlining
+ CLANG_FORMAT_COMMENT_ANCHOR;
+
+#if FEATURE_TAILCALL_OPT
+ opts.compTailCallLoopOpt = true;
+#endif // FEATURE_TAILCALL_OPT
opts.genFPorder = true;
opts.genFPopt = true;
@@ -3045,12 +3064,6 @@ void Compiler::compInitOptions(JitFlags* jitFlags)
opts.instrCount = 0;
opts.lvRefCount = 0;
-#if FEATURE_TAILCALL_OPT
- // By default opportunistic tail call optimization is enabled
- opts.compTailCallOpt = true;
- opts.compTailCallLoopOpt = true;
-#endif
-
#ifdef PROFILING_SUPPORTED
opts.compJitELTHookEnabled = false;
#endif // PROFILING_SUPPORTED
@@ -3308,11 +3321,9 @@ void Compiler::compInitOptions(JitFlags* jitFlags)
info.compMethodInfo->args.pSig);
#endif
-//-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
-#if RELOC_SUPPORT
opts.compReloc = jitFlags->IsSet(JitFlags::JIT_FLAG_RELOC);
-#endif
#ifdef DEBUG
#if defined(_TARGET_XARCH_) && !defined(LEGACY_BACKEND)
@@ -4444,7 +4455,7 @@ void Compiler::compCompile(void** methodCodePtr, ULONG* methodCodeSize, JitFlags
bool doRangeAnalysis = true;
int iterations = 1;
-#ifdef DEBUG
+#if defined(OPT_CONFIG)
doSsa = (JitConfig.JitDoSsa() != 0);
doEarlyProp = doSsa && (JitConfig.JitDoEarlyProp() != 0);
doValueNum = doSsa && (JitConfig.JitDoValueNumber() != 0);
@@ -4457,7 +4468,7 @@ void Compiler::compCompile(void** methodCodePtr, ULONG* methodCodeSize, JitFlags
{
iterations = JitConfig.JitOptRepeatCount();
}
-#endif
+#endif // defined(OPT_CONFIG)
while (iterations > 0)
{
@@ -4978,17 +4989,13 @@ int Compiler::compCompile(CORINFO_METHOD_HANDLE methodHnd,
// with an ARM-targeting "altjit").
info.compMatchedVM = IMAGE_FILE_MACHINE_TARGET == info.compCompHnd->getExpectedTargetArchitecture();
-#if defined(ALT_JIT) && defined(UNIX_AMD64_ABI)
- // ToDo: This code is to allow us to run UNIX codegen on Windows for now. Remove when appropriate.
- // Make sure that the generated UNIX altjit code is skipped on Windows. The static jit codegen is used to run.
+#if (defined(_TARGET_UNIX_) && !defined(_HOST_UNIX_)) || (!defined(_TARGET_UNIX_) && defined(_HOST_UNIX_))
+ // The host and target platforms don't match. This info isn't handled by the existing
+ // getExpectedTargetArchitecture() JIT-EE interface method.
info.compMatchedVM = false;
-#endif // UNIX_AMD64_ABI
+#endif
-#if COR_JIT_EE_VERSION > 460
compMaxUncheckedOffsetForNullObject = eeGetEEInfo()->maxUncheckedOffsetForNullObject;
-#else // COR_JIT_EE_VERSION <= 460
- compMaxUncheckedOffsetForNullObject = MAX_UNCHECKED_OFFSET_FOR_NULL_OBJECT;
-#endif // COR_JIT_EE_VERSION > 460
// Set the context for token lookup.
if (compIsForInlining())
@@ -5406,7 +5413,7 @@ void Compiler::compCompileFinish()
{
if (compJitHaltMethod())
{
-#if !defined(_TARGET_ARM64_) && !defined(PLATFORM_UNIX)
+#if !defined(_TARGET_ARM64_) && !defined(_HOST_UNIX_)
// TODO-ARM64-NYI: re-enable this when we have an OS that supports a pop-up dialog
// Don't do an assert, but just put up the dialog box so we get just-in-time debugger
@@ -5651,12 +5658,6 @@ int Compiler::compCompileHelper(CORINFO_MODULE_HANDLE classPtr,
info.compCallUnmanaged = 0;
info.compLvFrameListRoot = BAD_VAR_NUM;
-#if FEATURE_FIXED_OUT_ARGS
- lvaOutgoingArgSpaceSize = 0;
-#endif
-
- lvaGenericsContextUsed = false;
-
info.compInitMem = ((methodInfo->options & CORINFO_OPT_INIT_LOCALS) != 0);
/* Allocate the local variable table */
@@ -7206,29 +7207,34 @@ double JitTimer::s_cyclesPerSec = CycleTimer::CyclesPerSecond();
#if defined(FEATURE_JIT_METHOD_PERF) || DUMP_FLOWGRAPHS || defined(FEATURE_TRACELOGGING)
const char* PhaseNames[] = {
-#define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent) string_nm,
+#define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent, measureIR) string_nm,
#include "compphases.h"
};
const char* PhaseEnums[] = {
-#define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent) #enum_nm,
+#define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent, measureIR) #enum_nm,
#include "compphases.h"
};
const LPCWSTR PhaseShortNames[] = {
-#define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent) W(short_nm),
+#define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent, measureIR) W(short_nm),
#include "compphases.h"
};
#endif // defined(FEATURE_JIT_METHOD_PERF) || DUMP_FLOWGRAPHS
#ifdef FEATURE_JIT_METHOD_PERF
bool PhaseHasChildren[] = {
-#define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent) hasChildren,
+#define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent, measureIR) hasChildren,
#include "compphases.h"
};
int PhaseParent[] = {
-#define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent) parent,
+#define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent, measureIR) parent,
+#include "compphases.h"
+};
+
+bool PhaseReportsIRSize[] = {
+#define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent, measureIR) measureIR,
#include "compphases.h"
};
@@ -7636,7 +7642,7 @@ JitTimer::JitTimer(unsigned byteCodeSize) : m_info(byteCodeSize)
}
}
-void JitTimer::EndPhase(Phases phase)
+void JitTimer::EndPhase(Compiler* compiler, Phases phase)
{
// Otherwise...
// We re-run some phases currently, so this following assert doesn't work.
@@ -7687,6 +7693,15 @@ void JitTimer::EndPhase(Phases phase)
m_curPhaseStart = threadCurCycles;
}
}
+
+ if ((JitConfig.JitMeasureIR() != 0) && PhaseReportsIRSize[phase])
+ {
+ m_info.m_nodeCountAfterPhase[phase] = compiler->fgMeasureIR();
+ }
+ else
+ {
+ m_info.m_nodeCountAfterPhase[phase] = 0;
+ }
}
#ifdef DEBUG
@@ -7795,6 +7810,9 @@ void JitTimer::PrintCsvHeader()
FILE* fp = _wfopen(jitTimeLogCsv, W("a"));
if (fp != nullptr)
{
+ // Seek to the end of the file s.t. `ftell` doesn't lie to us on Windows
+ fseek(fp, 0, SEEK_END);
+
// Write the header if the file is empty
if (ftell(fp) == 0)
{
@@ -7808,10 +7826,17 @@ void JitTimer::PrintCsvHeader()
for (int i = 0; i < PHASE_NUMBER_OF; i++)
{
fprintf(fp, "\"%s\",", PhaseNames[i]);
+ if (PhaseReportsIRSize[i])
+ {
+ fprintf(fp, "\"Node Count After %s\",", PhaseNames[i]);
+ }
}
InlineStrategy::DumpCsvHeader(fp);
+ fprintf(fp, "\"Executable Code Bytes\",");
+ fprintf(fp, "\"GC Info Bytes\",");
+ fprintf(fp, "\"Total Bytes Allocated\",");
fprintf(fp, "\"Total Cycles\",");
fprintf(fp, "\"CPS\"\n");
}
@@ -7858,10 +7883,18 @@ void JitTimer::PrintCsvMethodStats(Compiler* comp)
totCycles += m_info.m_cyclesByPhase[i];
}
fprintf(fp, "%I64u,", m_info.m_cyclesByPhase[i]);
+
+ if (PhaseReportsIRSize[i])
+ {
+ fprintf(fp, "%u,", m_info.m_nodeCountAfterPhase[i]);
+ }
}
comp->m_inlineStrategy->DumpCsvData(fp);
+ fprintf(fp, "%Iu,", comp->info.compNativeCodeSize);
+ fprintf(fp, "%Iu,", comp->compInfoBlkSize);
+ fprintf(fp, "%Iu,", comp->compGetAllocator()->getTotalBytesAllocated());
fprintf(fp, "%I64u,", m_info.m_totalCycles);
fprintf(fp, "%f\n", CycleTimer::CyclesPerSecond());
fclose(fp);
@@ -8126,11 +8159,12 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
* The versions that start with 'd' use the tlsCompiler, so don't require a Compiler*.
*
* Summary:
- * cBlock, dBlock : Display a basic block (call fgDispBasicBlock()).
+ * cBlock, dBlock : Display a basic block (call fgTableDispBasicBlock()).
* cBlocks, dBlocks : Display all the basic blocks of a function (call fgDispBasicBlocks()).
* cBlocksV, dBlocksV : Display all the basic blocks of a function (call fgDispBasicBlocks(true)).
* "V" means "verbose", and will dump all the trees.
* cTree, dTree : Display a tree (call gtDispTree()).
+ * cTreeLIR, dTreeLIR : Display a tree in LIR form (call gtDispLIRNode()).
* cTrees, dTrees : Display all the trees in a function (call fgDumpTrees()).
* cEH, dEH : Display the EH handler table (call fgDispHandlerTab()).
* cVar, dVar : Display a local variable given its number (call lvaDumpEntry()).
@@ -8200,6 +8234,13 @@ void cTree(Compiler* comp, GenTree* tree)
comp->gtDispTree(tree, nullptr, ">>>");
}
+void cTreeLIR(Compiler* comp, GenTree* tree)
+{
+ static unsigned sequenceNumber = 0; // separate calls with a number to indicate this function has been called
+ printf("===================================================================== *TreeLIR %u\n", sequenceNumber++);
+ comp->gtDispLIRNode(tree);
+}
+
void cTrees(Compiler* comp)
{
static unsigned sequenceNumber = 0; // separate calls with a number to indicate this function has been called
@@ -8314,6 +8355,11 @@ void dTree(GenTree* tree)
cTree(JitTls::GetCompiler(), tree);
}
+void dTreeLIR(GenTree* tree)
+{
+ cTreeLIR(JitTls::GetCompiler(), tree);
+}
+
void dTrees()
{
cTrees(JitTls::GetCompiler());