Chromium Code Reviews| 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 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 266 } | 266 } |
| 267 void VisitFloat64Cmp(Node* node) { VisitBinop(node, kMachFloat64, kRepBit); } | 267 void VisitFloat64Cmp(Node* node) { VisitBinop(node, kMachFloat64, kRepBit); } |
| 268 void VisitInt32Cmp(Node* node) { VisitBinop(node, kMachInt32, kRepBit); } | 268 void VisitInt32Cmp(Node* node) { VisitBinop(node, kMachInt32, kRepBit); } |
| 269 void VisitUint32Cmp(Node* node) { VisitBinop(node, kMachUint32, kRepBit); } | 269 void VisitUint32Cmp(Node* node) { VisitBinop(node, kMachUint32, kRepBit); } |
| 270 void VisitInt64Cmp(Node* node) { VisitBinop(node, kMachInt64, kRepBit); } | 270 void VisitInt64Cmp(Node* node) { VisitBinop(node, kMachInt64, kRepBit); } |
| 271 void VisitUint64Cmp(Node* node) { VisitBinop(node, kMachUint64, kRepBit); } | 271 void VisitUint64Cmp(Node* node) { VisitBinop(node, kMachUint64, kRepBit); } |
| 272 | 272 |
| 273 // Helper for handling phis. | 273 // Helper for handling phis. |
| 274 void VisitPhi(Node* node, MachineTypeUnion use, | 274 void VisitPhi(Node* node, MachineTypeUnion use, |
| 275 SimplifiedLowering* lowering) { | 275 SimplifiedLowering* lowering) { |
| 276 // First, propagate the usage information to inputs of the phi. | 276 // Phis adapt to the output representation their uses demand, pushing |
| 277 if (!lower()) { | 277 // representation changes to their inputs. |
| 278 int values = OperatorProperties::GetValueInputCount(node->op()); | 278 Type* upper = NodeProperties::GetBounds(node).upper; |
| 279 // Propagate {use} of the phi to value inputs, and 0 to control. | 279 MachineType output = kMachNone; |
| 280 Node::Inputs inputs = node->inputs(); | 280 MachineType prop = kMachNone; |
|
Jarin
2014/10/08 15:12:03
How about expanding to {propagate}?
titzer
2014/10/15 11:51:49
Done.
| |
| 281 for (Node::Inputs::iterator iter(inputs.begin()); iter != inputs.end(); | 281 |
| 282 ++iter, --values) { | 282 if (upper->Is(Type::Signed32()) || upper->Is(Type::Unsigned32())) { |
| 283 // TODO(titzer): it'd be nice to have distinguished edge kinds here. | 283 // legal = kRepTagged | kRepFloat64 | kRepWord32; |
| 284 ProcessInput(node, iter.index(), values > 0 ? use : 0); | 284 if ((use & kRepMask) == kRepTagged) { |
| 285 // only tagged uses. | |
| 286 output = kRepTagged; | |
| 287 prop = kRepTagged; | |
| 288 } else if ((use & kRepMask) == kRepFloat64) { | |
| 289 // only float64 uses. | |
| 290 output = kRepFloat64; | |
| 291 prop = kRepFloat64; | |
| 292 } else { | |
| 293 // multiple uses. | |
| 294 output = kRepWord32; | |
| 295 prop = kRepWord32; | |
| 285 } | 296 } |
| 297 } else if (upper->Is(Type::Boolean())) { | |
| 298 // legal = kRepTagged | kRepBit; | |
| 299 if ((use & kRepMask) == kRepTagged) { | |
| 300 // only tagged uses. | |
| 301 output = kRepTagged; | |
| 302 prop = kRepTagged; | |
| 303 } else { | |
| 304 // multiple uses. | |
| 305 output = kRepBit; | |
| 306 prop = kRepBit; | |
| 307 } | |
| 308 } else if (upper->Is(Type::Number())) { | |
| 309 // legal = kRepTagged | kRepFloat64; | |
| 310 if ((use & kRepMask) == kRepTagged) { | |
| 311 // only tagged uses. | |
| 312 output = kRepTagged; | |
| 313 prop = kRepTagged; | |
| 314 } else { | |
| 315 // multiple uses. | |
| 316 output = kRepFloat64; | |
| 317 prop = kRepFloat64; | |
| 318 } | |
| 319 } else { | |
| 320 // legal = kRepTagged; | |
| 321 output = kRepTagged; | |
| 322 prop = kRepTagged; | |
| 286 } | 323 } |
| 287 // Phis adapt to whatever output representation their uses demand, | 324 |
| 288 // pushing representation changes to their inputs. | 325 MachineType output_type = |
| 289 MachineTypeUnion use_rep = GetUseInfo(node) & kRepMask; | 326 static_cast<MachineType>(changer_->TypeFromUpperBound(upper) | output); |
| 290 Type* upper = NodeProperties::GetBounds(node).upper; | |
| 291 MachineTypeUnion phi_type = changer_->TypeFromUpperBound(upper); | |
| 292 MachineTypeUnion rep = 0; | |
| 293 if (use_rep & kRepTagged) { | |
| 294 rep = kRepTagged; // Tagged overrides everything. | |
| 295 } else if (use_rep & kRepFloat32) { | |
| 296 rep = kRepFloat32; | |
| 297 } else if (use_rep & kRepFloat64) { | |
| 298 rep = kRepFloat64; | |
| 299 } else if (use_rep & kRepWord64) { | |
| 300 rep = kRepWord64; | |
| 301 } else if (use_rep & kRepWord32) { | |
| 302 if (phi_type & kTypeNumber) { | |
| 303 rep = kRepFloat64; | |
| 304 } else { | |
| 305 rep = kRepWord32; | |
| 306 } | |
| 307 } else if (use_rep & kRepBit) { | |
| 308 rep = kRepBit; | |
| 309 } else { | |
| 310 // There was no representation associated with any of the uses. | |
| 311 if (phi_type & kTypeAny) { | |
| 312 rep = kRepTagged; | |
| 313 } else if (phi_type & kTypeNumber) { | |
| 314 rep = kRepFloat64; | |
| 315 } else if (phi_type & kTypeInt64 || phi_type & kTypeUint64) { | |
| 316 rep = kRepWord64; | |
| 317 } else if (phi_type & kTypeInt32 || phi_type & kTypeUint32) { | |
| 318 rep = kRepWord32; | |
| 319 } else if (phi_type & kTypeBool) { | |
| 320 rep = kRepBit; | |
| 321 } else { | |
| 322 UNREACHABLE(); // should have at least a usage type! | |
| 323 } | |
| 324 } | |
| 325 // Preserve the usage type, but set the representation. | |
| 326 MachineTypeUnion output_type = rep | phi_type; | |
| 327 SetOutput(node, output_type); | 327 SetOutput(node, output_type); |
| 328 | 328 |
| 329 int values = OperatorProperties::GetValueInputCount(node->op()); | |
| 330 | |
| 329 if (lower()) { | 331 if (lower()) { |
| 330 int values = OperatorProperties::GetValueInputCount(node->op()); | |
| 331 | |
| 332 // Update the phi operator. | 332 // Update the phi operator. |
| 333 MachineType type = static_cast<MachineType>(output_type); | 333 MachineType type = static_cast<MachineType>(output_type); |
| 334 if (type != OpParameter<MachineType>(node)) { | 334 if (type != OpParameter<MachineType>(node)) { |
| 335 node->set_op(lowering->common()->Phi(type, values)); | 335 node->set_op(lowering->common()->Phi(type, values)); |
| 336 } | 336 } |
| 337 | 337 |
| 338 // Convert inputs to the output representation of this phi. | 338 // Convert inputs to the output representation of this phi. |
| 339 Node::Inputs inputs = node->inputs(); | 339 Node::Inputs inputs = node->inputs(); |
| 340 for (Node::Inputs::iterator iter(inputs.begin()); iter != inputs.end(); | 340 for (Node::Inputs::iterator iter(inputs.begin()); iter != inputs.end(); |
| 341 ++iter, --values) { | 341 ++iter, --values) { |
| 342 // TODO(titzer): it'd be nice to have distinguished edge kinds here. | 342 // TODO(titzer): it'd be nice to have distinguished edge kinds here. |
| 343 ProcessInput(node, iter.index(), values > 0 ? output_type : 0); | 343 ProcessInput(node, iter.index(), values > 0 ? output_type : 0); |
| 344 } | 344 } |
| 345 } else { | |
| 346 // Propagate {use} of the phi to value inputs, and 0 to control. | |
| 347 Node::Inputs inputs = node->inputs(); | |
| 348 MachineType use_type = static_cast<MachineType>((use & kTypeMask) | prop); | |
| 349 for (Node::Inputs::iterator iter(inputs.begin()); iter != inputs.end(); | |
| 350 ++iter, --values) { | |
| 351 // TODO(titzer): it'd be nice to have distinguished edge kinds here. | |
| 352 ProcessInput(node, iter.index(), values > 0 ? use_type : 0); | |
| 353 } | |
| 345 } | 354 } |
| 346 } | 355 } |
| 347 | 356 |
| 348 const Operator* Int32Op(Node* node) { | 357 const Operator* Int32Op(Node* node) { |
| 349 return changer_->Int32OperatorFor(node->opcode()); | 358 return changer_->Int32OperatorFor(node->opcode()); |
| 350 } | 359 } |
| 351 | 360 |
| 352 const Operator* Uint32Op(Node* node) { | 361 const Operator* Uint32Op(Node* node) { |
| 353 return changer_->Uint32OperatorFor(node->opcode()); | 362 return changer_->Uint32OperatorFor(node->opcode()); |
| 354 } | 363 } |
| (...skipping 769 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1124 void SimplifiedLowering::DoStringLessThanOrEqual(Node* node) { | 1133 void SimplifiedLowering::DoStringLessThanOrEqual(Node* node) { |
| 1125 node->set_op(machine()->IntLessThanOrEqual()); | 1134 node->set_op(machine()->IntLessThanOrEqual()); |
| 1126 node->ReplaceInput(0, StringComparison(node, true)); | 1135 node->ReplaceInput(0, StringComparison(node, true)); |
| 1127 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL)); | 1136 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL)); |
| 1128 } | 1137 } |
| 1129 | 1138 |
| 1130 | 1139 |
| 1131 } // namespace compiler | 1140 } // namespace compiler |
| 1132 } // namespace internal | 1141 } // namespace internal |
| 1133 } // namespace v8 | 1142 } // namespace v8 |
| OLD | NEW |