void TR_LocalLiveRangeReduction::initPotentialDeps(TR_TreeRefInfo *tree) { int32_t symRefCount = comp()->getSymRefCount(); if (tree->getDefSym() == NULL) tree->setDefSym(new (trStackMemory()) TR_BitVector(symRefCount, trMemory(), stackAlloc)); if (tree->getUseSym() == NULL) tree->setUseSym(new (trStackMemory()) TR_BitVector(symRefCount, trMemory(), stackAlloc)); }
void TR_ReachingBlocks::initializeGenAndKillSetInfo() { // For each block in the CFG build the gen and kill set for this analysis. // Go in treetop order, which guarantees that we see the correct (i.e. first) // evaluation point for each node. // int32_t blockNum; for (blockNum = 0; blockNum < _numberOfBlocks; blockNum++) { _regularGenSetInfo[blockNum] = new (trStackMemory()) TR_BitVector(getNumberOfBits(),trMemory(), stackAlloc); _regularGenSetInfo[blockNum]->set(blockNum); _exceptionGenSetInfo[blockNum] = new (trStackMemory()) TR_BitVector(getNumberOfBits(),trMemory(), stackAlloc); _exceptionGenSetInfo[blockNum]->set(blockNum); } }
void TR_RegisterAnticipatability::initializeRegisterUsageInfo() { // initialize outSets bitvector as well // TR_BitVector **originalRegUsageInfo = _registerUsageInfo; _registerUsageInfo = (TR_BitVector **) trMemory()->allocateStackMemory(_numberOfNodes * sizeof(TR_BitVector *)); _outSetInfo = (TR_BitVector **) trMemory()->allocateStackMemory(_numberOfNodes * sizeof(TR_BitVector *)); for (int32_t i = 0; i < _numberOfNodes; i++) { _registerUsageInfo[i] = new (trStackMemory()) TR_BitVector(_numberOfBits, trMemory(), stackAlloc); copyFromInto(originalRegUsageInfo[i], _registerUsageInfo[i]); _outSetInfo[i] = new (trStackMemory()) TR_BitVector(_numberOfBits, trMemory(), stackAlloc); _outSetInfo[i]->empty(); } }
bool TR_DominatorVerifier::isExpensiveAlgorithmCorrect(TR_DominatorsChk &expensiveAlgorithm) { int32_t i,j; _nodesSeenOnEveryPath = new (trStackMemory()) TR_BitVector(_numBlocks,trMemory(), stackAlloc); _nodesSeenOnCurrentPath = new (trStackMemory()) TR_BitVector(_numBlocks,trMemory(), stackAlloc); _dominatorsChkInfo = expensiveAlgorithm.getDominatorsChkInfo(); for (i = 2; i < _numBlocks-1; i++) { TR_BitVector *bucket = _dominatorsChkInfo[i]._tmpbucket; for (j = 0; j < _numBlocks-1; j++) { if (bucket->get(j)) // dominator according to algorithm { // Initializing these BitVectors before checking // dominators for the next block. // The last bit is not changed for either bit vector - is that what // was intended? // _nodesSeenOnEveryPath->setAll(_numBlocks-1); int32_t lastBit = _nodesSeenOnCurrentPath->get(_numBlocks-1); _nodesSeenOnCurrentPath->empty(); if (lastBit) _nodesSeenOnCurrentPath->set(_numBlocks-1); if ( ! dominates(_dominatorsChkInfo[j+1]._block,_dominatorsChkInfo[i]._block) ) // dominator according to the CFG { if (debug("traceVER")) { dumpOptDetails(comp(), " Dominator info for expensive algorithm is incorrect \n"); dumpOptDetails(comp(), " Dominator of [%p] is [%p] as per the algorithm\n", _dominatorsChkInfo[i]._block, _dominatorsChkInfo[j+1]._block); dumpOptDetails(comp(), " But [%p] is not an the dominator of [%p] as per the Control Flow Graph", _dominatorsChkInfo[j+1]._block, _dominatorsChkInfo[i]._block); } return false; } } } } return true; }
//---------------------------- collecting ref info at the beginning ----------------------------------------- void TR_LocalLiveRangeReduction::collectInfo(TR::TreeTop *entryTree,TR::TreeTop *exitTree) { TR::TreeTop *currentTree = entryTree; TR_TreeRefInfo *treeRefInfo; int32_t i = 0; int32_t maxRefCount = 0; vcount_t visitCount = comp()->getVisitCount(); while (!(currentTree == exitTree)) { treeRefInfo = new (trStackMemory()) TR_TreeRefInfo(currentTree, trMemory()); collectRefInfo(treeRefInfo, currentTree->getNode(),visitCount,&maxRefCount); _treesRefInfoArray[i++] = treeRefInfo; initPotentialDeps(treeRefInfo); treeRefInfo->resetSyms(); populatePotentialDeps(treeRefInfo,treeRefInfo->getTreeTop()->getNode()); currentTree = currentTree->getNextTreeTop(); } comp()->setVisitCount(visitCount+maxRefCount); }
//add pair into dependant list void TR_LocalLiveRangeReduction::addDepPair(TR_TreeRefInfo *dep,TR_TreeRefInfo *anchor) { DepPair *depPair = new (trStackMemory()) DepPair(dep,anchor); _depPairList.add(depPair); }
bool TR_LocalLiveRangeReduction::moveTreeBefore(TR_TreeRefInfo *treeToMove,TR_TreeRefInfo *anchor,int32_t passNumber) { TR::TreeTop *treeToMoveTT = treeToMove->getTreeTop(); TR::TreeTop *anchorTT = anchor->getTreeTop(); if (treeToMoveTT->getNextRealTreeTop() == anchorTT) { addDepPair(treeToMove, anchor); return false; } if (!performTransformation(comp(), "%sPass %d: moving tree [%p] before Tree %p\n", OPT_DETAILS, passNumber, treeToMoveTT->getNode(),anchorTT->getNode())) return false; // printf("Moving [%p] before Tree %p\n", treeToMoveTT->getNode(),anchorTT->getNode()); //changing location in block TR::TreeTop *origPrevTree = treeToMoveTT->getPrevTreeTop(); TR::TreeTop *origNextTree = treeToMoveTT->getNextTreeTop(); origPrevTree->setNextTreeTop(origNextTree); origNextTree->setPrevTreeTop(origPrevTree); TR::TreeTop *prevTree = anchorTT->getPrevTreeTop(); anchorTT->setPrevTreeTop(treeToMoveTT); treeToMoveTT->setNextTreeTop(anchorTT); treeToMoveTT->setPrevTreeTop(prevTree); prevTree->setNextTreeTop(treeToMoveTT); //UPDATE REFINFO //find locations of treeTops in TreeTopsRefInfo array //startIndex points to the currentTree that has moved //endIndex points to the treeTop after which we moved the tree (nextTree) int32_t startIndex = getIndexInArray(treeToMove); int32_t endIndex = getIndexInArray(anchor)-1; int32_t i=0; for ( i = startIndex+1; i<= endIndex ; i++) { TR_TreeRefInfo *currentTreeRefInfo = _treesRefInfoArray[i]; List<TR::Node> *firstList = currentTreeRefInfo->getFirstRefNodesList(); List<TR::Node> *midList = currentTreeRefInfo->getMidRefNodesList(); List<TR::Node> *lastList = currentTreeRefInfo->getLastRefNodesList(); List<TR::Node> *M_firstList = treeToMove->getFirstRefNodesList(); List<TR::Node> *M_midList = treeToMove->getMidRefNodesList(); List<TR::Node> *M_lastList = treeToMove->getLastRefNodesList(); if (trace()) { traceMsg(comp(),"Before move:\n"); printRefInfo(treeToMove); printRefInfo(currentTreeRefInfo); } updateRefInfo(treeToMove->getTreeTop()->getNode(), currentTreeRefInfo, treeToMove , false); treeToMove->resetSyms(); currentTreeRefInfo->resetSyms(); populatePotentialDeps(currentTreeRefInfo,currentTreeRefInfo->getTreeTop()->getNode()); populatePotentialDeps(treeToMove,treeToMove->getTreeTop()->getNode()); if (trace()) { traceMsg(comp(),"After move:\n"); printRefInfo(treeToMove); printRefInfo(currentTreeRefInfo); traceMsg(comp(),"------------------------\n"); } } TR_TreeRefInfo *temp = _treesRefInfoArray[startIndex]; for (i = startIndex; i< endIndex ; i++) { _treesRefInfoArray[i] = _treesRefInfoArray[i+1]; } _treesRefInfoArray[endIndex]=temp; #if defined(DEBUG) || defined(PROD_WITH_ASSUMES) if (!(comp()->getOption(TR_EnableParanoidOptCheck) || debug("paranoidOptCheck"))) return true; //verifier { TR::StackMemoryRegion stackMemoryRegion(*trMemory()); vcount_t visitCount = comp()->getVisitCount(); int32_t maxRefCount = 0; TR::TreeTop *tt; TR_TreeRefInfo **treesRefInfoArrayTemp = (TR_TreeRefInfo**)trMemory()->allocateStackMemory(_numTreeTops*sizeof(TR_TreeRefInfo*)); memset(treesRefInfoArrayTemp, 0, _numTreeTops*sizeof(TR_TreeRefInfo*)); TR_TreeRefInfo *treeRefInfoTemp; //collect info for ( int32_t i = 0; i<_numTreeTops-1; i++) { tt =_treesRefInfoArray[i]->getTreeTop(); treeRefInfoTemp = new (trStackMemory()) TR_TreeRefInfo(tt, trMemory()); collectRefInfo(treeRefInfoTemp, tt->getNode(),visitCount,&maxRefCount); treesRefInfoArrayTemp[i] = treeRefInfoTemp; } comp()->setVisitCount(visitCount+maxRefCount); for ( int32_t i = 0; i<_numTreeTops-1; i++) { if (!verifyRefInfo(treesRefInfoArrayTemp[i]->getFirstRefNodesList(),_treesRefInfoArray[i]->getFirstRefNodesList())) { printOnVerifyError(_treesRefInfoArray[i],treesRefInfoArrayTemp[i]); TR_ASSERT(0,"fail to verify firstRefNodesList for %p\n",_treesRefInfoArray[i]->getTreeTop()->getNode()); } if (!verifyRefInfo(treesRefInfoArrayTemp[i]->getMidRefNodesList(),_treesRefInfoArray[i]->getMidRefNodesList())) { printOnVerifyError(_treesRefInfoArray[i],treesRefInfoArrayTemp[i]); TR_ASSERT(0,"fail to verify midRefNodesList for %p\n",_treesRefInfoArray[i]->getTreeTop()->getNode()); } if (!verifyRefInfo(treesRefInfoArrayTemp[i]->getLastRefNodesList(),_treesRefInfoArray[i]->getLastRefNodesList())) { printOnVerifyError(_treesRefInfoArray[i],treesRefInfoArrayTemp[i]); TR_ASSERT(0,"fail to verify lastRefNodesList for %p\n",_treesRefInfoArray[i]->getTreeTop()->getNode()); } } } // scope of the stack memory region #endif return true; }
void TR_LocalLiveRangeReduction::prePerformOnBlocks() { comp()->incVisitCount(); int32_t symRefCount = comp()->getSymRefCount(); _temp = new (trStackMemory()) TR_BitVector(symRefCount, trMemory(), stackAlloc); }
int32_t TR::ARM64SystemLinkage::buildArgs(TR::Node *callNode, TR::RegisterDependencyConditions *dependencies) { const TR::ARM64LinkageProperties &properties = getProperties(); TR::ARM64MemoryArgument *pushToMemory = NULL; TR::Register *argMemReg; TR::Register *tempReg; int32_t argIndex = 0; int32_t numMemArgs = 0; int32_t argSize = 0; int32_t numIntegerArgs = 0; int32_t numFloatArgs = 0; int32_t totalSize; int32_t i; TR::Node *child; TR::DataType childType; TR::DataType resType = callNode->getType(); uint32_t firstArgumentChild = callNode->getFirstArgumentIndex(); /* Step 1 - figure out how many arguments are going to be spilled to memory i.e. not in registers */ for (i = firstArgumentChild; i < callNode->getNumChildren(); i++) { child = callNode->getChild(i); childType = child->getDataType(); switch (childType) { case TR::Int8: case TR::Int16: case TR::Int32: case TR::Int64: case TR::Address: if (numIntegerArgs >= properties.getNumIntArgRegs()) numMemArgs++; numIntegerArgs++; break; case TR::Float: case TR::Double: if (numFloatArgs >= properties.getNumFloatArgRegs()) numMemArgs++; numFloatArgs++; break; default: TR_ASSERT(false, "Argument type %s is not supported\n", childType.toString()); } } // From here, down, any new stack allocations will expire / die when the function returns TR::StackMemoryRegion stackMemoryRegion(*trMemory()); /* End result of Step 1 - determined number of memory arguments! */ if (numMemArgs > 0) { pushToMemory = new (trStackMemory()) TR::ARM64MemoryArgument[numMemArgs]; argMemReg = cg()->allocateRegister(); } totalSize = numMemArgs * 8; // align to 16-byte boundary totalSize = (totalSize + 15) & (~15); numIntegerArgs = 0; numFloatArgs = 0; for (i = firstArgumentChild; i < callNode->getNumChildren(); i++) { TR::MemoryReference *mref = NULL; TR::Register *argRegister; TR::InstOpCode::Mnemonic op; child = callNode->getChild(i); childType = child->getDataType(); switch (childType) { case TR::Int8: case TR::Int16: case TR::Int32: case TR::Int64: case TR::Address: if (childType == TR::Address) argRegister = pushAddressArg(child); else if (childType == TR::Int64) argRegister = pushLongArg(child); else argRegister = pushIntegerWordArg(child); if (numIntegerArgs < properties.getNumIntArgRegs()) { if (!cg()->canClobberNodesRegister(child, 0)) { if (argRegister->containsCollectedReference()) tempReg = cg()->allocateCollectedReferenceRegister(); else tempReg = cg()->allocateRegister(); generateMovInstruction(cg(), callNode, tempReg, argRegister); argRegister = tempReg; } if (numIntegerArgs == 0 && (resType.isAddress() || resType.isInt32() || resType.isInt64())) { TR::Register *resultReg; if (resType.isAddress()) resultReg = cg()->allocateCollectedReferenceRegister(); else resultReg = cg()->allocateRegister(); dependencies->addPreCondition(argRegister, TR::RealRegister::x0); dependencies->addPostCondition(resultReg, TR::RealRegister::x0); } else { addDependency(dependencies, argRegister, properties.getIntegerArgumentRegister(numIntegerArgs), TR_GPR, cg()); } } else { // numIntegerArgs >= properties.getNumIntArgRegs() if (childType == TR::Address || childType == TR::Int64) { op = TR::InstOpCode::strpostx; } else { op = TR::InstOpCode::strpostw; } mref = getOutgoingArgumentMemRef(argMemReg, argRegister, op, pushToMemory[argIndex++]); argSize += 8; // always 8-byte aligned } numIntegerArgs++; break; case TR::Float: case TR::Double: if (childType == TR::Float) argRegister = pushFloatArg(child); else argRegister = pushDoubleArg(child); if (numFloatArgs < properties.getNumFloatArgRegs()) { if (!cg()->canClobberNodesRegister(child, 0)) { tempReg = cg()->allocateRegister(TR_FPR); op = (childType == TR::Float) ? TR::InstOpCode::fmovs : TR::InstOpCode::fmovd; generateTrg1Src1Instruction(cg(), op, callNode, tempReg, argRegister); argRegister = tempReg; } if ((numFloatArgs == 0 && resType.isFloatingPoint())) { TR::Register *resultReg; if (resType.getDataType() == TR::Float) resultReg = cg()->allocateSinglePrecisionRegister(); else resultReg = cg()->allocateRegister(TR_FPR); dependencies->addPreCondition(argRegister, TR::RealRegister::v0); dependencies->addPostCondition(resultReg, TR::RealRegister::v0); } else { addDependency(dependencies, argRegister, properties.getFloatArgumentRegister(numFloatArgs), TR_FPR, cg()); } } else { // numFloatArgs >= properties.getNumFloatArgRegs() if (childType == TR::Double) { op = TR::InstOpCode::vstrpostd; } else { op = TR::InstOpCode::vstrposts; } mref = getOutgoingArgumentMemRef(argMemReg, argRegister, op, pushToMemory[argIndex++]); argSize += 8; // always 8-byte aligned } numFloatArgs++; break; } // end of switch } // end of for // NULL deps for non-preserved and non-system regs while (numIntegerArgs < properties.getNumIntArgRegs()) { if (numIntegerArgs == 0 && resType.isAddress()) { dependencies->addPreCondition(cg()->allocateRegister(), properties.getIntegerArgumentRegister(0)); dependencies->addPostCondition(cg()->allocateCollectedReferenceRegister(), properties.getIntegerArgumentRegister(0)); } else { addDependency(dependencies, NULL, properties.getIntegerArgumentRegister(numIntegerArgs), TR_GPR, cg()); } numIntegerArgs++; } int32_t floatRegsUsed = (numFloatArgs > properties.getNumFloatArgRegs()) ? properties.getNumFloatArgRegs() : numFloatArgs; for (i = (TR::RealRegister::RegNum)((uint32_t)TR::RealRegister::v0 + floatRegsUsed); i <= TR::RealRegister::LastFPR; i++) { if (!properties.getPreserved((TR::RealRegister::RegNum)i)) { // NULL dependency for non-preserved regs addDependency(dependencies, NULL, (TR::RealRegister::RegNum)i, TR_FPR, cg()); } } if (numMemArgs > 0) { TR::RealRegister *sp = cg()->machine()->getRealRegister(properties.getStackPointerRegister()); generateTrg1Src1ImmInstruction(cg(), TR::InstOpCode::subimmx, callNode, argMemReg, sp, totalSize); for (argIndex = 0; argIndex < numMemArgs; argIndex++) { TR::Register *aReg = pushToMemory[argIndex].argRegister; generateMemSrc1Instruction(cg(), pushToMemory[argIndex].opCode, callNode, pushToMemory[argIndex].argMemory, aReg); cg()->stopUsingRegister(aReg); } cg()->stopUsingRegister(argMemReg); } return totalSize; }
TR_ExpressionsSimplification::LoopInfo* TR_ExpressionsSimplification::findLoopInfo(TR_RegionStructure* region) { ListIterator<TR::CFGEdge> exitEdges(®ion->getExitEdges()); if (region->getExitEdges().getSize() != 1) { if (trace()) traceMsg(comp(), "Region with more than 1 exit edges can't be handled\n"); return 0; } TR_StructureSubGraphNode* exitNode = toStructureSubGraphNode(exitEdges.getFirst()->getFrom()); if (!exitNode->getStructure()->asBlock()) { if (trace()) traceMsg(comp(), "The exit block can't be found\n"); return 0; } TR::Block *exitBlock = exitNode->getStructure()->asBlock()->getBlock(); TR::Node *lastTreeInExitBlock = exitBlock->getLastRealTreeTop()->getNode(); if (trace()) { traceMsg(comp(), "The exit block is %d\n", exitBlock->getNumber()); traceMsg(comp(), "The branch node is %p\n", lastTreeInExitBlock); } if (!lastTreeInExitBlock->getOpCode().isBranch()) { if (trace()) traceMsg(comp(), "The branch node couldn't be found\n"); return 0; } if (lastTreeInExitBlock->getNumChildren() < 2) { if (trace()) traceMsg(comp(), "The branch node has less than 2 children\n"); return 0; } TR::Node *firstChildOfLastTree = lastTreeInExitBlock->getFirstChild(); TR::Node *secondChildOfLastTree = lastTreeInExitBlock->getSecondChild(); if (!firstChildOfLastTree->getOpCode().hasSymbolReference()) { if (trace()) traceMsg(comp(), "The branch node's first child node %p - its opcode does not have a symbol reference\n", firstChildOfLastTree); return 0; } TR::SymbolReference *firstChildSymRef = firstChildOfLastTree->getSymbolReference(); if (trace()) traceMsg(comp(), "Symbol Reference: %p Symbol: %p\n", firstChildSymRef, firstChildSymRef->getSymbol()); // Locate the induction variable that matches with the exit node symbol // TR_InductionVariable *indVar = region->findMatchingIV(firstChildSymRef); if (!indVar) return 0; if (!indVar->getIncr()->asIntConst()) { if (trace()) traceMsg(comp(), "Increment is not a constant\n"); return 0; } int32_t increment = indVar->getIncr()->getLowInt(); _visitCount = comp()->incVisitCount(); bool indVarWrittenAndUsedUnexpectedly = false; if (firstChildOfLastTree->getReferenceCount() > 1) { TR::TreeTop *cursorTreeTopInExitBlock = exitBlock->getEntry(); TR::TreeTop *exitTreeTopInExitBlock = exitBlock->getExit(); bool loadSeen = false; while (cursorTreeTopInExitBlock != exitTreeTopInExitBlock) { TR::Node *cursorNode = cursorTreeTopInExitBlock->getNode(); if (checkForLoad(cursorNode, firstChildOfLastTree)) loadSeen = true; if (!cursorNode->getOpCode().isStore() && (cursorNode->getNumChildren() > 0)) cursorNode = cursorNode->getFirstChild(); if (cursorNode->getOpCode().isStore() && (cursorNode->getSymbolReference() == firstChildSymRef)) { indVarWrittenAndUsedUnexpectedly = true; if ((cursorNode->getFirstChild() == firstChildOfLastTree) || !loadSeen) indVarWrittenAndUsedUnexpectedly = false; else break; } cursorTreeTopInExitBlock = cursorTreeTopInExitBlock->getNextTreeTop(); } } if (indVarWrittenAndUsedUnexpectedly) { return 0; } int32_t lowerBound; int32_t upperBound = 0; TR::Node *bound = 0; bool equals = false; switch(lastTreeInExitBlock->getOpCodeValue()) { case TR::ificmplt: case TR::ificmpgt: equals = true; case TR::ificmple: case TR::ificmpge: if (!(indVar->getEntry() && indVar->getEntry()->asIntConst())) { if (trace()) traceMsg(comp(), "Entry value is not a constant\n"); return 0; } lowerBound = indVar->getEntry()->getLowInt(); if (secondChildOfLastTree->getOpCode().isLoadConst()) { upperBound = secondChildOfLastTree->getInt(); } else if (secondChildOfLastTree->getOpCode().isLoadVar()) { bound = secondChildOfLastTree; } else { if (trace()) traceMsg(comp(), "Second child is not a const or a load\n"); return 0; } return new (trStackMemory()) LoopInfo(bound, lowerBound, upperBound, increment, equals); default: if (trace()) traceMsg(comp(), "The condition has not been implemeted\n"); return 0; } return 0; }
void TR_ExpressionsSimplification::simplifyInvariantLoopExpressions(ListIterator<TR::Block> &blocks) { // Need to locate the induction variable of the loop // LoopInfo *loopInfo = findLoopInfo(_currentRegion); if (trace()) { if (!loopInfo) { traceMsg(comp(), "Accurate loop info is not found, cannot carry out summation reduction\n"); } else { traceMsg(comp(), "Accurate loop info has been found, will try to carry out summation reduction\n"); if (loopInfo->getBoundaryNode()) { traceMsg(comp(), "Variable iterations from node %p has not been handled\n",loopInfo->getBoundaryNode()); } else { traceMsg(comp(), "Natural Loop %p will run %d times\n", _currentRegion, loopInfo->getNumIterations()); } } } // Initialize the list of candidates // _candidateTTs = new (trStackMemory()) TR_ScratchList<TR::TreeTop>(trMemory()); for (TR::Block *currentBlock = blocks.getFirst(); currentBlock; currentBlock = blocks.getNext()) { if (trace()) traceMsg(comp(), "Analyzing block #%d, which must be executed once per iteration\n", currentBlock->getNumber()); // Scan through each node in the block // TR::TreeTop *tt = currentBlock->getEntry(); TR::TreeTop *exitTreeTop = currentBlock->getExit(); while (tt != exitTreeTop) { TR::Node *currentNode = tt->getNode(); if (trace()) traceMsg(comp(), "Analyzing tree top node %p\n", currentNode); if (loopInfo) { // requires loop info for the number of iterations setSummationReductionCandidates(currentNode, tt); } setStoreMotionCandidates(currentNode, tt); tt = tt->getNextTreeTop(); } } // New code: without using any UDI // walk through the trees in the loop // to invalidate the candidates // if (!_supportedExpressions) { _supportedExpressions = new (trStackMemory()) TR_BitVector(comp()->getNodeCount(), trMemory(), stackAlloc, growable); } invalidateCandidates(); ListIterator<TR::TreeTop> treeTops(_candidateTTs); for (TR::TreeTop *treeTop = treeTops.getFirst(); treeTop; treeTop = treeTops.getNext()) { if (trace()) traceMsg(comp(), "Candidate TreeTop: %p, Node:%p\n", treeTop, treeTop->getNode()); bool usedCandidate = false; bool isPreheaderBlockInvalid = false; if (loopInfo) { usedCandidate = tranformSummationReductionCandidate(treeTop, loopInfo, &isPreheaderBlockInvalid); } if (isPreheaderBlockInvalid) { break; } if (!usedCandidate) { tranformStoreMotionCandidate(treeTop, &isPreheaderBlockInvalid); } if (isPreheaderBlockInvalid) { break; } } }
TR_LocalAnalysisInfo::TR_LocalAnalysisInfo(TR::Compilation *c, bool t) : _compilation(c), _trace(t), _trMemory(c->trMemory()) { _numNodes = -1; #if 0 // somehow stops PRE from happening // We are going to increment visit count for every tree so can reach max // for big methods quickly. Perhaps can improve containsCall() in the future. comp()->resetVisitCounts(0); #endif if (comp()->getVisitCount() > HIGH_VISIT_COUNT) { _compilation->resetVisitCounts(1); dumpOptDetails(comp(), "\nResetting visit counts for this method before LocalAnalysisInfo\n"); } TR::CFG *cfg = comp()->getFlowGraph(); _numBlocks = cfg->getNextNodeNumber(); TR_ASSERT(_numBlocks > 0, "Local analysis, node numbers not assigned"); // Allocate information on the stack. It is the responsibility of the user // of this class to determine the life of the information by using jitStackMark // and jitStackRelease. // //_blocksInfo = (TR::Block **) trMemory()->allocateStackMemory(_numBlocks*sizeof(TR::Block *)); //memset(_blocksInfo, 0, _numBlocks*sizeof(TR::Block *)); TR::TreeTop *currentTree = comp()->getStartTree(); // Only do this if not done before; typically this would be done in the // first call to this method through LocalTransparency and would NOT // need to be re-done by LocalAnticipatability. // if (_numNodes < 0) { _optimizer = comp()->getOptimizer(); int32_t numBuckets; int32_t numNodes = comp()->getNodeCount(); if (numNodes < 10) numBuckets = 1; else if (numNodes < 100) numBuckets = 7; else if (numNodes < 500) numBuckets = 31; else if (numNodes < 3000) numBuckets = 127; else if (numNodes < 6000) numBuckets = 511; else numBuckets = 1023; // Allocate hash table for matching expressions // HashTable hashTable(numBuckets, comp()); _hashTable = &hashTable; // Null checks are handled differently as the criterion for // commoning a null check is different than that used for // other nodes; for a null check, the null check reference is // important (and not the actual indirect access itself) // _numNullChecks = 0; while (currentTree) { if (currentTree->getNode()->getOpCodeValue() == TR::NULLCHK) //////if (currentTree->getNode()->getOpCode().isNullCheck()) _numNullChecks++; currentTree = currentTree->getNextTreeTop(); } if (_numNullChecks == 0) _nullCheckNodesAsArray = NULL; else { _nullCheckNodesAsArray = (TR::Node**)trMemory()->allocateStackMemory(_numNullChecks*sizeof(TR::Node*)); memset(_nullCheckNodesAsArray, 0, _numNullChecks*sizeof(TR::Node*)); } currentTree = comp()->getStartTree(); int32_t symRefCount = comp()->getSymRefCount(); _checkSymbolReferences = new (trStackMemory()) TR_BitVector(symRefCount, trMemory(), stackAlloc); _numNodes = 1; _numNullChecks = 0; // This loop counts all the nodes that are going to take part in PRE. // This is a computation intensive loop as we check if the node that // is syntactically equivalent to a given node has been seen before // and if so we use the local index of the original node (that // is syntactically equivalent to the given node). Could be improved // in complexity with value numbering at some stage. // _visitCount = comp()->incVisitCount(); while (currentTree) { TR::Node *firstNodeInTree = currentTree->getNode(); TR::ILOpCode *opCode = &firstNodeInTree->getOpCode(); if (((firstNodeInTree->getOpCodeValue() == TR::treetop) || (comp()->useAnchors() && firstNodeInTree->getOpCode().isAnchor())) && (firstNodeInTree->getFirstChild()->getOpCode().isStore())) { firstNodeInTree->setLocalIndex(-1); if (comp()->useAnchors() && firstNodeInTree->getOpCode().isAnchor()) firstNodeInTree->getSecondChild()->setLocalIndex(-1); firstNodeInTree = firstNodeInTree->getFirstChild(); opCode = &firstNodeInTree->getOpCode(); } // This call finds nodes with opcodes that are supported by PRE // in this subtree; this accounts for all opcodes other than stores/checks // which are handled later on below // bool firstNodeInTreeHasCallsInStoreLhs = false; countSupportedNodes(firstNodeInTree, NULL, firstNodeInTreeHasCallsInStoreLhs); if ((opCode->isStore() && !firstNodeInTree->getSymbolReference()->getSymbol()->isAutoOrParm()) || opCode->isCheck()) { int32_t oldExpressionOnRhs = hasOldExpressionOnRhs(firstNodeInTree); // // Return value 0 denotes that the node contains some sub-expression // that cannot participate in PRE; e.g. a call or a new // // Return value -1 denotes that the node can participate in PRE // but did not match with any existing expression seen so far // // Any other return value (should be positive always) denotes that // the node can participate in PRE and has been matched with a seen // expression having local index == return value // if (oldExpressionOnRhs == -1) { if (trace()) { traceMsg(comp(), "\nExpression #%d is : \n", _numNodes); comp()->getDebug()->print(comp()->getOutFile(), firstNodeInTree, 6, true); } firstNodeInTree->setLocalIndex(_numNodes++); } else firstNodeInTree->setLocalIndex(oldExpressionOnRhs); if (opCode->isCheck() && (firstNodeInTree->getFirstChild()->getOpCode().isStore() && !firstNodeInTree->getFirstChild()->getSymbolReference()->getSymbol()->isAutoOrParm())) { int oldExpressionOnRhs = hasOldExpressionOnRhs(firstNodeInTree->getFirstChild()); if (oldExpressionOnRhs == -1) { if (trace()) { traceMsg(comp(), "\nExpression #%d is : \n", _numNodes); comp()->getDebug()->print(comp()->getOutFile(), firstNodeInTree->getFirstChild(), 6, true); } firstNodeInTree->getFirstChild()->setLocalIndex(_numNodes++); } else firstNodeInTree->getFirstChild()->setLocalIndex(oldExpressionOnRhs); } } else firstNodeInTree->setLocalIndex(-1); currentTree = currentTree->getNextTreeTop(); } } _supportedNodesAsArray = (TR::Node**)trMemory()->allocateStackMemory(_numNodes*sizeof(TR::Node*)); memset(_supportedNodesAsArray, 0, _numNodes*sizeof(TR::Node*)); _checkExpressions = new (trStackMemory()) TR_BitVector(_numNodes, trMemory(), stackAlloc); //_checkExpressions.init(_numNodes, trMemory(), stackAlloc); // This loop goes through the trees and collects the nodes // that would take part in PRE. Each node has its local index set to // the bit position that it occupies in the bit vector analyses. // currentTree = comp()->getStartTree(); _visitCount = comp()->incVisitCount(); while (currentTree) { TR::Node *firstNodeInTree = currentTree->getNode(); TR::ILOpCode *opCode = &firstNodeInTree->getOpCode(); if (((firstNodeInTree->getOpCodeValue() == TR::treetop) || (comp()->useAnchors() && firstNodeInTree->getOpCode().isAnchor())) && (firstNodeInTree->getFirstChild()->getOpCode().isStore())) { firstNodeInTree = firstNodeInTree->getFirstChild(); opCode = &firstNodeInTree->getOpCode(); } collectSupportedNodes(firstNodeInTree, NULL); if ((opCode->isStore() && !firstNodeInTree->getSymbolReference()->getSymbol()->isAutoOrParm()) || opCode->isCheck()) { if (opCode->isCheck()) { _checkSymbolReferences->set(firstNodeInTree->getSymbolReference()->getReferenceNumber()); _checkExpressions->set(firstNodeInTree->getLocalIndex()); } if (!_supportedNodesAsArray[firstNodeInTree->getLocalIndex()]) _supportedNodesAsArray[firstNodeInTree->getLocalIndex()] = firstNodeInTree; if (opCode->isCheck() && firstNodeInTree->getFirstChild()->getOpCode().isStore() && !firstNodeInTree->getFirstChild()->getSymbolReference()->getSymbol()->isAutoOrParm() && !_supportedNodesAsArray[firstNodeInTree->getFirstChild()->getLocalIndex()]) _supportedNodesAsArray[firstNodeInTree->getFirstChild()->getLocalIndex()] = firstNodeInTree->getFirstChild(); } currentTree = currentTree->getNextTreeTop(); } //initialize(toBlock(cfg->getStart())); }