@@ -1014,7 +1014,7 @@ void RangeCheck::MergeAssertion(BasicBlock* block, GenTree* op, Range* pRange DE
10141014// Compute the range for a binary operation.
10151015Range RangeCheck::ComputeRangeForBinOp (BasicBlock* block, GenTreeOp* binop, bool monIncreasing DEBUGARG (int indent))
10161016{
1017- assert (binop->OperIs (GT_ADD, GT_AND, GT_RSH, GT_LSH, GT_UMOD, GT_MUL));
1017+ assert (binop->OperIs (GT_ADD, GT_AND, GT_RSH, GT_RSZ, GT_LSH, GT_UMOD, GT_MUL));
10181018
10191019 GenTree* op1 = binop->gtGetOp1 ();
10201020 GenTree* op2 = binop->gtGetOp2 ();
@@ -1036,7 +1036,7 @@ Range RangeCheck::ComputeRangeForBinOp(BasicBlock* block, GenTreeOp* binop, bool
10361036 }
10371037
10381038 // Special cases for binops where op2 is a constant
1039- if (binop->OperIs (GT_AND, GT_RSH, GT_LSH, GT_UMOD))
1039+ if (binop->OperIs (GT_AND, GT_RSH, GT_RSZ, GT_LSH, GT_UMOD))
10401040 {
10411041 if (!op2IsCns)
10421042 {
@@ -1073,6 +1073,25 @@ Range RangeCheck::ComputeRangeForBinOp(BasicBlock* block, GenTreeOp* binop, bool
10731073 icon = binop->OperIs (GT_RSH) ? (icon1 >> icon2) : (icon1 << icon2);
10741074 }
10751075 }
1076+ else if (binop->OperIs (GT_RSZ))
1077+ {
1078+ // (x u>> cns) -> [0..(x's max value >> cns)]
1079+ int shiftBy = static_cast <int >(op2->AsIntCon ()->IconValue ());
1080+ if (shiftBy < 0 )
1081+ {
1082+ return Range (Limit::keUnknown);
1083+ }
1084+
1085+ int op1Width = (int )(genTypeSize (op1) * BITS_PER_BYTE);
1086+ if (shiftBy >= op1Width)
1087+ {
1088+ return Range (Limit (Limit::keConstant, 0 ));
1089+ }
1090+
1091+ // Calculate max possible value of op1, e.g. UINT_MAX for TYP_INT/TYP_UINT
1092+ uint64_t maxValue = (1ULL << op1Width) - 1 ;
1093+ icon = (int )(maxValue >> static_cast <int >(op2->AsIntCon ()->IconValue ()));
1094+ }
10761095
10771096 if (icon >= 0 )
10781097 {
@@ -1088,7 +1107,7 @@ Range RangeCheck::ComputeRangeForBinOp(BasicBlock* block, GenTreeOp* binop, bool
10881107 }
10891108
10901109 // other operators are expected to be handled above.
1091- assert (binop->OperIs (GT_ADD, GT_MUL, GT_LSH, GT_RSH));
1110+ assert (binop->OperIs (GT_ADD, GT_MUL, GT_LSH, GT_RSH, GT_RSZ ));
10921111
10931112 Range* op1RangeCached = nullptr ;
10941113 Range op1Range = Limit (Limit::keUndef);
@@ -1453,7 +1472,7 @@ bool RangeCheck::ComputeDoesOverflow(BasicBlock* block, GenTree* expr, const Ran
14531472 }
14541473 // These operators don't overflow.
14551474 // Actually, GT_LSH can overflow so it depends on the analysis done in ComputeRangeForBinOp
1456- else if (expr->OperIs (GT_AND, GT_RSH, GT_LSH, GT_UMOD, GT_NEG))
1475+ else if (expr->OperIs (GT_AND, GT_RSH, GT_RSZ, GT_LSH, GT_UMOD, GT_NEG))
14571476 {
14581477 overflows = false ;
14591478 }
@@ -1547,7 +1566,7 @@ Range RangeCheck::ComputeRange(BasicBlock* block, GenTree* expr, bool monIncreas
15471566 MergeAssertion (block, expr, &range DEBUGARG (indent + 1 ));
15481567 }
15491568 // compute the range for binary operation
1550- else if (expr->OperIs (GT_ADD, GT_AND, GT_RSH, GT_LSH, GT_UMOD, GT_MUL))
1569+ else if (expr->OperIs (GT_ADD, GT_AND, GT_RSH, GT_RSZ, GT_LSH, GT_UMOD, GT_MUL))
15511570 {
15521571 range = ComputeRangeForBinOp (block, expr->AsOp (), monIncreasing DEBUGARG (indent + 1 ));
15531572 }
0 commit comments