@@ -2663,6 +2663,60 @@ AssertionIndex Compiler::optAssertionIsSubtype(GenTree* tree, GenTree* methodTab
26632663 return NO_ASSERTION_INDEX;
26642664}
26652665
2666+ // ------------------------------------------------------------------------------
2667+ // optVNStrengthReductionOnTree:
2668+ //
2669+ // Arguments:
2670+ // block - The block containing the tree.
2671+ // parent - The parent node of the tree.
2672+ // tree - The tree node
2673+ //
2674+ // Return Value:
2675+ // Returns a new tree or nullptr if nothing is changed.
2676+ //
2677+ GenTree* Compiler::optVNStrengthReductionOnTree (BasicBlock* block, GenTree* parent, GenTree* tree)
2678+ {
2679+ if (tree->IsHelperCall ())
2680+ {
2681+ GenTreeCall* call = tree->AsCall ();
2682+ switch (call->GetHelperNum ())
2683+ {
2684+ // Fold "cast(cast(obj, cls), cls)" to "cast(obj, cls)"
2685+ case CORINFO_HELP_CHKCASTARRAY:
2686+ case CORINFO_HELP_CHKCASTANY:
2687+ case CORINFO_HELP_CHKCASTINTERFACE:
2688+ case CORINFO_HELP_CHKCASTCLASS:
2689+ case CORINFO_HELP_ISINSTANCEOFARRAY:
2690+ case CORINFO_HELP_ISINSTANCEOFCLASS:
2691+ case CORINFO_HELP_ISINSTANCEOFANY:
2692+ case CORINFO_HELP_ISINSTANCEOFINTERFACE:
2693+ {
2694+ GenTree* clsArg = call->gtArgs .GetUserArgByIndex (0 )->GetNode ();
2695+ GenTree* objArg = call->gtArgs .GetUserArgByIndex (1 )->GetNode ();
2696+ ValueNum clsArgVN = clsArg->gtVNPair .GetConservative ();
2697+ ValueNum objArgVN = objArg->gtVNPair .GetConservative ();
2698+
2699+ VNFuncApp funcApp;
2700+ if (vnStore->GetVNFunc (objArgVN, &funcApp) &&
2701+ ((funcApp.m_func == VNF_CastClass) || (funcApp.m_func == VNF_IsInstanceOf)) &&
2702+ (funcApp.m_args [0 ] == clsArgVN))
2703+ {
2704+ // The outer cast is redundant, remove it and preserve its side effects
2705+ // We do ignoreRoot here because the actual cast node is proven to never any exceptions
2706+ // (namely, InvalidCastException).
2707+ return gtWrapWithSideEffects (objArg, call, GTF_ALL_EFFECT, true );
2708+ }
2709+ }
2710+ break ;
2711+
2712+ default :
2713+ break ;
2714+ }
2715+ }
2716+
2717+ return nullptr ;
2718+ }
2719+
26662720// ------------------------------------------------------------------------------
26672721// optVNConstantPropOnTree: Substitutes tree with an evaluated constant while
26682722// managing side-effects.
@@ -5098,41 +5152,30 @@ GenTree* Compiler::optAssertionProp_Call(ASSERT_VALARG_TP assertions, GenTreeCal
50985152 (helper == CORINFO_HELP_CHKCASTCLASS) || (helper == CORINFO_HELP_CHKCASTANY) ||
50995153 (helper == CORINFO_HELP_CHKCASTCLASS_SPECIAL))
51005154 {
5101- GenTree* arg1 = call->gtArgs .GetArgByIndex (1 )->GetNode ();
5102- if (arg1->gtOper != GT_LCL_VAR)
5155+ GenTree* objArg = call->gtArgs .GetArgByIndex (1 )->GetNode ();
5156+ GenTree* clsArg = call->gtArgs .GetArgByIndex (0 )->GetNode ();
5157+
5158+ if (objArg->gtOper != GT_LCL_VAR)
51035159 {
51045160 return nullptr ;
51055161 }
51065162
5107- GenTree* arg2 = call->gtArgs .GetArgByIndex (0 )->GetNode ();
5108-
5109- unsigned index = optAssertionIsSubtype (arg1, arg2, assertions);
5163+ unsigned index = optAssertionIsSubtype (objArg, clsArg, assertions);
51105164 if (index != NO_ASSERTION_INDEX)
51115165 {
5112- #ifdef DEBUG
5113- if (verbose)
5114- {
5115- printf (" \n Did VN based subtype prop for index #%02u in " FMT_BB " :\n " , index, compCurBB->bbNum );
5116- gtDispTree (call, nullptr , nullptr , true );
5117- }
5118- #endif
5119- GenTree* list = nullptr ;
5120- gtExtractSideEffList (call, &list, GTF_SIDE_EFFECT, true );
5121- if (list != nullptr )
5122- {
5123- arg1 = gtNewOperNode (GT_COMMA, call->TypeGet (), list, arg1);
5124- fgSetTreeSeq (arg1);
5125- }
5166+ JITDUMP (" \n Did VN based subtype prop for index #%02u in " FMT_BB " :\n " , index, compCurBB->bbNum );
5167+ DISPTREE (call);
51265168
5127- return optAssertionProp_Update (arg1, call, stmt);
5169+ objArg = gtWrapWithSideEffects (objArg, call, GTF_SIDE_EFFECT, true );
5170+ return optAssertionProp_Update (objArg, call, stmt);
51285171 }
51295172
51305173 // Leave a hint for fgLateCastExpansion that obj is never null.
51315174 INDEBUG (AssertionIndex nonNullIdx = NO_ASSERTION_INDEX);
51325175 INDEBUG (bool vnBased = false );
51335176 // GTF_CALL_M_CAST_CAN_BE_EXPANDED check is to improve TP
51345177 if (((call->gtCallMoreFlags & GTF_CALL_M_CAST_CAN_BE_EXPANDED) != 0 ) &&
5135- optAssertionIsNonNull (arg1 , assertions DEBUGARG (&vnBased) DEBUGARG (&nonNullIdx)))
5178+ optAssertionIsNonNull (objArg , assertions DEBUGARG (&vnBased) DEBUGARG (&nonNullIdx)))
51365179 {
51375180 call->gtCallMoreFlags |= GTF_CALL_M_CAST_OBJ_NONNULL;
51385181 return optAssertionProp_Update (call, call, stmt);
@@ -6419,8 +6462,14 @@ Compiler::fgWalkResult Compiler::optVNConstantPropCurStmt(BasicBlock* block,
64196462
64206463 if (newTree == nullptr )
64216464 {
6422- // Not propagated, keep going.
6423- return WALK_CONTINUE;
6465+ // If it wasn't a constant, let's see if we can reduce the strength
6466+ // of the tree using VN.
6467+ newTree = optVNStrengthReductionOnTree (block, parent, tree);
6468+ if (newTree == nullptr )
6469+ {
6470+ // Not propagated, keep going.
6471+ return WALK_CONTINUE;
6472+ }
64246473 }
64256474
64266475 // TODO https://github.com/dotnet/runtime/issues/10450:
0 commit comments