OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/simplified-lowering.h" | 5 #include "src/compiler/simplified-lowering.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 | 8 |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
65 // 1. During propagation, the use info is used to inform the input node | 65 // 1. During propagation, the use info is used to inform the input node |
66 // about what part of the input is used (we call this truncation) and what | 66 // about what part of the input is used (we call this truncation) and what |
67 // is the preferred representation. | 67 // is the preferred representation. |
68 // | 68 // |
69 // 2. During lowering, the use info is used to properly convert the input | 69 // 2. During lowering, the use info is used to properly convert the input |
70 // to the preferred representation. The preferred representation might be | 70 // to the preferred representation. The preferred representation might be |
71 // insufficient to do the conversion (e.g. word32->float64 conv), so we also | 71 // insufficient to do the conversion (e.g. word32->float64 conv), so we also |
72 // need the signedness information to produce the correct value. | 72 // need the signedness information to produce the correct value. |
73 class UseInfo { | 73 class UseInfo { |
74 public: | 74 public: |
75 // Constructors | 75 UseInfo(MachineType preferred, Truncation truncation) |
76 // ================================================================ | 76 : preferred_(preferred), truncation_(truncation) { |
77 | 77 DCHECK(preferred == (preferred & kRepMask)); |
78 // Uses truncating to the preferred representation. | 78 } |
79 static UseInfo TruncatingWord32() { | 79 static UseInfo TruncatingWord32() { |
80 return UseInfo(kTypeInt32 | kTypeUint32 | kRepWord32); | 80 return UseInfo(kRepWord32, Truncation::Word32()); |
81 } | 81 } |
82 static UseInfo TruncatingWord64() { | 82 static UseInfo TruncatingWord64() { |
83 return UseInfo(kTypeInt64 | kTypeUint64 | kRepWord64); | 83 return UseInfo(kRepWord64, Truncation::Word64()); |
84 } | 84 } |
85 static UseInfo Bool() { return UseInfo(kMachBool); } | 85 static UseInfo Bool() { return UseInfo(kRepBit, Truncation::Bool()); } |
86 static UseInfo Float32() { return UseInfo(kMachFloat32); } | 86 static UseInfo Float32() { |
87 static UseInfo Float64() { return UseInfo(kMachFloat64); } | 87 return UseInfo(kRepFloat32, Truncation::Float32()); |
| 88 } |
| 89 static UseInfo Float64() { |
| 90 return UseInfo(kRepFloat64, Truncation::Float64()); |
| 91 } |
88 static UseInfo PointerInt() { | 92 static UseInfo PointerInt() { |
89 return kPointerSize == 4 ? TruncatingWord32() : TruncatingWord64(); | 93 return kPointerSize == 4 ? TruncatingWord32() : TruncatingWord64(); |
90 } | 94 } |
| 95 static UseInfo AnyTagged() { return UseInfo(kRepTagged, Truncation::Any()); } |
91 | 96 |
92 // Non-truncating uses. | 97 // Undetermined representation. |
93 static UseInfo AnyTagged() { return UseInfo(kMachAnyTagged); } | 98 static UseInfo Any() { return UseInfo(kMachNone, Truncation::Any()); } |
94 static UseInfo Any() { return UseInfo(kTypeAny); } | 99 static UseInfo None() { return UseInfo(kMachNone, Truncation::None()); } |
95 | 100 |
96 // Ignored-value 'use'. | 101 // Truncation to a representation that is smaller than the preferred |
97 static UseInfo None() { return UseInfo(kMachNone); } | |
98 | |
99 // Truncating to a representation that is smaller than the preferred | |
100 // one. | 102 // one. |
101 static UseInfo Float64TruncatingToWord32() { | 103 static UseInfo Float64TruncatingToWord32() { |
102 return UseInfo(kRepFloat64 | kTypeInt32 | kTypeUint32); | 104 return UseInfo(kRepFloat64, Truncation::Word32()); |
103 } | 105 } |
104 static UseInfo Word64TruncatingToWord32() { | 106 static UseInfo Word64TruncatingToWord32() { |
105 return UseInfo(kRepWord64 | kTypeInt32 | kTypeUint32); | 107 return UseInfo(kRepWord64, Truncation::Word32()); |
106 } | 108 } |
107 static UseInfo AnyTruncatingToBool() { return UseInfo(kTypeBool); } | 109 static UseInfo AnyTruncatingToBool() { |
108 | 110 return UseInfo(kMachNone, Truncation::Bool()); |
109 UseInfo(MachineTypeUnion representation, MachineTypeUnion truncation) | |
110 : type_(representation | truncation) { | |
111 DCHECK(base::bits::CountPopulation32(representation & kRepMask) == 1); | |
112 DCHECK((representation & kTypeMask) == 0); | |
113 DCHECK((truncation & kRepMask) == 0); | |
114 // TODO(jarin) Check/normalize truncation? | |
115 } | 111 } |
116 | 112 |
117 // Queries | 113 MachineType preferred() const { return preferred_; } |
118 // ================================================================ | 114 Truncation truncation() const { return truncation_; } |
119 MachineType GetRepresentation() const { | |
120 return static_cast<MachineType>(type_ & kRepMask); | |
121 } | |
122 | |
123 // This should only be used by the Enqueue method. | |
124 MachineTypeUnion machine_type() const { return type_; } | |
125 | 115 |
126 private: | 116 private: |
127 explicit UseInfo(MachineTypeUnion type) : type_(type) {} | 117 MachineType preferred_; |
128 | 118 Truncation truncation_; |
129 MachineTypeUnion type_; | |
130 }; | 119 }; |
131 | 120 |
132 | 121 |
133 UseInfo UseInfoFromMachineType(MachineType type) { | 122 UseInfo UseInfoFromMachineType(MachineType type) { |
134 MachineTypeUnion rep = RepresentationOf(type); | 123 MachineTypeUnion rep = RepresentationOf(type); |
135 DCHECK((rep & kTypeMask) == 0); | 124 DCHECK((rep & kTypeMask) == 0); |
| 125 |
136 if (rep & kRepTagged) return UseInfo::AnyTagged(); | 126 if (rep & kRepTagged) return UseInfo::AnyTagged(); |
137 if (rep & kRepFloat64) { | 127 if (rep & kRepFloat64) { |
138 DCHECK((rep & kRepWord64) == 0); | 128 DCHECK((rep & kRepWord64) == 0); |
139 return UseInfo::Float64(); | 129 return UseInfo::Float64(); |
140 } | 130 } |
141 if (rep & kRepFloat32) { | 131 if (rep & kRepFloat32) { |
142 if (rep == kRepFloat32) return UseInfo::Float32(); | 132 if (rep == kRepFloat32) return UseInfo::Float32(); |
143 return UseInfo::AnyTagged(); | 133 return UseInfo::AnyTagged(); |
144 } | 134 } |
145 if (rep & kRepWord64) { | 135 if (rep & kRepWord64) { |
(...skipping 16 matching lines...) Expand all Loading... |
162 UseInfo UseInfoForBasePointer(const ElementAccess& access) { | 152 UseInfo UseInfoForBasePointer(const ElementAccess& access) { |
163 return access.tag() != 0 ? UseInfo::AnyTagged() : UseInfo::PointerInt(); | 153 return access.tag() != 0 ? UseInfo::AnyTagged() : UseInfo::PointerInt(); |
164 } | 154 } |
165 | 155 |
166 } // namespace | 156 } // namespace |
167 | 157 |
168 | 158 |
169 class RepresentationSelector { | 159 class RepresentationSelector { |
170 public: | 160 public: |
171 // Information for each node tracked during the fixpoint. | 161 // Information for each node tracked during the fixpoint. |
172 struct NodeInfo { | 162 class NodeInfo { |
173 MachineTypeUnion use : 15; // Union of all usages for the node. | 163 public: |
174 bool queued : 1; // Bookkeeping for the traversal. | 164 // Adds new use to the node. Returns true if something has changed |
175 bool visited : 1; // Bookkeeping for the traversal. | 165 // and the node has to be requeued. |
176 MachineTypeUnion output : 15; // Output type of the node. | 166 bool AddUse(UseInfo info) { |
| 167 Truncation old_truncation = truncation_; |
| 168 truncation_ = Truncation::Generalize(truncation_, info.truncation()); |
| 169 return truncation_ != old_truncation; |
| 170 } |
| 171 |
| 172 void set_queued(bool value) { queued_ = value; } |
| 173 bool queued() const { return queued_; } |
| 174 void set_visited() { visited_ = true; } |
| 175 bool visited() const { return visited_; } |
| 176 Truncation truncation() const { return truncation_; } |
| 177 void set_output_type(MachineTypeUnion type) { output_ = type; } |
| 178 MachineTypeUnion output_type() const { return output_; } |
| 179 |
| 180 private: |
| 181 bool queued_ = false; // Bookkeeping for the traversal. |
| 182 bool visited_ = false; // Bookkeeping for the traversal. |
| 183 MachineTypeUnion output_ = kMachNone; // Output type of the node. |
| 184 Truncation truncation_ = Truncation::None(); // Information about uses. |
177 }; | 185 }; |
178 | 186 |
179 RepresentationSelector(JSGraph* jsgraph, Zone* zone, | 187 RepresentationSelector(JSGraph* jsgraph, Zone* zone, |
180 RepresentationChanger* changer, | 188 RepresentationChanger* changer, |
181 SourcePositionTable* source_positions) | 189 SourcePositionTable* source_positions) |
182 : jsgraph_(jsgraph), | 190 : jsgraph_(jsgraph), |
183 count_(jsgraph->graph()->NodeCount()), | 191 count_(jsgraph->graph()->NodeCount()), |
184 info_(zone->NewArray<NodeInfo>(count_)), | 192 info_(count_, zone), |
185 nodes_(zone), | 193 nodes_(zone), |
186 replacements_(zone), | 194 replacements_(zone), |
187 phase_(PROPAGATE), | 195 phase_(PROPAGATE), |
188 changer_(changer), | 196 changer_(changer), |
189 queue_(zone), | 197 queue_(zone), |
190 source_positions_(source_positions) { | 198 source_positions_(source_positions) { |
191 memset(info_, 0, sizeof(NodeInfo) * count_); | |
192 | |
193 safe_int_additive_range_ = | 199 safe_int_additive_range_ = |
194 Type::Range(-std::pow(2.0, 52.0), std::pow(2.0, 52.0), zone); | 200 Type::Range(-std::pow(2.0, 52.0), std::pow(2.0, 52.0), zone); |
195 } | 201 } |
196 | 202 |
197 void Run(SimplifiedLowering* lowering) { | 203 void Run(SimplifiedLowering* lowering) { |
198 // Run propagation phase to a fixpoint. | 204 // Run propagation phase to a fixpoint. |
199 TRACE("--{Propagation phase}--\n"); | 205 TRACE("--{Propagation phase}--\n"); |
200 phase_ = PROPAGATE; | 206 phase_ = PROPAGATE; |
201 Enqueue(jsgraph_->graph()->end()); | 207 Enqueue(jsgraph_->graph()->end()); |
202 // Process nodes from the queue until it is empty. | 208 // Process nodes from the queue until it is empty. |
203 while (!queue_.empty()) { | 209 while (!queue_.empty()) { |
204 Node* node = queue_.front(); | 210 Node* node = queue_.front(); |
205 NodeInfo* info = GetInfo(node); | 211 NodeInfo* info = GetInfo(node); |
206 queue_.pop(); | 212 queue_.pop(); |
207 info->queued = false; | 213 info->set_queued(false); |
208 TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic()); | 214 TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic()); |
209 VisitNode(node, info->use, NULL); | 215 VisitNode(node, info->truncation(), NULL); |
210 TRACE(" ==> output "); | 216 TRACE(" ==> output "); |
211 PrintInfo(info->output); | 217 PrintInfo(info->output_type()); |
212 TRACE("\n"); | 218 TRACE("\n"); |
213 } | 219 } |
214 | 220 |
215 // Run lowering and change insertion phase. | 221 // Run lowering and change insertion phase. |
216 TRACE("--{Simplified lowering phase}--\n"); | 222 TRACE("--{Simplified lowering phase}--\n"); |
217 phase_ = LOWER; | 223 phase_ = LOWER; |
218 // Process nodes from the collected {nodes_} vector. | 224 // Process nodes from the collected {nodes_} vector. |
219 for (NodeVector::iterator i = nodes_.begin(); i != nodes_.end(); ++i) { | 225 for (NodeVector::iterator i = nodes_.begin(); i != nodes_.end(); ++i) { |
220 Node* node = *i; | 226 Node* node = *i; |
| 227 NodeInfo* info = GetInfo(node); |
221 TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic()); | 228 TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic()); |
222 // Reuse {VisitNode()} so the representation rules are in one place. | 229 // Reuse {VisitNode()} so the representation rules are in one place. |
223 SourcePositionTable::Scope scope( | 230 SourcePositionTable::Scope scope( |
224 source_positions_, source_positions_->GetSourcePosition(node)); | 231 source_positions_, source_positions_->GetSourcePosition(node)); |
225 VisitNode(node, GetUseInfo(node), lowering); | 232 VisitNode(node, info->truncation(), lowering); |
226 } | 233 } |
227 | 234 |
228 // Perform the final replacements. | 235 // Perform the final replacements. |
229 for (NodeVector::iterator i = replacements_.begin(); | 236 for (NodeVector::iterator i = replacements_.begin(); |
230 i != replacements_.end(); ++i) { | 237 i != replacements_.end(); ++i) { |
231 Node* node = *i; | 238 Node* node = *i; |
232 Node* replacement = *(++i); | 239 Node* replacement = *(++i); |
233 node->ReplaceUses(replacement); | 240 node->ReplaceUses(replacement); |
234 // We also need to replace the node in the rest of the vector. | 241 // We also need to replace the node in the rest of the vector. |
235 for (NodeVector::iterator j = i + 1; j != replacements_.end(); ++j) { | 242 for (NodeVector::iterator j = i + 1; j != replacements_.end(); ++j) { |
236 ++j; | 243 ++j; |
237 if (*j == node) *j = replacement; | 244 if (*j == node) *j = replacement; |
238 } | 245 } |
239 } | 246 } |
240 } | 247 } |
241 | 248 |
242 // Enqueue {node} if the {use} contains new information for that node. | 249 // Enqueue {node} if the {use} contains new information for that node. |
243 // Add {node} to {nodes_} if this is the first time it's been visited. | 250 // Add {node} to {nodes_} if this is the first time it's been visited. |
244 void Enqueue(Node* node, UseInfo use_info = UseInfo::None()) { | 251 void Enqueue(Node* node, UseInfo use_info = UseInfo::None()) { |
245 MachineTypeUnion use = use_info.machine_type(); | |
246 | |
247 if (phase_ != PROPAGATE) return; | 252 if (phase_ != PROPAGATE) return; |
248 NodeInfo* info = GetInfo(node); | 253 NodeInfo* info = GetInfo(node); |
249 if (!info->visited) { | 254 if (!info->visited()) { |
250 // First visit of this node. | 255 // First visit of this node. |
251 info->visited = true; | 256 info->set_visited(); |
252 info->queued = true; | 257 info->set_queued(true); |
253 nodes_.push_back(node); | 258 nodes_.push_back(node); |
254 queue_.push(node); | 259 queue_.push(node); |
255 TRACE(" initial: "); | 260 TRACE(" initial: "); |
256 info->use |= use; | 261 info->AddUse(use_info); |
257 PrintUseInfo(node); | 262 PrintTruncation(info->truncation()); |
258 return; | 263 return; |
259 } | 264 } |
260 TRACE(" queue?: "); | 265 TRACE(" queue?: "); |
261 PrintUseInfo(node); | 266 PrintTruncation(info->truncation()); |
262 if ((info->use & use) != use) { | 267 if (info->AddUse(use_info)) { |
263 // New usage information for the node is available. | 268 // New usage information for the node is available. |
264 if (!info->queued) { | 269 if (!info->queued()) { |
265 queue_.push(node); | 270 queue_.push(node); |
266 info->queued = true; | 271 info->set_queued(true); |
267 TRACE(" added: "); | 272 TRACE(" added: "); |
268 } else { | 273 } else { |
269 TRACE(" inqueue: "); | 274 TRACE(" inqueue: "); |
270 } | 275 } |
271 info->use |= use; | 276 PrintTruncation(info->truncation()); |
272 PrintUseInfo(node); | |
273 } | 277 } |
274 } | 278 } |
275 | 279 |
276 bool lower() { return phase_ == LOWER; } | 280 bool lower() { return phase_ == LOWER; } |
277 | 281 |
278 void SetOutput(Node* node, MachineTypeUnion output) { | 282 void SetOutput(Node* node, MachineTypeUnion output) { |
279 // Every node should have at most one output representation. Note that | 283 // Every node should have at most one output representation. Note that |
280 // phis can have 0, if they have not been used in a representation-inducing | 284 // phis can have 0, if they have not been used in a representation-inducing |
281 // instruction. | 285 // instruction. |
282 DCHECK((output & kRepMask) == 0 || | 286 DCHECK((output & kRepMask) == 0 || |
283 base::bits::IsPowerOfTwo32(output & kRepMask)); | 287 base::bits::IsPowerOfTwo32(output & kRepMask)); |
284 GetInfo(node)->output = output; | 288 GetInfo(node)->set_output_type(output); |
285 } | 289 } |
286 | 290 |
287 bool BothInputsAre(Node* node, Type* type) { | 291 bool BothInputsAre(Node* node, Type* type) { |
288 DCHECK_EQ(2, node->InputCount()); | 292 DCHECK_EQ(2, node->InputCount()); |
289 return NodeProperties::GetType(node->InputAt(0))->Is(type) && | 293 return NodeProperties::GetType(node->InputAt(0))->Is(type) && |
290 NodeProperties::GetType(node->InputAt(1))->Is(type); | 294 NodeProperties::GetType(node->InputAt(1))->Is(type); |
291 } | 295 } |
292 | 296 |
293 void ProcessTruncateWord32Input(Node* node, int index) { | 297 void ProcessTruncateWord32Input(Node* node, int index) { |
294 Node* input = node->InputAt(index); | 298 Node* input = node->InputAt(index); |
295 if (phase_ == PROPAGATE) { | 299 if (phase_ == PROPAGATE) { |
296 // In the propagate phase, propagate the usage information backward. | 300 // In the propagate phase, propagate the usage information backward. |
297 Enqueue(input, UseInfo::TruncatingWord32()); | 301 Enqueue(input, UseInfo::TruncatingWord32()); |
298 } else { | 302 } else { |
299 // In the change phase, insert a change before the use if necessary. | 303 // In the change phase, insert a change before the use if necessary. |
300 MachineTypeUnion output = GetInfo(input)->output; | 304 MachineTypeUnion output = GetInfo(input)->output_type(); |
301 if ((output & (kRepBit | kRepWord8 | kRepWord16 | kRepWord32)) == 0) { | 305 if ((output & (kRepBit | kRepWord8 | kRepWord16 | kRepWord32)) == 0) { |
302 // Output representation doesn't match usage. | 306 // Output representation doesn't match usage. |
303 TRACE(" truncate-to-int32: #%d:%s(@%d #%d:%s) ", node->id(), | 307 TRACE(" truncate-to-int32: #%d:%s(@%d #%d:%s) ", node->id(), |
304 node->op()->mnemonic(), index, input->id(), | 308 node->op()->mnemonic(), index, input->id(), |
305 input->op()->mnemonic()); | 309 input->op()->mnemonic()); |
306 TRACE(" from "); | 310 TRACE(" from "); |
307 PrintInfo(output); | 311 PrintInfo(output); |
308 TRACE("\n"); | 312 TRACE("\n"); |
309 Node* n = changer_->GetTruncatedWord32For(input, output); | 313 Node* n = changer_->GetTruncatedWord32For(input, output); |
310 node->ReplaceInput(index, n); | 314 node->ReplaceInput(index, n); |
311 } | 315 } |
312 } | 316 } |
313 } | 317 } |
314 | 318 |
315 void EnqueueInputUse(Node* node, int index, UseInfo use) { | 319 void EnqueueInputUse(Node* node, int index, UseInfo use) { |
316 Enqueue(node->InputAt(index), use); | 320 Enqueue(node->InputAt(index), use); |
317 } | 321 } |
318 | 322 |
319 void ConvertInput(Node* node, int index, UseInfo use) { | 323 void ConvertInput(Node* node, int index, UseInfo use) { |
320 Node* input = node->InputAt(index); | 324 Node* input = node->InputAt(index); |
321 // In the change phase, insert a change before the use if necessary. | 325 // In the change phase, insert a change before the use if necessary. |
322 if (use.GetRepresentation() == kMachNone) | 326 if (use.preferred() == kMachNone) |
323 return; // No input requirement on the use. | 327 return; // No input requirement on the use. |
324 MachineTypeUnion output = GetInfo(input)->output; | 328 MachineTypeUnion output = GetInfo(input)->output_type(); |
325 if ((output & kRepMask) != use.GetRepresentation()) { | 329 if ((output & kRepMask) != use.preferred()) { |
326 // Output representation doesn't match usage. | 330 // Output representation doesn't match usage. |
327 TRACE(" change: #%d:%s(@%d #%d:%s) ", node->id(), node->op()->mnemonic(), | 331 TRACE(" change: #%d:%s(@%d #%d:%s) ", node->id(), node->op()->mnemonic(), |
328 index, input->id(), input->op()->mnemonic()); | 332 index, input->id(), input->op()->mnemonic()); |
329 TRACE(" from "); | 333 TRACE(" from "); |
330 PrintInfo(output); | 334 PrintInfo(output); |
331 TRACE(" to "); | 335 TRACE(" to "); |
332 PrintUseInfo(use); | 336 PrintUseInfo(use); |
333 TRACE("\n"); | 337 TRACE("\n"); |
334 Node* n = | 338 Node* n = changer_->GetRepresentationFor(input, output, use.preferred(), |
335 changer_->GetRepresentationFor(input, output, use.machine_type()); | 339 use.truncation()); |
336 node->ReplaceInput(index, n); | 340 node->ReplaceInput(index, n); |
337 } | 341 } |
338 } | 342 } |
339 | 343 |
340 void ProcessInput(Node* node, int index, UseInfo use) { | 344 void ProcessInput(Node* node, int index, UseInfo use) { |
341 if (phase_ == PROPAGATE) { | 345 if (phase_ == PROPAGATE) { |
342 EnqueueInputUse(node, index, use); | 346 EnqueueInputUse(node, index, use); |
343 } else { | 347 } else { |
344 ConvertInput(node, index, use); | 348 ConvertInput(node, index, use); |
345 } | 349 } |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
433 VisitBinop(node, UseInfo::TruncatingWord32(), kMachBool); | 437 VisitBinop(node, UseInfo::TruncatingWord32(), kMachBool); |
434 } | 438 } |
435 void VisitInt64Cmp(Node* node) { | 439 void VisitInt64Cmp(Node* node) { |
436 VisitBinop(node, UseInfo::TruncatingWord64(), kMachBool); | 440 VisitBinop(node, UseInfo::TruncatingWord64(), kMachBool); |
437 } | 441 } |
438 void VisitUint64Cmp(Node* node) { | 442 void VisitUint64Cmp(Node* node) { |
439 VisitBinop(node, UseInfo::TruncatingWord64(), kMachBool); | 443 VisitBinop(node, UseInfo::TruncatingWord64(), kMachBool); |
440 } | 444 } |
441 | 445 |
442 // Infer representation for phi-like nodes. | 446 // Infer representation for phi-like nodes. |
443 static MachineType GetRepresentationForPhi(Node* node, MachineTypeUnion use) { | 447 static MachineType GetRepresentationForPhi(Node* node, Truncation use) { |
444 // Phis adapt to the output representation their uses demand. | 448 // Phis adapt to the output representation their uses demand. |
445 Type* upper = NodeProperties::GetType(node); | 449 Type* upper = NodeProperties::GetType(node); |
446 if (upper->Is(Type::Signed32()) || upper->Is(Type::Unsigned32())) { | 450 if (upper->Is(Type::Signed32()) || upper->Is(Type::Unsigned32())) { |
447 // We are within 32 bits range => pick kRepWord32. | 451 // We are within 32 bits range => pick kRepWord32. |
448 return kRepWord32; | 452 return kRepWord32; |
449 } else if (!CanObserveNonWord32(use)) { | 453 } else if (use.TruncatesToWord32()) { |
450 // We only use 32 bits. | 454 // We only use 32 bits. |
451 return kRepWord32; | 455 return kRepWord32; |
452 } else if (upper->Is(Type::Boolean())) { | 456 } else if (upper->Is(Type::Boolean())) { |
453 // multiple uses => pick kRepBit. | 457 // multiple uses => pick kRepBit. |
454 return kRepBit; | 458 return kRepBit; |
455 } else if (upper->Is(Type::Number())) { | 459 } else if (upper->Is(Type::Number())) { |
456 // multiple uses => pick kRepFloat64. | 460 // multiple uses => pick kRepFloat64. |
457 return kRepFloat64; | 461 return kRepFloat64; |
458 } else if (upper->Is(Type::Internal())) { | 462 } else if (upper->Is(Type::Internal())) { |
459 return kMachPtr; | 463 return kMachPtr; |
460 } | 464 } |
461 return kRepTagged; | 465 return kRepTagged; |
462 } | 466 } |
463 | 467 |
464 // Helper for handling selects. | 468 // Helper for handling selects. |
465 void VisitSelect(Node* node, MachineTypeUnion use, | 469 void VisitSelect(Node* node, Truncation truncation, |
466 SimplifiedLowering* lowering) { | 470 SimplifiedLowering* lowering) { |
467 ProcessInput(node, 0, UseInfo::Bool()); | 471 ProcessInput(node, 0, UseInfo::Bool()); |
468 MachineType output = GetRepresentationForPhi(node, use); | 472 MachineType output = GetRepresentationForPhi(node, truncation); |
469 | 473 |
470 Type* upper = NodeProperties::GetType(node); | 474 Type* upper = NodeProperties::GetType(node); |
471 MachineType output_type = | 475 MachineType output_type = |
472 static_cast<MachineType>(changer_->TypeFromUpperBound(upper) | output); | 476 static_cast<MachineType>(changer_->TypeFromUpperBound(upper) | output); |
473 SetOutput(node, output_type); | 477 SetOutput(node, output_type); |
474 | 478 |
475 if (lower()) { | 479 if (lower()) { |
476 // Update the select operator. | 480 // Update the select operator. |
477 SelectParameters p = SelectParametersOf(node->op()); | 481 SelectParameters p = SelectParametersOf(node->op()); |
478 MachineType type = static_cast<MachineType>(output_type); | 482 MachineType type = static_cast<MachineType>(output_type); |
479 if (type != p.type()) { | 483 if (type != p.type()) { |
480 NodeProperties::ChangeOp(node, | 484 NodeProperties::ChangeOp(node, |
481 lowering->common()->Select(type, p.hint())); | 485 lowering->common()->Select(type, p.hint())); |
482 } | 486 } |
483 } | 487 } |
484 // Convert inputs to the output representation of this phi, pass the | 488 // Convert inputs to the output representation of this phi, pass the |
485 // use truncation along. | 489 // truncation truncation along. |
486 UseInfo input_use(output, use & kTypeMask); | 490 UseInfo input_use(output, truncation); |
487 ProcessInput(node, 1, input_use); | 491 ProcessInput(node, 1, input_use); |
488 ProcessInput(node, 2, input_use); | 492 ProcessInput(node, 2, input_use); |
489 } | 493 } |
490 | 494 |
491 // Helper for handling phis. | 495 // Helper for handling phis. |
492 void VisitPhi(Node* node, MachineTypeUnion use, | 496 void VisitPhi(Node* node, Truncation truncation, |
493 SimplifiedLowering* lowering) { | 497 SimplifiedLowering* lowering) { |
494 MachineType output = GetRepresentationForPhi(node, use); | 498 MachineType output = GetRepresentationForPhi(node, truncation); |
495 | 499 |
496 Type* upper = NodeProperties::GetType(node); | 500 Type* upper = NodeProperties::GetType(node); |
497 MachineType output_type = | 501 MachineType output_type = |
498 static_cast<MachineType>(changer_->TypeFromUpperBound(upper) | output); | 502 static_cast<MachineType>(changer_->TypeFromUpperBound(upper) | output); |
499 SetOutput(node, output_type); | 503 SetOutput(node, output_type); |
500 | 504 |
501 int values = node->op()->ValueInputCount(); | 505 int values = node->op()->ValueInputCount(); |
502 | 506 |
503 if (lower()) { | 507 if (lower()) { |
504 // Update the phi operator. | 508 // Update the phi operator. |
505 MachineType type = static_cast<MachineType>(output_type); | 509 MachineType type = static_cast<MachineType>(output_type); |
506 if (type != OpParameter<MachineType>(node)) { | 510 if (type != OpParameter<MachineType>(node)) { |
507 NodeProperties::ChangeOp(node, lowering->common()->Phi(type, values)); | 511 NodeProperties::ChangeOp(node, lowering->common()->Phi(type, values)); |
508 } | 512 } |
509 } | 513 } |
510 | 514 |
511 // Convert inputs to the output representation of this phi, pass the | 515 // Convert inputs to the output representation of this phi, pass the |
512 // use truncation along. | 516 // truncation truncation along. |
513 UseInfo input_use(output, use & kTypeMask); | 517 UseInfo input_use(output, truncation); |
514 for (int i = 0; i < node->InputCount(); i++) { | 518 for (int i = 0; i < node->InputCount(); i++) { |
515 ProcessInput(node, i, i < values ? input_use : UseInfo::None()); | 519 ProcessInput(node, i, i < values ? input_use : UseInfo::None()); |
516 } | 520 } |
517 } | 521 } |
518 | 522 |
519 void VisitCall(Node* node, SimplifiedLowering* lowering) { | 523 void VisitCall(Node* node, SimplifiedLowering* lowering) { |
520 const CallDescriptor* desc = OpParameter<const CallDescriptor*>(node->op()); | 524 const CallDescriptor* desc = OpParameter<const CallDescriptor*>(node->op()); |
521 const MachineSignature* sig = desc->GetMachineSignature(); | 525 const MachineSignature* sig = desc->GetMachineSignature(); |
522 int params = static_cast<int>(sig->parameter_count()); | 526 int params = static_cast<int>(sig->parameter_count()); |
523 // Propagate representation information from call descriptor. | 527 // Propagate representation information from call descriptor. |
(...skipping 19 matching lines...) Expand all Loading... |
543 if (phase_ == PROPAGATE) { | 547 if (phase_ == PROPAGATE) { |
544 for (int i = 0; i < node->InputCount(); i++) { | 548 for (int i = 0; i < node->InputCount(); i++) { |
545 Enqueue(node->InputAt(i), UseInfo::Any()); | 549 Enqueue(node->InputAt(i), UseInfo::Any()); |
546 } | 550 } |
547 } else { | 551 } else { |
548 Zone* zone = jsgraph_->zone(); | 552 Zone* zone = jsgraph_->zone(); |
549 ZoneVector<MachineType>* types = | 553 ZoneVector<MachineType>* types = |
550 new (zone->New(sizeof(ZoneVector<MachineType>))) | 554 new (zone->New(sizeof(ZoneVector<MachineType>))) |
551 ZoneVector<MachineType>(node->InputCount(), zone); | 555 ZoneVector<MachineType>(node->InputCount(), zone); |
552 for (int i = 0; i < node->InputCount(); i++) { | 556 for (int i = 0; i < node->InputCount(); i++) { |
553 MachineTypeUnion input_type = GetInfo(node->InputAt(i))->output; | 557 MachineTypeUnion input_type = GetInfo(node->InputAt(i))->output_type(); |
554 (*types)[i] = static_cast<MachineType>(input_type); | 558 (*types)[i] = static_cast<MachineType>(input_type); |
555 } | 559 } |
556 NodeProperties::ChangeOp(node, | 560 NodeProperties::ChangeOp(node, |
557 jsgraph_->common()->TypedStateValues(types)); | 561 jsgraph_->common()->TypedStateValues(types)); |
558 } | 562 } |
559 SetOutput(node, kMachAnyTagged); | 563 SetOutput(node, kMachAnyTagged); |
560 } | 564 } |
561 | 565 |
562 const Operator* Int32Op(Node* node) { | 566 const Operator* Int32Op(Node* node) { |
563 return changer_->Int32OperatorFor(node->opcode()); | 567 return changer_->Int32OperatorFor(node->opcode()); |
564 } | 568 } |
565 | 569 |
566 const Operator* Uint32Op(Node* node) { | 570 const Operator* Uint32Op(Node* node) { |
567 return changer_->Uint32OperatorFor(node->opcode()); | 571 return changer_->Uint32OperatorFor(node->opcode()); |
568 } | 572 } |
569 | 573 |
570 const Operator* Float64Op(Node* node) { | 574 const Operator* Float64Op(Node* node) { |
571 return changer_->Float64OperatorFor(node->opcode()); | 575 return changer_->Float64OperatorFor(node->opcode()); |
572 } | 576 } |
573 | 577 |
574 bool CanLowerToInt32Binop(Node* node, MachineTypeUnion use) { | 578 bool CanLowerToInt32Binop(Node* node, Truncation use) { |
575 return BothInputsAre(node, Type::Signed32()) && | 579 return BothInputsAre(node, Type::Signed32()) && |
576 (!CanObserveNonWord32(use) || | 580 (use.TruncatesToWord32() || |
577 NodeProperties::GetType(node)->Is(Type::Signed32())); | 581 NodeProperties::GetType(node)->Is(Type::Signed32())); |
578 } | 582 } |
579 | 583 |
580 bool CanLowerToWord32AdditiveBinop(Node* node, MachineTypeUnion use) { | 584 bool CanLowerToWord32AdditiveBinop(Node* node, Truncation use) { |
581 return BothInputsAre(node, safe_int_additive_range_) && | 585 return BothInputsAre(node, safe_int_additive_range_) && |
582 !CanObserveNonWord32(use); | 586 use.TruncatesToWord32(); |
583 } | |
584 | |
585 bool CanLowerToUint32Binop(Node* node, MachineTypeUnion use) { | |
586 return BothInputsAre(node, Type::Unsigned32()) && | |
587 (!CanObserveNonWord32(use) || | |
588 NodeProperties::GetType(node)->Is(Type::Unsigned32())); | |
589 } | |
590 | |
591 static bool CanObserveNonWord32(MachineTypeUnion use) { | |
592 return (use & kTypeMask & ~(kTypeInt32 | kTypeUint32)) != 0; | |
593 } | |
594 | |
595 static bool CanObserveNaN(MachineTypeUnion use) { | |
596 return (use & (kTypeNumber | kTypeAny)) != 0; | |
597 } | 587 } |
598 | 588 |
599 // Dispatching routine for visiting the node {node} with the usage {use}. | 589 // Dispatching routine for visiting the node {node} with the usage {use}. |
600 // Depending on the operator, propagate new usage info to the inputs. | 590 // Depending on the operator, propagate new usage info to the inputs. |
601 void VisitNode(Node* node, MachineTypeUnion use, | 591 void VisitNode(Node* node, Truncation truncation, |
602 SimplifiedLowering* lowering) { | 592 SimplifiedLowering* lowering) { |
603 switch (node->opcode()) { | 593 switch (node->opcode()) { |
604 //------------------------------------------------------------------ | 594 //------------------------------------------------------------------ |
605 // Common operators. | 595 // Common operators. |
606 //------------------------------------------------------------------ | 596 //------------------------------------------------------------------ |
607 case IrOpcode::kStart: | 597 case IrOpcode::kStart: |
608 case IrOpcode::kDead: | 598 case IrOpcode::kDead: |
609 return VisitLeaf(node, 0); | 599 return VisitLeaf(node, 0); |
610 case IrOpcode::kParameter: { | 600 case IrOpcode::kParameter: { |
611 // TODO(titzer): use representation from linkage. | 601 // TODO(titzer): use representation from linkage. |
(...skipping 19 matching lines...) Expand all Loading... |
631 | 621 |
632 case IrOpcode::kBranch: | 622 case IrOpcode::kBranch: |
633 ProcessInput(node, 0, UseInfo::Bool()); | 623 ProcessInput(node, 0, UseInfo::Bool()); |
634 Enqueue(NodeProperties::GetControlInput(node, 0)); | 624 Enqueue(NodeProperties::GetControlInput(node, 0)); |
635 break; | 625 break; |
636 case IrOpcode::kSwitch: | 626 case IrOpcode::kSwitch: |
637 ProcessInput(node, 0, UseInfo::TruncatingWord32()); | 627 ProcessInput(node, 0, UseInfo::TruncatingWord32()); |
638 Enqueue(NodeProperties::GetControlInput(node, 0)); | 628 Enqueue(NodeProperties::GetControlInput(node, 0)); |
639 break; | 629 break; |
640 case IrOpcode::kSelect: | 630 case IrOpcode::kSelect: |
641 return VisitSelect(node, use, lowering); | 631 return VisitSelect(node, truncation, lowering); |
642 case IrOpcode::kPhi: | 632 case IrOpcode::kPhi: |
643 return VisitPhi(node, use, lowering); | 633 return VisitPhi(node, truncation, lowering); |
644 case IrOpcode::kCall: | 634 case IrOpcode::kCall: |
645 return VisitCall(node, lowering); | 635 return VisitCall(node, lowering); |
646 | 636 |
647 //------------------------------------------------------------------ | 637 //------------------------------------------------------------------ |
648 // JavaScript operators. | 638 // JavaScript operators. |
649 //------------------------------------------------------------------ | 639 //------------------------------------------------------------------ |
650 // For now, we assume that all JS operators were too complex to lower | 640 // For now, we assume that all JS operators were too complex to lower |
651 // to Simplified and that they will always require tagged value inputs | 641 // to Simplified and that they will always require tagged value inputs |
652 // and produce tagged value outputs. | 642 // and produce tagged value outputs. |
653 // TODO(turbofan): it might be possible to lower some JSOperators here, | 643 // TODO(turbofan): it might be possible to lower some JSOperators here, |
654 // but that responsibility really lies in the typed lowering phase. | 644 // but that responsibility really lies in the typed lowering phase. |
655 #define DEFINE_JS_CASE(x) case IrOpcode::k##x: | 645 #define DEFINE_JS_CASE(x) case IrOpcode::k##x: |
656 JS_OP_LIST(DEFINE_JS_CASE) | 646 JS_OP_LIST(DEFINE_JS_CASE) |
657 #undef DEFINE_JS_CASE | 647 #undef DEFINE_JS_CASE |
658 VisitInputs(node); | 648 VisitInputs(node); |
659 return SetOutput(node, kRepTagged); | 649 return SetOutput(node, kRepTagged); |
660 | 650 |
661 //------------------------------------------------------------------ | 651 //------------------------------------------------------------------ |
662 // Simplified operators. | 652 // Simplified operators. |
663 //------------------------------------------------------------------ | 653 //------------------------------------------------------------------ |
664 case IrOpcode::kBooleanNot: { | 654 case IrOpcode::kBooleanNot: { |
665 if (lower()) { | 655 if (lower()) { |
666 MachineTypeUnion input = GetInfo(node->InputAt(0))->output; | 656 MachineTypeUnion input = GetInfo(node->InputAt(0))->output_type(); |
667 if (input & kRepBit) { | 657 if (input & kRepBit) { |
668 // BooleanNot(x: kRepBit) => Word32Equal(x, #0) | 658 // BooleanNot(x: kRepBit) => Word32Equal(x, #0) |
669 node->AppendInput(jsgraph_->zone(), jsgraph_->Int32Constant(0)); | 659 node->AppendInput(jsgraph_->zone(), jsgraph_->Int32Constant(0)); |
670 NodeProperties::ChangeOp(node, lowering->machine()->Word32Equal()); | 660 NodeProperties::ChangeOp(node, lowering->machine()->Word32Equal()); |
671 } else { | 661 } else { |
672 // BooleanNot(x: kRepTagged) => WordEqual(x, #false) | 662 // BooleanNot(x: kRepTagged) => WordEqual(x, #false) |
673 node->AppendInput(jsgraph_->zone(), jsgraph_->FalseConstant()); | 663 node->AppendInput(jsgraph_->zone(), jsgraph_->FalseConstant()); |
674 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual()); | 664 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual()); |
675 } | 665 } |
676 } else { | 666 } else { |
677 // No input representation requirement; adapt during lowering. | 667 // No input representation requirement; adapt during lowering. |
678 ProcessInput(node, 0, UseInfo::AnyTruncatingToBool()); | 668 ProcessInput(node, 0, UseInfo::AnyTruncatingToBool()); |
679 SetOutput(node, kRepBit); | 669 SetOutput(node, kRepBit); |
680 } | 670 } |
681 break; | 671 break; |
682 } | 672 } |
683 case IrOpcode::kBooleanToNumber: { | 673 case IrOpcode::kBooleanToNumber: { |
684 if (lower()) { | 674 if (lower()) { |
685 MachineTypeUnion input = GetInfo(node->InputAt(0))->output; | 675 MachineTypeUnion input = GetInfo(node->InputAt(0))->output_type(); |
686 if (input & kRepBit) { | 676 if (input & kRepBit) { |
687 // BooleanToNumber(x: kRepBit) => x | 677 // BooleanToNumber(x: kRepBit) => x |
688 DeferReplacement(node, node->InputAt(0)); | 678 DeferReplacement(node, node->InputAt(0)); |
689 } else { | 679 } else { |
690 // BooleanToNumber(x: kRepTagged) => WordEqual(x, #true) | 680 // BooleanToNumber(x: kRepTagged) => WordEqual(x, #true) |
691 node->AppendInput(jsgraph_->zone(), jsgraph_->TrueConstant()); | 681 node->AppendInput(jsgraph_->zone(), jsgraph_->TrueConstant()); |
692 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual()); | 682 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual()); |
693 } | 683 } |
694 } else { | 684 } else { |
695 // No input representation requirement; adapt during lowering. | 685 // No input representation requirement; adapt during lowering. |
(...skipping 18 matching lines...) Expand all Loading... |
714 // => Float64Cmp | 704 // => Float64Cmp |
715 VisitFloat64Cmp(node); | 705 VisitFloat64Cmp(node); |
716 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); | 706 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); |
717 } | 707 } |
718 break; | 708 break; |
719 } | 709 } |
720 case IrOpcode::kNumberAdd: | 710 case IrOpcode::kNumberAdd: |
721 case IrOpcode::kNumberSubtract: { | 711 case IrOpcode::kNumberSubtract: { |
722 // Add and subtract reduce to Int32Add/Sub if the inputs | 712 // Add and subtract reduce to Int32Add/Sub if the inputs |
723 // are already integers and all uses are truncating. | 713 // are already integers and all uses are truncating. |
724 if (CanLowerToWord32AdditiveBinop(node, use)) { | 714 if (CanLowerToWord32AdditiveBinop(node, truncation)) { |
725 // => signed Int32Add/Sub | 715 // => signed Int32Add/Sub |
726 VisitInt32Binop(node); | 716 VisitInt32Binop(node); |
727 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); | 717 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); |
728 } else { | 718 } else { |
729 // => Float64Add/Sub | 719 // => Float64Add/Sub |
730 VisitFloat64Binop(node); | 720 VisitFloat64Binop(node); |
731 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); | 721 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); |
732 } | 722 } |
733 break; | 723 break; |
734 } | 724 } |
735 case IrOpcode::kNumberMultiply: { | 725 case IrOpcode::kNumberMultiply: { |
736 NumberMatcher right(node->InputAt(1)); | 726 NumberMatcher right(node->InputAt(1)); |
737 if (right.IsInRange(-1048576, 1048576)) { // must fit double mantissa. | 727 if (right.IsInRange(-1048576, 1048576)) { // must fit double mantissa. |
738 if (CanLowerToInt32Binop(node, use)) { | 728 if (CanLowerToInt32Binop(node, truncation)) { |
739 // => signed Int32Mul | 729 // => signed Int32Mul |
740 VisitInt32Binop(node); | 730 VisitInt32Binop(node); |
741 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); | 731 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); |
742 break; | 732 break; |
743 } | 733 } |
744 } | 734 } |
745 // => Float64Mul | 735 // => Float64Mul |
746 VisitFloat64Binop(node); | 736 VisitFloat64Binop(node); |
747 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); | 737 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); |
748 break; | 738 break; |
749 } | 739 } |
750 case IrOpcode::kNumberDivide: { | 740 case IrOpcode::kNumberDivide: { |
751 if (CanLowerToInt32Binop(node, use)) { | 741 if (CanLowerToInt32Binop(node, truncation)) { |
752 // => signed Int32Div | 742 // => signed Int32Div |
753 VisitInt32Binop(node); | 743 VisitInt32Binop(node); |
754 if (lower()) DeferReplacement(node, lowering->Int32Div(node)); | 744 if (lower()) DeferReplacement(node, lowering->Int32Div(node)); |
755 break; | 745 break; |
756 } | 746 } |
757 if (BothInputsAre(node, Type::Unsigned32()) && !CanObserveNaN(use)) { | 747 if (BothInputsAre(node, Type::Unsigned32()) && |
| 748 truncation.TruncatesNaNToZero()) { |
758 // => unsigned Uint32Div | 749 // => unsigned Uint32Div |
759 VisitUint32Binop(node); | 750 VisitUint32Binop(node); |
760 if (lower()) DeferReplacement(node, lowering->Uint32Div(node)); | 751 if (lower()) DeferReplacement(node, lowering->Uint32Div(node)); |
761 break; | 752 break; |
762 } | 753 } |
763 // => Float64Div | 754 // => Float64Div |
764 VisitFloat64Binop(node); | 755 VisitFloat64Binop(node); |
765 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); | 756 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); |
766 break; | 757 break; |
767 } | 758 } |
768 case IrOpcode::kNumberModulus: { | 759 case IrOpcode::kNumberModulus: { |
769 if (CanLowerToInt32Binop(node, use)) { | 760 if (CanLowerToInt32Binop(node, truncation)) { |
770 // => signed Int32Mod | 761 // => signed Int32Mod |
771 VisitInt32Binop(node); | 762 VisitInt32Binop(node); |
772 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); | 763 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); |
773 break; | 764 break; |
774 } | 765 } |
775 if (BothInputsAre(node, Type::Unsigned32()) && !CanObserveNaN(use)) { | 766 if (BothInputsAre(node, Type::Unsigned32()) && |
| 767 truncation.TruncatesNaNToZero()) { |
776 // => unsigned Uint32Mod | 768 // => unsigned Uint32Mod |
777 VisitUint32Binop(node); | 769 VisitUint32Binop(node); |
778 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); | 770 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); |
779 break; | 771 break; |
780 } | 772 } |
781 // => Float64Mod | 773 // => Float64Mod |
782 VisitFloat64Binop(node); | 774 VisitFloat64Binop(node); |
783 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); | 775 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); |
784 break; | 776 break; |
785 } | 777 } |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
894 ProcessRemainingInputs(node, 2); | 886 ProcessRemainingInputs(node, 2); |
895 SetOutput(node, 0); | 887 SetOutput(node, 0); |
896 break; | 888 break; |
897 } | 889 } |
898 case IrOpcode::kLoadBuffer: { | 890 case IrOpcode::kLoadBuffer: { |
899 BufferAccess access = BufferAccessOf(node->op()); | 891 BufferAccess access = BufferAccessOf(node->op()); |
900 ProcessInput(node, 0, UseInfo::PointerInt()); // buffer | 892 ProcessInput(node, 0, UseInfo::PointerInt()); // buffer |
901 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // offset | 893 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // offset |
902 ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length | 894 ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length |
903 ProcessRemainingInputs(node, 3); | 895 ProcessRemainingInputs(node, 3); |
904 // Tagged overrides everything if we have to do a typed array bounds | 896 |
905 // check, because we may need to return undefined then. | |
906 MachineType output_type; | 897 MachineType output_type; |
907 if (use & kRepTagged) { | 898 if (truncation.TruncatesUndefinedToZeroOrNaN()) { |
908 output_type = kMachAnyTagged; | 899 if (truncation.TruncatesNaNToZero()) { |
909 } else if (use & kRepFloat64) { | 900 // If undefined is truncated to a non-NaN number, we can use |
910 if (access.machine_type() & kRepFloat32) { | 901 // the load's representation. |
911 output_type = access.machine_type(); | 902 output_type = access.machine_type(); |
912 } else { | 903 } else { |
913 output_type = kMachFloat64; | 904 // If undefined is truncated to a number, but the use can |
| 905 // observe NaN, we need to output at least the float32 |
| 906 // representation. |
| 907 if (access.machine_type() & kRepFloat32) { |
| 908 output_type = access.machine_type(); |
| 909 } else { |
| 910 output_type = kMachFloat64; |
| 911 } |
914 } | 912 } |
915 } else if (use & kRepFloat32) { | |
916 output_type = kMachFloat32; | |
917 } else { | 913 } else { |
918 output_type = access.machine_type(); | 914 // If undefined is not truncated away, we need to have the tagged |
| 915 // representation. |
| 916 output_type = kMachAnyTagged; |
919 } | 917 } |
920 SetOutput(node, output_type); | 918 SetOutput(node, output_type); |
921 if (lower()) lowering->DoLoadBuffer(node, output_type, changer_); | 919 if (lower()) lowering->DoLoadBuffer(node, output_type, changer_); |
922 break; | 920 break; |
923 } | 921 } |
924 case IrOpcode::kStoreBuffer: { | 922 case IrOpcode::kStoreBuffer: { |
925 BufferAccess access = BufferAccessOf(node->op()); | 923 BufferAccess access = BufferAccessOf(node->op()); |
926 ProcessInput(node, 0, UseInfo::PointerInt()); // buffer | 924 ProcessInput(node, 0, UseInfo::PointerInt()); // buffer |
927 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // offset | 925 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // offset |
928 ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length | 926 ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1118 break; | 1116 break; |
1119 } | 1117 } |
1120 } | 1118 } |
1121 | 1119 |
1122 void DeferReplacement(Node* node, Node* replacement) { | 1120 void DeferReplacement(Node* node, Node* replacement) { |
1123 TRACE("defer replacement #%d:%s with #%d:%s\n", node->id(), | 1121 TRACE("defer replacement #%d:%s with #%d:%s\n", node->id(), |
1124 node->op()->mnemonic(), replacement->id(), | 1122 node->op()->mnemonic(), replacement->id(), |
1125 replacement->op()->mnemonic()); | 1123 replacement->op()->mnemonic()); |
1126 | 1124 |
1127 if (replacement->id() < count_ && | 1125 if (replacement->id() < count_ && |
1128 GetInfo(replacement)->output == GetInfo(node)->output) { | 1126 GetInfo(replacement)->output_type() == GetInfo(node)->output_type()) { |
1129 // Replace with a previously existing node eagerly only if the type is the | 1127 // Replace with a previously existing node eagerly only if the type is the |
1130 // same. | 1128 // same. |
1131 node->ReplaceUses(replacement); | 1129 node->ReplaceUses(replacement); |
1132 } else { | 1130 } else { |
1133 // Otherwise, we are replacing a node with a representation change. | 1131 // Otherwise, we are replacing a node with a representation change. |
1134 // Such a substitution must be done after all lowering is done, because | 1132 // Such a substitution must be done after all lowering is done, because |
1135 // changing the type could confuse the representation change | 1133 // changing the type could confuse the representation change |
1136 // insertion for uses of the node. | 1134 // insertion for uses of the node. |
1137 replacements_.push_back(node); | 1135 replacements_.push_back(node); |
1138 replacements_.push_back(replacement); | 1136 replacements_.push_back(replacement); |
1139 } | 1137 } |
1140 node->NullAllInputs(); // Node is now dead. | 1138 node->NullAllInputs(); // Node is now dead. |
1141 } | 1139 } |
1142 | 1140 |
1143 void PrintUseInfo(Node* node) { | |
1144 TRACE("#%d:%-20s ", node->id(), node->op()->mnemonic()); | |
1145 PrintInfo(GetUseInfo(node)); | |
1146 TRACE("\n"); | |
1147 } | |
1148 | |
1149 void PrintInfo(MachineTypeUnion info) { | 1141 void PrintInfo(MachineTypeUnion info) { |
1150 if (FLAG_trace_representation) { | 1142 if (FLAG_trace_representation) { |
1151 OFStream os(stdout); | 1143 OFStream os(stdout); |
1152 os << static_cast<MachineType>(info); | 1144 os << static_cast<MachineType>(info); |
1153 } | 1145 } |
1154 } | 1146 } |
1155 | 1147 |
| 1148 void PrintTruncation(Truncation truncation) { |
| 1149 if (FLAG_trace_representation) { |
| 1150 OFStream os(stdout); |
| 1151 os << truncation.description(); |
| 1152 } |
| 1153 } |
| 1154 |
1156 void PrintUseInfo(UseInfo info) { | 1155 void PrintUseInfo(UseInfo info) { |
1157 if (FLAG_trace_representation) { | 1156 if (FLAG_trace_representation) { |
1158 OFStream os(stdout); | 1157 OFStream os(stdout); |
1159 os << static_cast<MachineType>(info.machine_type()); | 1158 os << info.preferred() << ":" << info.truncation().description(); |
1160 } | 1159 } |
1161 } | 1160 } |
1162 | 1161 |
1163 private: | 1162 private: |
1164 JSGraph* jsgraph_; | 1163 JSGraph* jsgraph_; |
1165 size_t const count_; // number of nodes in the graph | 1164 size_t const count_; // number of nodes in the graph |
1166 NodeInfo* info_; // node id -> usage information | 1165 ZoneVector<NodeInfo> info_; // node id -> usage information |
1167 NodeVector nodes_; // collected nodes | 1166 NodeVector nodes_; // collected nodes |
1168 NodeVector replacements_; // replacements to be done after lowering | 1167 NodeVector replacements_; // replacements to be done after lowering |
1169 Phase phase_; // current phase of algorithm | 1168 Phase phase_; // current phase of algorithm |
1170 RepresentationChanger* changer_; // for inserting representation changes | 1169 RepresentationChanger* changer_; // for inserting representation changes |
1171 ZoneQueue<Node*> queue_; // queue for traversing the graph | 1170 ZoneQueue<Node*> queue_; // queue for traversing the graph |
1172 // TODO(danno): RepresentationSelector shouldn't know anything about the | 1171 // TODO(danno): RepresentationSelector shouldn't know anything about the |
1173 // source positions table, but must for now since there currently is no other | 1172 // source positions table, but must for now since there currently is no other |
1174 // way to pass down source position information to nodes created during | 1173 // way to pass down source position information to nodes created during |
1175 // lowering. Once this phase becomes a vanilla reducer, it should get source | 1174 // lowering. Once this phase becomes a vanilla reducer, it should get source |
1176 // position information via the SourcePositionWrapper like all other reducers. | 1175 // position information via the SourcePositionWrapper like all other reducers. |
1177 SourcePositionTable* source_positions_; | 1176 SourcePositionTable* source_positions_; |
1178 Type* safe_int_additive_range_; | 1177 Type* safe_int_additive_range_; |
1179 | 1178 |
1180 NodeInfo* GetInfo(Node* node) { | 1179 NodeInfo* GetInfo(Node* node) { |
1181 DCHECK(node->id() >= 0); | 1180 DCHECK(node->id() >= 0); |
1182 DCHECK(node->id() < count_); | 1181 DCHECK(node->id() < count_); |
1183 return &info_[node->id()]; | 1182 return &info_[node->id()]; |
1184 } | 1183 } |
1185 | |
1186 MachineTypeUnion GetUseInfo(Node* node) { return GetInfo(node)->use; } | |
1187 }; | 1184 }; |
1188 | 1185 |
1189 | 1186 |
1190 SimplifiedLowering::SimplifiedLowering(JSGraph* jsgraph, Zone* zone, | 1187 SimplifiedLowering::SimplifiedLowering(JSGraph* jsgraph, Zone* zone, |
1191 SourcePositionTable* source_positions) | 1188 SourcePositionTable* source_positions) |
1192 : jsgraph_(jsgraph), | 1189 : jsgraph_(jsgraph), |
1193 zone_(zone), | 1190 zone_(zone), |
1194 zero_thirtyone_range_(Type::Range(0, 31, zone)), | 1191 zero_thirtyone_range_(Type::Range(0, 31, zone)), |
1195 source_positions_(source_positions) {} | 1192 source_positions_(source_positions) {} |
1196 | 1193 |
(...skipping 22 matching lines...) Expand all Loading... |
1219 ? graph()->NewNode(machine()->ChangeUint32ToUint64(), offset) | 1216 ? graph()->NewNode(machine()->ChangeUint32ToUint64(), offset) |
1220 : offset; | 1217 : offset; |
1221 | 1218 |
1222 Node* check = graph()->NewNode(machine()->Uint32LessThan(), offset, length); | 1219 Node* check = graph()->NewNode(machine()->Uint32LessThan(), offset, length); |
1223 Node* branch = | 1220 Node* branch = |
1224 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); | 1221 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); |
1225 | 1222 |
1226 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | 1223 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); |
1227 Node* etrue = | 1224 Node* etrue = |
1228 graph()->NewNode(machine()->Load(type), buffer, index, effect, if_true); | 1225 graph()->NewNode(machine()->Load(type), buffer, index, effect, if_true); |
1229 Node* vtrue = changer->GetRepresentationFor(etrue, type, output_type); | 1226 Node* vtrue = changer->GetRepresentationFor( |
| 1227 etrue, type, RepresentationOf(output_type), Truncation::None()); |
1230 | 1228 |
1231 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | 1229 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); |
1232 Node* efalse = effect; | 1230 Node* efalse = effect; |
1233 Node* vfalse; | 1231 Node* vfalse; |
1234 if (output_type & kRepTagged) { | 1232 if (output_type & kRepTagged) { |
1235 vfalse = jsgraph()->UndefinedConstant(); | 1233 vfalse = jsgraph()->UndefinedConstant(); |
1236 } else if (output_type & kRepFloat64) { | 1234 } else if (output_type & kRepFloat64) { |
1237 vfalse = | 1235 vfalse = |
1238 jsgraph()->Float64Constant(std::numeric_limits<double>::quiet_NaN()); | 1236 jsgraph()->Float64Constant(std::numeric_limits<double>::quiet_NaN()); |
1239 } else if (output_type & kRepFloat32) { | 1237 } else if (output_type & kRepFloat32) { |
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1621 ReplaceEffectUses(node, comparison); | 1619 ReplaceEffectUses(node, comparison); |
1622 node->ReplaceInput(0, comparison); | 1620 node->ReplaceInput(0, comparison); |
1623 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL)); | 1621 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL)); |
1624 node->TrimInputCount(2); | 1622 node->TrimInputCount(2); |
1625 NodeProperties::ChangeOp(node, machine()->IntLessThanOrEqual()); | 1623 NodeProperties::ChangeOp(node, machine()->IntLessThanOrEqual()); |
1626 } | 1624 } |
1627 | 1625 |
1628 } // namespace compiler | 1626 } // namespace compiler |
1629 } // namespace internal | 1627 } // namespace internal |
1630 } // namespace v8 | 1628 } // namespace v8 |
OLD | NEW |