mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-23 14:00:47 +02:00
DCSE: Refactor LoadContext slightly
* Use a single path for both truncated and non-truncated reads * Support more truncation types * Support truncating partial reads
This commit is contained in:
1 parent
6dadf81001
commit
65af0335dd
2 files changed
+32
-40
No files matched your search
+5
-1
@@ -1391,13 +1391,17 @@
|
||||
},
|
||||
|
||||
"VMov": {
|
||||
"Desc" : ["Copy vector register",
|
||||
"When Register size is smaller than Source register size,",
|
||||
"this op is defined to truncate and zero extend"
|
||||
],
|
||||
"OpClass": "Vector",
|
||||
"HasDest": true,
|
||||
"DestClass": "FPR",
|
||||
"DestSize": "RegisterSize",
|
||||
"SSAArgs": "1",
|
||||
"SSANames": [
|
||||
"Vector"
|
||||
"Source"
|
||||
],
|
||||
"HelperArgs": [
|
||||
"uint8_t", "RegisterSize"
|
||||
|
||||
+27
-39
@@ -487,50 +487,50 @@ bool RCLSE::RedundantStoreLoadElimination(FEXCore::IR::IREmitter *IREmit) {
|
||||
else if (IROp->Op == OP_LOADCONTEXT) {
|
||||
auto Op = IROp->CW<IR::IROp_LoadContext>();
|
||||
auto Info = FindMemberInfo(&LocalInfo, Op->Offset, IROp->Size);
|
||||
uint8_t LastClass = Info->AccessRegClass;
|
||||
RegisterClassType LastClass = Info->AccessRegClass;
|
||||
uint32_t LastOffset = Info->AccessOffset;
|
||||
uint8_t LastSize = Info->AccessSize;
|
||||
RegisterClassType RegClass = Info->AccessRegClass;
|
||||
LastAccessType LastAccess = Info->Accessed;
|
||||
OrderedNode *LastNode = Info->Node;
|
||||
OrderedNode *LastStoreNode = Info->StoreNode;
|
||||
RecordAccess(Info, Op->Class, Op->Offset, IROp->Size, ACCESS_READ, CodeNode);
|
||||
|
||||
if (LastAccess == ACCESS_WRITE &&
|
||||
if ((LastAccess == ACCESS_WRITE || LastAccess == ACCESS_PARTIAL_WRITE) &&
|
||||
LastClass == Op->Class &&
|
||||
LastOffset == Op->Offset &&
|
||||
LastSize == IROp->Size &&
|
||||
Info->Accessed == ACCESS_READ) {
|
||||
LastClass == GPRClass &&
|
||||
IROp->Size <= LastSize) {
|
||||
// If the last store matches this load value then we can replace the loaded value with the previous valid one
|
||||
|
||||
IREmit->SetWriteCursor(CodeNode);
|
||||
|
||||
uint8_t TruncateSize = OpSize(LastNode);
|
||||
|
||||
// Did store context do an implicit truncation?
|
||||
if (OpSize(LastStoreNode) < OpSize(LastNode)) {
|
||||
uint8_t TruncateSize = OpSize(LastStoreNode);
|
||||
if (OpSize(LastStoreNode) < TruncateSize)
|
||||
TruncateSize = OpSize(LastStoreNode);
|
||||
|
||||
// Or are we doing a partial read
|
||||
if (IROp->Size < TruncateSize)
|
||||
TruncateSize = IROp->Size;
|
||||
|
||||
if (TruncateSize != OpSize(LastNode)) {
|
||||
// We need to insert an explict truncation
|
||||
if (RegClass == FPRClass)
|
||||
LastNode = IREmit->_Bfe(TruncateSize * 8, 0, LastNode); // XXX FIXME: BFE shouldn't be used on FPR registers
|
||||
else if (RegClass == GPRPairClass)
|
||||
if (LastClass == FPRClass) {
|
||||
LastNode = IREmit->_VMov(LastNode, TruncateSize); // Vmov truncates and zexts when register width is smaller than source
|
||||
}
|
||||
else if (LastClass == GPRPairClass) {
|
||||
LastNode = IREmit->_TruncElementPair(LastNode, TruncateSize);
|
||||
else if (RegClass == GPRClass)
|
||||
LastNode = IREmit->_Bfe(IROp->Size, TruncateSize * 8, 0, LastNode);
|
||||
}
|
||||
else if (LastClass == GPRClass) {
|
||||
LastNode = IREmit->_Bfe(Info->AccessSize, TruncateSize * 8, 0, LastNode);
|
||||
} else {
|
||||
LogMan::Msg::A("Unhandled Register class");
|
||||
}
|
||||
}
|
||||
|
||||
// If the last store matches this load value then we can replace the loaded value with the previous valid one
|
||||
|
||||
if (Op->Offset >= offsetof(FEXCore::Core::CPUState, xmm[0]) &&
|
||||
Op->Offset <= offsetof(FEXCore::Core::CPUState, xmm[15])) {
|
||||
|
||||
|
||||
// XMM needs a bit of special help
|
||||
auto BitCast = IREmit->_VBitcast(IROp->Size * 8, 1, LastNode); // FIXME
|
||||
IREmit->ReplaceAllUsesWithInclusive(CodeNode, BitCast, CodeBegin, CodeLast);
|
||||
RecordAccess(Info, Op->Class, Op->Offset, IROp->Size, ACCESS_READ, LastNode);
|
||||
}
|
||||
else {
|
||||
IREmit->ReplaceAllUsesWithInclusive(CodeNode, LastNode, CodeBegin, CodeLast);
|
||||
RecordAccess(Info, Op->Class, Op->Offset, IROp->Size, ACCESS_READ, LastNode);
|
||||
}
|
||||
IREmit->ReplaceAllUsesWithInclusive(CodeNode, LastNode, CodeBegin, CodeLast);
|
||||
RecordAccess(Info, Op->Class, Op->Offset, IROp->Size, ACCESS_READ, LastNode);
|
||||
Changed = true;
|
||||
}
|
||||
else if ((LastAccess == ACCESS_READ || LastAccess == ACCESS_PARTIAL_READ) &&
|
||||
@@ -543,18 +543,6 @@ bool RCLSE::RedundantStoreLoadElimination(FEXCore::IR::IREmitter *IREmit) {
|
||||
RecordAccess(Info, Op->Class, Op->Offset, IROp->Size, ACCESS_READ, LastNode);
|
||||
Changed = true;
|
||||
}
|
||||
else if (LastClass == Op->Class &&
|
||||
LastClass == 0 && // We only support GPRs
|
||||
LastOffset == Op->Offset &&
|
||||
LastSize > IROp->Size) {
|
||||
// We are reading only part of the previous write
|
||||
// XXX: This is just a temporary optimisation until this pass is improved
|
||||
IREmit->SetWriteCursor(CodeNode);
|
||||
auto Narrowed = IREmit->_Bfe(IROp->Size, IROp->Size * 8, 0, LastNode);
|
||||
IREmit->ReplaceAllUsesWithInclusive(CodeNode, Narrowed, CodeBegin, CodeLast);
|
||||
RecordAccess(Info, Op->Class, Op->Offset, IROp->Size, ACCESS_PARTIAL_READ, Narrowed);
|
||||
Changed = true;
|
||||
}
|
||||
}
|
||||
else if (IROp->Op == OP_STOREFLAG) {
|
||||
auto Op = IROp->CW<IR::IROp_StoreFlag>();
|
||||
|
||||
Reference in new issue
Block a user