@@ -78,34 +78,20 @@ bool Lowering::CheckImmedAndMakeContained(GenTree* parentNode, GenTree* childNod
78
78
// and returns 'true' iff memory operand childNode can be contained in parentNode.
79
79
//
80
80
// Arguments:
81
- // parentNode - a non-leaf binary node
82
- // childNode - a memory op that is a child op of ' parentNode'
81
+ // parentNode - any non-leaf node
82
+ // childNode - some node that is an input to ` parentNode`
83
83
//
84
84
// Return value:
85
85
// true if it is safe to make childNode a contained memory operand.
86
86
//
87
87
bool Lowering::IsSafeToContainMem (GenTree* parentNode, GenTree* childNode)
88
88
{
89
- assert (parentNode-> OperIsBinary () );
90
- assert ( childNode-> isMemoryOp () );
89
+ m_scratchSideEffects. Clear ( );
90
+ m_scratchSideEffects. AddNode (comp, childNode);
91
91
92
- unsigned int childFlags = (childNode->gtFlags & GTF_ALL_EFFECT);
93
-
94
- GenTree* node;
95
- for (node = childNode; node != parentNode; node = node->gtNext )
92
+ for (GenTree* node = childNode->gtNext ; node != parentNode; node = node->gtNext )
96
93
{
97
- assert (node != nullptr );
98
-
99
- if ((childFlags != 0 ) && node->IsCall ())
100
- {
101
- bool isPureHelper = (node->gtCall .gtCallType == CT_HELPER) &&
102
- comp->s_helperCallProperties .IsPure (comp->eeGetHelperNum (node->gtCall .gtCallMethHnd ));
103
- if (!isPureHelper && ((node->gtFlags & childFlags & GTF_ALL_EFFECT) != 0 ))
104
- {
105
- return false ;
106
- }
107
- }
108
- else if (node->OperIsStore () && comp->fgNodesMayInterfere (node, childNode))
94
+ if (m_scratchSideEffects.InterferesWith (comp, node, false ))
109
95
{
110
96
return false ;
111
97
}
@@ -2978,17 +2964,57 @@ void Lowering::AddrModeCleanupHelper(GenTreeAddrMode* addrMode, GenTree* node)
2978
2964
BlockRange ().Remove (node);
2979
2965
}
2980
2966
2981
- // given two nodes which will be used in an addressing mode (base, index)
2982
- // walk backwards from the use to those nodes to determine if they are
2983
- // potentially modified in that range
2967
+ // ------------------------------------------------------------------------
2968
+ // Lowering::AreSourcesPossibleModifiedLocals:
2969
+ // Given two nodes which will be used in an addressing mode (base,
2970
+ // index), check to see if they are lclVar reads, and if so, walk
2971
+ // backwards from the use until both reads have been visited to
2972
+ // determine if they are potentially modified in that range.
2973
+ //
2974
+ // Arguments:
2975
+ // addr - the node that uses the base and index nodes
2976
+ // base - the base node
2977
+ // index - the index node
2978
+ //
2979
+ // Returns: true if either the base or index may be modified between the
2980
+ // node and addr.
2984
2981
//
2985
- // returns: true if the sources given may be modified before they are used
2986
- bool Lowering::AreSourcesPossiblyModified (GenTree* addr, GenTree* base, GenTree* index)
2982
+ bool Lowering::AreSourcesPossiblyModifiedLocals (GenTree* addr, GenTree* base, GenTree* index)
2987
2983
{
2988
2984
assert (addr != nullptr );
2989
2985
2990
- for (GenTree* cursor = addr; cursor != nullptr ; cursor = cursor->gtPrev )
2986
+ unsigned markCount = 0 ;
2987
+
2988
+ SideEffectSet baseSideEffects;
2989
+ if (base != nullptr )
2991
2990
{
2991
+ if (base->OperIsLocalRead ())
2992
+ {
2993
+ baseSideEffects.AddNode (comp, base);
2994
+ }
2995
+ else
2996
+ {
2997
+ base = nullptr ;
2998
+ }
2999
+ }
3000
+
3001
+ SideEffectSet indexSideEffects;
3002
+ if (index != nullptr )
3003
+ {
3004
+ if (index->OperIsLocalRead ())
3005
+ {
3006
+ indexSideEffects.AddNode (comp, index);
3007
+ }
3008
+ else
3009
+ {
3010
+ index = nullptr ;
3011
+ }
3012
+ }
3013
+
3014
+ for (GenTree* cursor = addr;; cursor = cursor->gtPrev )
3015
+ {
3016
+ assert (cursor != nullptr );
3017
+
2992
3018
if (cursor == base)
2993
3019
{
2994
3020
base = nullptr ;
@@ -2999,17 +3025,19 @@ bool Lowering::AreSourcesPossiblyModified(GenTree* addr, GenTree* base, GenTree*
2999
3025
index = nullptr ;
3000
3026
}
3001
3027
3002
- if (base == nullptr && index == nullptr )
3028
+ if (( base == nullptr ) && ( index == nullptr ) )
3003
3029
{
3004
3030
return false ;
3005
3031
}
3006
3032
3007
- if (base != nullptr && comp->fgNodesMayInterfere (base, cursor))
3033
+ m_scratchSideEffects.Clear ();
3034
+ m_scratchSideEffects.AddNode (comp, cursor);
3035
+ if ((base != nullptr ) && m_scratchSideEffects.InterferesWith (baseSideEffects, false ))
3008
3036
{
3009
3037
return true ;
3010
3038
}
3011
3039
3012
- if (index != nullptr && comp-> fgNodesMayInterfere (index, cursor ))
3040
+ if (( index != nullptr ) && m_scratchSideEffects. InterferesWith (indexSideEffects, false ))
3013
3041
{
3014
3042
return true ;
3015
3043
}
@@ -3092,7 +3120,7 @@ GenTree* Lowering::TryCreateAddrMode(LIR::Use&& use, bool isIndir)
3092
3120
}
3093
3121
3094
3122
// make sure there are not any side effects between def of leaves and use
3095
- if (!doAddrMode || AreSourcesPossiblyModified (addr, base, index))
3123
+ if (!doAddrMode || AreSourcesPossiblyModifiedLocals (addr, base, index))
3096
3124
{
3097
3125
JITDUMP (" No addressing mode\n " );
3098
3126
return addr;
@@ -3122,7 +3150,8 @@ GenTree* Lowering::TryCreateAddrMode(LIR::Use&& use, bool isIndir)
3122
3150
GenTreeAddrMode* addrMode = new (comp, GT_LEA) GenTreeAddrMode (addrModeType, base, index, scale, offset);
3123
3151
3124
3152
addrMode->gtRsvdRegs = addr->gtRsvdRegs ;
3125
- addrMode->gtFlags |= (addr->gtFlags & (GTF_ALL_EFFECT | GTF_IND_FLAGS));
3153
+ addrMode->gtFlags |= (addr->gtFlags & GTF_IND_FLAGS);
3154
+ addrMode->gtFlags &= ~GTF_ALL_EFFECT; // LEAs are side-effect-free.
3126
3155
3127
3156
JITDUMP (" New addressing mode node:\n " );
3128
3157
DISPNODE (addrMode);
0 commit comments