Exemple #1
0
TR::Register *
TR::AMD64SystemLinkage::buildIndirectDispatch(TR::Node *callNode)
   {
   TR::SymbolReference *methodSymRef = callNode->getSymbolReference();
   TR_ASSERT(methodSymRef->getSymbol()->castToMethodSymbol()->isComputed(), "system linkage only supports computed indirect call for now %p\n", callNode);

   // Evaluate VFT
   //
   TR::Register *vftRegister;
   TR::Node *vftNode = callNode->getFirstChild();
   if (vftNode->getRegister())
      {
      vftRegister = vftNode->getRegister();
      }
   else
      {
      vftRegister = cg()->evaluate(vftNode);
      }

   // Allocate adequate register dependencies.
   //
   // pre = number of argument registers + 1 for VFT register
   // post = number of volatile + VMThread + return register
   //
   uint32_t pre = getProperties().getNumIntegerArgumentRegisters() + getProperties().getNumFloatArgumentRegisters() + 1;
   uint32_t post = getProperties().getNumVolatileRegisters() + 1 + (callNode->getDataType() == TR::NoType ? 0 : 1);

#if defined (PYTHON) && 0
   // Treat all preserved GP regs as volatile until register map support available.
   //
   post += getProperties().getNumberOfPreservedGPRegisters();
#endif

   TR::RegisterDependencyConditions *callDeps = generateRegisterDependencyConditions(pre, 1, cg());

   TR::RealRegister::RegNum scratchRegIndex = getProperties().getIntegerScratchRegister(1);
   callDeps->addPostCondition(vftRegister, scratchRegIndex, cg());
   callDeps->stopAddingPostConditions();

   // Evaluate outgoing arguments on the system stack and build pre-conditions.
   //
   int32_t memoryArgSize = buildArgs(callNode, callDeps);

   // Dispatch
   //
   generateRegInstruction(CALLReg, callNode, vftRegister, callDeps, cg());
   cg()->resetIsLeafMethod();

   // Build label post-conditions
   //
   TR::RegisterDependencyConditions *postDeps = generateRegisterDependencyConditions(0, post, cg());
   TR::Register *returnReg = buildVolatileAndReturnDependencies(callNode, postDeps);
   postDeps->stopAddingPostConditions();

   TR::LabelSymbol *postDepLabel = generateLabelSymbol(cg());
   generateLabelInstruction(LABEL, callNode, postDepLabel, postDeps, cg());

   return returnReg;
   }
Exemple #2
0
static TR::Register *l2fd(TR::Node *node, TR::RealRegister *target, TR_X86OpCodes opRegMem8, TR_X86OpCodes opRegReg8, TR::CodeGenerator *cg)
   {
   TR::Node                *child = node->getFirstChild();
   TR::MemoryReference  *tempMR;

   TR_ASSERT(cg->useSSEForSinglePrecision(), "assertion failure");

   if (child->getRegister() == NULL &&
       child->getReferenceCount() == 1 &&
       child->getOpCode().isLoadVar())
      {
      tempMR = generateX86MemoryReference(child, cg);
      generateRegMemInstruction(opRegMem8, node, target, tempMR, cg);
      tempMR->decNodeReferenceCounts(cg);
      }
   else
      {
      TR::Register *intReg = cg->evaluate(child);
      generateRegRegInstruction(opRegReg8, node, target, intReg, cg);
      cg->decReferenceCount(child);
      }

   node->setRegister(target);
   return target;
   }
Exemple #3
0
static TR::Register *addOrSubInteger(TR::Node *node, TR::CodeGenerator *cg)
   {
   TR::Node *firstChild = node->getFirstChild();
   TR::Register *src1Reg = cg->evaluate(firstChild);
   TR::Node *secondChild = node->getSecondChild();
   TR::Register *trgReg = cg->allocateRegister();
   bool isAdd = node->getOpCode().isAdd();

   if (secondChild->getOpCode().isLoadConst() && secondChild->getRegister() == NULL)
      {
      int32_t value = secondChild->getInt();
      if (constantIsUnsignedImm12(value))
         {
         generateTrg1Src1ImmInstruction(cg, isAdd ? TR::InstOpCode::addimmw : TR::InstOpCode::subimmw, node, trgReg, src1Reg, value);
         }
      else
         {
         TR::Register *tmpReg = cg->allocateRegister();
         loadConstant32(cg, node, value, tmpReg);
         generateTrg1Src2Instruction(cg, isAdd ? TR::InstOpCode::addw : TR::InstOpCode::subw, node, trgReg, src1Reg, tmpReg);
         cg->stopUsingRegister(tmpReg);
         }
      }
   else
      {
      TR::Register *src2Reg = cg->evaluate(secondChild);
      generateTrg1Src2Instruction(cg, isAdd ? TR::InstOpCode::addw : TR::InstOpCode::subw, node, trgReg, src1Reg, src2Reg);
      }

   node->setRegister(trgReg);
   firstChild->decReferenceCount();
   secondChild->decReferenceCount();
   return trgReg;
   }
Exemple #4
0
TR::Register *
OMR::ARM64::TreeEvaluator::lmulhEvaluator(TR::Node *node, TR::CodeGenerator *cg)
   {
   TR::Node *firstChild = node->getFirstChild();
   TR::Register *src1Reg = cg->evaluate(firstChild);
   TR::Node *secondChild = node->getSecondChild();
   TR::Register *src2Reg;
   TR::Register *trgReg = cg->allocateRegister();
   TR::Register *tmpReg = NULL;

   // lmulh is generated for constant ldiv and the second child is the magic number
   // assume magic number is usually a large odd number with little optimization opportunity
   if (secondChild->getOpCode().isLoadConst() && secondChild->getRegister() == NULL)
      {
      int64_t value = secondChild->getLongInt();
      src2Reg = tmpReg = cg->allocateRegister();
      loadConstant64(cg, node, value, src2Reg);
      }
   else
      {
      src2Reg = cg->evaluate(secondChild);
      }

   generateTrg1Src2Instruction(cg, TR::InstOpCode::smulh, node, trgReg, src1Reg, src2Reg);

   if (tmpReg)
      {
      cg->stopUsingRegister(tmpReg);
      }

   firstChild->decReferenceCount();
   secondChild->decReferenceCount();
   node->setRegister(trgReg);
   return trgReg;
   }
Exemple #5
0
TR::Register *
OMR::ARM64::TreeEvaluator::imulEvaluator(TR::Node *node, TR::CodeGenerator *cg)
   {
   TR::Node *firstChild = node->getFirstChild();
   TR::Register *src1Reg = cg->evaluate(firstChild);
   TR::Node *secondChild = node->getSecondChild();
   TR::Register *trgReg;

   if (secondChild->getOpCode().isLoadConst() && secondChild->getRegister() == NULL)
      {
      int32_t value = secondChild->getInt();
      if (value > 0 && cg->convertMultiplyToShift(node))
         {
         // The multiply has been converted to a shift.
         trgReg = cg->evaluate(node);
         return trgReg;
         }
      else
         {
         trgReg = cg->allocateRegister();
         mulConstant32(node, trgReg, src1Reg, value, cg);
         }
      }
   else
      {
      TR::Register *src2Reg = cg->evaluate(secondChild);
      trgReg = cg->allocateRegister();
      generateMulInstruction(cg, node, trgReg, src1Reg, src2Reg);
      }
   firstChild->decReferenceCount();
   secondChild->decReferenceCount();
   node->setRegister(trgReg);
   return trgReg;
   }
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;
   }
Exemple #7
0
void
OMR::CodeGenerator::evaluateChildrenWithMultipleRefCount(TR::Node * node)
   {
   for (int i=0; i < node->getNumChildren(); i++)
      {
      TR::Node *child = node->getChild(i);
      if (child->getRegister() == NULL) // not already evaluated
         {
         // Note: we assume things without a symbol reference don't
         // necessarily need to be evaluated here, and can wait
         // until they are actually needed.
         //
         // vft pointers are speical - we need to evaluate the object in all cases
         // but for nopable virtual guards we can wait to load and mask the pointer
         // until we actually need to use it
         //
         if (child->getReferenceCount() > 1 && 
	     (child->getOpCode().hasSymbolReference() ||
	      (child->getOpCodeValue() == TR::l2a && child->getChild(0)->containsCompressionSequence())))
            {
            TR::SymbolReference *vftPointerSymRef = TR::comp()->getSymRefTab()->element(TR::SymbolReferenceTable::vftSymbol);
            if (node->isNopableInlineGuard()
                && self()->getSupportsVirtualGuardNOPing()
                && child->getOpCodeValue() == TR::aloadi
                && child->getChild(0)->getOpCode().hasSymbolReference()
                && child->getChild(0)->getSymbolReference() == vftPointerSymRef
                && child->getChild(0)->getOpCodeValue() == TR::aloadi)
               {
               if (!child->getChild(0)->getChild(0)->getRegister() &&
                   child->getChild(0)->getChild(0)->getReferenceCount() > 1)
                  self()->evaluate(child->getChild(0)->getChild(0));
               else
                  self()->evaluateChildrenWithMultipleRefCount(child->getChild(0)->getChild(0));
               }
            else
               {
               self()->evaluate(child);
               }
            }
         else
            {
            self()->evaluateChildrenWithMultipleRefCount(child);
            }
         }
      }
   }
Exemple #8
0
// TODO:AMD64: Could this be combined with istoreEvaluator without too much ugliness?
TR::Register *OMR::X86::AMD64::TreeEvaluator::lstoreEvaluator(TR::Node *node, TR::CodeGenerator *cg)
   {
   TR::Node *valueChild;
   TR::Compilation* comp = cg->comp();

   if (node->getOpCode().isIndirect())
      valueChild = node->getSecondChild();
   else
      valueChild = node->getFirstChild();

   // Handle special cases
   //
   if (valueChild->getRegister() == NULL &&
       valueChild->getReferenceCount() == 1)
      {
      // Special case storing a double value into long variable
      //
      if (valueChild->getOpCodeValue() == TR::dbits2l &&
          !valueChild->normalizeNanValues())
         {
         if (node->getOpCode().isIndirect())
            {
            node->setChild(1, valueChild->getFirstChild());
            TR::Node::recreate(node, TR::dstorei);
            TR::TreeEvaluator::floatingPointStoreEvaluator(node, cg);
            node->setChild(1, valueChild);
            TR::Node::recreate(node, TR::lstorei);
            }
         else
            {
            node->setChild(0, valueChild->getFirstChild());
            TR::Node::recreate(node, TR::dstore);
            TR::TreeEvaluator::floatingPointStoreEvaluator(node, cg);
            node->setChild(0, valueChild);
            TR::Node::recreate(node, TR::lstore);
            }
         cg->decReferenceCount(valueChild);
         return NULL;
         }
      }

   return TR::TreeEvaluator::integerStoreEvaluator(node, cg);
   }
Exemple #9
0
TR::Register *
OMR::ARM64::TreeEvaluator::imulhEvaluator(TR::Node *node, TR::CodeGenerator *cg)
   {
   TR::Node *firstChild = node->getFirstChild();
   TR::Register *src1Reg = cg->evaluate(firstChild);
   TR::Node *secondChild = node->getSecondChild();
   TR::Register *src2Reg;
   TR::Register *trgReg = cg->allocateRegister();
   TR::Register *tmpReg = NULL;

   TR::Register *zeroReg = cg->allocateRegister();
   TR::RegisterDependencyConditions *cond = new (cg->trHeapMemory()) TR::RegisterDependencyConditions(1, 1, cg->trMemory());
   addDependency(cond, zeroReg, TR::RealRegister::xzr, TR_GPR, cg);

   // imulh is generated for constant idiv and the second child is the magic number
   // assume magic number is usually a large odd number with little optimization opportunity
   if (secondChild->getOpCode().isLoadConst() && secondChild->getRegister() == NULL)
      {
      int32_t value = secondChild->getInt();
      src2Reg = tmpReg = cg->allocateRegister();
      loadConstant32(cg, node, value, src2Reg);
      }
   else
      {
      src2Reg = cg->evaluate(secondChild);
      }

   generateTrg1Src3Instruction(cg, TR::InstOpCode::smaddl, node, trgReg, src1Reg, src2Reg, zeroReg, cond);
   cg->stopUsingRegister(zeroReg);
   /* logical shift right by 32 bits */
   uint32_t imm = 0x183F; // N=1, immr=32, imms=63
   generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::ubfmx, node, trgReg, trgReg, imm);

   if (tmpReg)
      {
      cg->stopUsingRegister(tmpReg);
      }

   firstChild->decReferenceCount();
   secondChild->decReferenceCount();
   node->setRegister(trgReg);
   return trgReg;
   }
Exemple #10
0
int32_t
OMR::CodeGenerator::getEvaluationPriority(TR::Node *node)
   {
   // Evaluation priority is the depth of the sub-tree.
   //
   int32_t nodePriority = 0;

   for (int32_t childCount = node->getNumChildren() - 1; childCount >= 0; childCount--)
      {
      TR::Node *child = node->getChild(childCount);
      int32_t childPriority;
      if (child->getRegister() != NULL)
         childPriority = 0;
      else
         childPriority = child->getEvaluationPriority(self());
      if (childPriority >= nodePriority)
         nodePriority = childPriority + 1;
      }

   return nodePriority;
   }
Exemple #11
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 #12
0
void
TR_S390BinaryAnalyser::longSubtractAnalyser(TR::Node * root)
   {
   TR::Node * firstChild;
   TR::Node * secondChild;
   TR::Instruction * cursor = NULL;
   TR::RegisterDependencyConditions * dependencies = NULL;
   bool setsOrReadsCC = NEED_CC(root) || (root->getOpCodeValue() == TR::lusubb);
   TR::InstOpCode::Mnemonic regToRegOpCode;
   TR::InstOpCode::Mnemonic memToRegOpCode;
   TR::Compilation *comp = TR::comp();

   if (TR::Compiler->target.is64Bit() || cg()->use64BitRegsOn32Bit())
      {
      if (!setsOrReadsCC)
         {
         regToRegOpCode = TR::InstOpCode::SGR;
         memToRegOpCode = TR::InstOpCode::SG;
         }
      else
         {
         regToRegOpCode = TR::InstOpCode::SLGR;
         memToRegOpCode = TR::InstOpCode::SLG;
         }
      }
   else
      {
      regToRegOpCode = TR::InstOpCode::SLR;
      memToRegOpCode = TR::InstOpCode::SL;
      }

   firstChild = root->getFirstChild();
   secondChild = root->getSecondChild();
   TR::Register * firstRegister = firstChild->getRegister();
   TR::Register * secondRegister = secondChild->getRegister();

   setInputs(firstChild, firstRegister, secondChild, secondRegister,
             false, false, comp);

   /**  Attempt to use SGH to subtract halfword (64 <- 16).
    * The second child is a halfword from memory */
   bool is16BitMemory2Operand = false;
   if (TR::Compiler->target.cpu.getS390SupportsZ14() &&
       secondChild->getOpCodeValue() == TR::s2l &&
       secondChild->getFirstChild()->getOpCodeValue() == TR::sloadi &&
       secondChild->isSingleRefUnevaluated() &&
       secondChild->getFirstChild()->isSingleRefUnevaluated())
      {
      setMem2();
      memToRegOpCode = TR::InstOpCode::SGH;
      is16BitMemory2Operand = true;
      }

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

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

   remapInputs(firstChild, firstRegister, secondChild, secondRegister);

   if ((root->getOpCodeValue() == TR::lusubb) &&
       TR_S390ComputeCC::setCarryBorrow(root->getChild(2), false, cg()))
      {
      // use SLBGR rather than SLGR/SGR
      //     SLBG rather than SLG/SG
      // or
      // use SLBR rather than SLR
      //     SLB rather than SL
      bool uses64bit = TR::Compiler->target.is64Bit() || cg()->use64BitRegsOn32Bit();
      regToRegOpCode = uses64bit ? TR::InstOpCode::SLBGR : TR::InstOpCode::SLBR;
      memToRegOpCode = uses64bit ? TR::InstOpCode::SLBG  : TR::InstOpCode::SLB;
      }

   if (TR::Compiler->target.is64Bit() || cg()->use64BitRegsOn32Bit())
      {
      if (getCopyReg1())
         {
         TR::Register * thirdReg = cg()->allocate64bitRegister();

         root->setRegister(thirdReg);
         generateRRInstruction(cg(), TR::InstOpCode::LGR, root, thirdReg, firstRegister);
         if (getBinaryReg3Reg2())
            {
            generateRRInstruction(cg(), regToRegOpCode, root, thirdReg, secondRegister);
            }
         else // assert getBinaryReg3Mem2() == true
            {
            TR::MemoryReference * longMR = generateS390MemoryReference(secondChild, cg());

            generateRXInstruction(cg(), memToRegOpCode, root, thirdReg, longMR);
            longMR->stopUsingMemRefRegister(cg());
            }
         }
      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::Node* baseAddrNode = is16BitMemory2Operand ? secondChild->getFirstChild() : secondChild;
         TR::MemoryReference * longMR = generateS390MemoryReference(baseAddrNode, cg());

         generateRXInstruction(cg(), memToRegOpCode, root, firstRegister, longMR);

         longMR->stopUsingMemRefRegister(cg());
         root->setRegister(firstRegister);

         if(is16BitMemory2Operand)
            {
            cg()->decReferenceCount(secondChild->getFirstChild());
            }
         }

      }
   else    // if 32bit codegen...
      {
      bool zArchTrexsupported = performTransformation(comp, "O^O Use SL/SLB for long sub.");

      TR::Register * highDiff = NULL;
      TR::LabelSymbol * doneLSub = TR::LabelSymbol::create(cg()->trHeapMemory(),cg());
      if (getCopyReg1())
         {
         TR::Register * lowThird = cg()->allocateRegister();
         TR::Register * highThird = cg()->allocateRegister();

         TR::RegisterPair * thirdReg = cg()->allocateConsecutiveRegisterPair(lowThird, highThird);

         highDiff = highThird;

         dependencies = new (cg()->trHeapMemory()) TR::RegisterDependencyConditions(0, 9, cg());
         dependencies->addPostCondition(firstRegister, TR::RealRegister::EvenOddPair);
         dependencies->addPostCondition(firstRegister->getHighOrder(), TR::RealRegister::LegalEvenOfPair);
         dependencies->addPostCondition(firstRegister->getLowOrder(), TR::RealRegister::LegalOddOfPair);

         // If 2nd operand has ref count of 1 and can be accessed by a memory reference,
         // then second register will not be used.
         if(secondRegister == firstRegister && !setsOrReadsCC)
            {
            TR_ASSERT( false, "lsub with identical children - fix Simplifier");
            }
         if (secondRegister != NULL && firstRegister != secondRegister)
            {
            dependencies->addPostCondition(secondRegister, TR::RealRegister::EvenOddPair);
            dependencies->addPostCondition(secondRegister->getHighOrder(), TR::RealRegister::LegalEvenOfPair);
            dependencies->addPostCondition(secondRegister->getLowOrder(), TR::RealRegister::LegalOddOfPair);
            }
         dependencies->addPostCondition(highThird, TR::RealRegister::AssignAny);

         root->setRegister(thirdReg);
         generateRRInstruction(cg(), TR::InstOpCode::LR, root, highThird, firstRegister->getHighOrder());
         generateRRInstruction(cg(), TR::InstOpCode::LR, root, lowThird, firstRegister->getLowOrder());
         if (getBinaryReg3Reg2())
            {
            if ((ENABLE_ZARCH_FOR_32 && zArchTrexsupported) || setsOrReadsCC)
               {
               generateRRInstruction(cg(), regToRegOpCode, root, lowThird, secondRegister->getLowOrder());
               generateRRInstruction(cg(), TR::InstOpCode::SLBR, root, highThird, secondRegister->getHighOrder());
               }
            else
               {
               generateRRInstruction(cg(), TR::InstOpCode::SR, root, highThird, secondRegister->getHighOrder());
               generateRRInstruction(cg(), TR::InstOpCode::SLR, root, lowThird, secondRegister->getLowOrder());
               }
            }
         else // assert getBinaryReg3Mem2() == true
            {
            TR::MemoryReference * highMR = generateS390MemoryReference(secondChild, cg());
            TR::MemoryReference * lowMR = generateS390MemoryReference(*highMR, 4, cg());
            dependencies->addAssignAnyPostCondOnMemRef(highMR);

            if ((ENABLE_ZARCH_FOR_32 && zArchTrexsupported) || setsOrReadsCC)
               {
               generateRXInstruction(cg(), memToRegOpCode, root, lowThird, lowMR);
               generateRXInstruction(cg(), TR::InstOpCode::SLB, root, highThird, highMR);
               }
            else
               {
               generateRXInstruction(cg(), TR::InstOpCode::S, root, highThird, highMR);
               generateRXInstruction(cg(), TR::InstOpCode::SL, root, lowThird, lowMR);
               }
            highMR->stopUsingMemRefRegister(cg());
            lowMR->stopUsingMemRefRegister(cg());
            }
         }
      else if (getBinaryReg1Reg2())
         {
         dependencies = new (cg()->trHeapMemory()) TR::RegisterDependencyConditions(0, 6, cg());
         dependencies->addPostCondition(firstRegister, TR::RealRegister::EvenOddPair);
         dependencies->addPostCondition(firstRegister->getHighOrder(), TR::RealRegister::LegalEvenOfPair);
         dependencies->addPostCondition(firstRegister->getLowOrder(), TR::RealRegister::LegalOddOfPair);

         if(secondRegister == firstRegister)
            {
            TR_ASSERT( false, "lsub with identical children - fix Simplifier");
            }

         if (secondRegister != firstRegister)
            {
            dependencies->addPostCondition(secondRegister, TR::RealRegister::EvenOddPair);
            dependencies->addPostCondition(secondRegister->getHighOrder(), TR::RealRegister::LegalEvenOfPair);
            dependencies->addPostCondition(secondRegister->getLowOrder(), TR::RealRegister::LegalOddOfPair);
            }

         if ((ENABLE_ZARCH_FOR_32 && zArchTrexsupported) || setsOrReadsCC)
            {
            generateRRInstruction(cg(), regToRegOpCode, root, firstRegister->getLowOrder(), secondRegister->getLowOrder());
            generateRRInstruction(cg(), TR::InstOpCode::SLBR, root, firstRegister->getHighOrder(), secondRegister->getHighOrder());
            }
         else
            {
            generateRRInstruction(cg(), TR::InstOpCode::SR, root, firstRegister->getHighOrder(), secondRegister->getHighOrder());
            generateRRInstruction(cg(), TR::InstOpCode::SLR, root, firstRegister->getLowOrder(), secondRegister->getLowOrder());
            }

         highDiff = firstRegister->getHighOrder();
         root->setRegister(firstRegister);
         }
      else // assert getBinaryReg1Mem2() == true
         {
         TR_ASSERT(  !getInvalid(),"TR_S390BinaryAnalyser::invalid case\n");

         dependencies = new (cg()->trHeapMemory()) TR::RegisterDependencyConditions(0, 5, cg());
         dependencies->addPostCondition(firstRegister, TR::RealRegister::EvenOddPair);
         dependencies->addPostCondition(firstRegister->getHighOrder(), TR::RealRegister::LegalEvenOfPair);
         dependencies->addPostCondition(firstRegister->getLowOrder(), TR::RealRegister::LegalOddOfPair);

         TR::MemoryReference * highMR = generateS390MemoryReference(secondChild, cg());
         TR::MemoryReference * lowMR = generateS390MemoryReference(*highMR, 4, cg());
         dependencies->addAssignAnyPostCondOnMemRef(highMR);

         if ((ENABLE_ZARCH_FOR_32 && zArchTrexsupported) || setsOrReadsCC)
            {
            generateRXInstruction(cg(), memToRegOpCode, root, firstRegister->getLowOrder(), lowMR);
            generateRXInstruction(cg(), TR::InstOpCode::SLB, root, firstRegister->getHighOrder(), highMR);
            }
         else
            {
            generateRXInstruction(cg(), TR::InstOpCode::S, root, firstRegister->getHighOrder(), highMR);
            generateRXInstruction(cg(), TR::InstOpCode::SL, root, firstRegister->getLowOrder(), lowMR);
            }
         highDiff = firstRegister->getHighOrder();
         root->setRegister(firstRegister);
         highMR->stopUsingMemRefRegister(cg());
         lowMR->stopUsingMemRefRegister(cg());
         }

      if (!((ENABLE_ZARCH_FOR_32 && zArchTrexsupported) || setsOrReadsCC))
         {
         // Check for overflow in LS int. If overflow, we are done.
         generateS390BranchInstruction(cg(), TR::InstOpCode::BRC,TR::InstOpCode::COND_MASK3, root, doneLSub);

         // Increment MS int due to overflow in LS int
         generateRIInstruction(cg(), TR::InstOpCode::AHI, root, highDiff, -1);

         generateS390LabelInstruction(cg(), TR::InstOpCode::LABEL, root, doneLSub, dependencies);
         }
      }

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

   return;
   }
Exemple #13
0
TR::Register *
OMR::CodeGenerator::evaluate(TR::Node * node)
   {
   TR::Register *reg;

   bool trace = self()->comp()->getOptions()->getTraceCGOption(TR_TraceCGEvaluation);
   TR::ILOpCodes opcode = node->getOpCodeValue();

   TR_ASSERT(!self()->comp()->getOption(TR_EnableParanoidRefCountChecks) || node->getOpCode().isTreeTop() || node->getReferenceCount() > 0,
      "OMR::CodeGenerator::evaluate invoked for nontreetop node [%s] with count == 0", node->getName(self()->comp()->getDebug()));

   if (opcode != TR::BBStart && node->getRegister())
      {
      reg = node->getRegister();
      if (trace)
         {
         self()->getDebug()->printNodeEvaluation(node, ":  ", reg);
         }
      }
   else
      {
      if (trace)
         {
         self()->getDebug()->printNodeEvaluation(node);
         _indentation += 2;
         }

      // Evaluation of a TR IL tree can be performed by many functions:
      //
      // 1) evaluate(...)
      // 2) populateMemoryReference(...)
      // 3) populateAddTree(...)
      // ...
      //
      // However all of these functions can be categorized into two classes:
      //
      // A) functions which completely evaluate their subtree.
      // B) functions which partially evaluate their subtree.
      //
      // Because functions of class A and class B can be used interchangably to
      // perform a recursive decent of a TR IL tree, and because A or B functions
      // can perform a destructive evaluation of their subtree, a bug can occur where
      // the results of a partial evalutation are destructively overwritten before
      // being completely evalutated.
      //
      // Ex: the motivating case is the following evaluation pattern:
      //
      // node_A evaluate
      //    node_B populateMemoryReference
      //    node_C evaluate
      //
      // where
      //
      // a) there is a common node between the subtrees of node_B and node_C.
      // b) calling populateMemoryReference on node_B reduces the reference count of one
      //    of the base or index nodes to 1, creating the "opportunity" for a destructive
      //    evaluation.
      //
      // The following chain of events occurs:
      //
      // 1) evaluate is called on node_A. This evaluator can produce instructions of RX form,
      //    and chooses to do so for this node.
      //
      // 2) populateMemoryReference is called on node_B, and evaluates the subtree, returning
      //    a TR_MemoryReference to node_A's evaluator. This memory reference has not been
      //    dereferenced yet, and the base (and optionally index) nodes may have registers
      //    assigned to them.
      //
      // 3) evaluate is called on node_C, which chooses to destructively evaluate the commoned
      //    base node. The memory reference's base register now contains a garbage value.
      //
      // 4) control passes to node_A's evaluator, which emits an RX instruction using node_B's
      //    memory reference and node_C's register.
      //
      // In the past, the fix for this was to switch the order of evaluation: call evaluate
      // on node_C and then call populateMemoryReference on node_B. This fixes this scenario, but
      // the capability of another tree and evaluation pattern to create this bug still exists.
      //
      // As well, more insidious trees exist:
      //
      // ificmpeq
      //    iiload
      //       i2l
      //          x
      //    iiload
      //       ishl
      //          ==> i2l
      //          4
      //
      // The evaluation pattern here could be:
      //
      // evaluate
      //    populateMemoryReference
      //       evaluate
      //    populateMemoryReference
      //       evaluate
      //
      // If the commoned node's reference count is 2 coming into ificmpeq's evaluator, then
      // the second sub-evaluate call could be destructive to the first populateMemoryReference.
      //
      // Even worse, if either subtree could be destructive, then there would be no correct order to
      // perform the function calls:
      //
      // ificmpeq
      //    iiload
      //       ishl
      //          ==> x
      //          7
      //    iiload
      //       ishl
      //          ==> x
      //          4
      //
      // Generally, two conditions must be true for this bug to be possible:
      //
      // 1) the following two classes of recursive decent functions must exist:
      //    A) functions which completely evaluate their subtree.
      //    B) functions which partially evaluate their subtree.
      //
      // 2) destructive evaluation by either class of function must be possible.
      //
      // This code implements changes to eliminate the second condition for this bug by performing
      // the following check and fixup:
      //
      // If in a function which partially evaluates its subtree, note all non-restricted nodes that
      // have a reference count > 1. If any of those node's reference counts reach 1, then artificially
      // inflate those reference counts by 1 for the lifetime of the parent evaluation.
      //
      int32_t topOfNodeStackBeforeEvaluation = _stackOfArtificiallyInflatedNodes.topIndex();

      // Memory references are not like registers, and should not be allowed to escape their evaluator.
      // Explicitly note memory references that are not loaded into registers and automatically call
      // stopUsingMemRefRegister on all memory references that have "escaped".
      //
      // Only the s390 memory references are tracked in this way.
      //
      int32_t topOfMemRefStackBeforeEvaluation = _stackOfMemoryReferencesCreatedDuringEvaluation.topIndex();

      reg = _nodeToInstrEvaluators[opcode](node, self());

      if (self()->comp()->getOptions()->getTraceCGOption(TR_TraceCGEvaluation))
         {
         self()->getDebug()->printNodeEvaluation(node, "<- ", reg, false);
         _indentation -= 2;
         }
      if (self()->comp()->getOption(TR_TraceRegisterPressureDetails))
         {
         traceMsg(self()->comp(), "  evaluated %s", self()->getDebug()->getName(node));
         self()->getDebug()->dumpLiveRegisters();
         traceMsg(self()->comp(), "\n");
         }

      // Pop off and decrement tracked nodes
      //
      while (_stackOfArtificiallyInflatedNodes.topIndex() > topOfNodeStackBeforeEvaluation)
         {
         TR::Node * artificiallyInflatedNode = _stackOfArtificiallyInflatedNodes.pop();

         if (artificiallyInflatedNode->getReferenceCount() == 1)
            {
            // When inflating reference counts, two cases exist:
            //
            // 1) N's ref count reaches 1 in a populate* call, which is then inc'ed to 2.
            //
            // 1a) N is never evaluated, so the ref count never goes down to 1. (node was not commoned in another subtree)
            //
            //     - no tree difference should be seen in this case.
            //
            // 1b) N is evaluated, so the ref count then goes down to 1. (node was commoned in another subtree)
            //
            //     - register shuffling _could_ be seen in this case.
            //     - but a bug might have been avoided: partial and complete evaluation of a commoned node occurred.
            //
            if (self()->comp()->getOption(TR_TraceCG))
               {
               self()->comp()->getDebug()->trace(" _stackOfArtificiallyInflatedNodes.pop(): node %p part of commoned case, might have avoided a bug!\n", artificiallyInflatedNode);
               }
            }

         self()->decReferenceCount(artificiallyInflatedNode);

#ifdef J9_PROJECT_SPECIFIC
#if defined(TR_TARGET_S390)
         if (artificiallyInflatedNode->getOpaquePseudoRegister())
            {
            TR_OpaquePseudoRegister *reg = artificiallyInflatedNode->getOpaquePseudoRegister();
            TR_StorageReference *ref = reg->getStorageReference();
            self()->processUnusedStorageRef(ref);
            }
#endif
#endif

         if (self()->comp()->getOption(TR_TraceCG))
            {
            self()->comp()->getDebug()->trace(" _stackOfArtificiallyInflatedNodes.pop() %p, decReferenceCount(...) called. reg=%s\n", artificiallyInflatedNode,
                                      artificiallyInflatedNode->getRegister()?artificiallyInflatedNode->getRegister()->getRegisterName(self()->comp()):"null");
            }
         }

#if defined(TR_TARGET_S390)
      self()->StopUsingEscapedMemRefsRegisters(topOfMemRefStackBeforeEvaluation);
#endif

      bool checkRefCount = (node->getReferenceCount() <= 1 ||
                              (reg && reg == node->getRegister()));
      // for anchor mode, if node is an indirect store, it can have
      // ref count <= 2
      // but for compressedRefs, the indirect store must be an address
      if (self()->comp()->useAnchors())
         {
         if (((node->getOpCode().isStoreIndirect() &&
               (self()->comp()->useCompressedPointers() && (node->getSymbolReference()->getSymbol()->getDataType() == TR::Address))) ||
                opcode == TR::wrtbari) &&
               node->getReferenceCount() <= 2 &&
               !checkRefCount)
            checkRefCount = true;
         }

      TR_ASSERT(checkRefCount,
                  "evaluate: the node's register wasn't set (node [%s])", node->getName(self()->comp()->getDebug()));
      }

   return reg;
   }
Exemple #14
0
// Build arguments for system linkage dispatch.
//
int32_t TR::AMD64SystemLinkage::buildArgs(
      TR::Node *callNode,
      TR::RegisterDependencyConditions *deps)
   {
   TR::SymbolReference *methodSymRef = callNode->getSymbolReference();
   TR::MethodSymbol *methodSymbol = methodSymRef->getSymbol()->castToMethodSymbol();
   TR::RealRegister::RegNum noReg = TR::RealRegister::NoReg;
   TR::RealRegister *espReal = machine()->getX86RealRegister(TR::RealRegister::esp);
   int32_t firstNodeArgument = callNode->getFirstArgumentIndex();
   int32_t lastNodeArgument = callNode->getNumChildren() - 1;
   int32_t offset = 0;
   int32_t sizeOfOutGoingArgs= 0;
   uint16_t numIntArgs = 0,
            numFloatArgs = 0;
   int32_t first, last, direction;
   int32_t numCopiedRegs = 0;
   TR::Register *copiedRegs[TR::X86LinkageProperties::MaxArgumentRegisters];

   if (getProperties().passArgsRightToLeft())
      {
      first = lastNodeArgument;
      last  = firstNodeArgument - 1;
      direction = -1;
      }
   else
      {
      first = firstNodeArgument;
      last  = lastNodeArgument + 1;
      direction = 1;
      }

   // If the dispatch is indirect we must add the VFT register to the preconditions
   // so that it gets register assigned with the other preconditions to the call.
   //
   if (callNode->getOpCode().isIndirect())
      {
      TR::Node *vftChild = callNode->getFirstChild();
      TR_ASSERT(vftChild->getRegister(), "expecting VFT child to be evaluated");
      TR::RealRegister::RegNum scratchRegIndex = getProperties().getIntegerScratchRegister(1);
      deps->addPreCondition(vftChild->getRegister(), scratchRegIndex, cg());
      }

   int32_t i;
   for (i = first; i != last; i += direction)
      {
      TR::parmLayoutResult layoutResult;
      TR::RealRegister::RegNum rregIndex = noReg;
      TR::Node *child = callNode->getChild(i);

      layoutParm(child, sizeOfOutGoingArgs, numIntArgs, numFloatArgs, layoutResult);

      if (layoutResult.abstract & TR::parmLayoutResult::IN_LINKAGE_REG_PAIR)
         {
         // TODO: AMD64 SysV ABI might put a struct into a pair of linkage registerr
         TR_ASSERT(false, "haven't support linkage_reg_pair yet.\n");
         }
      else if (layoutResult.abstract & TR::parmLayoutResult::IN_LINKAGE_REG)
         {
         TR_RegisterKinds regKind = layoutResult.regs[0].regKind;
         uint32_t regIndex = layoutResult.regs[0].regIndex;
         TR_ASSERT(regKind == TR_GPR || regKind == TR_FPR, "linkage registers includes TR_GPR and TR_FPR\n");
         rregIndex = (regKind == TR_FPR) ? getProperties().getFloatArgumentRegister(regIndex): getProperties().getIntegerArgumentRegister(regIndex);
         }
      else
         {
         offset = layoutResult.offset;
         }

      TR::Register *vreg;
      vreg = cg()->evaluate(child);

      bool needsStackOffsetUpdate = false;
      if (rregIndex != noReg)
         {
         // For NULL JNI reference parameters, it is possible that the NULL value will be evaluated into
         // a different register than the child.  In that case it is not necessary to copy the temporary scratch
         // register across the call.
         //
         if ((child->getReferenceCount() > 1) &&
             (vreg == child->getRegister()))
            {
            TR::Register *argReg = cg()->allocateRegister();
            if (vreg->containsCollectedReference())
               argReg->setContainsCollectedReference();
            generateRegRegInstruction(TR::Linkage::movOpcodes(RegReg, movType(child->getDataType())), child, argReg, vreg, cg());
            vreg = argReg;
            copiedRegs[numCopiedRegs++] = vreg;
            }

         deps->addPreCondition(vreg, rregIndex, cg());
         }
      else
         {
         // Ideally, we would like to push rather than move
         generateMemRegInstruction(TR::Linkage::movOpcodes(MemReg, fullRegisterMovType(vreg)),
                                   child,
                                   generateX86MemoryReference(espReal, offset, cg()),
                                   vreg,
                                   cg());
         }

      cg()->decReferenceCount(child);
      }

   // Now that we're finished making the preconditions, all the interferences
   // are established and we can kill these regs.
   //
   for (i = 0; i < numCopiedRegs; i++)
      cg()->stopUsingRegister(copiedRegs[i]);

   deps->stopAddingPreConditions();

   return sizeOfOutGoingArgs;
   }
Exemple #15
0
TR::Register *
TR::AMD64SystemLinkage::buildVolatileAndReturnDependencies(
      TR::Node *callNode,
      TR::RegisterDependencyConditions *deps)
   {

   if (callNode->getOpCode().isIndirect())
      {
      TR::Node *vftChild = callNode->getFirstChild();
      if (vftChild->getRegister() && (vftChild->getReferenceCount() > 1))
         {
         }
      else
         {
         // VFT child dies here; decrement it early so it doesn't interfere with dummy regs.
         cg()->recursivelyDecReferenceCount(vftChild);
         }
      }

   TR_ASSERT(deps != NULL, "expected register dependencies");

   // Figure out which is the return register.
   //
   TR::RealRegister::RegNum returnRegIndex;
   TR_RegisterKinds returnKind;

   switch (callNode->getDataType())
      {
      case TR::NoType:
         returnRegIndex = TR::RealRegister::NoReg;
         returnKind = TR_NoRegister;
         break;

      case TR::Int8:
      case TR::Int16:
      case TR::Int32:
      case TR::Int64:
      case TR::Address:
         returnRegIndex = getProperties().getIntegerReturnRegister();
         returnKind = TR_GPR;
         break;

      case TR::Float:
      case TR::Double:
         returnRegIndex = getProperties().getFloatReturnRegister();
         returnKind = TR_FPR;
         break;

      case TR::Aggregate:
      default:
         TR_ASSERT(false, "Unrecognized call node data type: #%d", (int)callNode->getDataType());
         break;
      }

   // Kill all non-preserved int and float regs besides the return register.
   //
   int32_t i;
   TR::RealRegister::RegNum scratchIndex = getProperties().getIntegerScratchRegister(1);
   for (i=0; i<getProperties().getNumVolatileRegisters(); i++)
      {
      TR::RealRegister::RegNum regIndex = getProperties()._volatileRegisters[i];

      if (regIndex != returnRegIndex)
         {
         TR_RegisterKinds rk = (i < getProperties()._numberOfVolatileGPRegisters) ? TR_GPR : TR_FPR;
         TR::Register *dummy = cg()->allocateRegister(rk);
         deps->addPostCondition(dummy, regIndex, cg());

         // Note that we don't setPlaceholderReg here.  If this volatile reg is also volatile
         // in the caller's linkage, then that flag doesn't matter much anyway.  If it's preserved
         // in the caller's linkage, then we don't want to set that flag because we want this
         // use of the register to count as a "real" use, thereby motivating the prologue to
         // preserve the register.

         // A scratch register is necessary to call the native without a trampoline.
         //
         if (callNode->getOpCode().isIndirect() || (regIndex != scratchIndex))
            cg()->stopUsingRegister(dummy);
         }
      }

#if defined (PYTHON) && 0
   // Evict the preserved registers across the call
   //
   for (i=0; i<getProperties().getNumberOfPreservedGPRegisters(); i++)
      {
      TR::RealRegister::RegNum regIndex = getProperties()._preservedRegisters[i];

      TR::Register *dummy = cg()->allocateRegister(TR_GPR);
      deps->addPostCondition(dummy, regIndex, cg());

      // Note that we don't setPlaceholderReg here.  If this volatile reg is also volatile
      // in the caller's linkage, then that flag doesn't matter much anyway.  If it's preserved
      // in the caller's linkage, then we don't want to set that flag because we want this
      // use of the register to count as a "real" use, thereby motivating the prologue to
      // preserve the register.

      // A scratch register is necessary to call the native without a trampoline.
      //
      if (callNode->getOpCode().isIndirect() || (regIndex != scratchIndex))
         cg()->stopUsingRegister(dummy);
      }
#endif

   if (callNode->getOpCode().isIndirect())
      {
      TR::Node *vftChild = callNode->getFirstChild();
      if (vftChild->getRegister() && (vftChild->getReferenceCount() > 1))
         {
         // VFT child survives the call, so we must include it in the postconditions.
         deps->addPostCondition(vftChild->getRegister(), TR::RealRegister::NoReg, cg());
         cg()->recursivelyDecReferenceCount(vftChild);
         }
      }

   // Now that everything is dead, we can allocate the return register without
   // interference
   //
   TR::Register *returnRegister;
   if (returnRegIndex)
      {
      TR_ASSERT(returnKind != TR_NoRegister, "assertion failure");

      if (callNode->getDataType() == TR::Address)
         returnRegister = cg()->allocateCollectedReferenceRegister();
      else
         {
         returnRegister = cg()->allocateRegister(returnKind);
         if (callNode->getDataType() == TR::Float)
            returnRegister->setIsSinglePrecision();
         }

      deps->addPostCondition(returnRegister, returnRegIndex, cg());
      }
   else
      returnRegister = NULL;


 // The reg dependency is left open intentionally, and need to be closed by
 // the caller. The reason is because, child class might call this method, while
 // adding more register dependecies;  if we close the reg dependency here,
 // the child class won't be able to add more register dependencies.

   return returnRegister;
   }
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;
   }