From 0a6e875329eaf0c70340d6ece60275fc290a1372 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Tue, 9 Jan 2024 10:49:54 -0400 Subject: [PATCH 1/4] InstCountCI: add nontrivial gpr cmpxchg cases cmpxchg handles rax specially, so cmpxchg with dest=rax is a special case. test also the general case. Signed-off-by: Alyssa Rosenzweig --- .../InstructionCountCI/FlagM/Secondary.json | 104 +++++++++++++++--- 1 file changed, 90 insertions(+), 14 deletions(-) diff --git a/unittests/InstructionCountCI/FlagM/Secondary.json b/unittests/InstructionCountCI/FlagM/Secondary.json index 812370f15..5016c197e 100644 --- a/unittests/InstructionCountCI/FlagM/Secondary.json +++ b/unittests/InstructionCountCI/FlagM/Secondary.json @@ -1025,6 +1025,96 @@ "ccmn xzr, #0, #nzCV, eq" ] }, + "cmpxchg cl, bl": { + "ExpectedInstructionCount": 17, + "ExpectedArm64ASM": [ + "uxtb w20, w7", + "uxtb w21, w5", + "uxtb x22, w4", + "cmp x21, x22", + "csel x23, x22, x21, eq", + "cmp x21, x22", + "csel w20, w20, w21, eq", + "bfxil x4, x23, #0, #8", + "bfxil x5, x20, #0, #8", + "sub x26, x22, x23", + "eor w27, w22, w23", + "cmn wzr, w26, lsl #24", + "rmif x26, #7, #nzCv", + "eor w20, w22, w23", + "eor w21, w26, w22", + "and w20, w21, w20", + "rmif x20, #7, #nzcV" + ] + }, + "cmpxchg cx, bx": { + "ExpectedInstructionCount": 17, + "ExpectedArm64ASM": [ + "uxth w20, w7", + "uxth w21, w5", + "uxth x22, w4", + "cmp x21, x22", + "csel x23, x22, x21, eq", + "cmp x21, x22", + "csel w20, w20, w21, eq", + "bfxil x4, x23, #0, #16", + "bfxil x5, x20, #0, #16", + "sub x26, x22, x23", + "eor w27, w22, w23", + "cmn wzr, w26, lsl #16", + "rmif x26, #15, #nzCv", + "eor w20, w22, w23", + "eor w21, w26, w22", + "and w20, w21, w20", + "rmif x20, #15, #nzcV" + ] + }, + "cmpxchg ecx, ebx": { + "ExpectedInstructionCount": 13, + "ExpectedArm64ASM": [ + "mov w20, w7", + "mov w21, w5", + "mov w22, w4", + "cmp x21, x22", + "csel x23, x22, x21, eq", + "cmp x21, x22", + "csel x5, x20, x5, eq", + "cmp x23, x22", + "csel x4, x4, x21, eq", + "sub x26, x22, x23", + "eor w27, w22, w23", + "cmp w22, w23", + "cfinv" + ] + }, + "cmpxchg rcx, rbx": { + "ExpectedInstructionCount": 9, + "ExpectedArm64ASM": [ + "mov x20, x4", + "cmp x5, x20", + "csel x4, x20, x5, eq", + "cmp x5, x20", + "csel x5, x7, x5, eq", + "sub x26, x20, x4", + "eor x27, x20, x4", + "cmp x20, x4", + "cfinv" + ] + }, + "cmpxchg [rax], rbx": { + "ExpectedInstructionCount": 8, + "Comment": "0x0f 0xb1", + "ExpectedArm64ASM": [ + "mov x20, x4", + "mov x1, x20", + "casal x1, x7, [x20]", + "mov x4, x1", + "sub x26, x20, x4", + "eor x27, x20, x4", + "cmp x20, x4", + "cfinv" + ] + }, "cmpxchg al, bl": { "ExpectedInstructionCount": 17, "Comment": "0x0f 0xb0", @@ -1166,20 +1256,6 @@ "cfinv" ] }, - "cmpxchg [rax], rbx": { - "ExpectedInstructionCount": 8, - "Comment": "0x0f 0xb1", - "ExpectedArm64ASM": [ - "mov x20, x4", - "mov x1, x20", - "casal x1, x7, [x20]", - "mov x4, x1", - "sub x26, x20, x4", - "eor x27, x20, x4", - "cmp x20, x4", - "cfinv" - ] - }, "btr ax, bx": { "ExpectedInstructionCount": 7, "Comment": "0x0f 0xb3", From e8945dfb6dad2762ffddd97804b2ead5e665163f Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Fri, 12 Jan 2024 11:31:36 -0400 Subject: [PATCH 2/4] OpcodeDispatcher: optimize gpr cmpxchg NZCV stuff. Signed-off-by: Alyssa Rosenzweig --- .../Interface/Core/OpcodeDispatcher.cpp | 43 ++++++++----------- 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index 14cdacfc2..fe0e7966d 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -4288,40 +4288,35 @@ void OpDispatchBuilder::CMPXCHGOp(OpcodeArgs) { Src3Lower = Src3; } - // If our destination is a GPR then this behaves differently - // RAX = RAX == Op1 ? RAX : Op1 - // AKA if they match then don't touch RAX value - // Otherwise set it to the rm operand - OrderedNode *CASResult = _Select(FEXCore::IR::COND_EQ, - Src1Lower, Src3Lower, - Src3Lower, Src1Lower); + // Compare RAX with the destination, setting flags accordingly. + OrderedNode *Result = _Sub(IR::SizeToOpSize(GPRSize), Src3Lower, Src1Lower); + GenerateFlags_SUB(Op, Result, Src3Lower, Src1Lower); + CalculateDeferredFlags(); + + if (GPRSize == 8 && Size == 4) { + // This allows us to only hit the ZEXT case on failure + OrderedNode *RAXResult = _NZCVSelect(IR::i64Bit, CondClassType{COND_EQ}, + Src3, Src1Lower); + + // When the size is 4 we need to make sure not zext the GPR when the comparison fails + StoreGPRRegister(X86State::REG_RAX, RAXResult); + } + else { + StoreGPRRegister(X86State::REG_RAX, Src1Lower, Size); + } // Op1 = RAX == Op1 ? Op2 : Op1 // If they match then set the rm operand to the input // else don't set the rm operand - OrderedNode *DestResult = _Select(FEXCore::IR::COND_EQ, - Src1Lower, Src3Lower, - Src2, Src1); + OrderedNode *DestResult = _NZCVSelect(IR::i64Bit, CondClassType{COND_EQ}, + Src2, Src1); // Store in to GPR Dest - // Have to make sure this is after the result store in RAX for when Dest == RAX if (GPRSize == 8 && Size == 4) { - // This allows us to only hit the ZEXT case on failure - OrderedNode *RAXResult = _Select(FEXCore::IR::COND_EQ, - CASResult, Src3Lower, - Src3, Src1Lower); - - // When the size is 4 we need to make sure not zext the GPR when the comparison fails - StoreGPRRegister(X86State::REG_RAX, RAXResult); StoreResult_WithOpSize(GPRClass, Op, Op->Dest, DestResult, GPRSize, -1); - } - else { - StoreGPRRegister(X86State::REG_RAX, CASResult, Size); + } else { StoreResult(GPRClass, Op, DestResult, -1); } - - OrderedNode *Result = _Sub(IR::SizeToOpSize(GPRSize), Src3Lower, CASResult); - GenerateFlags_SUB(Op, Result, Src3Lower, CASResult); } else { HandledLock = Op->Flags & FEXCore::X86Tables::DecodeFlags::FLAG_LOCK; From 58127bd0e823a086f68340dc1a92954c4a6fbff1 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Fri, 12 Jan 2024 12:23:11 -0400 Subject: [PATCH 3/4] OpcodeDispatcher: optimize trivial cmpxchgs Signed-off-by: Alyssa Rosenzweig --- .../Interface/Core/OpcodeDispatcher.cpp | 31 ++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index fe0e7966d..b29472e51 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -4265,6 +4265,13 @@ void OpDispatchBuilder::CMPXCHGOp(OpcodeArgs) { // 0x80064000 if (Op->Dest.IsGPR()) { + // If the destination is also the accumulator, we get some algebraic + // simplifications. Not sure if this is actually hit but it's in + // InstCountCI. + bool Trivial = Op->Dest.Data.GPR.GPR == X86State::REG_RAX && + !Op->Dest.IsGPRDirect() && + !Op->Dest.Data.GPR.HighBits; + OrderedNode *Src1{}; OrderedNode *Src1Lower{}; @@ -4293,23 +4300,25 @@ void OpDispatchBuilder::CMPXCHGOp(OpcodeArgs) { GenerateFlags_SUB(Op, Result, Src3Lower, Src1Lower); CalculateDeferredFlags(); - if (GPRSize == 8 && Size == 4) { - // This allows us to only hit the ZEXT case on failure - OrderedNode *RAXResult = _NZCVSelect(IR::i64Bit, CondClassType{COND_EQ}, - Src3, Src1Lower); + if (!Trivial) { + if (GPRSize == 8 && Size == 4) { + // This allows us to only hit the ZEXT case on failure + OrderedNode *RAXResult = _NZCVSelect(IR::i64Bit, CondClassType{COND_EQ}, + Src3, Src1Lower); - // When the size is 4 we need to make sure not zext the GPR when the comparison fails - StoreGPRRegister(X86State::REG_RAX, RAXResult); - } - else { - StoreGPRRegister(X86State::REG_RAX, Src1Lower, Size); + // When the size is 4 we need to make sure not zext the GPR when the comparison fails + StoreGPRRegister(X86State::REG_RAX, RAXResult); + } + else { + StoreGPRRegister(X86State::REG_RAX, Src1Lower, Size); + } } // Op1 = RAX == Op1 ? Op2 : Op1 // If they match then set the rm operand to the input // else don't set the rm operand - OrderedNode *DestResult = _NZCVSelect(IR::i64Bit, CondClassType{COND_EQ}, - Src2, Src1); + OrderedNode *DestResult = + Trivial ? Src2 : _NZCVSelect(IR::i64Bit, CondClassType{COND_EQ}, Src2, Src1); // Store in to GPR Dest if (GPRSize == 8 && Size == 4) { From d9985eb87756abee99475f1da8fd2f864dbaeeb3 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Fri, 12 Jan 2024 11:48:15 -0400 Subject: [PATCH 4/4] InstCountCI: Update Signed-off-by: Alyssa Rosenzweig --- .../InstructionCountCI/FlagM/Secondary.json | 164 +++++++----------- unittests/InstructionCountCI/Secondary.json | 100 +++++------ 2 files changed, 104 insertions(+), 160 deletions(-) diff --git a/unittests/InstructionCountCI/FlagM/Secondary.json b/unittests/InstructionCountCI/FlagM/Secondary.json index 5016c197e..d0a30a9b1 100644 --- a/unittests/InstructionCountCI/FlagM/Secondary.json +++ b/unittests/InstructionCountCI/FlagM/Secondary.json @@ -1026,79 +1026,67 @@ ] }, "cmpxchg cl, bl": { - "ExpectedInstructionCount": 17, + "ExpectedInstructionCount": 14, "ExpectedArm64ASM": [ "uxtb w20, w7", "uxtb w21, w5", "uxtb x22, w4", - "cmp x21, x22", - "csel x23, x22, x21, eq", - "cmp x21, x22", - "csel w20, w20, w21, eq", - "bfxil x4, x23, #0, #8", - "bfxil x5, x20, #0, #8", - "sub x26, x22, x23", - "eor w27, w22, w23", + "sub x26, x22, x21", + "eor w27, w22, w21", "cmn wzr, w26, lsl #24", "rmif x26, #7, #nzCv", - "eor w20, w22, w23", - "eor w21, w26, w22", - "and w20, w21, w20", - "rmif x20, #7, #nzcV" + "eor w23, w22, w21", + "eor w22, w26, w22", + "and w22, w22, w23", + "rmif x22, #7, #nzcV", + "bfxil x4, x21, #0, #8", + "csel x20, x20, x21, eq", + "bfxil x5, x20, #0, #8" ] }, "cmpxchg cx, bx": { - "ExpectedInstructionCount": 17, + "ExpectedInstructionCount": 14, "ExpectedArm64ASM": [ "uxth w20, w7", "uxth w21, w5", "uxth x22, w4", - "cmp x21, x22", - "csel x23, x22, x21, eq", - "cmp x21, x22", - "csel w20, w20, w21, eq", - "bfxil x4, x23, #0, #16", - "bfxil x5, x20, #0, #16", - "sub x26, x22, x23", - "eor w27, w22, w23", + "sub x26, x22, x21", + "eor w27, w22, w21", "cmn wzr, w26, lsl #16", "rmif x26, #15, #nzCv", - "eor w20, w22, w23", - "eor w21, w26, w22", - "and w20, w21, w20", - "rmif x20, #15, #nzcV" + "eor w23, w22, w21", + "eor w22, w26, w22", + "and w22, w22, w23", + "rmif x22, #15, #nzcV", + "bfxil x4, x21, #0, #16", + "csel x20, x20, x21, eq", + "bfxil x5, x20, #0, #16" ] }, "cmpxchg ecx, ebx": { - "ExpectedInstructionCount": 13, + "ExpectedInstructionCount": 9, "ExpectedArm64ASM": [ "mov w20, w7", "mov w21, w5", "mov w22, w4", - "cmp x21, x22", - "csel x23, x22, x21, eq", - "cmp x21, x22", - "csel x5, x20, x5, eq", - "cmp x23, x22", + "sub x26, x22, x21", + "eor w27, w22, w21", + "cmp w22, w21", + "cfinv", "csel x4, x4, x21, eq", - "sub x26, x22, x23", - "eor w27, w22, w23", - "cmp w22, w23", - "cfinv" + "csel x5, x20, x5, eq" ] }, "cmpxchg rcx, rbx": { - "ExpectedInstructionCount": 9, + "ExpectedInstructionCount": 7, "ExpectedArm64ASM": [ - "mov x20, x4", - "cmp x5, x20", - "csel x4, x20, x5, eq", - "cmp x5, x20", - "csel x5, x7, x5, eq", - "sub x26, x20, x4", - "eor x27, x20, x4", - "cmp x20, x4", - "cfinv" + "mov x20, x5", + "sub x26, x4, x20", + "eor x27, x4, x20", + "cmp x4, x20", + "cfinv", + "mov x4, x20", + "csel x5, x7, x20, eq" ] }, "cmpxchg [rax], rbx": { @@ -1116,26 +1104,21 @@ ] }, "cmpxchg al, bl": { - "ExpectedInstructionCount": 17, + "ExpectedInstructionCount": 12, "Comment": "0x0f 0xb0", "ExpectedArm64ASM": [ "uxtb w20, w7", "uxtb w21, w4", "uxtb x22, w4", - "cmp x21, x22", - "csel x23, x22, x21, eq", - "cmp x21, x22", - "csel w20, w20, w21, eq", - "bfxil x4, x23, #0, #8", - "bfxil x4, x20, #0, #8", - "sub x26, x22, x23", - "eor w27, w22, w23", + "sub x26, x22, x21", + "eor w27, w22, w21", "cmn wzr, w26, lsl #24", "rmif x26, #7, #nzCv", - "eor w20, w22, w23", - "eor w21, w26, w22", - "and w20, w21, w20", - "rmif x20, #7, #nzcV" + "eor w21, w22, w21", + "eor w22, w26, w22", + "and w21, w22, w21", + "rmif x21, #7, #nzcV", + "bfxil x4, x20, #0, #8" ] }, "cmpxchg [rax], bl": { @@ -1159,26 +1142,21 @@ ] }, "cmpxchg ax, bx": { - "ExpectedInstructionCount": 17, + "ExpectedInstructionCount": 12, "Comment": "0x0f 0xb1", "ExpectedArm64ASM": [ "uxth w20, w7", "uxth w21, w4", "uxth x22, w4", - "cmp x21, x22", - "csel x23, x22, x21, eq", - "cmp x21, x22", - "csel w20, w20, w21, eq", - "bfxil x4, x23, #0, #16", - "bfxil x4, x20, #0, #16", - "sub x26, x22, x23", - "eor w27, w22, w23", + "sub x26, x22, x21", + "eor w27, w22, w21", "cmn wzr, w26, lsl #16", "rmif x26, #15, #nzCv", - "eor w20, w22, w23", - "eor w21, w26, w22", - "and w20, w21, w20", - "rmif x20, #15, #nzcV" + "eor w21, w22, w21", + "eor w22, w26, w22", + "and w21, w22, w21", + "rmif x21, #15, #nzcV", + "bfxil x4, x20, #0, #16" ] }, "cmpxchg [rax], bx": { @@ -1202,24 +1180,17 @@ ] }, "cmpxchg eax, ebx": { - "ExpectedInstructionCount": 15, + "ExpectedInstructionCount": 8, "Comment": "0x0f 0xb1", "ExpectedArm64ASM": [ "mov w20, w7", - "mov x21, x4", - "mov w22, w21", - "mov w23, w21", - "cmp x22, x23", - "csel x24, x23, x22, eq", - "cmp x22, x23", - "csel x20, x20, x21, eq", - "cmp x24, x23", - "csel x4, x21, x22, eq", - "mov x4, x20", - "sub x26, x23, x24", - "eor w27, w23, w24", - "cmp w23, w24", - "cfinv" + "mov w21, w4", + "mov w22, w4", + "sub x26, x22, x21", + "eor w27, w22, w21", + "cmp w22, w21", + "cfinv", + "mov x4, x20" ] }, "cmpxchg [rax], ebx": { @@ -1240,20 +1211,15 @@ ] }, "cmpxchg rax, rbx": { - "ExpectedInstructionCount": 11, + "ExpectedInstructionCount": 6, "Comment": "0x0f 0xb1", "ExpectedArm64ASM": [ - "mov x20, x4", - "cmp x20, x20", - "csel x21, x20, x20, eq", - "cmp x20, x20", - "csel x22, x7, x20, eq", - "mov x4, x21", - "mov x4, x22", - "sub x26, x20, x21", - "eor x27, x20, x21", - "cmp x20, x21", - "cfinv" + "mov x20, x7", + "sub x26, x4, x4", + "mov w27, #0x0", + "cmp x4, x4", + "cfinv", + "mov x4, x20" ] }, "btr ax, bx": { diff --git a/unittests/InstructionCountCI/Secondary.json b/unittests/InstructionCountCI/Secondary.json index 2056e27e5..591b8751b 100644 --- a/unittests/InstructionCountCI/Secondary.json +++ b/unittests/InstructionCountCI/Secondary.json @@ -1895,30 +1895,25 @@ ] }, "cmpxchg al, bl": { - "ExpectedInstructionCount": 21, + "ExpectedInstructionCount": 16, "Comment": "0x0f 0xb0", "ExpectedArm64ASM": [ "uxtb w20, w7", "uxtb w21, w4", "uxtb x22, w4", - "cmp x21, x22", - "csel x23, x22, x21, eq", - "cmp x21, x22", - "csel w20, w20, w21, eq", - "bfxil x4, x23, #0, #8", - "bfxil x4, x20, #0, #8", - "sub x26, x22, x23", - "eor w27, w22, w23", + "sub x26, x22, x21", + "eor w27, w22, w21", "cmn wzr, w26, lsl #24", - "mrs x20, nzcv", - "ubfx x21, x26, #8, #1", - "orr w20, w20, w21, lsl #29", - "eor w21, w22, w23", + "mrs x23, nzcv", + "ubfx x24, x26, #8, #1", + "orr w23, w23, w24, lsl #29", + "eor w21, w22, w21", "eor w22, w26, w22", "and w21, w22, w21", "ubfx x21, x21, #7, #1", - "orr w20, w20, w21, lsl #28", - "msr nzcv, x20" + "orr w21, w23, w21, lsl #28", + "msr nzcv, x21", + "bfxil x4, x20, #0, #8" ] }, "cmpxchg [rax], bl": { @@ -1946,30 +1941,25 @@ ] }, "cmpxchg ax, bx": { - "ExpectedInstructionCount": 21, + "ExpectedInstructionCount": 16, "Comment": "0x0f 0xb1", "ExpectedArm64ASM": [ "uxth w20, w7", "uxth w21, w4", "uxth x22, w4", - "cmp x21, x22", - "csel x23, x22, x21, eq", - "cmp x21, x22", - "csel w20, w20, w21, eq", - "bfxil x4, x23, #0, #16", - "bfxil x4, x20, #0, #16", - "sub x26, x22, x23", - "eor w27, w22, w23", + "sub x26, x22, x21", + "eor w27, w22, w21", "cmn wzr, w26, lsl #16", - "mrs x20, nzcv", - "ubfx x21, x26, #16, #1", - "orr w20, w20, w21, lsl #29", - "eor w21, w22, w23", + "mrs x23, nzcv", + "ubfx x24, x26, #16, #1", + "orr w23, w23, w24, lsl #29", + "eor w21, w22, w21", "eor w22, w26, w22", "and w21, w22, w21", "ubfx x21, x21, #15, #1", - "orr w20, w20, w21, lsl #28", - "msr nzcv, x20" + "orr w21, w23, w21, lsl #28", + "msr nzcv, x21", + "bfxil x4, x20, #0, #16" ] }, "cmpxchg [rax], bx": { @@ -1997,26 +1987,19 @@ ] }, "cmpxchg eax, ebx": { - "ExpectedInstructionCount": 17, + "ExpectedInstructionCount": 10, "Comment": "0x0f 0xb1", "ExpectedArm64ASM": [ "mov w20, w7", - "mov x21, x4", - "mov w22, w21", - "mov w23, w21", - "cmp x22, x23", - "csel x24, x23, x22, eq", - "cmp x22, x23", - "csel x20, x20, x21, eq", - "cmp x24, x23", - "csel x4, x21, x22, eq", - "mov x4, x20", - "sub x26, x23, x24", - "eor w27, w23, w24", - "cmp w23, w24", - "mrs x20, nzcv", - "eor w20, w20, #0x20000000", - "msr nzcv, x20" + "mov w21, w4", + "mov w22, w4", + "sub x26, x22, x21", + "eor w27, w22, w21", + "cmp w22, w21", + "mrs x21, nzcv", + "eor w21, w21, #0x20000000", + "msr nzcv, x21", + "mov x4, x20" ] }, "cmpxchg [rax], ebx": { @@ -2039,22 +2022,17 @@ ] }, "cmpxchg rax, rbx": { - "ExpectedInstructionCount": 13, + "ExpectedInstructionCount": 8, "Comment": "0x0f 0xb1", "ExpectedArm64ASM": [ - "mov x20, x4", - "cmp x20, x20", - "csel x21, x20, x20, eq", - "cmp x20, x20", - "csel x22, x7, x20, eq", - "mov x4, x21", - "mov x4, x22", - "sub x26, x20, x21", - "eor x27, x20, x21", - "cmp x20, x21", - "mrs x20, nzcv", - "eor w20, w20, #0x20000000", - "msr nzcv, x20" + "mov x20, x7", + "sub x26, x4, x4", + "mov w27, #0x0", + "cmp x4, x4", + "mrs x21, nzcv", + "eor w21, w21, #0x20000000", + "msr nzcv, x21", + "mov x4, x20" ] }, "cmpxchg [rax], rbx": {