@@ -1636,8 +1636,35 @@ AssertionIndex Compiler::optCreateAssertion(GenTree* op1,
16361636 //
16371637 // Copy Assertions
16381638 //
1639+ case GT_OBJ:
1640+ case GT_BLK:
1641+ {
1642+ // TODO-ADDR: delete once local morph folds SIMD-typed indirections.
1643+ //
1644+ GenTree* const addr = op2->AsIndir ()->Addr ();
1645+
1646+ if (addr->OperIs (GT_ADDR))
1647+ {
1648+ GenTree* const base = addr->AsOp ()->gtOp1 ;
1649+
1650+ if (base->OperIs (GT_LCL_VAR) && varTypeIsStruct (base))
1651+ {
1652+ ClassLayout* const varLayout = base->GetLayout (this );
1653+ ClassLayout* const objLayout = op2->GetLayout (this );
1654+ if (ClassLayout::AreCompatible (varLayout, objLayout))
1655+ {
1656+ op2 = base;
1657+ goto IS_COPY;
1658+ }
1659+ }
1660+ }
1661+
1662+ goto DONE_ASSERTION;
1663+ }
1664+
16391665 case GT_LCL_VAR:
16401666 {
1667+ IS_COPY:
16411668 //
16421669 // Must either be an OAK_EQUAL or an OAK_NOT_EQUAL assertion
16431670 //
@@ -3416,7 +3443,14 @@ bool Compiler::optZeroObjAssertionProp(GenTree* tree, ASSERT_VALARG_TP assertion
34163443 return false ;
34173444 }
34183445
3419- unsigned lclNum = tree->AsLclVar ()->GetLclNum ();
3446+ // No ZEROOBJ assertions for simd.
3447+ //
3448+ if (varTypeIsSIMD (tree))
3449+ {
3450+ return false ;
3451+ }
3452+
3453+ const unsigned lclNum = tree->AsLclVar ()->GetLclNum ();
34203454 AssertionIndex assertionIndex = optLocalAssertionIsEqualOrNotEqual (O1K_LCLVAR, lclNum, O2K_ZEROOBJ, 0 , assertions);
34213455 if (assertionIndex == NO_ASSERTION_INDEX)
34223456 {
@@ -3568,6 +3602,20 @@ GenTree* Compiler::optCopyAssertionProp(AssertionDsc* curAssertion,
35683602 return nullptr ;
35693603 }
35703604
3605+ // Heuristic: for LclFld prop, don't force the copy or its promoted fields to be in memory.
3606+ //
3607+ if (tree->OperIs (GT_LCL_FLD))
3608+ {
3609+ if (copyVarDsc->IsEnregisterableLcl () || copyVarDsc->lvPromotedStruct ())
3610+ {
3611+ return nullptr ;
3612+ }
3613+ else
3614+ {
3615+ lvaSetVarDoNotEnregister (copyLclNum DEBUGARG (DoNotEnregisterReason::LocalField));
3616+ }
3617+ }
3618+
35713619 tree->SetLclNum (copyLclNum);
35723620 tree->SetSsaNum (copySsaNum);
35733621
@@ -3689,6 +3737,71 @@ GenTree* Compiler::optAssertionProp_LclVar(ASSERT_VALARG_TP assertions, GenTreeL
36893737 return nullptr ;
36903738}
36913739
3740+ // ------------------------------------------------------------------------
3741+ // optAssertionProp_LclFld: try and optimize a local field use via assertions
3742+ //
3743+ // Arguments:
3744+ // assertions - set of live assertions
3745+ // tree - local field use to optimize
3746+ // stmt - statement containing the tree
3747+ //
3748+ // Returns:
3749+ // Updated tree, or nullptr
3750+ //
3751+ // Notes:
3752+ // stmt may be nullptr during local assertion prop
3753+ //
3754+ GenTree* Compiler::optAssertionProp_LclFld (ASSERT_VALARG_TP assertions, GenTreeLclVarCommon* tree, Statement* stmt)
3755+ {
3756+ // If we have a var definition then bail or
3757+ // If this is the address of the var then it will have the GTF_DONT_CSE
3758+ // flag set and we don't want to to assertion prop on it.
3759+ if (tree->gtFlags & (GTF_VAR_DEF | GTF_DONT_CSE))
3760+ {
3761+ return nullptr ;
3762+ }
3763+
3764+ // Only run during local prop and if copies are available.
3765+ //
3766+ if (!optLocalAssertionProp || !optCanPropLclVar)
3767+ {
3768+ return nullptr ;
3769+ }
3770+
3771+ BitVecOps::Iter iter (apTraits, assertions);
3772+ unsigned index = 0 ;
3773+ while (iter.NextElem (&index))
3774+ {
3775+ AssertionIndex assertionIndex = GetAssertionIndex (index);
3776+ if (assertionIndex > optAssertionCount)
3777+ {
3778+ break ;
3779+ }
3780+
3781+ // See if the variable is equal to another variable.
3782+ AssertionDsc* curAssertion = optGetAssertion (assertionIndex);
3783+ if (!curAssertion->CanPropLclVar ())
3784+ {
3785+ continue ;
3786+ }
3787+
3788+ // Copy prop.
3789+ if (curAssertion->op2 .kind == O2K_LCLVAR_COPY)
3790+ {
3791+ // Perform copy assertion prop.
3792+ GenTree* newTree = optCopyAssertionProp (curAssertion, tree, stmt DEBUGARG (assertionIndex));
3793+ if (newTree != nullptr )
3794+ {
3795+ return newTree;
3796+ }
3797+ }
3798+
3799+ continue ;
3800+ }
3801+
3802+ return nullptr ;
3803+ }
3804+
36923805// ------------------------------------------------------------------------
36933806// optAssertionProp_Asg: Try and optimize an assignment via assertions.
36943807//
@@ -4916,6 +5029,9 @@ GenTree* Compiler::optAssertionProp(ASSERT_VALARG_TP assertions, GenTree* tree,
49165029 case GT_LCL_VAR:
49175030 return optAssertionProp_LclVar (assertions, tree->AsLclVarCommon (), stmt);
49185031
5032+ case GT_LCL_FLD:
5033+ return optAssertionProp_LclFld (assertions, tree->AsLclVarCommon (), stmt);
5034+
49195035 case GT_ASG:
49205036 return optAssertionProp_Asg (assertions, tree->AsOp (), stmt);
49215037
0 commit comments