void TR::RegDepCopyRemoval::readRegDeps() { for (int i = 0; i < _regDeps->getNumChildren(); i++) { TR::Node *depNode = _regDeps->getChild(i); TR::Node *depValue = depNode; if (depValue->getOpCodeValue() == TR::PassThrough) { do depValue = depValue->getFirstChild(); while (depValue->getOpCodeValue() == TR::PassThrough); } else { TR_ASSERT(depNode->getOpCode().isLoadReg(), "invalid GlRegDeps child opcode n%un %s\n", depNode->getGlobalIndex(), depNode->getOpCode().getName()); } // Avoid register pairs for simplicity, at least for now bool isRegPairDep = depNode->getHighGlobalRegisterNumber() != (TR_GlobalRegisterNumber)-1; bool valueNeedsRegPair = comp()->nodeNeeds2Regs(depValue); TR_ASSERT(isRegPairDep == valueNeedsRegPair, "mismatch on number of registers required for n%un\n", depNode->getGlobalIndex()); if (isRegPairDep) { ignoreRegister(depNode->getLowGlobalRegisterNumber()); ignoreRegister(depNode->getHighGlobalRegisterNumber()); 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()) { ignoreRegister(reg); continue; } RegDepInfo &dep = getRegDepInfo(reg); TR_ASSERT(dep.state == REGDEP_ABSENT, "register %s is multiply-specified\n", registerName(reg)); dep.node = depNode; dep.value = depValue; dep.state = REGDEP_UNDECIDED; dep.childIndex = i; } }
uint8_t *TR::PPCArrayCopyCallSnippet::emitSnippetBody() { TR::Node *node = getNode(); TR_ASSERT(node->getOpCodeValue() == TR::arraycopy && node->getChild(2)->getOpCode().isLoadConst(), "only valid for arraycopies with a constant length\n"); uint8_t *buffer = cg()->getBinaryBufferCursor(); getSnippetLabel()->setCodeLocation(buffer); TR::RealRegister *lengthReg = cg()->machine()->getRealRegister(_lengthRegNum); TR::Node *lengthNode = node->getChild(2); int64_t byteLen = (lengthNode->getType().isInt32() ? lengthNode->getInt() : lengthNode->getLongInt()); TR::InstOpCode opcode; // li lengthReg, #byteLen opcode.setOpCodeValue(TR::InstOpCode::li); buffer = opcode.copyBinaryToBuffer(buffer); lengthReg->setRegisterFieldRT((uint32_t *)buffer); TR_ASSERT(byteLen <= UPPER_IMMED,"byteLen too big to encode\n"); *(int32_t *)buffer |= byteLen; buffer += 4; return TR::PPCHelperCallSnippet::genHelperCall(buffer); }
TR::Node * OMR::TransformUtil::scalarizeAddressParameter( TR::Compilation *comp, TR::Node *address, size_t byteLengthOrPrecision, // precision for BCD types and byteLength for all other types TR::DataType dataType, TR::SymbolReference *ref, bool store) { TR_ASSERT(ref,"symRef should not be NULL in scalarizeAddressParameter for address node %p\n",address); TR::Node * loadOrStore = NULL; #ifdef J9_PROJECT_SPECIFIC size_t byteLength = dataType.isBCD() ? TR::DataType::getSizeFromBCDPrecision(dataType, byteLengthOrPrecision) : byteLengthOrPrecision; #else size_t byteLength = byteLengthOrPrecision; #endif bool isLengthValidForDirect = false; if (address->getOpCodeValue() == TR::loadaddr && address->getOpCode().hasSymbolReference() && address->getSymbolReference() && !address->getSymbol()->isStatic()) { if (byteLength == address->getSymbol()->getSize()) isLengthValidForDirect = true; } if (address->getOpCodeValue() == TR::loadaddr && !address->getSymbol()->isStatic() && isLengthValidForDirect && address->getSymbolReference() == ref && ref->getSymbol()->getDataType() == dataType) { if (comp->getOption(TR_TraceScalarizeSSOps)) traceMsg(comp,"\n\tscalarizeAddressParameter auto direct case: address %p, dt %s\n",address,dataType.toString()); TR::ILOpCodes opcode = store ? comp->il.opCodeForDirectStore(dataType) : comp->il.opCodeForDirectLoad(dataType); loadOrStore = TR::Node::create(address, opcode, store ? 1 : 0); loadOrStore->setSymbolReference(ref); } else { TR::ILOpCodes opcode = store ? comp->il.opCodeForIndirectArrayStore(dataType) : comp->il.opCodeForIndirectArrayLoad(dataType); loadOrStore = TR::Node::create(address, opcode, store ? 2 : 1); loadOrStore->setSymbolReference(ref); loadOrStore->setAndIncChild(0, address); } if (byteLength == 8) { comp->getJittedMethodSymbol()->setMayHaveLongOps(true); } #ifdef J9_PROJECT_SPECIFIC if (loadOrStore->getType().isBCD()) { loadOrStore->setDecimalPrecision(byteLengthOrPrecision); } else #endif if (!store && loadOrStore->getType().isIntegral() && !loadOrStore->getType().isInt64()) { loadOrStore->setUnsigned(true); } return loadOrStore; }
// Checks for syntactic equivalence and returns the side-table index // of the syntactically equivalent node if it found one; else it returns // -1 signifying that this is the first time any node similar syntactically // to this node has been seen. Adds the node to the hash table if seen for the // first time. // // int TR_LocalAnalysisInfo::hasOldExpressionOnRhs(TR::Node *node, bool recalcContainsCall, bool storeLhsContainsCall) { // // Get the relevant portion of the subtree // for this node; this is different for a null check // as its null check reference is the only // sub-expression that matters // TR::Node *relevantSubtree = NULL; if (node->getOpCodeValue() == TR::NULLCHK) relevantSubtree = node->getNullCheckReference(); else relevantSubtree = node; // containsCall checks whether the relevant node has some // sub-expression that cannot be commoned, e.g. call or a new // bool nodeContainsCall; if (!recalcContainsCall && (relevantSubtree == node)) { // can use pre-calculated value of containsCall and storeLhsContainsCall, to avoid visitCount overflow nodeContainsCall = node->containsCall(); } else { storeLhsContainsCall = false; nodeContainsCall = containsCall(relevantSubtree, storeLhsContainsCall); } if (nodeContainsCall) { // // If the node is not a store, a call-like sub-expression is inadmissable; // if the node is a store, a call-like sub-expression is allowed on the RHS // of the store as this does not inhibit privatization in any way as // the private temp store's RHS simply points at original RHS. But if a call-like // sub-expression is present in the LHS of the store, that is inadmissable // if (!node->getOpCode().isStore() || storeLhsContainsCall) return 0; } bool seenIndirectStore = false; #ifdef J9_PROJECT_SPECIFIC bool seenIndirectBCDStore = false; #endif bool seenWriteBarrier = false; int32_t storeNumChildren = node->getNumChildren(); // If node is a null check, compare the // null check reference only to establish syntactic equivalence // if (node->getOpCodeValue() == TR::NULLCHK) /////if (node->getOpCode().isNullCheck()) { int32_t k; for (k=0;k<_numNullChecks;k++) { if (!(_nullCheckNodesAsArray[k] == NULL)) { if (areSyntacticallyEquivalent(_nullCheckNodesAsArray[k]->getNullCheckReference(), node->getNullCheckReference())) return _nullCheckNodesAsArray[k]->getLocalIndex(); } } _nullCheckNodesAsArray[_numNullChecks++] = node; } else { // // If this node is a global store, then equivalence check is different. // We try to give a store to field (or static) o.f the same index as // a load of o.f. This is so that privatization happens for fields/statics. // So the store's opcode value is changed temporarily to be a load before // syntactic equivalence is checked; this enables matching stores/loads to // same global symbol. // if (node->getOpCode().isStore() && !node->getSymbolReference()->getSymbol()->isAutoOrParm()) { if (node->getOpCode().isWrtBar()) seenWriteBarrier = true; #ifdef J9_PROJECT_SPECIFIC seenIndirectBCDStore = node->getType().isBCD(); #endif if (node->getOpCode().isStoreIndirect()) { if (seenWriteBarrier) { TR::Node::recreate(node, _compilation->il.opCodeForIndirectArrayLoad(node->getDataType())); } else { TR::Node::recreate(node, _compilation->il.opCodeForCorrespondingIndirectStore(node->getOpCodeValue())); } node->setNumChildren(1); } else { TR::Node::recreate(node, _compilation->il.opCodeForDirectLoad(node->getDataType())); node->setNumChildren(0); } #ifdef J9_PROJECT_SPECIFIC if (seenIndirectBCDStore) node->setBCDStoreIsTemporarilyALoad(true); #endif seenIndirectStore = true; } int32_t hashValue = _hashTable->hash(node); HashTable::Cursor cursor(_hashTable, hashValue); TR::Node *other; for (other = cursor.firstNode(); other; other = cursor.nextNode()) { // Convert other node's opcode to be a load temporarily // (only for syntactic equivalence check; see explanation above) // to enable matching global stores/loads. // bool seenOtherIndirectStore = false; #ifdef J9_PROJECT_SPECIFIC bool seenOtherIndirectBCDStore = false; #endif bool seenOtherWriteBarrier = false; int32_t otherStoreNumChildren = other->getNumChildren(); if (other->getOpCode().isStore() && !other->getSymbolReference()->getSymbol()->isAutoOrParm()) { if (other->getOpCode().isWrtBar()) seenOtherWriteBarrier = true; #ifdef J9_PROJECT_SPECIFIC seenOtherIndirectBCDStore = other->getType().isBCD(); #endif if (other->getOpCode().isStoreIndirect()) { if (seenOtherWriteBarrier) { TR::Node::recreate(other, _compilation->il.opCodeForIndirectArrayLoad(other->getDataType())); } else { TR::Node::recreate(other, _compilation->il.opCodeForCorrespondingIndirectStore(other->getOpCodeValue())); } other->setNumChildren(1); } else { TR::Node::recreate(other, _compilation->il.opCodeForDirectLoad(other->getDataType())); other->setNumChildren(0); } #ifdef J9_PROJECT_SPECIFIC if (seenOtherIndirectBCDStore) other->setBCDStoreIsTemporarilyALoad(true); #endif seenOtherIndirectStore = true; } bool areSame = areSyntacticallyEquivalent(node, other); // Restore the other node's state to what it was originally // (if it was a global store) // if (seenOtherWriteBarrier) { other->setNumChildren(otherStoreNumChildren); if (otherStoreNumChildren == 3) TR::Node::recreate(other, TR::awrtbari); else TR::Node::recreate(other, TR::awrtbar); } else if (seenOtherIndirectStore) { other->setNumChildren(otherStoreNumChildren); #ifdef J9_PROJECT_SPECIFIC if (seenOtherIndirectBCDStore) other->setBCDStoreIsTemporarilyALoad(false); #endif if (other->getOpCode().isIndirect()) TR::Node::recreate(other, _compilation->il.opCodeForCorrespondingIndirectLoad(other->getOpCodeValue())); else TR::Node::recreate(other, _compilation->il.opCodeForDirectStore(other->getDataType())); } if (areSame) { if (seenWriteBarrier) { node->setNumChildren(storeNumChildren); if (storeNumChildren == 3) TR::Node::recreate(node, TR::awrtbari); else TR::Node::recreate(node, TR::awrtbar); } else if (seenIndirectStore) { node->setNumChildren(storeNumChildren); #ifdef J9_PROJECT_SPECIFIC if (seenIndirectBCDStore) node->setBCDStoreIsTemporarilyALoad(false); #endif if (node->getOpCode().isIndirect()) TR::Node::recreate(node, _compilation->il.opCodeForCorrespondingIndirectLoad(node->getOpCodeValue())); else TR::Node::recreate(node, _compilation->il.opCodeForDirectStore(node->getDataType())); } return other->getLocalIndex(); } } // No match from existing nodes in the hash table; // add this node to the hash table. // _hashTable->add(node, hashValue); } // Restore this node's state to what it was before // (if it was a global store) // if (seenWriteBarrier) { node->setNumChildren(storeNumChildren); if (storeNumChildren == 3) TR::Node::recreate(node, TR::awrtbari); else TR::Node::recreate(node, TR::awrtbar); } else if (seenIndirectStore) { node->setNumChildren(storeNumChildren); #ifdef J9_PROJECT_SPECIFIC if (seenIndirectBCDStore) node->setBCDStoreIsTemporarilyALoad(false); #endif if (node->getOpCode().isIndirect()) TR::Node::recreate(node, _compilation->il.opCodeForCorrespondingIndirectLoad(node->getOpCodeValue())); else TR::Node::recreate(node, _compilation->il.opCodeForDirectStore(node->getDataType())); } return -1; }