TR::Block *
TR_ExpressionsSimplification::findPredecessorBlock(TR::CFGNode *entryNode)
   {
   if (!(entryNode->getPredecessors().size() == 2))
       return 0;


   TR::Block *block = 0;

   for (auto edge = entryNode->getPredecessors().begin(); edge != entryNode->getPredecessors().end(); ++edge)
      {
      if ((*edge)->getFrom()->getSuccessors().size() == 1)
         {
         block = toBlock((*edge)->getFrom());
         if (block->getStructureOf()->isLoopInvariantBlock())
            break;
         else
            block = 0;
         }
      }
   //traceMsg(comp(), "Commoned code will be put in block_%d\n", block->getNumber());
   return block;
   }
Beispiel #2
0
TR::TreeTop *
OMR::Simplifier::simplifyExtendedBlock(TR::TreeTop * treeTop)
   {
   TR::Block * block = 0;

   _containingStructure = NULL;
   _blockRemoved = false;

   for (; treeTop; treeTop = treeTop->getNextTreeTop())
      {
      TR::Node * node = treeTop->getNode();
      TR_ASSERT(node->getOpCodeValue() == TR::BBStart, "Simplification, expected BBStart treetop");

      TR::Block * b = node->getBlock();
      if (block && !b->isExtensionOfPreviousBlock())
         break;

      if (b->isOSRCodeBlock() || b->isOSRCatchBlock())
         {
         b->setHasBeenVisited();
         treeTop = b->getExit();
         continue;
         }

#ifdef DEBUG
      if (block != b)
         b->setHasBeenVisited();
#endif

      if (!block && _reassociate &&
          comp()->getFlowGraph()->getStructure() != NULL         // [99391] getStructureOf() only valid if structure isn't invalidated
         )
         { // b is first block in the extended block
         TR_BlockStructure *blockStructure = b->getStructureOf();

         if(blockStructure)
            {
            TR_Structure *parent = blockStructure->getParent();
            while (parent)
               {
               TR_RegionStructure *region = parent->asRegion();
               if (region->isNaturalLoop() /* || region->containsInternalCycles() */)
                  {
                  _containingStructure = region;
                  break;
                  }
               parent = parent->getParent();
               }
            }
         }

      block = b;

      if (trace())
         traceMsg(comp(), "simplifying block_%d\n", block->getNumber());

      _performLowerTreeSimplifier=NULL;
      _performLowerTreeNode=NULL;
      simplify(block);

      if(_performLowerTreeSimplifier)
         {
         _performLowerTreeNode = postWalkLowerTreeSimplifier(_performLowerTreeSimplifier, _performLowerTreeNode, block, (TR::Simplifier *) this);
         _performLowerTreeSimplifier->setNode(_performLowerTreeNode);
         }

      // If the block itself was removed from the CFG during simplification, find
      // the next 'legitimate' block to be simplified
      //
      //if (comp()->getFlowGraph()->getRemovedNodes().find(block))
        if(block->nodeIsRemoved())
         {
         TR::TreeTop * tt = findNextLegalTreeTop(comp(), block);
         // in certain cases the removed block might be the last one we haven't
         // visited and therefore we won't be able to find a treetop to continue
         // in such cases we exit the loop
         //
         treeTop = tt ? tt->getPrevTreeTop() : 0;
         if (!treeTop)
            break;
         }
      else
         {
         treeTop = block->getExit();
         }
      }

   // now remove any unreachable blocks
   //
   if (_blockRemoved)
      {
      // if the next block to be processed has been removed,
      // find the next valid block to process
      //
      if (treeTop)
         {
         TR::Block *b = treeTop->getNode()->getBlock();
         //if (comp()->getFlowGraph()->getRemovedNodes().find(b))
           if(b->nodeIsRemoved())
            treeTop = findNextLegalTreeTop(comp(), b);
         }
      }

   return treeTop;
   }
Beispiel #3
0
TR_GlobalRegisterNumber
OMR::X86::I386::CodeGenerator::pickRegister(
      TR_RegisterCandidate *rc,
      TR::Block **allBlocks,
      TR_BitVector &availableRegisters,
      TR_GlobalRegisterNumber &highRegisterNumber,
      TR_LinkHead<TR_RegisterCandidate> *candidates)
   {
   if (!self()->comp()->getOption(TR_DisableRegisterPressureSimulation))
      {
      if (self()->comp()->getOption(TR_AssignEveryGlobalRegister))
         {
         // This is not really necessary except for testing purposes.
         // Conceptually, the common pickRegister code should be free to make
         // its choices based only on performance considerations, and shouldn't
         // need to worry about correctness.  When SupportsVMThreadGRA is not set,
         // it is incorrect to choose the VMThread register.  Therefore we mask
         // it out here.
         //
         // Having said that, the common code *does* already mask out the
         // VMThread register for convenience, so under normal circumstances,
         // this code is redundant.  It is only necessary when
         // TR_AssignEveryGlobalRegister is set.
         //
         availableRegisters -= *self()->getGlobalRegisters(TR_vmThreadSpill, self()->comp()->getMethodSymbol()->getLinkageConvention());
         }
      return OMR::CodeGenerator::pickRegister(rc, allBlocks, availableRegisters, highRegisterNumber, candidates);
      }

   if ((rc->getSymbol()->getDataType() == TR::Float) ||
       (rc->getSymbol()->getDataType() == TR::Double))
      {
      if (availableRegisters.get(7))
         return 7;
      if (availableRegisters.get(8))
         return 8;
      if (availableRegisters.get(9))
         return 9;
      if (availableRegisters.get(10))
         return 10;
      if (availableRegisters.get(11))
         return 11;
      if (availableRegisters.get(12))
         return 12;

      return -1;
      }


   if (!_assignedGlobalRegisters)
      _assignedGlobalRegisters = new (self()->trStackMemory()) TR_BitVector(self()->comp()->getSymRefCount(), self()->trMemory(), stackAlloc, growable);

   if (availableRegisters.get(5))
      return 5; // esi

   if (availableRegisters.get(2))
      return 2; // ecx

   static char *dontUseEBXasGPR = feGetEnv("dontUseEBXasGPR");
   if (!dontUseEBXasGPR && availableRegisters.get(1))
      return 1;

#ifdef J9_PROJECT_SPECIFIC
   TR::RecognizedMethod rm = self()->comp()->getMethodSymbol()->getRecognizedMethod();
   if (rm == TR::java_util_HashtableHashEnumerator_hasMoreElements)
      {
      if (availableRegisters.get(4))
         return 4; // edi
      if (availableRegisters.get(3))
         return 3; // edx
      }
   else
#endif
      {
      int32_t numExtraRegs = 0;
      int32_t maxRegisterPressure = 0;

      vcount_t visitCount = self()->comp()->incVisitCount();
      TR_BitVectorIterator bvi(rc->getBlocksLiveOnEntry());
      int32_t maxFrequency = 0;
      while (bvi.hasMoreElements())
         {
         int32_t liveBlockNum = bvi.getNextElement();
         TR::Block *block = allBlocks[liveBlockNum];
         if (block->getFrequency() > maxFrequency)
             maxFrequency = block->getFrequency();
         }

      int32_t maxStaticFrequency = 0;
      if (maxFrequency == 0)
         {
         bvi.setBitVector(rc->getBlocksLiveOnEntry());
         while (bvi.hasMoreElements())
            {
            int32_t liveBlockNum = bvi.getNextElement();
            TR::Block *block = allBlocks[liveBlockNum];
            TR_BlockStructure *blockStructure = block->getStructureOf();
            int32_t blockWeight = 1;
            if (blockStructure &&
                !block->isCold())
               {
               blockStructure->calculateFrequencyOfExecution(&blockWeight);
               if (blockWeight > maxStaticFrequency)
                  maxStaticFrequency = blockWeight;
               }
            }
         }

      bool assigningEDX = false;
      if (!availableRegisters.get(4) &&
          availableRegisters.get(3))
         assigningEDX = true;

      bool vmThreadUsed = false;

      bvi.setBitVector(rc->getBlocksLiveOnEntry());
      while (bvi.hasMoreElements())
         {
         int32_t liveBlockNum = bvi.getNextElement();
         TR::Block *block = allBlocks[liveBlockNum];

         _assignedGlobalRegisters->empty();
         int32_t numAssignedGlobalRegs = 0;
         TR_RegisterCandidate *prev;
         for (prev = candidates->getFirst(); prev; prev = prev->getNext())
            {
            bool gprCandidate = true;
            if ((prev->getSymbol()->getDataType() == TR::Float) ||
                (prev->getSymbol()->getDataType() == TR::Double))
               gprCandidate = false;
            if (gprCandidate && prev->getBlocksLiveOnEntry().get(liveBlockNum))
               {
               numAssignedGlobalRegs++;
               if (prev->getDataType() == TR::Int64)
                  numAssignedGlobalRegs++;
               _assignedGlobalRegisters->set(prev->getSymbolReference()->getReferenceNumber());
               }
            }

         maxRegisterPressure = self()->estimateRegisterPressure(block, visitCount, maxStaticFrequency, maxFrequency, vmThreadUsed, numAssignedGlobalRegs, _assignedGlobalRegisters, rc->getSymbolReference(), assigningEDX);

         if (maxRegisterPressure >= self()->getMaximumNumbersOfAssignableGPRs())
            break;
         }

      // Determine if we can spare any extra registers for this candidate without spilling
      // in any hot (critical) blocks
      //
      if (maxRegisterPressure < self()->getMaximumNumbersOfAssignableGPRs())
         numExtraRegs = self()->getMaximumNumbersOfAssignableGPRs() - maxRegisterPressure;

      //dumpOptDetails("For global register candidate %d reg pressure is %d maxRegs %d numExtraRegs %d\n", rc->getSymbolReference()->getReferenceNumber(), maxRegisterPressure, comp()->cg()->getMaximumNumbersOfAssignableGPRs(), numExtraRegs);

      if (numExtraRegs > 0)
         {
         if (availableRegisters.get(4))
            return 4; // edi

         if (availableRegisters.get(3))
            return 3; // edx
         }
      }

   return -1; // -1 ==> don't use a global register
   }