Ejemplo n.º 1
0
TR::Node *TR_OutlinedInstructions::createOutlinedCallNode(TR::Node *callNode, TR::ILOpCodes callOp)
   {
   int32_t   i;
   TR::Node  *child;

   //We pass true for getSymbolReference because
   TR::Node *newCallNode = TR::Node::createWithSymRef(callNode, callOp, callNode->getNumChildren(), callNode->getSymbolReference());

   newCallNode->setReferenceCount(1);

   for (i=0; i<callNode->getNumChildren(); i++)
      {
      child = callNode->getChild(i);

      if (child->getRegister() != NULL)
         {
         // Child has already been evaluated outside this tree.
         //
         newCallNode->setAndIncChild(i, child);
         }
      else if (child->getOpCode().isLoadConst())
         {
         // Copy unevaluated constant nodes.
         //
         child = TR::Node::copy(child);
         child->setReferenceCount(1);
         newCallNode->setChild(i, child);
         }
      else
         {
         if ((child->getOpCodeValue() == TR::loadaddr) &&
             /*(callNode->getOpCodeValue() == TR::instanceof || callNode->getOpCodeValue() == TR::checkcast || callNode->getOpCodeValue() == TR::checkcastAndNULLCHK || callNode->getOpCodeValue() == TR::New || callNode->getOpCodeValue() == TR::anewarray)    &&*/
             (child->getSymbolReference()->getSymbol()) &&
             (child->getSymbolReference()->getSymbol()->getStaticSymbol()))
            {
            child = TR::Node::copy(child);
            child->setReferenceCount(1);
            newCallNode->setChild(i, child);
            }
         else
            {
            // Be very conservative at this point, even though it is possible to make it less so.  For example, this will catch
            // the case of an unevaluated argument not persisting outside of the outlined region even though one of its subtrees will.
            //
            (void)_cg->evaluate(child);

            // Do not decrement the reference count here.  It will be decremented when the call node is evaluated
            // again in the helper instruction stream.
            //
            newCallNode->setAndIncChild(i, child);
            }
         }
      }
   if(callNode->isPreparedForDirectJNI())
      {
         newCallNode->setPreparedForDirectJNI();
      }

   return newCallNode;
   }
Ejemplo n.º 2
0
// resolved casts that are not to abstract, interface, or array need a super test
bool OMR::TreeEvaluator::instanceOfOrCheckCastNeedSuperTest(TR::Node * node, TR::CodeGenerator *cg)
   {
   TR::Node            *castClassNode    = node->getSecondChild();
   TR::MethodSymbol    *helperSym        = node->getSymbol()->castToMethodSymbol();
   TR::SymbolReference *castClassSymRef  = castClassNode->getSymbolReference();

   if (!TR::TreeEvaluator::isStaticClassSymRef(castClassSymRef))
      {
      // We could theoretically do a super test on something with no sym, but it would require significant
      // changes to platform code. The benefit is little at this point (shows up from reference arraycopy reductions)

      if (cg->supportsInliningOfIsInstance() &&
          node->getOpCodeValue() == TR::instanceof &&
          node->getSecondChild()->getOpCodeValue() != TR::loadaddr)
         return true;
      else
         return false;
      }

   TR::StaticSymbol    *castClassSym = castClassSymRef->getSymbol()->getStaticSymbol();

   if (castClassSymRef->isUnresolved())
      {
      return false;
      }
   else
      {
      TR_OpaqueClassBlock * clazz;
      // If the class is a regular class (i.e., not an interface nor an array) and
      // not known to be a final class, an inline superclass test can be generated.
      // If the helper does not preserve all the registers there will not be
      // enough registers to do the superclass test inline.
      // Also, don't generate the superclass test if optimizing for space.
      //
      if (castClassSym &&
          (clazz = (TR_OpaqueClassBlock *) castClassSym->getStaticAddress()) &&
          !TR::Compiler->cls.isClassArray(cg->comp(), clazz) &&
          !TR::Compiler->cls.isInterfaceClass(cg->comp(), clazz) &&
          !TR::Compiler->cls.isClassFinal(cg->comp(), clazz) &&
           helperSym->preservesAllRegisters() &&
          !cg->comp()->getOption(TR_OptimizeForSpace))
         return true;
      }
   return false;
   }
Ejemplo n.º 3
0
// unresolved casts or casts to things other than abstract or interface benefit from
// an equality test
bool OMR::TreeEvaluator::instanceOfOrCheckCastNeedEqualityTest(TR::Node * node, TR::CodeGenerator *cg)
   {
   TR::Node            *castClassNode    = node->getSecondChild();
   TR::SymbolReference *castClassSymRef  = castClassNode->getSymbolReference();

   if (!TR::TreeEvaluator::isStaticClassSymRef(castClassSymRef))
      {
      return true;
      }

   TR::StaticSymbol    *castClassSym     = castClassSymRef->getSymbol()->getStaticSymbol();

   if (castClassSymRef->isUnresolved())
      {
      return false;
      }
   else
      {
      TR_OpaqueClassBlock * clazz;

      if (castClassSym
          && (clazz = (TR_OpaqueClassBlock *) castClassSym->getStaticAddress())
          && !TR::Compiler->cls.isInterfaceClass(cg->comp(), clazz)
          && (
              !TR::Compiler->cls.isAbstractClass(cg->comp(), clazz)

              // here be dragons
              // int.class, char.class, etc are final & abstract
              // usually instanceOf calls on these classes are ripped out by the optimizer
              // but in some cases they can persist to codegen which without the following
              // case causes assertions because we opt out of calling the helper and doing
              // all inline tests. Really we could just jmp to the failed side, but to reduce
              // service risk we are going to do an equality test that we know will fail
              // NOTE final abstract is not enough - all array classes are final abstract
              //      to prevent them being used with new and being extended...
              || (TR::Compiler->cls.isAbstractClass(cg->comp(), clazz) && TR::Compiler->cls.isClassFinal(cg->comp(), clazz)
                  && TR::Compiler->cls.isPrimitiveClass(cg->comp(), clazz)))
         )
         return true;
      }

   return false;
   }
Ejemplo n.º 4
0
int32_t TR_LocalAnalysisInfo::HashTable::hash(TR::Node *node)
   {
   // Hash on the opcode and value numbers of the children
   //
   uint32_t h, g;
   int32_t numChildren = node->getNumChildren();
   h = (node->getOpCodeValue() << 4) + numChildren;
   g = 0;
   for (int32_t i = numChildren-1; i >= 0; i--)
      {
      TR::Node *child = node->getChild(i);
      h <<= 4;

      if (child->getOpCode().hasSymbolReference())
         h += (int32_t)(intptrj_t)child->getSymbolReference()->getSymbol();
      else
         h++;

      g = h & 0xF0000000;
      h ^= g >> 24;
      }
   return (h ^ g) % _numBuckets;
   }
Ejemplo n.º 5
0
bool TR_ExpressionsSimplification::tranformSummationReductionCandidate(TR::TreeTop *treeTop, LoopInfo *loopInfo, bool *isPreheaderBlockInvalid)
   {
   TR::Node *node = treeTop->getNode();
   TR::Node *opNode = node->getFirstChild();
   TR::Node *expNode = NULL;
   int32_t expChildNumber = 0;
   bool removeOnly = false;
   bool replaceWithNewNode = false;

   if (opNode->getOpCodeValue() == TR::iadd || opNode->getOpCodeValue() == TR::isub)
      {
      if (opNode->getSecondChild()->getOpCode().hasSymbolReference() &&
            node->getSymbolReference() == opNode->getSecondChild()->getSymbolReference())
         {
         expChildNumber = 0;
         expNode = opNode->getFirstChild();
         }
      else
         {
         expChildNumber = 1;
         expNode = opNode->getSecondChild();
         }
      expNode = iaddisubSimplifier(expNode, loopInfo);
      replaceWithNewNode = true;
      }
   else if (opNode->getOpCodeValue() == TR::ixor || opNode->getOpCodeValue() == TR::ineg)
      {
      expNode = ixorinegSimplifier(opNode, loopInfo, &removeOnly);
      }

   if (expNode)
      {
      if (trace())
         comp()->getDebug()->print(comp()->getOutFile(), expNode, 0, true);

      TR::Block *entryBlock = _currentRegion->getEntryBlock();
      TR::Block *preheaderBlock = findPredecessorBlock(entryBlock);

      if (!preheaderBlock)
         {
         if (trace())
            traceMsg(comp(), "Fail to find a place to put the hoist code in\n");
         *isPreheaderBlockInvalid = true;
         return true;
         }

      if (loopInfo->getNumIterations() > 0 ||     // make sure that the loop is going to be executed at least once
            _currentRegion->isCanonicalizedLoop())  // or that the loop is canonicalized, in which case the preheader is
         {                                        // executed in its first iteration and is protected.
         if (performTransformation(comp(), "%sMove out loop-invariant node [%p] to block_%d\n", OPT_DETAILS, node, preheaderBlock->getNumber()))
            {
            if (!(removeOnly))
               {
               TR::Node *newNode = node->duplicateTree();
               if (replaceWithNewNode)
                  newNode->getFirstChild()->setAndIncChild(expChildNumber, expNode);
               transformNode(newNode, preheaderBlock);
               }
            TR::TransformUtil::removeTree(comp(), treeTop);
            }
         }
      }
      return (expNode != NULL);
   }
Ejemplo n.º 6
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
   }
Ejemplo n.º 7
0
void
TR_S390BinaryAnalyser::genericAnalyser(TR::Node * root,
                                       TR::InstOpCode::Mnemonic regToRegOpCode,
                                       TR::InstOpCode::Mnemonic memToRegOpCode,
                                       TR::InstOpCode::Mnemonic copyOpCode)
   {
   TR::Node * firstChild;
   TR::Node * secondChild;
   firstChild = root->getFirstChild();
   secondChild = root->getSecondChild();
   TR::Register * firstRegister = firstChild->getRegister();
   TR::Register * secondRegister = secondChild->getRegister();
   TR::Compilation *comp = TR::comp();

   TR::SymbolReference * firstReference = firstChild->getOpCode().hasSymbolReference() ? firstChild->getSymbolReference() : NULL;
   TR::SymbolReference * secondReference = secondChild->getOpCode().hasSymbolReference() ? secondChild->getSymbolReference() : NULL;

   setInputs(firstChild, firstRegister, secondChild, secondRegister,
             false, false, comp,
             (cg()->isAddressOfStaticSymRefWithLockedReg(firstReference) ||
              cg()->isAddressOfPrivateStaticSymRefWithLockedReg(firstReference)),
             (cg()->isAddressOfStaticSymRefWithLockedReg(secondReference) ||
              cg()->isAddressOfPrivateStaticSymRefWithLockedReg(secondReference)));

   /*
    * Check if SH or CH can be used to evaluate this integer subtract/compare node.
    * The second operand of SH/CH is a 16-bit number from memory. And using
    * these directly can save a load instruction.
    */
   bool is16BitMemory2Operand = false;
   if (secondChild->getOpCodeValue() == TR::s2i &&
       secondChild->getFirstChild()->getOpCodeValue() == TR::sloadi &&
       secondChild->isSingleRefUnevaluated() &&
       secondChild->getFirstChild()->isSingleRefUnevaluated())
      {
      bool supported = true;

      if (memToRegOpCode == TR::InstOpCode::S)
         {
         memToRegOpCode = TR::InstOpCode::SH;
         }
      else if (memToRegOpCode == TR::InstOpCode::C)
         {
         memToRegOpCode = TR::InstOpCode::CH;
         }
      else
         {
         supported = false;
         }

      if (supported)
         {
         setMem2();
         is16BitMemory2Operand = true;
         }
      }

   if (getEvalChild1())
      {
      firstRegister = cg()->evaluate(firstChild);
      }

   if (getEvalChild2())
      {
      secondRegister = cg()->evaluate(secondChild);
      }

   remapInputs(firstChild, firstRegister, secondChild, secondRegister);

   if (getCopyReg1())
      {
      TR::Register * thirdReg;
      bool done = false;

      if (firstRegister->getKind() == TR_GPR64)
         {
         thirdReg = cg()->allocate64bitRegister();
         }
      else if (firstRegister->getKind() == TR_VRF)
         {
         TR_ASSERT(false,"VRF: genericAnalyser unimplemented");
         }
      else if (firstRegister->getKind() != TR_FPR && firstRegister->getKind() != TR_VRF)
         {
         thirdReg = cg()->allocateRegister();
         }
      else
         {
         thirdReg = cg()->allocateRegister(TR_FPR);
         }

      if (cg()->getS390ProcessorInfo()->supportsArch(TR_S390ProcessorInfo::TR_z196))
         {
         if (getBinaryReg3Reg2() || secondRegister != NULL)
            {
            if (regToRegOpCode == TR::InstOpCode::SR)
               {
               generateRRRInstruction(cg(), TR::InstOpCode::SRK, root, thirdReg, firstRegister, secondRegister);
               done = true;
               }
            else if (regToRegOpCode == TR::InstOpCode::SLR)
               {
               generateRRRInstruction(cg(), TR::InstOpCode::SLRK, root, thirdReg, firstRegister, secondRegister);
               done = true;
               }
            else if (regToRegOpCode == TR::InstOpCode::SGR)
               {
               generateRRRInstruction(cg(), TR::InstOpCode::SGRK, root, thirdReg, firstRegister, secondRegister);
               done = true;
               }
            else if (regToRegOpCode == TR::InstOpCode::SLGR)
               {
               generateRRRInstruction(cg(), TR::InstOpCode::SLGRK, root, thirdReg, firstRegister, secondRegister);
               done = true;
               }
            }
         }

      if (!done)
         {
         generateRRInstruction(cg(), copyOpCode, root, thirdReg, firstRegister);
         if (getBinaryReg3Reg2() || (secondRegister != NULL))
            {
            generateRRInstruction(cg(), regToRegOpCode, root, thirdReg, secondRegister);
            }
         else
            {
            TR::Node* loadBaseAddr = is16BitMemory2Operand ? secondChild->getFirstChild() : secondChild;
            TR::MemoryReference * tempMR = generateS390MemoryReference(loadBaseAddr, cg());

            //floating-point arithmatics don't have RXY format instructions, so no long displacement
            if (secondChild->getOpCode().isFloatingPoint())
               {
               tempMR->enforce4KDisplacementLimit(secondChild, cg(), NULL);
               }

            generateRXInstruction(cg(), memToRegOpCode, root, thirdReg, tempMR);
            tempMR->stopUsingMemRefRegister(cg());
            if (is16BitMemory2Operand)
               {
               cg()->decReferenceCount(secondChild->getFirstChild());
               }
            }
         }

      root->setRegister(thirdReg);
      }
   else if (getBinaryReg1Reg2())
      {
      generateRRInstruction(cg(), regToRegOpCode, root, firstRegister, secondRegister);
      root->setRegister(firstRegister);
      }
   else // assert getBinaryReg1Mem2() == true
      {
      TR_ASSERT(  !getInvalid(), "TR_S390BinaryAnalyser::invalid case\n");

      TR::MemoryReference * tempMR = generateS390MemoryReference(is16BitMemory2Operand ? secondChild->getFirstChild() : secondChild, cg());
      //floating-point arithmatics don't have RXY format instructions, so no long displacement
      if (secondChild->getOpCode().isFloatingPoint())
         {
         tempMR->enforce4KDisplacementLimit(secondChild, cg(), NULL);
         }

      generateRXInstruction(cg(), memToRegOpCode, root, firstRegister, tempMR);
      tempMR->stopUsingMemRefRegister(cg());
      if (is16BitMemory2Operand)
         cg()->decReferenceCount(secondChild->getFirstChild());
      root->setRegister(firstRegister);
      }

   cg()->decReferenceCount(firstChild);
   cg()->decReferenceCount(secondChild);

   return;
   }
Ejemplo n.º 8
0
// Returns true if there is any constraint to the move
bool TR_LocalLiveRangeReduction::isAnySymInDefinedOrUsedBy(TR_TreeRefInfo *currentTreeRefInfo, TR::Node *currentNode, TR_TreeRefInfo *movingTreeRefInfo )
   {
   TR::Node *movingNode = movingTreeRefInfo->getTreeTop()->getNode();
   // ignore anchors
   //
   if (movingNode->getOpCode().isAnchor())
      movingNode = movingNode->getFirstChild();

   TR::ILOpCode &opCode = currentNode->getOpCode();

   ////if ((opCode.getOpCodeValue() == TR::monent) || (opCode.getOpCodeValue() == TR::monexit))
   if (nodeMaybeMonitor(currentNode))
      {
      if (trace())
    	 traceMsg(comp(),"cannot move %p beyond monitor %p\n",movingNode,currentNode);
      return true;
      }

   // Don't move gc points or things across gc points
   //
   if (movingNode->canGCandReturn() ||
         currentNode->canGCandReturn())
      {
      if (trace())
         traceMsg(comp(), "cannot move gc points %p past %p\n", movingNode, currentNode);
      return true;
      }

   // Don't move checks or calls at all
   //
   if (containsCallOrCheck(movingTreeRefInfo,movingNode))
      {
      if (trace())
    	   traceMsg(comp(),"cannot move check or call %s\n", getDebug()->getName(movingNode));
      return true;
      }

   // Don't move object header store past a GC point
   //
   if ((currentNode->getOpCode().isWrtBar() || currentNode->canCauseGC()) && mayBeObjectHeaderStore(movingNode, fe()))
      {
      if (trace())
    	   traceMsg(comp(),"cannot move possible object header store %s past GC point %s\n", getDebug()->getName(movingNode), getDebug()->getName(currentNode));
      return true;
      }

   if (TR::Compiler->target.cpu.isPower() && opCode.getOpCodeValue() == TR::allocationFence)
      {
      // Can't move allocations past flushes
      if (movingNode->getOpCodeValue() == TR::treetop &&
          movingNode->getFirstChild()->getOpCode().isNew() &&
          (currentNode->getAllocation() == NULL ||
           currentNode->getAllocation() == movingNode->getFirstChild()))
         {
         if (trace())
            {
            traceMsg(comp(),"cannot move %p beyond flush %p - ", movingNode, currentNode);
            if (currentNode->getAllocation() == NULL)
               traceMsg(comp(),"(flush with null allocation)\n");
            else
               traceMsg(comp(),"(flush for allocation %p)\n", currentNode->getAllocation());
            }
         return true;
         }

      // Can't move certain stores past flushes
      // Exclude all indirect stores, they may be for stack allocs, in which case the flush is needed at least as a scheduling barrier
      // Direct stores to autos and parms are the only safe candidates
      if (movingNode->getOpCode().isStoreIndirect() ||
          (movingNode->getOpCode().isStoreDirect() && !movingNode->getSymbol()->isParm() && !movingNode->getSymbol()->isAuto()))
         {
         if (trace())
            traceMsg(comp(),"cannot move %p beyond flush %p - (flush for possible stack alloc)", movingNode, currentNode);
         return true;
         }
      }

   for (int32_t i = 0; i < currentNode->getNumChildren(); i++)
      {
      TR::Node *child = currentNode->getChild(i);

      //Any node that has side effects (like call and newarrya) cannot be evaluated in the middle of the tree.
      if (movingTreeRefInfo->getFirstRefNodesList()->find(child))
         {
         //for calls and unresolve symbol that are not under check

         if (child->exceptionsRaised() ||
             (child->getOpCode().hasSymbolReference() && child->getSymbolReference()->isUnresolved()))
    	    {
    	    if (trace())
    	       traceMsg(comp(),"cannot move %p beyond %p - cannot change evaluation point of %p\n ",movingNode,currentTreeRefInfo->getTreeTop()->getNode(),child);
            return true;
    	    }

         else if(movingNode->getOpCode().isStore())
            {
            TR::SymbolReference *stSymRef = movingNode->getSymbolReference();
            int32_t stSymRefNum = stSymRef->getReferenceNumber();
            //TR::SymbolReference *stSymRef = movingNode->getSymbolReference();
            int32_t numHelperSymbols = comp()->getSymRefTab()->getNumHelperSymbols();
            if ((comp()->getSymRefTab()->isNonHelper(stSymRefNum, TR::SymbolReferenceTable::vftSymbol))||
                (comp()->getSymRefTab()->isNonHelper(stSymRefNum, TR::SymbolReferenceTable::contiguousArraySizeSymbol))||
                (comp()->getSymRefTab()->isNonHelper(stSymRefNum, TR::SymbolReferenceTable::discontiguousArraySizeSymbol))||
                (stSymRef == comp()->getSymRefTab()->findHeaderFlagsSymbolRef())||
                (stSymRef->getSymbol() == comp()->getSymRefTab()->findGenericIntShadowSymbol()))

               return true;
            }

         else if (movingNode->getOpCode().isResolveOrNullCheck())
            {
    	    if (trace())
    	       traceMsg(comp(),"cannot move %p beyond %p - node %p under ResolveOrNullCheck",movingNode,currentTreeRefInfo->getTreeTop()->getNode(),currentNode);
            return true;
            }

    	 else if (TR::Compiler->target.is64Bit() &&
    		  movingNode->getOpCode().isBndCheck() &&
    		  ((opCode.getOpCodeValue() == TR::i2l) || (opCode.getOpCodeValue() == TR::iu2l)) &&
    		  !child->isNonNegative())
    	    {
    	    if (trace())
    	       traceMsg(comp(),"cannot move %p beyond %p - changing the eval point of %p will casue extra cg instruction ",movingNode,currentTreeRefInfo->getTreeTop()->getNode(),currentNode);
    	    return true;
    	    }
         }

      //don't recurse over nodes each are not the first reference
      if (child->getReferenceCount()==1 || currentTreeRefInfo->getFirstRefNodesList()->find(child))
         {
         if (isAnySymInDefinedOrUsedBy(currentTreeRefInfo, child, movingTreeRefInfo ))
            return true;
         }
      }

   return false;
   }
Ejemplo n.º 9
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.º 10
0
void
TR_Debug::print(TR::FILE *pOutFile, TR::S390CallSnippet * snippet)
   {
   uint8_t * bufferPos = snippet->getSnippetLabel()->getCodeLocation();
   TR::Node * callNode = snippet->getNode();
   TR::SymbolReference * methodSymRef = snippet->getRealMethodSymbolReference();
   if(!methodSymRef)
      methodSymRef = callNode->getSymbolReference();

   TR::MethodSymbol * methodSymbol = methodSymRef->getSymbol()->castToMethodSymbol();
   TR::SymbolReference * glueRef;
   int8_t padbytes = snippet->getPadBytes();

   printSnippetLabel(pOutFile, snippet->getSnippetLabel(), bufferPos,
      methodSymRef->isUnresolved() ? "Unresolved Call Snippet" : "Call Snippet");

   bufferPos = printS390ArgumentsFlush(pOutFile, callNode, bufferPos, snippet->getSizeOfArguments());

   if (methodSymRef->isUnresolved() || _comp->compileRelocatableCode())
      {
      if (methodSymbol->isSpecial())
         {
         glueRef = _cg->getSymRef(TR_S390interpreterUnresolvedSpecialGlue);
         }
      else if (methodSymbol->isStatic())
         {
         glueRef = _cg->getSymRef(TR_S390interpreterUnresolvedStaticGlue);
         }
      else
         {
         glueRef = _cg->getSymRef(TR_S390interpreterUnresolvedDirectVirtualGlue);
         }
      }
   else
      {
      bool synchronised = methodSymbol->isSynchronised();

      if ((methodSymbol->isVMInternalNative() || methodSymbol->isJITInternalNative()))
         {
         glueRef = _cg->getSymRef(TR_S390nativeStaticHelper);
         }
      else
         {
         switch (callNode->getDataType())
            {
            case TR::NoType:
               if (synchronised)
                  {
                  glueRef = _cg->getSymRef(TR_S390interpreterSyncVoidStaticGlue);
                  }
               else
                  {
                  glueRef = _cg->getSymRef(TR_S390interpreterVoidStaticGlue);
                  }
               break;
            case TR::Int8:
            case TR::Int16:
            case TR::Int32:
               if (synchronised)
                  {
                  glueRef = _cg->getSymRef(TR_S390interpreterSyncIntStaticGlue);
                  }
               else
                  {
                  glueRef = _cg->getSymRef(TR_S390interpreterIntStaticGlue);

                  }
               break;
            case TR::Address:
            if (TR::Compiler->target.is64Bit())
               {
               if (synchronised)
                  {
                  glueRef = _cg->getSymRef(TR_S390interpreterSyncLongStaticGlue);
                  }
               else
                  {
                  glueRef = _cg->getSymRef(TR_S390interpreterLongStaticGlue);
                  }
               }
            else
               {
               if (synchronised)
                  {
                  glueRef = _cg->getSymRef(TR_S390interpreterSyncIntStaticGlue);
                  }
               else
                  {
                  glueRef = _cg->getSymRef(TR_S390interpreterIntStaticGlue);
                  }
               }
               break;

            case TR::Int64:
               if (synchronised)
                  {
                  glueRef = _cg->getSymRef(TR_S390interpreterSyncLongStaticGlue);
                  }
               else
                  {
                  glueRef = _cg->getSymRef(TR_S390interpreterLongStaticGlue);
                  }
               break;

            case TR::Float:
               if (synchronised)
                  {
                  glueRef = _cg->getSymRef(TR_S390interpreterSyncFloatStaticGlue);
                  }
               else
                  {
                  glueRef = _cg->getSymRef(TR_S390interpreterFloatStaticGlue);
                  }
               break;

            case TR::Double:
               if (synchronised)
                  {
                  glueRef = _cg->getSymRef(TR_S390interpreterSyncDoubleStaticGlue);
                  }
               else
                  {
                  glueRef = _cg->getSymRef(TR_S390interpreterDoubleStaticGlue);
                  }
               break;

            default:
               TR_ASSERT(0, "Bad return data type for a call node.  DataType was %s\n",
                  getName(callNode->getDataType()));
            }
         }
      }
   bufferPos = printRuntimeInstrumentationOnOffInstruction(pOutFile, bufferPos, false); // RIOFF

   if (snippet->getKind() == TR::Snippet::IsUnresolvedCall)
      {
      int lengthOfLoad = (TR::Compiler->target.is64Bit())?6:4;

      printPrefix(pOutFile, NULL, bufferPos, 6);
      trfprintf(pOutFile, "LARL \tGPR14, *+%d <%p>\t# Start of Data Const.",
                        8 + lengthOfLoad + padbytes,
                        bufferPos + 8 + lengthOfLoad + padbytes);
      bufferPos += 6;
      if (TR::Compiler->target.is64Bit())
         {
         printPrefix(pOutFile, NULL, bufferPos, 6);
         trfprintf(pOutFile, "LG  \tGPR_EP, 0(,GPR14)");
         bufferPos += 6;
         }
      else
         {
         printPrefix(pOutFile, NULL, bufferPos, 4);
         trfprintf(pOutFile, "L   \tGPR_EP, 0(,GPR14)");
         bufferPos += 4;
         }
      printPrefix(pOutFile, NULL, bufferPos, 2);
      trfprintf(pOutFile, "BCR    \tGPR_EP");
      bufferPos += 2;
      }
   else
      {
      printPrefix(pOutFile, NULL, bufferPos, 6);
      trfprintf(pOutFile, "BRASL \tGPR14, <%p>\t# Branch to Helper Method %s",
                    snippet->getSnippetDestAddr(),
                    snippet->usedTrampoline()?"- Trampoline Used.":"");
      bufferPos += 6;
      }

   if (padbytes == 2)
      {
      printPrefix(pOutFile, NULL, bufferPos, 2);
      trfprintf(pOutFile, "DC   \t0x0000 \t\t\t# 2-bytes padding for alignment");
      bufferPos += 2;
      }
   else if (padbytes == 4)
      {
      printPrefix(pOutFile, NULL, bufferPos, 4) ;
      trfprintf(pOutFile, "DC   \t0x00000000 \t\t# 4-bytes padding for alignment");
      bufferPos += 4;
      }
   else if (padbytes == 6)
      {
      printPrefix(pOutFile, NULL, bufferPos, 6) ;
      trfprintf(pOutFile, "DC   \t0x000000000000 \t\t# 6-bytes padding for alignment");
      bufferPos += 6;
      }

   printPrefix(pOutFile, NULL, bufferPos, sizeof(intptrj_t));
   trfprintf(pOutFile, "DC   \t%p \t\t# Method Address", glueRef->getMethodAddress());
   bufferPos += sizeof(intptrj_t);


   printPrefix(pOutFile, NULL, bufferPos, sizeof(intptrj_t));
   trfprintf(pOutFile, "DC   \t%p \t\t# Call Site RA", snippet->getCallRA());
   bufferPos += sizeof(intptrj_t);

   if (methodSymRef->isUnresolved())
      {
      printPrefix(pOutFile, NULL, bufferPos, 0);
      }
   else
      {
      printPrefix(pOutFile, NULL, bufferPos, sizeof(intptrj_t));
      }

   trfprintf(pOutFile, "DC   \t%p \t\t# Method Pointer", methodSymRef->isUnresolved() ? 0 : methodSymbol->getMethodAddress());
   }
Ejemplo n.º 11
0
TR::Node *
OMR::TransformUtil::scalarizeArrayCopy(
      TR::Compilation *comp,
      TR::Node *node,
      TR::TreeTop *tt,
      bool useElementType,
      bool &didTransformArrayCopyNode,
      TR::SymbolReference *sourceRef,
      TR::SymbolReference *targetRef,
      bool castToIntegral)
   {
   TR::CodeGenerator *cg = comp->cg();

   didTransformArrayCopyNode = false;

   if ((comp->getOptLevel() == noOpt) ||
       !comp->getOption(TR_ScalarizeSSOps) ||
       node->getOpCodeValue() != TR::arraycopy ||
       node->getNumChildren() != 3 ||
       comp->requiresSpineChecks() ||
       !node->getChild(2)->getOpCode().isLoadConst() ||
       cg->getOptimizationPhaseIsComplete())
      return node;

   int64_t byteLen = node->getChild(2)->get64bitIntegralValue();
   if (byteLen == 0)
      {
      if (tt)
         {
         // Anchor the first two children
         if (!node->getFirstChild()->safeToDoRecursiveDecrement())
            TR::TreeTop::create(comp, tt->getPrevTreeTop(),
                               TR::Node::create(TR::treetop, 1, node->getFirstChild()));
         if (!node->getSecondChild()->safeToDoRecursiveDecrement())
            TR::TreeTop::create(comp, tt->getPrevTreeTop(),
                               TR::Node::create(TR::treetop, 1, node->getSecondChild()));
         tt->getPrevTreeTop()->join(tt->getNextTreeTop());
         tt->getNode()->recursivelyDecReferenceCount();
         didTransformArrayCopyNode = true;
         }
      return node;
      }
   else if (byteLen < 0)
      {
      return node;
      }
   else if (byteLen > TR_MAX_OTYPE_SIZE)
      {
      return node;
      }
   TR::DataType dataType = TR::Aggregate;

   // Get the element datatype from the (hidden) 4th child
   TR::DataType elementType = node->getArrayCopyElementType();
   int32_t elementSize = TR::Symbol::convertTypeToSize(elementType);

   if (byteLen == elementSize)
      {
      dataType = elementType;
      }
   else if (!useElementType)
      {
      switch (byteLen)
         {
         case 1: dataType = TR::Int8; break;
         case 2: dataType = TR::Int16; break;
         case 4: dataType = TR::Int32; break;
         case 8: dataType = TR::Int64; break;
         }
      }
   else
      {
      return node;
      }

   // load/store double on 64-bit PPC requires offset to be word aligned
   // abort if this requirement is not met.
   // TODO: also need to check if the first two children are aload nodes
   bool cannot_use_load_store_long = false;
   if (TR::Compiler->target.cpu.isPower())
      if (dataType == TR::Int64 && TR::Compiler->target.is64Bit())
         {
         TR::Node * firstChild = node->getFirstChild();
         if (firstChild->getNumChildren() == 2)
            {
            TR::Node *offsetChild = firstChild->getSecondChild();
            TR_ASSERT(offsetChild->getOpCodeValue() != TR::iconst, "iconst shouldn't be used for 64-bit array indexing");
            if (offsetChild->getOpCodeValue() == TR::lconst)
               {
               if ((offsetChild->getLongInt() & 0x3) != 0)
                  cannot_use_load_store_long = true;
               }
            }
         TR::Node *secondChild = node->getSecondChild();
         if (secondChild->getNumChildren() == 2)
            {
            TR::Node *offsetChild = secondChild->getSecondChild();
            TR_ASSERT(offsetChild->getOpCodeValue() != TR::iconst, "iconst shouldn't be used for 64-bit array indexing");
            if (offsetChild->getOpCodeValue() == TR::lconst)
               {
               if ((offsetChild->getLongInt() & 0x3) != 0)
                  cannot_use_load_store_long = true;
               }
            }
         }
   if (cannot_use_load_store_long) return node;

   TR::SymbolReference *nodeRef;

   targetRef = comp->getSymRefTab()->findOrCreateGenericIntShadowSymbolReference(0);
   sourceRef = targetRef;

   bool trace = comp->getOption(TR_TraceScalarizeSSOps);
   if (trace)
      traceMsg(comp,"scalarizeArrayCopy: node %p got targetRef (#%d) and sourceRef (#%d)\n",
         node,targetRef?targetRef->getReferenceNumber():-1,sourceRef?sourceRef->getReferenceNumber():-1);

   if (targetRef == NULL || sourceRef == NULL)
      {
      if (trace)
         traceMsg(comp,"do not scalarizeArrayCopy node %p : targetRef is NULL (%s) or sourceRef is NULL (%s)\n",node,targetRef?"no":"yes",sourceRef?"no":"yes");
      return node;
      }
#ifdef J9_PROJECT_SPECIFIC
   if (targetRef->getSymbol()->getDataType().isBCD() ||
       sourceRef->getSymbol()->getDataType().isBCD())
      {
      return node;
      }
#endif

   if (performTransformation(comp, "%sScalarize arraycopy 0x%p\n", OPT_DETAILS, node))
      {
      TR::Node *store = TR::TransformUtil::scalarizeAddressParameter(comp, node->getSecondChild(), byteLen, dataType, targetRef, true);
      TR::Node *load = TR::TransformUtil::scalarizeAddressParameter(comp, node->getFirstChild(), byteLen, dataType, sourceRef, false);

      if (tt)
         {
         // Transforming
         //    treetop
         //      arrayCopy   <-- node
         // into
         //    *store
         //
         node->recursivelyDecReferenceCount();
         tt->setNode(node);
         }
      else
         {
         for (int16_t c = node->getNumChildren() - 1; c >= 0; c--)
            cg->recursivelyDecReferenceCount(node->getChild(c));
         }

      TR::Node::recreate(node, store->getOpCodeValue());
      node->setSymbolReference(store->getSymbolReference());

      if (store->getOpCode().isStoreIndirect())
         {
         node->setChild(0, store->getFirstChild());
         node->setAndIncChild(1, load);
         node->setNumChildren(2);
         }
      else
         {
         node->setAndIncChild(0, load);
         node->setNumChildren(1);
         }

      didTransformArrayCopyNode = true;
      }

   return node;
   }
Ejemplo n.º 12
0
TR_ExpressionsSimplification::LoopInfo*
TR_ExpressionsSimplification::findLoopInfo(TR_RegionStructure* region)
   {
   ListIterator<TR::CFGEdge> exitEdges(&region->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;
   }
Ejemplo n.º 13
0
static bool isSafeToReplaceNode(TR::Node *currentNode, TR::TreeTop *curTreeTop, bool *seenConditionalBranch,
      vcount_t visitCount, TR::Compilation *comp, List<OMR::TreeInfo> *targetTrees, bool &cannotBeEliminated,
      LongestPathMap &longestPaths)
   {
   LexicalTimer tx("safeToReplace", comp->phaseTimer());

   TR::SparseBitVector symbolReferencesInNode(comp->allocator());

   // Collect all symbols that could be killed between here and the next reference
   //
   comp->incVisitCount();
   //////vcount_t visitCount = comp->getVisitCount();
   int32_t numDeadSubNodes = 0;
   bool cantMoveUnderBranch = false;
   bool seenInternalPointer = false;
   bool seenArraylet = false;
   int32_t curMaxHeight = getLongestPathOfDAG(currentNode, longestPaths);
   collectSymbolReferencesInNode(currentNode, symbolReferencesInNode, &numDeadSubNodes, visitCount, comp,
         &seenInternalPointer, &seenArraylet, &cantMoveUnderBranch);

   bool registersScarce = comp->cg()->areAssignableGPRsScarce();
#ifdef J9_PROJECT_SPECIFIC
   bool isBCD = currentNode->getType().isBCD();
#endif

   if (numDeadSubNodes > 1 &&
#ifdef J9_PROJECT_SPECIFIC
       !isBCD &&
#endif
       registersScarce)
      {
      return false;
      }

   OMR::TreeInfo *curTreeInfo = findOrCreateTreeInfo(curTreeTop, targetTrees, comp);
   int32_t curHeight = curTreeInfo->getHeight()+curMaxHeight;
   if (curHeight > MAX_ALLOWED_HEIGHT)
      {
      cannotBeEliminated = true;
      return false;
      }

   // TEMPORARY
   // Don't allow removal of a node containing an unresolved reference if
   // the gcOnResolve option is set
   //
   bool isUnresolvedReference = currentNode->hasUnresolvedSymbolReference();
   if (isUnresolvedReference)
      return false;

   bool mayBeVolatileReference = currentNode->mightHaveVolatileSymbolReference();
   //if (mayBeVolatileReference)
   //   return false;

   // Now scan forwards through the trees looking for the next use and checking
   // to see if any symbols in the subtree are getting modified; if so it is not
   // safe to replace the node at its next use.
   //

   comp->incVisitCount();
   for (TR::TreeTop *treeTop = curTreeTop->getNextTreeTop(); treeTop; treeTop = treeTop->getNextTreeTop())

      {
      TR::Node *node = treeTop->getNode();
      if(node->getOpCodeValue() == TR::treetop)
          node = node->getFirstChild();

      if (node->getOpCodeValue() == TR::BBStart &&
          !node->getBlock()->isExtensionOfPreviousBlock())
         return true;

      if (cantMoveUnderBranch && (node->getOpCode().isBranch()
         || node->getOpCode().isJumpWithMultipleTargets()))
         return false;

      if (node->canGCandReturn() &&
          seenInternalPointer)
         return false;

      int32_t tempHeight = 0;
      int32_t maxHeight = 0;
      bool canMoveIfVolatile = true;
      if (containsNode(node, currentNode, visitCount, comp, &tempHeight, &maxHeight, canMoveIfVolatile))
         {
         // TEMPORARY
         // Disable moving an unresolved reference down to the middle of a
         // JNI call, until the resolve helper is fixed properly
         //
         if (isUnresolvedReference && node->getFirstChild()->getOpCode().isCall() &&
             node->getFirstChild()->getSymbol()->castToMethodSymbol()->isJNI())
            return false;

         if (curTreeInfo)
            {
            OMR::TreeInfo *treeInfo = findOrCreateTreeInfo(treeTop, targetTrees, comp);
            int32_t height = treeInfo->getHeight();
            int32_t maxHeightUsed = maxHeight;
            if (maxHeightUsed < curMaxHeight)
               maxHeightUsed = curMaxHeight;

            if (height < curTreeInfo->getHeight())
               height = curTreeInfo->getHeight();
            height++;
            if ((height+maxHeightUsed) > MAX_ALLOWED_HEIGHT)
               {
               cannotBeEliminated = true;
               return false;
               }
            treeInfo->setHeight(height);
            }

         return true;
         }

      if (mayBeVolatileReference && !canMoveIfVolatile)
         return false;

      if ((node->getOpCode().isBranch() &&
           (node->getOpCodeValue() != TR::Goto)) ||
           (node->getOpCode().isJumpWithMultipleTargets() && node->getOpCode().hasBranchChildren()))
        *seenConditionalBranch = true;

      if (node->getOpCodeValue() == TR::treetop ||
          node->getOpCode().isNullCheck() ||
          node->getOpCode().isResolveCheck() ||
          node->getOpCodeValue() == TR::ArrayStoreCHK ||
          node->getOpCode().isSpineCheck())
         {
         node = node->getFirstChild();
         }

      if (node->getOpCode().isStore())
         {
         // For a store, just the single symbol reference is killed.
         // Resolution of the store symbol is handled by TR::ResolveCHK
         //
         if (symbolReferencesInNode.ValueAt(node->getSymbolReference()->getReferenceNumber()))
            return false;
         }

      // Node Aliasing Changes
      // Check if the definition modifies any symbol in the subtree
      //
      if (node->mayKill(true).containsAny(symbolReferencesInNode, comp))
        return false;
      }
   return true;
   }
Ejemplo n.º 14
0
void TR_ExpressionsSimplification::setSummationReductionCandidates(TR::Node *node, TR::TreeTop *tt)
   {
   // Must be a store node
   //
   if (node->getOpCodeValue() != TR::istore
   /* || node->getOpCodeValue() != TR::astore */)
      {
      if (trace())
         traceMsg(comp(), "Node %p: The opcode is not istore so not a summation reduction candidate\n",node);
      return;
      }

   TR::Node *opNode = node->getFirstChild();

   if (opNode->getOpCodeValue() == TR::iadd ||
       opNode->getOpCodeValue() == TR::isub)
      {
      TR::Node *firstNode = opNode->getFirstChild();
      TR::Node *secondNode = opNode->getSecondChild();

      if (firstNode->getOpCode().hasSymbolReference() &&
            node->getSymbolReference() == firstNode->getSymbolReference() &&
            opNode->getReferenceCount() == 1 && firstNode->getReferenceCount() == 1)
         {
         // The second node must be loop invariant
         //
         if (!_currentRegion->isExprInvariant(secondNode))
            {
            if (trace())
               {
               traceMsg(comp(), "The node %p is not loop invariant\n",secondNode);

               // This can be the arithmetic series case
               // only when the node is an induction variable
               if (secondNode->getNumChildren() == 1 && secondNode->getOpCode().hasSymbolReference())
                  {
                  TR_InductionVariable *indVar = _currentRegion->findMatchingIV(secondNode->getSymbolReference());
                  if (indVar)
                     {
                     //printf("Found Candidate of arithmetic series\n" );
                     }
                  }
               }
            return;
            }

         _candidateTTs->add(tt);
         }
      else if (secondNode->getOpCode().hasSymbolReference() &&
            node->getSymbolReference() == secondNode->getSymbolReference() &&
            opNode->getReferenceCount() == 1 && secondNode->getReferenceCount() == 1 &&
            _currentRegion->isExprInvariant(firstNode))
         {
         _candidateTTs->add(tt);
         }
      }
   else if (opNode->getOpCodeValue() == TR::ixor ||
            opNode->getOpCodeValue() == TR::ineg)
      {
      if (opNode->getFirstChild()->getOpCode().hasSymbolReference() &&
            node->getSymbolReference() == opNode->getFirstChild()->getSymbolReference() &&
            opNode->getReferenceCount() == 1 && opNode->getFirstChild()->getReferenceCount() == 1 &&
            (opNode->getOpCodeValue() == TR::ineg || _currentRegion->isExprInvariant(opNode->getSecondChild())))
         _candidateTTs->add(tt);
      else if (opNode->getOpCodeValue() == TR::ixor && opNode->getSecondChild()->getOpCode().hasSymbolReference() &&
            node->getSymbolReference() == opNode->getSecondChild()->getSymbolReference() &&
            opNode->getReferenceCount() == 1 && opNode->getSecondChild()->getReferenceCount() == 1 &&
            _currentRegion->isExprInvariant(opNode->getFirstChild()))
         _candidateTTs->add(tt);
      }
   }
Ejemplo n.º 15
0
// Checks for syntactic equivalence and returns the side-table index
// of the syntactically equivalent node if it found one; else it returns
// -1 signifying that this is the first time any node similar syntactically
// to this node has been seen. Adds the node to the hash table if seen for the
// first time.
//
//
int TR_LocalAnalysisInfo::hasOldExpressionOnRhs(TR::Node *node, bool recalcContainsCall, bool storeLhsContainsCall)
   {
   //
   // Get the relevant portion of the subtree
   // for this node; this is different for a null check
   // as its null check reference is the only
   // sub-expression that matters
   //
   TR::Node *relevantSubtree = NULL;
   if (node->getOpCodeValue() == TR::NULLCHK)
      relevantSubtree = node->getNullCheckReference();
   else
      relevantSubtree = node;

   // containsCall checks whether the relevant node has some
   // sub-expression that cannot be commoned, e.g. call or a new
   //
   bool nodeContainsCall;
   if (!recalcContainsCall && (relevantSubtree == node))
      {
      // can use pre-calculated value of containsCall and storeLhsContainsCall, to avoid visitCount overflow
      nodeContainsCall = node->containsCall();
      }
   else
      {
      storeLhsContainsCall = false;
      nodeContainsCall = containsCall(relevantSubtree, storeLhsContainsCall);
      }

   if (nodeContainsCall)
      {
      //
      // If the node is not a store, a call-like sub-expression is inadmissable;
      // if the node is a store, a call-like sub-expression is allowed on the RHS
      // of the store as this does not inhibit privatization in any way as
      // the private temp store's RHS simply points at original RHS. But if a call-like
      // sub-expression is present in the LHS of the store, that is inadmissable
      //
      if (!node->getOpCode().isStore() ||
          storeLhsContainsCall)
         return 0;
      }

   bool seenIndirectStore = false;
#ifdef J9_PROJECT_SPECIFIC
   bool seenIndirectBCDStore = false;
#endif
   bool seenWriteBarrier = false;
   int32_t storeNumChildren = node->getNumChildren();


   // If node is a null check, compare the
   // null check reference only to establish syntactic equivalence
   //
   if (node->getOpCodeValue() == TR::NULLCHK)
   /////if (node->getOpCode().isNullCheck())
      {
      int32_t k;
      for (k=0;k<_numNullChecks;k++)
         {
         if (!(_nullCheckNodesAsArray[k] == NULL))
            {
            if (areSyntacticallyEquivalent(_nullCheckNodesAsArray[k]->getNullCheckReference(), node->getNullCheckReference()))
               return _nullCheckNodesAsArray[k]->getLocalIndex();
            }
         }

      _nullCheckNodesAsArray[_numNullChecks++] = node;
      }
   else
      {
      //
      // If this node is a global store, then equivalence check is different.
      // We try to give a store to field (or static) o.f the same index as
      // a load of o.f. This is so that privatization happens for fields/statics.
      // So the store's opcode value is changed temporarily to be a load before
      // syntactic equivalence is checked; this enables matching stores/loads to
      // same global symbol.
      //
      if (node->getOpCode().isStore() &&
          !node->getSymbolReference()->getSymbol()->isAutoOrParm())
         {
         if (node->getOpCode().isWrtBar())
            seenWriteBarrier = true;
#ifdef J9_PROJECT_SPECIFIC
         seenIndirectBCDStore = node->getType().isBCD();
#endif
         if (node->getOpCode().isStoreIndirect())
            {
            if (seenWriteBarrier)
               {
               TR::Node::recreate(node, _compilation->il.opCodeForIndirectArrayLoad(node->getDataType()));
               }
            else
               {
               TR::Node::recreate(node, _compilation->il.opCodeForCorrespondingIndirectStore(node->getOpCodeValue()));
               }
            node->setNumChildren(1);
            }
         else
            {
            TR::Node::recreate(node, _compilation->il.opCodeForDirectLoad(node->getDataType()));
            node->setNumChildren(0);
            }

#ifdef J9_PROJECT_SPECIFIC
         if (seenIndirectBCDStore)
            node->setBCDStoreIsTemporarilyALoad(true);
#endif

         seenIndirectStore = true;
         }

      int32_t hashValue = _hashTable->hash(node);
      HashTable::Cursor cursor(_hashTable, hashValue);
      TR::Node *other;
      for (other = cursor.firstNode(); other; other = cursor.nextNode())
         {
         // Convert other node's opcode to be a load temporarily
         // (only for syntactic equivalence check; see explanation above)
         // to enable matching global stores/loads.
         //
         bool seenOtherIndirectStore = false;
#ifdef J9_PROJECT_SPECIFIC
         bool seenOtherIndirectBCDStore = false;
#endif
         bool seenOtherWriteBarrier = false;
         int32_t otherStoreNumChildren = other->getNumChildren();
         if (other->getOpCode().isStore() &&
             !other->getSymbolReference()->getSymbol()->isAutoOrParm())
            {
            if (other->getOpCode().isWrtBar())
               seenOtherWriteBarrier = true;

#ifdef J9_PROJECT_SPECIFIC
            seenOtherIndirectBCDStore = other->getType().isBCD();
#endif
            if (other->getOpCode().isStoreIndirect())
               {
               if (seenOtherWriteBarrier)
                  {
                  TR::Node::recreate(other, _compilation->il.opCodeForIndirectArrayLoad(other->getDataType()));
                  }
               else
                  {
                  TR::Node::recreate(other, _compilation->il.opCodeForCorrespondingIndirectStore(other->getOpCodeValue()));
                  }
               other->setNumChildren(1);
               }
            else
               {
               TR::Node::recreate(other, _compilation->il.opCodeForDirectLoad(other->getDataType()));
               other->setNumChildren(0);
               }

#ifdef J9_PROJECT_SPECIFIC
            if (seenOtherIndirectBCDStore)
               other->setBCDStoreIsTemporarilyALoad(true);
#endif

            seenOtherIndirectStore = true;
            }

         bool areSame = areSyntacticallyEquivalent(node, other);

         // Restore the other node's state to what it was originally
         // (if it was a global store)
         //
         if (seenOtherWriteBarrier)
            {
            other->setNumChildren(otherStoreNumChildren);

            if (otherStoreNumChildren == 3)
               TR::Node::recreate(other, TR::awrtbari);
            else
               TR::Node::recreate(other, TR::awrtbar);
            }
         else if (seenOtherIndirectStore)
            {
            other->setNumChildren(otherStoreNumChildren);

#ifdef J9_PROJECT_SPECIFIC
            if (seenOtherIndirectBCDStore)
               other->setBCDStoreIsTemporarilyALoad(false);
#endif

            if (other->getOpCode().isIndirect())
               TR::Node::recreate(other, _compilation->il.opCodeForCorrespondingIndirectLoad(other->getOpCodeValue()));
            else
               TR::Node::recreate(other, _compilation->il.opCodeForDirectStore(other->getDataType()));
            }

         if (areSame)
            {
            if (seenWriteBarrier)
               {
               node->setNumChildren(storeNumChildren);

               if (storeNumChildren == 3)
                  TR::Node::recreate(node, TR::awrtbari);
               else
                  TR::Node::recreate(node, TR::awrtbar);
               }
            else if (seenIndirectStore)
               {
               node->setNumChildren(storeNumChildren);

#ifdef J9_PROJECT_SPECIFIC
               if (seenIndirectBCDStore)
                  node->setBCDStoreIsTemporarilyALoad(false);
#endif

               if (node->getOpCode().isIndirect())
                  TR::Node::recreate(node, _compilation->il.opCodeForCorrespondingIndirectLoad(node->getOpCodeValue()));
               else
                  TR::Node::recreate(node, _compilation->il.opCodeForDirectStore(node->getDataType()));
               }

            return other->getLocalIndex();
            }
         }

      // No match from existing nodes in the hash table;
      // add this node to the hash table.
      //
      _hashTable->add(node, hashValue);
      }

   // Restore this node's state to what it was before
   // (if it was a global store)
   //
   if (seenWriteBarrier)
      {
      node->setNumChildren(storeNumChildren);

      if (storeNumChildren == 3)
         TR::Node::recreate(node, TR::awrtbari);
      else
         TR::Node::recreate(node, TR::awrtbar);
      }
   else if (seenIndirectStore)
      {
      node->setNumChildren(storeNumChildren);

#ifdef J9_PROJECT_SPECIFIC
      if (seenIndirectBCDStore)
         node->setBCDStoreIsTemporarilyALoad(false);
#endif

      if (node->getOpCode().isIndirect())
         TR::Node::recreate(node, _compilation->il.opCodeForCorrespondingIndirectLoad(node->getOpCodeValue()));
      else
         TR::Node::recreate(node, _compilation->il.opCodeForDirectStore(node->getDataType()));
      }

   return -1;
   }
Ejemplo n.º 16
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.º 17
0
// Collects nodes that involved in PRE that are not stores or checks.
// These nodes require temps.
//
bool TR_LocalAnalysisInfo::collectSupportedNodes(TR::Node *node, TR::Node *parent)
   {
   if (node->getVisitCount() == _visitCount)
      return false;

   node->setVisitCount(_visitCount);

   bool flag = false;
   bool childRelevant = false;
   TR::ILOpCode &opCode = node->getOpCode();

   int32_t i;
   for (i = 0; i < node->getNumChildren(); i++)
      {
      TR::Node *child = node->getChild(i);
      if (collectSupportedNodes(child, node))
         flag = true;

      if (_checkExpressions->get(child->getLocalIndex()))
         childRelevant = true;
      }

   if (TR_LocalAnalysis::isSupportedNode(node, _compilation, parent))
      {
      _supportedNodesAsArray[node->getLocalIndex()] = node;

      bool indirectionSafe = true;
      if (opCode.isIndirect() && (opCode.isLoadVar() || opCode.isStore()))
         {
         indirectionSafe = false;
         if (node->getFirstChild()->isThisPointer() &&
             node->getFirstChild()->isNonNull())
            {
            indirectionSafe = true;
            TR::Node *firstChild = node->getFirstChild();
            TR::SymbolReference *symRef = firstChild->getSymbolReference();
            int32_t len;
            const char *sig = symRef->getTypeSignature(len);

            TR::SymbolReference *otherSymRef = node->getSymbolReference();

            TR_OpaqueClassBlock *cl = NULL;
            if (sig && (len > 0))
               cl = _compilation->fe()->getClassFromSignature(sig, len, symRef->getOwningMethod(_compilation));

            TR_OpaqueClassBlock *otherClassObject = NULL;
            int32_t otherLen;
            const char *otherSig = otherSymRef->getOwningMethod(_compilation)->classNameOfFieldOrStatic(otherSymRef->getCPIndex(), otherLen);
            if (otherSig)
               {
               otherSig = classNameToSignature(otherSig, otherLen, _compilation);
               otherClassObject = _compilation->fe()->getClassFromSignature(otherSig, otherLen, otherSymRef->getOwningMethod(_compilation));
               }

            if (!cl ||
                !otherClassObject ||
                (cl != otherClassObject))
               indirectionSafe = false;
            }
         }

      if (childRelevant ||
         (!indirectionSafe || (opCode.isArrayLength())) ||
         (node->getOpCode().isArrayRef()) ||
         (opCode.hasSymbolReference() && (node->getSymbolReference()->isUnresolved() || node->getSymbol()->isArrayShadowSymbol())) ||
         (opCode.isDiv() || opCode.isRem()))
         _checkExpressions->set(node->getLocalIndex());
      }

   return flag;
   }