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);