diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2442548..cad0d0f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -17,7 +17,7 @@ jobs: uses: actions/checkout@v3 - name: "Setup node.js" - uses: actions/setup-node@v1 + uses: actions/setup-node@v3 with: node-version: "14" diff --git a/src/asmjit/core.h b/src/asmjit/core.h index 5a07269..a9e4df7 100644 --- a/src/asmjit/core.h +++ b/src/asmjit/core.h @@ -454,7 +454,8 @@ namespace asmjit { //! JitRuntime rt; // Runtime specialized for JIT code execution. //! //! CodeHolder code; // Holds code and relocation information. -//! code.init(rt.environment()); // Initialize code to match the JIT environment. +//! code.init(rt.environment(), // Initialize code to match the JIT environment. +//! rt.cpuFeatures()); //! //! x86::Assembler a(&code); // Create and attach x86::Assembler to code. //! a.mov(x86::eax, 1); // Move one to eax register. @@ -599,9 +600,10 @@ namespace asmjit { //! int main() { //! // Create a custom environment that matches the current host environment. //! Environment env = Environment::host(); +//! CpuFeatures cpuFeatures = CpuInfo::host().features(); //! //! CodeHolder code; // Create a CodeHolder. -//! code.init(env); // Initialize CodeHolder with environment. +//! code.init(env, cpuFeatures); // Initialize CodeHolder with environment. //! //! x86::Assembler a(&code); // Create and attach x86::Assembler to `code`. //! @@ -722,10 +724,11 @@ namespace asmjit { //! //! void initializeCodeHolder(CodeHolder& code) { //! Environment env = Environment::host(); +//! CpuFeatures cpuFeatures = CpuInfo::host().features(); //! uint64_t baseAddress = uint64_t(0x1234); //! //! // initialize CodeHolder with environment and custom base address. -//! code.init(env, baseAddress); +//! code.init(env, cpuFeatures, baseAddress); //! } //! ``` //! @@ -1346,7 +1349,8 @@ namespace asmjit { //! FileLogger logger(stdout); // Logger should always survive CodeHolder. //! //! CodeHolder code; // Holds code and relocation information. -//! code.init(rt.environment()); // Initialize to the same arch as JIT runtime. +//! code.init(rt.environment(), // Initialize code to match the JIT environment. +//! rt.cpuFeatures()); //! code.setLogger(&logger); // Attach the `logger` to `code` holder. //! //! // ... code as usual, everything emitted will be logged to `stdout` ... @@ -1369,7 +1373,8 @@ namespace asmjit { //! StringLogger logger; // Logger should always survive CodeHolder. //! //! CodeHolder code; // Holds code and relocation information. -//! code.init(rt.environment()); // Initialize to the same arch as JIT runtime. +//! code.init(rt.environment(), // Initialize code to match the JIT environment. +//! rt.cpuFeatures()); //! code.setLogger(&logger); // Attach the `logger` to `code` holder. //! //! // ... code as usual, logging will be concatenated to logger string ... @@ -1560,7 +1565,7 @@ namespace asmjit { //! MyErrorHandler myErrorHandler; //! CodeHolder code; //! -//! code.init(rt.environment()); +//! code.init(rt.environment(), rt.cpuFeatures()); //! code.setErrorHandler(&myErrorHandler); //! //! x86::Assembler a(&code); diff --git a/src/asmjit/core/codeholder.cpp b/src/asmjit/core/codeholder.cpp index cf763cf..3f7f5f5 100644 --- a/src/asmjit/core/codeholder.cpp +++ b/src/asmjit/core/codeholder.cpp @@ -74,6 +74,7 @@ static void CodeHolder_resetInternal(CodeHolder* self, ResetPolicy resetPolicy) // Reset everything into its construction state. self->_environment.reset(); + self->_cpuFeatures.reset(); self->_baseAddress = Globals::kNoBaseAddress; self->_logger = nullptr; self->_errorHandler = nullptr; @@ -118,6 +119,7 @@ static void CodeHolder_onSettingsUpdated(CodeHolder* self) noexcept { CodeHolder::CodeHolder(const Support::Temporary* temporary) noexcept : _environment(), + _cpuFeatures{}, _baseAddress(Globals::kNoBaseAddress), _logger(nullptr), _errorHandler(nullptr), @@ -143,6 +145,10 @@ inline void CodeHolder_setSectionDefaultName( } Error CodeHolder::init(const Environment& environment, uint64_t baseAddress) noexcept { + return init(environment, CpuFeatures{}, baseAddress); +} + +Error CodeHolder::init(const Environment& environment, const CpuFeatures& cpuFeatures, uint64_t baseAddress) noexcept { // Cannot reinitialize if it's locked or there is one or more emitter attached. if (isInitialized()) return DebugUtils::errored(kErrorAlreadyInitialized); @@ -172,6 +178,7 @@ Error CodeHolder::init(const Environment& environment, uint64_t baseAddress) noe } else { _environment = environment; + _cpuFeatures = cpuFeatures; _baseAddress = baseAddress; return kErrorOk; } diff --git a/src/asmjit/core/codeholder.h b/src/asmjit/core/codeholder.h index 6ed2ddf..d663d3e 100644 --- a/src/asmjit/core/codeholder.h +++ b/src/asmjit/core/codeholder.h @@ -640,6 +640,8 @@ public: //! Environment information. Environment _environment; + //! CPU features of the target architecture. + CpuFeatures _cpuFeatures; //! Base address or \ref Globals::kNoBaseAddress. uint64_t _baseAddress; @@ -698,6 +700,8 @@ public: //! Initializes CodeHolder to hold code described by the given `environment` and `baseAddress`. ASMJIT_API Error init(const Environment& environment, uint64_t baseAddress = Globals::kNoBaseAddress) noexcept; + //! Initializes CodeHolder to hold code described by the given `environment`, `cpuFeatures`, and `baseAddress`. + ASMJIT_API Error init(const Environment& environment, const CpuFeatures& cpuFeatures, uint64_t baseAddress = Globals::kNoBaseAddress) noexcept; //! Detaches all code-generators attached and resets the `CodeHolder`. ASMJIT_API void reset(ResetPolicy resetPolicy = ResetPolicy::kSoft) noexcept; @@ -736,6 +740,9 @@ public: //! Returns the target sub-architecture. inline SubArch subArch() const noexcept { return environment().subArch(); } + //! Returns the minimum CPU features of the target architecture. + inline const CpuFeatures& cpuFeatures() const noexcept { return _cpuFeatures; } + //! Tests whether a static base-address is set. inline bool hasBaseAddress() const noexcept { return _baseAddress != Globals::kNoBaseAddress; } //! Returns a static base-address or \ref Globals::kNoBaseAddress, if not set. diff --git a/src/asmjit/core/errorhandler.h b/src/asmjit/core/errorhandler.h index 5151d43..3b0096f 100644 --- a/src/asmjit/core/errorhandler.h +++ b/src/asmjit/core/errorhandler.h @@ -61,7 +61,7 @@ class BaseEmitter; //! SimpleErrorHandler eh; //! //! CodeHolder code; -//! code.init(rt.environment()); +//! code.init(rt.environment(), rt.cpuFeatures()); //! code.setErrorHandler(&eh); //! //! // Try to emit instruction that doesn't exist. @@ -117,7 +117,7 @@ class BaseEmitter; //! ThrowableErrorHandler eh; //! //! CodeHolder code; -//! code.init(rt.environment()); +//! code.init(rt.environment(), rt.cpuFeatures()); //! code.setErrorHandler(&eh); //! //! x86::Assembler a(&code); @@ -166,7 +166,7 @@ class BaseEmitter; //! LongJmpErrorHandler eh; //! //! CodeHolder code; -//! code.init(rt.rt.environment()); +//! code.init(rt.environment(), rt.cpuFeatures()); //! code.setErrorHandler(&eh); //! //! x86::Assembler a(&code); diff --git a/src/asmjit/core/jitruntime.cpp b/src/asmjit/core/jitruntime.cpp index 491c204..be1c2f4 100644 --- a/src/asmjit/core/jitruntime.cpp +++ b/src/asmjit/core/jitruntime.cpp @@ -15,6 +15,7 @@ JitRuntime::JitRuntime(const JitAllocator::CreateParams* params) noexcept : _allocator(params) { _environment = Environment::host(); _environment.setObjectFormat(ObjectFormat::kJIT); + _cpuFeatures = CpuInfo::host().features(); } JitRuntime::~JitRuntime() noexcept {} diff --git a/src/asmjit/core/target.cpp b/src/asmjit/core/target.cpp index fef025d..cbc6ab5 100644 --- a/src/asmjit/core/target.cpp +++ b/src/asmjit/core/target.cpp @@ -8,7 +8,9 @@ ASMJIT_BEGIN_NAMESPACE -Target::Target() noexcept : _environment() {} +Target::Target() noexcept + : _environment{}, + _cpuFeatures{} {} Target::~Target() noexcept {} ASMJIT_END_NAMESPACE diff --git a/src/asmjit/core/target.h b/src/asmjit/core/target.h index 23b0c62..322a338 100644 --- a/src/asmjit/core/target.h +++ b/src/asmjit/core/target.h @@ -7,6 +7,7 @@ #define ASMJIT_CORE_TARGET_H_INCLUDED #include "../core/archtraits.h" +#include "../core/cpuinfo.h" #include "../core/func.h" ASMJIT_BEGIN_NAMESPACE @@ -22,6 +23,8 @@ public: //! Target environment information. Environment _environment; + //! Target CPU features. + CpuFeatures _cpuFeatures; //! \name Construction & Destruction //! \{ @@ -43,6 +46,9 @@ public: //! Returns the target sub-architecture. inline SubArch subArch() const noexcept { return _environment.subArch(); } + //! Returns target CPU features. + inline const CpuFeatures& cpuFeatures() const noexcept { return _cpuFeatures; } + //! \} }; diff --git a/src/asmjit/x86/x86assembler.h b/src/asmjit/x86/x86assembler.h index dbffae6..dde27f4 100644 --- a/src/asmjit/x86/x86assembler.h +++ b/src/asmjit/x86/x86assembler.h @@ -38,7 +38,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! JitRuntime rt; // Create a runtime specialized for JIT. //! CodeHolder code; // Create a CodeHolder. //! -//! code.init(rt.environment()); // Initialize code to match the JIT environment. +//! code.init(rt.environment(), // Initialize code to match the JIT environment. +//! rt.cpuFeatures()); //! x86::Assembler a(&code); // Create and attach x86::Assembler to code. //! //! // Decide between 32-bit CDECL, WIN64, and SysV64 calling conventions: @@ -131,7 +132,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! JitRuntime rt; // Create a runtime specialized for JIT. //! CodeHolder code; // Create a CodeHolder. //! -//! code.init(rt.environment()); // Initialize code to match the JIT environment. +//! code.init(rt.environment(), // Initialize code to match the JIT environment. +//! rt.cpuFeatures()); //! x86::Assembler a(&code); // Create and attach x86::Assembler to code. //! //! // Enable strict validation. @@ -187,7 +189,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! JitRuntime rt; // Create a runtime specialized for JIT. //! CodeHolder code; // Create a CodeHolder. //! -//! code.init(rt.environment()); // Initialize code to match the JIT environment. +//! code.init(rt.environment(), // Initialize code to match the JIT environment. +//! rt.cpuFeatures()); //! x86::Assembler a(&code); // Create and attach x86::Assembler to code. //! //! // Let's get these registers from x86::Assembler. @@ -346,7 +349,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! JitRuntime rt; // Create JIT Runtime. //! CodeHolder code; // Create a CodeHolder. //! -//! code.init(rt.environment()); // Initialize code to match the JIT environment. +//! code.init(rt.environment(), // Initialize code to match the JIT environment. +//! rt.cpuFeatures()); //! x86::Assembler a(&code); // Create and attach x86::Assembler to code. //! //! // Decide which registers will be mapped to function arguments. Try changing @@ -453,7 +457,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! JitRuntime rt; // Create a runtime specialized for JIT. //! CodeHolder code; // Create a CodeHolder. //! -//! code.init(rt.environment()); // Initialize code to match the JIT environment. +//! code.init(rt.environment(), // Initialize code to match the JIT environment. +//! rt.cpuFeatures()); //! x86::Assembler a(&code); // Create and attach x86::Assembler to code. //! //! // Let's get these registers from x86::Assembler. diff --git a/src/asmjit/x86/x86builder.h b/src/asmjit/x86/x86builder.h index 5671c9d..4c56cba 100644 --- a/src/asmjit/x86/x86builder.h +++ b/src/asmjit/x86/x86builder.h @@ -46,7 +46,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! JitRuntime rt; // Create JIT Runtime. //! CodeHolder code; // Create a CodeHolder. //! -//! code.init(rt.environment()); // Initialize code to match the JIT environment. +//! code.init(rt.environment(), // Initialize code to match the JIT environment. +//! rt.cpuFeatures()); //! x86::Builder cb(&code); // Create and attach x86::Builder to `code`. //! //! // Decide which registers will be mapped to function arguments. Try changing registers diff --git a/src/asmjit/x86/x86compiler.h b/src/asmjit/x86/x86compiler.h index d89aea0..8bb9a43 100644 --- a/src/asmjit/x86/x86compiler.h +++ b/src/asmjit/x86/x86compiler.h @@ -38,7 +38,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! JitRuntime rt; // Runtime specialized for JIT code execution. //! CodeHolder code; // Holds code and relocation information. //! -//! code.init(rt.environment()); // Initialize code to match the JIT environment. +//! code.init(rt.environment(), // Initialize code to match the JIT environment. +//! rt.cpuFeatures()); //! x86::Compiler cc(&code); // Create and attach x86::Compiler to code. //! //! cc.addFunc(FuncSignatureT());// Begin a function of `int fn(void)` signature. @@ -82,7 +83,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! JitRuntime rt; // Runtime specialized for JIT code execution. //! CodeHolder code; // Holds code and relocation information. //! -//! code.init(rt.environment()); // Initialize code to match the JIT environment. +//! code.init(rt.environment(), // Initialize code to match the JIT environment. +//! rt.cpuFeatures()); //! x86::Compiler cc(&code); // Create and attach x86::Compiler to code. //! //! FuncNode* funcNode = cc.addFunc( // Begin the function of the following signature: @@ -164,7 +166,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! JitRuntime rt; // Runtime specialized for JIT code execution. //! CodeHolder code; // Holds code and relocation information. //! -//! code.init(rt.environment()); // Initialize code to match the JIT environment. +//! code.init(rt.environment(), // Initialize code to match the JIT environment. +//! rt.cpuFeatures()); //! x86::Compiler cc(&code); // Create and attach x86::Compiler to code. //! //! FuncNode* funcNode = cc.addFunc(FuncSignatureT()); @@ -222,7 +225,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! JitRuntime rt; // Runtime specialized for JIT code execution. //! CodeHolder code; // Holds code and relocation information. //! -//! code.init(rt.environment()); // Initialize code to match the JIT environment. +//! code.init(rt.environment(), // Initialize code to match the JIT environment. +//! rt.cpuFeatures()); //! x86::Compiler cc(&code); // Create and attach x86::Compiler to code. //! //! FuncNode* funcNode = cc.addFunc( // Begin of the Fibonacci function, addFunc() @@ -290,7 +294,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! JitRuntime rt; // Runtime specialized for JIT code execution. //! CodeHolder code; // Holds code and relocation information. //! -//! code.init(rt.environment()); // Initialize code to match the JIT environment. +//! code.init(rt.environment(), // Initialize code to match the JIT environment. +//! rt.cpuFeatures()); //! x86::Compiler cc(&code); // Create and attach x86::Compiler to code. //! //! cc.addFunc(FuncSignatureT());// Create a function that returns int. diff --git a/src/asmjit/x86/x86rapass.cpp b/src/asmjit/x86/x86rapass.cpp index 02870d9..4d8f3aa 100644 --- a/src/asmjit/x86/x86rapass.cpp +++ b/src/asmjit/x86/x86rapass.cpp @@ -220,9 +220,11 @@ Error RACFGBuilder::onInst(InstNode* inst, InstControlFlow& cf, RAInstBuilder& i } } - // Do not use RegMem flag if changing Reg to Mem requires additional CPU feature that may not be enabled. + // Do not use RegMem flag if changing Reg to Mem requires a CPU feature that is not available. if (rwInfo.rmFeature() && Support::test(flags, RATiedFlags::kUseRM | RATiedFlags::kOutRM)) { - flags &= ~(RATiedFlags::kUseRM | RATiedFlags::kOutRM); + if (!cc()->code()->cpuFeatures().has(rwInfo.rmFeature())) { + flags &= ~(RATiedFlags::kUseRM | RATiedFlags::kOutRM); + } } RegGroup group = workReg->group(); diff --git a/test/asmjit_test_compiler.cpp b/test/asmjit_test_compiler.cpp index f2bc306..293b84e 100644 --- a/test/asmjit_test_compiler.cpp +++ b/test/asmjit_test_compiler.cpp @@ -91,7 +91,7 @@ int TestApp::run() { CodeHolder code; SimpleErrorHandler errorHandler; - code.init(runtime.environment()); + code.init(runtime.environment(), runtime.cpuFeatures()); code.setErrorHandler(&errorHandler); if (pass != 0) { diff --git a/test/asmjit_test_emitters.cpp b/test/asmjit_test_emitters.cpp index 63c14a6..74db996 100644 --- a/test/asmjit_test_emitters.cpp +++ b/test/asmjit_test_emitters.cpp @@ -90,7 +90,7 @@ static uint32_t testFunc(JitRuntime& rt, EmitterType emitterType) noexcept { #endif CodeHolder code; - code.init(rt.environment()); + code.init(rt.environment(), rt.cpuFeatures()); #ifndef ASMJIT_NO_LOGGING code.setLogger(&logger); diff --git a/test/asmjit_test_perf.h b/test/asmjit_test_perf.h index 2ab0038..fb65db5 100644 --- a/test/asmjit_test_perf.h +++ b/test/asmjit_test_perf.h @@ -10,7 +10,9 @@ #include "asmjitutils.h" #include "performancetimer.h" -class MyErrorHandler : public asmjit::ErrorHandler { +namespace asmjit_perf_utils { + +class TestErrorHandler : public asmjit::ErrorHandler { void handleError(asmjit::Error err, const char* message, asmjit::BaseEmitter* origin) { (void)err; (void)origin; @@ -19,10 +21,49 @@ class MyErrorHandler : public asmjit::ErrorHandler { } }; +#ifndef ASMJIT_NO_BUILDER +template +static uint32_t calculateInstructionCount(asmjit::CodeHolder& code, asmjit::Arch arch, const FuncT& func) noexcept { + BuilderT builder; + TestErrorHandler eh; + + asmjit::Environment env(arch); + code.init(env); + code.setErrorHandler(&eh); + code.attach(&builder); + func(builder); + + uint32_t count = 0; + asmjit::BaseNode* node = builder.firstNode(); + + while (node) { + count += uint32_t(node->isInst()); + node = node->next(); + } + + return count; +} +#endif + +static inline double mbps(double duration, uint64_t outputSize) noexcept { + if (duration == 0) + return 0.0; + + double bytesTotal = double(outputSize); + return (bytesTotal * 1000) / (duration * 1024 * 1024); +} + +static inline double mips(double duration, uint64_t instCount) noexcept { + if (duration == 0) + return 0.0; + + return double(instCount) * 1000.0 / (duration * 1e6); +} + template -static void bench(asmjit::CodeHolder& code, asmjit::Arch arch, uint32_t numIterations, const char* testName, const FuncT& func) noexcept { +static void bench(asmjit::CodeHolder& code, asmjit::Arch arch, uint32_t numIterations, const char* testName, uint32_t instCount, const FuncT& func) noexcept { EmitterT emitter; - MyErrorHandler eh; + TestErrorHandler eh; const char* archName = asmjitArchAsString(arch); const char* emitterName = @@ -53,9 +94,20 @@ static void bench(asmjit::CodeHolder& code, asmjit::Arch arch, uint32_t numItera } printf(" [%s] %-9s %-16s | CodeSize:%5llu [B] | Time:%8.4f [ms]", archName, emitterName, testName, (unsigned long long)codeSize, duration); - if (codeSize) + if (codeSize) { printf(" | Speed:%8.3f [MB/s]", mbps(duration, codeSize)); + } + else { + printf(" | Speed: N/A "); + } + + if (instCount) { + printf(", %8.3f [MI/s]", mips(duration, instCount)); + } + printf("\n"); } +} // {asmjit_perf_utils} + #endif // ASMJIT_TEST_PERF_H_INCLUDED diff --git a/test/asmjit_test_perf_a64.cpp b/test/asmjit_test_perf_a64.cpp index 4f4aebb..054959b 100644 --- a/test/asmjit_test_perf_a64.cpp +++ b/test/asmjit_test_perf_a64.cpp @@ -645,42 +645,50 @@ static void benchmarkA64Function(Arch arch, uint32_t numIterations, const char* CodeHolder code; printf("%s:\n", description); - bench(code, arch, numIterations, "[raw]", [&](a64::Assembler& cc) { + uint32_t instCount = 0; + +#ifndef ASMJIT_NO_BUILDER + instCount = asmjit_perf_utils::calculateInstructionCount(code, arch, [&](a64::Builder& cc) { + emitterFn(cc, false); + }); +#endif + + asmjit_perf_utils::bench(code, arch, numIterations, "[raw]", instCount, [&](a64::Assembler& cc) { emitterFn(cc, false); }); - bench(code, arch, numIterations, "[validated]", [&](a64::Assembler& cc) { + asmjit_perf_utils::bench(code, arch, numIterations, "[validated]", instCount, [&](a64::Assembler& cc) { cc.addDiagnosticOptions(DiagnosticOptions::kValidateAssembler); emitterFn(cc, false); }); - bench(code, arch, numIterations, "[prolog/epilog]", [&](a64::Assembler& cc) { + asmjit_perf_utils::bench(code, arch, numIterations, "[prolog/epilog]", instCount, [&](a64::Assembler& cc) { cc.addDiagnosticOptions(DiagnosticOptions::kValidateAssembler); emitterFn(cc, true); }); #ifndef ASMJIT_NO_BUILDER - bench(code, arch, numIterations, "[no-asm]", [&](a64::Builder& cc) { + asmjit_perf_utils::bench(code, arch, numIterations, "[no-asm]", instCount, [&](a64::Builder& cc) { emitterFn(cc, false); }); - bench(code, arch, numIterations, "[finalized]", [&](a64::Builder& cc) { + asmjit_perf_utils::bench(code, arch, numIterations, "[finalized]", instCount, [&](a64::Builder& cc) { emitterFn(cc, false); cc.finalize(); }); - bench(code, arch, numIterations, "[prolog/epilog]", [&](a64::Builder& cc) { + asmjit_perf_utils::bench(code, arch, numIterations, "[prolog/epilog]", instCount, [&](a64::Builder& cc) { emitterFn(cc, true); cc.finalize(); }); #endif #ifndef ASMJIT_NO_COMPILER - bench(code, arch, numIterations, "[no-asm]", [&](a64::Compiler& cc) { + asmjit_perf_utils::bench(code, arch, numIterations, "[no-asm]", instCount, [&](a64::Compiler& cc) { emitterFn(cc, true); }); - bench(code, arch, numIterations, "[finalized]", [&](a64::Compiler& cc) { + asmjit_perf_utils::bench(code, arch, numIterations, "[finalized]", instCount, [&](a64::Compiler& cc) { emitterFn(cc, true); cc.finalize(); }); diff --git a/test/asmjit_test_perf_x86.cpp b/test/asmjit_test_perf_x86.cpp index e2720b7..515de80 100644 --- a/test/asmjit_test_perf_x86.cpp +++ b/test/asmjit_test_perf_x86.cpp @@ -4912,42 +4912,49 @@ static void benchmarkX86Function(Arch arch, uint32_t numIterations, const char* CodeHolder code; printf("%s:\n", description); - bench(code, arch, numIterations, "[raw]", [&](x86::Assembler& cc) { + uint32_t instCount = 0; + +#ifndef ASMJIT_NO_BUILDER + instCount = asmjit_perf_utils::calculateInstructionCount(code, arch, [&](x86::Builder& cc) { + emitterFn(cc, false); + }); +#endif + + asmjit_perf_utils::bench(code, arch, numIterations, "[raw]", instCount, [&](x86::Assembler& cc) { emitterFn(cc, false); }); - bench(code, arch, numIterations, "[validated]", [&](x86::Assembler& cc) { + asmjit_perf_utils::bench(code, arch, numIterations, "[validated]", instCount, [&](x86::Assembler& cc) { cc.addDiagnosticOptions(DiagnosticOptions::kValidateAssembler); emitterFn(cc, false); }); - bench(code, arch, numIterations, "[prolog/epilog]", [&](x86::Assembler& cc) { - cc.addDiagnosticOptions(DiagnosticOptions::kValidateAssembler); + asmjit_perf_utils::bench(code, arch, numIterations, "[prolog/epilog]", instCount, [&](x86::Assembler& cc) { emitterFn(cc, true); }); #ifndef ASMJIT_NO_BUILDER - bench(code, arch, numIterations, "[no-asm]", [&](x86::Builder& cc) { + asmjit_perf_utils::bench(code, arch, numIterations, "[no-asm]", instCount, [&](x86::Builder& cc) { emitterFn(cc, false); }); - bench(code, arch, numIterations, "[finalized]", [&](x86::Builder& cc) { + asmjit_perf_utils::bench(code, arch, numIterations, "[finalized]", instCount, [&](x86::Builder& cc) { emitterFn(cc, false); cc.finalize(); }); - bench(code, arch, numIterations, "[prolog/epilog]", [&](x86::Builder& cc) { + asmjit_perf_utils::bench(code, arch, numIterations, "[prolog/epilog]", instCount, [&](x86::Builder& cc) { emitterFn(cc, true); cc.finalize(); }); #endif #ifndef ASMJIT_NO_COMPILER - bench(code, arch, numIterations, "[no-asm]", [&](x86::Compiler& cc) { + asmjit_perf_utils::bench(code, arch, numIterations, "[no-asm]", instCount, [&](x86::Compiler& cc) { emitterFn(cc, true); }); - bench(code, arch, numIterations, "[finalized]", [&](x86::Compiler& cc) { + asmjit_perf_utils::bench(code, arch, numIterations, "[finalized]", instCount, [&](x86::Compiler& cc) { emitterFn(cc, true); cc.finalize(); }); diff --git a/test/performancetimer.h b/test/performancetimer.h index baa0479..c7a8ebe 100644 --- a/test/performancetimer.h +++ b/test/performancetimer.h @@ -30,12 +30,4 @@ public: } }; -static inline double mbps(double duration, uint64_t outputSize) noexcept { - if (duration == 0) - return 0.0; - - double bytesTotal = double(outputSize); - return (bytesTotal * 1000) / (duration * 1024 * 1024); -} - #endif // PERFORMANCETIMER_H_INCLUDED