diff --git a/src/coreclr/jit/codegen.h b/src/coreclr/jit/codegen.h index f86d7db1e6b305..cefb5f5c2052e5 100644 --- a/src/coreclr/jit/codegen.h +++ b/src/coreclr/jit/codegen.h @@ -1552,6 +1552,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #if defined(TARGET_ARM64) static insCond JumpKindToInsCond(emitJumpKind condition); + static insOpts ShiftOpToInsOpts(genTreeOps op); #elif defined(TARGET_XARCH) static instruction JumpKindToCmov(emitJumpKind condition); #endif diff --git a/src/coreclr/jit/codegenarm64.cpp b/src/coreclr/jit/codegenarm64.cpp index 6b1a20565dec2c..e8c067ac07ccff 100644 --- a/src/coreclr/jit/codegenarm64.cpp +++ b/src/coreclr/jit/codegenarm64.cpp @@ -2626,31 +2626,7 @@ void CodeGen::genCodeForBinary(GenTreeOp* tree) } } - switch (op2->gtOper) - { - case GT_LSH: - { - opt = INS_OPTS_LSL; - break; - } - - case GT_RSH: - { - opt = INS_OPTS_ASR; - break; - } - - case GT_RSZ: - { - opt = INS_OPTS_LSR; - break; - } - - default: - { - unreached(); - } - } + opt = ShiftOpToInsOpts(op2->gtOper); emit->emitIns_R_R_R_I(ins, emitActualTypeSize(tree), targetReg, a->GetRegNum(), b->GetRegNum(), c->AsIntConCommon()->IconValue(), opt); @@ -4546,6 +4522,15 @@ void CodeGen::genCodeForCompare(GenTreeOp* tree) emit->emitIns_R_I(ins, cmpSize, op1Reg, intConst->IconValue()); } + else if (op2->isContained()) + { + assert(op2->OperIs(GT_LSH, GT_RSH, GT_RSZ)); + assert(op2->gtGetOp2()->IsCnsIntOrI()); + assert(op2->gtGetOp2()->isContained()); + + emit->emitIns_R_R_I(ins, cmpSize, op1->GetRegNum(), op2->gtGetOp1()->GetRegNum(), + op2->gtGetOp2()->AsIntConCommon()->IntegralValue(), ShiftOpToInsOpts(op2->gtOper)); + } else { emit->emitIns_R_R(ins, cmpSize, op1->GetRegNum(), op2->GetRegNum()); @@ -10329,4 +10314,29 @@ insCond CodeGen::JumpKindToInsCond(emitJumpKind condition) } } +//------------------------------------------------------------------------ +// ShiftOpToInsOpts: Convert a shift-op to a insOpts. +// +// Arguments: +// shiftOp - the shift-op +// +insOpts CodeGen::ShiftOpToInsOpts(genTreeOps shiftOp) +{ + switch (shiftOp) + { + case GT_LSH: + return INS_OPTS_LSL; + + case GT_RSH: + return INS_OPTS_ASR; + + case GT_RSZ: + return INS_OPTS_LSR; + + default: + NO_WAY("expected a shift-op"); + return INS_OPTS_NONE; + } +} + #endif // TARGET_ARM64 diff --git a/src/coreclr/jit/lowerarmarch.cpp b/src/coreclr/jit/lowerarmarch.cpp index 0a9f57f5469264..8ebb2c044a7f7c 100644 --- a/src/coreclr/jit/lowerarmarch.cpp +++ b/src/coreclr/jit/lowerarmarch.cpp @@ -269,7 +269,7 @@ bool Lowering::IsContainableBinaryOp(GenTree* parentNode, GenTree* childNode) co return false; } - if (parentNode->OperIs(GT_CMP, GT_OR, GT_XOR)) + if (parentNode->OperIs(GT_CMP, GT_OR, GT_XOR) || parentNode->OperIsCompare()) { if (IsInvariantInRange(childNode, parentNode)) { @@ -2264,7 +2264,37 @@ void Lowering::ContainCheckCast(GenTreeCast* node) // void Lowering::ContainCheckCompare(GenTreeOp* cmp) { - CheckImmedAndMakeContained(cmp, cmp->gtOp2); + GenTree* op1 = cmp->gtGetOp1(); + GenTree* op2 = cmp->gtGetOp2(); + + if (CheckImmedAndMakeContained(cmp, op2)) + return; + + if (cmp->OperIsCompare() && CheckImmedAndMakeContained(cmp, op1)) + { + std::swap(cmp->gtOp1, cmp->gtOp2); + cmp->ChangeOper(cmp->SwapRelop(cmp->gtOper)); + return; + } + +#ifdef TARGET_ARM64 + if (comp->opts.OptimizationEnabled() && cmp->OperIsCompare()) + { + if (IsContainableBinaryOp(cmp, op2)) + { + MakeSrcContained(cmp, op2); + return; + } + + if (IsContainableBinaryOp(cmp, op1)) + { + MakeSrcContained(cmp, op1); + std::swap(cmp->gtOp1, cmp->gtOp2); + cmp->ChangeOper(cmp->SwapRelop(cmp->gtOper)); + return; + } + } +#endif } #ifdef TARGET_ARM64