1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5#ifndef _SIDEEFFECTS_H_
6#define _SIDEEFFECTS_H_
7
8//------------------------------------------------------------------------
9// LclVarSet:
10// Represents a set of lclVars. Optimized for the case that the set
11// never holds more than a single element. This type is used internally
12// by `AliasSet` to track the sets of lclVars that are read and
13// written for a given alias set.
14//
15class LclVarSet final
16{
17 union {
18 hashBv* m_bitVector;
19 unsigned m_lclNum;
20 };
21
22 bool m_hasAnyLcl;
23 bool m_hasBitVector;
24
25public:
26 LclVarSet();
27
28 inline bool IsEmpty() const
29 {
30 return !m_hasAnyLcl || !m_hasBitVector || !m_bitVector->anySet();
31 }
32
33 void Add(Compiler* compiler, unsigned lclNum);
34 bool Intersects(const LclVarSet& other) const;
35 bool Contains(unsigned lclNum) const;
36 void Clear();
37};
38
39//------------------------------------------------------------------------
40// AliasSet:
41// Represents a set of reads and writes for the purposes of alias
42// analysis. This type partitions storage into two categories:
43// lclVars and addressable locations. The definition of the former is
44// intuitive. The latter is the union of the set of address-exposed
45// lclVars with the set of all other memory locations. Any memory
46// access is assumed to alias any other memory access.
47//
48class AliasSet final
49{
50 LclVarSet m_lclVarReads;
51 LclVarSet m_lclVarWrites;
52
53 bool m_readsAddressableLocation;
54 bool m_writesAddressableLocation;
55
56public:
57 //------------------------------------------------------------------------
58 // AliasSet::NodeInfo:
59 // Represents basic alias information for a single IR node.
60 //
61 class NodeInfo final
62 {
63 enum : unsigned
64 {
65 ALIAS_NONE = 0x0,
66 ALIAS_READS_ADDRESSABLE_LOCATION = 0x1,
67 ALIAS_WRITES_ADDRESSABLE_LOCATION = 0x2,
68 ALIAS_READS_LCL_VAR = 0x4,
69 ALIAS_WRITES_LCL_VAR = 0x8
70 };
71
72 Compiler* m_compiler;
73 GenTree* m_node;
74 unsigned m_flags;
75 unsigned m_lclNum;
76
77 public:
78 NodeInfo(Compiler* compiler, GenTree* node);
79
80 inline Compiler* TheCompiler() const
81 {
82 return m_compiler;
83 }
84
85 inline GenTree* Node() const
86 {
87 return m_node;
88 }
89
90 inline bool ReadsAddressableLocation() const
91 {
92 return (m_flags & ALIAS_READS_ADDRESSABLE_LOCATION) != 0;
93 }
94
95 inline bool WritesAddressableLocation() const
96 {
97 return (m_flags & ALIAS_WRITES_ADDRESSABLE_LOCATION) != 0;
98 }
99
100 inline bool IsLclVarRead() const
101 {
102 return (m_flags & ALIAS_READS_LCL_VAR) != 0;
103 }
104
105 inline bool IsLclVarWrite() const
106 {
107 return (m_flags & ALIAS_WRITES_LCL_VAR) != 0;
108 }
109
110 inline unsigned LclNum() const
111 {
112 assert(IsLclVarRead() || IsLclVarWrite());
113 return m_lclNum;
114 }
115
116 inline bool WritesAnyLocation() const
117 {
118 return (m_flags & (ALIAS_WRITES_ADDRESSABLE_LOCATION | ALIAS_WRITES_LCL_VAR)) != 0;
119 }
120 };
121
122 AliasSet();
123
124 inline bool WritesAnyLocation() const
125 {
126 return m_writesAddressableLocation || !m_lclVarWrites.IsEmpty();
127 }
128
129 void AddNode(Compiler* compiler, GenTree* node);
130 bool InterferesWith(const AliasSet& other) const;
131 bool InterferesWith(const NodeInfo& node) const;
132 void Clear();
133};
134
135//------------------------------------------------------------------------
136// SideEffectSet:
137// Represents a set of side effects for the purposes of analyzing code
138// motion.
139// Note that for non-fixed-size frames without a frame pointer (currently
140// x86-only), we don't track the modification of the stack level that occurs
141// with a GT_PUTARG_STK as a side-effect. If we ever support general code
142// reordering, that would have to be taken into account. As it happens,
143// we currently do not reorder any other side-effecting nodes relative to
144// these.
145//
146class SideEffectSet final
147{
148 unsigned m_sideEffectFlags; // A mask of GTF_* flags that represents exceptional and barrier side effects.
149 AliasSet m_aliasSet; // An AliasSet that represents read and write side effects.
150
151 template <typename TOtherAliasInfo>
152 bool InterferesWith(unsigned otherSideEffectFlags, const TOtherAliasInfo& otherAliasInfo, bool strict) const;
153
154public:
155 SideEffectSet();
156 SideEffectSet(Compiler* compiler, GenTree* node);
157
158 void AddNode(Compiler* compiler, GenTree* node);
159 bool InterferesWith(const SideEffectSet& other, bool strict) const;
160 bool InterferesWith(Compiler* compiler, GenTree* node, bool strict) const;
161 void Clear();
162};
163
164#endif // _SIDEEFFECTS_H_
165