Skip to content

Commit

Permalink
Z: Short circuit var length array cmp helper
Browse files Browse the repository at this point in the history
Add short circuit test of whether two array addresses are equal for
arraycmp. This particular case handles unsigned result and variable
length or length greater than 4K.
Short circuit branching is added to the start of instruction sequence.

Signed-off-by: Ehsan Kiani Far <ehsan.kianifar@gmail.com>
  • Loading branch information
ehsankianifar committed Feb 1, 2024
1 parent a2b3b25 commit 47bc735
Showing 1 changed file with 33 additions and 44 deletions.
77 changes: 33 additions & 44 deletions compiler/z/codegen/OMRTreeEvaluator.cpp
Expand Up @@ -10780,6 +10780,7 @@ OMR::Z::TreeEvaluator::arraycmpHelper(TR::Node *node,
bool lenMinusOne = false;
bool needs64BitOpCode = false;

TR::LabelSymbol *cFlowRegionStart = generateLabelSymbol(cg);
TR::LabelSymbol *cFlowRegionEnd = generateLabelSymbol(cg);

TR::Register *loopCountReg = NULL;
Expand Down Expand Up @@ -10833,17 +10834,30 @@ OMR::Z::TreeEvaluator::arraycmpHelper(TR::Node *node,
maxLenIn256 ? 5 : (isWideChar ? (isFoldedIf ? 10 : 11) : 5 + 4),
cg);

if (!isFoldedIf && needResultReg)
{
branchDeps->addPostCondition(retValReg, TR::RealRegister::AssignAny);
generateRRInstruction(cg, TR::InstOpCode::getXORRegOpCode(), node, retValReg, retValReg);
}

generateS390LabelInstruction(cg, TR::InstOpCode::label, node, cFlowRegionStart);
cFlowRegionStart->setStartInternalControlFlow();

generateS390CompareAndBranchInstruction(
cg,
TR::InstOpCode::getCmpLogicalRegOpCode(),
node,
source1Reg,
source2Reg,
TR::InstOpCode::COND_BE,
isIfxcmpBrCondContainEqual ? compareTarget : cFlowRegionEnd,
false /* needsCC */);

//We could do better job in future for the known length (>=4k)
//Currently there are some unnecessary test/load instructions generated.

if (maxLenIn256)
{
if (!isFoldedIf && needResultReg)
{
branchDeps->addPostCondition(retValReg, TR::RealRegister::AssignAny);
generateRRInstruction(cg, TR::InstOpCode::getXORRegOpCode(), node, retValReg, retValReg);
}

if (!lenMinusOne)
{
generateRIInstruction(cg, (needs64BitOpCode) ? TR::InstOpCode::AGHI : TR::InstOpCode::AHI, node, lengthReg, -1);
Expand All @@ -10858,15 +10872,12 @@ OMR::Z::TreeEvaluator::arraycmpHelper(TR::Node *node,
if (isFoldedIf)
{
if (isIfxcmpBrCondContainEqual)
setStartInternalControlFlow(cg, node, generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BL, node, compareTarget),
isStartInternalControlFlowSet);
generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BL, node, compareTarget);
else
setStartInternalControlFlow(cg, node, generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BL, node, cFlowRegionEnd),
isStartInternalControlFlowSet);
generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BL, node, cFlowRegionEnd);
}
else
setStartInternalControlFlow(cg, node, generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BL, node, cFlowRegionEnd),
isStartInternalControlFlowSet);
generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BL, node, cFlowRegionEnd);
}

TR::MemoryReference *source1MemRef = generateS390MemoryReference(source1Reg, 0, cg);
Expand Down Expand Up @@ -10895,12 +10906,6 @@ OMR::Z::TreeEvaluator::arraycmpHelper(TR::Node *node,

//compareDeps = new (cg->trHeapMemory()) TR::RegisterDependencyConditions(0, isFoldedIf ? 6 : 7, cg);

if(!isFoldedIf && needResultReg)
{
branchDeps->addPostCondition(retValReg, TR::RealRegister::AssignAny);
generateRRInstruction(cg, TR::InstOpCode::getXORRegOpCode(), node, retValReg, retValReg);
}

//cFlowRegionEnd = generateLabelSymbol(cg);

generateRRInstruction(cg, cg->comp()->target().is64Bit() ? TR::InstOpCode::LTGR : TR::InstOpCode::LTR, node, lengthReg, lengthReg);
Expand All @@ -10909,15 +10914,12 @@ OMR::Z::TreeEvaluator::arraycmpHelper(TR::Node *node,
if (isFoldedIf)
{
if (isIfxcmpBrCondContainEqual)
setStartInternalControlFlow(cg, node, generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BZ, node, compareTarget),
isStartInternalControlFlowSet);
generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BZ, node, compareTarget);
else
setStartInternalControlFlow(cg, node, generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_MASK8, node, cFlowRegionEnd),
isStartInternalControlFlowSet);
generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_MASK8, node, cFlowRegionEnd);
}
else
setStartInternalControlFlow(cg, node, generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_MASK8, node, cFlowRegionEnd),
isStartInternalControlFlowSet);
generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_MASK8, node, cFlowRegionEnd);

if(isWideChar)
{
Expand All @@ -10943,12 +10945,6 @@ OMR::Z::TreeEvaluator::arraycmpHelper(TR::Node *node,
//This part uses CLC loop to do the compare
//CLC loop is considered superior to CLCLE -- task 33860

if (!isFoldedIf && needResultReg)
{
branchDeps->addPostCondition(retValReg, TR::RealRegister::AssignAny);
generateRRInstruction(cg, TR::InstOpCode::getXORRegOpCode(), node, retValReg, retValReg);
}

loopCountReg = cg->allocateRegister();

if (!lenMinusOne)
Expand All @@ -10966,15 +10962,12 @@ OMR::Z::TreeEvaluator::arraycmpHelper(TR::Node *node,
{
if (isIfxcmpBrCondContainEqual)
// generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BL, node, compareTarget);
setStartInternalControlFlow(cg, node, generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BL, node, compareTarget),
isStartInternalControlFlowSet);
generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BL, node, compareTarget);
else
setStartInternalControlFlow(cg, node, generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BL, node, cFlowRegionEnd),
isStartInternalControlFlowSet);
generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BL, node, cFlowRegionEnd);
}
else
setStartInternalControlFlow(cg, node, generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BL, node, cFlowRegionEnd),
isStartInternalControlFlowSet);
generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BL, node, cFlowRegionEnd);
}

branchDeps->addPostConditionIfNotAlreadyInserted(source1Reg, TR::RealRegister::AssignAny);
Expand All @@ -10994,8 +10987,7 @@ OMR::Z::TreeEvaluator::arraycmpHelper(TR::Node *node,
generateRSInstruction(cg, TR::InstOpCode::SRA, node, loopCountReg, 8);
}

setStartInternalControlFlow(cg, node, generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BE, node, bottomOfLoop),
isStartInternalControlFlowSet);
generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BE, node, bottomOfLoop);

TR::MemoryReference *source1MemRef = generateS390MemoryReference(source1Reg, 0, cg);
TR::MemoryReference *source2MemRef = generateS390MemoryReference(source2Reg, 0, cg);
Expand All @@ -11020,15 +11012,12 @@ OMR::Z::TreeEvaluator::arraycmpHelper(TR::Node *node,
if (isFoldedIf)
{
if (ifxcmpBrCond == TR::InstOpCode::COND_MASK8)
setStartInternalControlFlow(cg, node, generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_MASK6, node, cFlowRegionEnd),
isStartInternalControlFlowSet);
generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_MASK6, node, cFlowRegionEnd);
else
setStartInternalControlFlow(cg, node, generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_MASK6, node, outOfCompare),
isStartInternalControlFlowSet);
generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_MASK6, node, outOfCompare);
}
else
setStartInternalControlFlow(cg, node, generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_MASK6, node, outOfCompare),
isStartInternalControlFlowSet);
generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_MASK6, node, outOfCompare);

generateRXInstruction(cg, TR::InstOpCode::LA, node, source1Reg, generateS390MemoryReference(source1Reg, 256, cg));
generateRXInstruction(cg, TR::InstOpCode::LA, node, source2Reg, generateS390MemoryReference(source2Reg, 256, cg));
Expand Down

0 comments on commit 47bc735

Please sign in to comment.