From f6b4c76d76235f09d21ce0ee156c90c60a53884a Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Mon, 2 Jun 2025 12:10:39 -0700 Subject: [PATCH] InstcountCI: Adds tests for instructions discovered by #4597 Apparently I completely missed that cpuid, xgetbv, syscall, l{u,}{div,rem} were failing to hit their optimized cases for inlining and avoiding 128-bit software divide. The divisions are a clear performance regression for 64-bit applications since that is the only real way to do a 64-bit division on x86, I added those specifically because it sped up games. CPUID depends heavily on the game, since some games use that as a serialization instruction fairly heavily. XGETBV is trivial since it matches behaviour of CPUID (and is basically an extension of it). Syscall inlining can save a decent amount of time, again heavily depends on game. Adds multi-inst tests for all of these situations so that once it gets fixed (Apparently broken once RCLSE got stripped out), we can see that they keep working. Obviously tests couldn't have existed in instcountCI before since we didn't support multi-instruction tests. --- Source/Tools/CodeSizeValidation/Main.cpp | 31 +- .../InstructionCountCI/FEXOpt/MultiInst.json | 339 ++++++++++++++++++ 2 files changed, 369 insertions(+), 1 deletion(-) diff --git a/Source/Tools/CodeSizeValidation/Main.cpp b/Source/Tools/CodeSizeValidation/Main.cpp index 04d6453f3..7f3a8d557 100644 --- a/Source/Tools/CodeSizeValidation/Main.cpp +++ b/Source/Tools/CodeSizeValidation/Main.cpp @@ -434,6 +434,35 @@ public: private: fextl::vector> Env; }; + +class SimpleSyscallHandler : public FEXCore::HLE::SyscallHandler, public FEXCore::Allocator::FEXAllocOperators { +public: + SimpleSyscallHandler() { + // Just claim to be linux 64-bit for simplicity. + OSABI = FEXCore::HLE::SyscallOSABI::OS_LINUX64; + } + uint64_t HandleSyscall(FEXCore::Core::CpuStateFrame* Frame, FEXCore::HLE::SyscallArguments* Args) override { + // Don't do anything + return 0; + } + + FEXCore::HLE::SyscallABI GetSyscallABI(uint64_t Syscall) override { + if (Syscall == 0) { + // Claim syscall 0 is simple for instcountci inline tests. + return FEXCore::HLE::SyscallABI { + .NumArgs = 0, + .HasReturn = true, + .HostSyscallNumber = 0, // Just map to host syscall zero, it isn't going to get called. + }; + } + return {0, false, -1}; + } + + // These are no-ops implementations of the SyscallHandler API + FEXCore::HLE::AOTIRCacheEntryLookupResult LookupAOTIRCacheEntry(FEXCore::Core::InternalThreadState* Thread, uint64_t GuestAddr) override { + return {0, 0}; + } +}; } // namespace int main(int argc, char** argv, char** const envp) { @@ -620,7 +649,7 @@ int main(int argc, char** argv, char** const envp) { } auto SignalDelegation = FEX::DummyHandlers::CreateSignalDelegator(); - auto SyscallHandler = FEX::DummyHandlers::CreateSyscallHandler(); + auto SyscallHandler = fextl::make_unique(); CTX->SetSignalDelegator(SignalDelegation.get()); CTX->SetSyscallHandler(SyscallHandler.get()); diff --git a/unittests/InstructionCountCI/FEXOpt/MultiInst.json b/unittests/InstructionCountCI/FEXOpt/MultiInst.json index 4696cad39..0aaf6c7e5 100644 --- a/unittests/InstructionCountCI/FEXOpt/MultiInst.json +++ b/unittests/InstructionCountCI/FEXOpt/MultiInst.json @@ -17,6 +17,345 @@ "These are instruction combinations that could be more optimal if FEX optimized for them" ], "Instructions": { + "cpuid constant": { + "x86InstructionCount": 2, + "ExpectedInstructionCount": 57, + "Comment": [ + "CPUID function call with constant function id" + ], + "x86Insts": [ + "mov rax, 0", + "cpuid" + ], + "ExpectedArm64ASM": [ + "mov w4, #0x0", + "isb", + "mov x1, x4", + "mov x2, x7", + "sub sp, sp, #0xf0 (240)", + "mov x3, sp", + "st1 {v2.2d, v3.2d}, [x3], #32", + "st1 {v4.2d, v5.2d, v6.2d, v7.2d}, [x3], #64", + "st1 {v8.2d, v9.2d, v10.2d, v11.2d}, [x3], #64", + "st1 {v12.2d, v13.2d, v14.2d, v15.2d}, [x3], #64", + "stp x18, x30, [x3], #16", + "mrs x3, nzcv", + "str w3, [x28, #1000]", + "stp x4, x7, [x28, #288]", + "stp x5, x6, [x28, #304]", + "stp x8, x9, [x28, #320]", + "stp x10, x11, [x28, #336]", + "stp x12, x13, [x28, #352]", + "stp x14, x15, [x28, #368]", + "stp x16, x17, [x28, #384]", + "stp x19, x29, [x28, #400]", + "stp w26, w27, [x28, #16]", + "add x3, x28, #0x1a0 (416)", + "st1 {v16.2d, v17.2d, v18.2d, v19.2d}, [x3], #64", + "st1 {v20.2d, v21.2d, v22.2d, v23.2d}, [x3], #64", + "st1 {v24.2d, v25.2d, v26.2d, v27.2d}, [x3], #64", + "st1 {v28.2d, v29.2d, v30.2d, v31.2d}, [x3], #64", + "ldr x0, [x28, #1368]", + "ldr x3, [x28, #1376]", + "blr x3", + "ldr w4, [x28, #1000]", + "msr nzcv, x4", + "add x4, x28, #0x1a0 (416)", + "ld1 {v16.2d, v17.2d, v18.2d, v19.2d}, [x4], #64", + "ld1 {v20.2d, v21.2d, v22.2d, v23.2d}, [x4], #64", + "ld1 {v24.2d, v25.2d, v26.2d, v27.2d}, [x4], #64", + "ld1 {v28.2d, v29.2d, v30.2d, v31.2d}, [x4], #64", + "ldp x4, x7, [x28, #288]", + "ldp x5, x6, [x28, #304]", + "ldp x8, x9, [x28, #320]", + "ldp x10, x11, [x28, #336]", + "ldp x12, x13, [x28, #352]", + "ldp x14, x15, [x28, #368]", + "ldp x16, x17, [x28, #384]", + "ldp x19, x29, [x28, #400]", + "ldp w26, w27, [x28, #16]", + "ld1 {v2.2d, v3.2d}, [sp], #32", + "ld1 {v4.2d, v5.2d, v6.2d, v7.2d}, [sp], #64", + "ld1 {v8.2d, v9.2d, v10.2d, v11.2d}, [sp], #64", + "ld1 {v12.2d, v13.2d, v14.2d, v15.2d}, [sp], #64", + "ldp x18, x30, [sp], #16", + "mov w20, w0", + "mov w21, w1", + "lsr x6, x0, #32", + "lsr x5, x1, #32", + "mov x7, x21", + "mov x4, x20" + ] + }, + "xgetbv constant": { + "x86InstructionCount": 2, + "ExpectedInstructionCount": 51, + "Comment": [ + "XGETBV function call with constant function id" + ], + "x86Insts": [ + "mov rcx, 0", + "xgetbv" + ], + "ExpectedArm64ASM": [ + "mov w7, #0x0", + "sub sp, sp, #0xf0 (240)", + "mov x3, sp", + "st1 {v2.2d, v3.2d}, [x3], #32", + "st1 {v4.2d, v5.2d, v6.2d, v7.2d}, [x3], #64", + "st1 {v8.2d, v9.2d, v10.2d, v11.2d}, [x3], #64", + "st1 {v12.2d, v13.2d, v14.2d, v15.2d}, [x3], #64", + "stp x18, x30, [x3], #16", + "mrs x3, nzcv", + "str w3, [x28, #1000]", + "stp x4, x7, [x28, #288]", + "stp x5, x6, [x28, #304]", + "stp x8, x9, [x28, #320]", + "stp x10, x11, [x28, #336]", + "stp x12, x13, [x28, #352]", + "stp x14, x15, [x28, #368]", + "stp x16, x17, [x28, #384]", + "stp x19, x29, [x28, #400]", + "stp w26, w27, [x28, #16]", + "add x3, x28, #0x1a0 (416)", + "st1 {v16.2d, v17.2d, v18.2d, v19.2d}, [x3], #64", + "st1 {v20.2d, v21.2d, v22.2d, v23.2d}, [x3], #64", + "st1 {v24.2d, v25.2d, v26.2d, v27.2d}, [x3], #64", + "st1 {v28.2d, v29.2d, v30.2d, v31.2d}, [x3], #64", + "mov w1, w7", + "ldr x0, [x28, #1368]", + "ldr x2, [x28, #1384]", + "blr x2", + "ldr w4, [x28, #1000]", + "msr nzcv, x4", + "add x4, x28, #0x1a0 (416)", + "ld1 {v16.2d, v17.2d, v18.2d, v19.2d}, [x4], #64", + "ld1 {v20.2d, v21.2d, v22.2d, v23.2d}, [x4], #64", + "ld1 {v24.2d, v25.2d, v26.2d, v27.2d}, [x4], #64", + "ld1 {v28.2d, v29.2d, v30.2d, v31.2d}, [x4], #64", + "ldp x4, x7, [x28, #288]", + "ldp x5, x6, [x28, #304]", + "ldp x8, x9, [x28, #320]", + "ldp x10, x11, [x28, #336]", + "ldp x12, x13, [x28, #352]", + "ldp x14, x15, [x28, #368]", + "ldp x16, x17, [x28, #384]", + "ldp x19, x29, [x28, #400]", + "ldp w26, w27, [x28, #16]", + "ld1 {v2.2d, v3.2d}, [sp], #32", + "ld1 {v4.2d, v5.2d, v6.2d, v7.2d}, [sp], #64", + "ld1 {v8.2d, v9.2d, v10.2d, v11.2d}, [sp], #64", + "ld1 {v12.2d, v13.2d, v14.2d, v15.2d}, [sp], #64", + "ldp x18, x30, [sp], #16", + "mov w4, w0", + "lsr x5, x0, #32" + ] + }, + "signed div narrow": { + "x86InstructionCount": 2, + "ExpectedInstructionCount": 31, + "Comment": [ + "div narrowing with known smaller sources", + "dividend in rdx:rax" + ], + "x86Insts": [ + "cdq", + "idiv rcx" + ], + "ExpectedArm64ASM": [ + "mov w20, w4", + "sbfx x20, x20, #31, #1", + "mov w5, w20", + "asr x0, x4, #63", + "eor x0, x0, x5", + "cbz x0, #+0x28", + "mov x0, x5", + "mov x1, x4", + "mov x2, x7", + "ldr x3, [x28, #3400]", + "str x30, [sp, #-16]!", + "blr x3", + "ldr x30, [sp], #16", + "mov x20, x0", + "b #+0x8", + "sdiv x20, x4, x7", + "asr x0, x4, #63", + "eor x0, x0, x5", + "cbz x0, #+0x28", + "mov x0, x5", + "mov x1, x4", + "mov x2, x7", + "ldr x3, [x28, #3416]", + "str x30, [sp, #-16]!", + "blr x3", + "ldr x30, [sp], #16", + "mov x5, x0", + "b #+0xc", + "sdiv x0, x4, x7", + "msub x5, x0, x7, x4", + "mov x4, x20" + ] + }, + "unsigned div narrow": { + "x86InstructionCount": 2, + "ExpectedInstructionCount": 25, + "Comment": [ + "div narrowing with known smaller sources", + "dividend in rdx:rax" + ], + "x86Insts": [ + "mov rdx, 0", + "div rcx" + ], + "ExpectedArm64ASM": [ + "mov w5, #0x0", + "cbz x5, #+0x28", + "mov x0, x5", + "mov x1, x4", + "mov x2, x7", + "ldr x3, [x28, #3392]", + "str x30, [sp, #-16]!", + "blr x3", + "ldr x30, [sp], #16", + "mov x20, x0", + "b #+0x8", + "udiv x20, x4, x7", + "cbz x5, #+0x28", + "mov x0, x5", + "mov x1, x4", + "mov x2, x7", + "ldr x3, [x28, #3408]", + "str x30, [sp, #-16]!", + "blr x3", + "ldr x30, [sp], #16", + "mov x5, x0", + "b #+0xc", + "udiv x0, x4, x7", + "msub x5, x0, x7, x4", + "mov x4, x20" + ] + }, + "inline syscall": { + "x86InstructionCount": 2, + "ExpectedInstructionCount": 106, + "Comment": [ + "Simple inline syscall check", + "When the syscall number is a known constant that matches host semantics then it can be inlined", + "InstcountCI is setup that it claims to be a 64-bit Linux syscall handler" + ], + "x86Insts": [ + "mov rax, 0", + "syscall" + ], + "ExpectedArm64ASM": [ + "mov w4, #0x0", + "mov w20, #0x5", + "movk w20, #0x1, lsl #16", + "str x20, [x28, #24]", + "cset w20, lo", + "eor x21, x27, x26", + "ubfx w21, w21, #4, #1", + "orr x20, x20, x21, lsl #4", + "ldrb w21, [x28, #984]", + "orr x20, x20, x21, lsl #8", + "ldrb w21, [x28, #985]", + "orr x20, x20, x21, lsl #9", + "ldrsb x21, [x28, #986]", + "lsr x21, x21, #63", + "orr x20, x20, x21, lsl #10", + "cset w21, vs", + "orr x20, x20, x21, lsl #11", + "ldrb w21, [x28, #988]", + "orr x20, x20, x21, lsl #12", + "ldrb w21, [x28, #990]", + "orr x20, x20, x21, lsl #14", + "ldrb w21, [x28, #992]", + "orr x20, x20, x21, lsl #16", + "ldrb w21, [x28, #993]", + "orr x20, x20, x21, lsl #17", + "ldrb w21, [x28, #994]", + "orr x20, x20, x21, lsl #18", + "ldrb w21, [x28, #995]", + "orr x20, x20, x21, lsl #19", + "ldrb w21, [x28, #996]", + "orr x20, x20, x21, lsl #20", + "ldrb w21, [x28, #997]", + "orr x20, x20, x21, lsl #21", + "eor w0, w26, w26, lsr #4", + "eor w0, w0, w0, lsr #2", + "eor w21, w0, w0, lsr #1", + "orr x21, x21, #0xfffffffffffffffe", + "orn x20, x20, x21, ror #62", + "mrs x21, nzcv", + "and x21, x21, #0xc0000000", + "orr x20, x20, x21, lsr #24", + "orr x15, x20, #0x2", + "mov w7, #0x7", + "movk w7, #0x1, lsl #16", + "sub sp, sp, #0xf0 (240)", + "mov x0, sp", + "st1 {v2.2d, v3.2d}, [x0], #32", + "st1 {v4.2d, v5.2d, v6.2d, v7.2d}, [x0], #64", + "st1 {v8.2d, v9.2d, v10.2d, v11.2d}, [x0], #64", + "st1 {v12.2d, v13.2d, v14.2d, v15.2d}, [x0], #64", + "stp x18, x30, [x0], #16", + "mrs x0, nzcv", + "str w0, [x28, #1000]", + "stp x4, x7, [x28, #288]", + "stp x5, x6, [x28, #304]", + "stp x8, x9, [x28, #320]", + "stp x10, x11, [x28, #336]", + "stp x12, x13, [x28, #352]", + "stp x14, x15, [x28, #368]", + "stp x16, x17, [x28, #384]", + "stp x19, x29, [x28, #400]", + "stp w26, w27, [x28, #16]", + "add x0, x28, #0x1a0 (416)", + "st1 {v16.2d, v17.2d, v18.2d, v19.2d}, [x0], #64", + "st1 {v20.2d, v21.2d, v22.2d, v23.2d}, [x0], #64", + "st1 {v24.2d, v25.2d, v26.2d, v27.2d}, [x0], #64", + "st1 {v28.2d, v29.2d, v30.2d, v31.2d}, [x0], #64", + "mov w0, #0xffff", + "str x0, [x28, #1312]", + "sub sp, sp, #0x40 (64)", + "str x4, [sp]", + "str x11, [sp, #8]", + "str x10, [sp, #16]", + "str x5, [sp, #24]", + "str x14, [sp, #32]", + "str x12, [sp, #40]", + "str x13, [sp, #48]", + "ldr x0, [x28, #1392]", + "ldr x3, [x28, #1400]", + "mov x1, x28", + "mov x2, sp", + "blr x3", + "add sp, sp, #0x40 (64)", + "ldr w1, [x28, #1000]", + "msr nzcv, x1", + "add x1, x28, #0x1a0 (416)", + "ld1 {v16.2d, v17.2d, v18.2d, v19.2d}, [x1], #64", + "ld1 {v20.2d, v21.2d, v22.2d, v23.2d}, [x1], #64", + "ld1 {v24.2d, v25.2d, v26.2d, v27.2d}, [x1], #64", + "ld1 {v28.2d, v29.2d, v30.2d, v31.2d}, [x1], #64", + "ldp x4, x7, [x28, #288]", + "ldp x5, x6, [x28, #304]", + "ldp x8, x9, [x28, #320]", + "ldp x10, x11, [x28, #336]", + "ldp x12, x13, [x28, #352]", + "ldp x14, x15, [x28, #368]", + "ldp x16, x17, [x28, #384]", + "ldp x19, x29, [x28, #400]", + "ldp w26, w27, [x28, #16]", + "str xzr, [x28, #1312]", + "ld1 {v2.2d, v3.2d}, [sp], #32", + "ld1 {v4.2d, v5.2d, v6.2d, v7.2d}, [sp], #64", + "ld1 {v8.2d, v9.2d, v10.2d, v11.2d}, [sp], #64", + "ld1 {v12.2d, v13.2d, v14.2d, v15.2d}, [sp], #64", + "ldp x18, x30, [sp], #16", + "mov x4, x0" + ] + }, "push ax, bx": { "x86InstructionCount": 2, "ExpectedInstructionCount": 2,