v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
maglev-phi-representation-selector.h
Go to the documentation of this file.
1// Copyright 2023 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_MAGLEV_MAGLEV_PHI_REPRESENTATION_SELECTOR_H_
6#define V8_MAGLEV_MAGLEV_PHI_REPRESENTATION_SELECTOR_H_
7
8#include <optional>
9
15
16namespace v8 {
17namespace internal {
18namespace maglev {
19
20class Graph;
21
23 template <class Value>
27
28 public:
30 : builder_(builder),
31 phi_taggings_(builder->zone()),
32 predecessors_(builder->zone()),
33 new_nodes_at_start_(builder->zone()) {}
34
35 void PreProcessGraph(Graph* graph) {
36 if (v8_flags.trace_maglev_phi_untagging) {
37 StdoutStream{} << "\nMaglevPhiRepresentationSelector\n";
38 }
39 }
40 void PostProcessGraph(Graph* graph) {
41 if (v8_flags.trace_maglev_phi_untagging) {
42 StdoutStream{} << "\n";
43 }
44 }
48
51
52 // The visitor method is a no-op since phis are processed in
53 // PreProcessBasicBlock.
57
59 FixLoopPhisBackedge(node->target());
61 }
62
66
67 template <class NodeT>
69 return UpdateNodeInputs(node, &state);
70 }
71
72 private:
73 enum class HoistType : uint8_t {
74 kNone,
78 };
80
81 // Update the inputs of {phi} so that they all have {repr} representation, and
82 // updates {phi}'s representation to {repr}.
84 const HoistTypeList& hoist_untagging);
85 template <class NodeT>
87 Phi* phi,
88 uint32_t input_index);
89
90 // Since this pass changes the representation of Phis, it makes some untagging
91 // operations outdated: if we've decided that a Phi should have Int32
92 // representation, then we don't need to do a kCheckedSmiUntag before using
93 // it. UpdateNodeInputs(n) removes such untagging from {n}'s input (and insert
94 // new conversions if needed, from Int32 to Float64 for instance).
95 template <class NodeT>
97 NodeBase* node = static_cast<NodeBase*>(n);
98
100 if (IsUntagging(n->opcode())) {
101 if (node->input(0).node()->Is<Phi>() &&
102 node->input(0).node()->value_representation() !=
104 DCHECK_EQ(node->input_count(), 1);
105 // This untagging conversion is outdated, since its input has been
106 // untagged. Depending on the conversion, it might need to be replaced
107 // by another untagged->untagged conversion, or it might need to be
108 // removed alltogether (or rather, replaced by an identity node).
109 UpdateUntaggingOfPhi(node->input(0).node()->Cast<Phi>(),
110 n->template Cast<ValueNode>());
111 }
112 } else {
114 }
115
116 return result;
117 }
118
119 template <class NodeT>
121 const ProcessingState* state) {
122 NodeBase* node = static_cast<NodeBase*>(n);
123
124 // It would be bad to re-tag the input of an untagging node, so this
125 // function should never be called on untagging nodes.
126 DCHECK(!IsUntagging(n->opcode()));
127
128 for (int i = 0; i < n->input_count(); i++) {
129 ValueNode* input = node->input(i).node();
130 if (input->Is<Identity>()) {
131 // Bypassing the identity
132 node->change_input(i, input->input(0).node());
133 } else if (Phi* phi = input->TryCast<Phi>()) {
134 // If the input is a Phi and it was used without any untagging, then
135 // we need to retag it (with some additional checks/changes for some
136 // nodes, cf the overload of UpdateNodePhiInput).
137 ProcessResult result = UpdateNodePhiInput(n, phi, i, state);
140 }
141 }
142 }
143
145 }
146
147 ProcessResult UpdateNodePhiInput(CheckSmi* node, Phi* phi, int input_index,
148 const ProcessingState* state);
149 ProcessResult UpdateNodePhiInput(CheckNumber* node, Phi* phi, int input_index,
150 const ProcessingState* state);
152 Phi* phi, int input_index,
153 const ProcessingState* state);
155 Phi* phi, int input_index,
156 const ProcessingState* state);
158 int input_index,
159 const ProcessingState* state);
160 ProcessResult UpdateNodePhiInput(NodeBase* node, Phi* phi, int input_index,
161 const ProcessingState* state);
162
163 void EnsurePhiInputsTagged(Phi* phi);
164
165 // Returns true if {op} is an untagging node.
166 bool IsUntagging(Opcode op);
167
168 // Updates {old_untagging} to reflect that its Phi input has been untagged and
169 // that a different conversion is now needed.
170 void UpdateUntaggingOfPhi(Phi* phi, ValueNode* old_untagging);
171
173
174 // Returns a tagged node that represents a tagged version of {phi}.
175 // If we are calling EnsurePhiTagged to ensure a Phi input of a Phi is tagged,
176 // then {predecessor_index} should be set to the id of this input (ie, 0 for
177 // the 1st input, 1 for the 2nd, etc.), so that we can use the SnapshotTable
178 // to find existing tagging for {phi} in the {predecessor_index}th predecessor
179 // of the current block.
181 Phi* phi, BasicBlock* block, NewNodePosition pos,
182 const ProcessingState* state,
183 std::optional<int> predecessor_index = std::nullopt);
184
186 DeoptFrame* deopt_frame = nullptr);
187
189 const ProcessingState* state,
190 DeoptFrame* deopt_frame = nullptr);
191 void RegisterNewNode(ValueNode* node);
192
193 // If {block} is the start of a loop header, FixLoopPhisBackedge inserts the
194 // necessary tagging on the backedge of the loop Phis of the loop header.
195 // Additionally, if {block} contains untagged loop phis whose backedges have
196 // been updated to Identity, FixLoopPhisBackedge unwraps those Identity.
197 void FixLoopPhisBackedge(BasicBlock* block);
198
199 void PreparePhiTaggings(BasicBlock* old_block, const BasicBlock* new_block);
200
204
205 bool CanHoistUntaggingTo(BasicBlock* block);
206
209
210 // {phi_taggings_} is a SnapshotTable containing mappings from untagged Phis
211 // to Tagged alternatives for those phis.
213 // {predecessors_} is used during merging, but we use an instance variable for
214 // it, in order to save memory and not reallocate it for each merge.
216
218
219 absl::flat_hash_map<BasicBlock::Id, Snapshot> snapshots_;
220
221#ifdef DEBUG
222 std::unordered_set<NodeBase*> new_nodes_;
223#endif
224};
225
226} // namespace maglev
227} // namespace internal
228} // namespace v8
229
230#endif // V8_MAGLEV_MAGLEV_PHI_REPRESENTATION_SELECTOR_H_
SourcePosition pos
ValueNode * node() const
Definition maglev-ir.h:1300
MaglevGraphLabeller * graph_labeller() const
ProcessResult Process(NodeT *node, const ProcessingState &state)
ValueNode * EnsurePhiTagged(Phi *phi, BasicBlock *block, NewNodePosition pos, const ProcessingState *state, std::optional< int > predecessor_index=std::nullopt)
void ConvertTaggedPhiTo(Phi *phi, ValueRepresentation repr, const HoistTypeList &hoist_untagging)
ValueNode * AddNode(ValueNode *node, BasicBlock *block, NewNodePosition pos, const ProcessingState *state, DeoptFrame *deopt_frame=nullptr)
void PreparePhiTaggings(BasicBlock *old_block, const BasicBlock *new_block)
ProcessResult Process(JumpLoop *node, const ProcessingState &)
ProcessResult Process(Dead *node, const ProcessingState &)
ProcessResult UpdateNodePhiInput(CheckSmi *node, Phi *phi, int input_index, const ProcessingState *state)
ProcessResult Process(Phi *node, const ProcessingState &)
ProcessResult UpdateNodeInputs(NodeT *n, const ProcessingState *state)
ValueNode * AddNodeAtBlockEnd(ValueNode *new_node, BasicBlock *block, DeoptFrame *deopt_frame=nullptr)
ValueNode * GetReplacementForPhiInputConversion(ValueNode *conversion_node, Phi *phi, uint32_t input_index)
ProcessResult UpdateNonUntaggingNodeInputs(NodeT *n, const ProcessingState *state)
constexpr Input & input(int index)
Definition maglev-ir.h:1978
ZoneVector< RpoNumber > & result
int n
Definition mul-fft.cc:296
V8_EXPORT_PRIVATE FlagValues v8_flags
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define V8_UNLIKELY(condition)
Definition v8config.h:660