From efa37c8e2625e41d274c426266e2ae39c2079b22 Mon Sep 17 00:00:00 2001 From: Rahil Shah Date: Thu, 14 May 2020 18:32:24 -0400 Subject: [PATCH] Changes in RegDepCopyRemoval for splitPostGRA block splitter RegDepCopyRemoval is the last ran optimization which intends to reduce register shuffling due to global register dependencies. It was generating tree where we have a PassThrough Child under PassThrough to copy node to new virtual register. This tree was not working well with the post GRA block splitter. Issue was that PassThrough child encountered in GlRegDeps was anchored to tree top. In postGRA block splitter, it records the regStores encountered before the GlRegDeps in extended basic block to guide decision on which register to chose for the node after split point.In this commit, adding changes to both splitPostGRA block splitter and RegDepCopyRemoval optimization so that we can split the blocks after later has run. Signed-off-by: Rahil Shah --- compiler/il/OMRBlock.cpp | 10 ++++-- compiler/optimizer/RegDepCopyRemoval.cpp | 39 +++++++++++++++++++----- compiler/optimizer/RegDepCopyRemoval.hpp | 3 +- 3 files changed, 41 insertions(+), 11 deletions(-) diff --git a/compiler/il/OMRBlock.cpp b/compiler/il/OMRBlock.cpp index 1f0c90bf7f0..ae9d3027f31 100644 --- a/compiler/il/OMRBlock.cpp +++ b/compiler/il/OMRBlock.cpp @@ -1018,6 +1018,9 @@ static void gatherUnavailableRegisters(TR::Compilation *comp, TR::Node *regDeps, if (dep->getOpCodeValue() == TR::PassThrough) { TR::Node *value = dep->getFirstChild(); + TR::Node *originalNode = value; + while (originalNode->getOpCodeValue() == TR::PassThrough) + originalNode = originalNode->getFirstChild(); auto nodeInfoEntry = nodeInfo->find(value); // If a node referenced under the PassThrough node post split point requires uncommoning // We need to check if the we can use the information to allocate the register for the node or not. @@ -1043,7 +1046,7 @@ static void gatherUnavailableRegisters(TR::Compilation *comp, TR::Node *regDeps, if (checkIfRegisterIsAvailable(comp, storeNode, unavailableRegisters)) { // Whether the PassThrough uses same register or not, use the last recorded regStore to assign register to the node. - TR::Node *regLoad = TR::Node::create(value, comp->il.opCodeForRegisterLoad(value->getDataType())); + TR::Node *regLoad = TR::Node::create(value, comp->il.opCodeForRegisterLoad(originalNode->getDataType())); regLoad->setRegLoadStoreSymbolReference(storeNode->getRegLoadStoreSymbolReference()); regLoad->setGlobalRegisterNumber(storeNode->getGlobalRegisterNumber()); unavailableRegisters.set(storeNode->getGlobalRegisterNumber()); @@ -1066,7 +1069,8 @@ static void gatherUnavailableRegisters(TR::Compilation *comp, TR::Node *regDeps, dep->getLowGlobalRegisterNumber() == nodeInfoEntry->second.second->getLowGlobalRegisterNumber() && dep->getHighGlobalRegisterNumber() == nodeInfoEntry->second.second->getHighGlobalRegisterNumber()) { - // Passthrough uses same register as the replacement, do not need to do anything + regDeps->setAndIncChild(i, nodeInfoEntry->second.second); + dep->recursivelyDecReferenceCount(); } else if (needToCreateRegStore && (!needToCheckStoreRegPostSplitPoint || !checkStoreRegNodeListForNode(dep, storeRegNodePostSplitPoint))) { @@ -1074,7 +1078,7 @@ static void gatherUnavailableRegisters(TR::Compilation *comp, TR::Node *regDeps, // In these cases we need to create a regStore for the PassThrough. // If we have replacement then need to store the replacement to register, else, value needs to be stored. TR::Node *nodeToBeStored = nodeInfoEntry->second.second != NULL ? nodeInfoEntry->second.second : value; - TR::Node *regStore = TR::Node::create(value, comp->il.opCodeForRegisterStore(value->getDataType()), 1, nodeToBeStored); + TR::Node *regStore = TR::Node::create(value, comp->il.opCodeForRegisterStore(originalNode->getDataType()), 1, nodeToBeStored); currentTT->insertBefore(TR::TreeTop::create(comp, regStore)); regStore->setGlobalRegisterNumber(dep->getGlobalRegisterNumber()); if (nodeToBeStored->requiresRegisterPair(comp)) diff --git a/compiler/optimizer/RegDepCopyRemoval.cpp b/compiler/optimizer/RegDepCopyRemoval.cpp index 7d6e6f2d2af..7165adf5f9c 100644 --- a/compiler/optimizer/RegDepCopyRemoval.cpp +++ b/compiler/optimizer/RegDepCopyRemoval.cpp @@ -98,6 +98,14 @@ TR::RegDepCopyRemoval::perform() processRegDeps(lastChild, tt); } } + else if (node->getOpCode().isStoreReg() + && node->getHighGlobalRegisterNumber() == static_cast(-1) + && (node->getType().isIntegral() || node->getType().isAddress())) + { + TR_GlobalRegisterNumber lowReg = node->getLowGlobalRegisterNumber(); + NodeChoice &choice = getNodeChoice(lowReg); + choice.regStoreNode = node; + } break; } } @@ -136,15 +144,17 @@ void TR::RegDepCopyRemoval::discardAllNodeChoices() { for (TR_GlobalRegisterNumber reg = _regBegin; reg < _regEnd; reg++) - discardNodeChoice(reg); + discardNodeChoice(reg , true); } void -TR::RegDepCopyRemoval::discardNodeChoice(TR_GlobalRegisterNumber reg) +TR::RegDepCopyRemoval::discardNodeChoice(TR_GlobalRegisterNumber reg, bool clearRegStore) { NodeChoice &choice = getNodeChoice(reg); choice.original = NULL; choice.selected = NULL; + if (clearRegStore) + choice.regStoreNode = NULL; } void @@ -218,10 +228,13 @@ TR::RegDepCopyRemoval::readRegDeps() continue; } - // Only process integral and address-type nodes; they'll go into GPRs + TR_GlobalRegisterNumber reg = depNode->getGlobalRegisterNumber(); TR::DataType depType = depValue->getType(); - if (!depType.isIntegral() && !depType.isAddress()) + NodeChoice &choice = getNodeChoice(reg); + // Only process integral and address-type nodes; they'll go into GPRs + // For the PassThrough Node, if the recorded regStore node does not have same child as depValue, we skip it. + if ((!depType.isIntegral() && !depType.isAddress()) || (choice.regStoreNode != NULL && choice.regStoreNode->getFirstChild() != depValue)) { ignoreRegister(reg); continue; @@ -408,9 +421,21 @@ TR::RegDepCopyRemoval::makeFreshCopy(TR_GlobalRegisterNumber reg) copyNode = TR::Node::create(TR::PassThrough, 1, dep.value); copyNode->setCopyToNewVirtualRegister(); } - - TR::Node *copyTreetopNode = TR::Node::create(TR::treetop, 1, copyNode); - _treetop->insertBefore(TR::TreeTop::create(comp(), copyTreetopNode)); + NodeChoice &choice = getNodeChoice(reg); + if (choice.regStoreNode == NULL) + { + // As we walk down in Extended Basic Block, for each register, if exists, we record a regStore node, if we do not have one found for given register, node should be regLoad. + TR_ASSERT_FATAL(dep.node->getOpCode().isLoadReg(), "Only PassThrough (with a corresponding regStore appeared before) or regLoad is expected as children of GlRegDeps, Unexpected Node is n%dn OpCode %s",dep.node->getGlobalIndex(), dep.node->getOpCode().getName()); + choice.regStoreNode = TR::Node::create(dep.node, comp()->il.opCodeForRegisterStore(dep.node->getDataType()), 1, copyNode); + _treetop->insertBefore(TR::TreeTop::create(comp(), choice.regStoreNode)); + choice.regStoreNode->setGlobalRegisterNumber(dep.node->getGlobalRegisterNumber()); + choice.regStoreNode->setRegLoadStoreSymbolReference(dep.node->getRegLoadStoreSymbolReference()); + } + else + { + choice.regStoreNode->setAndIncChild(0, copyNode); + dep.value->recursivelyDecReferenceCount(); + } if (trace()) traceMsg(comp(), "\tcopy is n%un\n", copyNode->getGlobalIndex()); diff --git a/compiler/optimizer/RegDepCopyRemoval.hpp b/compiler/optimizer/RegDepCopyRemoval.hpp index bf265b9ae75..a8597b01ced 100644 --- a/compiler/optimizer/RegDepCopyRemoval.hpp +++ b/compiler/optimizer/RegDepCopyRemoval.hpp @@ -97,6 +97,7 @@ class RegDepCopyRemoval : public TR::Optimization { TR::Node *original; TR::Node *selected; + TR::Node *regStoreNode; }; const char *registerName(TR_GlobalRegisterNumber reg); @@ -105,7 +106,7 @@ class RegDepCopyRemoval : public TR::Optimization NodeChoice &getNodeChoice(TR_GlobalRegisterNumber reg); void discardAllNodeChoices(); - void discardNodeChoice(TR_GlobalRegisterNumber reg); + void discardNodeChoice(TR_GlobalRegisterNumber reg, bool clearRegStore = false); void rememberNodeChoice(TR_GlobalRegisterNumber reg, TR::Node *selected); void processRegDeps(TR::Node *deps, TR::TreeTop *depTT);