Skip to content

Commit

Permalink
Change arraycmp length child to 64 bits
Browse files Browse the repository at this point in the history
Previously the arraycmp IL opcode's length child  was specified as 32 bits but
was inconsistent in its use. This commit changes the specification of the
length child to 64 bits, and normalizes the use to 64 bits.

Closes: #6992
Signed-off-by: Spencer Comin <spencer.comin@ibm.com>
  • Loading branch information
Spencer-Comin committed May 1, 2024
1 parent 49ff22b commit 9589a57
Show file tree
Hide file tree
Showing 7 changed files with 61 additions and 69 deletions.
33 changes: 9 additions & 24 deletions compiler/aarch64/codegen/OMRTreeEvaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6938,7 +6938,7 @@ arraycmpEvaluatorHelper(TR::Node *node, TR::CodeGenerator *cg, bool isArrayCmpLe
generateCompareInstruction(cg, node, src1Reg, src2Reg, true);
if (!isLengthGreaterThan15)
{
auto ccmpLengthInstr = generateConditionalCompareImmInstruction(cg, node, lengthReg, 0, 4, TR::CC_NE, /* is64bit */ isArrayCmpLen); /* 4 for Z flag */
auto ccmpLengthInstr = generateConditionalCompareImmInstruction(cg, node, lengthReg, 0, 4, TR::CC_NE, /* is64bit */ true); /* 4 for Z flag */
if (debugObj)
{
debugObj->addInstructionComment(ccmpLengthInstr, "Compares lengthReg with 0 if src1 and src2 are not the same array. Otherwise, sets EQ flag.");
Expand All @@ -6960,14 +6960,14 @@ arraycmpEvaluatorHelper(TR::Node *node, TR::CodeGenerator *cg, bool isArrayCmpLe
TR::Register *data4Reg = srm->findOrCreateScratchRegister();
if (!isLengthGreaterThan15)
{
generateCompareImmInstruction(cg, node, lengthReg, 16, /* is64bit */ isArrayCmpLen);
generateCompareImmInstruction(cg, node, lengthReg, 16, /* is64bit */ true);
auto branchToLessThan16LabelInstr = generateConditionalBranchInstruction(cg, TR::InstOpCode::b_cond, node, lessThan16Label, TR::CC_CC);
if (debugObj)
{
debugObj->addInstructionComment(branchToLessThan16LabelInstr, "Jumps to lessThan16Label if length < 16.");
}
}
generateTrg1Src1ImmInstruction(cg, isArrayCmpLen ? TR::InstOpCode::subimmx : TR::InstOpCode::subimmw, node, lengthReg, lengthReg, 16);
generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::subimmx, node, lengthReg, lengthReg, 16);

TR::LabelSymbol *loop16Label = generateLabelSymbol(cg);
{
Expand All @@ -6984,29 +6984,22 @@ arraycmpEvaluatorHelper(TR::Node *node, TR::CodeGenerator *cg, bool isArrayCmpLe
}
generateConditionalCompareInstruction(cg, node, data3Reg, data4Reg, 0, TR::CC_EQ, true);
auto branchToNotEqual16LabelInstr2 = generateConditionalBranchInstruction(cg, TR::InstOpCode::b_cond, node, notEqual16Label, TR::CC_NE);
auto subtractLengthInstr = generateTrg1Src1ImmInstruction(cg, (isLengthGreaterThan15 || isArrayCmpLen) ? TR::InstOpCode::subsimmx : TR::InstOpCode::subsimmw, node, lengthReg, lengthReg, 16);
auto subtractLengthInstr = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::subsimmx, node, lengthReg, lengthReg, 16);
auto branchBacktoLoop16LabelInstr = generateConditionalBranchInstruction(cg, TR::InstOpCode::b_cond, node, loop16Label, TR::CC_CS);
if (debugObj)
{
debugObj->addInstructionComment(loop16LabelInstr, "loop16Label");
debugObj->addInstructionComment(branchToNotEqual16LabelInstr2, "Jumps to notEqual16Label if mismatch is found in the 16-byte data");
debugObj->addInstructionComment(branchBacktoLoop16LabelInstr, "Jumps to loop16Label if the remaining length >= 16 and no mismatch is found so far.");
if (isLengthGreaterThan15)
{
debugObj->addInstructionComment(subtractLengthInstr, "Treats length reg as a 64-bit reg as it is used as the 2nd source reg for 64-bit add later.");
}
}
}
if (isLengthGreaterThan15)
{
generateCompareImmInstruction(cg, node, lengthReg, -16, true);
auto branchToDoneLabelInstr3 = generateConditionalBranchInstruction(cg, TR::InstOpCode::b_cond, node, isArrayCmpLen ? done0Label : doneLabel, TR::CC_EQ);
auto branchToDoneLabelInstr3 = generateConditionalBranchInstruction(cg, TR::InstOpCode::b_cond, node, done0Label, TR::CC_EQ);
auto adjustSrc1RegInstr = generateTrg1Src2Instruction(cg, TR::InstOpCode::addx, node, src1Reg, src1Reg, lengthReg);
generateTrg1Src2Instruction(cg, TR::InstOpCode::addx, node, src2Reg, src2Reg, lengthReg);
if (isArrayCmpLen)
loadConstant64(cg, node, 0, lengthReg);
else
loadConstant32(cg, node, 0, lengthReg);
loadConstant64(cg, node, 0, lengthReg);
auto branchBacktoLoop16LabelInstr = generateLabelInstruction(cg, TR::InstOpCode::b, node, loop16Label);
if (debugObj)
{
Expand All @@ -7025,16 +7018,8 @@ arraycmpEvaluatorHelper(TR::Node *node, TR::CodeGenerator *cg, bool isArrayCmpLe
else
{
TR::Instruction *branchToDoneLabelInstr3;
if (isArrayCmpLen)
{
generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addimmx, node, lengthReg, lengthReg, 16);
branchToDoneLabelInstr3 = generateCompareBranchInstruction(cg, TR::InstOpCode::cbzx, node, lengthReg, done0Label);
}
else
{
generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addimmw, node, lengthReg, lengthReg, 16);
branchToDoneLabelInstr3 = generateCompareBranchInstruction(cg, TR::InstOpCode::cbzw, node, lengthReg, doneLabel);
}
generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addimmx, node, lengthReg, lengthReg, 16);
branchToDoneLabelInstr3 = generateCompareBranchInstruction(cg, TR::InstOpCode::cbzx, node, lengthReg, isArrayCmpLen? done0Label : doneLabel);

auto branchToLessThan16Label2 = generateLabelInstruction(cg, TR::InstOpCode::b, node, lessThan16Label);

Expand Down Expand Up @@ -7092,7 +7077,7 @@ arraycmpEvaluatorHelper(TR::Node *node, TR::CodeGenerator *cg, bool isArrayCmpLe
auto branchToDone0LabelInstr = generateLabelInstruction(cg, TR::InstOpCode::b, node, done0Label);

auto lessThan16LabelInstr = generateLabelInstruction(cg, TR::InstOpCode::label, node, lessThan16Label);
generateTrg1Src1ImmInstruction(cg, isArrayCmpLen ? TR::InstOpCode::subsimmx : TR::InstOpCode::subsimmw, node, lengthReg, lengthReg, 1);
generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::subsimmx, node, lengthReg, lengthReg, 1);
generateTrg1MemInstruction(cg, TR::InstOpCode::ldrbpost, node, data1Reg, TR::MemoryReference::createWithDisplacement(cg, src1Reg, 1));
generateTrg1MemInstruction(cg, TR::InstOpCode::ldrbpost, node, data2Reg, TR::MemoryReference::createWithDisplacement(cg, src2Reg, 1));
generateConditionalCompareInstruction(cg, node, data1Reg, data2Reg, 0, TR::CC_HI);
Expand Down
2 changes: 1 addition & 1 deletion compiler/il/OMROpcodes.enum
Original file line number Diff line number Diff line change
Expand Up @@ -7196,7 +7196,7 @@ OPCODE_MACRO(\
/* .properties4 = */ 0, \
/* .dataType = */ TR::Int32, \
/* .typeProperties = */ ILTypeProp::Size_4 | ILTypeProp::Integer, \
/* .childProperties = */ THREE_CHILD(TR::Address, TR::Address, TR::Int32), \
/* .childProperties = */ THREE_CHILD(TR::Address, TR::Address, TR::Int64), \
/* .swapChildrenOpCode = */ TR::BadILOp, \
/* .reverseBranchOpCode = */ TR::BadILOp, \
/* .booleanCompareOpCode = */ TR::BadILOp, \
Expand Down
11 changes: 9 additions & 2 deletions compiler/optimizer/LoopReducer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2143,7 +2143,14 @@ TR_LoopReducer::generateArraycmp(TR_RegionStructure * whileLoop, TR_InductionVar
//
arraycmpLoop.getFirstAddress()->updateAiaddSubTree(arraycmpLoop.getFirstIndVarNode(), &arraycmpLoop);
arraycmpLoop.getSecondAddress()->updateAiaddSubTree(arraycmpLoop.getSecondIndVarNode(), &arraycmpLoop);
TR::Node * imul = arraycmpLoop.updateIndVarStore(arraycmpLoop.getFirstIndVarNode(), indVarStoreNode, arraycmpLoop.getFirstAddress());
TR::Node * mul = arraycmpLoop.updateIndVarStore(arraycmpLoop.getFirstIndVarNode(), indVarStoreNode, arraycmpLoop.getFirstAddress());
if (!comp()->target().is64Bit())
{
// updateIndVarStore returns an imul on 32 bit, extend as arraycmp takes 64 bit length
mul = TR::Node::create(TR::i2l, 1, mul);
// extending the imul is technically unneccessary since the length of an array on 32 bit cannot exceed 32 bit range
mul->setUnneededConversion(true);
}

arraycmpLoop.getFirstAddress()->updateMultiply(arraycmpLoop.getFirstMultiplyNode());
arraycmpLoop.getFirstAddress()->updateMultiply(arraycmpLoop.getSecondMultiplyNode());
Expand All @@ -2159,7 +2166,7 @@ TR_LoopReducer::generateArraycmp(TR_RegionStructure * whileLoop, TR_InductionVar
TR_ASSERT(arraycmpLoop.getSecondLoad()->getOpCode().isLoadVar(),"secondLoad %s (%p) is not a loadVar for arraycmp reduction\n",
arraycmpLoop.getSecondLoad()->getOpCode().getName(),arraycmpLoop.getSecondLoad());

TR::Node * arraycmp = TR::Node::create(TR::arraycmp, 3, firstBase, secondBase, imul);
TR::Node * arraycmp = TR::Node::create(TR::arraycmp, 3, firstBase, secondBase, mul);

TR::SymbolReference *arraycmpSymRef = comp()->getSymRefTab()->findOrCreateArrayCmpSymbol();
arraycmp->setSymbolReference(arraycmpSymRef);
Expand Down
20 changes: 10 additions & 10 deletions compiler/p/codegen/OMRTreeEvaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5472,7 +5472,7 @@ static TR::Register *inlineArrayCmpP10(TR::Node *node, TR::CodeGenerator *cg, bo

bool is64bit = cg->comp()->target().is64Bit();

if (isArrayCmpLen && !is64bit)
if (!is64bit)
{
pairReg = tempReg;
tempReg = tempReg->getLowOrder();
Expand All @@ -5482,13 +5482,13 @@ static TR::Register *inlineArrayCmpP10(TR::Node *node, TR::CodeGenerator *cg, bo
startLabel->setStartInternalControlFlow();

generateTrg1ImmInstruction(cg, TR::InstOpCode::li, node, indexReg, 0);
generateTrg1Src1ImmInstruction(cg, (is64bit && isArrayCmpLen) ? TR::InstOpCode::cmpi8 : TR::InstOpCode::cmpli4, node, condReg, tempReg, 16);
generateTrg1Src1ImmInstruction(cg, is64bit ? TR::InstOpCode::cmpi8 : TR::InstOpCode::cmpli4, node, condReg, tempReg, 16);

// We don't need length anymore as we can calculate the appropriate index by using indexReg and the remainder
generateTrg1Src1Imm2Instruction(cg, TR::InstOpCode::rlwinm, node, returnReg, tempReg, 0, 0xF);
generateConditionalBranchInstruction(cg, TR::InstOpCode::blt, node, residueStartLabel, condReg);

if (is64bit && isArrayCmpLen)
if (is64bit)
{
generateShiftRightLogicalImmediateLong(cg, node, tempReg, tempReg, 4);
}
Expand Down Expand Up @@ -5641,7 +5641,7 @@ static TR::Register *inlineArrayCmp(TR::Node *node, TR::CodeGenerator *cg, bool
}

byteLenRegister = cg->evaluate(lengthNode);
if (isArrayCmpLen && !is64bit)
if (!is64bit)
{
byteLenRegister = byteLenRegister->getLowOrder();
}
Expand All @@ -5660,13 +5660,13 @@ static TR::Register *inlineArrayCmp(TR::Node *node, TR::CodeGenerator *cg, bool
condReg2 = cg->allocateRegister(TR_CCR);

mid2Label = generateLabelSymbol(cg);
generateTrg1Src1ImmInstruction(cg, (is64bit && isArrayCmpLen) ? TR::InstOpCode::cmpi8 : TR::InstOpCode::cmpli4, node, condReg2, byteLenRemainingRegister, byteLen);
generateTrg1Src1ImmInstruction(cg, is64bit ? TR::InstOpCode::cmpi8 : TR::InstOpCode::cmpli4, node, condReg2, byteLenRemainingRegister, byteLen);
generateConditionalBranchInstruction(cg, TR::InstOpCode::blt, node, mid2Label, condReg2);

generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi2, node, src1AddrReg, src1AddrReg, -1*byteLen);
generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi2, node, src2AddrReg, src2AddrReg, -1*byteLen);

if (is64bit && isArrayCmpLen)
if (is64bit)
{
generateShiftRightLogicalImmediateLong(cg, node, tempReg, byteLenRemainingRegister, (byteLen == 8) ? 3 : 2);
}
Expand Down Expand Up @@ -5728,17 +5728,17 @@ static TR::Register *inlineArrayCmp(TR::Node *node, TR::CodeGenerator *cg, bool

generateTrg1Instruction(cg, TR::InstOpCode::mfctr, node, byteLenRemainingRegister);

generateTrg1Src1ImmInstruction(cg, (is64bit && isArrayCmpLen) ? TR::InstOpCode::cmpi8 : TR::InstOpCode::cmpli4, node, condReg2, byteLenRemainingRegister, 0);
generateTrg1Src1ImmInstruction(cg, is64bit ? TR::InstOpCode::cmpi8 : TR::InstOpCode::cmpli4, node, condReg2, byteLenRemainingRegister, 0);
generateTrg1Src2Instruction(cg, TR::InstOpCode::subf, node, byteLenRemainingRegister, byteLenRemainingRegister, tempReg);

if (is64bit && isArrayCmpLen)
if (is64bit)
generateShiftLeftImmediateLong(cg, node, byteLenRemainingRegister, byteLenRemainingRegister, (byteLen == 8) ? 3 : 2);
else
generateShiftLeftImmediate(cg, node, byteLenRemainingRegister, byteLenRemainingRegister, (byteLen == 8) ? 3 : 2);

generateConditionalBranchInstruction(cg, TR::InstOpCode::bne, node, midLabel, condReg2);

generateTrg1Src2Instruction(cg, (is64bit && isArrayCmpLen) ? TR::InstOpCode::cmp8 : TR::InstOpCode::cmpl4, node, condReg2, byteLenRemainingRegister, byteLenRegister);
generateTrg1Src2Instruction(cg, is64bit ? TR::InstOpCode::cmp8 : TR::InstOpCode::cmpl4, node, condReg2, byteLenRemainingRegister, byteLenRegister);
generateLabelInstruction(cg, TR::InstOpCode::label, node, midLabel);
generateTrg1Src2Instruction(cg, TR::InstOpCode::subf, node, byteLenRemainingRegister, byteLenRemainingRegister, byteLenRegister);
generateLabelInstruction(cg, TR::InstOpCode::label, node, mid2Label);
Expand Down Expand Up @@ -5778,7 +5778,7 @@ static TR::Register *inlineArrayCmp(TR::Node *node, TR::CodeGenerator *cg, bool
}
else
{
generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::cmpli4, node, condReg2, byteLenRemainingRegister, 0);
generateTrg1Src1ImmInstruction(cg, is64bit ? TR::InstOpCode::cmpli8 : TR::InstOpCode::cmpli4, node, condReg2, byteLenRemainingRegister, 0);
generateConditionalBranchInstruction(cg, TR::InstOpCode::bne, node, result2Label, condReg2);
generateTrg1ImmInstruction(cg, TR::InstOpCode::li, node, ccReg, 0);
generateLabelInstruction(cg, TR::InstOpCode::b, node, residueEndLabel);
Expand Down
10 changes: 9 additions & 1 deletion compiler/x/codegen/OMRTreeEvaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1151,7 +1151,15 @@ TR::Register *OMR::X86::TreeEvaluator::SSE2ArraycmpEvaluator(TR::Node *node, TR:

TR::Register *s1Reg = cg->gprClobberEvaluate(s1AddrNode, TR::InstOpCode::MOVRegReg());
TR::Register *s2Reg = cg->gprClobberEvaluate(s2AddrNode, TR::InstOpCode::MOVRegReg());
TR::Register *strLenReg = cg->gprClobberEvaluate(lengthNode, TR::InstOpCode::MOVRegReg());
TR::Register *strLenReg = cg->longClobberEvaluate(lengthNode);

if (cg->comp()->target().is32Bit() && strLenReg->getRegisterPair())
{
// On 32-bit, the length is guaranteed to fit into the bottom 32 bits
cg->stopUsingRegister(strLenReg->getHighOrder());
strLenReg = strLenReg->getLowOrder();
}

TR::Register *deltaReg = cg->allocateRegister(TR_GPR);
TR::Register *equalTestReg = cg->allocateRegister(TR_GPR);
TR::Register *s2ByteVer1Reg = cg->allocateRegister(TR_GPR);
Expand Down
13 changes: 3 additions & 10 deletions compiler/z/codegen/OMRTreeEvaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10759,7 +10759,9 @@ OMR::Z::TreeEvaluator::arraycmpHelper(TR::Node *node,

bool lengthCanBeZero = true;
bool lenMinusOne = false;
bool needs64BitOpCode = false;

// Length is specified to be 64 bits, however on 32 bit target the length is guaranteed to fit in 32 bits
bool needs64BitOpCode = cg->comp()->target().is64Bit();

TR::LabelSymbol *cFlowRegionStart = generateLabelSymbol(cg);
TR::LabelSymbol *cFlowRegionEnd = generateLabelSymbol(cg);
Expand All @@ -10770,15 +10772,6 @@ OMR::Z::TreeEvaluator::arraycmpHelper(TR::Node *node,
TR::RegisterPair *source1Pair = NULL;
TR::RegisterPair *source2Pair = NULL;

if (lengthNode)
{
needs64BitOpCode = lengthNode->getSize() > 4;
}
else
{
needs64BitOpCode = cg->comp()->target().is64Bit();
}

if (maxLenIn256)
{
source1Reg = cg->evaluate(source1Node);
Expand Down
Loading

0 comments on commit 9589a57

Please sign in to comment.