// Process the structure recursively // int32_t TR_ExpressionsSimplification::perform(TR_Structure * str) { if (trace()) traceMsg(comp(), "Analyzing root Structure : %p\n", str); TR_RegionStructure *region; // Only regions can be simplified // if (!(region = str->asRegion())) return 0; TR_RegionStructure::Cursor it(*region); for (TR_StructureSubGraphNode *node = it.getCurrent(); node != 0; node = it.getNext()) { // Too strict /* if ((node->getPredecessors().size() == 1)) { TR::CFGEdge *edge = node->getPredecessors().front(); TR_StructureSubGraphNode *pred = toStructureSubGraphNode(edge->getFrom()); TR_BlockStructure *b = pred->getStructure()->asBlock(); if (b && pred->getSuccessors().size() == 1)) perform(node->getStructure()); } */ perform(node->getStructure()); } // debug only // /* if (region->isNaturalLoop() && (region->getParent() && !region->getParent()->asRegion()->isCanonicalizedLoop())) { traceMsg(comp(), "Loop not canonicalized %x\n", region); } */ TR::Block *entryBlock = region->getEntryBlock(); if (region->isNaturalLoop() && !entryBlock->isCold() && (region->getParent() /* && region->getParent()->asRegion()->isCanonicalizedLoop() */)) { if (trace()) traceMsg(comp(), "Found candidate non cold loop %p for expression elimination\n", region); findAndSimplifyInvariantLoopExpressions(region); } return 1; // Need to specify the cost }
static void computeInvarianceOfAllStructures(TR::Compilation *comp, TR_Structure * s) { TR_RegionStructure *region = s->asRegion(); if (region) { TR_StructureSubGraphNode *node; TR_RegionStructure::Cursor si(*region); for (node = si.getCurrent(); node != NULL; node = si.getNext()) computeInvarianceOfAllStructures(comp, node->getStructure()); region->resetInvariance(); if (region->isNaturalLoop() /*|| region->containsInternalCycles() */) { region->computeInvariantExpressions(); } } }
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; }