OpcodeDispatcher: optimize LOOP invert

need to reorder since the select clobbers nzcv. before/after diff on the loopne
unit test:

> 4308: [INFO] cset w20, ne
40c41
< 4308: [INFO] mrs x20, nzcv
---
> 4308: [INFO] mrs x21, nzcv
42,49c43,48
< 4308: [INFO] cset x21, ne
< 4308: [INFO] ubfx w22, w20, #30, #1
< 4308: [INFO] eor x22, x22, #0x1
< 4308: [INFO] and x21, x21, x22
< 4308: [INFO] msr nzcv, x20
< 4308: [INFO] cbnz x21, #+0x8 (addr 0xfffed66f8094)
< 4308: [INFO] b #+0x1c (addr 0xfffed66f80ac)
< 4308: [INFO] ldr x0, pc+8 (addr 0xfffed66f809c)
---
> 4308: [INFO] cset x22, ne
> 4308: [INFO] and x20, x22, x20
> 4308: [INFO] msr nzcv, x21
> 4308: [INFO] cbnz x20, #+0x8 (addr 0xfffec94e8090)
> 4308: [INFO] b #+0x1c (addr 0xfffec94e80a8)
> 4308: [INFO] ldr x0, pc+8 (addr 0xfffec94e8098)

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
This commit is contained in:
Alyssa Rosenzweig 2023-11-10 11:06:51 -04:00
parent 0d70c6a0d0
commit ec14a65e23

View File

@ -1092,6 +1092,12 @@ void OpDispatchBuilder::LoopOp(OpcodeArgs) {
bool CheckZF = Op->OP != 0xE2;
bool ZFTrue = Op->OP == 0xE1;
// If LOOPE then jumps to target if RCX != 0 && ZF == 1
// If LOOPNE then jumps to target if RCX != 0 && ZF == 0
OrderedNode *AndCondWith = nullptr;
if (CheckZF)
AndCondWith = GetRFLAG(FEXCore::X86State::RFLAG_ZF_RAW_LOC, !ZFTrue);
BlockSetRIP = true;
auto ZeroConst = _Constant(0);
IRPair<IROp_Header> SrcCond;
@ -1112,15 +1118,8 @@ void OpDispatchBuilder::LoopOp(OpcodeArgs) {
SrcCond = _Select(FEXCore::IR::COND_NEQ,
CondReg, ZeroConst, TakeBranch, DoNotTakeBranch);
// If LOOPE then jumps to target if RCX != 0 && ZF == 1
// If LOOPNE then jumps to target if RCX != 0 && ZF == 0
if (CheckZF) {
OrderedNode *ZF = GetRFLAG(FEXCore::X86State::RFLAG_ZF_RAW_LOC);
if (!ZFTrue) {
ZF = _Xor(OpSize::i64Bit, ZF, _Constant(1));
}
SrcCond = _And(OpSize::i64Bit, SrcCond, ZF);
}
if (AndCondWith)
SrcCond = _And(OpSize::i64Bit, SrcCond, AndCondWith);
CalculateDeferredFlags();
auto TrueBlock = JumpTargets.find(Target);