예제 #1
0
void
TR::RegDepCopyRemoval::updateSingleRegDep(TR_GlobalRegisterNumber reg, TR::Node *newValueNode)
   {
   RegDepInfo &dep = getRegDepInfo(reg);
   TR_ASSERT(_treetop->getNode()->getOpCodeValue() != TR::BBStart, "attempted to change %s in incoming GlRegDeps on BBStart n%un\n", registerName(reg), _treetop->getNode()->getGlobalIndex());

   TR::Node *prevChild = _regDeps->getChild(dep.childIndex);
   TR_ASSERT(prevChild == dep.node, "childIndex and node inconsistent in RegDepInfo for %s\n", registerName(reg));
   TR_ASSERT(prevChild->getGlobalRegisterNumber() == reg, "childIndex and reg inconsistent in RegDepInfo for %s\n", registerName(reg));

   if (newValueNode->getOpCode().isLoadReg()
       && newValueNode->getGlobalRegisterNumber() == reg)
      {
      _regDeps->setAndIncChild(dep.childIndex, newValueNode);
      }
   else
      {
      TR::Node *newOutgoingPassThroughNode = TR::Node::create(TR::PassThrough, 1, newValueNode);
      newOutgoingPassThroughNode->setGlobalRegisterNumber(reg);
      _regDeps->setAndIncChild(dep.childIndex, newOutgoingPassThroughNode);
      }

   prevChild->recursivelyDecReferenceCount();
   rememberNodeChoice(reg, newValueNode);
   }
예제 #2
0
void
TR::RegDepCopyRemoval::readRegDeps()
   {
   for (int i = 0; i < _regDeps->getNumChildren(); i++)
      {
      TR::Node *depNode = _regDeps->getChild(i);
      TR::Node *depValue = depNode;
      if (depValue->getOpCodeValue() == TR::PassThrough)
         {
         do
            depValue = depValue->getFirstChild();
         while (depValue->getOpCodeValue() == TR::PassThrough);
         }
      else
         {
         TR_ASSERT(depNode->getOpCode().isLoadReg(), "invalid GlRegDeps child opcode n%un %s\n", depNode->getGlobalIndex(), depNode->getOpCode().getName());
         }

      // Avoid register pairs for simplicity, at least for now
      bool isRegPairDep = depNode->getHighGlobalRegisterNumber() != (TR_GlobalRegisterNumber)-1;
      bool valueNeedsRegPair = comp()->nodeNeeds2Regs(depValue);
      TR_ASSERT(isRegPairDep == valueNeedsRegPair, "mismatch on number of registers required for n%un\n", depNode->getGlobalIndex());
      if (isRegPairDep)
         {
         ignoreRegister(depNode->getLowGlobalRegisterNumber());
         ignoreRegister(depNode->getHighGlobalRegisterNumber());
         continue;
         }

      // Only process integral and address-type nodes; they'll go into GPRs
      TR_GlobalRegisterNumber reg = depNode->getGlobalRegisterNumber();
      TR::DataType depType = depValue->getType();
      if (!depType.isIntegral() && !depType.isAddress())
         {
         ignoreRegister(reg);
         continue;
         }

      RegDepInfo &dep = getRegDepInfo(reg);
      TR_ASSERT(dep.state == REGDEP_ABSENT, "register %s is multiply-specified\n", registerName(reg));
      dep.node = depNode;
      dep.value = depValue;
      dep.state = REGDEP_UNDECIDED;
      dep.childIndex = i;
      }
   }
예제 #3
0
OMR::Power::RegisterDependencyConditions::RegisterDependencyConditions(
                                       TR::CodeGenerator *cg,
                                       TR::Node          *node,
                                       uint32_t          extranum,
                                       TR::Instruction  **cursorPtr)
   {
   List<TR::Register>  regList(cg->trMemory());
   TR::Instruction    *iCursor = (cursorPtr==NULL)?NULL:*cursorPtr;
   int32_t totalNum = node->getNumChildren() + extranum;
   int32_t i;


   cg->comp()->incVisitCount();

   int32_t numLongs = 0;
   //
   // Pre-compute how many longs are global register candidates
   //
   for (i = 0; i < node->getNumChildren(); ++i)
      {
      TR::Node     *child = node->getChild(i);
      TR::Register *reg   = child->getRegister();

      if (reg!=NULL /* && reg->getKind()==TR_GPR */)
	 {
	 if (child->getHighGlobalRegisterNumber() > -1)
	    numLongs++;
	 }
      }

   totalNum = totalNum + numLongs;

   _preConditions = new (totalNum, cg->trMemory()) TR_PPCRegisterDependencyGroup;
   _postConditions = new (totalNum, cg->trMemory()) TR_PPCRegisterDependencyGroup;
   _numPreConditions = totalNum;
   _addCursorForPre = 0;
   _numPostConditions = totalNum;
   _addCursorForPost = 0;

   // First, handle dependencies that match current association
   for (i=0; i<node->getNumChildren(); i++)
      {
      TR::Node *child = node->getChild(i);
      TR::Register *reg = child->getRegister();
      TR::Register *highReg = NULL;
      TR::RealRegister::RegNum regNum = (TR::RealRegister::RegNum)cg->getGlobalRegister(child->getGlobalRegisterNumber());

      TR::RealRegister::RegNum highRegNum;

      if (child->getHighGlobalRegisterNumber() > -1)
         {
         highRegNum = (TR::RealRegister::RegNum)cg->getGlobalRegister(child->getHighGlobalRegisterNumber());

         TR::RegisterPair *regPair = reg->getRegisterPair();
         TR_ASSERT(regPair, "assertion failure");
	 highReg = regPair->getHighOrder();
	 reg = regPair->getLowOrder();

         if (highReg->getAssociation() != highRegNum ||
             reg->getAssociation() != regNum)
            continue;
         }
      else if (reg->getAssociation() != regNum)
         continue;

      TR_ASSERT(!regList.find(reg) && (!highReg || !regList.find(highReg)), "Should not happen\n");

      addPreCondition(reg, regNum);
      addPostCondition(reg, regNum);
      regList.add(reg);

      if (highReg)
	 {
	 addPreCondition(highReg, highRegNum);
	 addPostCondition(highReg, highRegNum);
         regList.add(highReg);
	 }
      }


   // Second pass to handle dependencies for which association does not exist
   // or does not match
   for (i=0; i<node->getNumChildren(); i++)
      {
      TR::Node *child = node->getChild(i);
      TR::Register *reg = child->getRegister();
      TR::Register *highReg = NULL;
      TR::Register *copyReg = NULL;
      TR::Register *highCopyReg = NULL;
      TR::RealRegister::RegNum regNum = (TR::RealRegister::RegNum)cg->getGlobalRegister(child->getGlobalRegisterNumber());


      TR::RealRegister::RegNum highRegNum;

      if (child->getHighGlobalRegisterNumber() > -1)
         {
         highRegNum = (TR::RealRegister::RegNum)cg->getGlobalRegister(child->getHighGlobalRegisterNumber());
         TR::RegisterPair *regPair = reg->getRegisterPair();
         TR_ASSERT(regPair, "assertion failure");
	 highReg = regPair->getHighOrder();
	 reg = regPair->getLowOrder();

         if (highReg->getAssociation() == highRegNum &&
             reg->getAssociation() == regNum)
            continue;

         }
      else  if (reg->getAssociation() == regNum)
             continue;

      if (regList.find(reg) || (highReg && regList.find(highReg)))
	 {
         TR::InstOpCode::Mnemonic    opCode;
         TR_RegisterKinds kind = reg->getKind();

         switch (kind)
	    {
            case TR_GPR:
               opCode = TR::InstOpCode::mr;
               break;
            case TR_FPR:
               opCode = TR::InstOpCode::fmr;
               break;
            case TR_VRF:
               opCode = TR::InstOpCode::vor;
               //TR_ASSERT(0, "VMX not fully supported.");
               break;
            case TR_VSX_VECTOR:
               opCode = TR::InstOpCode::xxlor;
               break;
            case TR_CCR:
               opCode = TR::InstOpCode::mcrf;
               break;
            default:
               TR_ASSERT(0, "Invalid register kind.");
	    }


         if (regList.find(reg))
            {
	    bool containsInternalPointer = false;
	    if (reg->getPinningArrayPointer())
	       containsInternalPointer = true;

	    copyReg = (reg->containsCollectedReference() && !containsInternalPointer) ?
	               cg->allocateCollectedReferenceRegister() : cg->allocateRegister(kind);

	    if (containsInternalPointer)
	       {
	       copyReg->setContainsInternalPointer();
	       copyReg->setPinningArrayPointer(reg->getPinningArrayPointer());
	       }
            if (opCode == TR::InstOpCode::vor || opCode == TR::InstOpCode::xxlor)
               iCursor = generateTrg1Src2Instruction(cg, opCode, node, copyReg, reg, reg, iCursor);
            else
               iCursor = generateTrg1Src1Instruction(cg, opCode, node, copyReg, reg, iCursor);

            reg = copyReg;
            }

	 if (highReg && regList.find(highReg))
	    {
	    bool containsInternalPointer = false;
	    if (highReg->getPinningArrayPointer())
	       containsInternalPointer = true;

	    highCopyReg = (highReg->containsCollectedReference() && !containsInternalPointer) ?
	                  cg->allocateCollectedReferenceRegister() : cg->allocateRegister(kind);

	    if (containsInternalPointer)
	       {
	       highCopyReg->setContainsInternalPointer();
	       highCopyReg->setPinningArrayPointer(highReg->getPinningArrayPointer());
	       }
            if (opCode == TR::InstOpCode::vor || opCode == TR::InstOpCode::xxlor)
               iCursor = generateTrg1Src2Instruction(cg, opCode, node, highCopyReg, highReg, highReg, iCursor);
            else
	       iCursor = generateTrg1Src1Instruction(cg, opCode, node, highCopyReg, highReg, iCursor);

	    highReg = highCopyReg;
	    }
	 }

      addPreCondition(reg, regNum);
      addPostCondition(reg, regNum);
      if (copyReg != NULL)
         cg->stopUsingRegister(copyReg);
      else
         regList.add(reg);

      if (highReg)
	 {
	 addPreCondition(highReg, highRegNum);
	 addPostCondition(highReg, highRegNum);
	 if (highCopyReg != NULL)
	    cg->stopUsingRegister(highCopyReg);
         else
            regList.add(highReg);
	 }
      }

   if (iCursor!=NULL && cursorPtr!=NULL)
      *cursorPtr = iCursor;
   }
예제 #4
0
void TR_LoadExtensions::flagPreferredLoadExtensions(TR::Node* parent)
   {
   if (isSupportedType(parent) && parent->getOpCode().isConversion())
      {
      TR::Node* child = parent->getFirstChild();

      bool canSkipConversion = false;

      if (isSupportedType(child))
         {
         if (parent->getSize() == child->getSize())
            {
            TR::DebugCounter::incStaticDebugCounter(comp(), TR::DebugCounter::debugCounterName(comp(), "codegen/LoadExtensions/success/unneededConversion/%s", comp()->signature()));

            parent->setUnneededConversion(true);
            }
         else
            {
            TR::ILOpCode& childOpCode = child->getOpCode();

            if (childOpCode.isLoadReg()
               && !(parent->getSize() > 4 && TR::Compiler->target.is32Bit())
               && excludedNodes->count(parent) == 0)
               {
               TR::Node* useRegLoad = child;

               TR_UseDefInfo* useDefInfo = optimizer()->getUseDefInfo();

               if (useDefInfo != NULL && useDefInfo->infoIsValid() && useRegLoad->getUseDefIndex() != 0 && useDefInfo->isUseIndex(useRegLoad->getUseDefIndex() != 0))
                  {
                  TR_UseDefInfo::BitVector info(comp()->allocator());

                  if (useDefInfo->getUseDef(info, useRegLoad->getUseDefIndex()))
                     {
                     TR_UseDefInfo::BitVector::Cursor cursor(info);

                     int32_t firstDefIndex = useDefInfo->getFirstRealDefIndex();
                     int32_t firstUseIndex = useDefInfo->getFirstUseIndex();

                     canSkipConversion = true;

                     bool forceExtensionOnAnyLoads = false;
                     bool forceExtensionOnAllLoads = true;

                     for (cursor.SetToFirstOne(); cursor.Valid() && canSkipConversion; cursor.SetToNextOne())
                        {
                        int32_t defIndex = cursor;

                        // We've examined all the defs of this particular use
                        if (defIndex >= firstUseIndex)
                           {
                           break;
                           }

                        // Do not consider defs that correspond to method arguments as we cannot force extension on those
                        if (defIndex < firstDefIndex)
                           {
                           continue;
                           }

                        TR::Node* defRegLoad = useDefInfo->getNode(defIndex);

                        if (defRegLoad != NULL)
                           {
                           TR::Node* defRegLoadChild = defRegLoad->getFirstChild();

                           bool forceExtension = false;
                           canSkipConversion = TR_LoadExtensions::canSkipConversion(parent, defRegLoadChild, forceExtension);

                           forceExtensionOnAnyLoads |= forceExtension;
                           forceExtensionOnAllLoads &= forceExtension;

                           // If we have to force extension on any loads which feed a def of this use ensure we must also 
                           // force extension on all such loads. Conversely the conversion can be skipped if none of the
                           // loads feeding the def of this use need to be extended. This ensures either all loads feeding
                           // into defs of this use should be extended or none of them.
                           canSkipConversion &= forceExtensionOnAllLoads == forceExtensionOnAnyLoads;

                           if (trace())
                              {
                              traceMsg(comp(), "\t\tPeeked through %s [%p] and found %s [%p] with child %s [%p] - conversion %s be skipped\n",
                                 useRegLoad->getOpCode().getName(), 
                                 useRegLoad,
                                 defRegLoad->getOpCode().getName(), 
                                 defRegLoad,
                                 defRegLoadChild->getOpCode().getName(), 
                                 defRegLoadChild,
                                 canSkipConversion ? 
                                    "can" :
                                    "cannot");
                              }
                           }
                        }

                     if (canSkipConversion && performTransformation(comp(), "%sSkipping conversion %s [%p] after RegLoad\n", optDetailString(), parent->getOpCode().getName(), parent))
                        {
                        TR::DebugCounter::incStaticDebugCounter(comp(), TR::DebugCounter::debugCounterName(comp(), "codegen/LoadExtensions/success/unneededConversion/GRA/%s", comp()->signature()));

                        parent->setUnneededConversion(true);

                        if (forceExtensionOnAllLoads)
                           {
                           TR_UseDefInfo::BitVector info(comp()->allocator());

                           if (useDefInfo->getUseDef(info, useRegLoad->getUseDefIndex()))
                              {
                              TR_UseDefInfo::BitVector::Cursor cursor(info);

                              for (cursor.SetToFirstOne(); cursor.Valid(); cursor.SetToNextOne())
                                 {
                                 int32_t defIndex = cursor;

                                 // We've examined all the defs of this particular use
                                 if (defIndex >= firstUseIndex)
                                    {
                                    break;
                                    }

                                 // Do not consider defs that correspond to method arguments as we cannot force extension on those
                                 if (defIndex < firstDefIndex)
                                    {
                                    continue;
                                    }

                                 TR::Node *defRegLoad = useDefInfo->getNode(defIndex);

                                 if (defRegLoad != NULL)
                                    {
                                    TR::Node* defRegLoadChild = defRegLoad->getFirstChild();

                                    const int32_t preference = getExtensionPreference(defRegLoadChild);

                                    if (preference > 0)
                                       {
                                       if (trace())
                                          {
                                          traceMsg(comp(), "\t\t\tForcing sign extension on %s [%p]\n",
                                             defRegLoadChild->getOpCode().getName(),
                                             defRegLoadChild);
                                          }

                                       if (parent->getSize() == 8 || parent->useSignExtensionMode())
                                          {
                                          defRegLoadChild->setSignExtendTo64BitAtSource(true);
                                          }
                                       else
                                          {
                                          defRegLoadChild->setSignExtendTo32BitAtSource(true);
                                          }
                                       }

                                    if (preference < 0)
                                       {
                                       if (trace())
                                          {
                                          traceMsg(comp(), "\t\t\tForcing zero extension on %s [%p]\n",
                                             defRegLoadChild->getOpCode().getName(),
                                             defRegLoadChild);
                                          }

                                       if (parent->getSize() == 8 || parent->useSignExtensionMode())
                                          {
                                          defRegLoadChild->setZeroExtendTo64BitAtSource(true);
                                          }
                                       else
                                          {
                                          defRegLoadChild->setZeroExtendTo32BitAtSource(true);
                                          }
                                       }
                                    }
                                 }
                              }
                           }

                        if (parent->getType().isInt64() && parent->getSize() > child->getSize())
                           {
                           if (trace())
                              {
                              traceMsg(comp(), "\t\t\tSet global register %s in getExtendedToInt64GlobalRegisters for child %s [%p] with parent node %s [%p]\n",
                                 comp()->getDebug()->getGlobalRegisterName(child->getGlobalRegisterNumber()),
                                 child->getOpCode().getName(),
                                 child,
                                 parent->getOpCode().getName(),
                                 parent);
                              }

                           // getExtendedToInt64GlobalRegisters is used by the evaluators to force a larger virtual register to be used when
                           // evaluating the regload so any instructions generated by local RA are the correct size to preserve the upper bits
                           cg()->getExtendedToInt64GlobalRegisters()[child->getGlobalRegisterNumber()] = true;
                           }
                        }
                     }
                  }
               }
            }
         }

      if (!canSkipConversion)
         {
         bool forceExtension = false;
         canSkipConversion = TR_LoadExtensions::canSkipConversion(parent, child, forceExtension);

         if (canSkipConversion && performTransformation(comp(), "%sSkipping conversion %s [%p]\n", optDetailString(), parent->getOpCode().getName(), parent))
            {
            TR::DebugCounter::incStaticDebugCounter(comp(), TR::DebugCounter::debugCounterName(comp(), "codegen/LoadExtensions/success/unneededConversion/%s", comp()->signature()));

            parent->setUnneededConversion(true);

            if (forceExtension)
               {
               const int32_t preference = getExtensionPreference(child);

               if (preference > 0)
                  {
                  if (trace())
                     {
                     traceMsg(comp(), "\t\t\tForcing sign extension on %s [%p]\n",
                        child->getOpCode().getName(),
                        child);
                     }

                  if (parent->getSize() == 8 || parent->useSignExtensionMode())
                     {
                     child->setSignExtendTo64BitAtSource(true);
                     }
                  else
                     {
                     child->setSignExtendTo32BitAtSource(true);
                     }
                  }

               if (preference < 0)
                  {
                  if (trace())
                     {
                     traceMsg(comp(), "\t\t\tForcing zero extension on %s [%p]\n",
                        child->getOpCode().getName(),
                        child);
                     }

                  if (parent->getSize() == 8 || parent->useSignExtensionMode())
                     {
                     child->setZeroExtendTo64BitAtSource(true);
                     }
                  else
                     {
                     child->setZeroExtendTo32BitAtSource(true);
                     }
                  }
               }
            }
         }
      }
   }
예제 #5
0
void TR::DeadTreesElimination::prePerformOnBlocks()
   {
   _cannotBeEliminated = false;
   _delayedRegStores = false;

   _targetTrees.deleteAll();

   // Walk through all the blocks to remove trivial dead trees of the form
   // treetop
   //   => node
   // The problem with these trees is in the scenario where the earlier use
   // of 'node' is also dead.  However, our analysis won't find that because
   // the reference count is > 1.
   vcount_t visitCount = comp()->incOrResetVisitCount();
   for (TR::TreeTop *tt = comp()->getStartTree();
        tt != 0;
        tt = tt->getNextTreeTop())
      {
      bool removed = false;

      TR::Node *node = tt->getNode();
      if (node->getOpCodeValue() == TR::treetop &&
          node->getFirstChild()->getVisitCount() == visitCount &&
          performTransformation(comp(), "%sRemove trivial dead tree: %p\n", optDetailString(), node))
         {
         TR::TransformUtil::removeTree(comp(), tt);
         removed = true;
         }
      else
         {
         if (node->getOpCode().isCheck() &&
             node->getFirstChild()->getOpCode().isCall() &&
             node->getFirstChild()->getReferenceCount() == 1 &&
             node->getFirstChild()->getSymbolReference()->getSymbol()->isResolvedMethod() &&
             node->getFirstChild()->getSymbolReference()->getSymbol()->castToResolvedMethodSymbol()->isSideEffectFree() &&
             performTransformation(comp(), "%sRemove dead check of side-effect free call: %p\n", optDetailString(), node))
            {
            TR::TransformUtil::removeTree(comp(), tt);
            removed = true;
            }
         }

      if (removed
          && tt->getNextTreeTop()->getNode()->getOpCodeValue() == TR::Goto
          && tt->getPrevTreeTop()->getNode()->getOpCodeValue() == TR::BBStart
          && !tt->getPrevTreeTop()->getNode()->getBlock()->isExtensionOfPreviousBlock())
         {
         requestOpt(OMR::redundantGotoElimination, tt->getEnclosingBlock());
         }

      if (node->getVisitCount() >= visitCount)
         continue;
      TR::TransformUtil::recursivelySetNodeVisitCount(tt->getNode(), visitCount);
      }

   // If the last use of an iRegLoad has been removed, then remove the node from
   // the BBStart and remove the corresponding dependency node from each of the block's
   // predecessors.
   //
   while (1)
      {
      bool glRegDepRemoved = false;
      for (TR::Block * b = comp()->getStartBlock(); b; b = b->getNextBlock())
         {
         TR::TreeTop * startTT = b->getEntry();
         TR::Node * startNode = startTT->getNode();
         if (startNode->getNumChildren() > 0 && !debug("disableEliminationOfGlRegDeps"))
            {
            TR::Node * glRegDeps = startNode->getFirstChild();
            TR_ASSERT(glRegDeps->getOpCodeValue() == TR::GlRegDeps, "expected TR::GlRegDeps");
            for (int32_t i = glRegDeps->getNumChildren() - 1; i >= 0; --i)
               {
               TR::Node * dep = glRegDeps->getChild(i);
               if (dep->getReferenceCount() == 1 &&
                   (!dep->getOpCode().isFloatingPoint() ||
                    cg()->getSupportsJavaFloatSemantics()) &&
                   performTransformation(comp(), "%sRemove GlRegDep : %p\n", optDetailString(), glRegDeps->getChild(i)))

                  {
                  glRegDeps->removeChild(i);
                  glRegDepRemoved = true;
                  TR_GlobalRegisterNumber registerNum = dep->getGlobalRegisterNumber();
                  for (auto e = b->getPredecessors().begin(); e != b->getPredecessors().end(); ++e)
                     {
                     TR::Block * pred = toBlock((*e)->getFrom());
                     if (pred == comp()->getFlowGraph()->getStart())
                        continue;

                     TR::Node * parent = pred->getLastRealTreeTop()->getNode();
                     if ( parent->getOpCode().isJumpWithMultipleTargets() && parent->getOpCode().hasBranchChildren())
                        {
                        for (int32_t j = parent->getCaseIndexUpperBound() - 1; j > 0; --j)
                           {
                           TR::Node * caseNode = parent->getChild(j);
                           TR_ASSERT(caseNode->getOpCode().isCase() || caseNode->getOpCodeValue() == TR::branch,
                                  "having problems navigating a switch");
                           if (caseNode->getBranchDestination() == startTT &&
                               caseNode->getNumChildren() > 0 &&
                               0) // can't do this now that all glRegDeps are hung off the default branch
                              removeGlRegDep(caseNode, registerNum, pred, this);
                           }
                        }
                     else if (!parent->getOpCode().isReturn() &&
                              parent->getOpCodeValue() != TR::igoto &&
                              !( parent->getOpCode().isJumpWithMultipleTargets() && parent->getOpCode().hasBranchChildren()) &&
                              !(parent->getOpCodeValue()==TR::treetop &&
                              parent->getFirstChild()->getOpCode().isCall() &&
                              parent->getFirstChild()->getOpCode().isIndirect()))

                        {
                        if (pred->getNextBlock() == b)
                           parent = pred->getExit()->getNode();
                        removeGlRegDep(parent, registerNum, pred, this);
                        }
                     }
                  }
               }

            if (glRegDeps->getNumChildren() == 0)
               startNode->removeChild(0);
            }
         }

      if (!glRegDepRemoved)
         break;
      }
   }