noway_assert(oper->OperIsBoundsCheck());
GenTreeBoundsChk* bndsChk = oper->AsBoundsChk();
- GenTree* arrIndex = bndsChk->gtIndex;
- GenTree* arrLen = bndsChk->gtArrLen;
- GenTree* arrRef = nullptr;
- int lenOffset = 0;
+ GenTree* arrIndex = bndsChk->gtIndex;
+ GenTree* arrLen = bndsChk->gtArrLen;
GenTree * src1, *src2;
emitJumpKind jmpKind;
+ instruction cmpKind;
genConsumeRegs(arrIndex);
genConsumeRegs(arrLen);
- if (arrIndex->isContainedIntOrIImmed())
+ if (arrIndex->IsIntegralConst(0) && arrLen->isUsedFromReg())
+ {
+ // arrIndex is 0 and arrLen is in a reg. In this case
+ // we can generate
+ // test reg, reg
+ // since arrLen is non-negative
+ src1 = arrLen;
+ src2 = arrLen;
+ jmpKind = EJ_je;
+ cmpKind = INS_test;
+ }
+ else if (arrIndex->isContainedIntOrIImmed())
{
// arrIndex is a contained constant. In this case
// we will generate one of the following
src1 = arrLen;
src2 = arrIndex;
jmpKind = EJ_jbe;
+ cmpKind = INS_cmp;
}
else
{
// cmp [mem], immed (if arrLen is a constant)
// cmp [mem], reg (if arrLen is in a reg)
// cmp reg, immed (if arrIndex is in a reg)
- // cmp reg1, reg2 (if arraIndex is in reg1)
+ // cmp reg1, reg2 (if arrIndex is in reg1)
// cmp reg, [mem] (if arrLen is a memory op)
//
// That is only one of arrIndex or arrLen can be a memory op.
src1 = arrIndex;
src2 = arrLen;
jmpKind = EJ_jae;
+ cmpKind = INS_cmp;
}
var_types bndsChkType = src2->TypeGet();
assert(emitTypeSize(bndsChkType) >= emitTypeSize(src1->TypeGet()));
#endif // DEBUG
- GetEmitter()->emitInsBinary(INS_cmp, emitTypeSize(bndsChkType), src1, src2);
+ GetEmitter()->emitInsBinary(cmpKind, emitTypeSize(bndsChkType), src1, src2);
genJumpToThrowHlpBlk(jmpKind, bndsChk->gtThrowKind, bndsChk->gtIndRngFailBB);
}