Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(137)

Side by Side Diff: src/compiler/simplified-lowering.cc

Issue 1464763003: [turbofan] Replace information about uses by UseInfo in representation selection. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: final goodness Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/compiler/representation-change.h ('k') | test/cctest/compiler/test-representation-change.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698