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_ReachingDefinitions::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. // TR::Block *block; int32_t blockNum = 0; bool seenException = false; TR_BitVector defsKilled(getNumberOfBits(), trMemory()->currentStackRegion()); comp()->incVisitCount(); for (TR::TreeTop *treeTop = comp()->getStartTree(); treeTop; treeTop = treeTop->getNextTreeTop()) { TR::Node *node = treeTop->getNode(); if (node->getOpCodeValue() == TR::BBStart) { block = node->getBlock(); blockNum = block->getNumber(); seenException = false; if (traceRD()) traceMsg(comp(), "\nNow generating gen and kill information for block_%d\n", blockNum); continue; } #if DEBUG if (node->getOpCodeValue() == TR::BBEnd && traceRD()) { traceMsg(comp(), " Block %d:\n", blockNum); traceMsg(comp(), " Gen set "); if (_regularGenSetInfo[blockNum]) _regularGenSetInfo[blockNum]->print(comp()); else traceMsg(comp(), "{}"); traceMsg(comp(), "\n Kill set "); if (_regularKillSetInfo[blockNum]) _regularKillSetInfo[blockNum]->print(comp()); else traceMsg(comp(), "{}"); traceMsg(comp(), "\n Exception Gen set "); if (_exceptionGenSetInfo[blockNum]) _exceptionGenSetInfo[blockNum]->print(comp()); else traceMsg(comp(), "{}"); traceMsg(comp(), "\n Exception Kill set "); if (_exceptionKillSetInfo[blockNum]) _exceptionKillSetInfo[blockNum]->print(comp()); else traceMsg(comp(), "{}"); continue; } #endif initializeGenAndKillSetInfoForNode(node, defsKilled, seenException, blockNum, NULL); if (!seenException && treeHasChecks(treeTop)) seenException = true; } }
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(); } }
TR_DominatorVerifier::TR_DominatorVerifier(TR_Dominators &findDominators) : _compilation(findDominators.comp()) { TR::StackMemoryRegion stackMemoryRegion(*trMemory()); _dominators = &findDominators; TR::CFG *cfg = comp()->getFlowGraph(); _visitCount = comp()->incVisitCount(); _numBlocks = cfg->getNumberOfNodes()+1; if (debug("traceVER")) { dumpOptDetails(comp(), "Printing out the TreeTops from DominatorVerifier\n"); TR::TreeTop *currentTree = comp()->getStartTree(); while (!(currentTree == NULL)) { comp()->getDebug()->print(comp()->getOutFile(), currentTree); currentTree = currentTree->getNextTreeTop(); } dumpOptDetails(comp(), "Printing out the CFG from DominatorVerifier\n"); if (cfg != NULL) comp()->getDebug()->print(comp()->getOutFile(), cfg); } TR_DominatorsChk expensiveAlgorithm(comp()); expensiveAlgorithmCorrect = isExpensiveAlgorithmCorrect(expensiveAlgorithm); if (expensiveAlgorithmCorrect) { if (debug("traceVER")) dumpOptDetails(comp(), "Dominators computed by the expensive algorithm are correct\n"); } else { if (debug("traceVER")) dumpOptDetails(comp(), "Dominators computed by the expensive algorithm are NOT correct\n"); TR_ASSERT(0, "Dominators computed by the expensive algorithm are NOT correct\n"); } bothImplementationsConsistent = areBothImplementationsConsistent(expensiveAlgorithm, findDominators); if (bothImplementationsConsistent) { if (debug("traceVER")) dumpOptDetails(comp(), "Dominators computed by the two implementations are consistent\n"); } else { if (debug("traceVER")) dumpOptDetails(comp(), "Dominators computed by the two implementations are NOT consistent\n"); TR_ASSERT(0, "Dominators computed by the two implementations are NOT consistent\n"); } }
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; }
int32_t TR_LocalLiveRangeReduction::perform() { if (TR::Compiler->target.cpu.isZ()) return false; TR::TreeTop * exitTT, * nextTT; TR::Block *b; TR::TreeTop * tt; //calculate number of TreeTops in each bb (or extended bb) for (tt = comp()->getStartTree(); tt; tt = nextTT) { TR::StackMemoryRegion stackMemoryRegion(*trMemory()); TR::Node *node = tt->getNode(); b = node->getBlock(); exitTT = b->getExit(); _numTreeTops = b->getNumberOfRealTreeTops()+2; //include both BBStart/BBend //support for extended blocks while ((nextTT = exitTT->getNextTreeTop()) && (b = nextTT->getNode()->getBlock(), b->isExtensionOfPreviousBlock())) { _numTreeTops += b->getNumberOfRealTreeTops()+2; exitTT = b->getExit(); } _treesRefInfoArray = (TR_TreeRefInfo**)trMemory()->allocateStackMemory(_numTreeTops*sizeof(TR_TreeRefInfo*)); memset(_treesRefInfoArray, 0, _numTreeTops*sizeof(TR_TreeRefInfo*)); _movedTreesList.deleteAll(); _depPairList.deleteAll(); transformExtendedBlock(tt,exitTT->getNextTreeTop()); } if (trace()) traceMsg(comp(), "\nEnding LocalLiveRangeReducer\n"); return 2; }
int32_t TR_ExpressionsSimplification::perform() { TR::StackMemoryRegion stackMemoryRegion(*trMemory()); int32_t cost = 0; _supportedExpressions = NULL; if (trace()) { comp()->dumpMethodTrees("Trees Before Performing Expression Simplification"); } cost = perform(comp()->getFlowGraph()->getStructure()); return cost; }
void TR_LocalAnalysis::initializeLocalAnalysis(bool isSparse, bool lock) { _info = (TR_LocalAnalysisInfo::LAInfo*) trMemory()->allocateStackMemory(_lainfo._numBlocks*sizeof(TR_LocalAnalysisInfo::LAInfo)); memset(_info, 0, _lainfo._numBlocks*sizeof(TR_LocalAnalysisInfo::LAInfo)); TR::BitVector blocksSeen(comp()->allocator()); initializeBlocks(toBlock(comp()->getFlowGraph()->getStart()), blocksSeen); int32_t i; for (i = 0; i < _lainfo._numBlocks; i++) { _info[i]._analysisInfo = allocateContainer(getNumNodes()); _info[i]._downwardExposedAnalysisInfo = allocateContainer(getNumNodes()); _info[i]._downwardExposedStoreAnalysisInfo = allocateContainer(getNumNodes()); } }
int32_t TR_ReachingBlocks::perform() { // Allocate the block info before setting the stack mark - it will be used by // the caller // initializeBlockInfo(); { TR::StackMemoryRegion stackMemoryRegion(*trMemory()); TR_Structure *rootStructure = comp()->getFlowGraph()->getStructure(); performAnalysis(rootStructure, false); } // scope of the stack memory region return 10; // actual cost }
int32_t TR_LoadExtensions::perform() { if (comp()->getOptLevel() >= warm && !optimizer()->cantBuildGlobalsUseDefInfo()) { if (!comp()->getFlowGraph()->getStructure()) { optimizer()->doStructuralAnalysis(); } TR::LexicalMemProfiler memoryProfiler("Load Extensions: Usedef calculation", comp()->phaseMemProfiler()); optimizer()->setUseDefInfo(NULL); TR_UseDefInfo* useDefInfo = new (comp()->allocator()) TR_UseDefInfo(comp(), comp()->getFlowGraph(), optimizer(), false, false, false, true, true); if (useDefInfo->infoIsValid()) { optimizer()->setUseDefInfo(useDefInfo); } else { delete useDefInfo; } } TR::StackMemoryRegion stackMemoryRegion(*trMemory()); excludedNodes = new (stackMemoryRegion) NodeToIntTable(NodeToIntTableComparator(), NodeToIntTableAllocator(stackMemoryRegion)); loadExtensionPreference = new (stackMemoryRegion) NodeToIntTable(NodeToIntTableComparator(), NodeToIntTableAllocator(stackMemoryRegion)); for (TR::PreorderNodeIterator iter(comp()->getStartTree(), comp()); iter.currentTree() != NULL; ++iter) { findPreferredLoadExtensions(iter.currentNode()); } for (TR::PreorderNodeIterator iter(comp()->getStartTree(), comp()); iter.currentTree() != NULL; ++iter) { flagPreferredLoadExtensions(iter.currentNode()); } return 0; }
void TR_ExpressionsSimplification::findAndSimplifyInvariantLoopExpressions(TR_RegionStructure * region) { _currentRegion = region; TR::Block *entryBlock = _currentRegion->getEntryBlock(); if (trace()) traceMsg(comp(), "Entry block: %p in loop region %p\n", entryBlock, region); // Generate a list of blocks that can be processed // Criteria: the block must be excucted exactly once // TR_ScratchList<TR::Block> candidateBlocksList(trMemory()); _currentRegion->getBlocks(&candidateBlocksList); if (candidateBlocksList.getSize() > 1) { if (trace()) traceMsg(comp(), "More than 1 blocks in the natural loop, need to remove uncertain blocks\n"); removeUncertainBlocks(_currentRegion, &candidateBlocksList); if (candidateBlocksList.getSize() < 1) return; } _currentRegion->resetInvariance(); _currentRegion->computeInvariantExpressions(); // The rest is the transformation // // For each block that is definitely executed once // analyze its nodes // ListIterator<TR::Block> candidateBlocks; candidateBlocks.set(&candidateBlocksList); simplifyInvariantLoopExpressions(candidateBlocks); }
int32_t TR_AsyncCheckInsertion::perform() { TR::StackMemoryRegion stackMemoryRegion(*trMemory()); // If this is a large acyclic method - add a yield point at each return from this method // so that sampling will realize that we are actually in this method. // static const char *p; static uint32_t numNodesInLargeMethod = (p = feGetEnv("TR_LargeMethodNodes")) ? atoi(p) : NUMBER_OF_NODES_IN_LARGE_METHOD; const bool largeAcyclicMethod = !comp()->mayHaveLoops() && comp()->getNodeCount() > numNodesInLargeMethod; // If this method has loops whose asyncchecks were versioned out, it may // still spend a significant amount of time in each invocation without // yielding. In this case, insert yield points before returns whenever there // is a sufficiently frequent block somewhere in the method. // bool loopyMethodWithVersionedAsyncChecks = false; if (!largeAcyclicMethod && comp()->getLoopWasVersionedWrtAsyncChecks()) { // The max (normalized) block frequency is fixed, but very frequent // blocks push down the frequency of method entry. int32_t entry = comp()->getStartTree()->getNode()->getBlock()->getFrequency(); int32_t limit = comp()->getOptions()->getLoopyAsyncCheckInsertionMaxEntryFreq(); loopyMethodWithVersionedAsyncChecks = 0 <= entry && entry <= limit; } if (largeAcyclicMethod || loopyMethodWithVersionedAsyncChecks) { const char * counterPrefix = largeAcyclicMethod ? "acyclic" : "loopy"; int32_t numAsyncChecksInserted = insertReturnAsyncChecks(this, counterPrefix); if (trace()) traceMsg(comp(), "Inserted %d async checks\n", numAsyncChecksInserted); return 1; } return 0; }
void TR_ExpressionsSimplification::invalidateCandidates() { _visitCount = comp()->incVisitCount(); if (trace()) { traceMsg(comp(), "Checking which candidates may be invalidated\n"); ListIterator<TR::TreeTop> treeTops(_candidateTTs); for (TR::TreeTop *treeTop = treeTops.getFirst(); treeTop; treeTop = treeTops.getNext()) { traceMsg(comp(), " Candidate treetop: %p node: %p\n", treeTop, treeTop->getNode()); } } TR_ScratchList<TR::Block> blocksInLoop(trMemory()); _currentRegion->getBlocks(&blocksInLoop); ListIterator<TR::Block> blocks(&blocksInLoop); for (TR::Block *currentBlock = blocks.getFirst(); currentBlock; currentBlock = blocks.getNext()) { TR::TreeTop *tt = currentBlock->getEntry(); TR::TreeTop *exitTreeTop = currentBlock->getExit(); while (tt != exitTreeTop) { TR::Node *currentNode = tt->getNode(); if (trace()) traceMsg(comp(), "Looking at treeTop [%p]\n", currentNode); removeCandidate(currentNode, tt); tt = tt->getNextTreeTop(); } } removeUnsupportedCandidates(); }
//---------------------------- 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); }
int32_t TR_ReachingDefinitions::perform() { LexicalTimer tlex("reachingDefs_perform", comp()->phaseTimer()); if (traceRD()) traceMsg(comp(), "Starting ReachingDefinitions\n"); // Allocate the block info, allowing the bit vectors to be allocated on the fly // initializeBlockInfo(false); { TR::StackMemoryRegion stackMemoryRegion(*trMemory()); TR_Structure *rootStructure = _cfg->getStructure(); performAnalysis(rootStructure, false); if (traceRD()) traceMsg(comp(), "\nEnding ReachingDefinitions\n"); } // scope of the stack memory region return 10; // actual cost }
TR_LocalLiveRangeReduction::TR_LocalLiveRangeReduction(TR::OptimizationManager *manager) : TR::Optimization(manager), _movedTreesList(trMemory()), _depPairList(trMemory()) {}
TR_Latestness::TR_Latestness(TR::Compilation *comp, TR::Optimizer *optimizer, TR_Structure *rootStructure, bool trace) : TR_BackwardIntersectionBitVectorAnalysis(comp, comp->getFlowGraph(), optimizer, trace) { _delayedness = new (comp->allocator()) TR_Delayedness(comp, optimizer, rootStructure, trace); _supportedNodesAsArray = _delayedness->_supportedNodesAsArray; if (trace) traceMsg(comp, "Starting Latestness\n"); TR::CFG *cfg = comp->getFlowGraph(); _numberOfNodes = cfg->getNextNodeNumber(); TR_ASSERT(_numberOfNodes > 0, "Latestness, node numbers not assigned"); _numberOfBits = getNumberOfBits(); _inSetInfo = (ContainerType **)trMemory()->allocateStackMemory(_numberOfNodes*sizeof(ContainerType *)); for (int32_t i=0;i<_numberOfNodes;i++) allocateContainer(_inSetInfo+i); // Allocate temp bit vectors from block info, since it is local to this analysis ContainerType *intersection, *negation; allocateBlockInfoContainer(&intersection); allocateBlockInfoContainer(&negation); TR::CFGNode *nextNode; for (nextNode = cfg->getFirstNode(); nextNode; nextNode = nextNode->getNext()) { TR_BlockStructure *blockStructure = (toBlock(nextNode))->getStructureOf(); if ((blockStructure == NULL) || (blockStructure->getBlock()->getSuccessors().empty() && blockStructure->getBlock()->getExceptionSuccessors().empty())) continue; /////analyzeTreeTopsInBlockStructure(blockStructure); /////analysisInfo->_containsExceptionTreeTop = _containsExceptionTreeTop; initializeInfo(intersection); for (auto succ = nextNode->getSuccessors().begin(); succ != nextNode->getSuccessors().end(); ++succ) { TR::CFGNode *succBlock = (*succ)->getTo(); compose(intersection, _delayedness->_inSetInfo[succBlock->getNumber()]); } /////if (getAnalysisInfo(blockStructure)->_containsExceptionTreeTop) { for (auto succ = nextNode->getExceptionSuccessors().begin(); succ != nextNode->getExceptionSuccessors().end(); ++succ) { TR::CFGNode *succBlock = (*succ)->getTo(); compose(intersection, _delayedness->_inSetInfo[succBlock->getNumber()]); } } negation->setAll(_numberOfBits); *negation -= *intersection; copyFromInto(negation, _inSetInfo[blockStructure->getNumber()]); *(_inSetInfo[blockStructure->getNumber()]) |= *(_delayedness->_earliestness->_globalAnticipatability->_localAnticipatability.getDownwardExposedAnalysisInfo(blockStructure->getBlock()->getNumber())); *(_inSetInfo[blockStructure->getNumber()]) &= *(_delayedness->_inSetInfo[blockStructure->getNumber()]); if (trace) { traceMsg(comp, "\nIn Set of Block : %d\n", blockStructure->getNumber()); _inSetInfo[blockStructure->getNumber()]->print(comp); } } if (trace) traceMsg(comp, "\nEnding Latestness\n"); // Null out info that will not be used by callers _delayedness->_inSetInfo = NULL; _blockAnalysisInfo = NULL; }
TR::Register *TR::ARM64SystemLinkage::buildDirectDispatch(TR::Node *callNode) { TR::SymbolReference *callSymRef = callNode->getSymbolReference(); const TR::ARM64LinkageProperties &pp = getProperties(); TR::RealRegister *sp = cg()->machine()->getRealRegister(pp.getStackPointerRegister()); TR::RegisterDependencyConditions *dependencies = new (trHeapMemory()) TR::RegisterDependencyConditions( pp.getNumberOfDependencyGPRegisters(), pp.getNumberOfDependencyGPRegisters(), trMemory()); int32_t totalSize = buildArgs(callNode, dependencies); if (totalSize > 0) { if (constantIsUnsignedImm12(totalSize)) { generateTrg1Src1ImmInstruction(cg(), TR::InstOpCode::subimmx, callNode, sp, sp, totalSize); } else { TR_ASSERT_FATAL(false, "Too many arguments."); } } TR::MethodSymbol *callSymbol = callSymRef->getSymbol()->castToMethodSymbol(); generateImmSymInstruction(cg(), TR::InstOpCode::bl, callNode, (uintptr_t)callSymbol->getMethodAddress(), dependencies, callSymRef ? callSymRef : callNode->getSymbolReference(), NULL); cg()->machine()->setLinkRegisterKilled(true); if (totalSize > 0) { if (constantIsUnsignedImm12(totalSize)) { generateTrg1Src1ImmInstruction(cg(), TR::InstOpCode::addimmx, callNode, sp, sp, totalSize); } else { TR_ASSERT_FATAL(false, "Too many arguments."); } } TR::Register *retReg; switch(callNode->getOpCodeValue()) { case TR::icall: case TR::iucall: retReg = dependencies->searchPostConditionRegister( pp.getIntegerReturnRegister()); break; case TR::lcall: case TR::lucall: case TR::acall: retReg = dependencies->searchPostConditionRegister( pp.getLongReturnRegister()); break; case TR::fcall: case TR::dcall: retReg = dependencies->searchPostConditionRegister( pp.getFloatReturnRegister()); break; case TR::call: retReg = NULL; break; default: retReg = NULL; TR_ASSERT(false, "Unsupported direct call Opcode."); } callNode->setRegister(retReg); return retReg; }
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; }
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); } }
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())); }
TR_StackMemory trStackMemory() { return trMemory(); }
uint8_t * compileMethodFromDetails( OMR_VMThread *omrVMThread, TR::IlGeneratorMethodDetails & details, TR_Hotness hotness, int32_t &rc) { uint64_t translationStartTime = TR::Compiler->vm.getUSecClock(); OMR::FrontEnd &fe = OMR::FrontEnd::singleton(); auto jitConfig = fe.jitConfig(); TR::RawAllocator rawAllocator; TR::SystemSegmentProvider defaultSegmentProvider(1 << 16, rawAllocator); TR::DebugSegmentProvider debugSegmentProvider(1 << 16, rawAllocator); TR::SegmentAllocator &scratchSegmentProvider = TR::Options::getCmdLineOptions()->getOption(TR_EnableScratchMemoryDebugging) ? static_cast<TR::SegmentAllocator &>(debugSegmentProvider) : static_cast<TR::SegmentAllocator &>(defaultSegmentProvider); TR::Region dispatchRegion(scratchSegmentProvider, rawAllocator); TR_Memory trMemory(*fe.persistentMemory(), dispatchRegion); TR_ResolvedMethod & compilee = *((TR_ResolvedMethod *)details.getMethod()); TR::CompileIlGenRequest request(details); // initialize return code before compilation starts rc = COMPILATION_REQUESTED; uint8_t *startPC = 0; TR_FilterBST *filterInfo = 0; TR_OptimizationPlan *plan = 0; if (!methodCanBeCompiled(&fe, compilee, filterInfo, &trMemory)) { if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompileExclude)) { TR_VerboseLog::write("<JIT: %s cannot be translated>\n", compilee.signature(&trMemory)); } return 0; } if (0 == (plan = TR_OptimizationPlan::alloc(hotness, false, false))) { // FIXME: maybe it would be better to allocate the plan on the stack // so that we don't have to deal with OOM ugliness below if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompileExclude)) { TR_VerboseLog::write("<JIT: %s out-of-memory allocating optimization plan>\n", compilee.signature(&trMemory)); } return 0; } int32_t optionSetIndex = filterInfo ? filterInfo->getOptionSet() : 0; int32_t lineNumber = filterInfo ? filterInfo->getLineNumber() : 0; TR::Options options( &trMemory, optionSetIndex, lineNumber, &compilee, 0, plan, false); // FIXME: once we can do recompilation , we need to pass in the old start PC -----------------------^ // FIXME: what happens if we can't allocate memory at the new above? // FIXME: perhaps use stack memory instead TR_ASSERT(TR::comp() == NULL, "there seems to be a current TLS TR::Compilation object %p for this thread. At this point there should be no current TR::Compilation object", TR::comp()); TR::Compilation compiler(0, omrVMThread, &fe, &compilee, request, options, dispatchRegion, &trMemory, plan); TR_ASSERT(TR::comp() == &compiler, "the TLS TR::Compilation object %p for this thread does not match the one %p just created.", TR::comp(), &compiler); try { //fprintf(stderr,"loading JIT debug\n"); if (TR::Options::requiresDebugObject() || options.getLogFileName() || options.enableDebugCounters()) { compiler.setDebug(createDebugObject(&compiler)); } compiler.setIlVerifier(details.getIlVerifier()); if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompileStart)) { const char *signature = compilee.signature(&trMemory); TR_VerboseLog::writeLineLocked(TR_Vlog_COMPSTART,"compiling %s", signature); } if (compiler.getOutFile() != NULL && compiler.getOption(TR_TraceAll)) { const char *signature = compilee.signature(&trMemory); traceMsg((&compiler), "<compile hotness=\"%s\" method=\"%s\">\n", compiler.getHotnessName(compiler.getMethodHotness()), signature); } compiler.getJittedMethodSymbol()->setLinkage(TR_System); // -------------------------------------------------------------------- // Compile the method // rc = compiler.compile(); if (rc == COMPILATION_SUCCEEDED) // success! { // not ready yet... //OMR::MethodMetaDataPOD *metaData = fe.createMethodMetaData(&compiler); startPC = compiler.cg()->getCodeStart(); uint64_t translationTime = TR::Compiler->vm.getUSecClock() - translationStartTime; if (TR::Options::isAnyVerboseOptionSet(TR_VerboseCompileEnd, TR_VerbosePerformance)) { const char *signature = compilee.signature(&trMemory); TR_VerboseLog::vlogAcquire(); TR_VerboseLog::writeLine(TR_Vlog_COMP,"(%s) %s @ " POINTER_PRINTF_FORMAT "-" POINTER_PRINTF_FORMAT, compiler.getHotnessName(compiler.getMethodHotness()), signature, startPC, compiler.cg()->getCodeEnd()); if (TR::Options::getVerboseOption(TR_VerbosePerformance)) { TR_VerboseLog::write( " time=%llu mem=%lluKB", translationTime, static_cast<unsigned long long>(scratchSegmentProvider.bytesAllocated()) / 1024 ); } TR_VerboseLog::vlogRelease(); trfflush(jitConfig->options.vLogFile); } if ( TR::Options::getCmdLineOptions()->getOption(TR_PerfTool) || TR::Options::getCmdLineOptions()->getOption(TR_EmitExecutableELFFile) || TR::Options::getCmdLineOptions()->getOption(TR_EmitRelocatableELFFile) ) { TR::CodeCacheManager &codeCacheManager(fe.codeCacheManager()); TR::CodeGenerator &codeGenerator(*compiler.cg()); codeCacheManager.registerCompiledMethod(compiler.externalName(), startPC, codeGenerator.getCodeLength()); if (TR::Options::getCmdLineOptions()->getOption(TR_EmitRelocatableELFFile)) { auto &relocations = codeGenerator.getStaticRelocations(); for (auto it = relocations.begin(); it != relocations.end(); ++it) { codeCacheManager.registerStaticRelocation(*it); } } if (TR::Options::getCmdLineOptions()->getOption(TR_PerfTool)) { generatePerfToolEntry(startPC, codeGenerator.getCodeEnd(), compiler.signature(), compiler.getHotnessName(compiler.getMethodHotness())); } } if (compiler.getOutFile() != NULL && compiler.getOption(TR_TraceAll)) traceMsg((&compiler), "<result success=\"true\" startPC=\"%#p\" time=\"%lld.%lldms\"/>\n", startPC, translationTime/1000, translationTime%1000); } else /* of rc == COMPILATION_SUCCEEDED */ { TR_ASSERT(false, "compiler error code %d returned\n", rc); } if (compiler.getOption(TR_BreakAfterCompile)) { TR::Compiler->debug.breakPoint(); } } catch (const TR::ILValidationFailure &exception) { rc = COMPILATION_IL_VALIDATION_FAILURE; #if defined(J9ZOS390) // Compiling with -Wc,lp64 results in a crash on z/OS when trying // to call the what() virtual method of the exception. printCompFailureInfo(jitConfig, &compiler, ""); #else printCompFailureInfo(jitConfig, &compiler, exception.what()); #endif } catch (const std::exception &exception) { // failed! :-( #if defined(J9ZOS390) // Compiling with -Wc,lp64 results in a crash on z/OS when trying // to call the what() virtual method of the exception. printCompFailureInfo(jitConfig, &compiler, ""); #else printCompFailureInfo(jitConfig, &compiler, exception.what()); #endif } // A better place to do this would have been the destructor for // TR::Compilation. We'll need exceptions working instead of setjmp // before we can get working, and we need to make sure the other // frontends are properly calling the destructor TR::CodeCacheManager::instance()->unreserveCodeCache(compiler.getCurrentCodeCache()); TR_OptimizationPlan::freeOptimizationPlan(plan); return startPC; }
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; } } }
void TR_LocalLiveRangeReduction::prePerformOnBlocks() { comp()->incVisitCount(); int32_t symRefCount = comp()->getSymRefCount(); _temp = new (trStackMemory()) TR_BitVector(symRefCount, trMemory(), stackAlloc); }
int32_t TR_CatchBlockRemover::perform() { TR::CFG *cfg = comp()->getFlowGraph(); if (cfg == NULL) { if (trace()) traceMsg(comp(), "Can't do Catch Block Removal, no CFG\n"); return 0; } if (trace()) traceMsg(comp(), "Starting Catch Block Removal\n"); bool thereMayBeRemovableCatchBlocks = false; { TR::StackMemoryRegion stackMemoryRegion(*trMemory()); TR::Block *block; ListIterator<TR::CFGEdge> edgeIterator; // Go through all blocks that have exception successors and see if any of them // are not reached. Mark each of these edges with a visit count so they can // be identified later. // vcount_t visitCount = comp()->incOrResetVisitCount(); TR::CFGNode *cfgNode; for (cfgNode = cfg->getFirstNode(); cfgNode; cfgNode = cfgNode->getNext()) { if (cfgNode->getExceptionSuccessors().empty()) continue; block = toBlock(cfgNode); uint32_t reachedExceptions = 0; TR::TreeTop *treeTop; for (treeTop = block->getEntry(); treeTop != block->getExit(); treeTop = treeTop->getNextTreeTop()) { reachedExceptions |= treeTop->getNode()->exceptionsRaised(); if (treeTop->getNode()->getOpCodeValue() == TR::monexitfence) // for live monitor metadata reachedExceptions |= TR::Block::CanCatchMonitorExit; } if (reachedExceptions & TR::Block::CanCatchUserThrows) continue; for (auto edge = block->getExceptionSuccessors().begin(); edge != block->getExceptionSuccessors().end();) { TR::CFGEdge * current = *(edge++); TR::Block *catchBlock = toBlock(current->getTo()); if (catchBlock->isOSRCodeBlock() || catchBlock->isOSRCatchBlock()) continue; if (!reachedExceptions && performTransformation(comp(), "%sRemove redundant exception edge from block_%d at [%p] to catch block_%d at [%p]\n", optDetailString(), block->getNumber(), block, catchBlock->getNumber(), catchBlock)) { cfg->removeEdge(block, catchBlock); thereMayBeRemovableCatchBlocks = true; } else { if (!catchBlock->canCatchExceptions(reachedExceptions)) { current->setVisitCount(visitCount); thereMayBeRemovableCatchBlocks = true; } } } } bool edgesRemoved = false; // Now look to see if there are any catch blocks for which all exception // predecessors have the visit count set. If so, the block is unreachable and // can be removed. // If only some of the exception predecessors are marked, these edges are // left in place to identify the try/catch structure properly. // while (thereMayBeRemovableCatchBlocks) { thereMayBeRemovableCatchBlocks = false; for (cfgNode = cfg->getFirstNode(); cfgNode; cfgNode = cfgNode->getNext()) { if (cfgNode->getExceptionPredecessors().empty()) continue; auto edgeIt = cfgNode->getExceptionPredecessors().begin(); for (; edgeIt != cfgNode->getExceptionPredecessors().end(); ++edgeIt) { if ((*edgeIt)->getVisitCount() != visitCount) break; } if (edgeIt == cfgNode->getExceptionPredecessors().end() && performTransformation(comp(), "%sRemove redundant catch block_%d at [%p]\n", optDetailString(), cfgNode->getNumber(), cfgNode)) { while (!cfgNode->getExceptionPredecessors().empty()) { cfg->removeEdge(cfgNode->getExceptionPredecessors().front()); } edgesRemoved = true; thereMayBeRemovableCatchBlocks = true; } } } // Any transformations invalidate use/def and value number information // if (edgesRemoved) { optimizer()->setUseDefInfo(NULL); optimizer()->setValueNumberInfo(NULL); requestOpt(OMR::treeSimplification, true); } } // scope of the stack memory region if (trace()) traceMsg(comp(), "\nEnding Catch Block Removal\n"); return 1; // actual cost }
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; }
inline void * TR_HeapMemory::allocate(size_t size, TR_MemoryBase::ObjectType ot) { return trMemory().allocateHeapMemory(size, ot); }
TR::Register *TR::IA32SystemLinkage::buildDirectDispatch(TR::Node *callNode, bool spillFPRegs) { TR::RealRegister *stackPointerReg = machine()->getX86RealRegister(TR::RealRegister::esp); TR::SymbolReference *methodSymRef = callNode->getSymbolReference(); TR::MethodSymbol *methodSymbol = callNode->getSymbol()->castToMethodSymbol(); TR::ILOpCodes callOpCodeValue = callNode->getOpCodeValue(); if (!methodSymbol->isHelper()) diagnostic("Building call site for %s\n", methodSymbol->getMethod()->signature(trMemory())); TR::RegisterDependencyConditions *deps; deps = generateRegisterDependencyConditions((uint8_t)0, (uint8_t)6, cg()); TR::Register *returnReg = buildVolatileAndReturnDependencies(callNode, deps); deps->stopAddingConditions(); TR::RegisterDependencyConditions *dummy = generateRegisterDependencyConditions((uint8_t)0, (uint8_t)0, cg()); uint32_t argSize = buildArgs(callNode, dummy); TR::Register* targetAddressReg = NULL; TR::MemoryReference* targetAddressMem = NULL; // Call-out int32_t stackAdjustment = cg()->getProperties().getCallerCleanup() ? 0 : -argSize; TR::X86ImmInstruction* instr = generateImmSymInstruction(CALLImm4, callNode, (uintptr_t)methodSymbol->getMethodAddress(), methodSymRef, cg()); instr->setAdjustsFramePointerBy(stackAdjustment); if (cg()->getProperties().getCallerCleanup() && argSize > 0) { // Clean up arguments // generateRegImmInstruction( (argSize <= 127) ? ADD4RegImms : ADD4RegImm4, callNode, stackPointerReg, argSize, cg() ); } // Label denoting end of dispatch code sequence; dependencies are on // this label rather than on the call // TR::LabelSymbol *endSystemCallSequence = generateLabelSymbol(cg()); generateLabelInstruction(LABEL, callNode, endSystemCallSequence, deps, cg()); // Stop using the killed registers that are not going to persist // if (deps) stopUsingKilledRegisters(deps, returnReg); // If the method returns a floating point value that is not used, insert a dummy store to // eventually pop the value from the floating point stack. // if ((callNode->getDataType() == TR::Float || callNode->getDataType() == TR::Double) && callNode->getReferenceCount() == 1) { generateFPSTiST0RegRegInstruction(FSTRegReg, callNode, returnReg, returnReg, cg()); } if (cg()->enableRegisterAssociations()) associatePreservedRegisters(deps, returnReg); return returnReg; }
TR_HeapMemory trHeapMemory() { return trMemory(); }