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 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 49 // 2.) LOWER: perform lowering for all {Simplified} nodes by replacing some | 49 // 2.) LOWER: perform lowering for all {Simplified} nodes by replacing some |
| 50 // operators for some nodes, expanding some nodes to multiple nodes, or | 50 // operators for some nodes, expanding some nodes to multiple nodes, or |
| 51 // removing some (redundant) nodes. | 51 // removing some (redundant) nodes. |
| 52 // During this phase, use the {RepresentationChanger} to insert | 52 // During this phase, use the {RepresentationChanger} to insert |
| 53 // representation changes between uses that demand a particular | 53 // representation changes between uses that demand a particular |
| 54 // representation and nodes that produce a different representation. | 54 // representation and nodes that produce a different representation. |
| 55 LOWER | 55 LOWER |
| 56 }; | 56 }; |
| 57 | 57 |
| 58 | 58 |
| 59 namespace { | |
| 60 | |
| 61 // The {UseInfo} class is used to describe a use of an input of a node. | |
| 62 // | |
| 63 // This information is used in two different ways, based on the phase: | |
| 64 // | |
| 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 | |
| 67 // is the preferred representation. | |
| 68 // | |
| 69 // 2. During lowering, the use info is used to properly convert the input | |
| 70 // to the preferred representation. The preferred representation might be | |
| 71 // insufficient to do the conversion (e.g. word32->float64 conv), so we also | |
| 72 // need the signedness information to produce the correct value. | |
| 73 struct UseInfo { | |
|
Benedikt Meurer
2015/11/19 10:38:31
Nit: class please
Jarin
2015/11/19 10:44:59
Done.
| |
| 74 // Constructors | |
| 75 // ================================================================ | |
| 76 | |
| 77 // Uses truncating to the preferred representation. | |
| 78 static UseInfo TruncatingWord32() { | |
| 79 return UseInfo(kTypeInt32 | kTypeUint32 | kRepWord32); | |
| 80 } | |
| 81 static UseInfo TruncatingWord64() { | |
| 82 return UseInfo(kTypeInt64 | kTypeUint64 | kRepWord64); | |
| 83 } | |
| 84 static UseInfo Bool() { return UseInfo(kMachBool); } | |
| 85 static UseInfo Float32() { return UseInfo(kMachFloat32); } | |
| 86 static UseInfo Float64() { return UseInfo(kMachFloat64); } | |
| 87 static UseInfo PointerInt() { | |
| 88 return kPointerSize == 4 ? TruncatingWord32() : TruncatingWord64(); | |
| 89 } | |
| 90 | |
| 91 // Non-truncating uses. | |
| 92 static UseInfo AnyTagged() { return UseInfo(kMachAnyTagged); } | |
| 93 static UseInfo Any() { return UseInfo(kTypeAny); } | |
| 94 | |
| 95 // Ignored-value 'use'. | |
| 96 static UseInfo None() { return UseInfo(kMachNone); } | |
| 97 | |
| 98 // Truncating to a representation that is smaller than the preferred | |
| 99 // one. | |
| 100 static UseInfo Float64TruncatingToWord32() { | |
| 101 return UseInfo(kRepFloat64 | kTypeInt32 | kTypeUint32); | |
| 102 } | |
| 103 static UseInfo Word64TruncatingToWord32() { | |
| 104 return UseInfo(kRepWord64 | kTypeInt32 | kTypeUint32); | |
| 105 } | |
| 106 static UseInfo AnyTruncatingToBool() { return UseInfo(kTypeBool); } | |
| 107 | |
| 108 UseInfo(MachineTypeUnion representation, MachineTypeUnion truncation) | |
| 109 : type_(representation | truncation) { | |
| 110 DCHECK(base::bits::CountPopulation32(representation & kRepMask) == 1); | |
| 111 DCHECK((representation & kTypeMask) == 0); | |
| 112 DCHECK((truncation & kRepMask) == 0); | |
| 113 // TODO(jarin) Check/normalize truncation? | |
| 114 } | |
| 115 | |
| 116 // Queries | |
| 117 // ================================================================ | |
| 118 MachineType GetRepresentation() const { | |
| 119 return static_cast<MachineType>(type_ & kRepMask); | |
| 120 } | |
| 121 | |
| 122 // This should only be used by the Enqueue method. | |
| 123 MachineTypeUnion machine_type() const { return type_; } | |
| 124 | |
| 125 private: | |
| 126 explicit UseInfo(MachineTypeUnion type) : type_(type) {} | |
| 127 | |
| 128 MachineTypeUnion type_; | |
| 129 }; | |
| 130 | |
| 131 | |
| 132 UseInfo UseInfoFromRepresentation(MachineTypeUnion rep) { | |
| 133 DCHECK((rep & kTypeMask) == 0); | |
| 134 if (rep & kRepTagged) return UseInfo::AnyTagged(); | |
| 135 if (rep & kRepFloat64) { | |
| 136 DCHECK((rep & kRepWord64) == 0); | |
| 137 return UseInfo::Float64(); | |
| 138 } | |
| 139 if (rep & kRepFloat32) { | |
| 140 if (rep == kRepFloat32) return UseInfo::Float32(); | |
| 141 return UseInfo::AnyTagged(); | |
| 142 } | |
| 143 if (rep & kRepWord64) { | |
| 144 return UseInfo::TruncatingWord64(); | |
| 145 } | |
| 146 if (rep & (kRepWord32 | kRepWord16 | kRepWord8)) { | |
| 147 CHECK(!(rep & kRepBit)); | |
| 148 return UseInfo::TruncatingWord32(); | |
| 149 } | |
| 150 DCHECK(rep & kRepBit); | |
| 151 return UseInfo::Bool(); | |
| 152 } | |
| 153 | |
| 154 | |
| 155 UseInfo UseInfoFromMachineType(MachineType type) { | |
| 156 return UseInfoFromRepresentation(RepresentationOf(type)); | |
| 157 } | |
| 158 | |
| 159 | |
| 160 UseInfo UseInfoForBasePointer(const FieldAccess& access) { | |
| 161 return access.tag() != 0 ? UseInfo::AnyTagged() : UseInfo::PointerInt(); | |
| 162 } | |
| 163 | |
| 164 | |
| 165 UseInfo UseInfoForBasePointer(const ElementAccess& access) { | |
| 166 return access.tag() != 0 ? UseInfo::AnyTagged() : UseInfo::PointerInt(); | |
| 167 } | |
| 168 | |
| 169 } // namespace | |
| 170 | |
| 171 | |
| 59 class RepresentationSelector { | 172 class RepresentationSelector { |
| 60 public: | 173 public: |
| 61 // Information for each node tracked during the fixpoint. | 174 // Information for each node tracked during the fixpoint. |
| 62 struct NodeInfo { | 175 struct NodeInfo { |
| 63 MachineTypeUnion use : 15; // Union of all usages for the node. | 176 MachineTypeUnion use : 15; // Union of all usages for the node. |
| 64 bool queued : 1; // Bookkeeping for the traversal. | 177 bool queued : 1; // Bookkeeping for the traversal. |
| 65 bool visited : 1; // Bookkeeping for the traversal. | 178 bool visited : 1; // Bookkeeping for the traversal. |
| 66 MachineTypeUnion output : 15; // Output type of the node. | 179 MachineTypeUnion output : 15; // Output type of the node. |
| 67 }; | 180 }; |
| 68 | 181 |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 124 // We also need to replace the node in the rest of the vector. | 237 // We also need to replace the node in the rest of the vector. |
| 125 for (NodeVector::iterator j = i + 1; j != replacements_.end(); ++j) { | 238 for (NodeVector::iterator j = i + 1; j != replacements_.end(); ++j) { |
| 126 ++j; | 239 ++j; |
| 127 if (*j == node) *j = replacement; | 240 if (*j == node) *j = replacement; |
| 128 } | 241 } |
| 129 } | 242 } |
| 130 } | 243 } |
| 131 | 244 |
| 132 // Enqueue {node} if the {use} contains new information for that node. | 245 // Enqueue {node} if the {use} contains new information for that node. |
| 133 // Add {node} to {nodes_} if this is the first time it's been visited. | 246 // Add {node} to {nodes_} if this is the first time it's been visited. |
| 134 void Enqueue(Node* node, MachineTypeUnion use = 0) { | 247 void Enqueue(Node* node, UseInfo use_info = UseInfo::None()) { |
| 248 MachineTypeUnion use = use_info.machine_type(); | |
| 249 | |
| 135 if (phase_ != PROPAGATE) return; | 250 if (phase_ != PROPAGATE) return; |
| 136 NodeInfo* info = GetInfo(node); | 251 NodeInfo* info = GetInfo(node); |
| 137 if (!info->visited) { | 252 if (!info->visited) { |
| 138 // First visit of this node. | 253 // First visit of this node. |
| 139 info->visited = true; | 254 info->visited = true; |
| 140 info->queued = true; | 255 info->queued = true; |
| 141 nodes_.push_back(node); | 256 nodes_.push_back(node); |
| 142 queue_.push(node); | 257 queue_.push(node); |
| 143 TRACE(" initial: "); | 258 TRACE(" initial: "); |
| 144 info->use |= use; | 259 info->use |= use; |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 156 } else { | 271 } else { |
| 157 TRACE(" inqueue: "); | 272 TRACE(" inqueue: "); |
| 158 } | 273 } |
| 159 info->use |= use; | 274 info->use |= use; |
| 160 PrintUseInfo(node); | 275 PrintUseInfo(node); |
| 161 } | 276 } |
| 162 } | 277 } |
| 163 | 278 |
| 164 bool lower() { return phase_ == LOWER; } | 279 bool lower() { return phase_ == LOWER; } |
| 165 | 280 |
| 166 void Enqueue(Node* node, MachineType use) { | |
| 167 Enqueue(node, static_cast<MachineTypeUnion>(use)); | |
| 168 } | |
| 169 | |
| 170 void SetOutput(Node* node, MachineTypeUnion output) { | 281 void SetOutput(Node* node, MachineTypeUnion output) { |
| 171 // Every node should have at most one output representation. Note that | 282 // Every node should have at most one output representation. Note that |
| 172 // phis can have 0, if they have not been used in a representation-inducing | 283 // phis can have 0, if they have not been used in a representation-inducing |
| 173 // instruction. | 284 // instruction. |
| 174 DCHECK((output & kRepMask) == 0 || | 285 DCHECK((output & kRepMask) == 0 || |
| 175 base::bits::IsPowerOfTwo32(output & kRepMask)); | 286 base::bits::IsPowerOfTwo32(output & kRepMask)); |
| 176 GetInfo(node)->output = output; | 287 GetInfo(node)->output = output; |
| 177 } | 288 } |
| 178 | 289 |
| 179 bool BothInputsAre(Node* node, Type* type) { | 290 bool BothInputsAre(Node* node, Type* type) { |
| 180 DCHECK_EQ(2, node->InputCount()); | 291 DCHECK_EQ(2, node->InputCount()); |
| 181 return NodeProperties::GetType(node->InputAt(0))->Is(type) && | 292 return NodeProperties::GetType(node->InputAt(0))->Is(type) && |
| 182 NodeProperties::GetType(node->InputAt(1))->Is(type); | 293 NodeProperties::GetType(node->InputAt(1))->Is(type); |
| 183 } | 294 } |
| 184 | 295 |
| 185 void ProcessTruncateWord32Input(Node* node, int index, MachineTypeUnion use) { | 296 void ProcessTruncateWord32Input(Node* node, int index) { |
| 186 Node* input = node->InputAt(index); | 297 Node* input = node->InputAt(index); |
| 187 if (phase_ == PROPAGATE) { | 298 if (phase_ == PROPAGATE) { |
| 188 // In the propagate phase, propagate the usage information backward. | 299 // In the propagate phase, propagate the usage information backward. |
| 189 Enqueue(input, use); | 300 Enqueue(input, UseInfo::TruncatingWord32()); |
| 190 } else { | 301 } else { |
| 191 // In the change phase, insert a change before the use if necessary. | 302 // In the change phase, insert a change before the use if necessary. |
| 192 MachineTypeUnion output = GetInfo(input)->output; | 303 MachineTypeUnion output = GetInfo(input)->output; |
| 193 if ((output & (kRepBit | kRepWord8 | kRepWord16 | kRepWord32)) == 0) { | 304 if ((output & (kRepBit | kRepWord8 | kRepWord16 | kRepWord32)) == 0) { |
| 194 // Output representation doesn't match usage. | 305 // Output representation doesn't match usage. |
| 195 TRACE(" truncate-to-int32: #%d:%s(@%d #%d:%s) ", node->id(), | 306 TRACE(" truncate-to-int32: #%d:%s(@%d #%d:%s) ", node->id(), |
| 196 node->op()->mnemonic(), index, input->id(), | 307 node->op()->mnemonic(), index, input->id(), |
| 197 input->op()->mnemonic()); | 308 input->op()->mnemonic()); |
| 198 TRACE(" from "); | 309 TRACE(" from "); |
| 199 PrintInfo(output); | 310 PrintInfo(output); |
| 200 TRACE(" to "); | |
| 201 PrintInfo(use); | |
| 202 TRACE("\n"); | 311 TRACE("\n"); |
| 203 Node* n = changer_->GetTruncatedWord32For(input, output); | 312 Node* n = changer_->GetTruncatedWord32For(input, output); |
| 204 node->ReplaceInput(index, n); | 313 node->ReplaceInput(index, n); |
| 205 } | 314 } |
| 206 } | 315 } |
| 207 } | 316 } |
| 208 | 317 |
| 209 void ProcessInput(Node* node, int index, MachineTypeUnion use) { | 318 void EnqueueInputUse(Node* node, int index, UseInfo use) { |
| 319 Enqueue(node->InputAt(index), use); | |
| 320 } | |
| 321 | |
| 322 void ConvertInput(Node* node, int index, UseInfo use) { | |
| 210 Node* input = node->InputAt(index); | 323 Node* input = node->InputAt(index); |
| 211 if (phase_ == PROPAGATE) { | 324 // In the change phase, insert a change before the use if necessary. |
| 212 // In the propagate phase, propagate the usage information backward. | 325 if (use.GetRepresentation() == kMachNone) |
| 213 Enqueue(input, use); | 326 return; // No input requirement on the use. |
| 214 } else { | 327 MachineTypeUnion output = GetInfo(input)->output; |
| 215 // In the change phase, insert a change before the use if necessary. | 328 if ((output & kRepMask) != use.GetRepresentation()) { |
| 216 if ((use & kRepMask) == 0) return; // No input requirement on the use. | 329 // Output representation doesn't match usage. |
| 217 MachineTypeUnion output = GetInfo(input)->output; | 330 TRACE(" change: #%d:%s(@%d #%d:%s) ", node->id(), node->op()->mnemonic(), |
| 218 if ((output & kRepMask & use) == 0) { | 331 index, input->id(), input->op()->mnemonic()); |
| 219 // Output representation doesn't match usage. | 332 TRACE(" from "); |
| 220 TRACE(" change: #%d:%s(@%d #%d:%s) ", node->id(), | 333 PrintInfo(output); |
| 221 node->op()->mnemonic(), index, input->id(), | 334 TRACE(" to "); |
| 222 input->op()->mnemonic()); | 335 PrintUseInfo(use); |
| 223 TRACE(" from "); | 336 TRACE("\n"); |
| 224 PrintInfo(output); | 337 Node* n = |
| 225 TRACE(" to "); | 338 changer_->GetRepresentationFor(input, output, use.machine_type()); |
| 226 PrintInfo(use); | 339 node->ReplaceInput(index, n); |
| 227 TRACE("\n"); | |
| 228 Node* n = changer_->GetRepresentationFor(input, output, use); | |
| 229 node->ReplaceInput(index, n); | |
| 230 } | |
| 231 } | 340 } |
| 232 } | 341 } |
| 233 | 342 |
| 343 void ProcessInput(Node* node, int index, UseInfo use) { | |
| 344 if (phase_ == PROPAGATE) { | |
| 345 EnqueueInputUse(node, index, use); | |
| 346 } else { | |
| 347 ConvertInput(node, index, use); | |
| 348 } | |
| 349 } | |
| 350 | |
| 234 void ProcessRemainingInputs(Node* node, int index) { | 351 void ProcessRemainingInputs(Node* node, int index) { |
| 235 DCHECK_GE(index, NodeProperties::PastValueIndex(node)); | 352 DCHECK_GE(index, NodeProperties::PastValueIndex(node)); |
| 236 DCHECK_GE(index, NodeProperties::PastContextIndex(node)); | 353 DCHECK_GE(index, NodeProperties::PastContextIndex(node)); |
| 237 for (int i = std::max(index, NodeProperties::FirstEffectIndex(node)); | 354 for (int i = std::max(index, NodeProperties::FirstEffectIndex(node)); |
| 238 i < NodeProperties::PastEffectIndex(node); ++i) { | 355 i < NodeProperties::PastEffectIndex(node); ++i) { |
| 239 Enqueue(node->InputAt(i)); // Effect inputs: just visit | 356 Enqueue(node->InputAt(i)); // Effect inputs: just visit |
| 240 } | 357 } |
| 241 for (int i = std::max(index, NodeProperties::FirstControlIndex(node)); | 358 for (int i = std::max(index, NodeProperties::FirstControlIndex(node)); |
| 242 i < NodeProperties::PastControlIndex(node); ++i) { | 359 i < NodeProperties::PastControlIndex(node); ++i) { |
| 243 Enqueue(node->InputAt(i)); // Control inputs: just visit | 360 Enqueue(node->InputAt(i)); // Control inputs: just visit |
| 244 } | 361 } |
| 245 } | 362 } |
| 246 | 363 |
| 247 // The default, most general visitation case. For {node}, process all value, | 364 // The default, most general visitation case. For {node}, process all value, |
| 248 // context, frame state, effect, and control inputs, assuming that value | 365 // context, frame state, effect, and control inputs, assuming that value |
| 249 // inputs should have {kRepTagged} representation and can observe all output | 366 // inputs should have {kRepTagged} representation and can observe all output |
| 250 // values {kTypeAny}. | 367 // values {kTypeAny}. |
| 251 void VisitInputs(Node* node) { | 368 void VisitInputs(Node* node) { |
| 252 int tagged_count = node->op()->ValueInputCount() + | 369 int tagged_count = node->op()->ValueInputCount() + |
| 253 OperatorProperties::GetContextInputCount(node->op()); | 370 OperatorProperties::GetContextInputCount(node->op()); |
| 254 // Visit value and context inputs as tagged. | 371 // Visit value and context inputs as tagged. |
| 255 for (int i = 0; i < tagged_count; i++) { | 372 for (int i = 0; i < tagged_count; i++) { |
| 256 ProcessInput(node, i, kMachAnyTagged); | 373 ProcessInput(node, i, UseInfo::AnyTagged()); |
| 257 } | 374 } |
| 258 // Only enqueue other inputs (framestates, effects, control). | 375 // Only enqueue other inputs (framestates, effects, control). |
| 259 for (int i = tagged_count; i < node->InputCount(); i++) { | 376 for (int i = tagged_count; i < node->InputCount(); i++) { |
| 260 Enqueue(node->InputAt(i)); | 377 Enqueue(node->InputAt(i)); |
| 261 } | 378 } |
| 262 // Assume the output is tagged. | 379 // Assume the output is tagged. |
| 263 SetOutput(node, kMachAnyTagged); | 380 SetOutput(node, kMachAnyTagged); |
| 264 } | 381 } |
| 265 | 382 |
| 266 // Helper for binops of the R x L -> O variety. | 383 // Helper for binops of the R x L -> O variety. |
| 267 void VisitBinop(Node* node, MachineTypeUnion left_use, | 384 void VisitBinop(Node* node, UseInfo left_use, UseInfo right_use, |
| 268 MachineTypeUnion right_use, MachineTypeUnion output) { | 385 MachineTypeUnion output) { |
| 269 DCHECK_EQ(2, node->op()->ValueInputCount()); | 386 DCHECK_EQ(2, node->op()->ValueInputCount()); |
| 270 ProcessInput(node, 0, left_use); | 387 ProcessInput(node, 0, left_use); |
| 271 ProcessInput(node, 1, right_use); | 388 ProcessInput(node, 1, right_use); |
| 272 for (int i = 2; i < node->InputCount(); i++) { | 389 for (int i = 2; i < node->InputCount(); i++) { |
| 273 Enqueue(node->InputAt(i)); | 390 Enqueue(node->InputAt(i)); |
| 274 } | 391 } |
| 275 SetOutput(node, output); | 392 SetOutput(node, output); |
| 276 } | 393 } |
| 277 | 394 |
| 278 // Helper for binops of the I x I -> O variety. | 395 // Helper for binops of the I x I -> O variety. |
| 279 void VisitBinop(Node* node, MachineTypeUnion input_use, | 396 void VisitBinop(Node* node, UseInfo input_use, MachineTypeUnion output) { |
| 280 MachineTypeUnion output) { | |
| 281 VisitBinop(node, input_use, input_use, output); | 397 VisitBinop(node, input_use, input_use, output); |
| 282 } | 398 } |
| 283 | 399 |
| 284 // Helper for unops of the I -> O variety. | 400 // Helper for unops of the I -> O variety. |
| 285 void VisitUnop(Node* node, MachineTypeUnion input_use, | 401 void VisitUnop(Node* node, UseInfo input_use, MachineTypeUnion output) { |
| 286 MachineTypeUnion output) { | |
| 287 DCHECK_EQ(1, node->InputCount()); | 402 DCHECK_EQ(1, node->InputCount()); |
| 288 ProcessInput(node, 0, input_use); | 403 ProcessInput(node, 0, input_use); |
| 289 SetOutput(node, output); | 404 SetOutput(node, output); |
| 290 } | 405 } |
| 291 | 406 |
| 292 // Helper for leaf nodes. | 407 // Helper for leaf nodes. |
| 293 void VisitLeaf(Node* node, MachineTypeUnion output) { | 408 void VisitLeaf(Node* node, MachineTypeUnion output) { |
| 294 DCHECK_EQ(0, node->InputCount()); | 409 DCHECK_EQ(0, node->InputCount()); |
| 295 SetOutput(node, output); | 410 SetOutput(node, output); |
| 296 } | 411 } |
| 297 | 412 |
| 298 // Helpers for specific types of binops. | 413 // Helpers for specific types of binops. |
| 299 void VisitFloat64Binop(Node* node) { | 414 void VisitFloat64Binop(Node* node) { |
| 300 VisitBinop(node, kMachFloat64, kMachFloat64); | 415 VisitBinop(node, UseInfo::Float64(), kMachFloat64); |
| 301 } | 416 } |
| 302 void VisitInt32Binop(Node* node) { VisitBinop(node, kMachInt32, kMachInt32); } | 417 void VisitInt32Binop(Node* node) { |
| 418 VisitBinop(node, UseInfo::TruncatingWord32(), kMachInt32); | |
| 419 } | |
| 303 void VisitUint32Binop(Node* node) { | 420 void VisitUint32Binop(Node* node) { |
| 304 VisitBinop(node, kMachUint32, kMachUint32); | 421 VisitBinop(node, UseInfo::TruncatingWord32(), kMachUint32); |
| 305 } | 422 } |
| 306 void VisitInt64Binop(Node* node) { VisitBinop(node, kMachInt64, kMachInt64); } | 423 void VisitInt64Binop(Node* node) { |
| 424 VisitBinop(node, UseInfo::TruncatingWord64(), kMachInt64); | |
| 425 } | |
| 307 void VisitUint64Binop(Node* node) { | 426 void VisitUint64Binop(Node* node) { |
| 308 VisitBinop(node, kMachUint64, kMachUint64); | 427 VisitBinop(node, UseInfo::TruncatingWord64(), kMachUint64); |
| 309 } | 428 } |
| 310 void VisitFloat64Cmp(Node* node) { VisitBinop(node, kMachFloat64, kRepBit); } | 429 void VisitFloat64Cmp(Node* node) { |
| 311 void VisitInt32Cmp(Node* node) { VisitBinop(node, kMachInt32, kRepBit); } | 430 VisitBinop(node, UseInfo::Float64(), kMachBool); |
| 312 void VisitUint32Cmp(Node* node) { VisitBinop(node, kMachUint32, kRepBit); } | 431 } |
| 313 void VisitInt64Cmp(Node* node) { VisitBinop(node, kMachInt64, kRepBit); } | 432 void VisitInt32Cmp(Node* node) { |
| 314 void VisitUint64Cmp(Node* node) { VisitBinop(node, kMachUint64, kRepBit); } | 433 VisitBinop(node, UseInfo::TruncatingWord32(), kMachBool); |
| 434 } | |
| 435 void VisitUint32Cmp(Node* node) { | |
| 436 VisitBinop(node, UseInfo::TruncatingWord32(), kMachBool); | |
| 437 } | |
| 438 void VisitInt64Cmp(Node* node) { | |
| 439 VisitBinop(node, UseInfo::TruncatingWord64(), kMachBool); | |
| 440 } | |
| 441 void VisitUint64Cmp(Node* node) { | |
| 442 VisitBinop(node, UseInfo::TruncatingWord64(), kMachBool); | |
| 443 } | |
| 315 | 444 |
| 316 // Infer representation for phi-like nodes. | 445 // Infer representation for phi-like nodes. |
| 317 MachineType GetRepresentationForPhi(Node* node, MachineTypeUnion use) { | 446 static MachineType GetRepresentationForPhi(Node* node, MachineTypeUnion use) { |
| 318 // Phis adapt to the output representation their uses demand. | 447 // Phis adapt to the output representation their uses demand. |
| 319 Type* upper = NodeProperties::GetType(node); | 448 Type* upper = NodeProperties::GetType(node); |
| 320 if ((use & kRepMask) == kRepFloat32) { | 449 if ((use & kRepMask) == kRepFloat32) { |
| 321 // only float32 uses. | 450 // only float32 uses. |
| 322 return kRepFloat32; | 451 return kRepFloat32; |
| 323 } else if ((use & kRepMask) == kRepFloat64) { | 452 } else if ((use & kRepMask) == kRepFloat64) { |
| 324 // only float64 uses. | 453 // only float64 uses. |
| 325 return kRepFloat64; | 454 return kRepFloat64; |
| 326 } else if ((use & kRepMask) == kRepTagged) { | 455 } else if ((use & kRepMask) == kRepTagged) { |
| 327 // only tagged uses. | 456 // only tagged uses. |
| 328 return kRepTagged; | 457 return kRepTagged; |
| 329 } else if (upper->Is(Type::Integral32())) { | 458 } else if (upper->Is(Type::Integral32())) { |
| 330 // Integer within [-2^31, 2^32[ range. | 459 // Integer within [-2^31, 2^32[ range. |
| 331 if (upper->Is(Type::Signed32()) || upper->Is(Type::Unsigned32())) { | 460 if (upper->Is(Type::Signed32()) || upper->Is(Type::Unsigned32())) { |
| 332 // multiple uses, but we are within 32 bits range => pick kRepWord32. | 461 // multiple uses, but we are within 32 bits range => pick kRepWord32. |
| 333 return kRepWord32; | 462 return kRepWord32; |
| 334 } else if ((use & kTypeMask) == kTypeInt32 || | 463 } else if (!CanObserveNonWord32(use)) { |
| 335 (use & kTypeMask) == kTypeUint32) { | 464 // We only use 32 bits. |
| 336 // We only use 32 bits or we use the result consistently. | |
| 337 return kRepWord32; | 465 return kRepWord32; |
| 338 } else { | 466 } else { |
| 339 return kRepFloat64; | 467 return kRepFloat64; |
| 340 } | 468 } |
| 341 } else if (upper->Is(Type::Boolean())) { | 469 } else if (upper->Is(Type::Boolean())) { |
| 342 // multiple uses => pick kRepBit. | 470 // multiple uses => pick kRepBit. |
| 343 return kRepBit; | 471 return kRepBit; |
| 344 } else if (upper->Is(Type::Number())) { | 472 } else if (upper->Is(Type::Number())) { |
| 345 // multiple uses => pick kRepFloat64. | 473 // multiple uses => pick kRepFloat64. |
| 346 return kRepFloat64; | 474 return kRepFloat64; |
| 347 } else if (upper->Is(Type::Internal())) { | 475 } else if (upper->Is(Type::Internal())) { |
| 348 return kMachPtr; | 476 return kMachPtr; |
| 349 } | 477 } |
| 350 return kRepTagged; | 478 return kRepTagged; |
| 351 } | 479 } |
| 352 | 480 |
| 353 // Helper for handling selects. | 481 // Helper for handling selects. |
| 354 void VisitSelect(Node* node, MachineTypeUnion use, | 482 void VisitSelect(Node* node, MachineTypeUnion use, |
| 355 SimplifiedLowering* lowering) { | 483 SimplifiedLowering* lowering) { |
| 356 ProcessInput(node, 0, kRepBit); | 484 ProcessInput(node, 0, UseInfo::Bool()); |
| 357 MachineType output = GetRepresentationForPhi(node, use); | 485 MachineType output = GetRepresentationForPhi(node, use); |
| 358 | 486 |
| 359 Type* upper = NodeProperties::GetType(node); | 487 Type* upper = NodeProperties::GetType(node); |
| 360 MachineType output_type = | 488 MachineType output_type = |
| 361 static_cast<MachineType>(changer_->TypeFromUpperBound(upper) | output); | 489 static_cast<MachineType>(changer_->TypeFromUpperBound(upper) | output); |
| 362 SetOutput(node, output_type); | 490 SetOutput(node, output_type); |
| 363 | 491 |
| 364 if (lower()) { | 492 if (lower()) { |
| 365 // Update the select operator. | 493 // Update the select operator. |
| 366 SelectParameters p = SelectParametersOf(node->op()); | 494 SelectParameters p = SelectParametersOf(node->op()); |
| 367 MachineType type = static_cast<MachineType>(output_type); | 495 MachineType type = static_cast<MachineType>(output_type); |
| 368 if (type != p.type()) { | 496 if (type != p.type()) { |
| 369 NodeProperties::ChangeOp(node, | 497 NodeProperties::ChangeOp(node, |
| 370 lowering->common()->Select(type, p.hint())); | 498 lowering->common()->Select(type, p.hint())); |
| 371 } | 499 } |
| 372 | |
| 373 // Convert inputs to the output representation of this select. | |
| 374 ProcessInput(node, 1, output_type); | |
| 375 ProcessInput(node, 2, output_type); | |
| 376 } else { | |
| 377 // Propagate {use} of the select to value inputs. | |
| 378 MachineType use_type = | |
| 379 static_cast<MachineType>((use & kTypeMask) | output); | |
| 380 ProcessInput(node, 1, use_type); | |
| 381 ProcessInput(node, 2, use_type); | |
| 382 } | 500 } |
| 501 // Convert inputs to the output representation of this phi, pass the | |
| 502 // use truncation along. | |
| 503 UseInfo input_use(output, use & kTypeMask); | |
| 504 ProcessInput(node, 1, input_use); | |
| 505 ProcessInput(node, 2, input_use); | |
| 383 } | 506 } |
| 384 | 507 |
| 385 // Helper for handling phis. | 508 // Helper for handling phis. |
| 386 void VisitPhi(Node* node, MachineTypeUnion use, | 509 void VisitPhi(Node* node, MachineTypeUnion use, |
| 387 SimplifiedLowering* lowering) { | 510 SimplifiedLowering* lowering) { |
| 388 MachineType output = GetRepresentationForPhi(node, use); | 511 MachineType output = GetRepresentationForPhi(node, use); |
| 389 | 512 |
| 390 Type* upper = NodeProperties::GetType(node); | 513 Type* upper = NodeProperties::GetType(node); |
| 391 MachineType output_type = | 514 MachineType output_type = |
| 392 static_cast<MachineType>(changer_->TypeFromUpperBound(upper) | output); | 515 static_cast<MachineType>(changer_->TypeFromUpperBound(upper) | output); |
| 393 SetOutput(node, output_type); | 516 SetOutput(node, output_type); |
| 394 | 517 |
| 395 int values = node->op()->ValueInputCount(); | 518 int values = node->op()->ValueInputCount(); |
| 396 | 519 |
| 397 if (lower()) { | 520 if (lower()) { |
| 398 // Update the phi operator. | 521 // Update the phi operator. |
| 399 MachineType type = static_cast<MachineType>(output_type); | 522 MachineType type = static_cast<MachineType>(output_type); |
| 400 if (type != OpParameter<MachineType>(node)) { | 523 if (type != OpParameter<MachineType>(node)) { |
| 401 NodeProperties::ChangeOp(node, lowering->common()->Phi(type, values)); | 524 NodeProperties::ChangeOp(node, lowering->common()->Phi(type, values)); |
| 402 } | 525 } |
| 403 } | 526 } |
| 404 | 527 |
| 405 // Convert inputs to the output representation of this phi, pass the | 528 // Convert inputs to the output representation of this phi, pass the |
| 406 // use truncation along. | 529 // use truncation along. |
| 407 MachineType use_type = static_cast<MachineType>((use & kTypeMask) | output); | 530 UseInfo input_use(output, use & kTypeMask); |
| 408 for (int i = 0; i < node->InputCount(); i++) { | 531 for (int i = 0; i < node->InputCount(); i++) { |
| 409 ProcessInput(node, i, i < values ? use_type : 0); | 532 ProcessInput(node, i, i < values ? input_use : UseInfo::None()); |
| 410 } | 533 } |
| 411 } | 534 } |
| 412 | 535 |
| 413 void VisitCall(Node* node, SimplifiedLowering* lowering) { | 536 void VisitCall(Node* node, SimplifiedLowering* lowering) { |
| 414 const CallDescriptor* desc = OpParameter<const CallDescriptor*>(node->op()); | 537 const CallDescriptor* desc = OpParameter<const CallDescriptor*>(node->op()); |
| 415 const MachineSignature* sig = desc->GetMachineSignature(); | 538 const MachineSignature* sig = desc->GetMachineSignature(); |
| 416 int params = static_cast<int>(sig->parameter_count()); | 539 int params = static_cast<int>(sig->parameter_count()); |
| 417 // Propagate representation information from call descriptor. | 540 // Propagate representation information from call descriptor. |
| 418 for (int i = 0; i < node->InputCount(); i++) { | 541 for (int i = 0; i < node->InputCount(); i++) { |
| 419 if (i == 0) { | 542 if (i == 0) { |
| 420 // The target of the call. | 543 // The target of the call. |
| 421 ProcessInput(node, i, 0); | 544 ProcessInput(node, i, UseInfo::None()); |
| 422 } else if ((i - 1) < params) { | 545 } else if ((i - 1) < params) { |
| 423 ProcessInput(node, i, sig->GetParam(i - 1)); | 546 ProcessInput(node, i, UseInfoFromMachineType(sig->GetParam(i - 1))); |
| 424 } else { | 547 } else { |
| 425 ProcessInput(node, i, 0); | 548 ProcessInput(node, i, UseInfo::None()); |
| 426 } | 549 } |
| 427 } | 550 } |
| 428 | 551 |
| 429 if (sig->return_count() > 0) { | 552 if (sig->return_count() > 0) { |
| 430 SetOutput(node, desc->GetMachineSignature()->GetReturn()); | 553 SetOutput(node, desc->GetMachineSignature()->GetReturn()); |
| 431 } else { | 554 } else { |
| 432 SetOutput(node, kMachAnyTagged); | 555 SetOutput(node, kMachAnyTagged); |
| 433 } | 556 } |
| 434 } | 557 } |
| 435 | 558 |
| 436 void VisitStateValues(Node* node) { | 559 void VisitStateValues(Node* node) { |
| 437 if (phase_ == PROPAGATE) { | 560 if (phase_ == PROPAGATE) { |
| 438 for (int i = 0; i < node->InputCount(); i++) { | 561 for (int i = 0; i < node->InputCount(); i++) { |
| 439 Enqueue(node->InputAt(i), kTypeAny); | 562 Enqueue(node->InputAt(i), UseInfo::Any()); |
| 440 } | 563 } |
| 441 } else { | 564 } else { |
| 442 Zone* zone = jsgraph_->zone(); | 565 Zone* zone = jsgraph_->zone(); |
| 443 ZoneVector<MachineType>* types = | 566 ZoneVector<MachineType>* types = |
| 444 new (zone->New(sizeof(ZoneVector<MachineType>))) | 567 new (zone->New(sizeof(ZoneVector<MachineType>))) |
| 445 ZoneVector<MachineType>(node->InputCount(), zone); | 568 ZoneVector<MachineType>(node->InputCount(), zone); |
| 446 for (int i = 0; i < node->InputCount(); i++) { | 569 for (int i = 0; i < node->InputCount(); i++) { |
| 447 MachineTypeUnion input_type = GetInfo(node->InputAt(i))->output; | 570 MachineTypeUnion input_type = GetInfo(node->InputAt(i))->output; |
| 448 (*types)[i] = static_cast<MachineType>(input_type); | 571 (*types)[i] = static_cast<MachineType>(input_type); |
| 449 } | 572 } |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 475 return BothInputsAre(node, safe_int_additive_range_) && | 598 return BothInputsAre(node, safe_int_additive_range_) && |
| 476 !CanObserveNonWord32(use); | 599 !CanObserveNonWord32(use); |
| 477 } | 600 } |
| 478 | 601 |
| 479 bool CanLowerToUint32Binop(Node* node, MachineTypeUnion use) { | 602 bool CanLowerToUint32Binop(Node* node, MachineTypeUnion use) { |
| 480 return BothInputsAre(node, Type::Unsigned32()) && | 603 return BothInputsAre(node, Type::Unsigned32()) && |
| 481 (!CanObserveNonWord32(use) || | 604 (!CanObserveNonWord32(use) || |
| 482 NodeProperties::GetType(node)->Is(Type::Unsigned32())); | 605 NodeProperties::GetType(node)->Is(Type::Unsigned32())); |
| 483 } | 606 } |
| 484 | 607 |
| 485 bool CanObserveNonWord32(MachineTypeUnion use) { | 608 static bool CanObserveNonWord32(MachineTypeUnion use) { |
| 486 return (use & kTypeMask & ~(kTypeInt32 | kTypeUint32)) != 0; | 609 return (use & kTypeMask & ~(kTypeInt32 | kTypeUint32)) != 0; |
| 487 } | 610 } |
| 488 | 611 |
| 489 bool CanObserveNaN(MachineTypeUnion use) { | 612 static bool CanObserveNaN(MachineTypeUnion use) { |
| 490 return (use & (kTypeNumber | kTypeAny)) != 0; | 613 return (use & (kTypeNumber | kTypeAny)) != 0; |
| 491 } | 614 } |
| 492 | 615 |
| 493 // Dispatching routine for visiting the node {node} with the usage {use}. | 616 // Dispatching routine for visiting the node {node} with the usage {use}. |
| 494 // Depending on the operator, propagate new usage info to the inputs. | 617 // Depending on the operator, propagate new usage info to the inputs. |
| 495 void VisitNode(Node* node, MachineTypeUnion use, | 618 void VisitNode(Node* node, MachineTypeUnion use, |
| 496 SimplifiedLowering* lowering) { | 619 SimplifiedLowering* lowering) { |
| 497 switch (node->opcode()) { | 620 switch (node->opcode()) { |
| 498 //------------------------------------------------------------------ | 621 //------------------------------------------------------------------ |
| 499 // Common operators. | 622 // Common operators. |
| 500 //------------------------------------------------------------------ | 623 //------------------------------------------------------------------ |
| 501 case IrOpcode::kStart: | 624 case IrOpcode::kStart: |
| 502 case IrOpcode::kDead: | 625 case IrOpcode::kDead: |
| 503 return VisitLeaf(node, 0); | 626 return VisitLeaf(node, 0); |
| 504 case IrOpcode::kParameter: { | 627 case IrOpcode::kParameter: { |
| 505 // TODO(titzer): use representation from linkage. | 628 // TODO(titzer): use representation from linkage. |
| 506 Type* upper = NodeProperties::GetType(node); | 629 Type* upper = NodeProperties::GetType(node); |
| 507 ProcessInput(node, 0, 0); | 630 ProcessInput(node, 0, UseInfo::None()); |
| 508 SetOutput(node, kRepTagged | changer_->TypeFromUpperBound(upper)); | 631 SetOutput(node, kRepTagged | changer_->TypeFromUpperBound(upper)); |
| 509 return; | 632 return; |
| 510 } | 633 } |
| 511 case IrOpcode::kInt32Constant: | 634 case IrOpcode::kInt32Constant: |
| 512 return VisitLeaf(node, kRepWord32); | 635 return VisitLeaf(node, kRepWord32); |
| 513 case IrOpcode::kInt64Constant: | 636 case IrOpcode::kInt64Constant: |
| 514 return VisitLeaf(node, kRepWord64); | 637 return VisitLeaf(node, kRepWord64); |
| 515 case IrOpcode::kFloat32Constant: | 638 case IrOpcode::kFloat32Constant: |
| 516 return VisitLeaf(node, kRepFloat32); | 639 return VisitLeaf(node, kRepFloat32); |
| 517 case IrOpcode::kFloat64Constant: | 640 case IrOpcode::kFloat64Constant: |
| 518 return VisitLeaf(node, kRepFloat64); | 641 return VisitLeaf(node, kRepFloat64); |
| 519 case IrOpcode::kExternalConstant: | 642 case IrOpcode::kExternalConstant: |
| 520 return VisitLeaf(node, kMachPtr); | 643 return VisitLeaf(node, kMachPtr); |
| 521 case IrOpcode::kNumberConstant: | 644 case IrOpcode::kNumberConstant: |
| 522 return VisitLeaf(node, kRepTagged); | 645 return VisitLeaf(node, kRepTagged); |
| 523 case IrOpcode::kHeapConstant: | 646 case IrOpcode::kHeapConstant: |
| 524 return VisitLeaf(node, kRepTagged); | 647 return VisitLeaf(node, kRepTagged); |
| 525 | 648 |
| 526 case IrOpcode::kBranch: | 649 case IrOpcode::kBranch: |
| 527 ProcessInput(node, 0, kRepBit); | 650 ProcessInput(node, 0, UseInfo::Bool()); |
| 528 Enqueue(NodeProperties::GetControlInput(node, 0)); | 651 Enqueue(NodeProperties::GetControlInput(node, 0)); |
| 529 break; | 652 break; |
| 530 case IrOpcode::kSwitch: | 653 case IrOpcode::kSwitch: |
| 531 ProcessInput(node, 0, kRepWord32); | 654 ProcessInput(node, 0, UseInfo::TruncatingWord32()); |
| 532 Enqueue(NodeProperties::GetControlInput(node, 0)); | 655 Enqueue(NodeProperties::GetControlInput(node, 0)); |
| 533 break; | 656 break; |
| 534 case IrOpcode::kSelect: | 657 case IrOpcode::kSelect: |
| 535 return VisitSelect(node, use, lowering); | 658 return VisitSelect(node, use, lowering); |
| 536 case IrOpcode::kPhi: | 659 case IrOpcode::kPhi: |
| 537 return VisitPhi(node, use, lowering); | 660 return VisitPhi(node, use, lowering); |
| 538 case IrOpcode::kCall: | 661 case IrOpcode::kCall: |
| 539 return VisitCall(node, lowering); | 662 return VisitCall(node, lowering); |
| 540 | 663 |
| 541 //------------------------------------------------------------------ | 664 //------------------------------------------------------------------ |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 562 // BooleanNot(x: kRepBit) => Word32Equal(x, #0) | 685 // BooleanNot(x: kRepBit) => Word32Equal(x, #0) |
| 563 node->AppendInput(jsgraph_->zone(), jsgraph_->Int32Constant(0)); | 686 node->AppendInput(jsgraph_->zone(), jsgraph_->Int32Constant(0)); |
| 564 NodeProperties::ChangeOp(node, lowering->machine()->Word32Equal()); | 687 NodeProperties::ChangeOp(node, lowering->machine()->Word32Equal()); |
| 565 } else { | 688 } else { |
| 566 // BooleanNot(x: kRepTagged) => WordEqual(x, #false) | 689 // BooleanNot(x: kRepTagged) => WordEqual(x, #false) |
| 567 node->AppendInput(jsgraph_->zone(), jsgraph_->FalseConstant()); | 690 node->AppendInput(jsgraph_->zone(), jsgraph_->FalseConstant()); |
| 568 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual()); | 691 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual()); |
| 569 } | 692 } |
| 570 } else { | 693 } else { |
| 571 // No input representation requirement; adapt during lowering. | 694 // No input representation requirement; adapt during lowering. |
| 572 ProcessInput(node, 0, kTypeBool); | 695 ProcessInput(node, 0, UseInfo::AnyTruncatingToBool()); |
| 573 SetOutput(node, kRepBit); | 696 SetOutput(node, kRepBit); |
| 574 } | 697 } |
| 575 break; | 698 break; |
| 576 } | 699 } |
| 577 case IrOpcode::kBooleanToNumber: { | 700 case IrOpcode::kBooleanToNumber: { |
| 578 if (lower()) { | 701 if (lower()) { |
| 579 MachineTypeUnion input = GetInfo(node->InputAt(0))->output; | 702 MachineTypeUnion input = GetInfo(node->InputAt(0))->output; |
| 580 if (input & kRepBit) { | 703 if (input & kRepBit) { |
| 581 // BooleanToNumber(x: kRepBit) => x | 704 // BooleanToNumber(x: kRepBit) => x |
| 582 DeferReplacement(node, node->InputAt(0)); | 705 DeferReplacement(node, node->InputAt(0)); |
| 583 } else { | 706 } else { |
| 584 // BooleanToNumber(x: kRepTagged) => WordEqual(x, #true) | 707 // BooleanToNumber(x: kRepTagged) => WordEqual(x, #true) |
| 585 node->AppendInput(jsgraph_->zone(), jsgraph_->TrueConstant()); | 708 node->AppendInput(jsgraph_->zone(), jsgraph_->TrueConstant()); |
| 586 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual()); | 709 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual()); |
| 587 } | 710 } |
| 588 } else { | 711 } else { |
| 589 // No input representation requirement; adapt during lowering. | 712 // No input representation requirement; adapt during lowering. |
| 590 ProcessInput(node, 0, kTypeBool); | 713 ProcessInput(node, 0, UseInfo::AnyTruncatingToBool()); |
| 591 SetOutput(node, kMachInt32); | 714 SetOutput(node, kMachInt32); |
| 592 } | 715 } |
| 593 break; | 716 break; |
| 594 } | 717 } |
| 595 case IrOpcode::kNumberEqual: | 718 case IrOpcode::kNumberEqual: |
| 596 case IrOpcode::kNumberLessThan: | 719 case IrOpcode::kNumberLessThan: |
| 597 case IrOpcode::kNumberLessThanOrEqual: { | 720 case IrOpcode::kNumberLessThanOrEqual: { |
| 598 // Number comparisons reduce to integer comparisons for integer inputs. | 721 // Number comparisons reduce to integer comparisons for integer inputs. |
| 599 if (BothInputsAre(node, Type::Signed32())) { | 722 if (BothInputsAre(node, Type::Signed32())) { |
| 600 // => signed Int32Cmp | 723 // => signed Int32Cmp |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 618 if (CanLowerToInt32Binop(node, use)) { | 741 if (CanLowerToInt32Binop(node, use)) { |
| 619 // => signed Int32Add/Sub | 742 // => signed Int32Add/Sub |
| 620 VisitInt32Binop(node); | 743 VisitInt32Binop(node); |
| 621 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); | 744 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); |
| 622 } else if (CanLowerToUint32Binop(node, use)) { | 745 } else if (CanLowerToUint32Binop(node, use)) { |
| 623 // => unsigned Int32Add/Sub | 746 // => unsigned Int32Add/Sub |
| 624 VisitUint32Binop(node); | 747 VisitUint32Binop(node); |
| 625 if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node)); | 748 if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node)); |
| 626 } else if (CanLowerToWord32AdditiveBinop(node, use)) { | 749 } else if (CanLowerToWord32AdditiveBinop(node, use)) { |
| 627 // => signed Int32Add/Sub, truncating inputs | 750 // => signed Int32Add/Sub, truncating inputs |
| 628 ProcessTruncateWord32Input(node, 0, kTypeInt32); | 751 ProcessTruncateWord32Input(node, 0); |
| 629 ProcessTruncateWord32Input(node, 1, kTypeInt32); | 752 ProcessTruncateWord32Input(node, 1); |
| 630 SetOutput(node, kMachInt32); | 753 SetOutput(node, kMachInt32); |
| 631 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); | 754 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); |
| 632 } else { | 755 } else { |
| 633 // => Float64Add/Sub | 756 // => Float64Add/Sub |
| 634 VisitFloat64Binop(node); | 757 VisitFloat64Binop(node); |
| 635 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); | 758 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); |
| 636 } | 759 } |
| 637 break; | 760 break; |
| 638 } | 761 } |
| 639 case IrOpcode::kNumberMultiply: { | 762 case IrOpcode::kNumberMultiply: { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 688 break; | 811 break; |
| 689 } | 812 } |
| 690 case IrOpcode::kNumberBitwiseOr: | 813 case IrOpcode::kNumberBitwiseOr: |
| 691 case IrOpcode::kNumberBitwiseXor: | 814 case IrOpcode::kNumberBitwiseXor: |
| 692 case IrOpcode::kNumberBitwiseAnd: { | 815 case IrOpcode::kNumberBitwiseAnd: { |
| 693 VisitInt32Binop(node); | 816 VisitInt32Binop(node); |
| 694 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); | 817 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); |
| 695 break; | 818 break; |
| 696 } | 819 } |
| 697 case IrOpcode::kNumberShiftLeft: { | 820 case IrOpcode::kNumberShiftLeft: { |
| 698 VisitBinop(node, kMachInt32, kMachUint32, kMachInt32); | 821 VisitBinop(node, UseInfo::TruncatingWord32(), |
| 822 UseInfo::TruncatingWord32(), kMachInt32); | |
| 699 if (lower()) lowering->DoShift(node, lowering->machine()->Word32Shl()); | 823 if (lower()) lowering->DoShift(node, lowering->machine()->Word32Shl()); |
| 700 break; | 824 break; |
| 701 } | 825 } |
| 702 case IrOpcode::kNumberShiftRight: { | 826 case IrOpcode::kNumberShiftRight: { |
| 703 VisitBinop(node, kMachInt32, kMachUint32, kMachInt32); | 827 VisitBinop(node, UseInfo::TruncatingWord32(), |
| 828 UseInfo::TruncatingWord32(), kMachInt32); | |
| 704 if (lower()) lowering->DoShift(node, lowering->machine()->Word32Sar()); | 829 if (lower()) lowering->DoShift(node, lowering->machine()->Word32Sar()); |
| 705 break; | 830 break; |
| 706 } | 831 } |
| 707 case IrOpcode::kNumberShiftRightLogical: { | 832 case IrOpcode::kNumberShiftRightLogical: { |
| 708 VisitBinop(node, kMachUint32, kMachUint32, kMachUint32); | 833 VisitBinop(node, UseInfo::TruncatingWord32(), |
| 834 UseInfo::TruncatingWord32(), kMachUint32); | |
| 709 if (lower()) lowering->DoShift(node, lowering->machine()->Word32Shr()); | 835 if (lower()) lowering->DoShift(node, lowering->machine()->Word32Shr()); |
| 710 break; | 836 break; |
| 711 } | 837 } |
| 712 case IrOpcode::kNumberToInt32: { | 838 case IrOpcode::kNumberToInt32: { |
| 713 MachineTypeUnion use_rep = use & kRepMask; | 839 MachineTypeUnion use_rep = use & kRepMask; |
| 714 Node* input = node->InputAt(0); | 840 Node* input = node->InputAt(0); |
| 715 Type* in_upper = NodeProperties::GetType(input); | 841 Type* in_upper = NodeProperties::GetType(input); |
| 716 MachineTypeUnion in = GetInfo(input)->output; | 842 MachineTypeUnion in = GetInfo(input)->output; |
| 717 if (in_upper->Is(Type::Signed32())) { | 843 if (in_upper->Is(Type::Signed32())) { |
| 718 // If the input has type int32, pass through representation. | 844 // If the input has type int32, pass through representation. |
| 719 VisitUnop(node, kTypeInt32 | use_rep, kTypeInt32 | use_rep); | 845 VisitUnop(node, UseInfoFromRepresentation(use_rep), |
| 846 kTypeInt32 | use_rep); | |
| 720 if (lower()) DeferReplacement(node, node->InputAt(0)); | 847 if (lower()) DeferReplacement(node, node->InputAt(0)); |
| 721 } else if ((in & kTypeMask) == kTypeUint32 || | 848 } else if ((in & kTypeMask) == kTypeUint32 || |
| 722 in_upper->Is(Type::Unsigned32())) { | 849 in_upper->Is(Type::Unsigned32())) { |
| 723 // Just change representation if necessary. | 850 // Just change representation if necessary. |
| 724 VisitUnop(node, kTypeUint32 | kRepWord32, kTypeInt32 | kRepWord32); | 851 VisitUnop(node, UseInfo::TruncatingWord32(), kTypeInt32 | kRepWord32); |
| 725 if (lower()) DeferReplacement(node, node->InputAt(0)); | 852 if (lower()) DeferReplacement(node, node->InputAt(0)); |
| 726 } else if ((in & kTypeMask) == kTypeInt32 || | 853 } else if ((in & kTypeMask) == kTypeInt32 || |
| 727 (in & kRepMask) == kRepWord32) { | 854 (in & kRepMask) == kRepWord32) { |
| 728 // Just change representation if necessary. | 855 // Just change representation if necessary. |
| 729 VisitUnop(node, kTypeInt32 | kRepWord32, kTypeInt32 | kRepWord32); | 856 VisitUnop(node, UseInfo::TruncatingWord32(), kTypeInt32 | kRepWord32); |
| 730 if (lower()) DeferReplacement(node, node->InputAt(0)); | 857 if (lower()) DeferReplacement(node, node->InputAt(0)); |
| 731 } else { | 858 } else { |
| 732 // Require the input in float64 format and perform truncation. | 859 // Require the input in float64 format and perform truncation. |
| 733 // TODO(turbofan): avoid a truncation with a smi check. | 860 // TODO(turbofan): avoid a truncation with a smi check. |
| 734 VisitUnop(node, kTypeInt32 | kRepFloat64, kTypeInt32 | kRepWord32); | 861 VisitUnop(node, UseInfo::Float64TruncatingToWord32(), |
| 862 kTypeInt32 | kRepWord32); | |
| 735 if (lower()) { | 863 if (lower()) { |
| 736 NodeProperties::ChangeOp( | 864 NodeProperties::ChangeOp( |
| 737 node, lowering->machine()->TruncateFloat64ToInt32( | 865 node, lowering->machine()->TruncateFloat64ToInt32( |
| 738 TruncationMode::kJavaScript)); | 866 TruncationMode::kJavaScript)); |
| 739 } | 867 } |
| 740 } | 868 } |
| 741 break; | 869 break; |
| 742 } | 870 } |
| 743 case IrOpcode::kNumberToUint32: { | 871 case IrOpcode::kNumberToUint32: { |
| 744 MachineTypeUnion use_rep = use & kRepMask; | 872 MachineTypeUnion use_rep = use & kRepMask; |
| 745 Node* input = node->InputAt(0); | 873 Node* input = node->InputAt(0); |
| 746 Type* in_upper = NodeProperties::GetType(input); | 874 Type* in_upper = NodeProperties::GetType(input); |
| 747 MachineTypeUnion in = GetInfo(input)->output; | 875 MachineTypeUnion in = GetInfo(input)->output; |
| 748 if (in_upper->Is(Type::Unsigned32())) { | 876 if (in_upper->Is(Type::Unsigned32())) { |
| 749 // If the input has type uint32, pass through representation. | 877 // If the input has type uint32, pass through representation. |
| 750 VisitUnop(node, kTypeUint32 | use_rep, kTypeUint32 | use_rep); | 878 VisitUnop(node, UseInfoFromRepresentation(use_rep), |
| 879 kTypeUint32 | use_rep); | |
| 751 if (lower()) DeferReplacement(node, node->InputAt(0)); | 880 if (lower()) DeferReplacement(node, node->InputAt(0)); |
| 752 } else if ((in & kTypeMask) == kTypeInt32 || | 881 } else if ((in & kTypeMask) == kTypeInt32 || |
| 753 in_upper->Is(Type::Signed32())) { | 882 in_upper->Is(Type::Signed32())) { |
| 754 // Just change representation if necessary. | 883 // Just change representation if necessary. |
| 755 VisitUnop(node, kTypeInt32 | kRepWord32, kTypeUint32 | kRepWord32); | 884 VisitUnop(node, UseInfo::TruncatingWord32(), |
| 885 kTypeUint32 | kRepWord32); | |
| 756 if (lower()) DeferReplacement(node, node->InputAt(0)); | 886 if (lower()) DeferReplacement(node, node->InputAt(0)); |
| 757 } else if ((in & kTypeMask) == kTypeUint32 || | 887 } else if ((in & kTypeMask) == kTypeUint32 || |
| 758 (in & kRepMask) == kRepWord32) { | 888 (in & kRepMask) == kRepWord32) { |
| 759 // Just change representation if necessary. | 889 // Just change representation if necessary. |
| 760 VisitUnop(node, kTypeUint32 | kRepWord32, kTypeUint32 | kRepWord32); | 890 VisitUnop(node, UseInfo::TruncatingWord32(), |
| 891 kTypeUint32 | kRepWord32); | |
| 761 if (lower()) DeferReplacement(node, node->InputAt(0)); | 892 if (lower()) DeferReplacement(node, node->InputAt(0)); |
| 762 } else { | 893 } else { |
| 763 // Require the input in float64 format and perform truncation. | 894 // Require the input in float64 format and perform truncation. |
| 764 // TODO(turbofan): avoid a truncation with a smi check. | 895 // TODO(turbofan): avoid a truncation with a smi check. |
| 765 VisitUnop(node, kTypeUint32 | kRepFloat64, kTypeUint32 | kRepWord32); | 896 VisitUnop(node, UseInfo::Float64TruncatingToWord32(), |
| 897 kTypeUint32 | kRepWord32); | |
| 766 if (lower()) { | 898 if (lower()) { |
| 767 NodeProperties::ChangeOp( | 899 NodeProperties::ChangeOp( |
| 768 node, lowering->machine()->TruncateFloat64ToInt32( | 900 node, lowering->machine()->TruncateFloat64ToInt32( |
| 769 TruncationMode::kJavaScript)); | 901 TruncationMode::kJavaScript)); |
| 770 } | 902 } |
| 771 } | 903 } |
| 772 break; | 904 break; |
| 773 } | 905 } |
| 774 case IrOpcode::kNumberIsHoleNaN: { | 906 case IrOpcode::kNumberIsHoleNaN: { |
| 775 VisitUnop(node, kMachFloat64, kMachBool); | 907 VisitUnop(node, UseInfo::Float64(), kMachBool); |
| 776 if (lower()) { | 908 if (lower()) { |
| 777 // NumberIsHoleNaN(x) => Word32Equal(Float64ExtractLowWord32(x), | 909 // NumberIsHoleNaN(x) => Word32Equal(Float64ExtractLowWord32(x), |
| 778 // #HoleNaNLower32) | 910 // #HoleNaNLower32) |
| 779 node->ReplaceInput(0, | 911 node->ReplaceInput(0, |
| 780 jsgraph_->graph()->NewNode( | 912 jsgraph_->graph()->NewNode( |
| 781 lowering->machine()->Float64ExtractLowWord32(), | 913 lowering->machine()->Float64ExtractLowWord32(), |
| 782 node->InputAt(0))); | 914 node->InputAt(0))); |
| 783 node->AppendInput(jsgraph_->zone(), | 915 node->AppendInput(jsgraph_->zone(), |
| 784 jsgraph_->Int32Constant(kHoleNanLower32)); | 916 jsgraph_->Int32Constant(kHoleNanLower32)); |
| 785 NodeProperties::ChangeOp(node, jsgraph_->machine()->Word32Equal()); | 917 NodeProperties::ChangeOp(node, jsgraph_->machine()->Word32Equal()); |
| 786 } | 918 } |
| 787 break; | 919 break; |
| 788 } | 920 } |
| 789 case IrOpcode::kPlainPrimitiveToNumber: { | 921 case IrOpcode::kPlainPrimitiveToNumber: { |
| 790 VisitUnop(node, kMachAnyTagged, kTypeNumber | kRepTagged); | 922 VisitUnop(node, UseInfo::AnyTagged(), kTypeNumber | kRepTagged); |
| 791 if (lower()) { | 923 if (lower()) { |
| 792 // PlainPrimitiveToNumber(x) => Call(ToNumberStub, x, no-context) | 924 // PlainPrimitiveToNumber(x) => Call(ToNumberStub, x, no-context) |
| 793 Operator::Properties properties = node->op()->properties(); | 925 Operator::Properties properties = node->op()->properties(); |
| 794 Callable callable = CodeFactory::ToNumber(jsgraph_->isolate()); | 926 Callable callable = CodeFactory::ToNumber(jsgraph_->isolate()); |
| 795 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; | 927 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; |
| 796 CallDescriptor* desc = Linkage::GetStubCallDescriptor( | 928 CallDescriptor* desc = Linkage::GetStubCallDescriptor( |
| 797 jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0, | 929 jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0, |
| 798 flags, properties); | 930 flags, properties); |
| 799 node->InsertInput(jsgraph_->zone(), 0, | 931 node->InsertInput(jsgraph_->zone(), 0, |
| 800 jsgraph_->HeapConstant(callable.code())); | 932 jsgraph_->HeapConstant(callable.code())); |
| 801 node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant()); | 933 node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant()); |
| 802 NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc)); | 934 NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc)); |
| 803 } | 935 } |
| 804 break; | 936 break; |
| 805 } | 937 } |
| 806 case IrOpcode::kReferenceEqual: { | 938 case IrOpcode::kReferenceEqual: { |
| 807 VisitBinop(node, kMachAnyTagged, kRepBit); | 939 VisitBinop(node, UseInfo::AnyTagged(), kMachBool); |
| 808 if (lower()) { | 940 if (lower()) { |
| 809 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual()); | 941 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual()); |
| 810 } | 942 } |
| 811 break; | 943 break; |
| 812 } | 944 } |
| 813 case IrOpcode::kStringEqual: { | 945 case IrOpcode::kStringEqual: { |
| 814 VisitBinop(node, kMachAnyTagged, kRepBit); | 946 VisitBinop(node, UseInfo::AnyTagged(), kMachBool); |
| 815 if (lower()) lowering->DoStringEqual(node); | 947 if (lower()) lowering->DoStringEqual(node); |
| 816 break; | 948 break; |
| 817 } | 949 } |
| 818 case IrOpcode::kStringLessThan: { | 950 case IrOpcode::kStringLessThan: { |
| 819 VisitBinop(node, kMachAnyTagged, kRepBit); | 951 VisitBinop(node, UseInfo::AnyTagged(), kMachBool); |
| 820 if (lower()) lowering->DoStringLessThan(node); | 952 if (lower()) lowering->DoStringLessThan(node); |
| 821 break; | 953 break; |
| 822 } | 954 } |
| 823 case IrOpcode::kStringLessThanOrEqual: { | 955 case IrOpcode::kStringLessThanOrEqual: { |
| 824 VisitBinop(node, kMachAnyTagged, kRepBit); | 956 VisitBinop(node, UseInfo::AnyTagged(), kMachBool); |
| 825 if (lower()) lowering->DoStringLessThanOrEqual(node); | 957 if (lower()) lowering->DoStringLessThanOrEqual(node); |
| 826 break; | 958 break; |
| 827 } | 959 } |
| 828 case IrOpcode::kAllocate: { | 960 case IrOpcode::kAllocate: { |
| 829 ProcessInput(node, 0, kMachAnyTagged); | 961 ProcessInput(node, 0, UseInfo::AnyTagged()); |
| 830 ProcessRemainingInputs(node, 1); | 962 ProcessRemainingInputs(node, 1); |
| 831 SetOutput(node, kMachAnyTagged); | 963 SetOutput(node, kMachAnyTagged); |
| 832 break; | 964 break; |
| 833 } | 965 } |
| 834 case IrOpcode::kLoadField: { | 966 case IrOpcode::kLoadField: { |
| 835 FieldAccess access = FieldAccessOf(node->op()); | 967 FieldAccess access = FieldAccessOf(node->op()); |
| 836 ProcessInput(node, 0, changer_->TypeForBasePointer(access)); | 968 ProcessInput(node, 0, UseInfoForBasePointer(access)); |
| 837 ProcessRemainingInputs(node, 1); | 969 ProcessRemainingInputs(node, 1); |
| 838 SetOutput(node, access.machine_type); | 970 SetOutput(node, access.machine_type); |
| 839 break; | 971 break; |
| 840 } | 972 } |
| 841 case IrOpcode::kStoreField: { | 973 case IrOpcode::kStoreField: { |
| 842 FieldAccess access = FieldAccessOf(node->op()); | 974 FieldAccess access = FieldAccessOf(node->op()); |
| 843 ProcessInput(node, 0, changer_->TypeForBasePointer(access)); | 975 ProcessInput(node, 0, UseInfoForBasePointer(access)); |
| 844 ProcessInput(node, 1, access.machine_type); | 976 ProcessInput(node, 1, UseInfoFromMachineType(access.machine_type)); |
| 845 ProcessRemainingInputs(node, 2); | 977 ProcessRemainingInputs(node, 2); |
| 846 SetOutput(node, 0); | 978 SetOutput(node, 0); |
| 847 break; | 979 break; |
| 848 } | 980 } |
| 849 case IrOpcode::kLoadBuffer: { | 981 case IrOpcode::kLoadBuffer: { |
| 850 BufferAccess access = BufferAccessOf(node->op()); | 982 BufferAccess access = BufferAccessOf(node->op()); |
| 851 ProcessInput(node, 0, kMachPtr); // buffer | 983 ProcessInput(node, 0, UseInfo::PointerInt()); // buffer |
| 852 ProcessInput(node, 1, kMachInt32); // offset | 984 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // offset |
| 853 ProcessInput(node, 2, kMachInt32); // length | 985 ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length |
| 854 ProcessRemainingInputs(node, 3); | 986 ProcessRemainingInputs(node, 3); |
| 855 // Tagged overrides everything if we have to do a typed array bounds | 987 // Tagged overrides everything if we have to do a typed array bounds |
| 856 // check, because we may need to return undefined then. | 988 // check, because we may need to return undefined then. |
| 857 MachineType output_type; | 989 MachineType output_type; |
| 858 if (use & kRepTagged) { | 990 if (use & kRepTagged) { |
| 859 output_type = kMachAnyTagged; | 991 output_type = kMachAnyTagged; |
| 860 } else if (use & kRepFloat64) { | 992 } else if (use & kRepFloat64) { |
| 861 if (access.machine_type() & kRepFloat32) { | 993 if (access.machine_type() & kRepFloat32) { |
| 862 output_type = access.machine_type(); | 994 output_type = access.machine_type(); |
| 863 } else { | 995 } else { |
| 864 output_type = kMachFloat64; | 996 output_type = kMachFloat64; |
| 865 } | 997 } |
| 866 } else if (use & kRepFloat32) { | 998 } else if (use & kRepFloat32) { |
| 867 output_type = kMachFloat32; | 999 output_type = kMachFloat32; |
| 868 } else { | 1000 } else { |
| 869 output_type = access.machine_type(); | 1001 output_type = access.machine_type(); |
| 870 } | 1002 } |
| 871 SetOutput(node, output_type); | 1003 SetOutput(node, output_type); |
| 872 if (lower()) lowering->DoLoadBuffer(node, output_type, changer_); | 1004 if (lower()) lowering->DoLoadBuffer(node, output_type, changer_); |
| 873 break; | 1005 break; |
| 874 } | 1006 } |
| 875 case IrOpcode::kStoreBuffer: { | 1007 case IrOpcode::kStoreBuffer: { |
| 876 BufferAccess access = BufferAccessOf(node->op()); | 1008 BufferAccess access = BufferAccessOf(node->op()); |
| 877 ProcessInput(node, 0, kMachPtr); // buffer | 1009 ProcessInput(node, 0, UseInfo::PointerInt()); // buffer |
| 878 ProcessInput(node, 1, kMachInt32); // offset | 1010 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // offset |
| 879 ProcessInput(node, 2, kMachInt32); // length | 1011 ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length |
| 880 ProcessInput(node, 3, access.machine_type()); // value | 1012 ProcessInput(node, 3, |
| 1013 UseInfoFromMachineType(access.machine_type())); // value | |
| 881 ProcessRemainingInputs(node, 4); | 1014 ProcessRemainingInputs(node, 4); |
| 882 SetOutput(node, 0); | 1015 SetOutput(node, 0); |
| 883 if (lower()) lowering->DoStoreBuffer(node); | 1016 if (lower()) lowering->DoStoreBuffer(node); |
| 884 break; | 1017 break; |
| 885 } | 1018 } |
| 886 case IrOpcode::kLoadElement: { | 1019 case IrOpcode::kLoadElement: { |
| 887 ElementAccess access = ElementAccessOf(node->op()); | 1020 ElementAccess access = ElementAccessOf(node->op()); |
| 888 ProcessInput(node, 0, changer_->TypeForBasePointer(access)); // base | 1021 ProcessInput(node, 0, UseInfoForBasePointer(access)); // base |
| 889 ProcessInput(node, 1, kMachInt32); // index | 1022 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // index |
| 890 ProcessRemainingInputs(node, 2); | 1023 ProcessRemainingInputs(node, 2); |
| 891 SetOutput(node, access.machine_type); | 1024 SetOutput(node, access.machine_type); |
| 892 break; | 1025 break; |
| 893 } | 1026 } |
| 894 case IrOpcode::kStoreElement: { | 1027 case IrOpcode::kStoreElement: { |
| 895 ElementAccess access = ElementAccessOf(node->op()); | 1028 ElementAccess access = ElementAccessOf(node->op()); |
| 896 ProcessInput(node, 0, changer_->TypeForBasePointer(access)); // base | 1029 ProcessInput(node, 0, UseInfoForBasePointer(access)); // base |
| 897 ProcessInput(node, 1, kMachInt32); // index | 1030 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // index |
| 898 ProcessInput(node, 2, access.machine_type); // value | 1031 ProcessInput(node, 2, |
| 1032 UseInfoFromMachineType(access.machine_type)); // value | |
| 899 ProcessRemainingInputs(node, 3); | 1033 ProcessRemainingInputs(node, 3); |
| 900 SetOutput(node, 0); | 1034 SetOutput(node, 0); |
| 901 break; | 1035 break; |
| 902 } | 1036 } |
| 903 case IrOpcode::kObjectIsNumber: { | 1037 case IrOpcode::kObjectIsNumber: { |
| 904 ProcessInput(node, 0, kMachAnyTagged); | 1038 ProcessInput(node, 0, UseInfo::AnyTagged()); |
| 905 SetOutput(node, kRepBit | kTypeBool); | 1039 SetOutput(node, kMachBool); |
| 906 if (lower()) lowering->DoObjectIsNumber(node); | 1040 if (lower()) lowering->DoObjectIsNumber(node); |
| 907 break; | 1041 break; |
| 908 } | 1042 } |
| 909 case IrOpcode::kObjectIsSmi: { | 1043 case IrOpcode::kObjectIsSmi: { |
| 910 ProcessInput(node, 0, kMachAnyTagged); | 1044 ProcessInput(node, 0, UseInfo::AnyTagged()); |
| 911 SetOutput(node, kRepBit | kTypeBool); | 1045 SetOutput(node, kMachBool); |
| 912 if (lower()) lowering->DoObjectIsSmi(node); | 1046 if (lower()) lowering->DoObjectIsSmi(node); |
| 913 break; | 1047 break; |
| 914 } | 1048 } |
| 915 | 1049 |
| 916 //------------------------------------------------------------------ | 1050 //------------------------------------------------------------------ |
| 917 // Machine-level operators. | 1051 // Machine-level operators. |
| 918 //------------------------------------------------------------------ | 1052 //------------------------------------------------------------------ |
| 919 case IrOpcode::kLoad: { | 1053 case IrOpcode::kLoad: { |
| 920 // TODO(titzer): machine loads/stores need to know BaseTaggedness!? | 1054 // TODO(jarin) Eventually, we should get rid of all machine stores |
| 921 MachineTypeUnion tBase = kRepTagged | kMachPtr; | 1055 // from the high-level phases, then this becomes UNREACHABLE. |
| 922 LoadRepresentation rep = OpParameter<LoadRepresentation>(node); | 1056 LoadRepresentation rep = OpParameter<LoadRepresentation>(node); |
| 923 ProcessInput(node, 0, tBase); // pointer or object | 1057 ProcessInput(node, 0, UseInfo::AnyTagged()); // tagged pointer |
| 924 ProcessInput(node, 1, kMachIntPtr); // index | 1058 ProcessInput(node, 1, UseInfo::PointerInt()); // index |
| 925 ProcessRemainingInputs(node, 2); | 1059 ProcessRemainingInputs(node, 2); |
| 926 SetOutput(node, rep); | 1060 SetOutput(node, rep); |
| 927 break; | 1061 break; |
| 928 } | 1062 } |
| 929 case IrOpcode::kStore: { | 1063 case IrOpcode::kStore: { |
| 930 // TODO(titzer): machine loads/stores need to know BaseTaggedness!? | 1064 // TODO(jarin) Eventually, we should get rid of all machine stores |
| 931 MachineTypeUnion tBase = kRepTagged | kMachPtr; | 1065 // from the high-level phases, then this becomes UNREACHABLE. |
| 932 StoreRepresentation rep = OpParameter<StoreRepresentation>(node); | 1066 StoreRepresentation rep = OpParameter<StoreRepresentation>(node); |
| 933 ProcessInput(node, 0, tBase); // pointer or object | 1067 ProcessInput(node, 0, UseInfo::AnyTagged()); // tagged pointer |
| 934 ProcessInput(node, 1, kMachIntPtr); // index | 1068 ProcessInput(node, 1, UseInfo::PointerInt()); // index |
| 935 ProcessInput(node, 2, rep.machine_type()); | 1069 ProcessInput(node, 2, UseInfoFromMachineType(rep.machine_type())); |
| 936 ProcessRemainingInputs(node, 3); | 1070 ProcessRemainingInputs(node, 3); |
| 937 SetOutput(node, 0); | 1071 SetOutput(node, 0); |
| 938 break; | 1072 break; |
| 939 } | 1073 } |
| 940 case IrOpcode::kWord32Shr: | 1074 case IrOpcode::kWord32Shr: |
| 941 // We output unsigned int32 for shift right because JavaScript. | 1075 // We output unsigned int32 for shift right because JavaScript. |
| 942 return VisitBinop(node, kMachUint32, kMachUint32); | 1076 return VisitBinop(node, UseInfo::TruncatingWord32(), kMachUint32); |
| 943 case IrOpcode::kWord32And: | 1077 case IrOpcode::kWord32And: |
| 944 case IrOpcode::kWord32Or: | 1078 case IrOpcode::kWord32Or: |
| 945 case IrOpcode::kWord32Xor: | 1079 case IrOpcode::kWord32Xor: |
| 946 case IrOpcode::kWord32Shl: | 1080 case IrOpcode::kWord32Shl: |
| 947 case IrOpcode::kWord32Sar: | 1081 case IrOpcode::kWord32Sar: |
| 948 // We use signed int32 as the output type for these word32 operations, | 1082 // We use signed int32 as the output type for these word32 operations, |
| 949 // though the machine bits are the same for either signed or unsigned, | 1083 // though the machine bits are the same for either signed or unsigned, |
| 950 // because JavaScript considers the result from these operations signed. | 1084 // because JavaScript considers the result from these operations signed. |
| 951 return VisitBinop(node, kRepWord32, kRepWord32 | kTypeInt32); | 1085 return VisitBinop(node, UseInfo::TruncatingWord32(), |
| 1086 kRepWord32 | kTypeInt32); | |
| 952 case IrOpcode::kWord32Equal: | 1087 case IrOpcode::kWord32Equal: |
| 953 return VisitBinop(node, kRepWord32, kRepBit); | 1088 return VisitBinop(node, UseInfo::TruncatingWord32(), kMachBool); |
| 954 | 1089 |
| 955 case IrOpcode::kWord32Clz: | 1090 case IrOpcode::kWord32Clz: |
| 956 return VisitUnop(node, kMachUint32, kMachUint32); | 1091 return VisitUnop(node, UseInfo::TruncatingWord32(), kMachUint32); |
| 957 | 1092 |
| 958 case IrOpcode::kInt32Add: | 1093 case IrOpcode::kInt32Add: |
| 959 case IrOpcode::kInt32Sub: | 1094 case IrOpcode::kInt32Sub: |
| 960 case IrOpcode::kInt32Mul: | 1095 case IrOpcode::kInt32Mul: |
| 961 case IrOpcode::kInt32MulHigh: | 1096 case IrOpcode::kInt32MulHigh: |
| 962 case IrOpcode::kInt32Div: | 1097 case IrOpcode::kInt32Div: |
| 963 case IrOpcode::kInt32Mod: | 1098 case IrOpcode::kInt32Mod: |
| 964 return VisitInt32Binop(node); | 1099 return VisitInt32Binop(node); |
| 965 case IrOpcode::kUint32Div: | 1100 case IrOpcode::kUint32Div: |
| 966 case IrOpcode::kUint32Mod: | 1101 case IrOpcode::kUint32Mod: |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 990 case IrOpcode::kUint64Div: | 1125 case IrOpcode::kUint64Div: |
| 991 case IrOpcode::kUint64Mod: | 1126 case IrOpcode::kUint64Mod: |
| 992 return VisitUint64Binop(node); | 1127 return VisitUint64Binop(node); |
| 993 | 1128 |
| 994 case IrOpcode::kWord64And: | 1129 case IrOpcode::kWord64And: |
| 995 case IrOpcode::kWord64Or: | 1130 case IrOpcode::kWord64Or: |
| 996 case IrOpcode::kWord64Xor: | 1131 case IrOpcode::kWord64Xor: |
| 997 case IrOpcode::kWord64Shl: | 1132 case IrOpcode::kWord64Shl: |
| 998 case IrOpcode::kWord64Shr: | 1133 case IrOpcode::kWord64Shr: |
| 999 case IrOpcode::kWord64Sar: | 1134 case IrOpcode::kWord64Sar: |
| 1000 return VisitBinop(node, kRepWord64, kRepWord64); | 1135 return VisitBinop(node, UseInfo::TruncatingWord64(), kRepWord64); |
| 1001 case IrOpcode::kWord64Equal: | 1136 case IrOpcode::kWord64Equal: |
| 1002 return VisitBinop(node, kRepWord64, kRepBit); | 1137 return VisitBinop(node, UseInfo::TruncatingWord64(), kMachBool); |
| 1003 | 1138 |
| 1004 case IrOpcode::kChangeInt32ToInt64: | 1139 case IrOpcode::kChangeInt32ToInt64: |
| 1005 return VisitUnop(node, kTypeInt32 | kRepWord32, | 1140 return VisitUnop(node, UseInfo::TruncatingWord32(), |
| 1006 kTypeInt32 | kRepWord64); | 1141 kTypeInt32 | kRepWord64); |
| 1007 case IrOpcode::kChangeUint32ToUint64: | 1142 case IrOpcode::kChangeUint32ToUint64: |
| 1008 return VisitUnop(node, kTypeUint32 | kRepWord32, | 1143 return VisitUnop(node, UseInfo::TruncatingWord32(), |
| 1009 kTypeUint32 | kRepWord64); | 1144 kTypeUint32 | kRepWord64); |
| 1010 case IrOpcode::kTruncateFloat64ToFloat32: | 1145 case IrOpcode::kTruncateFloat64ToFloat32: |
| 1011 return VisitUnop(node, kTypeNumber | kRepFloat64, | 1146 return VisitUnop(node, UseInfo::Float64(), kTypeNumber | kRepFloat32); |
| 1012 kTypeNumber | kRepFloat32); | |
| 1013 case IrOpcode::kTruncateFloat64ToInt32: | 1147 case IrOpcode::kTruncateFloat64ToInt32: |
| 1014 return VisitUnop(node, kTypeNumber | kRepFloat64, | 1148 return VisitUnop(node, UseInfo::Float64(), kTypeInt32 | kRepWord32); |
| 1015 kTypeInt32 | kRepWord32); | |
| 1016 case IrOpcode::kTruncateInt64ToInt32: | 1149 case IrOpcode::kTruncateInt64ToInt32: |
| 1017 // TODO(titzer): Is kTypeInt32 correct here? | 1150 // TODO(titzer): Is kTypeInt32 correct here? |
| 1018 return VisitUnop(node, kTypeInt32 | kRepWord64, | 1151 return VisitUnop(node, UseInfo::Word64TruncatingToWord32(), |
| 1019 kTypeInt32 | kRepWord32); | 1152 kTypeInt32 | kRepWord32); |
| 1020 | 1153 |
| 1021 case IrOpcode::kChangeFloat32ToFloat64: | 1154 case IrOpcode::kChangeFloat32ToFloat64: |
| 1022 return VisitUnop(node, kTypeNumber | kRepFloat32, | 1155 return VisitUnop(node, UseInfo::Float32(), kTypeNumber | kRepFloat64); |
| 1023 kTypeNumber | kRepFloat64); | |
| 1024 case IrOpcode::kChangeInt32ToFloat64: | 1156 case IrOpcode::kChangeInt32ToFloat64: |
| 1025 return VisitUnop(node, kTypeInt32 | kRepWord32, | 1157 return VisitUnop(node, UseInfo::TruncatingWord32(), |
| 1026 kTypeInt32 | kRepFloat64); | 1158 kTypeInt32 | kRepFloat64); |
| 1027 case IrOpcode::kChangeUint32ToFloat64: | 1159 case IrOpcode::kChangeUint32ToFloat64: |
| 1028 return VisitUnop(node, kTypeUint32 | kRepWord32, | 1160 return VisitUnop(node, UseInfo::TruncatingWord32(), |
| 1029 kTypeUint32 | kRepFloat64); | 1161 kTypeUint32 | kRepFloat64); |
| 1030 case IrOpcode::kChangeFloat64ToInt32: | 1162 case IrOpcode::kChangeFloat64ToInt32: |
| 1031 return VisitUnop(node, kTypeInt32 | kRepFloat64, | 1163 return VisitUnop(node, UseInfo::Float64TruncatingToWord32(), |
| 1032 kTypeInt32 | kRepWord32); | 1164 kTypeInt32 | kRepWord32); |
| 1033 case IrOpcode::kChangeFloat64ToUint32: | 1165 case IrOpcode::kChangeFloat64ToUint32: |
| 1034 return VisitUnop(node, kTypeUint32 | kRepFloat64, | 1166 return VisitUnop(node, UseInfo::Float64TruncatingToWord32(), |
| 1035 kTypeUint32 | kRepWord32); | 1167 kTypeUint32 | kRepWord32); |
| 1036 | 1168 |
| 1037 case IrOpcode::kFloat64Add: | 1169 case IrOpcode::kFloat64Add: |
| 1038 case IrOpcode::kFloat64Sub: | 1170 case IrOpcode::kFloat64Sub: |
| 1039 case IrOpcode::kFloat64Mul: | 1171 case IrOpcode::kFloat64Mul: |
| 1040 case IrOpcode::kFloat64Div: | 1172 case IrOpcode::kFloat64Div: |
| 1041 case IrOpcode::kFloat64Mod: | 1173 case IrOpcode::kFloat64Mod: |
| 1042 case IrOpcode::kFloat64Min: | 1174 case IrOpcode::kFloat64Min: |
| 1043 return VisitFloat64Binop(node); | 1175 return VisitFloat64Binop(node); |
| 1044 case IrOpcode::kFloat64Abs: | 1176 case IrOpcode::kFloat64Abs: |
| 1045 case IrOpcode::kFloat64Sqrt: | 1177 case IrOpcode::kFloat64Sqrt: |
| 1046 case IrOpcode::kFloat64RoundDown: | 1178 case IrOpcode::kFloat64RoundDown: |
| 1047 case IrOpcode::kFloat64RoundTruncate: | 1179 case IrOpcode::kFloat64RoundTruncate: |
| 1048 case IrOpcode::kFloat64RoundTiesAway: | 1180 case IrOpcode::kFloat64RoundTiesAway: |
| 1049 return VisitUnop(node, kMachFloat64, kMachFloat64); | 1181 return VisitUnop(node, UseInfo::Float64(), kMachFloat64); |
| 1050 case IrOpcode::kFloat64Equal: | 1182 case IrOpcode::kFloat64Equal: |
| 1051 case IrOpcode::kFloat64LessThan: | 1183 case IrOpcode::kFloat64LessThan: |
| 1052 case IrOpcode::kFloat64LessThanOrEqual: | 1184 case IrOpcode::kFloat64LessThanOrEqual: |
| 1053 return VisitFloat64Cmp(node); | 1185 return VisitFloat64Cmp(node); |
| 1054 case IrOpcode::kFloat64ExtractLowWord32: | 1186 case IrOpcode::kFloat64ExtractLowWord32: |
| 1055 case IrOpcode::kFloat64ExtractHighWord32: | 1187 case IrOpcode::kFloat64ExtractHighWord32: |
| 1056 return VisitUnop(node, kMachFloat64, kMachInt32); | 1188 return VisitUnop(node, UseInfo::Float64(), kMachInt32); |
| 1057 case IrOpcode::kFloat64InsertLowWord32: | 1189 case IrOpcode::kFloat64InsertLowWord32: |
| 1058 case IrOpcode::kFloat64InsertHighWord32: | 1190 case IrOpcode::kFloat64InsertHighWord32: |
| 1059 return VisitBinop(node, kMachFloat64, kMachInt32, kMachFloat64); | 1191 return VisitBinop(node, UseInfo::Float64(), UseInfo::TruncatingWord32(), |
| 1192 kMachFloat64); | |
| 1060 case IrOpcode::kLoadStackPointer: | 1193 case IrOpcode::kLoadStackPointer: |
| 1061 case IrOpcode::kLoadFramePointer: | 1194 case IrOpcode::kLoadFramePointer: |
| 1062 return VisitLeaf(node, kMachPtr); | 1195 return VisitLeaf(node, kMachPtr); |
| 1063 case IrOpcode::kStateValues: | 1196 case IrOpcode::kStateValues: |
| 1064 VisitStateValues(node); | 1197 VisitStateValues(node); |
| 1065 break; | 1198 break; |
| 1066 default: | 1199 default: |
| 1067 VisitInputs(node); | 1200 VisitInputs(node); |
| 1068 break; | 1201 break; |
| 1069 } | 1202 } |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 1096 TRACE("\n"); | 1229 TRACE("\n"); |
| 1097 } | 1230 } |
| 1098 | 1231 |
| 1099 void PrintInfo(MachineTypeUnion info) { | 1232 void PrintInfo(MachineTypeUnion info) { |
| 1100 if (FLAG_trace_representation) { | 1233 if (FLAG_trace_representation) { |
| 1101 OFStream os(stdout); | 1234 OFStream os(stdout); |
| 1102 os << static_cast<MachineType>(info); | 1235 os << static_cast<MachineType>(info); |
| 1103 } | 1236 } |
| 1104 } | 1237 } |
| 1105 | 1238 |
| 1239 void PrintUseInfo(UseInfo info) { | |
| 1240 if (FLAG_trace_representation) { | |
| 1241 OFStream os(stdout); | |
| 1242 os << static_cast<MachineType>(info.machine_type()); | |
| 1243 } | |
| 1244 } | |
| 1245 | |
| 1106 private: | 1246 private: |
| 1107 JSGraph* jsgraph_; | 1247 JSGraph* jsgraph_; |
| 1108 size_t const count_; // number of nodes in the graph | 1248 size_t const count_; // number of nodes in the graph |
| 1109 NodeInfo* info_; // node id -> usage information | 1249 NodeInfo* info_; // node id -> usage information |
| 1110 NodeVector nodes_; // collected nodes | 1250 NodeVector nodes_; // collected nodes |
| 1111 NodeVector replacements_; // replacements to be done after lowering | 1251 NodeVector replacements_; // replacements to be done after lowering |
| 1112 Phase phase_; // current phase of algorithm | 1252 Phase phase_; // current phase of algorithm |
| 1113 RepresentationChanger* changer_; // for inserting representation changes | 1253 RepresentationChanger* changer_; // for inserting representation changes |
| 1114 ZoneQueue<Node*> queue_; // queue for traversing the graph | 1254 ZoneQueue<Node*> queue_; // queue for traversing the graph |
| 1115 // TODO(danno): RepresentationSelector shouldn't know anything about the | 1255 // TODO(danno): RepresentationSelector shouldn't know anything about the |
| (...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1564 ReplaceEffectUses(node, comparison); | 1704 ReplaceEffectUses(node, comparison); |
| 1565 node->ReplaceInput(0, comparison); | 1705 node->ReplaceInput(0, comparison); |
| 1566 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL)); | 1706 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL)); |
| 1567 node->TrimInputCount(2); | 1707 node->TrimInputCount(2); |
| 1568 NodeProperties::ChangeOp(node, machine()->IntLessThanOrEqual()); | 1708 NodeProperties::ChangeOp(node, machine()->IntLessThanOrEqual()); |
| 1569 } | 1709 } |
| 1570 | 1710 |
| 1571 } // namespace compiler | 1711 } // namespace compiler |
| 1572 } // namespace internal | 1712 } // namespace internal |
| 1573 } // namespace v8 | 1713 } // namespace v8 |
| OLD | NEW |