@@ -5068,7 +5068,7 @@ void Compiler::optPerformStaticOptimizations(unsigned loopNum, LoopCloneContext*
5068
5068
{
5069
5069
LcJaggedArrayOptInfo* arrIndexInfo = optInfo->AsLcJaggedArrayOptInfo ();
5070
5070
compCurBB = arrIndexInfo->arrIndex .useBlock ;
5071
- optRemoveRangeCheck (arrIndexInfo->arrIndex .bndsChks [arrIndexInfo->dim ], arrIndexInfo->stmt );
5071
+ optRemoveCommaBasedRangeCheck (arrIndexInfo->arrIndex .bndsChks [arrIndexInfo->dim ], arrIndexInfo->stmt );
5072
5072
DBEXEC (dynamicPath, optDebugLogLoopCloning (arrIndexInfo->arrIndex .useBlock , arrIndexInfo->stmt ));
5073
5073
}
5074
5074
break ;
@@ -8211,24 +8211,34 @@ void Compiler::AddModifiedElemTypeAllContainingLoops(unsigned lnum, CORINFO_CLAS
8211
8211
}
8212
8212
8213
8213
// ------------------------------------------------------------------------------
8214
- // optRemoveRangeCheck : Given an array index node, mark it as not needing a range check.
8214
+ // optRemoveRangeCheck : Given an indexing node, mark it as not needing a range check.
8215
8215
//
8216
8216
// Arguments:
8217
- // tree - Range check tree
8218
- // stmt - Statement the tree belongs to
8219
-
8220
- void Compiler::optRemoveRangeCheck (GenTree* tree, Statement* stmt)
8217
+ // check - Range check tree, the raw CHECK node (ARRAY, SIMD or HWINTRINSIC).
8218
+ // comma - GT_COMMA to which the "check" belongs, "nullptr" if the check is a standalone one.
8219
+ // stmt - Statement the indexing nodes belongs to.
8220
+ //
8221
+ // Return Value:
8222
+ // Rewritten "check" - no-op if it has no side effects or the tree that contains them.
8223
+ //
8224
+ // Assumptions:
8225
+ // This method is capable of removing checks of two kinds: COMMA-based and standalone top-level ones.
8226
+ // In case of a COMMA-based check, "check" must be a non-null first operand of a non-null COMMA.
8227
+ // If case of a standalone check, "comma" must be null and "check" - "stmt"'s root.
8228
+ //
8229
+ GenTree* Compiler::optRemoveRangeCheck (GenTreeBoundsChk* check, GenTree* comma, Statement* stmt)
8221
8230
{
8222
8231
#if !REARRANGE_ADDS
8223
8232
noway_assert (!" can't remove range checks without REARRANGE_ADDS right now" );
8224
8233
#endif
8225
8234
8226
- noway_assert (tree->gtOper == GT_COMMA);
8227
-
8228
- GenTree* bndsChkTree = tree->AsOp ()->gtOp1 ;
8229
-
8230
- noway_assert (bndsChkTree->OperIsBoundsCheck ());
8235
+ noway_assert (stmt != nullptr );
8236
+ noway_assert ((comma != nullptr && comma->OperIs (GT_COMMA) && comma->gtGetOp1 () == check) ||
8237
+ (check != nullptr && check->OperIsBoundsCheck () && comma == nullptr ));
8238
+ noway_assert (check->OperIsBoundsCheck ());
8231
8239
8240
+ GenTree* tree = comma != nullptr ? comma : check;
8241
+
8232
8242
#ifdef DEBUG
8233
8243
if (verbose)
8234
8244
{
@@ -8239,19 +8249,40 @@ void Compiler::optRemoveRangeCheck(GenTree* tree, Statement* stmt)
8239
8249
8240
8250
// Extract side effects
8241
8251
GenTree* sideEffList = nullptr ;
8242
- gtExtractSideEffList (bndsChkTree, &sideEffList, GTF_ASG);
8252
+ gtExtractSideEffList (check, &sideEffList, GTF_ASG);
8253
+
8254
+ if (sideEffList != nullptr )
8255
+ {
8256
+ // We've got some side effects.
8257
+ if (tree->OperIs (GT_COMMA))
8258
+ {
8259
+ // Make the comma handle them.
8260
+ tree->AsOp ()->gtOp1 = sideEffList;
8261
+ }
8262
+ else
8263
+ {
8264
+ // Make the statement execute them instead of the check.
8265
+ stmt->SetRootNode (sideEffList);
8266
+ tree = sideEffList;
8267
+ }
8268
+ }
8269
+ else
8270
+ {
8271
+ check->gtBashToNOP ();
8272
+ }
8243
8273
8244
- // Just replace the bndsChk with a NOP as an operand to the GT_COMMA, if there are no side effects.
8245
- tree->AsOp ()->gtOp1 = (sideEffList != nullptr ) ? sideEffList : gtNewNothingNode ();
8246
- // TODO-CQ: We should also remove the GT_COMMA, but in any case we can no longer CSE the GT_COMMA.
8247
- tree->gtFlags |= GTF_DONT_CSE;
8274
+ if (tree->OperIs (GT_COMMA))
8275
+ {
8276
+ // TODO-CQ: We should also remove the GT_COMMA, but in any case we can no longer CSE the GT_COMMA.
8277
+ tree->gtFlags |= GTF_DONT_CSE;
8278
+ }
8248
8279
8249
8280
gtUpdateSideEffects (stmt, tree);
8250
8281
8251
- /* Recalculate the GetCostSz(), etc... */
8282
+ // Recalculate the GetCostSz(), etc...
8252
8283
gtSetStmtInfo (stmt);
8253
8284
8254
- /* Re-thread the nodes if necessary */
8285
+ // Re-thread the nodes if necessary
8255
8286
if (fgStmtListThreaded)
8256
8287
{
8257
8288
fgSetStmtSeq (stmt);
@@ -8264,6 +8295,32 @@ void Compiler::optRemoveRangeCheck(GenTree* tree, Statement* stmt)
8264
8295
gtDispTree (tree);
8265
8296
}
8266
8297
#endif
8298
+
8299
+ return check;
8300
+ }
8301
+
8302
+ // ------------------------------------------------------------------------------
8303
+ // optRemoveStandaloneRangeCheck : A thin wrapper over optRemoveRangeCheck that removes standalone checks.
8304
+ //
8305
+ GenTree* Compiler::optRemoveStandaloneRangeCheck (GenTreeBoundsChk* check, Statement* stmt)
8306
+ {
8307
+ assert (check != nullptr );
8308
+ assert (stmt != nullptr );
8309
+ assert (check == stmt->GetRootNode ());
8310
+
8311
+ return optRemoveRangeCheck (check, nullptr , stmt);
8312
+ }
8313
+
8314
+ // ------------------------------------------------------------------------------
8315
+ // optRemoveCommaBasedRangeCheck : A thin wrapper over optRemoveRangeCheck that removes COMMA-based checks.
8316
+ //
8317
+ void Compiler::optRemoveCommaBasedRangeCheck (GenTree* comma, Statement* stmt)
8318
+ {
8319
+ assert (comma != nullptr );
8320
+ assert (stmt != nullptr );
8321
+ assert (comma->gtGetOp1 ()->OperIsBoundsCheck ());
8322
+
8323
+ optRemoveRangeCheck (comma->gtGetOp1 ()->AsBoundsChk (), comma, stmt);
8267
8324
}
8268
8325
8269
8326
/* ****************************************************************************
0 commit comments