Exemple #1
0
TR::Register *IA32LinkageUtils::pushFloatArg(
      TR::Node *child,
      TR::CodeGenerator *cg)
   {
   TR::Register *pushRegister;
   if (child->getRegister() == NULL)
      {
      if (child->getOpCodeValue() == TR::fconst)
         {
         int32_t value = child->getFloatBits();
         TR_X86OpCodes pushOp;
         if (value >= -128 && value <= 127)
            {
            pushOp = PUSHImms;
            }
         else
            {
            pushOp = PUSHImm4;
            }
         generateImmInstruction(pushOp, child, value, cg);
         cg->decReferenceCount(child);
         return NULL;
         }
      else if (child->getReferenceCount() == 1)
         {
         if (child->getOpCode().isLoad())
            {
            TR::MemoryReference  *tempMR = generateX86MemoryReference(child, cg);
            generateMemInstruction(PUSHMem, child, tempMR, cg);
            tempMR->decNodeReferenceCounts(cg);
            cg->decReferenceCount(child);
            return NULL;
            }
      else if (child->getOpCodeValue() == TR::ibits2f)
         {
         pushRegister = pushIntegerWordArg(child->getFirstChild(), cg);
         cg->decReferenceCount(child);
         return pushRegister;
         }
      }
   }

   pushRegister = cg->evaluate(child);
   TR::RealRegister *espReal = cg->machine()->getRealRegister(TR::RealRegister::esp);
   generateRegImmInstruction(SUB4RegImms, child, espReal, 4, cg);

   if (cg->useSSEForSinglePrecision() && pushRegister->getKind() == TR_FPR)
      generateMemRegInstruction(MOVSSMemReg, child, generateX86MemoryReference(espReal, 0, cg), pushRegister, cg);
   else
      generateFPMemRegInstruction(FSTMemReg, child, generateX86MemoryReference(espReal, 0, cg), pushRegister, cg);

   cg->decReferenceCount(child);
   return pushRegister;
   }
Exemple #2
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;
   }
Exemple #3
0
rcount_t
OMR::CodeGenerator::decReferenceCount(TR::Node * node)
   {
   TR::Register *reg = node->getRegister();

   // restricted registers go dead when ref count==2 because
   // their ref count was inced in prepareNodeForInstructionSelection
   if ((node->getReferenceCount() == 1) &&
       reg && self()->getLiveRegisters(reg->getKind()))
       {
      TR_ASSERT(reg->isLive() ||
                (diagnostic("\n*** Error: Register %s for node "
                             "[%s] died prematurely\n",
                             reg->getRegisterName(self()->comp()),
                             node->getName(self()->comp()->getDebug())),
                 0),
             "Node %s register should be live",self()->getDebug()->getName(node));

      TR_LiveRegisterInfo *liveRegister = reg->getLiveRegisterInfo();
      TR::Register *pair = reg->getRegisterPair();
      if (pair)
         {
         pair->getHighOrder()->getLiveRegisterInfo()->decNodeCount();
         pair->getLowOrder()->getLiveRegisterInfo()->decNodeCount();
         }

      if (liveRegister && liveRegister->decNodeCount() == 0)
         {
         // The register is now dead
         //
         self()->getLiveRegisters(reg->getKind())->registerIsDead(reg);
         }
      }

#ifdef J9_PROJECT_SPECIFIC
#if defined(TR_TARGET_S390)
   if (reg && reg->getOpaquePseudoRegister())
      {
      TR_OpaquePseudoRegister *pseudoReg = reg->getOpaquePseudoRegister();
      TR_StorageReference *storageReference = pseudoReg->getStorageReference();
      TR_ASSERT(storageReference,"the pseudoReg should have a non-null storage reference\n");
      storageReference->decrementTemporaryReferenceCount();
      if (node->getReferenceCount() == 1)
         {
         storageReference->decOwningRegisterCount();
         if (self()->traceBCDCodeGen())
            traceMsg(self()->comp(),"\tdecrement owningRegisterCount %d->%d on ref #%d (%s) for reg %s as %s (%p) refCount == 1 (going to 0)\n",
               storageReference->getOwningRegisterCount()+1,
               storageReference->getOwningRegisterCount(),
               storageReference->getReferenceNumber(),
               self()->getDebug()->getName(storageReference->getSymbol()),
               self()->getDebug()->getName(reg),
               node->getOpCode().getName(),
               node);
         }
      }
   else if (node->getOpCode().hasSymbolReference() && node->getSymbolReference() && node->getSymbolReference()->isTempVariableSizeSymRef())
      {
      TR_ASSERT(false,"tempMemSlots should only be attached to pseudoRegisters and not node %p\n",node);
      }
#endif
#endif

   rcount_t count = node->decReferenceCount();
   if (self()->comp()->getOptions()->getTraceCGOption(TR_TraceCGEvaluation))
      {
      self()->getDebug()->printNodeEvaluation(node, "-- ", reg);
      }
   return count;
   }
void TR_PPCRegisterDependencyGroup::assignRegisters(TR::Instruction   *currentInstruction,
                                                    TR_RegisterKinds  kindToBeAssigned,
                                                    uint32_t          numberOfRegisters,
                                                    TR::CodeGenerator *cg)
   {
   // *this    swipeable for debugging purposes
   TR::Machine *machine = cg->machine();
   TR::Register   *virtReg;
   TR::RealRegister::RegNum dependentRegNum;
   TR::RealRegister *dependentRealReg, *assignedRegister, *realReg;
   int i, j;
   TR::Compilation *comp = cg->comp();

   int num_gprs = 0;
   int num_fprs = 0;
   int num_vrfs = 0;

   // Use to do lookups using real register numbers
   TR_PPCRegisterDependencyMap map(_dependencies, numberOfRegisters);

   if (!comp->getOption(TR_DisableOOL))
      {
      for (i = 0; i< numberOfRegisters; i++)
         {
         virtReg = _dependencies[i].getRegister();
         dependentRegNum = _dependencies[i].getRealRegister();
         if (dependentRegNum == TR::RealRegister::SpilledReg)
            {
            TR_ASSERT(virtReg->getBackingStorage(),"should have a backing store if dependentRegNum == spillRegIndex()\n");
            if (virtReg->getAssignedRealRegister())
               {
               // this happens when the register was first spilled in main line path then was reverse spilled
               // and assigned to a real register in OOL path. We protected the backing store when doing
               // the reverse spill so we could re-spill to the same slot now
               traceMsg (comp,"\nOOL: Found register spilled in main line and re-assigned inside OOL");
               TR::Node *currentNode = currentInstruction->getNode();
               TR::RealRegister *assignedReg    = toRealRegister(virtReg->getAssignedRegister());
               TR::MemoryReference *tempMR = new (cg->trHeapMemory()) TR::MemoryReference(currentNode, (TR::SymbolReference*)virtReg->getBackingStorage()->getSymbolReference(), sizeof(uintptr_t), cg);
               TR::InstOpCode::Mnemonic opCode;
               TR_RegisterKinds rk = virtReg->getKind();
               switch (rk)
                  {
                  case TR_GPR:
                     opCode =TR::InstOpCode::Op_load;
                     break;
                  case TR_FPR:
                     opCode = virtReg->isSinglePrecision() ? TR::InstOpCode::lfs : TR::InstOpCode::lfd;
                     break;
                  default:
                     TR_ASSERT(0, "\nRegister kind not supported in OOL spill\n");
                     break;
                  }

               TR::Instruction *inst = generateTrg1MemInstruction(cg, opCode, currentNode, assignedReg, tempMR, currentInstruction);

               assignedReg->setAssignedRegister(NULL);
               virtReg->setAssignedRegister(NULL);
               assignedReg->setState(TR::RealRegister::Free);
               if (comp->getDebug())
                  cg->traceRegisterAssignment("Generate reload of virt %s due to spillRegIndex dep at inst %p\n",comp->getDebug()->getName(virtReg),currentInstruction);
               cg->traceRAInstruction(inst);
               }

            if (!(std::find(cg->getSpilledRegisterList()->begin(), cg->getSpilledRegisterList()->end(), virtReg) != cg->getSpilledRegisterList()->end()))
               cg->getSpilledRegisterList()->push_front(virtReg);
            }
         // we also need to free up all locked backing storage if we are exiting the OOL during backwards RA assignment
         else if (currentInstruction->isLabel() && virtReg->getAssignedRealRegister())
            {
            TR::PPCLabelInstruction *labelInstr = (TR::PPCLabelInstruction *)currentInstruction;
            TR_BackingStore * location = virtReg->getBackingStorage();
            TR_RegisterKinds rk = virtReg->getKind();
            int32_t dataSize;
            if (labelInstr->getLabelSymbol()->isStartOfColdInstructionStream() && location)
               {
               traceMsg (comp,"\nOOL: Releasing backing storage (%p)\n", location);
               if (rk == TR_GPR)
                  dataSize = TR::Compiler->om.sizeofReferenceAddress();
               else
                  dataSize = 8;
               location->setMaxSpillDepth(0);
               cg->freeSpill(location,dataSize,0);
               virtReg->setBackingStorage(NULL);
               }
            }
         }
      }

   for (i = 0; i < numberOfRegisters; i++)
      {
      map.addDependency(_dependencies[i], i);

      virtReg = _dependencies[i].getRegister();
      dependentRegNum = _dependencies[i].getRealRegister();

      if (dependentRegNum != TR::RealRegister::SpilledReg)
         {
         if (virtReg->getKind() == TR_GPR)
            num_gprs++;
         else if (virtReg->getKind() == TR_FPR)
            num_fprs++;
         else if (virtReg->getKind() == TR_VRF)
            num_vrfs++;
         }
      }

#ifdef DEBUG
   int locked_gprs = 0;
   int locked_fprs = 0;
   int locked_vrfs = 0;

   // count up how many registers are locked for each type
   for(i = TR::RealRegister::FirstGPR; i <= TR::RealRegister::LastGPR; i++)
      {
        realReg = machine->getPPCRealRegister((TR::RealRegister::RegNum)i);
        if (realReg->getState() == TR::RealRegister::Locked)
           locked_gprs++;
      }
   for(i = TR::RealRegister::FirstFPR; i <= TR::RealRegister::LastFPR; i++)
      {
        realReg = machine->getPPCRealRegister((TR::RealRegister::RegNum)i);
        if (realReg->getState() == TR::RealRegister::Locked)
           locked_fprs++;
      }
   for(i = TR::RealRegister::FirstVRF; i <= TR::RealRegister::LastVRF; i++)
      {
        realReg = machine->getPPCRealRegister((TR::RealRegister::RegNum)i);
        if (realReg->getState() == TR::RealRegister::Locked)
           locked_vrfs++;
      }
   TR_ASSERT( locked_gprs == machine->getNumberOfLockedRegisters(TR_GPR),"Inconsistent number of locked GPRs");
   TR_ASSERT( locked_fprs == machine->getNumberOfLockedRegisters(TR_FPR),"Inconsistent number of locked FPRs");
   TR_ASSERT( locked_vrfs == machine->getNumberOfLockedRegisters(TR_VRF), "Inconsistent number of locked VRFs");
#endif

   // To handle circular dependencies, we block a real register if (1) it is already assigned to a correct
   // virtual register and (2) if it is assigned to one register in the list but is required by another.
   // However, if all available registers are requested, we do not block in case (2) to avoid all registers
   // being blocked.

   bool block_gprs = true;
   bool block_fprs = true;
   bool block_vrfs = true;

   TR_ASSERT(num_gprs <= (TR::RealRegister::LastGPR - TR::RealRegister::FirstGPR + 1 - machine->getNumberOfLockedRegisters(TR_GPR)), "Too many GPR dependencies, unable to assign" );
   TR_ASSERT(num_fprs <= (TR::RealRegister::LastFPR - TR::RealRegister::FirstFPR + 1 - machine->getNumberOfLockedRegisters(TR_FPR)), "Too many FPR dependencies, unable to assign" );
   TR_ASSERT(num_vrfs <= (TR::RealRegister::LastVRF - TR::RealRegister::FirstVRF + 1 - machine->getNumberOfLockedRegisters(TR_VRF)), "Too many VRF dependencies, unable to assign" );

   if (num_gprs == (TR::RealRegister::LastGPR - TR::RealRegister::FirstGPR + 1 - machine->getNumberOfLockedRegisters(TR_GPR)))
        block_gprs = false;
   if (num_fprs == (TR::RealRegister::LastFPR - TR::RealRegister::FirstFPR + 1 - machine->getNumberOfLockedRegisters(TR_FPR)))
        block_fprs = false;
   if (num_vrfs == (TR::RealRegister::LastVRF - TR::RealRegister::FirstVRF + 1 - machine->getNumberOfLockedRegisters(TR_VRF)))
        block_vrfs = false;

   for (i = 0; i < numberOfRegisters; i++)
      {
      virtReg = _dependencies[i].getRegister();

      if (virtReg->getAssignedRealRegister()!=NULL)
         {
         if (_dependencies[i].getRealRegister() == TR::RealRegister::NoReg)
            {
            virtReg->block();
            }
         else
            {
            TR::RealRegister::RegNum assignedRegNum;
            assignedRegNum = toRealRegister(virtReg->getAssignedRealRegister())->getRegisterNumber();

            // always block if required register and assigned register match;
            // block if assigned register is required by other dependency but only if
            // any spare registers are left to avoid blocking all existing registers
            if (_dependencies[i].getRealRegister() == assignedRegNum ||
                (map.getDependencyWithTarget(assignedRegNum) &&
                 ((virtReg->getKind() != TR_GPR || block_gprs) &&
                  (virtReg->getKind() != TR_FPR || block_fprs) &&
                  (virtReg->getKind() != TR_VRF || block_vrfs))))
               {
               virtReg->block();
               }
            }
         }
      }

   // Assign all virtual regs that depend on a specific real reg that is free
   for (i = 0; i < numberOfRegisters; i++)
      {
      virtReg = _dependencies[i].getRegister();
      dependentRegNum = _dependencies[i].getRealRegister();
      dependentRealReg = machine->getPPCRealRegister(dependentRegNum);

      if (dependentRegNum != TR::RealRegister::NoReg &&
          dependentRegNum != TR::RealRegister::SpilledReg &&
          dependentRealReg->getState() == TR::RealRegister::Free)
         {
         assignFreeRegisters(currentInstruction, &_dependencies[i], map, cg);
         }
      }

   // Assign all virtual regs that depend on a specfic real reg that is not free
   for (i = 0; i < numberOfRegisters; i++)
      {
      virtReg     = _dependencies[i].getRegister();
      assignedRegister = NULL;
      if (virtReg->getAssignedRealRegister() != NULL)
         {
         assignedRegister = toRealRegister(virtReg->getAssignedRealRegister());
         }
      dependentRegNum = _dependencies[i].getRealRegister();
      dependentRealReg = machine->getPPCRealRegister(dependentRegNum);
      if (dependentRegNum != TR::RealRegister::NoReg &&
          dependentRegNum != TR::RealRegister::SpilledReg &&
          dependentRealReg != assignedRegister)
         {
         bool depsBlocked = false;
         switch (_dependencies[i].getRegister()->getKind())
            {
            case TR_GPR:
               depsBlocked = block_gprs;
               break;
            case TR_FPR:
               depsBlocked = block_fprs;
               break;
            case TR_VRF:
               depsBlocked = block_vrfs;
               break;
            }
         assignContendedRegisters(currentInstruction, &_dependencies[i], map, depsBlocked, cg);
         }
      }

   // Assign all virtual regs that depend on NoReg but exclude gr0
   for (i=0; i<numberOfRegisters; i++)
      {
      if (_dependencies[i].getRealRegister() == TR::RealRegister::NoReg && _dependencies[i].getExcludeGPR0())
         {
         TR::RealRegister *realOne;

         virtReg     = _dependencies[i].getRegister();
         realOne     = virtReg->getAssignedRealRegister();
         if (realOne!=NULL && toRealRegister(realOne)->getRegisterNumber()==TR::RealRegister::gr0)
            {
            if ((assignedRegister = machine->findBestFreeRegister(currentInstruction, virtReg->getKind(), true, false, virtReg)) == NULL)
               {
               assignedRegister = machine->freeBestRegister(currentInstruction, virtReg, NULL, true);
               }
            machine->coerceRegisterAssignment(currentInstruction, virtReg, assignedRegister->getRegisterNumber());
            }
         else if (realOne == NULL)
            {
            machine->assignOneRegister(currentInstruction, virtReg, true);
            }
         virtReg->block();
         }
      }

   // Assign all virtual regs that depend on NoReg
   for (i=0; i<numberOfRegisters; i++)
      {
      if (_dependencies[i].getRealRegister() == TR::RealRegister::NoReg && !_dependencies[i].getExcludeGPR0())
         {
         TR::RealRegister *realOne;

         virtReg     = _dependencies[i].getRegister();
         realOne     = virtReg->getAssignedRealRegister();
         if (!realOne)
            {
            machine->assignOneRegister(currentInstruction, virtReg, false);
            }
         virtReg->block();
         }
      }

   unblockRegisters(numberOfRegisters);
   for (i = 0; i < numberOfRegisters; i++)
      {
      TR::Register     *dependentRegister = getRegisterDependency(i)->getRegister();
      // dependentRegister->getAssignedRegister() is NULL if the reg has already been spilled due to a spilledReg dep
      if (comp->getOption(TR_DisableOOL) || (!(cg->isOutOfLineColdPath()) && !(cg->isOutOfLineHotPath())))
         {
         TR_ASSERT(dependentRegister->getAssignedRegister(),
             "assignedRegister can not  be NULL");
         }
      if (dependentRegister->getAssignedRegister())
         {
         TR::RealRegister *assignedRegister = dependentRegister->getAssignedRegister()->getRealRegister();

         if (getRegisterDependency(i)->getRealRegister() == TR::RealRegister::NoReg)
            getRegisterDependency(i)->setRealRegister(toRealRegister(assignedRegister)->getRegisterNumber());

         machine->decFutureUseCountAndUnlatch(dependentRegister);
         }
      }
   }
static void assignContendedRegisters(TR::Instruction              *currentInstruction,
                                     TR::RegisterDependency    *dep,
                                     TR_PPCRegisterDependencyMap& map,
                                     bool                         depsBlocked,
                                     TR::CodeGenerator            *cg)
   {
   // *this    swipeable for debugging purposes
   TR::Machine *machine = cg->machine();

   dep = findDependencyChainHead(dep, map);


   TR::Register *virtReg = dep->getRegister();
   TR::RealRegister::RegNum targetRegNum = dep->getRealRegister();
   TR::RealRegister *targetReg = machine->getPPCRealRegister(targetRegNum);
   TR::RealRegister *assignedReg = virtReg->getAssignedRealRegister() ?
      toRealRegister(virtReg->getAssignedRealRegister()) :  NULL;


   // Chain of length 1
   if (!assignedReg || !map.getDependencyWithTarget(assignedReg->getRegisterNumber()))
      {
      machine->coerceRegisterAssignment(currentInstruction, virtReg, targetRegNum);
      virtReg->block();
      return;
      }
   // Chain of length 2, handled here instead of below to get 3*xor exchange on GPRs
   if (map.getDependencyWithTarget(assignedReg->getRegisterNumber()) == map.getDependencyWithAssigned(targetRegNum))
      {
      TR::Register *targetVirtReg = targetReg->getAssignedRegister();
      machine->coerceRegisterAssignment(currentInstruction, virtReg, targetRegNum);
      virtReg->block();
      targetVirtReg->block();
      return;
      }

   // Grab a spare reg in order to free the target of the first dep
   // At this point the first dep's target could be blocked, assigned, or NoReg
   // If it's blocked or assigned we allocate a spare and assign the target's virtual to it
   // If it's NoReg, the spare reg will be used as the first dep's actual target
   TR::RealRegister *spareReg = machine->findBestFreeRegister(currentInstruction, virtReg->getKind(),
                                                                targetRegNum == TR::RealRegister::NoReg ? dep->getExcludeGPR0() : false, false,
                                                                targetRegNum == TR::RealRegister::NoReg ? virtReg : targetReg->getAssignedRegister());
   bool                haveFreeSpare = spareReg != NULL;
   if (!spareReg)
      {
      // If the regs in this dep group are not blocked we need to make sure we don't spill a reg that's in the middle of the chain
      if (!depsBlocked)
         {
         if (targetRegNum == TR::RealRegister::NoReg)
            spareReg = machine->freeBestRegister(currentInstruction,
                                                 map.getDependencyWithTarget(assignedReg->getRegisterNumber())->getRegister(),
                                                 assignedReg, false);
         else
            spareReg = machine->freeBestRegister(currentInstruction, virtReg, targetReg, false);
         }
      else
         {
         if (targetRegNum == TR::RealRegister::NoReg)
            spareReg = machine->freeBestRegister(currentInstruction, virtReg, NULL, dep->getExcludeGPR0());
         else
            spareReg = machine->freeBestRegister(currentInstruction, targetReg->getAssignedRegister(), NULL, false);
         }
      }

   if (targetRegNum != TR::RealRegister::NoReg && spareReg != targetReg)
      {
      machine->coerceRegisterAssignment(currentInstruction, targetReg->getAssignedRegister(), spareReg->getRegisterNumber());
      }

   TR_ASSERT(targetRegNum == TR::RealRegister::NoReg ||
          targetReg->getState() == TR::RealRegister::Free, "Expecting free target register");

   if (depsBlocked || targetRegNum != TR::RealRegister::NoReg || haveFreeSpare)
      {

      machine->coerceRegisterAssignment(currentInstruction, virtReg,
                                        targetRegNum == TR::RealRegister::NoReg ?
                                        spareReg->getRegisterNumber() : targetRegNum);
      virtReg->block();
      }

   dep = map.getDependencyWithTarget(assignedReg->getRegisterNumber());
   while (dep)
      {
      virtReg = dep->getRegister();
      targetRegNum = dep->getRealRegister();
      targetReg = machine->getPPCRealRegister(targetRegNum);
      assignedReg = virtReg->getAssignedRealRegister() ?
         toRealRegister(virtReg->getAssignedRealRegister()) : NULL;

      TR_ASSERT(targetReg->getState() == TR::RealRegister::Free || targetReg == spareReg,
             "Expecting free target register or target to have been filled to free spare register");

      machine->coerceRegisterAssignment(currentInstruction, virtReg, targetRegNum);
      virtReg->block();
      dep = assignedReg ?
         map.getDependencyWithTarget(assignedReg->getRegisterNumber()) : NULL;
      }

   }
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;
   }
Exemple #7
0
TR::Register *IA32LinkageUtils::pushDoubleArg(
      TR::Node *child,
      TR::CodeGenerator *cg)
   {
   TR::Register *pushRegister;
   if (child->getRegister() == NULL)
      {
      if (child->getOpCodeValue() == TR::dconst)
         {
         TR_X86OpCodes pushOp;

         int32_t highValue = child->getLongIntHigh();
         if (highValue >= -128 && highValue <= 127)
            {
            pushOp = PUSHImms;
            }
         else
            {
            pushOp = PUSHImm4;
            }
         generateImmInstruction(pushOp, child, highValue, cg);

         int32_t lowValue = child->getLongIntLow();
         if (lowValue >= -128 && lowValue <= 127)
            {
            pushOp = PUSHImms;
            }
         else
            {
            pushOp = PUSHImm4;
            }
         generateImmInstruction(pushOp, child, lowValue, cg);
         cg->decReferenceCount(child);
         return NULL;
         }
      else if (child->getReferenceCount() == 1)
         {
         if (child->getOpCode().isLoad())
            {
            TR::MemoryReference  *lowMR = generateX86MemoryReference(child, cg);
            generateMemInstruction(PUSHMem, child, generateX86MemoryReference(*lowMR, 4, cg), cg);
            generateMemInstruction(PUSHMem, child, lowMR, cg);
            lowMR->decNodeReferenceCounts(cg);
            cg->decReferenceCount(child);
            return NULL;
            }
         else if (child->getOpCodeValue() == TR::lbits2d)
            {
            pushRegister = pushLongArg(child->getFirstChild(), cg);
            cg->decReferenceCount(child);
            return pushRegister;
            }
         }
      }

   pushRegister = cg->evaluate(child);
   TR::RealRegister *espReal = cg->machine()->getRealRegister(TR::RealRegister::esp);
   generateRegImmInstruction(SUB4RegImms, child, espReal, 8, cg);

   if (cg->useSSEForSinglePrecision() && pushRegister->getKind() == TR_FPR)
      generateMemRegInstruction(MOVSDMemReg, child, generateX86MemoryReference(espReal, 0, cg), pushRegister, cg);
   else
      generateFPMemRegInstruction(DSTMemReg, child, generateX86MemoryReference(espReal, 0, cg), pushRegister, cg);

   cg->decReferenceCount(child);
   return pushRegister;
   }
Exemple #8
0
void TR_ARMRegisterDependencyGroup::assignRegisters(TR::Instruction  *currentInstruction,
                                                    TR_RegisterKinds kindToBeAssigned,
                                                    uint32_t         numberOfRegisters,
                                                    TR::CodeGenerator *cg)
   {
   TR::Compilation *comp = cg->comp();
   TR::Machine *machine = cg->machine();
   TR::Register  *virtReg;
   TR::RealRegister::RegNum dependentRegNum;
   TR::RealRegister *dependentRealReg, *assignedRegister;
   uint32_t i, j;
   bool changed;

   if (!comp->getOption(TR_DisableOOL))
      {
      for (i = 0; i< numberOfRegisters; i++)
         {
         virtReg = dependencies[i].getRegister();
         dependentRegNum = dependencies[i].getRealRegister();
         if (dependentRegNum == TR::RealRegister::SpilledReg)
            {
            TR_ASSERT(virtReg->getBackingStorage(),"should have a backing store if dependentRegNum == spillRegIndex()\n");
            if (virtReg->getAssignedRealRegister())
               {
               // this happens when the register was first spilled in main line path then was reverse spilled
               // and assigned to a real register in OOL path. We protected the backing store when doing
               // the reverse spill so we could re-spill to the same slot now
               traceMsg (comp,"\nOOL: Found register spilled in main line and re-assigned inside OOL");
               TR::Node *currentNode = currentInstruction->getNode();
               TR::RealRegister *assignedReg    = toRealRegister(virtReg->getAssignedRegister());
               TR::MemoryReference *tempMR = new (cg->trHeapMemory()) TR::MemoryReference(currentNode, (TR::SymbolReference*)virtReg->getBackingStorage()->getSymbolReference(), sizeof(uintptr_t), cg);
               TR_ARMOpCodes opCode;
               TR_RegisterKinds rk = virtReg->getKind();
               switch (rk)
                  {
                  case TR_GPR:
                     opCode = ARMOp_ldr;
                     break;
                  case TR_FPR:
                     opCode = virtReg->isSinglePrecision() ? ARMOp_ldfs : ARMOp_ldfd;
                     break;
                  default:
                     TR_ASSERT(0, "\nRegister kind not supported in OOL spill\n");
                     break;
                  }

               TR::Instruction *inst = generateTrg1MemInstruction(cg, opCode, currentNode, assignedReg, tempMR, currentInstruction);

               assignedReg->setAssignedRegister(NULL);
               virtReg->setAssignedRegister(NULL);
               assignedReg->setState(TR::RealRegister::Free);

               if (comp->getDebug())
                  cg->traceRegisterAssignment("Generate reload of virt %s due to spillRegIndex dep at inst %p\n", cg->comp()->getDebug()->getName(virtReg),currentInstruction);
               cg->traceRAInstruction(inst);
               }
            if (!(std::find(cg->getSpilledRegisterList()->begin(), cg->getSpilledRegisterList()->end(), virtReg) != cg->getSpilledRegisterList()->end()))
               cg->getSpilledRegisterList()->push_front(virtReg);
            }
         // we also need to free up all locked backing storage if we are exiting the OOL during backwards RA assignment
         else if (currentInstruction->isLabel() && virtReg->getAssignedRealRegister())
            {
            TR::ARMLabelInstruction *labelInstr = (TR::ARMLabelInstruction *)currentInstruction;
            TR_BackingStore *location = virtReg->getBackingStorage();
            TR_RegisterKinds rk = virtReg->getKind();
            int32_t dataSize;
            if (labelInstr->getLabelSymbol()->isStartOfColdInstructionStream() && location)
               {
               traceMsg (comp,"\nOOL: Releasing backing storage (%p)\n", location);
               if (rk == TR_GPR)
                  dataSize = TR::Compiler->om.sizeofReferenceAddress();
               else
                  dataSize = 8;
               location->setMaxSpillDepth(0);
               cg->freeSpill(location,dataSize,0);
               virtReg->setBackingStorage(NULL);
               }
            }
         }
      }
   for (i = 0; i < numberOfRegisters; i++)
      {
      virtReg = dependencies[i].getRegister();

      if (virtReg->getAssignedRealRegister()!=NULL)
         {
         if (dependencies[i].getRealRegister() == TR::RealRegister::NoReg)
            {
            virtReg->block();
            }
         else
            {
            dependentRegNum = toRealRegister(virtReg->getAssignedRealRegister())->getRegisterNumber();
            for (j=0; j<numberOfRegisters; j++)
               {
               if (dependentRegNum == dependencies[j].getRealRegister())
                  {
                  virtReg->block();
                  break;
                  }
               }
            }
         }
      }

   do
      {
      changed = false;
      for (i = 0; i < numberOfRegisters; i++)
         {
         virtReg = dependencies[i].getRegister();
         dependentRegNum = dependencies[i].getRealRegister();
         dependentRealReg = machine->getRealRegister(dependentRegNum);

         if (dependentRegNum != TR::RealRegister::NoReg &&
             dependentRegNum != TR::RealRegister::SpilledReg &&
             dependentRealReg->getState() == TR::RealRegister::Free)
            {
            machine->coerceRegisterAssignment(currentInstruction, virtReg, dependentRegNum);
            virtReg->block();
            changed = true;
            }
         }
      } while (changed == true);


   do
      {
      changed = false;
      for (i = 0; i < numberOfRegisters; i++)
         {
         virtReg = dependencies[i].getRegister();
         assignedRegister = NULL;
         if (virtReg->getAssignedRealRegister() != NULL)
            {
            assignedRegister = toRealRegister(virtReg->getAssignedRealRegister());
            }
         dependentRegNum = dependencies[i].getRealRegister();
         dependentRealReg = machine->getRealRegister(dependentRegNum);
         if (dependentRegNum != TR::RealRegister::NoReg &&
             dependentRegNum != TR::RealRegister::SpilledReg &&
             dependentRealReg != assignedRegister)
            {
            machine->coerceRegisterAssignment(currentInstruction, virtReg, dependentRegNum);
            virtReg->block();
            changed = true;
            }
         }
      } while (changed == true);

   for (i=0; i<numberOfRegisters; i++)
      {
      if (dependencies[i].getRealRegister() == TR::RealRegister::NoReg)
         {
         bool excludeGPR0 = dependencies[i].getExcludeGPR0()?true:false;
         TR::RealRegister *realOne;

         virtReg = dependencies[i].getRegister();
         realOne = virtReg->getAssignedRealRegister();
         if (realOne!=NULL && excludeGPR0 && toRealRegister(realOne)->getRegisterNumber()==TR::RealRegister::gr0)
            {
            if ((assignedRegister = machine->findBestFreeRegister(virtReg->getKind(), true)) == NULL)
               {
               assignedRegister = machine->freeBestRegister(currentInstruction, virtReg->getKind(), NULL, true);
               }
            machine->coerceRegisterAssignment(currentInstruction, virtReg, assignedRegister->getRegisterNumber());
            }
         else if (realOne == NULL)
            {
            if (virtReg->getTotalUseCount() == virtReg->getFutureUseCount())
               {
               if ((assignedRegister = machine->findBestFreeRegister(virtReg->getKind(), excludeGPR0, true)) == NULL)
                  {
                  assignedRegister = machine->freeBestRegister(currentInstruction, virtReg->getKind(), NULL, excludeGPR0);
                  }
               }
            else
               {
               assignedRegister = machine->reverseSpillState(currentInstruction, virtReg, NULL, excludeGPR0);
               }
            virtReg->setAssignedRegister(assignedRegister);
            assignedRegister->setAssignedRegister(virtReg);
            assignedRegister->setState(TR::RealRegister::Assigned);
            virtReg->block();
            }
         }
      }

   unblockRegisters(numberOfRegisters);
   for (i = 0; i < numberOfRegisters; i++)
      {
      TR::Register *dependentRegister = getRegisterDependency(i)->getRegister();
      if (dependentRegister->getAssignedRegister())
      	 {
         TR::RealRegister *assignedRegister = dependentRegister->getAssignedRegister()->getRealRegister();

         if (getRegisterDependency(i)->getRealRegister() == TR::RealRegister::NoReg)
            getRegisterDependency(i)->setRealRegister(toRealRegister(assignedRegister)->getRegisterNumber());

         if (dependentRegister->decFutureUseCount() == 0)
            {
            dependentRegister->setAssignedRegister(NULL);
            assignedRegister->setAssignedRegister(NULL);
            assignedRegister->setState(TR::RealRegister::Unlatched); // Was setting to Free
            }
         }
      }
   }