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/address-map.h" | 9 #include "src/address-map.h" |
10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
(...skipping 1183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1194 } | 1194 } |
1195 switch (node->opcode()) { | 1195 switch (node->opcode()) { |
1196 //------------------------------------------------------------------ | 1196 //------------------------------------------------------------------ |
1197 // Common operators. | 1197 // Common operators. |
1198 //------------------------------------------------------------------ | 1198 //------------------------------------------------------------------ |
1199 case IrOpcode::kStart: | 1199 case IrOpcode::kStart: |
1200 // We use Start as a terminator for the frame state chain, so even | 1200 // We use Start as a terminator for the frame state chain, so even |
1201 // tho Start doesn't really produce a value, we have to say Tagged | 1201 // tho Start doesn't really produce a value, we have to say Tagged |
1202 // here, otherwise the input conversion will fail. | 1202 // here, otherwise the input conversion will fail. |
1203 return VisitLeaf(node, MachineRepresentation::kTagged); | 1203 return VisitLeaf(node, MachineRepresentation::kTagged); |
1204 case IrOpcode::kDead: | |
1205 return VisitLeaf(node, MachineRepresentation::kNone); | |
1206 case IrOpcode::kParameter: { | 1204 case IrOpcode::kParameter: { |
1207 // TODO(titzer): use representation from linkage. | 1205 // TODO(titzer): use representation from linkage. |
1208 ProcessInput(node, 0, UseInfo::None()); | 1206 ProcessInput(node, 0, UseInfo::None()); |
1209 SetOutput(node, MachineRepresentation::kTagged); | 1207 SetOutput(node, MachineRepresentation::kTagged); |
1210 return; | 1208 return; |
1211 } | 1209 } |
1212 case IrOpcode::kInt32Constant: | 1210 case IrOpcode::kInt32Constant: |
1213 return VisitLeaf(node, MachineRepresentation::kWord32); | 1211 return VisitLeaf(node, MachineRepresentation::kWord32); |
1214 case IrOpcode::kInt64Constant: | 1212 case IrOpcode::kInt64Constant: |
1215 return VisitLeaf(node, MachineRepresentation::kWord64); | 1213 return VisitLeaf(node, MachineRepresentation::kWord64); |
1216 case IrOpcode::kFloat32Constant: | |
1217 return VisitLeaf(node, MachineRepresentation::kFloat32); | |
1218 case IrOpcode::kFloat64Constant: | 1214 case IrOpcode::kFloat64Constant: |
1219 return VisitLeaf(node, MachineRepresentation::kFloat64); | 1215 return VisitLeaf(node, MachineRepresentation::kFloat64); |
1220 case IrOpcode::kExternalConstant: | 1216 case IrOpcode::kExternalConstant: |
1221 return VisitLeaf(node, MachineType::PointerRepresentation()); | 1217 return VisitLeaf(node, MachineType::PointerRepresentation()); |
1222 case IrOpcode::kNumberConstant: | 1218 case IrOpcode::kNumberConstant: |
1223 return VisitLeaf(node, MachineRepresentation::kTagged); | 1219 return VisitLeaf(node, MachineRepresentation::kTagged); |
1224 case IrOpcode::kHeapConstant: | 1220 case IrOpcode::kHeapConstant: |
1225 return VisitLeaf(node, MachineRepresentation::kTagged); | 1221 return VisitLeaf(node, MachineRepresentation::kTagged); |
1226 | 1222 |
1227 case IrOpcode::kDeoptimizeIf: | |
1228 case IrOpcode::kDeoptimizeUnless: | |
1229 ProcessInput(node, 0, UseInfo::Bool()); | |
1230 ProcessInput(node, 1, UseInfo::AnyTagged()); | |
1231 ProcessRemainingInputs(node, 2); | |
1232 return; | |
1233 case IrOpcode::kBranch: | 1223 case IrOpcode::kBranch: |
1234 ProcessInput(node, 0, UseInfo::Bool()); | 1224 ProcessInput(node, 0, UseInfo::Bool()); |
1235 EnqueueInput(node, NodeProperties::FirstControlIndex(node)); | 1225 EnqueueInput(node, NodeProperties::FirstControlIndex(node)); |
1236 return; | 1226 return; |
1237 case IrOpcode::kSwitch: | 1227 case IrOpcode::kSwitch: |
1238 ProcessInput(node, 0, UseInfo::TruncatingWord32()); | 1228 ProcessInput(node, 0, UseInfo::TruncatingWord32()); |
1239 EnqueueInput(node, NodeProperties::FirstControlIndex(node)); | 1229 EnqueueInput(node, NodeProperties::FirstControlIndex(node)); |
1240 return; | 1230 return; |
1241 case IrOpcode::kSelect: | 1231 case IrOpcode::kSelect: |
1242 return VisitSelect(node, truncation, lowering); | 1232 return VisitSelect(node, truncation, lowering); |
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1573 return; | 1563 return; |
1574 } | 1564 } |
1575 if (truncation.IsUsedAsWord32()) { | 1565 if (truncation.IsUsedAsWord32()) { |
1576 // => signed Int32Div | 1566 // => signed Int32Div |
1577 VisitWord32TruncatingBinop(node); | 1567 VisitWord32TruncatingBinop(node); |
1578 if (lower()) DeferReplacement(node, lowering->Int32Div(node)); | 1568 if (lower()) DeferReplacement(node, lowering->Int32Div(node)); |
1579 return; | 1569 return; |
1580 } | 1570 } |
1581 } | 1571 } |
1582 // Number x Number => Float64Div | 1572 // Number x Number => Float64Div |
1583 if (BothInputsAre(node, Type::NumberOrUndefined())) { | 1573 VisitFloat64Binop(node); |
1584 VisitFloat64Binop(node); | |
1585 if (lower()) ChangeToPureOp(node, Float64Op(node)); | |
1586 return; | |
1587 } | |
1588 // Checked float64 x float64 => float64 | |
1589 DCHECK_EQ(IrOpcode::kSpeculativeNumberDivide, node->opcode()); | |
1590 VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(), | |
1591 MachineRepresentation::kFloat64, Type::Number()); | |
1592 if (lower()) ChangeToPureOp(node, Float64Op(node)); | 1574 if (lower()) ChangeToPureOp(node, Float64Op(node)); |
1593 return; | 1575 return; |
1594 } | 1576 } |
1595 case IrOpcode::kSpeculativeNumberModulus: { | 1577 case IrOpcode::kSpeculativeNumberModulus: { |
1596 // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we | 1578 // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we |
1597 // can only eliminate an unused speculative number operation if we know | 1579 // can only eliminate an unused speculative number operation if we know |
1598 // that the inputs are PlainPrimitive, which excludes everything that's | 1580 // that the inputs are PlainPrimitive, which excludes everything that's |
1599 // might have side effects or throws during a ToNumber conversion. | 1581 // might have side effects or throws during a ToNumber conversion. |
1600 if (BothInputsAre(node, Type::PlainPrimitive())) { | 1582 if (BothInputsAre(node, Type::PlainPrimitive())) { |
1601 if (truncation.IsUnused()) return VisitUnused(node); | 1583 if (truncation.IsUnused()) return VisitUnused(node); |
(...skipping 800 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2402 case IrOpcode::kMaybeGrowFastElements: { | 2384 case IrOpcode::kMaybeGrowFastElements: { |
2403 ProcessInput(node, 0, UseInfo::AnyTagged()); // object | 2385 ProcessInput(node, 0, UseInfo::AnyTagged()); // object |
2404 ProcessInput(node, 1, UseInfo::AnyTagged()); // elements | 2386 ProcessInput(node, 1, UseInfo::AnyTagged()); // elements |
2405 ProcessInput(node, 2, UseInfo::TruncatingWord32()); // index | 2387 ProcessInput(node, 2, UseInfo::TruncatingWord32()); // index |
2406 ProcessInput(node, 3, UseInfo::TruncatingWord32()); // length | 2388 ProcessInput(node, 3, UseInfo::TruncatingWord32()); // length |
2407 ProcessRemainingInputs(node, 4); | 2389 ProcessRemainingInputs(node, 4); |
2408 SetOutput(node, MachineRepresentation::kTagged); | 2390 SetOutput(node, MachineRepresentation::kTagged); |
2409 return; | 2391 return; |
2410 } | 2392 } |
2411 | 2393 |
2412 //------------------------------------------------------------------ | |
2413 // Machine-level operators. | |
2414 //------------------------------------------------------------------ | |
2415 case IrOpcode::kLoad: { | |
2416 // TODO(jarin) Eventually, we should get rid of all machine stores | |
2417 // from the high-level phases, then this becomes UNREACHABLE. | |
2418 LoadRepresentation rep = LoadRepresentationOf(node->op()); | |
2419 ProcessInput(node, 0, UseInfo::AnyTagged()); // tagged pointer | |
2420 ProcessInput(node, 1, UseInfo::PointerInt()); // index | |
2421 ProcessRemainingInputs(node, 2); | |
2422 return SetOutput(node, rep.representation()); | |
2423 } | |
2424 case IrOpcode::kStore: { | |
2425 // TODO(jarin) Eventually, we should get rid of all machine stores | |
2426 // from the high-level phases, then this becomes UNREACHABLE. | |
2427 StoreRepresentation rep = StoreRepresentationOf(node->op()); | |
2428 ProcessInput(node, 0, UseInfo::AnyTagged()); // tagged pointer | |
2429 ProcessInput(node, 1, UseInfo::PointerInt()); // index | |
2430 ProcessInput(node, 2, | |
2431 TruncatingUseInfoFromRepresentation(rep.representation())); | |
2432 ProcessRemainingInputs(node, 3); | |
2433 return SetOutput(node, MachineRepresentation::kNone); | |
2434 } | |
2435 case IrOpcode::kWord32Shr: | |
2436 // We output unsigned int32 for shift right because JavaScript. | |
2437 return VisitBinop(node, UseInfo::TruncatingWord32(), | |
2438 MachineRepresentation::kWord32); | |
2439 case IrOpcode::kWord32And: | |
2440 case IrOpcode::kWord32Or: | |
2441 case IrOpcode::kWord32Xor: | |
2442 case IrOpcode::kWord32Shl: | |
2443 case IrOpcode::kWord32Sar: | |
2444 // We use signed int32 as the output type for these word32 operations, | |
2445 // though the machine bits are the same for either signed or unsigned, | |
2446 // because JavaScript considers the result from these operations signed. | |
2447 return VisitBinop(node, UseInfo::TruncatingWord32(), | |
2448 MachineRepresentation::kWord32); | |
2449 case IrOpcode::kWord32Equal: | |
2450 return VisitBinop(node, UseInfo::TruncatingWord32(), | |
2451 MachineRepresentation::kBit); | |
2452 | |
2453 case IrOpcode::kWord32Clz: | |
2454 return VisitUnop(node, UseInfo::TruncatingWord32(), | |
2455 MachineRepresentation::kWord32); | |
2456 | |
2457 case IrOpcode::kInt32Add: | |
2458 case IrOpcode::kInt32Sub: | |
2459 case IrOpcode::kInt32Mul: | |
2460 case IrOpcode::kInt32MulHigh: | |
2461 case IrOpcode::kInt32Div: | |
2462 case IrOpcode::kInt32Mod: | |
2463 return VisitInt32Binop(node); | |
2464 case IrOpcode::kUint32Div: | |
2465 case IrOpcode::kUint32Mod: | |
2466 case IrOpcode::kUint32MulHigh: | |
2467 return VisitUint32Binop(node); | |
2468 case IrOpcode::kInt32LessThan: | |
2469 case IrOpcode::kInt32LessThanOrEqual: | |
2470 return VisitInt32Cmp(node); | |
2471 | |
2472 case IrOpcode::kUint32LessThan: | |
2473 case IrOpcode::kUint32LessThanOrEqual: | |
2474 return VisitUint32Cmp(node); | |
2475 | |
2476 case IrOpcode::kInt64Add: | |
2477 case IrOpcode::kInt64Sub: | |
2478 case IrOpcode::kInt64Mul: | |
2479 case IrOpcode::kInt64Div: | |
2480 case IrOpcode::kInt64Mod: | |
2481 return VisitInt64Binop(node); | |
2482 case IrOpcode::kInt64LessThan: | |
2483 case IrOpcode::kInt64LessThanOrEqual: | |
2484 return VisitInt64Cmp(node); | |
2485 | |
2486 case IrOpcode::kUint64LessThan: | |
2487 return VisitUint64Cmp(node); | |
2488 | |
2489 case IrOpcode::kUint64Div: | |
2490 case IrOpcode::kUint64Mod: | |
2491 return VisitUint64Binop(node); | |
2492 | |
2493 case IrOpcode::kWord64And: | |
2494 case IrOpcode::kWord64Or: | |
2495 case IrOpcode::kWord64Xor: | |
2496 case IrOpcode::kWord64Shl: | |
2497 case IrOpcode::kWord64Shr: | |
2498 case IrOpcode::kWord64Sar: | |
2499 return VisitBinop(node, UseInfo::TruncatingWord64(), | |
2500 MachineRepresentation::kWord64); | |
2501 case IrOpcode::kWord64Equal: | |
2502 return VisitBinop(node, UseInfo::TruncatingWord64(), | |
2503 MachineRepresentation::kBit); | |
2504 | |
2505 case IrOpcode::kChangeInt32ToInt64: | |
2506 return VisitUnop(node, UseInfo::TruncatingWord32(), | |
2507 MachineRepresentation::kWord64); | |
2508 case IrOpcode::kChangeUint32ToUint64: | |
2509 return VisitUnop(node, UseInfo::TruncatingWord32(), | |
2510 MachineRepresentation::kWord64); | |
2511 case IrOpcode::kTruncateFloat64ToFloat32: | |
2512 return VisitUnop(node, UseInfo::TruncatingFloat64(), | |
2513 MachineRepresentation::kFloat32); | |
2514 case IrOpcode::kTruncateFloat64ToWord32: | |
2515 return VisitUnop(node, UseInfo::TruncatingFloat64(), | |
2516 MachineRepresentation::kWord32); | |
2517 | |
2518 case IrOpcode::kChangeInt32ToFloat64: | |
2519 return VisitUnop(node, UseInfo::TruncatingWord32(), | |
2520 MachineRepresentation::kFloat64); | |
2521 case IrOpcode::kChangeUint32ToFloat64: | |
2522 return VisitUnop(node, UseInfo::TruncatingWord32(), | |
2523 MachineRepresentation::kFloat64); | |
2524 case IrOpcode::kFloat64Add: | |
2525 case IrOpcode::kFloat64Sub: | |
2526 case IrOpcode::kFloat64Mul: | |
2527 case IrOpcode::kFloat64Div: | |
2528 case IrOpcode::kFloat64Mod: | |
2529 case IrOpcode::kFloat64Min: | |
2530 return VisitFloat64Binop(node); | |
2531 case IrOpcode::kFloat64Abs: | |
2532 case IrOpcode::kFloat64Sqrt: | |
2533 case IrOpcode::kFloat64RoundDown: | |
2534 case IrOpcode::kFloat64RoundTruncate: | |
2535 case IrOpcode::kFloat64RoundTiesAway: | |
2536 case IrOpcode::kFloat64RoundUp: | |
2537 return VisitUnop(node, UseInfo::TruncatingFloat64(), | |
2538 MachineRepresentation::kFloat64); | |
2539 case IrOpcode::kFloat64SilenceNaN: | |
2540 return VisitUnop(node, UseInfo::TruncatingFloat64(), | |
2541 MachineRepresentation::kFloat64); | |
2542 case IrOpcode::kFloat64Equal: | |
2543 case IrOpcode::kFloat64LessThan: | |
2544 case IrOpcode::kFloat64LessThanOrEqual: | |
2545 return VisitFloat64Cmp(node); | |
2546 case IrOpcode::kFloat64ExtractLowWord32: | |
2547 case IrOpcode::kFloat64ExtractHighWord32: | |
2548 return VisitUnop(node, UseInfo::TruncatingFloat64(), | |
2549 MachineRepresentation::kWord32); | |
2550 case IrOpcode::kFloat64InsertLowWord32: | |
2551 case IrOpcode::kFloat64InsertHighWord32: | |
2552 return VisitBinop(node, UseInfo::TruncatingFloat64(), | |
2553 UseInfo::TruncatingWord32(), | |
2554 MachineRepresentation::kFloat64); | |
2555 case IrOpcode::kNumberSilenceNaN: | 2394 case IrOpcode::kNumberSilenceNaN: |
2556 VisitUnop(node, UseInfo::TruncatingFloat64(), | 2395 VisitUnop(node, UseInfo::TruncatingFloat64(), |
2557 MachineRepresentation::kFloat64); | 2396 MachineRepresentation::kFloat64); |
2558 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); | 2397 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); |
2559 return; | 2398 return; |
2560 case IrOpcode::kLoadStackPointer: | |
2561 case IrOpcode::kLoadFramePointer: | |
2562 case IrOpcode::kLoadParentFramePointer: | |
2563 return VisitLeaf(node, MachineType::PointerRepresentation()); | |
2564 case IrOpcode::kStateValues: | 2399 case IrOpcode::kStateValues: |
2565 return VisitStateValues(node); | 2400 return VisitStateValues(node); |
2566 case IrOpcode::kTypeGuard: { | 2401 case IrOpcode::kTypeGuard: { |
2567 // We just get rid of the sigma here. In principle, it should be | 2402 // We just get rid of the sigma here. In principle, it should be |
2568 // possible to refine the truncation and representation based on | 2403 // possible to refine the truncation and representation based on |
2569 // the sigma's type. | 2404 // the sigma's type. |
2570 MachineRepresentation output = | 2405 MachineRepresentation output = |
2571 GetOutputInfoForPhi(node, TypeOf(node->InputAt(0)), truncation); | 2406 GetOutputInfoForPhi(node, TypeOf(node->InputAt(0)), truncation); |
2572 | 2407 |
2573 VisitUnop(node, UseInfo(output, truncation), output); | 2408 VisitUnop(node, UseInfo(output, truncation), output); |
2574 if (lower()) DeferReplacement(node, node->InputAt(0)); | 2409 if (lower()) DeferReplacement(node, node->InputAt(0)); |
2575 return; | 2410 return; |
2576 } | 2411 } |
2577 | 2412 |
2578 // The following opcodes are not produced before representation | 2413 // Operators with all inputs tagged and no or tagged output have uniform |
2579 // inference runs, so we do not have any real test coverage. | 2414 // handling. |
2580 // Simply fail here. | 2415 case IrOpcode::kEnd: |
2581 case IrOpcode::kChangeFloat64ToInt32: | 2416 case IrOpcode::kReturn: |
2582 case IrOpcode::kChangeFloat64ToUint32: | 2417 case IrOpcode::kIfSuccess: |
2583 case IrOpcode::kTruncateInt64ToInt32: | 2418 case IrOpcode::kIfException: |
2584 case IrOpcode::kChangeFloat32ToFloat64: | 2419 case IrOpcode::kIfTrue: |
2585 case IrOpcode::kCheckedInt32Add: | 2420 case IrOpcode::kIfFalse: |
2586 case IrOpcode::kCheckedInt32Sub: | 2421 case IrOpcode::kDeoptimize: |
2587 case IrOpcode::kCheckedUint32ToInt32: | 2422 case IrOpcode::kEffectPhi: |
2588 case IrOpcode::kCheckedFloat64ToInt32: | 2423 case IrOpcode::kTerminate: |
2589 case IrOpcode::kCheckedTaggedToInt32: | 2424 case IrOpcode::kFrameState: |
2590 case IrOpcode::kCheckedTaggedToFloat64: | 2425 case IrOpcode::kCheckpoint: |
2591 case IrOpcode::kPlainPrimitiveToWord32: | 2426 case IrOpcode::kLoop: |
2592 case IrOpcode::kPlainPrimitiveToFloat64: | 2427 case IrOpcode::kMerge: |
2593 case IrOpcode::kLoopExit: | 2428 case IrOpcode::kThrow: |
2594 case IrOpcode::kLoopExitValue: | 2429 case IrOpcode::kBeginRegion: |
2595 case IrOpcode::kLoopExitEffect: | 2430 case IrOpcode::kFinishRegion: |
2596 FATAL("Representation inference: unsupported opcodes."); | 2431 case IrOpcode::kOsrValue: |
2597 break; | 2432 case IrOpcode::kProjection: |
2598 | 2433 case IrOpcode::kObjectState: |
2599 default: | 2434 // All JavaScript operators except JSToNumber have uniform handling. |
| 2435 #define OPCODE_CASE(name) case IrOpcode::k##name: |
| 2436 JS_SIMPLE_BINOP_LIST(OPCODE_CASE) |
| 2437 JS_OTHER_UNOP_LIST(OPCODE_CASE) |
| 2438 JS_OBJECT_OP_LIST(OPCODE_CASE) |
| 2439 JS_CONTEXT_OP_LIST(OPCODE_CASE) |
| 2440 JS_OTHER_OP_LIST(OPCODE_CASE) |
| 2441 #undef OPCODE_CASE |
| 2442 case IrOpcode::kJSToBoolean: |
| 2443 case IrOpcode::kJSToInteger: |
| 2444 case IrOpcode::kJSToLength: |
| 2445 case IrOpcode::kJSToName: |
| 2446 case IrOpcode::kJSToObject: |
| 2447 case IrOpcode::kJSToString: |
2600 VisitInputs(node); | 2448 VisitInputs(node); |
2601 // Assume the output is tagged. | 2449 // Assume the output is tagged. |
2602 return SetOutput(node, MachineRepresentation::kTagged); | 2450 return SetOutput(node, MachineRepresentation::kTagged); |
| 2451 |
| 2452 default: |
| 2453 V8_Fatal(__FILE__, __LINE__, |
| 2454 "Representation inference: unsupported opcode %s\n.", |
| 2455 node->op()->mnemonic()); |
| 2456 break; |
2603 } | 2457 } |
2604 UNREACHABLE(); | 2458 UNREACHABLE(); |
2605 } | 2459 } |
2606 | 2460 |
2607 void DeferReplacement(Node* node, Node* replacement) { | 2461 void DeferReplacement(Node* node, Node* replacement) { |
2608 TRACE("defer replacement #%d:%s with #%d:%s\n", node->id(), | 2462 TRACE("defer replacement #%d:%s with #%d:%s\n", node->id(), |
2609 node->op()->mnemonic(), replacement->id(), | 2463 node->op()->mnemonic(), replacement->id(), |
2610 replacement->op()->mnemonic()); | 2464 replacement->op()->mnemonic()); |
2611 | 2465 |
2612 // Disconnect the node from effect and control chains, if necessary. | 2466 // Disconnect the node from effect and control chains, if necessary. |
(...skipping 716 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3329 isolate(), graph()->zone(), callable.descriptor(), 0, flags, | 3183 isolate(), graph()->zone(), callable.descriptor(), 0, flags, |
3330 Operator::kNoProperties); | 3184 Operator::kNoProperties); |
3331 to_number_operator_.set(common()->Call(desc)); | 3185 to_number_operator_.set(common()->Call(desc)); |
3332 } | 3186 } |
3333 return to_number_operator_.get(); | 3187 return to_number_operator_.get(); |
3334 } | 3188 } |
3335 | 3189 |
3336 } // namespace compiler | 3190 } // namespace compiler |
3337 } // namespace internal | 3191 } // namespace internal |
3338 } // namespace v8 | 3192 } // namespace v8 |
OLD | NEW |