Example #1
0
void
TR::RegDepCopyRemoval::selectNodesToReuse(TR::NodeChecklist &usedNodes)
   {
   for (TR_GlobalRegisterNumber reg = _regBegin; reg < _regEnd; reg++)
      {
      RegDepInfo &dep = getRegDepInfo(reg);
      if (dep.state != REGDEP_UNDECIDED)
         continue;

      NodeChoice &prevChoice = getNodeChoice(reg);
      if (dep.value != prevChoice.original)
         continue; // can't reuse

      // Reuse our previous choice!
      if (trace())
         traceMsg(comp(), "\t%s: prefer to reuse previous choice n%un\n", registerName(reg), prevChoice.selected->getGlobalIndex());

      TR_ASSERT(!usedNodes.contains(prevChoice.selected), "attempted to reuse the same node more than once\n");
      if (prevChoice.selected == dep.value)
         {
         dep.state = REGDEP_NODE_ORIGINAL;
         usedNodes.add(dep.value);
         }
      else
         {
         dep.state = REGDEP_NODE_REUSE_COPY;
         }
      }
   }
Example #2
0
/**
 * Collect direct loads in a node and its children, adding them to the provided BitVector.
 *
 * @param node The node to consider.
 * @param loadSymRefs BitVector of symbol reference numbers seen.
 * @param checklist Checklist of visited nodes.
 */
static void collectDirectLoads(TR::Node *node, TR_BitVector &loadSymRefs, TR::NodeChecklist &checklist)
   {
   if (checklist.contains(node))
      return;
   checklist.add(node);

   if (node->getOpCode().isLoadVarDirect())
      loadSymRefs.set(node->getSymbolReference()->getReferenceNumber());

   for (int i = 0; i < node->getNumChildren(); i++)
      collectDirectLoads(node->getChild(i), loadSymRefs, checklist);
   }
Example #3
0
void TR::SoundnessRule::checkNodeSoundness(TR::TreeTop *location, TR::Node *node,
                                           TR::NodeChecklist &ancestorNodes,
                                           TR::NodeChecklist &visitedNodes)
   {
   TR_ASSERT(node != NULL, "checkNodeSoundness requires that node is not NULL");
   if (visitedNodes.contains(node))
      {
      return;
      }
   visitedNodes.add(node);
   checkSoundnessCondition(location, !ancestorNodes.contains(node),
                           "n%dn must not be its own ancestor",
                           node->getGlobalIndex());
   ancestorNodes.add(node);
   for (int32_t i = 0; i < node->getNumChildren(); i++)
      {
      TR::Node *child = node->getChild(i);
      checkSoundnessCondition(location, child != NULL, "n%dn child %d must not be NULL",
                              node->getGlobalIndex(), i);
      checkNodeSoundness(location, child, ancestorNodes, visitedNodes);
      }
   ancestorNodes.remove(node);
   }
Example #4
0
/**
 * Recursive call to anchor nodes with a reference count greater than one prior to a treetop.
 *
 * @param comp Compilation object
 * @param node Node to potentially anchor
 * @param tt Treetop to anchor nodes before
 * @param checklist Checklist of visited nodes
 * @return Whether or not a nodes was anchored.
 */
static bool anchorCommonNodes(TR::Compilation *comp, TR::Node* node, TR::TreeTop* tt, TR::NodeChecklist &checklist)
   {
   if (checklist.contains(node))
      return false;
   checklist.add(node);

   bool anchored = false;
   if (node->getReferenceCount() > 1)
      {
      tt->insertBefore(TR::TreeTop::create(comp, TR::Node::create(TR::treetop, 1, node)));
      anchored = true;
      }
   else
      {
      for (int i = 0; i <node->getNumChildren(); i++)
         anchored |= anchorCommonNodes(comp, node->getChild(i), tt, checklist);
      }

   return anchored;
   }
Example #5
0
void
TR::RegDepCopyRemoval::updateRegDeps(TR::NodeChecklist &usedNodes)
   {
   for (TR_GlobalRegisterNumber reg = _regBegin; reg < _regEnd; reg++)
      {
      RegDepInfo &dep = getRegDepInfo(reg);
      switch (dep.state)
         {
         case REGDEP_NODE_ORIGINAL:
            rememberNodeChoice(reg, dep.value);
            break;
         case REGDEP_NODE_REUSE_COPY:
            reuseCopy(reg);
            break;
         case REGDEP_NODE_FRESH_COPY:
            makeFreshCopy(reg);
            break;
         case REGDEP_IGNORED:
            discardNodeChoice(reg);
            break;
         case REGDEP_ABSENT:
            {
            TR::Node *prevSel = getNodeChoice(reg).selected;
            if (prevSel != NULL && usedNodes.contains(prevSel))
               discardNodeChoice(reg);
            break;
            }
         case REGDEP_UNDECIDED:
            TR_ASSERT(false, "undecided preference for %s survived to updateRegDeps()\n", registerName(reg));
            break;
         default:
            TR_ASSERT(false, "%s has bad RegDepInfo state %d\n", registerName(reg), (int)dep.state);
            break;
         }
      }
   }
Example #6
0
void
TR::RegDepCopyRemoval::selectNodesToCopy(TR::NodeChecklist &usedNodes)
   {
   for (TR_GlobalRegisterNumber reg = _regBegin; reg < _regEnd; reg++)
      {
      RegDepInfo &dep = getRegDepInfo(reg);
      if (dep.state != REGDEP_UNDECIDED)
         continue;

      if (!usedNodes.contains(dep.value))
         {
         dep.state = REGDEP_NODE_ORIGINAL;
         usedNodes.add(dep.value);
         if (trace())
            traceMsg(comp(), "\t%s: prefer to keep the original node n%un\n", registerName(reg), dep.value->getGlobalIndex());
         }
      else
         {
         dep.state = REGDEP_NODE_FRESH_COPY;
         if (trace())
            traceMsg(comp(), "\t%s: prefer to make a new copy of n%un\n", registerName(reg), dep.value->getGlobalIndex());
         }
      }
   }
Example #7
0
static bool fixUpTree(TR::Node *node, TR::TreeTop *treeTop, TR::NodeChecklist &visited, bool &highGlobalIndex, TR::Optimization *opt, vcount_t evaluatedVisitCount)
   {
   if (node->getVisitCount() == evaluatedVisitCount)
      return false;

   if (visited.contains(node))
      return false;

   visited.add(node);

   bool containsFloatingPoint = false;
   bool anchorLoadaddr = true;
   bool anchorArrayCmp = true;

   // for arraycmp node, don't create its tree top anchor
   // fold it into if statment and save jump instruction
   if (node->getOpCodeValue() == TR::arraycmp &&
      !node->isArrayCmpLen() &&
      TR::Compiler->target.cpu.isX86())
      {
      anchorArrayCmp = false;
      }

   if ((node->getReferenceCount() > 1) &&
       !node->getOpCode().isLoadConst() &&
       anchorLoadaddr &&
       anchorArrayCmp)
      {
      if (!opt->comp()->getOption(TR_ProcessHugeMethods))
         {
         int32_t nodeCount = opt->comp()->getNodeCount();
         int32_t nodeCountLimit = 3 * USHRT_MAX / 4;
         if (nodeCount > nodeCountLimit)
            {
            dumpOptDetails(opt->comp(),
               "%snode count %d exceeds limit %d\n",
               opt->optDetailString(), nodeCount, nodeCountLimit);
            highGlobalIndex = true;
            return containsFloatingPoint;
            }
         }

      if (node->getOpCode().isFloatingPoint())
        containsFloatingPoint = true;
      TR::TreeTop *nextTree = treeTop->getNextTreeTop();
      node->incFutureUseCount();
      TR::TreeTop *anchorTreeTop = TR::TreeTop::create(opt->comp(), TR::Node::create(TR::treetop, 1, node));
      anchorTreeTop->getNode()->setFutureUseCount(0);
      treeTop->join(anchorTreeTop);
      anchorTreeTop->join(nextTree);
      }
   else
      {
      for (int32_t i = 0; i < node->getNumChildren(); ++i)
         {
         TR::Node *child = node->getChild(i);
         if (fixUpTree(child, treeTop, visited, highGlobalIndex, opt, evaluatedVisitCount))
            containsFloatingPoint = true;
         }
      }
   return containsFloatingPoint;
   }