MCPcopy Create free account
hub / github.com/FEX-Emu/FEX / TryPostRAMerge

Method TryPostRAMerge

FEXCore/Source/Interface/IR/Passes/RegisterAllocationPass.cpp:473–563  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

471}
472
473bool ConstrainedRAPass::TryPostRAMerge(Ref LastNode, Ref CodeNode, IROp_Header* IROp) {
474 auto LastOp = IR->GetOp<IROp_Header>(LastNode);
475
476 if (IROp->Op == OP_PUSH && LastOp->Op == OP_PUSH) {
477 auto SP = PhysicalRegister(CodeNode);
478 auto Push = IR->GetOp<IROp_Push>(CodeNode);
479 auto LastPush = IR->GetOp<IROp_Push>(LastNode);
480
481 if (LastOp->Size == IROp->Size && LastPush->ValueSize == Push->ValueSize && SP == PhysicalRegister(LastNode) &&
482 SP == PhysicalRegister(IROp->Args[1]) && SP == PhysicalRegister(LastOp->Args[1]) && SP != PhysicalRegister(IROp->Args[0]) &&
483 SP != PhysicalRegister(LastOp->Args[0]) && Push->ValueSize >= OpSize::i32Bit) {
484
485 IREmit->SetWriteCursorBefore(LastNode);
486 IREmit->_PushTwo(IROp->Size, Push->ValueSize, IROp->Args[0], LastOp->Args[0], IROp->Args[1]);
487 IREmit->RemovePostRA(CodeNode);
488 return true;
489 }
490 } else if (IROp->Op == OP_POP) {
491 auto SP = PhysicalRegister(IROp->Args[0]);
492
493 if (LastOp->Op == OP_POP && LastOp->Size == IROp->Size && IROp->Size >= OpSize::i32Bit && SP == PhysicalRegister(LastOp->Args[0])) {
494 IREmit->SetWriteCursorBefore(LastNode);
495 IREmit->_PopTwo(IROp->Size, IROp->Args[0], LastOp->Args[1], IROp->Args[1]);
496 IREmit->RemovePostRA(CodeNode);
497 return true;
498 }
499 } else if ((IROp->Op == OP_DIV || IROp->Op == OP_UDIV) && IROp->Size >= OpSize::i32Bit) {
500 // If Upper came from a sign/zero extension, we only need a 64-bit division.
501 auto Op = IROp->CW<IR::IROp_Div>();
502 if (!Op->Upper.IsInvalid() && PhysicalRegister(Op->Upper) == PhysicalRegister(LastNode)) {
503 if (IROp->Op == OP_DIV ? IsSignext(LastOp, Op->Lower, IROp->Size) : IsZero(LastOp)) {
504 Op->Upper.SetInvalid();
505 return PhysicalRegister(LastNode) == PhysicalRegister(Op->OutRemainder);
506 }
507 }
508 } else if (IROp->Op == OP_XGETBV && PhysicalRegister(IROp->Args[0]) == PhysicalRegister(LastNode) && LastOp->Op == OP_CONSTANT) {
509 // Try to constant fold
510 uint64_t ConstantFunction = LastOp->C<IROp_Constant>()->Constant;
511 auto Op = IROp->CW<IR::IROp_XGetBV>();
512 if (CPUID->DoesXCRFunctionReportConstantData(ConstantFunction)) {
513 const auto Result = CPUID->RunXCRFunction(ConstantFunction);
514 IREmit->SetWriteCursorBefore(CodeNode);
515 IREmit->_Constant(Result.eax).Node->Reg = PhysicalRegister(Op->OutEAX).Raw;
516 IREmit->_Constant(Result.edx).Node->Reg = PhysicalRegister(Op->OutEDX).Raw;
517 IREmit->RemovePostRA(CodeNode);
518 return false;
519 }
520 } else if (IROp->Op == OP_CPUID && PhysicalRegister(IROp->Args[0]) == PhysicalRegister(LastNode) && LastOp->Op == OP_CONSTANT) {
521 // Try to constant fold. As a limitation of merging only 2 instructions, we
522 // can only handle constant functions, not constant leafs. This could be
523 // lifted if we generalized at a (significant) complexity cost.
524 uint64_t ConstantFunction = LastOp->C<IROp_Constant>()->Constant;
525 auto Op = IROp->CW<IR::IROp_CPUID>();
526
527 const auto SupportsConstant = CPUID->DoesFunctionReportConstantData(ConstantFunction);
528 if (SupportsConstant.SupportsConstantFunction == CPUIDEmu::SupportsConstant::CONSTANT &&
529 SupportsConstant.NeedsLeaf != CPUIDEmu::NeedsLeafConstant::NEEDSLEAFCONSTANT) {
530 const auto Result = CPUID->RunFunction(ConstantFunction, 0 /* leaf */);

Callers

nothing calls this directly

Calls 11

PhysicalRegisterFunction · 0.85
IsSignextFunction · 0.85
IsZeroFunction · 0.85
KillMoveFunction · 0.85
SetWriteCursorBeforeMethod · 0.80
RemovePostRAMethod · 0.80
IsInvalidMethod · 0.80
RunFunctionMethod · 0.80
RunXCRFunctionMethod · 0.45

Tested by

no test coverage detected