Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/coreclr/jit/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ set( JIT_I386_SOURCES
set( JIT_ARM64_SOURCES
codegenarmarch.cpp
codegenarm64.cpp
codegenarm64test.cpp
emitarm64.cpp
lowerarmarch.cpp
lsraarmarch.cpp
Expand Down
17 changes: 10 additions & 7 deletions src/coreclr/jit/codegen.h
Original file line number Diff line number Diff line change
Expand Up @@ -639,18 +639,21 @@ class CodeGen final : public CodeGenInterface

void genGeneratePrologsAndEpilogs();

#if defined(DEBUG) && defined(TARGET_ARM64)
void genArm64EmitterUnitTests();
#endif
#if defined(DEBUG)
void genEmitterUnitTests();

#if defined(DEBUG) && defined(TARGET_LOONGARCH64)
void genLoongArch64EmitterUnitTests();
#if defined(TARGET_ARM64)
void genArm64EmitterUnitTestsGeneral();
void genArm64EmitterUnitTestsAdvSimd();
void genArm64EmitterUnitTestsSve();
#endif

#if defined(DEBUG) && defined(LATE_DISASM) && defined(TARGET_AMD64)
void genAmd64EmitterUnitTests();
#if defined(TARGET_AMD64)
void genAmd64EmitterUnitTestsSse2();
#endif

#endif // defined(DEBUG)

#ifdef TARGET_ARM64
virtual void SetSaveFpLrWithAllCalleeSavedRegisters(bool value);
virtual bool IsSaveFpLrWithAllCalleeSavedRegisters() const;
Expand Down
5,339 changes: 0 additions & 5,339 deletions src/coreclr/jit/codegenarm64.cpp

Large diffs are not rendered by default.

5,199 changes: 5,199 additions & 0 deletions src/coreclr/jit/codegenarm64test.cpp

Large diffs are not rendered by default.

76 changes: 67 additions & 9 deletions src/coreclr/jit/codegenlinear.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -516,15 +516,7 @@ void CodeGen::genCodeForBBlist()
#if defined(DEBUG)
if (block->IsLast())
{
// Unit testing of the emitter: generate a bunch of instructions into the last block
// (it's as good as any, but better than the prologue, which can only be a single instruction
// group) then use DOTNET_JitLateDisasm=* to see if the late disassembler
// thinks the instructions are the same as we do.
#if defined(TARGET_AMD64) && defined(LATE_DISASM)
genAmd64EmitterUnitTests();
#elif defined(TARGET_ARM64)
genArm64EmitterUnitTests();
#endif // TARGET_ARM64
genEmitterUnitTests();
}
#endif // defined(DEBUG)

Expand Down Expand Up @@ -2672,3 +2664,69 @@ void CodeGen::genCodeForSetcc(GenTreeCC* setcc)
genProduceReg(setcc);
}
#endif // !TARGET_LOONGARCH64 && !TARGET_RISCV64

/*****************************************************************************
* Unit testing of the emitter: If JitDumpEmitUnitTests is set, generate
* a bunch of instructions, then:
* Use DOTNET_JitLateDisasm=* to see if the late disassembler thinks the instructions as the same as we do.
* Or, use DOTNET_JitRawHexCode and DOTNET_JitRawHexCodeFile and dissassemble the output file.
*
* Possible values for JitDumpEmitUnitTests:
* Amd64: all, sse2
* Arm64: all, general, advsimd, sve
*/

#if defined(DEBUG)

void CodeGen::genEmitterUnitTests()
{
const WCHAR* unitTestSection = JitConfig.JitDumpEmitUnitTests();

if ((!verbose) || (unitTestSection == nullptr))
{
return;
}

// Mark the "fake" instructions in the output.
JITDUMP("*************** In genEmitterUnitTests()\n");

// Jump over the generated tests as they are not intended to be run.
BasicBlock* skipLabel = genCreateTempLabel();
inst_JMP(EJ_jmp, skipLabel);

// Add NOPs at the start and end for easier script parsing.
instGen(INS_nop);

bool unitTestSectionAll = (u16_strstr(unitTestSection, W("all")) != nullptr);

#if defined(TARGET_AMD64)
if (unitTestSectionAll || (u16_strstr(unitTestSection, W("sse2")) != nullptr))
{
genAmd64EmitterUnitTestsSse2();
}

#elif defined(TARGET_ARM64)
if (unitTestSectionAll || (u16_strstr(unitTestSection, W("general")) != nullptr))
{
genArm64EmitterUnitTestsGeneral();
}
if (unitTestSectionAll || (u16_strstr(unitTestSection, W("advsimd")) != nullptr))
{
genArm64EmitterUnitTestsAdvSimd();
}
if (unitTestSectionAll || (u16_strstr(unitTestSection, W("sve")) != nullptr))
{
genArm64EmitterUnitTestsSve();
}
#endif

genDefineTempLabel(skipLabel);
instGen(INS_nop);
instGen(INS_nop);
instGen(INS_nop);
instGen(INS_nop);

JITDUMP("*************** End of genEmitterUnitTests()\n");
}

#endif // defined(DEBUG)
31 changes: 0 additions & 31 deletions src/coreclr/jit/codegenloongarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4573,37 +4573,6 @@ void CodeGen::genStoreLclTypeSIMD12(GenTree* treeNode)

#endif // FEATURE_SIMD

/*****************************************************************************
* Unit testing of the LOONGARCH64 emitter: generate a bunch of instructions into the prolog
* (it's as good a place as any), then use DOTNET_JitLateDisasm=* to see if the late
* disassembler thinks the instructions as the same as we do.
*/

// Uncomment "#define ALL_LOONGARCH64_EMITTER_UNIT_TESTS" to run all the unit tests here.
// After adding a unit test, and verifying it works, put it under this #ifdef, so we don't see it run every time.
//#define ALL_LOONGARCH64_EMITTER_UNIT_TESTS

#if defined(DEBUG)
void CodeGen::genLoongArch64EmitterUnitTests()
{
if (!verbose)
{
return;
}

if (!compiler->opts.altJit)
{
// No point doing this in a "real" JIT.
return;
}

// Mark the "fake" instructions in the output.
printf("*************** In genLoongArch64EmitterUnitTests()\n");

printf("*************** End of genLoongArch64EmitterUnitTests()\n");
}
#endif // defined(DEBUG)

//------------------------------------------------------------------------
// genStackPointerConstantAdjustment: add a specified constant value to the stack pointer.
// No probe is done.
Expand Down
39 changes: 8 additions & 31 deletions src/coreclr/jit/codegenxarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9027,43 +9027,22 @@ void CodeGen::genEmitHelperCall(unsigned helper, int argSize, emitAttr retSize,
regSet.verifyRegistersUsed(killMask);
}

/*****************************************************************************
* Unit testing of the XArch emitter: generate a bunch of instructions into the prolog
* (it's as good a place as any), then use DOTNET_JitLateDisasm=* to see if the late
* disassembler thinks the instructions as the same as we do.
*/
#if defined(DEBUG) && defined(TARGET_AMD64)

// Uncomment "#define ALL_ARM64_EMITTER_UNIT_TESTS" to run all the unit tests here.
// After adding a unit test, and verifying it works, put it under this #ifdef, so we don't see it run every time.
//#define ALL_XARCH_EMITTER_UNIT_TESTS
/*****************************************************************************
* Unit tests for the SSE2 instructions.
*/

#if defined(DEBUG) && defined(LATE_DISASM) && defined(TARGET_AMD64)
void CodeGen::genAmd64EmitterUnitTests()
void CodeGen::genAmd64EmitterUnitTestsSse2()
{
if (!verbose)
{
return;
}

if (!compiler->opts.altJit)
{
// No point doing this in a "real" JIT.
return;
}

// Mark the "fake" instructions in the output.
printf("*************** In genAmd64EmitterUnitTests()\n");

// We use this:
// genDefineTempLabel(genCreateTempLabel());
// to create artificial labels to help separate groups of tests.
assert(verbose);
emitter* theEmitter = GetEmitter();

//
// Loads
//
CLANG_FORMAT_COMMENT_ANCHOR;

#ifdef ALL_XARCH_EMITTER_UNIT_TESTS
genDefineTempLabel(genCreateTempLabel());

// vhaddpd ymm0,ymm1,ymm2
Expand Down Expand Up @@ -9133,11 +9112,9 @@ void CodeGen::genAmd64EmitterUnitTests()
GetEmitter()->emitIns_R_R_R(INS_cvtss2sd, EA_4BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
// vdivsd xmm0,xmm1,xmm2
GetEmitter()->emitIns_R_R_R(INS_cvtsd2ss, EA_8BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
#endif // ALL_XARCH_EMITTER_UNIT_TESTS
printf("*************** End of genAmd64EmitterUnitTests()\n");
}

#endif // defined(DEBUG) && defined(LATE_DISASM) && defined(TARGET_AMD64)
#endif // defined(DEBUG) && defined(TARGET_AMD64)

#ifdef PROFILING_SUPPORTED

Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/jit/jitconfigvalues.h
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,8 @@ CONFIG_STRING(JitStressModeNamesNot, W("JitStressModeNamesNot")) // Internal Jit
// given set of stress mode names, e.g. STRESS_REGS,
// STRESS_TAILCALL
CONFIG_STRING(JitStressRange, W("JitStressRange")) // Internal Jit stress mode
CONFIG_STRING(JitDumpEmitUnitTests, W("JitDumpEmitUnitTests")) // Dump unit tests from Emit
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: will be good to mention example usage like should they be comma-separated, etc. May be in a follow-up PR.


///
/// JIT Hardware Intrinsics
///
Expand Down