From 44484a7b05cfd5ec3cd9db4dbb6b22e115b7f301 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Wed, 2 Oct 2024 13:59:03 -0400 Subject: [PATCH] ConstProp: drop non-loadbearing opts every pattern costs us JIT time, but not every pattern is doing anything. especially with the flag rework of 2023-2024, a lot of patterns just don't make sense anymore. constant folding in particular isn't too useful now. only instcountci change is AAD which i'm contractually forbidden from caring about. Signed-off-by: Alyssa Rosenzweig --- .../Source/Interface/IR/Passes/ConstProp.cpp | 114 +----------------- .../FlagM/Primary_32Bit.json | 5 +- .../InstructionCountCI/Primary_32Bit.json | 5 +- 3 files changed, 10 insertions(+), 114 deletions(-) diff --git a/FEXCore/Source/Interface/IR/Passes/ConstProp.cpp b/FEXCore/Source/Interface/IR/Passes/ConstProp.cpp index b0816cb3c..5ead4ffe7 100644 --- a/FEXCore/Source/Interface/IR/Passes/ConstProp.cpp +++ b/FEXCore/Source/Interface/IR/Passes/ConstProp.cpp @@ -52,17 +52,6 @@ static bool IsImmLogical(uint64_t imm, unsigned width) { return ARMEmitter::Emitter::IsImmLogical(imm, width); } -static bool IsBfeAlreadyDone(IREmitter* IREmit, OrderedNodeWrapper src, uint64_t Width) { - auto IROp = IREmit->GetOpHeader(src); - if (IROp->Op == OP_BFE) { - auto Op = IROp->C(); - if (Width >= Op->Width) { - return true; - } - } - return false; -} - class ConstProp final : public FEXCore::IR::Pass { public: explicit ConstProp(bool SupportsTSOImm9, const FEXCore::CPUIDEmu* CPUID) @@ -294,16 +283,6 @@ void ConstProp::ConstantPropagation(IREmitter* IREmit, const IRListView& Current uint64_t NewConstant = (Constant1 & Constant2) & getMask(IROp); IREmit->ReplaceWithConstant(CodeNode, NewConstant); Replaced = true; - } else if (Constant2 == 1) { - // happens from flag calcs - auto val = IREmit->GetOpHeader(IROp->Args[0]); - - uint64_t Constant3; - if (val->Op == OP_SELECT && IREmit->IsValueConstant(val->Args[2], &Constant2) && IREmit->IsValueConstant(val->Args[3], &Constant3) && - Constant2 == 1 && Constant3 == 0) { - IREmit->ReplaceAllUsesWith(CodeNode, CurrentIR.GetNode(IROp->Args[0])); - Replaced = true; - } } else if (IROp->Args[0].ID() == IROp->Args[1].ID() || (Constant2 & getMask(IROp)) == getMask(IROp)) { // AND with same value results in original value IREmit->ReplaceAllUsesWith(CodeNode, CurrentIR.GetNode(IROp->Args[0])); @@ -316,28 +295,13 @@ void ConstProp::ConstantPropagation(IREmitter* IREmit, const IRListView& Current break; } case OP_OR: { - uint64_t Constant1 {}; - uint64_t Constant2 {}; - - if (IREmit->IsValueConstant(IROp->Args[0], &Constant1) && IREmit->IsValueConstant(IROp->Args[1], &Constant2)) { - uint64_t NewConstant = Constant1 | Constant2; - IREmit->ReplaceWithConstant(CodeNode, NewConstant); - } else if (IROp->Args[0].ID() == IROp->Args[1].ID()) { - // OR with same value results in original value - IREmit->ReplaceAllUsesWith(CodeNode, CurrentIR.GetNode(IROp->Args[0])); - } else { - InlineIf(IREmit, CurrentIR, CodeNode, IROp, 1, [&IROp](uint64_t X) { return IsImmLogical(X, IROp->Size * 8); }); - } + InlineIf(IREmit, CurrentIR, CodeNode, IROp, 1, [&IROp](uint64_t X) { return IsImmLogical(X, IROp->Size * 8); }); break; } case OP_XOR: { uint64_t Constant1 {}; - uint64_t Constant2 {}; - if (IREmit->IsValueConstant(IROp->Args[0], &Constant1) && IREmit->IsValueConstant(IROp->Args[1], &Constant2)) { - uint64_t NewConstant = Constant1 ^ Constant2; - IREmit->ReplaceWithConstant(CodeNode, NewConstant); - } else if (IROp->Args[0].ID() == IROp->Args[1].ID()) { + if (IROp->Args[0].ID() == IROp->Args[1].ID()) { // XOR with same value results to zero IREmit->SetWriteCursor(CodeNode); IREmit->ReplaceAllUsesWith(CodeNode, IREmit->_Constant(0)); @@ -405,19 +369,9 @@ void ConstProp::ConstantPropagation(IREmitter* IREmit, const IRListView& Current break; } case OP_LSHR: { - uint64_t Constant1 {}; uint64_t Constant2 {}; - if (IREmit->IsValueConstant(IROp->Args[0], &Constant1) && IREmit->IsValueConstant(IROp->Args[1], &Constant2)) { - // Shifts mask the shift amount by 63 or 31 depending on operating size; - // The source is masked, which will produce a correctly masked - // destination. Masking the destination without the source instead will - // right-shift garbage into the upper bits instead of zeroes. - Constant1 &= getMask(IROp); - Constant2 &= (IROp->Size == 8 ? 63 : 31); - uint64_t NewConstant = (Constant1 >> Constant2); - IREmit->ReplaceWithConstant(CodeNode, NewConstant); - } else if (IREmit->IsValueConstant(IROp->Args[1], &Constant2) && Constant2 == 0) { + if (IREmit->IsValueConstant(IROp->Args[1], &Constant2) && Constant2 == 0) { IREmit->SetWriteCursor(CodeNode); Ref Arg = CurrentIR.GetNode(IROp->Args[0]); IREmit->ReplaceAllUsesWith(CodeNode, Arg); @@ -430,46 +384,12 @@ void ConstProp::ConstantPropagation(IREmitter* IREmit, const IRListView& Current auto Op = IROp->C(); uint64_t Constant; - // Is this value already BFE'd? - if (IsBfeAlreadyDone(IREmit, Op->Src, Op->Width)) { - IREmit->ReplaceAllUsesWith(CodeNode, CurrentIR.GetNode(Op->Src)); - break; - } - - // Is this value already ZEXT'd? - if (Op->lsb == 0) { - // LoadMem, LoadMemTSO & LoadContext ZExt - auto source = Op->Src; - auto sourceHeader = IREmit->GetOpHeader(source); - - if (Op->Width >= (sourceHeader->Size * 8) && - (sourceHeader->Op == OP_LOADMEM || sourceHeader->Op == OP_LOADMEMTSO || sourceHeader->Op == OP_LOADCONTEXT)) { - // Load mem / load ctx zexts, no need to vmem - IREmit->ReplaceAllUsesWith(CodeNode, CurrentIR.GetNode(source)); - break; - } - } - if (IROp->Size <= 8 && IREmit->IsValueConstant(Op->Src, &Constant)) { uint64_t SourceMask = Op->Width == 64 ? ~0ULL : ((1ULL << Op->Width) - 1); SourceMask <<= Op->lsb; uint64_t NewConstant = (Constant & SourceMask) >> Op->lsb; IREmit->ReplaceWithConstant(CodeNode, NewConstant); - } else if (IROp->Size == CurrentIR.GetOp(IROp->Args[0])->Size && Op->Width == (IROp->Size * 8) && Op->lsb == 0) { - // A BFE that extracts all bits results in original value - // XXX - This is broken for now - see https://github.com/FEX-Emu/FEX/issues/351 - // IREmit->ReplaceAllUsesWith(CodeNode, CurrentIR.GetNode(IROp->Args[0])); - } else if (Op->Width == 1 && Op->lsb == 0) { - // common from flag codegen - auto val = IREmit->GetOpHeader(IROp->Args[0]); - - uint64_t Constant2 {}; - uint64_t Constant3 {}; - if (val->Op == OP_SELECT && IREmit->IsValueConstant(val->Args[2], &Constant2) && IREmit->IsValueConstant(val->Args[3], &Constant3) && - Constant2 == 1 && Constant3 == 0) { - IREmit->ReplaceAllUsesWith(CodeNode, CurrentIR.GetNode(IROp->Args[0])); - } } break; @@ -494,18 +414,10 @@ void ConstProp::ConstantPropagation(IREmitter* IREmit, const IRListView& Current } case OP_BFI: { auto Op = IROp->C(); - uint64_t ConstantDest {}; uint64_t ConstantSrc {}; - bool DestIsConstant = IREmit->IsValueConstant(IROp->Args[0], &ConstantDest); bool SrcIsConstant = IREmit->IsValueConstant(IROp->Args[1], &ConstantSrc); - if (DestIsConstant && SrcIsConstant) { - uint64_t SourceMask = Op->Width == 64 ? ~0ULL : ((1ULL << Op->Width) - 1); - uint64_t NewConstant = ConstantDest & ~(SourceMask << Op->lsb); - NewConstant |= (ConstantSrc & SourceMask) << Op->lsb; - - IREmit->ReplaceWithConstant(CodeNode, NewConstant); - } else if (SrcIsConstant && HasConsecutiveBits(ConstantSrc, Op->Width)) { + if (SrcIsConstant && HasConsecutiveBits(ConstantSrc, Op->Width)) { // We are trying to insert constant, if it is a bitfield of only set bits then we can orr or and it. IREmit->SetWriteCursor(CodeNode); uint64_t SourceMask = Op->Width == 64 ? ~0ULL : ((1ULL << Op->Width) - 1); @@ -522,24 +434,6 @@ void ConstProp::ConstantPropagation(IREmitter* IREmit, const IRListView& Current } break; } - case OP_MUL: { - uint64_t Constant1 {}; - uint64_t Constant2 {}; - - if (IREmit->IsValueConstant(IROp->Args[0], &Constant1) && IREmit->IsValueConstant(IROp->Args[1], &Constant2)) { - uint64_t NewConstant = (Constant1 * Constant2) & getMask(IROp); - IREmit->ReplaceWithConstant(CodeNode, NewConstant); - } else if (IREmit->IsValueConstant(IROp->Args[1], &Constant2) && std::popcount(Constant2) == 1) { - if (IROp->Size == 4 || IROp->Size == 8) { - uint64_t amt = std::countr_zero(Constant2); - IREmit->SetWriteCursor(CodeNode); - auto shift = IREmit->_Lshl(IR::SizeToOpSize(IROp->Size), CurrentIR.GetNode(IROp->Args[0]), IREmit->_Constant(amt)); - IREmit->ReplaceAllUsesWith(CodeNode, shift); - } - } - break; - } - case OP_VMOV: { // elim from load mem auto source = IROp->Args[0]; diff --git a/unittests/InstructionCountCI/FlagM/Primary_32Bit.json b/unittests/InstructionCountCI/FlagM/Primary_32Bit.json index 73698a9d2..50eccd1ed 100644 --- a/unittests/InstructionCountCI/FlagM/Primary_32Bit.json +++ b/unittests/InstructionCountCI/FlagM/Primary_32Bit.json @@ -352,14 +352,15 @@ ] }, "db 0xd5, 0x40": { - "ExpectedInstructionCount": 7, + "ExpectedInstructionCount": 8, "Comment": [ "aad with a different immediate byte base", "0xd5" ], "ExpectedArm64ASM": [ "lsr w20, w4, #8", - "lsl x20, x20, #6", + "mov w21, #0x40", + "mul x20, x20, x21", "add x20, x4, x20", "and x26, x20, #0xff", "bfxil w4, w26, #0, #16", diff --git a/unittests/InstructionCountCI/Primary_32Bit.json b/unittests/InstructionCountCI/Primary_32Bit.json index b0945d1a9..bae7f6611 100644 --- a/unittests/InstructionCountCI/Primary_32Bit.json +++ b/unittests/InstructionCountCI/Primary_32Bit.json @@ -373,14 +373,15 @@ ] }, "db 0xd5, 0x40": { - "ExpectedInstructionCount": 9, + "ExpectedInstructionCount": 10, "Comment": [ "aad with a different immediate byte base", "0xd5" ], "ExpectedArm64ASM": [ "lsr w20, w4, #8", - "lsl x20, x20, #6", + "mov w21, #0x40", + "mul x20, x20, x21", "add x20, x4, x20", "and x26, x20, #0xff", "bfxil w4, w26, #0, #16",