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 | // |
15 | class LclVarSet final |
16 | { |
17 | union { |
18 | hashBv* m_bitVector; |
19 | unsigned m_lclNum; |
20 | }; |
21 | |
22 | bool m_hasAnyLcl; |
23 | bool m_hasBitVector; |
24 | |
25 | public: |
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 | // |
48 | class AliasSet final |
49 | { |
50 | LclVarSet m_lclVarReads; |
51 | LclVarSet m_lclVarWrites; |
52 | |
53 | bool m_readsAddressableLocation; |
54 | bool m_writesAddressableLocation; |
55 | |
56 | public: |
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 | // |
146 | class 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 | |
154 | public: |
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 | |