diff --git a/FEXCore/Source/Interface/IR/Passes/x87StackOptimizationPass.cpp b/FEXCore/Source/Interface/IR/Passes/x87StackOptimizationPass.cpp index 5bafe52bc0..a2713c12b3 100644 --- a/FEXCore/Source/Interface/IR/Passes/x87StackOptimizationPass.cpp +++ b/FEXCore/Source/Interface/IR/Passes/x87StackOptimizationPass.cpp @@ -48,6 +48,13 @@ bool X87StackOptimization::Run(IREmitter *IREmit) { StackData.clear(); + // Before any optimizations we need to update our StackData to match the + // status at the beginning of the block. We need to load the values from the + // context to the stack. We'll do this by checking which values to load + // through the x87 tag register. + // TODO(pmatos) + + // Run optimization proper for (auto [BlockNode, BlockHeader] : CurrentIR.GetBlocks()) { for (auto [CodeNode, IROp] : CurrentIR.GetCode(BlockNode)) { switch (IROp->Op) { @@ -130,24 +137,41 @@ bool X87StackOptimization::Run(IREmitter *IREmit) { } } } - IREmit->SetWriteCursor(OriginalWriteCursor); - // Before leaving we need to write the current values in the stack to context - // so that the values are correct. - // Copy SourceDataNode in the stack to the respective mmX register. - for (size_t i = 0; i < StackData.size(); ++i) { - auto &StackMember = StackData[i]; - auto *Node = StackMember.SourceDataNode; - IREmit->_StoreContextIndexed(Node, IREmit->_Constant(i), 16, MMBaseOffset(), - 16, FPRClass); + // FIXME(pmatos) there's probably a better way to do this + // TODO(pmatos): we don't need to do this if we don't have any followup + // blocks. How can we check that? OTOH, not writing to the proper registers + // might screw up testing that expects the values to be in the stack registers + // at the end, so maybe we need a testing flag that forces the writing of this + // data to the context. + for (auto [BlockNode, BlockHeader] : CurrentIR.GetBlocks()) { + for (auto [CodeNode, IROp] : CurrentIR.GetCode(BlockNode)) { + if (IROp->Op == OP_ENTRYPOINTOFFSET) { + LogMan::Msg::DFmt("OP_ENTRYPOINTOFFSET\n"); + // Set write cursor to previous instruction + IREmit->SetWriteCursor(IREmit->UnwrapNode(CodeNode->Header.Previous)); + + // Before leaving we need to write the current values in the stack to + // context so that the values are correct. Copy SourceDataNode in the + // stack to the respective mmX register. + for (size_t i = 0; i < StackData.size(); ++i) { + LogMan::Msg::DFmt("Writing stack member {} to context", i); + Changed = true; + auto &StackMember = StackData[i]; + auto *Node = StackMember.SourceDataNode; + IREmit->_StoreContextIndexed(Node, IREmit->_Constant(i), 16, + MMBaseOffset(), 16, FPRClass); + } + break; + } + } } + IREmit->SetWriteCursor(OriginalWriteCursor); return Changed; } fextl::unique_ptr CreateX87StackOptimizationPass() { return fextl::make_unique(); } - - -} +} // namespace FEXCore::IR diff --git a/docs/SourceOutline.md b/docs/SourceOutline.md index cb31f1e8f7..3bb4fda3db 100644 --- a/docs/SourceOutline.md +++ b/docs/SourceOutline.md @@ -5,7 +5,7 @@ See [FEXCore/Readme.md](../FEXCore/Readme.md) for more details ### Glossary -- Splatter: a code generator backend that concaternates configurable macros instead of doing isel +- Splatter: a code generator backend that concatenates configurable macros instead of doing isel - IR: Intermediate Representation, our high-level opcode representation, loosely modeling arm64 - SSA: Single Static Assignment, a form of representing IR in memory - Basic Block: A block of instructions with no control flow, terminated by control flow