Skip to content

Commit 613809b

Browse files
committed
Move setmemoryEvaluator from OMR to Openj9
Signed-off-by: midronij <[email protected]>
1 parent 05e6636 commit 613809b

File tree

2 files changed

+372
-0
lines changed

2 files changed

+372
-0
lines changed

runtime/compiler/p/codegen/J9TreeEvaluator.cpp

Lines changed: 371 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12598,6 +12598,377 @@ TR::Register *J9::Power::TreeEvaluator::directCallEvaluator(TR::Node *node, TR::
1259812598
}
1259912599

1260012600

12601+
TR::Register *J9::Power::TreeEvaluator::setmemoryEvaluator(TR::Node *node, TR::CodeGenerator *cg)
12602+
{
12603+
TR::Compilation *comp = cg->comp();
12604+
TR::Node *dstBaseAddrNode, *dstOffsetNode, *dstAddrNode, *lengthNode, *valueNode;
12605+
12606+
bool arrayCheckNeeded;
12607+
12608+
// IL tree structure depends on whether or not it's been determined that a runtime arrayCHK is needed:
12609+
// if node has four children (i.e.: object base address and offset are separate), need array check
12610+
// if node three children (i.e.: object base address and offset have already been added together), don't need array check
12611+
if (node->getNumChildren() == 4)
12612+
{
12613+
arrayCheckNeeded = true;
12614+
12615+
dstBaseAddrNode = node->getChild(0);
12616+
dstOffsetNode = node->getChild(1);
12617+
dstAddrNode = NULL;
12618+
lengthNode = node->getChild(2);
12619+
valueNode = node->getChild(3);
12620+
}
12621+
else //i.e.: node->getNumChildren() == 3
12622+
{
12623+
arrayCheckNeeded = false;
12624+
12625+
dstBaseAddrNode = NULL;
12626+
dstOffsetNode = NULL;
12627+
dstAddrNode = node->getChild(0);
12628+
lengthNode = node->getChild(1);
12629+
valueNode = node->getChild(2);
12630+
}
12631+
12632+
TR::Register *dstBaseAddrReg, *dstOffsetReg, *dstAddrReg, *lengthReg, *valueReg;
12633+
12634+
// if the offset is a constant value less than 16 bits, then we dont need a separate register for it
12635+
bool useOffsetAsImmVal = dstOffsetNode && dstOffsetNode->getOpCode().isLoadConst() &&
12636+
(dstOffsetNode->getConstValue() >= LOWER_IMMED) && (dstOffsetNode->getConstValue() <= UPPER_IMMED);
12637+
12638+
bool stopUsingCopyRegBase = dstBaseAddrNode ? TR::TreeEvaluator::stopUsingCopyReg(dstBaseAddrNode, dstBaseAddrReg, cg) : false;
12639+
bool stopUsingCopyRegAddr = dstAddrNode ? TR::TreeEvaluator::stopUsingCopyReg(dstAddrNode, dstAddrReg, cg) : false ;
12640+
12641+
bool stopUsingCopyRegOffset, stopUsingCopyRegLen, stopUsingCopyRegVal;
12642+
12643+
//dstOffsetNode (type: long)
12644+
if (dstOffsetNode && !useOffsetAsImmVal) //only want to allocate a register for dstoffset if we're using it for the array check AND it isn't a constant
12645+
{
12646+
if (!cg->canClobberNodesRegister(lengthNode)) //only need to copy dstOffset into another register if the current one isn't clobberable
12647+
{
12648+
if (cg->comp()->target().is32Bit()) //on 32-bit systems, need to grab the lower 32 bits of offset from the register pair
12649+
{
12650+
dstOffsetReg = cg->evaluate(dstOffsetNode);
12651+
TR::Register *offsetCopyReg = cg->allocateRegister();
12652+
generateTrg1Src1Instruction(cg, TR::InstOpCode::mr, dstOffsetNode, offsetCopyReg, dstOffsetReg->getLowOrder());
12653+
12654+
dstOffsetReg = offsetCopyReg;
12655+
stopUsingCopyRegOffset = true;
12656+
}
12657+
else
12658+
{
12659+
stopUsingCopyRegOffset = TR::TreeEvaluator::stopUsingCopyReg(dstOffsetNode, dstOffsetReg, cg);
12660+
}
12661+
}
12662+
else
12663+
{
12664+
dstOffsetReg = cg->evaluate(dstOffsetNode);
12665+
12666+
if (cg->comp()->target().is32Bit()) //on 32-bit systems, need to grab the lower 32 bits of offset from the register pair
12667+
dstOffsetReg = dstOffsetReg->getLowOrder();
12668+
12669+
stopUsingCopyRegOffset = false;
12670+
}
12671+
}
12672+
else
12673+
{
12674+
stopUsingCopyRegOffset = false;
12675+
}
12676+
12677+
//lengthNode (type: long)
12678+
lengthReg = cg->evaluate(lengthNode);
12679+
if (!cg->canClobberNodesRegister(lengthNode))
12680+
{
12681+
TR::Register *lenCopyReg = cg->allocateRegister();
12682+
12683+
if (cg->comp()->target().is32Bit()) //on 32-bit systems, need to grab the lower 32 bits of length from the register pair
12684+
generateTrg1Src1Instruction(cg, TR::InstOpCode::mr, lengthNode, lenCopyReg, lengthReg->getLowOrder());
12685+
else //on 64-bit system, can just do a normal copy
12686+
generateTrg1Src1Instruction(cg, TR::InstOpCode::mr, lengthNode, lenCopyReg, lengthReg);
12687+
12688+
lengthReg = lenCopyReg;
12689+
stopUsingCopyRegLen = true;
12690+
}
12691+
else
12692+
{
12693+
if (cg->comp()->target().is32Bit()) //on 32-bit system, need to grab lower 32 bits of length from the register pair
12694+
lengthReg = lengthReg->getLowOrder();
12695+
12696+
stopUsingCopyRegLen = false;
12697+
}
12698+
12699+
//valueNode (type: byte)
12700+
valueReg = cg->evaluate(valueNode);
12701+
if (cg->comp()->target().cpu.isAtLeast(OMR_PROCESSOR_PPC_P8))
12702+
{
12703+
//on P8 or higher, we can use vector instructions to cut down on loop iterations and residual tests -> need to copy valueReg into a VSX register
12704+
TR::Register *valVectorReg = cg->allocateRegister(TR_VRF);
12705+
generateTrg1Src1Instruction(cg, TR::InstOpCode::mtvsrd, valueNode, valVectorReg, valueReg);
12706+
12707+
valueReg = valVectorReg;
12708+
stopUsingCopyRegVal = true;
12709+
}
12710+
else if (!cg->canClobberNodesRegister(valueNode))
12711+
{
12712+
TR::Register *valCopyReg = cg->allocateRegister();
12713+
generateTrg1Src1Instruction(cg, TR::InstOpCode::mr, valueNode, valCopyReg, valueReg);
12714+
12715+
valueReg = valCopyReg;
12716+
stopUsingCopyRegVal = true;
12717+
}
12718+
12719+
TR::LabelSymbol * residualLabel = generateLabelSymbol(cg);
12720+
TR::LabelSymbol * loopStartLabel = generateLabelSymbol(cg);
12721+
TR::LabelSymbol * doneLabel = generateLabelSymbol(cg);
12722+
12723+
//these labels are not needed for the vector approach to storing to residual bytes (i.e.: P10+)
12724+
TR::LabelSymbol *label8aligned, *label4aligned, *label2aligned, *label1aligned;
12725+
12726+
if (!cg->comp()->target().cpu.isAtLeast(OMR_PROCESSOR_PPC_P10))
12727+
{
12728+
label8aligned = generateLabelSymbol(cg);
12729+
label4aligned = generateLabelSymbol(cg);
12730+
label2aligned = generateLabelSymbol(cg);
12731+
label1aligned = generateLabelSymbol(cg);
12732+
}
12733+
12734+
TR::RegisterDependencyConditions *conditions;
12735+
int32_t numDeps = 6;
12736+
12737+
//need extra register for offset only if it isn't already included in the destination address AND it isn't a constant
12738+
if (arrayCheckNeeded && !useOffsetAsImmVal)
12739+
numDeps++;
12740+
12741+
conditions = new (cg->trHeapMemory()) TR::RegisterDependencyConditions(numDeps, numDeps, cg->trMemory());
12742+
TR::Register *cndReg = cg->allocateRegister(TR_CCR);
12743+
TR::addDependency(conditions, cndReg, TR::RealRegister::cr0, TR_CCR, cg);
12744+
12745+
if (arrayCheckNeeded)
12746+
{
12747+
//dstBaseAddrReg holds the address of the object being written to, so need to exclude GPR0
12748+
TR::addDependency(conditions, dstBaseAddrReg, TR::RealRegister::NoReg, TR_GPR, cg);
12749+
conditions->getPostConditions()->getRegisterDependency(conditions->getAddCursorForPost() - 1)->setExcludeGPR0();
12750+
12751+
if (!useOffsetAsImmVal)
12752+
TR::addDependency(conditions, dstOffsetReg, TR::RealRegister::NoReg, TR_GPR, cg);
12753+
}
12754+
else
12755+
{
12756+
//dstAddrReg holds the address of the object being written to, so need to exclude GPR0
12757+
TR::addDependency(conditions, dstAddrReg, TR::RealRegister::NoReg, TR_GPR, cg);
12758+
conditions->getPostConditions()->getRegisterDependency(1)->setExcludeGPR0();
12759+
}
12760+
12761+
TR::addDependency(conditions, lengthReg, TR::RealRegister::NoReg, TR_GPR, cg);
12762+
TR::addDependency(conditions, valueReg, TR::RealRegister::NoReg, TR_GPR, cg);
12763+
12764+
//temp1Reg will later be used to hold the J9Class flags for the object at dst, so need to exclude GPR0
12765+
TR::Register * temp1Reg = cg->allocateRegister();
12766+
TR::addDependency(conditions, temp1Reg, TR::RealRegister::NoReg, TR_GPR, cg);
12767+
conditions->getPostConditions()->getRegisterDependency(conditions->getAddCursorForPost() - 1)->setExcludeGPR0();
12768+
12769+
TR::Register * temp2Reg = cg->allocateRegister();
12770+
TR::addDependency(conditions, temp2Reg, TR::RealRegister::NoReg, TR_GPR, cg);
12771+
12772+
12773+
#if defined (J9VM_GC_ENABLE_SPARSE_HEAP_ALLOCATION)
12774+
12775+
if (arrayCheckNeeded) // CASE (3)
12776+
{
12777+
// There are two scenarios in which we DON'T want to modify the dest base address:
12778+
// 1.) If the object is NULL (since we can't load dataAddr from a NULL pointer)
12779+
// 2.) If the object is a non-array object
12780+
// So two checks are required (NULL, Array) to determine whether dataAddr should be loaded or not
12781+
TR::LabelSymbol *noDataAddr = generateLabelSymbol(cg);
12782+
12783+
// We only want to generate a runtime NULL check if the status of the object (i.e.: whether it is NULL or non-NULL)
12784+
// is NOT known. Note that if the object is known to be NULL, arrayCheckNeeded will be false, so there is no need to check
12785+
// that condition here.
12786+
if (!dstBaseAddrNode->isNonNull())
12787+
{
12788+
//generate NULL test
12789+
generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::Op_cmpi, node, cndReg, dstBaseAddrReg, 0);
12790+
generateConditionalBranchInstruction(cg, TR::InstOpCode::beq, node, noDataAddr, cndReg);
12791+
}
12792+
12793+
//Array Check
12794+
TR::Register *dstClassInfoReg = temp1Reg;
12795+
TR::Register *arrayFlagReg = temp2Reg;
12796+
12797+
//load dst class info into temp1Reg
12798+
if (TR::Compiler->om.compressObjectReferences())
12799+
generateTrg1MemInstruction(cg, TR::InstOpCode::lwz, node, dstClassInfoReg,
12800+
TR::MemoryReference::createWithDisplacement(cg, dstBaseAddrReg, static_cast<int32_t>(TR::Compiler->om.offsetOfObjectVftField()), 4));
12801+
else
12802+
generateTrg1MemInstruction(cg,TR::InstOpCode::Op_load, node, dstClassInfoReg,
12803+
TR::MemoryReference::createWithDisplacement(cg, dstBaseAddrReg, static_cast<int32_t>(TR::Compiler->om.offsetOfObjectVftField()), TR::Compiler->om.sizeofReferenceAddress()));
12804+
12805+
TR::TreeEvaluator::generateVFTMaskInstruction(cg, node, dstClassInfoReg);
12806+
12807+
TR::MemoryReference *dstClassMR = TR::MemoryReference::createWithDisplacement(cg, dstClassInfoReg, offsetof(J9Class, classDepthAndFlags), TR::Compiler->om.sizeofReferenceAddress());
12808+
generateTrg1MemInstruction(cg, TR::InstOpCode::Op_load, node, dstClassInfoReg, dstClassMR);
12809+
12810+
//generate array check
12811+
int32_t arrayFlagValue = comp->fej9()->getFlagValueForArrayCheck();
12812+
generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::andis_r, node, arrayFlagReg, dstClassInfoReg, arrayFlagValue >> 16);
12813+
12814+
//if object is not an array (i.e.: temp1Reg & temp2Reg == 0), skip adjusting dstBaseAddr and dstOffset
12815+
generateConditionalBranchInstruction(cg, TR::InstOpCode::beq, node, noDataAddr, cndReg);
12816+
12817+
//load dataAddr if object is array:
12818+
TR::MemoryReference *dataAddrSlotMR = TR::MemoryReference::createWithDisplacement(cg, dstBaseAddrReg, comp->fej9()->getOffsetOfContiguousDataAddrField(), TR::Compiler->om.sizeofReferenceAddress());
12819+
generateTrg1MemInstruction(cg, TR::InstOpCode::Op_load, node, dstBaseAddrReg, dataAddrSlotMR);
12820+
12821+
//arrayCHK will skip to here if object is not an array
12822+
generateLabelInstruction(cg, TR::InstOpCode::label, node, noDataAddr);
12823+
12824+
//calculate dstAddr = dstBaseAddr + dstOffset
12825+
dstAddrReg = dstBaseAddrReg;
12826+
12827+
if (useOffsetAsImmVal)
12828+
{
12829+
int offsetImmVal = dstOffsetNode->getConstValue();
12830+
generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, node, dstAddrReg, dstBaseAddrReg, offsetImmVal);
12831+
}
12832+
else
12833+
generateTrg1Src2Instruction(cg, TR::InstOpCode::add, node, dstAddrReg, dstBaseAddrReg, dstOffsetReg);
12834+
}
12835+
12836+
#endif /* J9VM_GC_ENABLE_SPARSE_HEAP_ALLOCATION */
12837+
12838+
// assemble the double word value from byte value
12839+
if (cg->comp()->target().cpu.isAtLeast(OMR_PROCESSOR_PPC_P8))
12840+
{
12841+
generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::vspltb, valueNode, valueReg, valueReg, 7);
12842+
}
12843+
else
12844+
{
12845+
generateTrg1Src1Imm2Instruction(cg, TR::InstOpCode::rldimi, node, valueReg, valueReg, 8, CONSTANT64(0x000000000000FF00));
12846+
generateTrg1Src1Imm2Instruction(cg, TR::InstOpCode::rldimi, node, valueReg, valueReg, 16, CONSTANT64(0x00000000FFFF0000));
12847+
generateTrg1Src1Imm2Instruction(cg, TR::InstOpCode::rldimi, node, valueReg, valueReg, 32, CONSTANT64(0xFFFFFFFF00000000));
12848+
}
12849+
12850+
generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::Op_cmpli, node, cndReg, lengthReg, 32);
12851+
generateConditionalBranchInstruction(cg, TR::InstOpCode::blt, node, residualLabel, cndReg);
12852+
12853+
generateTrg1Src1ImmInstruction(cg, lengthNode->getType().isInt32() ? TR::InstOpCode::srawi : TR::InstOpCode::sradi, node, temp1Reg, lengthReg, 5);
12854+
generateSrc1Instruction(cg, TR::InstOpCode::mtctr, node, temp1Reg);
12855+
generateLabelInstruction(cg, TR::InstOpCode::label, node, loopStartLabel);
12856+
12857+
//store designated value to memory in chunks of 32 bytes
12858+
if (cg->comp()->target().cpu.isAtLeast(OMR_PROCESSOR_PPC_P8))
12859+
{
12860+
//on P8 and higher, we can use vector instructions to cut down on loop iterations/number of stores
12861+
generateMemSrc1Instruction(cg, TR::InstOpCode::stxvd2x, node, TR::MemoryReference::createWithIndexReg(cg, NULL, dstAddrReg, 16), valueReg);
12862+
generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, node, dstAddrReg, dstAddrReg, 16);
12863+
generateMemSrc1Instruction(cg, TR::InstOpCode::stxvd2x, node, TR::MemoryReference::createWithIndexReg(cg, NULL, dstAddrReg, 16), valueReg);
12864+
generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, node, dstAddrReg, dstAddrReg, 16);
12865+
}
12866+
else
12867+
{
12868+
generateMemSrc1Instruction(cg, TR::InstOpCode::std, node, TR::MemoryReference::createWithDisplacement(cg, dstAddrReg, 0, 8), valueReg);
12869+
generateMemSrc1Instruction(cg, TR::InstOpCode::std, node, TR::MemoryReference::createWithDisplacement(cg, dstAddrReg, 8, 8), valueReg);
12870+
generateMemSrc1Instruction(cg, TR::InstOpCode::std, node, TR::MemoryReference::createWithDisplacement(cg, dstAddrReg, 16, 8), valueReg);
12871+
generateMemSrc1Instruction(cg, TR::InstOpCode::std, node, TR::MemoryReference::createWithDisplacement(cg, dstAddrReg, 24, 8), valueReg);
12872+
generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, node, dstAddrReg, dstAddrReg, 32);
12873+
}
12874+
12875+
//decrement counter and return to start of loop
12876+
generateConditionalBranchInstruction(cg, TR::InstOpCode::bdnz, node, loopStartLabel, cndReg);
12877+
12878+
//loop exit
12879+
generateLabelInstruction(cg, TR::InstOpCode::label, node, residualLabel);
12880+
12881+
//Set residual bytes (max number of residual bytes = 31 = 0x1F)
12882+
if (cg->comp()->target().cpu.isAtLeast(OMR_PROCESSOR_PPC_P10)) //on P10, we can use stxvl to store all residual bytes efficiently
12883+
{
12884+
//First 16 byte segment
12885+
generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::andi_r, node, temp1Reg, lengthReg, 16); //get first hex char (can only be 0 or 1)
12886+
generateTrg1Src1Instruction(cg, TR::InstOpCode::mr, node, temp2Reg, temp1Reg); //keep a copy of first hex char
12887+
12888+
//store to memory
12889+
//NOTE: due to a quirk of the stxvl instruction on P10, the number of residual bytes must be shifted over before it can be used
12890+
generateTrg1Src1Imm2Instruction(cg, TR::InstOpCode::rldicr, node, temp1Reg, temp1Reg, 56, CONSTANT64(0xFF00000000000000));
12891+
generateSrc3Instruction(cg, TR::InstOpCode::stxvl, node, valueReg, dstAddrReg, temp1Reg);
12892+
12893+
//advance to next 16 byte chunk IF number of residual bytes >= 16
12894+
generateTrg1Src2Instruction(cg, TR::InstOpCode::add, node, dstAddrReg, dstAddrReg, temp2Reg);
12895+
12896+
//Second 16 byte segment
12897+
generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::andi_r, node, temp1Reg, lengthReg, 15); //get second hex char
12898+
generateTrg1Src1Imm2Instruction(cg, TR::InstOpCode::rldicr, node, temp1Reg, temp1Reg, 56, CONSTANT64(0xFF00000000000000)); //shift num residual bytes
12899+
generateSrc3Instruction(cg, TR::InstOpCode::stxvl, node, valueReg, dstAddrReg, temp1Reg); //store to memory
12900+
}
12901+
else
12902+
{
12903+
TR::Register *valueResidueReg;
12904+
12905+
if (cg->comp()->target().cpu.isAtLeast(OMR_PROCESSOR_PPC_P8))
12906+
{
12907+
//since P8 and P9 used the vector approach, we first need to copy valueReg back into a GPR
12908+
generateTrg1Src1Instruction(cg, TR::InstOpCode::mfvsrd, node, temp2Reg, valueReg);
12909+
valueResidueReg = temp2Reg;
12910+
}
12911+
else
12912+
valueResidueReg = valueReg;
12913+
12914+
//check if residual < 16
12915+
generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::andi_r, node, temp1Reg, lengthReg, 16);
12916+
generateConditionalBranchInstruction(cg, TR::InstOpCode::beq, node, label8aligned, cndReg);
12917+
generateMemSrc1Instruction(cg, TR::InstOpCode::std, node, TR::MemoryReference::createWithDisplacement(cg, dstAddrReg, 0, 8), valueResidueReg);
12918+
generateMemSrc1Instruction(cg, TR::InstOpCode::std, node, TR::MemoryReference::createWithDisplacement(cg, dstAddrReg, 8, 8), valueResidueReg);
12919+
generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, node, dstAddrReg, dstAddrReg, 16);
12920+
12921+
generateLabelInstruction(cg, TR::InstOpCode::label, node, label8aligned); //check if residual < 8
12922+
generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::andi_r, node, temp1Reg, lengthReg, 8);
12923+
generateConditionalBranchInstruction(cg, TR::InstOpCode::beq, node, label4aligned, cndReg);
12924+
generateMemSrc1Instruction(cg, TR::InstOpCode::std, node, TR::MemoryReference::createWithDisplacement(cg, dstAddrReg, 0, 8), valueResidueReg);
12925+
generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, node, dstAddrReg, dstAddrReg, 8);
12926+
12927+
generateLabelInstruction(cg, TR::InstOpCode::label, node, label4aligned); //check if residual < 4
12928+
generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::andi_r, node, temp1Reg, lengthReg, 4);
12929+
generateConditionalBranchInstruction(cg, TR::InstOpCode::beq, node, label2aligned, cndReg);
12930+
generateMemSrc1Instruction(cg, TR::InstOpCode::stw, node, TR::MemoryReference::createWithDisplacement(cg, dstAddrReg, 0, 4), valueResidueReg);
12931+
generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, node, dstAddrReg, dstAddrReg, 4);
12932+
12933+
generateLabelInstruction(cg, TR::InstOpCode::label, node, label2aligned); //check if residual < 2
12934+
generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::andi_r, node, temp1Reg, lengthReg, 2);
12935+
generateConditionalBranchInstruction(cg, TR::InstOpCode::beq, node, label1aligned, cndReg);
12936+
generateMemSrc1Instruction(cg, TR::InstOpCode::sth, node, TR::MemoryReference::createWithDisplacement(cg, dstAddrReg, 0, 2), valueResidueReg);
12937+
generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, node, dstAddrReg, dstAddrReg, 2);
12938+
12939+
generateLabelInstruction(cg, TR::InstOpCode::label, node, label1aligned); //residual <= 1
12940+
generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::andi_r, node, temp1Reg, lengthReg, 1);
12941+
generateConditionalBranchInstruction(cg, TR::InstOpCode::beq, node, doneLabel, cndReg);
12942+
generateMemSrc1Instruction(cg, TR::InstOpCode::stb, node, TR::MemoryReference::createWithDisplacement(cg, dstAddrReg, 0, 1), valueResidueReg);
12943+
}
12944+
12945+
generateDepLabelInstruction(cg, TR::InstOpCode::label, node, doneLabel, conditions);
12946+
12947+
if (stopUsingCopyRegBase)
12948+
cg->stopUsingRegister(dstBaseAddrReg);
12949+
if (stopUsingCopyRegOffset)
12950+
cg->stopUsingRegister(dstOffsetReg);
12951+
if (stopUsingCopyRegAddr)
12952+
cg->stopUsingRegister(dstAddrReg);
12953+
if (stopUsingCopyRegLen)
12954+
cg->stopUsingRegister(lengthReg);
12955+
if (stopUsingCopyRegVal)
12956+
cg->stopUsingRegister(valueReg);
12957+
12958+
cg->stopUsingRegister(cndReg);
12959+
cg->stopUsingRegister(temp1Reg);
12960+
cg->stopUsingRegister(temp2Reg);
12961+
12962+
if (dstBaseAddrNode) cg->decReferenceCount(dstBaseAddrNode);
12963+
if (dstOffsetNode) cg->decReferenceCount(dstOffsetNode);
12964+
if (dstAddrNode) cg->decReferenceCount(dstAddrNode);
12965+
cg->decReferenceCount(lengthNode);
12966+
cg->decReferenceCount(valueNode);
12967+
12968+
return(NULL);
12969+
}
12970+
12971+
1260112972
TR::Register *J9::Power::TreeEvaluator::tstartEvaluator(TR::Node *node, TR::CodeGenerator *cg)
1260212973
{
1260312974
// tstart

0 commit comments

Comments
 (0)