@@ -1014,7 +1014,7 @@ void RangeCheck::MergeAssertion(BasicBlock* block, GenTree* op, Range* pRange DE
1014
1014
// Compute the range for a binary operation.
1015
1015
Range RangeCheck::ComputeRangeForBinOp (BasicBlock* block, GenTreeOp* binop, bool monIncreasing DEBUGARG (int indent))
1016
1016
{
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));
1018
1018
1019
1019
GenTree* op1 = binop->gtGetOp1 ();
1020
1020
GenTree* op2 = binop->gtGetOp2 ();
@@ -1036,7 +1036,7 @@ Range RangeCheck::ComputeRangeForBinOp(BasicBlock* block, GenTreeOp* binop, bool
1036
1036
}
1037
1037
1038
1038
// 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))
1040
1040
{
1041
1041
if (!op2IsCns)
1042
1042
{
@@ -1073,6 +1073,25 @@ Range RangeCheck::ComputeRangeForBinOp(BasicBlock* block, GenTreeOp* binop, bool
1073
1073
icon = binop->OperIs (GT_RSH) ? (icon1 >> icon2) : (icon1 << icon2);
1074
1074
}
1075
1075
}
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
+ }
1076
1095
1077
1096
if (icon >= 0 )
1078
1097
{
@@ -1088,7 +1107,7 @@ Range RangeCheck::ComputeRangeForBinOp(BasicBlock* block, GenTreeOp* binop, bool
1088
1107
}
1089
1108
1090
1109
// 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 ));
1092
1111
1093
1112
Range* op1RangeCached = nullptr ;
1094
1113
Range op1Range = Limit (Limit::keUndef);
@@ -1453,7 +1472,7 @@ bool RangeCheck::ComputeDoesOverflow(BasicBlock* block, GenTree* expr, const Ran
1453
1472
}
1454
1473
// These operators don't overflow.
1455
1474
// 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))
1457
1476
{
1458
1477
overflows = false ;
1459
1478
}
@@ -1547,7 +1566,7 @@ Range RangeCheck::ComputeRange(BasicBlock* block, GenTree* expr, bool monIncreas
1547
1566
MergeAssertion (block, expr, &range DEBUGARG (indent + 1 ));
1548
1567
}
1549
1568
// 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))
1551
1570
{
1552
1571
range = ComputeRangeForBinOp (block, expr->AsOp (), monIncreasing DEBUGARG (indent + 1 ));
1553
1572
}
0 commit comments