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