Exemplo n.º 1
0
void
TR_ReachabilityAnalysis::perform(TR_BitVector *result)
   {
   TR::CFG *cfg = comp()->getFlowGraph();
   int32_t numBlockIndexes = cfg->getNextNodeNumber();
   int32_t numBlocks       = cfg->getNumberOfNodes();

   _blocks = cfg->createArrayOfBlocks();

   blocknum_t *stack    = (blocknum_t*)comp()->trMemory()->allocateStackMemory(numBlockIndexes * sizeof(stack[0]));
   blocknum_t *depthMap = (blocknum_t*)comp()->trMemory()->allocateStackMemory(numBlockIndexes * sizeof(depthMap[0]));
   memset(depthMap, 0, numBlockIndexes * sizeof(depthMap[0]));

   bool trace = comp()->getOption(TR_TraceReachability);

   if (trace)
      traceMsg(comp(), "BEGIN REACHABILITY: %d blocks\n", numBlocks);

   for (TR::Block *block = comp()->getStartBlock(); block; block = block->getNextBlock())
      {
      blocknum_t blockNum = block->getNumber();
      if (trace)
         traceMsg(comp(), "Visit block_%d\n", blockNum);
      if (depthMap[blockNum] == 0)
         traverse(blockNum, 0, stack, depthMap, result);
      else
         traceMsg(comp(), "  depth is already %d; skip\n", depthMap[blockNum]);
      }

   if (comp()->getOption(TR_TraceReachability))
      {
      traceMsg(comp(), "END REACHABILITY.  Result:\n");
      result->print(comp(), comp()->getOutFile());
      traceMsg(comp(), "\n");
      }
   }
Exemplo n.º 2
0
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;
   }
Exemplo n.º 3
0
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()));
   }