diff --git a/compiler/aarch64/codegen/OMRTreeEvaluator.cpp b/compiler/aarch64/codegen/OMRTreeEvaluator.cpp index 0e8b3aa97b8..2f6ac95e8ca 100644 --- a/compiler/aarch64/codegen/OMRTreeEvaluator.cpp +++ b/compiler/aarch64/codegen/OMRTreeEvaluator.cpp @@ -6891,7 +6891,7 @@ arraycmpEvaluatorHelper(TR::Node *node, TR::CodeGenerator *cg, bool isArrayCmpLe generateLabelInstruction(cg, TR::InstOpCode::label, node, startLabel); if (isArrayCmpLen) { - generateMovInstruction(cg, node, resultReg, lengthReg, false); + generateMovInstruction(cg, node, resultReg, lengthReg, true); } else { @@ -6900,7 +6900,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); /* 4 for Z flag */ + auto ccmpLengthInstr = generateConditionalCompareImmInstruction(cg, node, lengthReg, 0, 4, TR::CC_NE, /* is64bit */ isArrayCmpLen); /* 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."); @@ -6922,14 +6922,14 @@ arraycmpEvaluatorHelper(TR::Node *node, TR::CodeGenerator *cg, bool isArrayCmpLe TR::Register *data4Reg = srm->findOrCreateScratchRegister(); if (!isLengthGreaterThan15) { - generateCompareImmInstruction(cg, node, lengthReg, 16); + generateCompareImmInstruction(cg, node, lengthReg, 16, /* is64bit */ isArrayCmpLen); 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, TR::InstOpCode::subimmw, node, lengthReg, lengthReg, 16); + generateTrg1Src1ImmInstruction(cg, isArrayCmpLen ? TR::InstOpCode::subimmx : TR::InstOpCode::subimmw, node, lengthReg, lengthReg, 16); TR::LabelSymbol *loop16Label = generateLabelSymbol(cg); { @@ -6946,7 +6946,7 @@ 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 ? TR::InstOpCode::subsimmx : TR::InstOpCode::subsimmw, node, lengthReg, lengthReg, 16); + auto subtractLengthInstr = generateTrg1Src1ImmInstruction(cg, (isLengthGreaterThan15 || isArrayCmpLen) ? TR::InstOpCode::subsimmx : TR::InstOpCode::subsimmw, node, lengthReg, lengthReg, 16); auto branchBacktoLoop16LabelInstr = generateConditionalBranchInstruction(cg, TR::InstOpCode::b_cond, node, loop16Label, TR::CC_CS); if (debugObj) { @@ -6965,7 +6965,10 @@ arraycmpEvaluatorHelper(TR::Node *node, TR::CodeGenerator *cg, bool isArrayCmpLe auto branchToDoneLabelInstr3 = generateConditionalBranchInstruction(cg, TR::InstOpCode::b_cond, node, isArrayCmpLen ? done0Label : doneLabel, TR::CC_EQ); auto adjustSrc1RegInstr = generateTrg1Src2Instruction(cg, TR::InstOpCode::addx, node, src1Reg, src1Reg, lengthReg); generateTrg1Src2Instruction(cg, TR::InstOpCode::addx, node, src2Reg, src2Reg, lengthReg); - loadConstant32(cg, node, 0, lengthReg); + if (isArrayCmpLen) + loadConstant64(cg, node, 0, lengthReg); + else + loadConstant32(cg, node, 0, lengthReg); auto branchBacktoLoop16LabelInstr = generateLabelInstruction(cg, TR::InstOpCode::b, node, loop16Label); if (debugObj) { @@ -6983,8 +6986,18 @@ arraycmpEvaluatorHelper(TR::Node *node, TR::CodeGenerator *cg, bool isArrayCmpLe } else { - generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addimmw, node, lengthReg, lengthReg, 16); - auto branchToDoneLabelInstr3 = generateCompareBranchInstruction(cg, TR::InstOpCode::cbzw, node, lengthReg, isArrayCmpLen ? done0Label : doneLabel); + 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); + } + auto branchToLessThan16Label2 = generateLabelInstruction(cg, TR::InstOpCode::b, node, lessThan16Label); if (debugObj) @@ -7041,7 +7054,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, TR::InstOpCode::subsimmw, node, lengthReg, lengthReg, 1); + generateTrg1Src1ImmInstruction(cg, isArrayCmpLen ? TR::InstOpCode::subsimmx : TR::InstOpCode::subsimmw, 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); diff --git a/compiler/il/OMROpcodes.enum b/compiler/il/OMROpcodes.enum index 2dba4d20fa3..f3aa5d0a26b 100644 --- a/compiler/il/OMROpcodes.enum +++ b/compiler/il/OMROpcodes.enum @@ -7212,9 +7212,9 @@ OPCODE_MACRO(\ /* .properties2 = */ 0, \ /* .properties3 = */ ILProp3::LikeUse | ILProp3::LikeDef | ILProp3::SkipDynamicLitPoolOnInts, \ /* .properties4 = */ 0, \ - /* .dataType = */ TR::Int32, \ - /* .typeProperties = */ ILTypeProp::Size_4 | ILTypeProp::Integer, \ - /* .childProperties = */ THREE_CHILD(TR::Address, TR::Address, TR::Int32), \ + /* .dataType = */ TR::Int64, \ + /* .typeProperties = */ ILTypeProp::Size_8 | ILTypeProp::Integer | ILTypeProp::Unsigned, \ + /* .childProperties = */ THREE_CHILD(TR::Address, TR::Address, TR::Int64), \ /* .swapChildrenOpCode = */ TR::BadILOp, \ /* .reverseBranchOpCode = */ TR::BadILOp, \ /* .booleanCompareOpCode = */ TR::BadILOp, \ diff --git a/compiler/p/codegen/OMRTreeEvaluator.cpp b/compiler/p/codegen/OMRTreeEvaluator.cpp index ae82f19b12c..d6b285f817a 100644 --- a/compiler/p/codegen/OMRTreeEvaluator.cpp +++ b/compiler/p/codegen/OMRTreeEvaluator.cpp @@ -5447,7 +5447,7 @@ static inline void loadArrayCmpSources(TR::Node *node, TR::InstOpCode::Mnemonic } static TR::Register *inlineArrayCmpP10(TR::Node *node, TR::CodeGenerator *cg, bool isArrayCmpLen) -{ + { TR::Node *src1AddrNode = node->getChild(0); TR::Node *src2AddrNode = node->getChild(1); TR::Node *lengthNode = node->getChild(2); @@ -5458,6 +5458,7 @@ static TR::Register *inlineArrayCmpP10(TR::Node *node, TR::CodeGenerator *cg, bo TR::Register *returnReg = cg->allocateRegister(TR_GPR); TR::Register *tempReg = cg->gprClobberEvaluate(lengthNode); TR::Register *temp2Reg = cg->allocateRegister(TR_GPR); + TR::Register *pairReg = nullptr; TR::Register *vec0Reg = cg->allocateRegister(TR_VRF); TR::Register *vec1Reg = cg->allocateRegister(TR_VRF); @@ -5469,17 +5470,32 @@ static TR::Register *inlineArrayCmpP10(TR::Node *node, TR::CodeGenerator *cg, bo TR::LabelSymbol *endLabel = generateLabelSymbol(cg); TR::LabelSymbol *resultLabel = generateLabelSymbol(cg); + bool is64bit = cg->comp()->target().is64Bit(); + + if (isArrayCmpLen && !is64bit) + { + pairReg = tempReg; + tempReg = tempReg->getLowOrder(); + } + generateLabelInstruction(cg, TR::InstOpCode::label, node, startLabel); startLabel->setStartInternalControlFlow(); generateTrg1ImmInstruction(cg, TR::InstOpCode::li, node, indexReg, 0); - generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::cmpi4, node, condReg, tempReg, 16); + generateTrg1Src1ImmInstruction(cg, (is64bit && isArrayCmpLen) ? 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); - generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::srawi, node, tempReg, tempReg, 4); + if (is64bit && isArrayCmpLen) + { + generateShiftRightLogicalImmediateLong(cg, node, tempReg, tempReg, 4); + } + else + { + generateShiftRightLogicalImmediate(cg, node, tempReg, tempReg, 4); + } generateSrc1Instruction(cg, TR::InstOpCode::mtctr, node, tempReg); generateLabelInstruction(cg, TR::InstOpCode::label, node, loopStartLabel); @@ -5535,6 +5551,10 @@ static TR::Register *inlineArrayCmpP10(TR::Node *node, TR::CodeGenerator *cg, bo generateTrg1Src1Imm2Instruction(cg, TR::InstOpCode::rlwinm, node, returnReg, tempReg, 2, 3); generateTrg1Src2Instruction(cg, TR::InstOpCode::add, node, returnReg, returnReg, tempReg); } + else if (!is64bit) + { + generateTrg1ImmInstruction(cg, TR::InstOpCode::li, node, temp2Reg, 0); + } int32_t numRegs = 9; @@ -5555,15 +5575,27 @@ static TR::Register *inlineArrayCmpP10(TR::Node *node, TR::CodeGenerator *cg, bo generateDepLabelInstruction(cg, TR::InstOpCode::label, node, endLabel, dependencies); endLabel->setEndInternalControlFlow(); - node->setRegister(returnReg); + if (isArrayCmpLen && !is64bit) + { + TR::Register *lowReturnReg = returnReg; + returnReg = cg->allocateRegisterPair(returnReg, temp2Reg); + node->setRegister(returnReg); + TR::Register *liveRegs[4] = { src1AddrReg, src2AddrReg, lowReturnReg, temp2Reg }; + dependencies->stopUsingDepRegs(cg, 4, liveRegs); + cg->stopUsingRegister(pairReg); + } + else + { + node->setRegister(returnReg); + TR::Register *liveRegs[3] = { src1AddrReg, src2AddrReg, returnReg }; + dependencies->stopUsingDepRegs(cg, 3, liveRegs); + } cg->decReferenceCount(src1AddrNode); cg->decReferenceCount(src2AddrNode); cg->decReferenceCount(lengthNode); - TR::Register *liveRegs[3] = { src1AddrReg, src2AddrReg, returnReg }; - dependencies->stopUsingDepRegs(cg, 3, liveRegs); return returnReg; -} + } static TR::Register *inlineArrayCmp(TR::Node *node, TR::CodeGenerator *cg, bool isArrayCmpLen) @@ -5597,11 +5629,22 @@ static TR::Register *inlineArrayCmp(TR::Node *node, TR::CodeGenerator *cg, bool TR::Register *src1AddrReg = cg->gprClobberEvaluate(src1AddrNode); TR::Register *src2AddrReg = cg->gprClobberEvaluate(src2AddrNode); - byteLen = 4; - if (cg->comp()->target().is64Bit()) + bool is64bit = cg->comp()->target().is64Bit(); + + if (is64bit) + { byteLen = 8; + } + else + { + byteLen = 4; + } byteLenRegister = cg->evaluate(lengthNode); + if (isArrayCmpLen && !is64bit) + { + byteLenRegister = byteLenRegister->getLowOrder(); + } byteLenRemainingRegister = cg->allocateRegister(TR_GPR); tempReg = cg->allocateRegister(TR_GPR); @@ -5617,13 +5660,20 @@ static TR::Register *inlineArrayCmp(TR::Node *node, TR::CodeGenerator *cg, bool condReg2 = cg->allocateRegister(TR_CCR); mid2Label = generateLabelSymbol(cg); - generateTrg1Src1ImmInstruction(cg, (byteLen == 8) ? TR::InstOpCode::cmpi8 : TR::InstOpCode::cmpi4, node, condReg2, byteLenRemainingRegister, byteLen); + generateTrg1Src1ImmInstruction(cg, (is64bit && isArrayCmpLen) ? 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); - generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::srawi, node, tempReg, byteLenRemainingRegister, (byteLen == 8) ? 3 : 2); + if (is64bit && isArrayCmpLen) + { + generateShiftRightLogicalImmediateLong(cg, node, tempReg, byteLenRemainingRegister, (byteLen == 8) ? 3 : 2); + } + else + { + generateShiftRightLogicalImmediate(cg, node, tempReg, byteLenRemainingRegister, (byteLen == 8) ? 3 : 2); + } generateSrc1Instruction(cg, TR::InstOpCode::mtctr, node, tempReg); loopStartLabel = generateLabelSymbol(cg); @@ -5650,7 +5700,21 @@ static TR::Register *inlineArrayCmp(TR::Node *node, TR::CodeGenerator *cg, bool generateTrg1MemInstruction (cg, TR::InstOpCode::ldu, node, src2Reg, TR::MemoryReference::createWithDisplacement(cg, src2AddrReg, 8, 8)); } - TR::Register *ccReg = cg->allocateRegister(TR_GPR); + TR::Register *ccReg = nullptr; + TR::Register *lowReturnReg = nullptr; + TR::Register *highReturnReg = nullptr; + + if (!is64bit && isArrayCmpLen) + { + lowReturnReg = cg->allocateRegister(TR_GPR); + highReturnReg = cg->allocateRegister(TR_GPR); + ccReg = cg->allocateRegisterPair(lowReturnReg, highReturnReg); + } + else + { + ccReg = cg->allocateRegister(TR_GPR); + } + generateTrg1Src2Instruction(cg, (byteLen == 8) ? TR::InstOpCode::cmp8 : TR::InstOpCode::cmp4, node, condReg, src1Reg, src2Reg); generateConditionalBranchInstruction(cg, TR::InstOpCode::bne, node, residueStartLabel, condReg); @@ -5664,12 +5728,17 @@ static TR::Register *inlineArrayCmp(TR::Node *node, TR::CodeGenerator *cg, bool generateTrg1Instruction(cg, TR::InstOpCode::mfctr, node, byteLenRemainingRegister); - generateTrg1Src1ImmInstruction(cg, (byteLen == 8) ? TR::InstOpCode::cmpi8 : TR::InstOpCode::cmpi4, node, condReg2, byteLenRemainingRegister, 0); + generateTrg1Src1ImmInstruction(cg, (is64bit && isArrayCmpLen) ? TR::InstOpCode::cmpi8 : TR::InstOpCode::cmpli4, node, condReg2, byteLenRemainingRegister, 0); generateTrg1Src2Instruction(cg, TR::InstOpCode::subf, node, byteLenRemainingRegister, byteLenRemainingRegister, tempReg); - generateShiftLeftImmediate(cg, node, byteLenRemainingRegister, byteLenRemainingRegister, (byteLen == 8) ? 3 : 2); + + if (is64bit && isArrayCmpLen) + 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, (byteLen == 8) ? TR::InstOpCode::cmp8 : TR::InstOpCode::cmp4, node, condReg2, byteLenRemainingRegister, byteLenRegister); + generateTrg1Src2Instruction(cg, (is64bit && isArrayCmpLen) ? 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); @@ -5696,10 +5765,20 @@ static TR::Register *inlineArrayCmp(TR::Node *node, TR::CodeGenerator *cg, bool generateLabelInstruction(cg, TR::InstOpCode::label, node, resultLabel); if (isArrayCmpLen) - generateTrg1Src2Instruction(cg, TR::InstOpCode::subf, node, ccReg, byteLenRemainingRegister, byteLenRegister); + { + if (is64bit) + { + generateTrg1Src2Instruction(cg, TR::InstOpCode::subf, node, ccReg, byteLenRemainingRegister, byteLenRegister); + } + else + { + generateTrg1Src2Instruction(cg, TR::InstOpCode::subf, node, lowReturnReg, byteLenRemainingRegister, byteLenRegister); + generateTrg1ImmInstruction(cg, TR::InstOpCode::li, node, highReturnReg, 0); + } + } else { - generateTrg1Src1ImmInstruction(cg, (byteLen == 8) ? TR::InstOpCode::cmpi8 : TR::InstOpCode::cmpi4, node, condReg2, byteLenRemainingRegister, 0); + generateTrg1Src1ImmInstruction(cg, 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); @@ -5710,6 +5789,10 @@ static TR::Register *inlineArrayCmp(TR::Node *node, TR::CodeGenerator *cg, bool } int32_t numRegs = 10; + if (!is64bit && isArrayCmpLen) + { + numRegs = 11; + } TR::RegisterDependencyConditions *dependencies = new (cg->trHeapMemory()) TR::RegisterDependencyConditions(0, numRegs, cg->trMemory()); dependencies->addPostCondition(src1Reg, TR::RealRegister::NoReg); @@ -5719,7 +5802,15 @@ static TR::Register *inlineArrayCmp(TR::Node *node, TR::CodeGenerator *cg, bool dependencies->addPostCondition(byteLenRegister, TR::RealRegister::NoReg); dependencies->addPostCondition(byteLenRemainingRegister, TR::RealRegister::NoReg); dependencies->addPostCondition(tempReg, TR::RealRegister::NoReg); - dependencies->addPostCondition(ccReg, TR::RealRegister::NoReg); + if (!is64bit && isArrayCmpLen) + { + dependencies->addPostCondition(lowReturnReg, TR::RealRegister::NoReg); + dependencies->addPostCondition(highReturnReg, TR::RealRegister::NoReg); + } + else + { + dependencies->addPostCondition(ccReg, TR::RealRegister::NoReg); + } dependencies->addPostCondition(condReg, TR::RealRegister::NoReg); dependencies->addPostCondition(condReg2, TR::RealRegister::NoReg); diff --git a/compiler/x/codegen/OMRTreeEvaluator.cpp b/compiler/x/codegen/OMRTreeEvaluator.cpp index 763f70e900b..061af915132 100644 --- a/compiler/x/codegen/OMRTreeEvaluator.cpp +++ b/compiler/x/codegen/OMRTreeEvaluator.cpp @@ -1301,7 +1301,8 @@ TR::Register *OMR::X86::TreeEvaluator::SSE2ArraycmpLenEvaluator(TR::Node *node, 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); + TR::Register *highReg = NULL; TR::Register *equalTestReg = cg->allocateRegister(TR_GPR); TR::Register *s2ByteReg = cg->allocateRegister(TR_GPR); TR::Register *byteCounterReg = cg->allocateRegister(TR_GPR); @@ -1312,6 +1313,14 @@ TR::Register *OMR::X86::TreeEvaluator::SSE2ArraycmpLenEvaluator(TR::Node *node, TR::Machine *machine = cg->machine(); + if (cg->comp()->target().is32Bit() && strLenReg->getRegisterPair()) + { + // On 32-bit, the length is guaranteed to fit into the bottom 32 bits + strLenReg = strLenReg->getLowOrder(); + // The high 32 bits will all be zero, so we can save this reg to zero-extend the final result + highReg = strLenReg->getHighOrder(); + } + generateRegImmInstruction(TR::InstOpCode::MOVRegImm4(), node, resultReg, 0, cg); generateLabelInstruction(TR::InstOpCode::label, node, startLabel, cg); generateRegRegInstruction(TR::InstOpCode::MOVRegReg(), node, qwordCounterReg, strLenReg, cg); @@ -1378,6 +1387,17 @@ TR::Register *OMR::X86::TreeEvaluator::SSE2ArraycmpLenEvaluator(TR::Node *node, deps->addPostCondition(s1Reg, TR::RealRegister::NoReg, cg); generateLabelInstruction(TR::InstOpCode::label, node, doneLabel, deps, cg); + + if (cg->comp()->target().is32Bit()) + { + if (highReg == NULL) + { + highReg = cg->allocateRegister(TR_GPR); + generateRegImmInstruction(TR::InstOpCode::MOVRegImm4(), node, highReg, 0, cg); + } + resultReg = cg->allocateRegisterPair(resultReg, highReg); + } + node->setRegister(resultReg); cg->decReferenceCount(s1AddrNode); diff --git a/fvtest/compilertriltest/ArrayTest.cpp b/fvtest/compilertriltest/ArrayTest.cpp index d975dbc12d4..274f82647f1 100644 --- a/fvtest/compilertriltest/ArrayTest.cpp +++ b/fvtest/compilertriltest/ArrayTest.cpp @@ -265,8 +265,9 @@ TEST_P(ArraycmpNotEqualTest, ArraycmpLessThanVariableLen) { EXPECT_EQ(returnValueForArraycmpLessThan, entry_point(&s1[0], &s2[0], length)); } -static std::vector> createArraycmpNotEqualParam() { - std::vector> v; +template +static std::vector> createArraycmpNotEqualParam() { + std::vector> v; /* Small arrays */ for (int i = 1; i < 32; i++) { for (int j = 0; j < i; j++) { @@ -289,7 +290,7 @@ static std::vector> createArraycmpNotEqualParam() { } return v; } -INSTANTIATE_TEST_CASE_P(ArraycmpTest, ArraycmpNotEqualTest, ::testing::ValuesIn(createArraycmpNotEqualParam())); +INSTANTIATE_TEST_CASE_P(ArraycmpTest, ArraycmpNotEqualTest, ::testing::ValuesIn(createArraycmpNotEqualParam())); /** @@ -298,7 +299,7 @@ INSTANTIATE_TEST_CASE_P(ArraycmpTest, ArraycmpNotEqualTest, ::testing::ValuesIn( * @details Used for arraycmplen test with the arrays with same data. * The parameter is the length parameter for the arraycmp evaluator. */ -class ArraycmplenEqualTest : public TRTest::JitTest, public ::testing::WithParamInterface {}; +class ArraycmplenEqualTest : public TRTest::JitTest, public ::testing::WithParamInterface {}; /** * @brief TestFixture class for arraycmplen test * @@ -306,7 +307,7 @@ class ArraycmplenEqualTest : public TRTest::JitTest, public ::testing::WithParam * The first parameter is the length parameter for the arraycmp evaluator. * The second parameter is the offset of the mismatched element in the arrays. */ -class ArraycmplenNotEqualTest : public TRTest::JitTest, public ::testing::WithParamInterface> {}; +class ArraycmplenNotEqualTest : public TRTest::JitTest, public ::testing::WithParamInterface> {}; TEST_P(ArraycmplenEqualTest, ArraycmpLenSameArray) { SKIP_ON_ARM(MissingImplementation); @@ -318,13 +319,13 @@ TEST_P(ArraycmplenEqualTest, ArraycmpLenSameArray) { * "address=0" parameter is needed for arraycmp opcode because "Call" property is set to the opcode. */ std::snprintf(inputTrees, sizeof(inputTrees), - "(method return=Int32 args=[Address, Address]" + "(method return=Int64 args=[Address, Address]" " (block" - " (ireturn" + " (lreturn" " (arraycmplen address=0 args=[Address, Address]" " (aload parm=0)" " (aload parm=1)" - " (iconst %d)))))", + " (lconst %" OMR_PRId64 ")))))", length ); auto trees = parseString(inputTrees); @@ -336,7 +337,7 @@ TEST_P(ArraycmplenEqualTest, ArraycmpLenSameArray) { ASSERT_EQ(0, compiler.compile()) << "Compilation failed unexpectedly\n" << "Input trees: " << inputTrees; std::vector s1(length, 0x5c); - auto entry_point = compiler.getEntryPoint(); + auto entry_point = compiler.getEntryPoint(); EXPECT_EQ(length, entry_point(&s1[0], &s1[0])); } @@ -347,13 +348,13 @@ TEST_P(ArraycmplenEqualTest, ArraycmpLenEqualConstLen) { auto length = GetParam(); char inputTrees[1024] = {0}; std::snprintf(inputTrees, sizeof(inputTrees), - "(method return=Int32 args=[Address, Address]" + "(method return=Int64 args=[Address, Address]" " (block" - " (ireturn" + " (lreturn" " (arraycmplen address=0 args=[Address, Address]" " (aload parm=0)" " (aload parm=1)" - " (iconst %d)))))", + " (lconst %" OMR_PRId64 ")))))", length ); auto trees = parseString(inputTrees); @@ -366,7 +367,7 @@ TEST_P(ArraycmplenEqualTest, ArraycmpLenEqualConstLen) { std::vector s1(length, 0x5c); std::vector s2(length, 0x5c); - auto entry_point = compiler.getEntryPoint(); + auto entry_point = compiler.getEntryPoint(); EXPECT_EQ(length, entry_point(&s1[0], &s2[0])); } @@ -377,13 +378,13 @@ TEST_P(ArraycmplenEqualTest, ArraycmpLenEqualVariableLen) { auto length = GetParam(); char inputTrees[1024] = {0}; std::snprintf(inputTrees, sizeof(inputTrees), - "(method return=Int32 args=[Address, Address, Int32]" + "(method return=Int64 args=[Address, Address, Int64]" " (block" - " (ireturn" + " (lreturn" " (arraycmplen address=0 args=[Address, Address]" " (aload parm=0)" " (aload parm=1)" - " (iload parm=2)))))" + " (lload parm=2)))))" ); auto trees = parseString(inputTrees); @@ -395,11 +396,11 @@ TEST_P(ArraycmplenEqualTest, ArraycmpLenEqualVariableLen) { std::vector s1(length, 0x5c); std::vector s2(length, 0x5c); - auto entry_point = compiler.getEntryPoint(); + auto entry_point = compiler.getEntryPoint(); EXPECT_EQ(length, entry_point(&s1[0], &s2[0], length)); } -INSTANTIATE_TEST_CASE_P(ArraycmplenTest, ArraycmplenEqualTest, ::testing::Range(1L, 128L)); +INSTANTIATE_TEST_CASE_P(ArraycmplenTest, ArraycmplenEqualTest, ::testing::Range(static_cast(1), static_cast(128))); TEST_P(ArraycmplenNotEqualTest, ArraycmpLenNotEqualConstLen) { SKIP_ON_ARM(MissingImplementation); @@ -409,13 +410,13 @@ TEST_P(ArraycmplenNotEqualTest, ArraycmpLenNotEqualConstLen) { auto offset = std::get<1>(GetParam()); char inputTrees[1024] = {0}; std::snprintf(inputTrees, sizeof(inputTrees), - "(method return=Int32 args=[Address, Address]" + "(method return=Int64 args=[Address, Address]" " (block" - " (ireturn" + " (lreturn" " (arraycmplen address=0 args=[Address, Address]" " (aload parm=0)" " (aload parm=1)" - " (iconst %d)))))", + " (lconst %" OMR_PRId64 ")))))", length ); auto trees = parseString(inputTrees); @@ -430,7 +431,7 @@ TEST_P(ArraycmplenNotEqualTest, ArraycmpLenNotEqualConstLen) { std::vector s2(length, 0x5c); s1[offset] = 0x3f; - auto entry_point = compiler.getEntryPoint(); + auto entry_point = compiler.getEntryPoint(); EXPECT_EQ(offset, entry_point(&s1[0], &s2[0])); } @@ -442,13 +443,13 @@ TEST_P(ArraycmplenNotEqualTest, ArraycmpLenNotEqualVariableLen) { auto offset = std::get<1>(GetParam()); char inputTrees[1024] = {0}; std::snprintf(inputTrees, sizeof(inputTrees), - "(method return=Int32 args=[Address, Address, Int32]" + "(method return=Int64 args=[Address, Address, Int64]" " (block" - " (ireturn" + " (lreturn" " (arraycmplen address=0 args=[Address, Address]" " (aload parm=0)" " (aload parm=1)" - " (iload parm=2)))))" + " (lload parm=2)))))" ); auto trees = parseString(inputTrees); @@ -462,8 +463,8 @@ TEST_P(ArraycmplenNotEqualTest, ArraycmpLenNotEqualVariableLen) { std::vector s2(length, 0x5c); s1[offset] = 0x3f; - auto entry_point = compiler.getEntryPoint(); + auto entry_point = compiler.getEntryPoint(); EXPECT_EQ(offset, entry_point(&s1[0], &s2[0], length)); } -INSTANTIATE_TEST_CASE_P(ArraycmplenTest, ArraycmplenNotEqualTest, ::testing::ValuesIn(createArraycmpNotEqualParam())); +INSTANTIATE_TEST_CASE_P(ArraycmplenTest, ArraycmplenNotEqualTest, ::testing::ValuesIn(createArraycmpNotEqualParam()));