TR::RegisterDependencyConditions *OMR::ARM::RegisterDependencyConditions::cloneAndFix( TR::CodeGenerator * cg, TR::RegisterDependencyConditions *added) { TR::RegisterDependencyConditions *result; TR_ARMRegisterDependency *singlePair; int32_t idx, preNum, postNum, addPre=0, addPost=0; TR::Register *postReg, *tempReg; TR::RealRegister::RegNum rnum; if (added != NULL) { addPre = added->getAddCursorForPre(); addPost = added->getAddCursorForPost(); } preNum = this->getAddCursorForPre(); postNum = this->getAddCursorForPost(); result = new (cg->trHeapMemory()) TR::RegisterDependencyConditions(preNum + addPre, postNum + addPost, cg->trMemory()); for (idx=0; idx<postNum; idx++) { singlePair = this->getPostConditions()->getRegisterDependency(idx); rnum = singlePair->getRealRegister(); tempReg = singlePair->getRegister(); result->addPostCondition(tempReg, rnum, singlePair->getFlags()); if (rnum == TR::RealRegister::gr0) { postReg = tempReg; } } for (idx=0; idx<preNum; idx++) { singlePair = this->getPreConditions()->getRegisterDependency(idx); rnum = singlePair->getRealRegister(); tempReg = singlePair->getRegister(); if (rnum == TR::RealRegister::gr0) tempReg = postReg; result->addPreCondition(tempReg, rnum, singlePair->getFlags()); } for (idx=0; idx<addPost; idx++) { singlePair = added->getPostConditions()->getRegisterDependency(idx); result->addPostCondition(singlePair->getRegister(), singlePair->getRealRegister(), singlePair->getFlags()); } for (idx=0; idx<addPre; idx++) { singlePair = added->getPreConditions()->getRegisterDependency(idx); result->addPreCondition(singlePair->getRegister(), singlePair->getRealRegister(), singlePair->getFlags()); } return result; }
TR::Register *OMR::X86::AMD64::TreeEvaluator::dbits2lEvaluator(TR::Node *node, TR::CodeGenerator *cg) { // TODO:AMD64: Peepholing TR::Node *child = node->getFirstChild(); TR::Register *sreg = cg->evaluate(child); TR::Register *treg = cg->allocateRegister(TR_GPR); generateRegRegInstruction(MOVQReg8Reg, node, treg, sreg, cg); if (node->normalizeNanValues()) { static char *disableFastNormalizeNaNs = feGetEnv("TR_disableFastNormalizeNaNs"); if (disableFastNormalizeNaNs) { // This one is not clever, but it is simple, and it's based directly // on the IA32 version which is known to work, so is safer. // TR::RegisterDependencyConditions *deps = generateRegisterDependencyConditions((uint8_t)0, (uint8_t)1, cg); deps->addPostCondition(treg, TR::RealRegister::NoReg, cg); TR::IA32ConstantDataSnippet *nan1Snippet = cg->findOrCreate8ByteConstant(node, DOUBLE_NAN_1_LOW); TR::IA32ConstantDataSnippet *nan2Snippet = cg->findOrCreate8ByteConstant(node, DOUBLE_NAN_2_LOW); TR::MemoryReference *nan1MR = generateX86MemoryReference(nan1Snippet, cg); TR::MemoryReference *nan2MR = generateX86MemoryReference(nan2Snippet, cg); TR::LabelSymbol *startLabel = TR::LabelSymbol::create(cg->trHeapMemory(),cg); TR::LabelSymbol *normalizeLabel = TR::LabelSymbol::create(cg->trHeapMemory(),cg); TR::LabelSymbol *endLabel = TR::LabelSymbol::create(cg->trHeapMemory(),cg); startLabel->setStartInternalControlFlow(); endLabel ->setEndInternalControlFlow(); generateLabelInstruction( LABEL, node, startLabel, cg); generateRegMemInstruction( CMP8RegMem, node, treg, nan1MR, cg); generateLabelInstruction( JGE4, node, normalizeLabel, cg); generateRegMemInstruction( CMP8RegMem, node, treg, nan2MR, cg); generateLabelInstruction( JB4, node, endLabel, cg); generateLabelInstruction( LABEL, node, normalizeLabel, cg); generateRegImm64Instruction( MOV8RegImm64, node, treg, DOUBLE_NAN, cg); generateLabelInstruction( LABEL, node, endLabel, deps, cg); } else { // A bunch of bookkeeping // uint64_t nanDetector = DOUBLE_NAN_2_LOW; TR::RegisterDependencyConditions *internalControlFlowDeps = generateRegisterDependencyConditions((uint8_t)0, (uint8_t)1, cg); internalControlFlowDeps->addPostCondition(treg, TR::RealRegister::NoReg, cg); TR::RegisterDependencyConditions *helperDeps = generateRegisterDependencyConditions((uint8_t)1, (uint8_t)1, cg); helperDeps->addPreCondition( treg, TR::RealRegister::eax, cg); helperDeps->addPostCondition(treg, TR::RealRegister::eax, cg); TR::IA32ConstantDataSnippet *nanDetectorSnippet = cg->findOrCreate8ByteConstant(node, nanDetector); TR::MemoryReference *nanDetectorMR = generateX86MemoryReference(nanDetectorSnippet, cg); TR::LabelSymbol *startLabel = TR::LabelSymbol::create(cg->trHeapMemory(),cg); TR::LabelSymbol *slowPathLabel = TR::LabelSymbol::create(cg->trHeapMemory(),cg); TR::LabelSymbol *normalizeLabel = TR::LabelSymbol::create(cg->trHeapMemory(),cg); TR::LabelSymbol *endLabel = TR::LabelSymbol::create(cg->trHeapMemory(),cg); startLabel->setStartInternalControlFlow(); endLabel ->setEndInternalControlFlow(); // Fast path: if subtracting nanDetector leaves CF=0 or OF=1, then it // must be a NaN. // generateLabelInstruction( LABEL, node, startLabel, cg); generateRegMemInstruction( CMP8RegMem, node, treg, nanDetectorMR, cg); generateLabelInstruction( JAE4, node, slowPathLabel, cg); generateLabelInstruction( JO4, node, slowPathLabel, cg); // Slow path // TR_OutlinedInstructions *slowPath = new (cg->trHeapMemory()) TR_OutlinedInstructions(slowPathLabel, cg); cg->getOutlinedInstructionsList().push_front(slowPath); slowPath->swapInstructionListsWithCompilation(); generateLabelInstruction(NULL, LABEL, slowPathLabel, cg)->setNode(node); generateRegImm64Instruction(MOV8RegImm64, node, treg, DOUBLE_NAN, cg); generateLabelInstruction( JMP4, node, endLabel, cg); slowPath->swapInstructionListsWithCompilation(); // Merge point // generateLabelInstruction(LABEL, node, endLabel, internalControlFlowDeps, cg); } } node->setRegister(treg); cg->decReferenceCount(child); return treg; }
TR::RegisterDependencyConditions * OMR::Power::RegisterDependencyConditions::clone( TR::CodeGenerator *cg, TR::RegisterDependencyConditions *added) { TR::RegisterDependencyConditions *result; TR::RegisterDependency *singlePair; int32_t idx, preNum, postNum, addPre=0, addPost=0; #if defined(DEBUG) int32_t preGPR=0, postGPR=0; #endif if (added != NULL) { addPre = added->getAddCursorForPre(); addPost = added->getAddCursorForPost(); } preNum = this->getAddCursorForPre(); postNum = this->getAddCursorForPost(); result = new (cg->trHeapMemory()) TR::RegisterDependencyConditions(getNumPreConditions()+addPre, getNumPostConditions()+addPost, cg->trMemory()); for (idx=0; idx<postNum; idx++) { singlePair = this->getPostConditions()->getRegisterDependency(idx); //eliminate duplicate virtual->NoReg dependencies in 'this' conditions if (!((TR::RealRegister::NoReg == singlePair->getRealRegister()) && (added->postConditionContainsVirtual(singlePair->getRegister())))) result->addPostCondition(singlePair->getRegister(), singlePair->getRealRegister(), singlePair->getFlags()); #if defined(DEBUG) if (singlePair->getRegister()->getKind() == TR_GPR) postGPR++; #endif } for (idx=0; idx<preNum; idx++) { singlePair = this->getPreConditions()->getRegisterDependency(idx); //eliminate duplicate virtual->NoReg dependencies in 'this' conditions if (!((TR::RealRegister::NoReg == singlePair->getRealRegister()) && (added->preConditionContainsVirtual(singlePair->getRegister())))) result->addPreCondition(singlePair->getRegister(), singlePair->getRealRegister(), singlePair->getFlags()); #if defined(DEBUG) if (singlePair->getRegister()->getKind() == TR_GPR) preGPR++; #endif } for (idx=0; idx<addPost; idx++) { singlePair = added->getPostConditions()->getRegisterDependency(idx); result->addPostCondition(singlePair->getRegister(), singlePair->getRealRegister(), singlePair->getFlags()); #if defined(DEBUG) if (singlePair->getRegister()->getKind() == TR_GPR) postGPR++; #endif } for (idx=0; idx<addPre; idx++) { singlePair = added->getPreConditions()->getRegisterDependency(idx); result->addPreCondition(singlePair->getRegister(), singlePair->getRealRegister(), singlePair->getFlags()); #if defined(DEBUG) if (singlePair->getRegister()->getKind() == TR_GPR) preGPR++; #endif } #if defined(DEBUG) int32_t max_gpr = cg->getProperties().getNumAllocatableIntegerRegisters(); TR_ASSERT(preGPR<=max_gpr && postGPR<=max_gpr, "Over the limit of available global regsiters."); #endif return result; }
TR::RegisterDependencyConditions* TR_PPCScratchRegisterDependencyConditions::createDependencyConditions(TR::CodeGenerator *cg, TR_PPCScratchRegisterDependencyConditions *pre, TR_PPCScratchRegisterDependencyConditions *post) { int32_t preCount = pre ? pre->getNumberOfDependencies() : 0; int32_t postCount = post ? post->getNumberOfDependencies() : 0; TR_LiveRegisters *lrVector = cg->getLiveRegisters(TR_VSX_VECTOR); bool liveVSXVectorReg = (!lrVector || (lrVector->getNumberOfLiveRegisters() > 0)); TR_LiveRegisters *lrScalar = cg->getLiveRegisters(TR_VSX_SCALAR); bool liveVSXScalarReg = (!lrScalar || (lrScalar->getNumberOfLiveRegisters() > 0)); if (liveVSXVectorReg) { preCount += 64; postCount += 64; } else if (liveVSXScalarReg) { preCount += 32; postCount += 32; } TR::RegisterDependencyConditions *dependencies = new (cg->trHeapMemory()) TR::RegisterDependencyConditions(preCount, postCount, cg->trMemory()); for (int i = 0; i < (pre ? pre->_numGPRDeps : 0); ++i) { dependencies->addPreCondition(pre->_gprDeps[i].getRegister(), pre->_gprDeps[i].getRealRegister(), pre->_gprDeps[i].getFlags()); if (pre->_excludeGPR0 & (1 << i)) dependencies->getPreConditions()->getRegisterDependency(i)->setExcludeGPR0(); } for (int i = 0; i < (post ? post->_numGPRDeps : 0); ++i) { dependencies->addPostCondition(post->_gprDeps[i].getRegister(), post->_gprDeps[i].getRealRegister(), post->_gprDeps[i].getFlags()); if (post->_excludeGPR0 & (1 << i)) dependencies->getPostConditions()->getRegisterDependency(i)->setExcludeGPR0(); } for (int i = 0; i < (pre ? pre->_numCCRDeps : 0); ++i) { dependencies->addPreCondition(pre->_ccrDeps[i].getRegister(), pre->_ccrDeps[i].getRealRegister(), pre->_ccrDeps[i].getFlags()); } for (int i = 0; i < (post ? post->_numCCRDeps : 0); ++i) { dependencies->addPostCondition(post->_ccrDeps[i].getRegister(), post->_ccrDeps[i].getRealRegister(), post->_ccrDeps[i].getFlags()); } const TR_PPCLinkageProperties& properties = cg->getLinkage()->getProperties(); if (liveVSXVectorReg) { for (int32_t i=TR::RealRegister::FirstVSR; i<=TR::RealRegister::LastVSR; i++) { if (!properties.getPreserved((TR::RealRegister::RegNum)i)) { TR::Register *vreg = cg->allocateRegister(TR_FPR); vreg->setPlaceholderReg(); dependencies->addPreCondition(vreg, (TR::RealRegister::RegNum)i); dependencies->addPostCondition(vreg, (TR::RealRegister::RegNum)i); } } } else { if (liveVSXScalarReg) { for (int32_t i=TR::RealRegister::vsr32; i<=TR::RealRegister::LastVSR; i++) { if (!properties.getPreserved((TR::RealRegister::RegNum)i)) { TR::Register *vreg = cg->allocateRegister(TR_FPR); vreg->setPlaceholderReg(); dependencies->addPreCondition(vreg, (TR::RealRegister::RegNum)i); dependencies->addPostCondition(vreg, (TR::RealRegister::RegNum)i); } } } } return dependencies; }
TR::Register *TR_X86FPCompareAnalyser::fpCompareAnalyser(TR::Node *root, TR_X86OpCodes cmpRegRegOpCode, TR_X86OpCodes cmpRegMemOpCode, TR_X86OpCodes cmpiRegRegOpCode, bool useFCOMIInstructions) { TR::Node *firstChild, *secondChild; TR::ILOpCodes cmpOp = root->getOpCodeValue(); bool reverseMemOp = false; bool reverseCmpOp = false; TR::Compilation* comp = _cg->comp(); TR_X86OpCodes cmpInstr = useFCOMIInstructions ? cmpiRegRegOpCode : cmpRegRegOpCode; // Some operators must have their operands swapped to improve the generated // code needed to evaluate the result of the comparison. // bool mustSwapOperands = (cmpOp == TR::iffcmple || cmpOp == TR::ifdcmple || cmpOp == TR::iffcmpgtu || cmpOp == TR::ifdcmpgtu || cmpOp == TR::fcmple || cmpOp == TR::dcmple || cmpOp == TR::fcmpgtu || cmpOp == TR::dcmpgtu || (useFCOMIInstructions && (cmpOp == TR::iffcmplt || cmpOp == TR::ifdcmplt || cmpOp == TR::iffcmpgeu || cmpOp == TR::ifdcmpgeu || cmpOp == TR::fcmplt || cmpOp == TR::dcmplt || cmpOp == TR::fcmpgeu || cmpOp == TR::dcmpgeu))) ? true : false; // Some operators should not have their operands swapped to improve the generated // code needed to evaluate the result of the comparison. // bool preventOperandSwapping = (cmpOp == TR::iffcmpltu || cmpOp == TR::ifdcmpltu || cmpOp == TR::iffcmpge || cmpOp == TR::ifdcmpge || cmpOp == TR::fcmpltu || cmpOp == TR::dcmpltu || cmpOp == TR::fcmpge || cmpOp == TR::dcmpge || (useFCOMIInstructions && (cmpOp == TR::iffcmpgt || cmpOp == TR::ifdcmpgt || cmpOp == TR::iffcmpleu || cmpOp == TR::ifdcmpleu || cmpOp == TR::fcmpgt || cmpOp == TR::dcmpgt || cmpOp == TR::fcmpleu || cmpOp == TR::dcmpleu))) ? true : false; // For correctness, don't swap operands of these operators. // if (cmpOp == TR::fcmpg || cmpOp == TR::fcmpl || cmpOp == TR::dcmpg || cmpOp == TR::dcmpl) { preventOperandSwapping = true; } // Initial operand evaluation ordering. // if (preventOperandSwapping || (!mustSwapOperands && _cg->whichChildToEvaluate(root) == 0)) { firstChild = root->getFirstChild(); secondChild = root->getSecondChild(); setReversedOperands(false); } else { firstChild = root->getSecondChild(); secondChild = root->getFirstChild(); setReversedOperands(true); } TR::Register *firstRegister = firstChild->getRegister(); TR::Register *secondRegister = secondChild->getRegister(); setInputs(firstChild, firstRegister, secondChild, secondRegister, useFCOMIInstructions, // If either 'preventOperandSwapping' or 'mustSwapOperands' is set then the // initial operand ordering set above must be maintained. // preventOperandSwapping || mustSwapOperands); // Make sure any required operand ordering is respected. // if ((getCmpReg2Reg1() || getCmpReg2Mem1()) && (mustSwapOperands || preventOperandSwapping)) { reverseCmpOp = getCmpReg2Reg1() ? true : false; reverseMemOp = getCmpReg2Mem1() ? true : false; } // If we are not comparing with a memory operand, one of them evaluates // to a zero, and the zero is not already on the stack, then we can use // FTST to save a register. // // (With a memory operand, either the constant zero needs to be loaded // to use FCOM, or the memory operand needs to be loaded to use FTST, // so there is no gain in using FTST.) // // If the constant zero is in the target register, using FTST means the // comparison will be reversed. We cannot do this if the initial ordering // of the operands must be maintained. // // Finally, if FTST is used and this is the last use of the target, the // target register may need to be explicitly popped. // TR::Register *targetRegisterForFTST = NULL; TR::Node *targetChildForFTST = NULL; if (getEvalChild1() && isUnevaluatedZero(firstChild)) // do we need getEvalChild1() here? { if ( ((getCmpReg1Reg2() || reverseCmpOp) && !(preventOperandSwapping || mustSwapOperands)) || (getCmpReg2Reg1() && !reverseCmpOp)) { if (getEvalChild2()) { secondRegister = _cg->evaluate(secondChild); } targetRegisterForFTST = secondRegister; targetChildForFTST = secondChild; notReversedOperands(); } } else if (getEvalChild2() && isUnevaluatedZero(secondChild)) // do we need getEvalChild2() here? { if ( (getCmpReg1Reg2() || reverseCmpOp) || (getCmpReg2Reg1() && !reverseCmpOp && !(preventOperandSwapping || mustSwapOperands)) ) { if (getEvalChild1()) { firstRegister = _cg->evaluate(firstChild); } targetRegisterForFTST = firstRegister; targetChildForFTST = firstChild; } } if (!targetRegisterForFTST) { // If we have a choice, evaluate the target operand last. By doing so, we // help out the register assigner because the target must be TOS. This // avoids an unneccessary FXCH for the target. // if (getEvalChild1() && getEvalChild2()) { if (getCmpReg1Reg2() || getCmpReg1Mem2()) { secondRegister = _cg->evaluate(secondChild); firstRegister = _cg->evaluate(firstChild); } else { firstRegister = _cg->evaluate(firstChild); secondRegister = _cg->evaluate(secondChild); } } else { if (getEvalChild1()) { firstRegister = _cg->evaluate(firstChild); } if (getEvalChild2()) { secondRegister = _cg->evaluate(secondChild); } } } // Adjust the FP precision of feeding operands. // if (firstRegister && (firstRegister->needsPrecisionAdjustment() || comp->getOption(TR_StrictFPCompares) || (firstRegister->mayNeedPrecisionAdjustment() && secondChild->getOpCode().isLoadConst()) || (firstRegister->mayNeedPrecisionAdjustment() && !secondRegister))) { TR::TreeEvaluator::insertPrecisionAdjustment(firstRegister, root, _cg); } if (secondRegister && (secondRegister->needsPrecisionAdjustment() || comp->getOption(TR_StrictFPCompares) || (secondRegister->mayNeedPrecisionAdjustment() && firstChild->getOpCode().isLoadConst()) || (secondRegister->mayNeedPrecisionAdjustment() && !firstRegister))) { TR::TreeEvaluator::insertPrecisionAdjustment(secondRegister, root, _cg); } // Generate the compare instruction. // if (targetRegisterForFTST) { generateFPRegInstruction(FTSTReg, root, targetRegisterForFTST, _cg); } else if (!useFCOMIInstructions && (getCmpReg1Mem2() || reverseMemOp)) { TR::MemoryReference *tempMR = generateX86MemoryReference(secondChild, _cg); generateFPRegMemInstruction(cmpRegMemOpCode, root, firstRegister, tempMR, _cg); tempMR->decNodeReferenceCounts(_cg); } else if (!useFCOMIInstructions && getCmpReg2Mem1()) { TR::MemoryReference *tempMR = generateX86MemoryReference(firstChild, _cg); generateFPRegMemInstruction(cmpRegMemOpCode, root, secondRegister, tempMR, _cg); notReversedOperands(); tempMR->decNodeReferenceCounts(_cg); } else if (getCmpReg1Reg2() || reverseCmpOp) { generateFPCompareRegRegInstruction(cmpInstr, root, firstRegister, secondRegister, _cg); } else if (getCmpReg2Reg1()) { generateFPCompareRegRegInstruction(cmpInstr, root, secondRegister, firstRegister, _cg); notReversedOperands(); } _cg->decReferenceCount(firstChild); _cg->decReferenceCount(secondChild); // Evaluate the comparison. // if (getReversedOperands()) { cmpOp = TR::ILOpCode(cmpOp).getOpCodeForSwapChildren(); TR::Node::recreate(root, cmpOp); } if (useFCOMIInstructions && !targetRegisterForFTST) { return NULL; } // We must manually move the FP condition flags to the EFLAGS register if we don't // use the FCOMI instructions. // TR::Register *accRegister = _cg->allocateRegister(); TR::RegisterDependencyConditions *dependencies = generateRegisterDependencyConditions((uint8_t)1, 1, _cg); dependencies->addPreCondition(accRegister, TR::RealRegister::eax, _cg); dependencies->addPostCondition(accRegister, TR::RealRegister::eax, _cg); generateRegInstruction(STSWAcc, root, accRegister, dependencies, _cg); // Pop the FTST target register if it is not used any more. // if (targetRegisterForFTST && targetChildForFTST && targetChildForFTST->getReferenceCount() == 0) { generateFPSTiST0RegRegInstruction(FSTRegReg, root, targetRegisterForFTST, targetRegisterForFTST, _cg); } return accRegister; }