Ejemplo n.º 1
0
bool TR_DominatorVerifier::areBothImplementationsConsistent(TR_DominatorsChk &findDominatorsChk, TR_Dominators &findDominators)
   {
   int i;

   _dominatorsChkInfo = findDominatorsChk.getDominatorsChkInfo();

   for (i = 2; i < _numBlocks-1; i++)
      {
      TR::Block *conservativeDominator = _dominatorsChkInfo[i]._idom->_block;
      TR::Block *efficientDominator = findDominators.getDominator(_dominatorsChkInfo[i]._block);

      if (!(efficientDominator == conservativeDominator))
         {
         if (debug("traceVER"))
            {
            dumpOptDetails(comp(), "Inconsistency \n");
            dumpOptDetails(comp(), "   Dominator computed by expensive algorithm for [%p] is [%p]\n", _dominatorsChkInfo[i]._block, _dominatorsChkInfo[i]._idom->_block);
            dumpOptDetails(comp(), "   Dominator computed by efficient algorithm for [%p] is [%p]\n", _dominatorsChkInfo[i]._block, efficientDominator);
            }

         return false;
         }
     }

   return true;
   }
Ejemplo n.º 2
0
static void removeGlRegDep(TR::Node * parent, TR_GlobalRegisterNumber registerNum, TR::Block *containingBlock, TR::Optimization *opt)
   {
   if (parent->getNumChildren() == 0)
      return;

   TR_ASSERT(parent->getNumChildren() > 0, "expected TR::GlRegDeps %p", parent);
   TR::Node * predGlRegDeps = parent->getLastChild();

   if (predGlRegDeps->getOpCodeValue() != TR::GlRegDeps) // could be already removed
      return;

   TR_ASSERT(predGlRegDeps->getOpCodeValue() == TR::GlRegDeps, "expected TR::GlRegDeps");

   for (int32_t i = predGlRegDeps->getNumChildren() - 1; i >= 0; --i)
      if (predGlRegDeps->getChild(i)->getGlobalRegisterNumber() == registerNum)
         {
         dumpOptDetails(opt->comp(), "%sRemove GlRegDep : %p\n", opt->optDetailString(), predGlRegDeps->getChild(i));
         TR::Node *removedChild = predGlRegDeps->removeChild(i);
         if (removedChild->getReferenceCount() <= 1)
            {
            // The only remaining parent is the RegStore.  Another pass of
            // deadTrees may be able to eliminate that.
            //
            opt->requestOpt(OMR::deadTreesElimination, true, containingBlock);
            }
         break;
         }

   if (predGlRegDeps->getNumChildren() == 0)
      parent->removeLastChild();
   }
Ejemplo n.º 3
0
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;
   }
Ejemplo n.º 4
0
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");
      }
   }
Ejemplo n.º 5
0
TR_BitVector *
addVeryRefinedCallAliasSets(TR::ResolvedMethodSymbol * methodSymbol, TR_BitVector * aliases, List<void> * methodsPeeked)
   {
   TR::Compilation *comp = TR::comp();

   void * methodId = methodSymbol->getResolvedMethod()->getPersistentIdentifier();
   if (methodsPeeked->find(methodId))
      {
      // This can't be allocated into the alias region as it must be accessed across optimizations
      TR_BitVector *heapAliases = new (comp->trHeapMemory()) TR_BitVector(comp->getSymRefCount(), comp->trMemory(), heapAlloc, growable);
      *heapAliases |= *aliases;
      return heapAliases;
      }

   // stop if the peek is getting very deep
   //
   if (methodsPeeked->getSize() >= PEEK_THRESHOLD)
      return 0;

   methodsPeeked->add(methodId);

   dumpOptDetails(comp, "O^O REFINING ALIASES: Peeking into the IL to refine aliases \n");

   if (!methodSymbol->getResolvedMethod()->genMethodILForPeeking(methodSymbol, comp, true))
      return 0;

   TR::SymbolReferenceTable * symRefTab = comp->getSymRefTab();
   for (TR::TreeTop * tt = methodSymbol->getFirstTreeTop(); tt; tt = tt->getNextTreeTop())
      {
	   TR::Node *node = tt->getNode();
      if (node->getOpCode().isResolveCheck())
         return 0;

      if ((node->getOpCodeValue() == TR::treetop) ||
          (node->getOpCodeValue() == TR::compressedRefs) ||
          node->getOpCode().isCheck())
         node = node->getFirstChild();

      if (node->getOpCode().isStore())
         {
         TR::SymbolReference * symRefInCallee = node->getSymbolReference(), * symRefInCaller;
         TR::Symbol * symInCallee = symRefInCallee->getSymbol();
         TR::DataType type = symInCallee->getDataType();
         if (symInCallee->isShadow())
            {
            if (symInCallee->isArrayShadowSymbol())
               symRefInCaller = symRefTab->getSymRef(symRefTab->getArrayShadowIndex(type));

            else if (symInCallee->isArrayletShadowSymbol())
               symRefInCaller = symRefTab->getSymRef(symRefTab->getArrayletShadowIndex(type));

            else
               symRefInCaller = symRefTab->findShadowSymbol(symRefInCallee->getOwningMethod(comp), symRefInCallee->getCPIndex(), type);

            if (symRefInCaller)
               {
               if (symRefInCaller->reallySharesSymbol(comp))
                  symRefInCaller->setSharedShadowAliases(aliases, symRefTab);

               aliases->set(symRefInCaller->getReferenceNumber());
               }

            }
         else if (symInCallee->isStatic())
            {
            symRefInCaller = symRefTab->findStaticSymbol(symRefInCallee->getOwningMethod(comp), symRefInCallee->getCPIndex(), type);
            if (symRefInCaller)
               {
               if (symRefInCaller->reallySharesSymbol(comp))
                  symRefInCaller->setSharedStaticAliases(aliases, symRefTab);
               else
                  aliases->set(symRefInCaller->getReferenceNumber());
               }
            }
         }
      else if (node->getOpCode().isCall())
         {
         if (node->getOpCode().isCallIndirect())
            return 0;
         TR::ResolvedMethodSymbol * calleeSymbol = node->getSymbol()->getResolvedMethodSymbol();
         if (!calleeSymbol)
            return 0;
         TR_ResolvedMethod * calleeMethod = calleeSymbol->getResolvedMethod();
         if (!calleeMethod->isCompilable(comp->trMemory()) || calleeMethod->isJNINative())
            return 0;

         if (!addVeryRefinedCallAliasSets(calleeSymbol, aliases, methodsPeeked))
            return 0;
         }
      else if (node->getOpCodeValue() == TR::monent)
         return 0;
      }

   // This can't be allocated into the alias region as it must be accessed across optimizations
   TR_BitVector *heapAliases = new (comp->trHeapMemory()) TR_BitVector(comp->getSymRefCount(), comp->trMemory(), heapAlloc, growable);
   *heapAliases |= *aliases;
   return heapAliases;
   }
Ejemplo n.º 6
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()));
   }
Ejemplo n.º 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;
   }
Ejemplo n.º 8
0
int32_t TR::DeadTreesElimination::process(TR::TreeTop *startTree, TR::TreeTop *endTree)
   {
   TR::StackMemoryRegion stackRegion(*comp()->trMemory());
   LongestPathMap longestPaths(std::less<TR::Node*>(), stackRegion);

   typedef TR::typed_allocator<CRAnchor, TR::Region&> CRAnchorAlloc;
   typedef TR::forward_list<CRAnchor, CRAnchorAlloc> CRAnchorList;
   CRAnchorList anchors(stackRegion);

   vcount_t visitCount = comp()->incOrResetVisitCount();
   TR::TreeTop *treeTop;
   for (treeTop = startTree; (treeTop != endTree); treeTop = treeTop->getNextTreeTop())
      treeTop->getNode()->initializeFutureUseCounts(visitCount);

   TR::Block *block = NULL;
   bool delayedRegStoresBeforeThisPass = _delayedRegStores;

   // Update visitCount as they are used in this optimization and need to be
   visitCount = comp()->incOrResetVisitCount();
   for (TR::TreeTopIterator iter(startTree, comp()); iter != endTree; ++iter)
      {
      TR::Node *node = iter.currentTree()->getNode();

      if (node->getOpCodeValue() == TR::BBStart)
         {
         block = node->getBlock();
         if (!block->isExtensionOfPreviousBlock())
            longestPaths.clear();
         }

      int vcountLimit = MAX_VCOUNT - 3;
      if (comp()->getVisitCount() > vcountLimit)
         {
         dumpOptDetails(comp(),
            "%sVisit count %d exceeds limit %d; stopping\n",
            optDetailString(), comp()->getVisitCount(), vcountLimit);
         return 0;
         }

      // correct at all intermediate stages
      //
      if ((node->getOpCodeValue() != TR::treetop) &&
          (!node->getOpCode().isAnchor() || (node->getFirstChild()->getReferenceCount() != 1)) &&
          (!node->getOpCode().isStoreReg() || (node->getFirstChild()->getReferenceCount() != 1)) &&
          (delayedRegStoresBeforeThisPass ||
           (iter.currentTree() == block->getLastRealTreeTop()) ||
           !node->getOpCode().isStoreReg() ||
           (node->getVisitCount() == visitCount)))
         {
         if (node->getOpCode().isAnchor() && node->getFirstChild()->getOpCode().isLoadIndirect())
            anchors.push_front(CRAnchor(iter.currentTree(), block));

         TR::TransformUtil::recursivelySetNodeVisitCount(node, visitCount);
         continue;
         }

      if (node->getOpCode().isStoreReg())
         _delayedRegStores = true;

      TR::Node *child = node->getFirstChild();
      if (child->getOpCodeValue() == TR::PassThrough)
         {
         TR::Node *newChild = child->getFirstChild();
         node->setAndIncChild(0, newChild);
         newChild->incFutureUseCount();
         if (child->getReferenceCount() <= 1)
            optimizer()->prepareForNodeRemoval(child);
         child->recursivelyDecReferenceCount();
         recursivelyDecFutureUseCount(child);
         child = newChild;
         }

      bool treeTopCanBeEliminated = false;

      // If the treetop child has been seen before then it must be anchored
      // somewhere above already; so we don't need the treetop to be anchoring
      // this node (as the computation is already done at the first reference to
      // the node).
      //

      if (visitCount == child->getVisitCount())
         {
         treeTopCanBeEliminated = true;
         }
      else
         {
         TR::ILOpCode &childOpCode = child->getOpCode();
         TR::ILOpCodes opCodeValue = childOpCode.getOpCodeValue();
         bool seenConditionalBranch = false;

         bool callWithNoSideEffects = child->getOpCode().isCall() &&
              child->getSymbolReference()->getSymbol()->isResolvedMethod() &&
              child->getSymbolReference()->getSymbol()->castToResolvedMethodSymbol()->isSideEffectFree();

         if (callWithNoSideEffects)
            {
            treeTopCanBeEliminated = true;
            }
         else if (!((childOpCode.isCall() && !callWithNoSideEffects) ||
               childOpCode.isStore() ||
               ((opCodeValue == TR::New ||
                 opCodeValue == TR::anewarray ||
                 opCodeValue == TR::newarray) &&
                 child->getReferenceCount() > 1) ||
                 opCodeValue == TR::multianewarray ||
                 opCodeValue == TR::MergeNew ||
               opCodeValue == TR::checkcast ||
               opCodeValue == TR::Prefetch ||
               opCodeValue == TR::iu2l ||
               ((childOpCode.isDiv() ||
                 childOpCode.isRem()) &&
                 child->getNumChildren() == 3)))
            {
            // Perform the rather complex check to see whether its safe
            // to disconnect the child node from the treetop
            //
            bool safeToReplaceNode = false;
            if (child->getReferenceCount() == 1)
               {
               safeToReplaceNode = true;
#ifdef J9_PROJECT_SPECIFIC
               if (child->getOpCode().isPackedExponentiation())
                  {
                  // pdexp has a possible message side effect in truncating or no significant digits left cases
                  safeToReplaceNode = false;
                  }
#endif
               if (opCodeValue == TR::loadaddr)
                  treeTopCanBeEliminated = true;
               }
            else if (!_cannotBeEliminated)
               {
               safeToReplaceNode = isSafeToReplaceNode(
                  child,
                  iter.currentTree(),
                  &seenConditionalBranch,
                  visitCount,
                  comp(),
                  &_targetTrees,
                  _cannotBeEliminated,
                  longestPaths);
               }

            if (safeToReplaceNode)
               {
               if (childOpCode.hasSymbolReference())
                  {
                  TR::SymbolReference *symRef = child->getSymbolReference();

                  if (symRef->getSymbol()->isAuto() || symRef->getSymbol()->isParm())
                     treeTopCanBeEliminated = true;
                  else
                     {
                     if (childOpCode.isLoad() ||
                         (opCodeValue == TR::loadaddr) ||
                         (opCodeValue == TR::instanceof) ||
                         (((opCodeValue == TR::New)  ||
                            (opCodeValue == TR::anewarray ||
                              opCodeValue == TR::newarray)) &&
                          ///child->getFirstChild()->isNonNegative()))
                           child->markedAllocationCanBeRemoved()))
                       //        opCodeValue == TR::multianewarray ||
                       //        opCodeValue == TR::MergeNew)
                        treeTopCanBeEliminated = true;
                     }
                  }
               else
                  treeTopCanBeEliminated = true;
               }
            }

         // Fix for the case when a float to non-float conversion node swings
         // down past a branch on IA32; this would cause a FP value to be commoned
         // across a branch where there was none originally; this causes pblms
         // as a value is left on the stack.
         //
         if (treeTopCanBeEliminated &&
             seenConditionalBranch)
            {
            if (!cg()->getSupportsJavaFloatSemantics())
               {
               if (child->getOpCode().isConversion() ||
                   child->getOpCode().isBooleanCompare())
                 {
                 if (child->getFirstChild()->getOpCode().isFloatingPoint() &&
                     !child->getOpCode().isFloatingPoint())
                     treeTopCanBeEliminated = false;
                 }
               }
            }

         if (treeTopCanBeEliminated)
            {
            TR::NodeChecklist visited(comp());
            bool containsFloatingPoint = false;
            for (int32_t i = 0; i < child->getNumChildren(); ++i)
               {
               // Anchor nodes with reference count > 1
               //
               bool highGlobalIndex = false;
               if (fixUpTree(child->getChild(i), iter.currentTree(), visited, highGlobalIndex, self(), visitCount))
                  containsFloatingPoint = true;
               if (highGlobalIndex)
                  {
                  dumpOptDetails(comp(),
                     "%sGlobal index limit exceeded; stopping\n",
                     optDetailString());
                  return 0;
                  }
               }

            if (seenConditionalBranch &&
                containsFloatingPoint)
               {
               if (!cg()->getSupportsJavaFloatSemantics())
                  treeTopCanBeEliminated = false;
               }
            }
         }

      // Update visitCount as they are used in this optimization and need to be
      // correct at all intermediate stages
      //
      if (!treeTopCanBeEliminated)
         TR::TransformUtil::recursivelySetNodeVisitCount(node, visitCount);

      if (treeTopCanBeEliminated)
         {
         TR::TreeTop *prevTree = iter.currentTree()->getPrevTreeTop();
         TR::TreeTop *nextTree = iter.currentTree()->getNextTreeTop();

         if (!node->getOpCode().isStoreReg() || (node->getFirstChild()->getReferenceCount() == 1))
            {
            // Actually going to remove the treetop now
            //
            if (performTransformation(comp(), "%sRemove tree : [" POINTER_PRINTF_FORMAT "] ([" POINTER_PRINTF_FORMAT "] = %s)\n", optDetailString(), node, node->getFirstChild(), node->getFirstChild()->getOpCode().getName()))
               {
               prevTree->join(nextTree);
               optimizer()->prepareForNodeRemoval(node);
               ///child->recursivelyDecReferenceCount();
               node->recursivelyDecReferenceCount();
               recursivelyDecFutureUseCount(child);
               iter.jumpTo(prevTree);
               if (child->getReferenceCount() == 1)
                  requestOpt(OMR::treeSimplification, true, block);

               if (nextTree->getNode()->getOpCodeValue() == TR::Goto
                   && prevTree->getNode()->getOpCodeValue() == TR::BBStart
                   && !prevTree->getNode()->getBlock()->isExtensionOfPreviousBlock())
                  {
                  requestOpt(
                     OMR::redundantGotoElimination,
                     prevTree->getNode()->getBlock());
                  }
               }
            }
         else
            {
            if (performTransformation(comp(), "%sMove tree : [" POINTER_PRINTF_FORMAT "]([" POINTER_PRINTF_FORMAT "] = %s) to end of block\n", optDetailString(), node, node->getFirstChild(), node->getFirstChild()->getOpCode().getName()))
               {
               prevTree->join(nextTree);
               node->setVisitCount(visitCount);

               TR::TreeTop *lastTree = findLastTreetop(block, prevTree);
               TR::TreeTop *prevLastTree = lastTree->getPrevTreeTop();

               TR::TreeTop *cursorTreeTop = nextTree;
               while (cursorTreeTop != lastTree)
                  {
                  if (cursorTreeTop->getNode()->getOpCode().isStoreReg() &&
                      (cursorTreeTop->getNode()->getGlobalRegisterNumber() == iter.currentTree()->getNode()->getGlobalRegisterNumber()))
                     {
                     lastTree = cursorTreeTop;
                     prevLastTree = lastTree->getPrevTreeTop();
                     break;
                     }

                  cursorTreeTop = cursorTreeTop->getNextTreeTop();
                  }

               if (lastTree->getNode()->getOpCodeValue() == TR::BBStart)
                  {
                  prevLastTree = lastTree;
                  lastTree = block->getExit();
                  }

               TR::Node *lastNode = lastTree->getNode();
               TR::Node *prevLastNode = prevLastTree->getNode();

               if (lastNode->getOpCode().isIf() && !lastNode->getOpCode().isCompBranchOnly() &&
                   prevLastNode->getOpCode().isStoreReg() &&
                   ((prevLastNode->getFirstChild() == lastNode->getFirstChild()) ||
                    (prevLastNode->getFirstChild() == lastNode->getSecondChild())))
                  {
                  lastTree = prevLastTree;
                  prevLastTree = lastTree->getPrevTreeTop();
                  }

               prevLastTree->join(iter.currentTree());
               iter.currentTree()->join(lastTree);

               iter.jumpTo(prevTree);
               requestOpt(OMR::treeSimplification, true, block);
               }
            }
         }
      }

   for (auto it = anchors.begin(); it != anchors.end(); ++it)
      {
      TR::Node *anchor = it->tree->getNode();
      TR::Node *load = anchor->getChild(0);
      if (load->getReferenceCount() > 1)
         continue;

      // We can eliminate the indirect load immediately, but for the moment the
      // subtree providing the base object has to be anchored.

      TR::Node *heapBase = anchor->getChild(1);

      TR::Node::recreate(anchor, TR::treetop);
      anchor->setAndIncChild(0, load->getChild(0));
      anchor->setChild(1, NULL);
      anchor->setNumChildren(1);

      if (!heapBase->getOpCode().isLoadConst())
         {
         it->tree->insertAfter(
            TR::TreeTop::create(
               comp(),
               TR::Node::create(heapBase, TR::treetop, 1, heapBase)));
         }

      load->recursivelyDecReferenceCount();
      heapBase->recursivelyDecReferenceCount();

      // A later pass of dead trees can likely move (or even remove) the base
      // object expression.

      requestOpt(OMR::deadTreesElimination, true, it->block);
      }

   return 1; // actual cost
   }