From debcb0e0478b7fd5cc72957010e8a1b626f61b28 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Fri, 7 Jul 2023 16:43:41 -0700 Subject: [PATCH 1/2] Arm64: Optimize BFI in the case that Dst == srcDst ARM64 BFI doesn't allow you to encode two source registers here to match our SSA semantics. Also since we don't support RA constraints to ensure that these match, just do the optimal case in the backend. Leave a comment for future RA contraint excavators to make this more optimal --- .../Interface/Core/JIT/Arm64/ALUOps.cpp | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/External/FEXCore/Source/Interface/Core/JIT/Arm64/ALUOps.cpp b/External/FEXCore/Source/Interface/Core/JIT/Arm64/ALUOps.cpp index 40692c84f..71380ce54 100644 --- a/External/FEXCore/Source/Interface/Core/JIT/Arm64/ALUOps.cpp +++ b/External/FEXCore/Source/Interface/Core/JIT/Arm64/ALUOps.cpp @@ -1020,14 +1020,22 @@ DEF_OP(Bfi) { const auto SrcDst = GetReg(Op->Dest.ID()); const auto Src = GetReg(Op->Src.ID()); - mov(EmitSize, TMP1, SrcDst); - bfi(EmitSize, TMP1, Src, Op->lsb, Op->Width); - - if (OpSize == 8) { - mov(EmitSize, Dst, TMP1.R()); + if (Dst == SrcDst) { + // If Dst and SrcDst match then this turns in to a simple BFI instruction. + bfi(EmitSize, Dst, Src, Op->lsb, Op->Width); } else { - ubfx(EmitSize, Dst, TMP1, 0, OpSize * 8); + // Destination didn't match the dst source register. + // TODO: Inefficient until FEX can have RA constraints here. + mov(EmitSize, TMP1, SrcDst); + bfi(EmitSize, TMP1, Src, Op->lsb, Op->Width); + + if (OpSize == 8) { + mov(EmitSize, Dst, TMP1.R()); + } + else { + ubfx(EmitSize, Dst, TMP1, 0, OpSize * 8); + } } } From 052aa4317b14652dda5e61638b1a8743c260a29f Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Fri, 7 Jul 2023 16:45:47 -0700 Subject: [PATCH 2/2] OpcodeDispatcher: Optimize `GetPackedRFLAG` Only return the particular flags that are being requested in the moment since compacting them all when requested is fairly slow. x87 fcmov in particular was requesting all the flags when it only needs a couple. This reduces a `fcmovb` instruction count blowup from 103x to 38x. Still more room to go but this one stood out as being particularly bad. Old: ```asm 0x0000000265a002bc 10ffffe0 adr x0, #-0x4 (addr 0x265a002b8) 0x0000000265a002c0 f9005f80 str x0, [x28, #184] 0x0000000265a002c4 d2800014 mov x20, #0x0 0x0000000265a002c8 d2800035 mov x21, #0x1 0x0000000265a002cc d2800056 mov x22, #0x2 0x0000000265a002d0 394b0397 ldrb w23, [x28, #704] 0x0000000265a002d4 d3407ef7 ubfx x23, x23, #0, #32 0x0000000265a002d8 aa1702d6 orr x22, x22, x23 0x0000000265a002dc 394b0b97 ldrb w23, [x28, #706] 0x0000000265a002e0 d3407ef7 ubfx x23, x23, #0, #32 0x0000000265a002e4 531e76f7 lsl w23, w23, #2 0x0000000265a002e8 aa1702d6 orr x22, x22, x23 0x0000000265a002ec 394b1397 ldrb w23, [x28, #708] 0x0000000265a002f0 d3407ef7 ubfx x23, x23, #0, #32 0x0000000265a002f4 531c6ef7 lsl w23, w23, #4 0x0000000265a002f8 aa1702d6 orr x22, x22, x23 0x0000000265a002fc 394b1b97 ldrb w23, [x28, #710] 0x0000000265a00300 d3407ef7 ubfx x23, x23, #0, #32 0x0000000265a00304 531a66f7 lsl w23, w23, #6 0x0000000265a00308 aa1702d6 orr x22, x22, x23 0x0000000265a0030c 394b1f97 ldrb w23, [x28, #711] 0x0000000265a00310 d3407ef7 ubfx x23, x23, #0, #32 0x0000000265a00314 531962f7 lsl w23, w23, #7 0x0000000265a00318 aa1702d6 orr x22, x22, x23 0x0000000265a0031c 394b2397 ldrb w23, [x28, #712] 0x0000000265a00320 d3407ef7 ubfx x23, x23, #0, #32 0x0000000265a00324 53185ef7 lsl w23, w23, #8 0x0000000265a00328 aa1702d6 orr x22, x22, x23 0x0000000265a0032c 394b2797 ldrb w23, [x28, #713] 0x0000000265a00330 d3407ef7 ubfx x23, x23, #0, #32 0x0000000265a00334 53175af7 lsl w23, w23, #9 0x0000000265a00338 aa1702d6 orr x22, x22, x23 0x0000000265a0033c 394b2b97 ldrb w23, [x28, #714] 0x0000000265a00340 d3407ef7 ubfx x23, x23, #0, #32 0x0000000265a00344 531656f7 lsl w23, w23, #10 0x0000000265a00348 aa1702d6 orr x22, x22, x23 0x0000000265a0034c 394b2f97 ldrb w23, [x28, #715] 0x0000000265a00350 d3407ef7 ubfx x23, x23, #0, #32 0x0000000265a00354 531552f7 lsl w23, w23, #11 0x0000000265a00358 aa1702d6 orr x22, x22, x23 0x0000000265a0035c 394b3397 ldrb w23, [x28, #716] 0x0000000265a00360 d3407ef7 ubfx x23, x23, #0, #32 0x0000000265a00364 53144ef7 lsl w23, w23, #12 0x0000000265a00368 aa1702d6 orr x22, x22, x23 0x0000000265a0036c 394b3b97 ldrb w23, [x28, #718] 0x0000000265a00370 d3407ef7 ubfx x23, x23, #0, #32 0x0000000265a00374 531246f7 lsl w23, w23, #14 0x0000000265a00378 aa1702d6 orr x22, x22, x23 0x0000000265a0037c 394b4397 ldrb w23, [x28, #720] 0x0000000265a00380 d3407ef7 ubfx x23, x23, #0, #32 0x0000000265a00384 53103ef7 lsl w23, w23, #16 0x0000000265a00388 aa1702d6 orr x22, x22, x23 0x0000000265a0038c 394b4797 ldrb w23, [x28, #721] 0x0000000265a00390 d3407ef7 ubfx x23, x23, #0, #32 0x0000000265a00394 530f3af7 lsl w23, w23, #17 0x0000000265a00398 aa1702d6 orr x22, x22, x23 0x0000000265a0039c 394b4b97 ldrb w23, [x28, #722] 0x0000000265a003a0 d3407ef7 ubfx x23, x23, #0, #32 0x0000000265a003a4 530e36f7 lsl w23, w23, #18 0x0000000265a003a8 aa1702d6 orr x22, x22, x23 0x0000000265a003ac 394b4f97 ldrb w23, [x28, #723] 0x0000000265a003b0 d3407ef7 ubfx x23, x23, #0, #32 0x0000000265a003b4 530d32f7 lsl w23, w23, #19 0x0000000265a003b8 aa1702d6 orr x22, x22, x23 0x0000000265a003bc 394b5397 ldrb w23, [x28, #724] 0x0000000265a003c0 d3407ef7 ubfx x23, x23, #0, #32 0x0000000265a003c4 530c2ef7 lsl w23, w23, #20 0x0000000265a003c8 aa1702d6 orr x22, x22, x23 0x0000000265a003cc 394b5797 ldrb w23, [x28, #725] 0x0000000265a003d0 d3407ef7 ubfx x23, x23, #0, #32 0x0000000265a003d4 530b2af7 lsl w23, w23, #21 0x0000000265a003d8 aa1702d6 orr x22, x22, x23 0x0000000265a003dc 924002d6 and x22, x22, #0x1 0x0000000265a003e0 93400294 sbfx x20, x20, #0, #1 0x0000000265a003e4 934002b5 sbfx x21, x21, #0, #1 0x0000000265a003e8 f10002df cmp x22, #0x0 (0) 0x0000000265a003ec 9a950294 csel x20, x20, x21, eq 0x0000000265a003f0 4e080e84 dup v4.2d, x20 0x0000000265a003f4 394baf94 ldrb w20, [x28, #747] 0x0000000265a003f8 91000695 add x21, x20, #0x1 (1) 0x0000000265a003fc 92400ab5 and x21, x21, #0x7 0x0000000265a00400 d2800200 mov x0, #0x10 0x0000000265a00404 9b007e80 mul x0, x20, x0 0x0000000265a00408 8b000380 add x0, x28, x0 0x0000000265a0040c 3dc0bc05 ldr q5, [x0, #752] 0x0000000265a00410 d2800200 mov x0, #0x10 0x0000000265a00414 9b007ea0 mul x0, x21, x0 0x0000000265a00418 8b000380 add x0, x28, x0 0x0000000265a0041c 3dc0bc06 ldr q6, [x0, #752] 0x0000000265a00420 4ea41c80 mov v0.16b, v4.16b 0x0000000265a00424 6e651cc0 bsl v0.16b, v6.16b, v5.16b 0x0000000265a00428 4ea01c04 mov v4.16b, v0.16b 0x0000000265a0042c d2800200 mov x0, #0x10 0x0000000265a00430 9b007e80 mul x0, x20, x0 0x0000000265a00434 8b000380 add x0, x28, x0 0x0000000265a00438 3d80bc04 str q4, [x0, #752] 0x0000000265a0043c 58000040 ldr x0, pc+8 (addr 0x265a00444) 0x0000000265a00440 d63f0000 blr x0 ``` New: ```asm 0x0000000265a002bc 10ffffe0 adr x0, #-0x4 (addr 0x265a002b8) 0x0000000265a002c0 f9005f80 str x0, [x28, #184] 0x0000000265a002c4 d2800014 mov x20, #0x0 0x0000000265a002c8 d2800035 mov x21, #0x1 0x0000000265a002cc d2800056 mov x22, #0x2 0x0000000265a002d0 394b0397 ldrb w23, [x28, #704] 0x0000000265a002d4 330002f6 bfxil w22, w23, #0, #1 0x0000000265a002d8 924002d6 and x22, x22, #0x1 0x0000000265a002dc 93400294 sbfx x20, x20, #0, #1 0x0000000265a002e0 934002b5 sbfx x21, x21, #0, #1 0x0000000265a002e4 f10002df cmp x22, #0x0 (0) 0x0000000265a002e8 9a950294 csel x20, x20, x21, eq 0x0000000265a002ec 4e080e84 dup v4.2d, x20 0x0000000265a002f0 394baf94 ldrb w20, [x28, #747] 0x0000000265a002f4 91000695 add x21, x20, #0x1 (1) 0x0000000265a002f8 92400ab5 and x21, x21, #0x7 0x0000000265a002fc d2800200 mov x0, #0x10 0x0000000265a00300 9b007e80 mul x0, x20, x0 0x0000000265a00304 8b000380 add x0, x28, x0 0x0000000265a00308 3dc0bc05 ldr q5, [x0, #752] 0x0000000265a0030c d2800200 mov x0, #0x10 0x0000000265a00310 9b007ea0 mul x0, x21, x0 0x0000000265a00314 8b000380 add x0, x28, x0 0x0000000265a00318 3dc0bc06 ldr q6, [x0, #752] 0x0000000265a0031c 4ea41c80 mov v0.16b, v4.16b 0x0000000265a00320 6e651cc0 bsl v0.16b, v6.16b, v5.16b 0x0000000265a00324 4ea01c04 mov v4.16b, v0.16b 0x0000000265a00328 d2800200 mov x0, #0x10 0x0000000265a0032c 9b007e80 mul x0, x20, x0 0x0000000265a00330 8b000380 add x0, x28, x0 0x0000000265a00334 3d80bc04 str q4, [x0, #752] 0x0000000265a00338 58000040 ldr x0, pc+8 (addr 0x265a00340) 0x0000000265a0033c d63f0000 blr x0 ``` --- .../Source/Interface/Core/OpcodeDispatcher.cpp | 4 ++-- .../Source/Interface/Core/OpcodeDispatcher.h | 2 +- .../Interface/Core/OpcodeDispatcher/Flags.cpp | 17 +++++++---------- .../Interface/Core/OpcodeDispatcher/X87.cpp | 2 +- 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index 1749aac7d..ccd603132 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -1554,7 +1554,7 @@ void OpDispatchBuilder::SAHFOp(OpcodeArgs) { } void OpDispatchBuilder::LAHFOp(OpcodeArgs) { // Load the lower 8 bits of the Rflags register - auto RFLAG = GetPackedRFLAG(true); + auto RFLAG = GetPackedRFLAG(0xFF); // Store the lower 8 bits of the rflags register in to AH StoreGPRRegister(X86State::REG_RAX, RFLAG, 1, 8); @@ -4269,7 +4269,7 @@ void OpDispatchBuilder::BSWAPOp(OpcodeArgs) { void OpDispatchBuilder::PUSHFOp(OpcodeArgs) { const uint8_t Size = GetSrcSize(Op); - OrderedNode *Src = GetPackedRFLAG(false); + OrderedNode *Src = GetPackedRFLAG(); if (Size != 8) { Src = _Bfe(Size * 8, 0, Src); } diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h index 7ff483103..d390578e6 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h @@ -827,7 +827,7 @@ public: void InvalidOp(OpcodeArgs); void SetPackedRFLAG(bool Lower8, OrderedNode *Src); - OrderedNode *GetPackedRFLAG(bool Lower8); + OrderedNode *GetPackedRFLAG(uint32_t FlagsMask = ~0U); void SetMultiblock(bool _Multiblock) { Multiblock = _Multiblock; } diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp index a61c9f904..0eddf0e59 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp @@ -59,22 +59,19 @@ void OpDispatchBuilder::SetPackedRFLAG(bool Lower8, OrderedNode *Src) { } } -OrderedNode *OpDispatchBuilder::GetPackedRFLAG(bool Lower8) { +OrderedNode *OpDispatchBuilder::GetPackedRFLAG(uint32_t FlagsMask) { // Calculate flags early. CalculateDeferredFlags(); OrderedNode *Original = _Constant(2); - size_t NumFlags = FlagOffsets.size(); - if (Lower8) { - NumFlags = 5; - } - - for (size_t i = 0; i < NumFlags; ++i) { + for (size_t i = 0; i < FlagOffsets.size(); ++i) { const auto FlagOffset = FlagOffsets[i]; + if (!((1U << FlagOffset) & FlagsMask)) { + continue; + } + OrderedNode *Flag = _LoadFlag(FlagOffset); - Flag = _Bfe(4, 32, 0, Flag); - Flag = _Lshl(Flag, _Constant(FlagOffset)); - Original = _Or(Original, Flag); + Original = _Bfi(4, 1, FlagOffset, Original, Flag); } return Original; } diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp index c9c89abf6..7356b6c96 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp @@ -1356,7 +1356,7 @@ void OpDispatchBuilder::X87FCMOV(OpcodeArgs) { auto MaskConst = _Constant(FLAGMask); - auto RFLAG = GetPackedRFLAG(false); + auto RFLAG = GetPackedRFLAG(FLAGMask); auto AndOp = _And(RFLAG, MaskConst); switch (Type) {