// Volatile memory operands are not allowed in long subtractions // if we are compiling for an SMP machine, as the carry flag can // get clobbered by the memory barrier immediately preceding the // SBB4RegMem instruction. // static bool isVolatileMemoryOperand(TR::Node *node) { if (TR::Compiler->target.isSMP() && node->getOpCode().isMemoryReference()) { TR_ASSERT(node->getSymbolReference(), "expecting a symbol reference\n"); TR::Symbol *sym = node->getSymbolReference()->getSymbol(); return (sym && sym->isVolatile()); } return false; }
bool OMR::SymbolReference::storeCanBeRemoved() { TR::Compilation *comp = TR::comp(); TR::Symbol * s = self()->getSymbol(); return !s->isVolatile() && (((s->getDataType() != TR::Double) && (s->getDataType() != TR::Float)) || comp->cg()->getSupportsJavaFloatSemantics() || (self()->isTemporary(comp) && !s->behaveLikeNonTemp())); }
bool checkMethodSignature(TR::ValuePropagation *vp, TR::SymbolReference *symRef, const char *sig) { TR::Symbol *symbol = symRef->getSymbol(); if (!symbol->isResolvedMethod()) return false; TR::ResolvedMethodSymbol *method = symbol->castToResolvedMethodSymbol(); if (!method) return false; if (strncmp(method->getResolvedMethod()->signature(vp->trMemory()), sig, strlen(sig)) == 0) return true; return false; }
void TR_ReachingDefinitions::initializeGenAndKillSetInfoForNode(TR::Node *node, TR_UseDefInfo::BitVector &defsKilled, bool seenException, int32_t blockNum, TR::Node *parent) { // Update gen and kill info for nodes in this subtree // int32_t i; if (node->getVisitCount() == comp()->getVisitCount()) return; node->setVisitCount(comp()->getVisitCount()); // Process the children first // for (i = node->getNumChildren()-1; i >= 0; --i) { initializeGenAndKillSetInfoForNode(node->getChild(i), defsKilled, seenException, blockNum, node); } bool irrelevantStore = false; scount_t nodeIndex = node->getLocalIndex(); if (nodeIndex <= 0) { if (node->getOpCode().isStore() && node->getSymbol()->isAutoOrParm() && node->storedValueIsIrrelevant()) { irrelevantStore = true; } else return; } bool foundDefsToKill = false; int32_t numDefNodes = 0; defsKilled.Clear(); TR::ILOpCode &opCode = node->getOpCode(); TR::SymbolReference *symRef; TR::Symbol *sym; uint16_t symIndex; uint32_t num_aliases; if (_useDefInfo->_useDefForRegs && (opCode.isLoadReg() || opCode.isStoreReg())) { sym = NULL; symRef = NULL; symIndex = _useDefInfo->getNumSymbols() + node->getGlobalRegisterNumber(); num_aliases = 1; } else { symRef = node->getSymbolReference(); sym = symRef->getSymbol(); symIndex = symRef->getSymbol()->getLocalIndex(); num_aliases = _useDefInfo->getNumAliases(symRef, _aux); } if (symIndex == NULL_USEDEF_SYMBOL_INDEX || node->getOpCode().isCall() || node->getOpCode().isFence() || (parent && parent->getOpCode().isResolveCheck() && num_aliases > 1)) { // A call or unresolved reference is a definition of all // symbols it is aliased with // numDefNodes = num_aliases; //for all symbols that are a mustdef of a call, kill defs of those symbols if (node->getOpCode().isCall()) foundDefsToKill = false; } else if (irrelevantStore || _useDefInfo->isExpandedDefIndex(nodeIndex)) { // DefOnly node defines all symbols it is aliased with // UseDef node(load) defines only the symbol itself // if (!irrelevantStore) { numDefNodes = num_aliases; numDefNodes = _useDefInfo->isExpandedUseDefIndex(nodeIndex) ? 1 : numDefNodes; if (!_useDefInfo->getDefsForSymbolIsZero(symIndex, _aux) && (!sym || (!sym->isShadow() && !sym->isMethod()))) { foundDefsToKill = true; // defsKilled ORed with defsForSymbol(symIndex); _useDefInfo->getDefsForSymbol(defsKilled, symIndex, _aux); } if (node->getOpCode().isStoreIndirect()) { int32_t memSymIndex = _useDefInfo->getMemorySymbolIndex(node); if (memSymIndex != -1 && !_useDefInfo->getDefsForSymbolIsZero(memSymIndex, _aux)) { foundDefsToKill = true; // defsKilled ORed with defsForSymbol(symIndex); _useDefInfo->getDefsForSymbol(defsKilled, memSymIndex, _aux); } } } else if (!_useDefInfo->getDefsForSymbolIsZero(symIndex, _aux)) { numDefNodes = 1; foundDefsToKill = true; // defsKilled ORed with defsForSymbol(symIndex); _useDefInfo->getDefsForSymbol(defsKilled, symIndex, _aux); } } else { numDefNodes = 0; } if (foundDefsToKill) { if (_regularKillSetInfo[blockNum] == NULL) allocateContainer(&_regularKillSetInfo[blockNum]); *_regularKillSetInfo[blockNum] |= defsKilled; if (!seenException) { if (_exceptionKillSetInfo[blockNum] == NULL) allocateContainer(&_exceptionKillSetInfo[blockNum]); *_exceptionKillSetInfo[blockNum] |= defsKilled; } } if (_regularGenSetInfo[blockNum] == NULL) allocateContainer(&_regularGenSetInfo[blockNum]); else if (foundDefsToKill) *_regularGenSetInfo[blockNum] -= defsKilled; if (_exceptionGenSetInfo[blockNum] == NULL) allocateContainer(&_exceptionGenSetInfo[blockNum]); else if (foundDefsToKill && !seenException) *_exceptionGenSetInfo[blockNum] -= defsKilled; if (!irrelevantStore) { for (i = 0; i < numDefNodes; ++i) { _regularGenSetInfo[blockNum]->set(nodeIndex+i); _exceptionGenSetInfo[blockNum]->set(nodeIndex+i); } } else // fake up the method entry def as the def index to "gen" to avoid a use without a def completely { _regularGenSetInfo[blockNum]->set(sym->getLocalIndex()); _exceptionGenSetInfo[blockNum]->set(sym->getLocalIndex()); } }
TR_BitVector * addVeryRefinedCallAliasSets(TR::ResolvedMethodSymbol * methodSymbol, TR_BitVector * aliases, List<void> * methodsPeeked) { TR::Compilation *comp = TR::comp(); void * methodId = methodSymbol->getResolvedMethod()->getPersistentIdentifier(); if (methodsPeeked->find(methodId)) { // This can't be allocated into the alias region as it must be accessed across optimizations TR_BitVector *heapAliases = new (comp->trHeapMemory()) TR_BitVector(comp->getSymRefCount(), comp->trMemory(), heapAlloc, growable); *heapAliases |= *aliases; return heapAliases; } // stop if the peek is getting very deep // if (methodsPeeked->getSize() >= PEEK_THRESHOLD) return 0; methodsPeeked->add(methodId); dumpOptDetails(comp, "O^O REFINING ALIASES: Peeking into the IL to refine aliases \n"); if (!methodSymbol->getResolvedMethod()->genMethodILForPeeking(methodSymbol, comp, true)) return 0; TR::SymbolReferenceTable * symRefTab = comp->getSymRefTab(); for (TR::TreeTop * tt = methodSymbol->getFirstTreeTop(); tt; tt = tt->getNextTreeTop()) { TR::Node *node = tt->getNode(); if (node->getOpCode().isResolveCheck()) return 0; if ((node->getOpCodeValue() == TR::treetop) || (node->getOpCodeValue() == TR::compressedRefs) || node->getOpCode().isCheck()) node = node->getFirstChild(); if (node->getOpCode().isStore()) { TR::SymbolReference * symRefInCallee = node->getSymbolReference(), * symRefInCaller; TR::Symbol * symInCallee = symRefInCallee->getSymbol(); TR::DataType type = symInCallee->getDataType(); if (symInCallee->isShadow()) { if (symInCallee->isArrayShadowSymbol()) symRefInCaller = symRefTab->getSymRef(symRefTab->getArrayShadowIndex(type)); else if (symInCallee->isArrayletShadowSymbol()) symRefInCaller = symRefTab->getSymRef(symRefTab->getArrayletShadowIndex(type)); else symRefInCaller = symRefTab->findShadowSymbol(symRefInCallee->getOwningMethod(comp), symRefInCallee->getCPIndex(), type); if (symRefInCaller) { if (symRefInCaller->reallySharesSymbol(comp)) symRefInCaller->setSharedShadowAliases(aliases, symRefTab); aliases->set(symRefInCaller->getReferenceNumber()); } } else if (symInCallee->isStatic()) { symRefInCaller = symRefTab->findStaticSymbol(symRefInCallee->getOwningMethod(comp), symRefInCallee->getCPIndex(), type); if (symRefInCaller) { if (symRefInCaller->reallySharesSymbol(comp)) symRefInCaller->setSharedStaticAliases(aliases, symRefTab); else aliases->set(symRefInCaller->getReferenceNumber()); } } } else if (node->getOpCode().isCall()) { if (node->getOpCode().isCallIndirect()) return 0; TR::ResolvedMethodSymbol * calleeSymbol = node->getSymbol()->getResolvedMethodSymbol(); if (!calleeSymbol) return 0; TR_ResolvedMethod * calleeMethod = calleeSymbol->getResolvedMethod(); if (!calleeMethod->isCompilable(comp->trMemory()) || calleeMethod->isJNINative()) return 0; if (!addVeryRefinedCallAliasSets(calleeSymbol, aliases, methodsPeeked)) return 0; } else if (node->getOpCodeValue() == TR::monent) return 0; } // This can't be allocated into the alias region as it must be accessed across optimizations TR_BitVector *heapAliases = new (comp->trHeapMemory()) TR_BitVector(comp->getSymRefCount(), comp->trMemory(), heapAlloc, growable); *heapAliases |= *aliases; return heapAliases; }
static int cacheStringAppend(TR::ValuePropagation *vp,TR::Node *node) { return 0; if (!vp->lastTimeThrough()) return 0; TR::TreeTop *tt = vp->_curTree; TR::TreeTop *newTree = tt; TR::TreeTop *startTree = 0; TR::TreeTop *exitTree = vp->_curBlock->getExit(); TR::Node *newBuffer; if(node->getNumChildren() >= 1) newBuffer = node->getFirstChild(); else return 0; enum {MAX_STRINGS = 2}; int initWithString = 0; bool initWithInteger = false; TR::TreeTop *appendTree[MAX_STRINGS+1]; TR::Node *appendedString[MAX_STRINGS+1]; char pattern[MAX_STRINGS+1]; int stringCount = 0; bool useStringBuffer=false; TR::SymbolReference *valueOfSymRef[MAX_STRINGS+1]; bool success = false; char *sigBuffer="java/lang/StringBuffer.<init>("; char *sigBuilder = "java/lang/StringBuilder.<init>("; char *sigInit = "java/lang/String.<init>("; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// if (checkMethodSignature(vp,node->getSymbolReference(), sigInit)) { TR::Symbol *symbol =node->getSymbolReference()->getSymbol(); TR_ResolvedMethod *m = symbol->castToResolvedMethodSymbol()->getResolvedMethod(); if (strncmp(m->signatureChars(), "(Ljava/lang/String;Ljava/lang/String;)V", m->signatureLength())==0) { vp->_cachedStringPeepHolesVcalls.add(new (vp->comp()->trStackMemory()) TR::ValuePropagation::VPTreeTopPair(tt,tt->getPrevRealTreeTop())); } } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// if (checkMethodSignature(vp,node->getSymbolReference(), sigBuffer)) { useStringBuffer=true; success = true; } else if (checkMethodSignature(vp,node->getSymbolReference(), sigBuilder)) { success = true; useStringBuffer=false; } else { return 0; } if (success) { TR::Symbol *symbol =node->getSymbolReference()->getSymbol(); TR_ResolvedMethod *m = symbol->castToResolvedMethodSymbol()->getResolvedMethod(); if (strncmp(m->signatureChars(), "()V", m->signatureLength())==0) { // Diagnostics }else { return 0; } } else // <init> not found (could be unresolved) { return 0; } // now search for StringBuffer.append calls that are chained to one another TR::TreeTop *lastAppendTree = 0; // updated when we find an append TR::Node *child = newBuffer; while (1) { startTree = tt->getNextRealTreeTop(); appendedString[stringCount] = 0; int visitCount = 0; if (useStringBuffer) tt = searchForStringAppend(vp,"java/lang/StringBuffer.append(", startTree, exitTree, TR::acall, child, visitCount, appendedString + stringCount); else tt = searchForStringAppend(vp,"java/lang/StringBuilder.append(", startTree, exitTree, TR::acall, child, visitCount, appendedString + stringCount); if (appendedString[stringCount]) // we found it { appendTree[stringCount] = tt; // we could exit here if too many appends are chained if (stringCount >= MAX_STRINGS) return 0; // see which type of append we have TR::Symbol *symbol = tt->getNode()->getFirstChild()->getSymbolReference()->getSymbol(); TR_ASSERT(symbol->isResolvedMethod(), "assertion failure"); TR::ResolvedMethodSymbol *method = symbol->castToResolvedMethodSymbol(); TR_ASSERT(method, "assertion failure"); TR_ResolvedMethod *m = method->getResolvedMethod(); if (strncmp(m->signatureChars(), "(Ljava/lang/String;)", 20)==0) { pattern[stringCount] = 'S'; valueOfSymRef[stringCount] = 0; // don't need conversion to string } else // appending something that needs conversion using valueOf { TR::SymbolReference *symRefForValueOf = 0; // In the following we can vp->compare only (C) because we know that // StringBuffer.append returns a StringBuffer. //s char *sigBuffer = m->signatureChars(); TR_ASSERT(m->signatureLength() >= 3, "The minimum signature length should be 3 for ()V"); } stringCount++; } else // the chain of appends is broken { appendTree[stringCount] = 0; pattern[stringCount] = 0; // string terminator break; } lastAppendTree = tt; child = tt->getNode()->getFirstChild(); // the first node is a NULLCHK and its child is the call } // end while if (stringCount < 2) return 0; // cannot apply StringPeepholes if (stringCount > MAX_STRINGS) return 0; if (stringCount == 3) return 0; // same as above TR_ASSERT(lastAppendTree, "If stringCount <=2 then we must have found an append"); // now look for the toString call TR::TreeTop *toStringTree = 0; //visitCount = vp->comp()->incVisitCount(); int visitCount=0; tt = searchForToStringCall(vp,lastAppendTree->getNextRealTreeTop(), exitTree, lastAppendTree->getNode()->getFirstChild(), visitCount, &toStringTree, useStringBuffer); if (!toStringTree) return 0; vp->_cachedStringBufferVcalls.add(new (vp->comp()->trStackMemory()) TR::ValuePropagation::VPStringCached(appendTree[0],appendTree[1],appendedString[0],appendedString[1],newTree,toStringTree)); }