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

Side by Side Diff: src/compiler/js-typed-lowering.cc

Issue 2220573002: [turbofan] Add NumberOperationHint for speculative number operations. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Update comment. Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/js-typed-lowering.h ('k') | src/compiler/simplified-lowering.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/compiler/js-typed-lowering.h"
6
5 #include "src/code-factory.h" 7 #include "src/code-factory.h"
6 #include "src/compilation-dependencies.h" 8 #include "src/compilation-dependencies.h"
7 #include "src/compiler/access-builder.h" 9 #include "src/compiler/access-builder.h"
8 #include "src/compiler/js-graph.h" 10 #include "src/compiler/js-graph.h"
9 #include "src/compiler/js-typed-lowering.h"
10 #include "src/compiler/linkage.h" 11 #include "src/compiler/linkage.h"
11 #include "src/compiler/node-matchers.h" 12 #include "src/compiler/node-matchers.h"
12 #include "src/compiler/node-properties.h" 13 #include "src/compiler/node-properties.h"
13 #include "src/compiler/operator-properties.h" 14 #include "src/compiler/operator-properties.h"
14 #include "src/type-cache.h" 15 #include "src/type-cache.h"
15 #include "src/types.h" 16 #include "src/types.h"
16 17
17 namespace v8 { 18 namespace v8 {
18 namespace internal { 19 namespace internal {
19 namespace compiler { 20 namespace compiler {
20 21
21 // A helper class to simplify the process of reducing a single binop node with a 22 // A helper class to simplify the process of reducing a single binop node with a
22 // JSOperator. This class manages the rewriting of context, control, and effect 23 // JSOperator. This class manages the rewriting of context, control, and effect
23 // dependencies during lowering of a binop and contains numerous helper 24 // dependencies during lowering of a binop and contains numerous helper
24 // functions for matching the types of inputs to an operation. 25 // functions for matching the types of inputs to an operation.
25 class JSBinopReduction final { 26 class JSBinopReduction final {
26 public: 27 public:
27 JSBinopReduction(JSTypedLowering* lowering, Node* node) 28 JSBinopReduction(JSTypedLowering* lowering, Node* node)
28 : lowering_(lowering), node_(node) {} 29 : lowering_(lowering), node_(node) {}
29 30
30 BinaryOperationHints::Hint GetNumberBinaryOperationFeedback() { 31 bool GetBinaryNumberOperationHint(NumberOperationHint* hint) {
31 if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) { 32 if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) {
32 DCHECK_NE(0, node_->op()->ControlOutputCount()); 33 DCHECK_NE(0, node_->op()->ControlOutputCount());
33 DCHECK_EQ(1, node_->op()->EffectOutputCount()); 34 DCHECK_EQ(1, node_->op()->EffectOutputCount());
34 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node_->op())); 35 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node_->op()));
35 BinaryOperationHints hints = BinaryOperationHintsOf(node_->op()); 36 BinaryOperationHints hints = BinaryOperationHintsOf(node_->op());
36 BinaryOperationHints::Hint combined = hints.combined(); 37 switch (hints.combined()) {
37 if (combined == BinaryOperationHints::kSignedSmall || 38 case BinaryOperationHints::kSignedSmall:
38 combined == BinaryOperationHints::kSigned32 || 39 *hint = NumberOperationHint::kSignedSmall;
39 combined == BinaryOperationHints::kNumberOrOddball) { 40 return true;
40 return combined; 41 case BinaryOperationHints::kSigned32:
42 *hint = NumberOperationHint::kSigned32;
43 return true;
44 case BinaryOperationHints::kNumberOrOddball:
45 *hint = NumberOperationHint::kNumberOrOddball;
46 return true;
47 case BinaryOperationHints::kAny:
48 case BinaryOperationHints::kNone:
49 case BinaryOperationHints::kString:
50 break;
41 } 51 }
42 } 52 }
43 return BinaryOperationHints::kAny; 53 return false;
44 } 54 }
45 55
46 CompareOperationHints::Hint GetNumberCompareOperationFeedback() { 56 bool GetCompareNumberOperationHint(NumberOperationHint* hint) {
47 if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) { 57 if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) {
48 DCHECK_NE(0, node_->op()->ControlOutputCount()); 58 DCHECK_NE(0, node_->op()->ControlOutputCount());
49 DCHECK_EQ(1, node_->op()->EffectOutputCount()); 59 DCHECK_EQ(1, node_->op()->EffectOutputCount());
50 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node_->op())); 60 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node_->op()));
51 CompareOperationHints hints = CompareOperationHintsOf(node_->op()); 61 CompareOperationHints hints = CompareOperationHintsOf(node_->op());
52 CompareOperationHints::Hint combined = hints.combined(); 62 switch (hints.combined()) {
53 if (combined == CompareOperationHints::kSignedSmall || 63 case CompareOperationHints::kSignedSmall:
54 combined == CompareOperationHints::kNumberOrOddball) { 64 *hint = NumberOperationHint::kSignedSmall;
55 return combined; 65 return true;
66 case CompareOperationHints::kNumberOrOddball:
67 *hint = NumberOperationHint::kNumberOrOddball;
68 return true;
69 case CompareOperationHints::kAny:
70 case CompareOperationHints::kNone:
71 case CompareOperationHints::kString:
72 case CompareOperationHints::kBoolean:
73 case CompareOperationHints::kUniqueName:
74 case CompareOperationHints::kInternalizedString:
75 case CompareOperationHints::kReceiver:
76 break;
56 } 77 }
57 } 78 }
58 return CompareOperationHints::kAny; 79 return false;
59 } 80 }
60 81
61 void ConvertInputsToNumber() { 82 void ConvertInputsToNumber() {
62 // To convert the inputs to numbers, we have to provide frame states 83 // To convert the inputs to numbers, we have to provide frame states
63 // for lazy bailouts in the ToNumber conversions. 84 // for lazy bailouts in the ToNumber conversions.
64 // We use a little hack here: we take the frame state before the binary 85 // We use a little hack here: we take the frame state before the binary
65 // operation and use it to construct the frame states for the conversion 86 // operation and use it to construct the frame states for the conversion
66 // so that after the deoptimization, the binary operation IC gets 87 // so that after the deoptimization, the binary operation IC gets
67 // already converted values from full code. This way we are sure that we 88 // already converted values from full code. This way we are sure that we
68 // will not re-do any of the side effects. 89 // will not re-do any of the side effects.
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after
347 for (size_t k = 0; k < arraysize(shifted_int32_ranges_); ++k) { 368 for (size_t k = 0; k < arraysize(shifted_int32_ranges_); ++k) {
348 double min = kMinInt / (1 << k); 369 double min = kMinInt / (1 << k);
349 double max = kMaxInt / (1 << k); 370 double max = kMaxInt / (1 << k);
350 shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone()); 371 shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone());
351 } 372 }
352 } 373 }
353 374
354 375
355 Reduction JSTypedLowering::ReduceJSAdd(Node* node) { 376 Reduction JSTypedLowering::ReduceJSAdd(Node* node) {
356 JSBinopReduction r(this, node); 377 JSBinopReduction r(this, node);
357 BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); 378 NumberOperationHint hint;
358 if (feedback == BinaryOperationHints::kNumberOrOddball && 379 if (r.GetBinaryNumberOperationHint(&hint)) {
359 r.BothInputsAre(Type::PlainPrimitive()) && 380 if (hint == NumberOperationHint::kNumberOrOddball &&
360 r.NeitherInputCanBe(Type::StringOrReceiver())) { 381 r.BothInputsAre(Type::PlainPrimitive()) &&
361 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y)) 382 r.NeitherInputCanBe(Type::StringOrReceiver())) {
362 r.ConvertInputsToNumber(); 383 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y))
363 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number()); 384 r.ConvertInputsToNumber();
364 } 385 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
365 if (feedback != BinaryOperationHints::kAny) { 386 }
366 // Lower to the optimistic number binop.
367 return r.ChangeToSpeculativeOperator( 387 return r.ChangeToSpeculativeOperator(
368 simplified()->SpeculativeNumberAdd(feedback), Type::Number()); 388 simplified()->SpeculativeNumberAdd(hint), Type::Number());
369 } 389 }
370 if (r.BothInputsAre(Type::Number())) { 390 if (r.BothInputsAre(Type::Number())) {
371 // JSAdd(x:number, y:number) => NumberAdd(x, y) 391 // JSAdd(x:number, y:number) => NumberAdd(x, y)
372 r.ConvertInputsToNumber(); 392 r.ConvertInputsToNumber();
373 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number()); 393 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
374 } 394 }
375 if ((r.BothInputsAre(Type::PlainPrimitive()) || 395 if ((r.BothInputsAre(Type::PlainPrimitive()) ||
376 !(flags() & kDeoptimizationEnabled)) && 396 !(flags() & kDeoptimizationEnabled)) &&
377 r.NeitherInputCanBe(Type::StringOrReceiver())) { 397 r.NeitherInputCanBe(Type::StringOrReceiver())) {
378 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y)) 398 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y))
(...skipping 16 matching lines...) Expand all
395 CallDescriptor::kNeedsFrameState, node->op()->properties()); 415 CallDescriptor::kNeedsFrameState, node->op()->properties());
396 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op())); 416 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
397 node->InsertInput(graph()->zone(), 0, 417 node->InsertInput(graph()->zone(), 0,
398 jsgraph()->HeapConstant(callable.code())); 418 jsgraph()->HeapConstant(callable.code()));
399 NodeProperties::ChangeOp(node, common()->Call(desc)); 419 NodeProperties::ChangeOp(node, common()->Call(desc));
400 return Changed(node); 420 return Changed(node);
401 } 421 }
402 return NoChange(); 422 return NoChange();
403 } 423 }
404 424
405
406 Reduction JSTypedLowering::ReduceJSSubtract(Node* node) { 425 Reduction JSTypedLowering::ReduceJSSubtract(Node* node) {
407 JSBinopReduction r(this, node); 426 JSBinopReduction r(this, node);
408 BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); 427 NumberOperationHint hint;
409 if (feedback == BinaryOperationHints::kNumberOrOddball && 428 if (r.GetBinaryNumberOperationHint(&hint)) {
410 r.BothInputsAre(Type::PlainPrimitive())) { 429 if (hint == NumberOperationHint::kNumberOrOddball &&
411 // JSSubtract(x:plain-primitive, y:plain-primitive) 430 r.BothInputsAre(Type::PlainPrimitive())) {
412 // => NumberSubtract(ToNumber(x), ToNumber(y)) 431 // JSSubtract(x:plain-primitive, y:plain-primitive)
413 r.ConvertInputsToNumber(); 432 // => NumberSubtract(ToNumber(x), ToNumber(y))
414 return r.ChangeToPureOperator(simplified()->NumberSubtract(), 433 r.ConvertInputsToNumber();
415 Type::Number()); 434 return r.ChangeToPureOperator(simplified()->NumberSubtract(),
435 Type::Number());
436 }
437 return r.ChangeToSpeculativeOperator(
438 simplified()->SpeculativeNumberSubtract(hint), Type::Number());
416 } 439 }
417 if (feedback != BinaryOperationHints::kAny) {
418 // Lower to the optimistic number binop.
419 return r.ChangeToSpeculativeOperator(
420 simplified()->SpeculativeNumberSubtract(feedback), Type::Number());
421 }
422
423 // If deoptimization is enabled we rely on type feedback.
424 if (r.BothInputsAre(Type::PlainPrimitive()) || 440 if (r.BothInputsAre(Type::PlainPrimitive()) ||
425 !(flags() & kDeoptimizationEnabled)) { 441 !(flags() & kDeoptimizationEnabled)) {
426 r.ConvertInputsToNumber(); 442 r.ConvertInputsToNumber();
427 return r.ChangeToPureOperator(simplified()->NumberSubtract(), 443 return r.ChangeToPureOperator(simplified()->NumberSubtract(),
428 Type::Number()); 444 Type::Number());
429 } 445 }
430
431 return NoChange(); 446 return NoChange();
432 } 447 }
433 448
434 Reduction JSTypedLowering::ReduceJSMultiply(Node* node) { 449 Reduction JSTypedLowering::ReduceJSMultiply(Node* node) {
435 JSBinopReduction r(this, node); 450 JSBinopReduction r(this, node);
436 BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); 451 NumberOperationHint hint;
437 if (feedback == BinaryOperationHints::kNumberOrOddball && 452 if (r.GetBinaryNumberOperationHint(&hint)) {
438 r.BothInputsAre(Type::PlainPrimitive())) { 453 if (hint == NumberOperationHint::kNumberOrOddball &&
439 // JSMultiply(x:plain-primitive, 454 r.BothInputsAre(Type::PlainPrimitive())) {
440 // y:plain-primitive) => NumberMultiply(ToNumber(x), ToNumber(y)) 455 // JSMultiply(x:plain-primitive,
441 r.ConvertInputsToNumber(); 456 // y:plain-primitive) => NumberMultiply(ToNumber(x),
442 return r.ChangeToPureOperator(simplified()->NumberMultiply(), 457 // ToNumber(y))
443 Type::Number()); 458 r.ConvertInputsToNumber();
459 return r.ChangeToPureOperator(simplified()->NumberMultiply(),
460 Type::Number());
461 }
462 return r.ChangeToSpeculativeOperator(
463 simplified()->SpeculativeNumberMultiply(hint), Type::Number());
444 } 464 }
445 if (feedback != BinaryOperationHints::kAny) {
446 return r.ChangeToSpeculativeOperator(
447 simplified()->SpeculativeNumberMultiply(feedback), Type::Number());
448 }
449
450 // If deoptimization is enabled we rely on type feedback.
451 if (r.BothInputsAre(Type::PlainPrimitive()) || 465 if (r.BothInputsAre(Type::PlainPrimitive()) ||
452 !(flags() & kDeoptimizationEnabled)) { 466 !(flags() & kDeoptimizationEnabled)) {
453 r.ConvertInputsToNumber(); 467 r.ConvertInputsToNumber();
454 return r.ChangeToPureOperator(simplified()->NumberMultiply(), 468 return r.ChangeToPureOperator(simplified()->NumberMultiply(),
455 Type::Number()); 469 Type::Number());
456 } 470 }
457
458 return NoChange(); 471 return NoChange();
459 } 472 }
460 473
461 Reduction JSTypedLowering::ReduceJSDivide(Node* node) { 474 Reduction JSTypedLowering::ReduceJSDivide(Node* node) {
462 JSBinopReduction r(this, node); 475 JSBinopReduction r(this, node);
463 BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); 476 NumberOperationHint hint;
464 if (feedback == BinaryOperationHints::kNumberOrOddball && 477 if (r.GetBinaryNumberOperationHint(&hint)) {
465 r.BothInputsAre(Type::PlainPrimitive())) { 478 if (hint == NumberOperationHint::kNumberOrOddball &&
466 // JSDivide(x:plain-primitive, 479 r.BothInputsAre(Type::PlainPrimitive())) {
467 // y:plain-primitive) => NumberDivide(ToNumber(x), ToNumber(y)) 480 // JSDivide(x:plain-primitive,
468 r.ConvertInputsToNumber(); 481 // y:plain-primitive) => NumberDivide(ToNumber(x), ToNumber(y))
469 return r.ChangeToPureOperator(simplified()->NumberDivide(), Type::Number()); 482 r.ConvertInputsToNumber();
470 } 483 return r.ChangeToPureOperator(simplified()->NumberDivide(),
471 if (feedback != BinaryOperationHints::kAny) { 484 Type::Number());
485 }
472 return r.ChangeToSpeculativeOperator( 486 return r.ChangeToSpeculativeOperator(
473 simplified()->SpeculativeNumberDivide(feedback), Type::Number()); 487 simplified()->SpeculativeNumberDivide(hint), Type::Number());
474 } 488 }
475 if (r.BothInputsAre(Type::PlainPrimitive())) { 489 if (r.BothInputsAre(Type::PlainPrimitive())) {
476 // JSDivide(x:plain-primitive, 490 // JSDivide(x:plain-primitive,
477 // y:plain-primitive) => NumberDivide(ToNumber(x), ToNumber(y)) 491 // y:plain-primitive) => NumberDivide(ToNumber(x), ToNumber(y))
478 r.ConvertInputsToNumber(); 492 r.ConvertInputsToNumber();
479 return r.ChangeToPureOperator(simplified()->NumberDivide(), Type::Number()); 493 return r.ChangeToPureOperator(simplified()->NumberDivide(), Type::Number());
480 } 494 }
481 return NoChange(); 495 return NoChange();
482 } 496 }
483 497
484 Reduction JSTypedLowering::ReduceJSModulus(Node* node) { 498 Reduction JSTypedLowering::ReduceJSModulus(Node* node) {
485 JSBinopReduction r(this, node); 499 JSBinopReduction r(this, node);
486 BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); 500 NumberOperationHint hint;
487 if (feedback == BinaryOperationHints::kNumberOrOddball && 501 if (r.GetBinaryNumberOperationHint(&hint)) {
488 r.BothInputsAre(Type::PlainPrimitive())) { 502 if (hint == NumberOperationHint::kNumberOrOddball &&
489 // JSModulus(x:plain-primitive, 503 r.BothInputsAre(Type::PlainPrimitive())) {
490 // y:plain-primitive) => NumberModulus(ToNumber(x), ToNumber(y)) 504 // JSModulus(x:plain-primitive,
491 r.ConvertInputsToNumber(); 505 // y:plain-primitive) => NumberModulus(ToNumber(x), ToNumber(y))
492 return r.ChangeToPureOperator(simplified()->NumberModulus(), 506 r.ConvertInputsToNumber();
493 Type::Number()); 507 return r.ChangeToPureOperator(simplified()->NumberModulus(),
494 } 508 Type::Number());
495 if (feedback != BinaryOperationHints::kAny) { 509 }
496 return r.ChangeToSpeculativeOperator( 510 return r.ChangeToSpeculativeOperator(
497 simplified()->SpeculativeNumberModulus(feedback), Type::Number()); 511 simplified()->SpeculativeNumberModulus(hint), Type::Number());
498 } 512 }
499 if (r.BothInputsAre(Type::PlainPrimitive())) { 513 if (r.BothInputsAre(Type::PlainPrimitive())) {
500 // JSModulus(x:plain-primitive, 514 // JSModulus(x:plain-primitive,
501 // y:plain-primitive) => NumberModulus(ToNumber(x), ToNumber(y)) 515 // y:plain-primitive) => NumberModulus(ToNumber(x), ToNumber(y))
502 r.ConvertInputsToNumber(); 516 r.ConvertInputsToNumber();
503 return r.ChangeToPureOperator(simplified()->NumberModulus(), 517 return r.ChangeToPureOperator(simplified()->NumberModulus(),
504 Type::Number()); 518 Type::Number());
505 } 519 }
506 return NoChange(); 520 return NoChange();
507 } 521 }
508 522
509 Reduction JSTypedLowering::ReduceInt32Binop(Node* node, 523 Reduction JSTypedLowering::ReduceInt32Binop(Node* node,
510 const Operator* int_op) { 524 const Operator* int_op) {
511 JSBinopReduction r(this, node); 525 JSBinopReduction r(this, node);
512 BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); 526 NumberOperationHint hint;
513 if (feedback != BinaryOperationHints::kAny) { 527 if (r.GetBinaryNumberOperationHint(&hint)) {
514 Operator const* speculative_op; 528 Operator const* speculative_op;
515 if (int_op->opcode() == IrOpcode::kNumberBitwiseAnd) { 529 if (int_op->opcode() == IrOpcode::kNumberBitwiseAnd) {
516 speculative_op = simplified()->SpeculativeNumberBitwiseAnd(feedback); 530 speculative_op = simplified()->SpeculativeNumberBitwiseAnd(hint);
517 } else if (int_op->opcode() == IrOpcode::kNumberBitwiseOr) { 531 } else if (int_op->opcode() == IrOpcode::kNumberBitwiseOr) {
518 speculative_op = simplified()->SpeculativeNumberBitwiseOr(feedback); 532 speculative_op = simplified()->SpeculativeNumberBitwiseOr(hint);
519 } else { 533 } else {
520 DCHECK_EQ(IrOpcode::kNumberBitwiseXor, int_op->opcode()); 534 DCHECK_EQ(IrOpcode::kNumberBitwiseXor, int_op->opcode());
521 speculative_op = simplified()->SpeculativeNumberBitwiseXor(feedback); 535 speculative_op = simplified()->SpeculativeNumberBitwiseXor(hint);
522 } 536 }
523 return r.ChangeToSpeculativeOperator(speculative_op, Type::Signed32()); 537 return r.ChangeToSpeculativeOperator(speculative_op, Type::Signed32());
524 } 538 }
525
526 // If deoptimization is enabled we rely on type feedback.
527 if (r.BothInputsAre(Type::PlainPrimitive()) || 539 if (r.BothInputsAre(Type::PlainPrimitive()) ||
528 !(flags() & kDeoptimizationEnabled)) { 540 !(flags() & kDeoptimizationEnabled)) {
529 r.ConvertInputsToNumber(); 541 r.ConvertInputsToNumber();
530 r.ConvertInputsToUI32(kSigned, kSigned); 542 r.ConvertInputsToUI32(kSigned, kSigned);
531 return r.ChangeToPureOperator(int_op, Type::Signed32()); 543 return r.ChangeToPureOperator(int_op, Type::Signed32());
532 } 544 }
533 return NoChange(); 545 return NoChange();
534 } 546 }
535 547
536 Reduction JSTypedLowering::ReduceUI32Shift(Node* node, 548 Reduction JSTypedLowering::ReduceUI32Shift(Node* node, Signedness signedness,
537 Signedness left_signedness,
538 const Operator* shift_op) { 549 const Operator* shift_op) {
539 JSBinopReduction r(this, node); 550 JSBinopReduction r(this, node);
540 BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); 551 NumberOperationHint hint;
541 if (feedback != BinaryOperationHints::kAny) { 552 if (r.GetBinaryNumberOperationHint(&hint)) {
542 Operator const* speculative_op; 553 Operator const* speculative_op;
543 if (shift_op->opcode() == IrOpcode::kNumberShiftLeft) { 554 if (shift_op->opcode() == IrOpcode::kNumberShiftLeft) {
544 speculative_op = simplified()->SpeculativeNumberShiftLeft(feedback); 555 speculative_op = simplified()->SpeculativeNumberShiftLeft(hint);
545 } else if (shift_op->opcode() == IrOpcode::kNumberShiftRightLogical) { 556 } else if (shift_op->opcode() == IrOpcode::kNumberShiftRightLogical) {
546 speculative_op = 557 speculative_op = simplified()->SpeculativeNumberShiftRightLogical(hint);
547 simplified()->SpeculativeNumberShiftRightLogical(feedback);
548 } else { 558 } else {
549 DCHECK_EQ(IrOpcode::kNumberShiftRight, shift_op->opcode()); 559 DCHECK_EQ(IrOpcode::kNumberShiftRight, shift_op->opcode());
550 speculative_op = simplified()->SpeculativeNumberShiftRight(feedback); 560 speculative_op = simplified()->SpeculativeNumberShiftRight(hint);
551 } 561 }
552 return r.ChangeToSpeculativeOperator( 562 return r.ChangeToSpeculativeOperator(
553 speculative_op, shift_op->opcode() == IrOpcode::kNumberShiftRightLogical 563 speculative_op,
554 ? Type::Unsigned32() 564 signedness == kUnsigned ? Type::Unsigned32() : Type::Signed32());
555 : Type::Signed32());
556 } 565 }
557
558 // If deoptimization is enabled we rely on type feedback.
559 if (r.BothInputsAre(Type::PlainPrimitive()) || 566 if (r.BothInputsAre(Type::PlainPrimitive()) ||
560 !(flags() & kDeoptimizationEnabled)) { 567 !(flags() & kDeoptimizationEnabled)) {
561 r.ConvertInputsToNumber(); 568 r.ConvertInputsToNumber();
562 r.ConvertInputsToUI32(left_signedness, kUnsigned); 569 r.ConvertInputsToUI32(signedness, kUnsigned);
563 return r.ChangeToPureOperator(shift_op); 570 return r.ChangeToPureOperator(shift_op);
564 } 571 }
565 return NoChange(); 572 return NoChange();
566 } 573 }
567 574
568 Reduction JSTypedLowering::ReduceJSComparison(Node* node) { 575 Reduction JSTypedLowering::ReduceJSComparison(Node* node) {
569 JSBinopReduction r(this, node); 576 JSBinopReduction r(this, node);
570 if (r.BothInputsAre(Type::String())) { 577 if (r.BothInputsAre(Type::String())) {
571 // If both inputs are definitely strings, perform a string comparison. 578 // If both inputs are definitely strings, perform a string comparison.
572 const Operator* stringOp; 579 const Operator* stringOp;
(...skipping 12 matching lines...) Expand all
585 stringOp = simplified()->StringLessThanOrEqual(); 592 stringOp = simplified()->StringLessThanOrEqual();
586 r.SwapInputs(); // a >= b => b <= a 593 r.SwapInputs(); // a >= b => b <= a
587 break; 594 break;
588 default: 595 default:
589 return NoChange(); 596 return NoChange();
590 } 597 }
591 r.ChangeToPureOperator(stringOp); 598 r.ChangeToPureOperator(stringOp);
592 return Changed(node); 599 return Changed(node);
593 } 600 }
594 601
595 CompareOperationHints::Hint hint = r.GetNumberCompareOperationFeedback(); 602 NumberOperationHint hint;
596 if (hint != CompareOperationHints::kAny || 603 const Operator* less_than;
597 r.OneInputCannotBe(Type::StringOrReceiver())) { 604 const Operator* less_than_or_equal;
598 const Operator* less_than; 605 if (r.BothInputsAre(Type::Signed32()) ||
599 const Operator* less_than_or_equal; 606 r.BothInputsAre(Type::Unsigned32())) {
600 if (r.BothInputsAre(Type::Signed32()) || 607 less_than = simplified()->NumberLessThan();
601 r.BothInputsAre(Type::Unsigned32())) { 608 less_than_or_equal = simplified()->NumberLessThanOrEqual();
602 less_than = simplified()->NumberLessThan(); 609 } else if (r.GetCompareNumberOperationHint(&hint)) {
603 less_than_or_equal = simplified()->NumberLessThanOrEqual(); 610 less_than = simplified()->SpeculativeNumberLessThan(hint);
604 } else if (hint != CompareOperationHints::kAny) { 611 less_than_or_equal = simplified()->SpeculativeNumberLessThanOrEqual(hint);
605 less_than = simplified()->SpeculativeNumberLessThan(hint); 612 } else if (r.OneInputCannotBe(Type::StringOrReceiver()) &&
606 less_than_or_equal = simplified()->SpeculativeNumberLessThanOrEqual(hint); 613 (r.BothInputsAre(Type::PlainPrimitive()) ||
607 } else if (r.BothInputsAre(Type::PlainPrimitive()) || 614 !(flags() & kDeoptimizationEnabled))) {
608 !(flags() & kDeoptimizationEnabled)) { 615 r.ConvertInputsToNumber();
609 r.ConvertInputsToNumber(); 616 less_than = simplified()->NumberLessThan();
610 less_than = simplified()->NumberLessThan(); 617 less_than_or_equal = simplified()->NumberLessThanOrEqual();
611 less_than_or_equal = simplified()->NumberLessThanOrEqual(); 618 } else {
612 } else { 619 return NoChange();
620 }
621 const Operator* comparison;
622 switch (node->opcode()) {
623 case IrOpcode::kJSLessThan:
624 comparison = less_than;
625 break;
626 case IrOpcode::kJSGreaterThan:
627 comparison = less_than;
628 r.SwapInputs(); // a > b => b < a
629 break;
630 case IrOpcode::kJSLessThanOrEqual:
631 comparison = less_than_or_equal;
632 break;
633 case IrOpcode::kJSGreaterThanOrEqual:
634 comparison = less_than_or_equal;
635 r.SwapInputs(); // a >= b => b <= a
636 break;
637 default:
613 return NoChange(); 638 return NoChange();
614 }
615 const Operator* comparison;
616 switch (node->opcode()) {
617 case IrOpcode::kJSLessThan:
618 comparison = less_than;
619 break;
620 case IrOpcode::kJSGreaterThan:
621 comparison = less_than;
622 r.SwapInputs(); // a > b => b < a
623 break;
624 case IrOpcode::kJSLessThanOrEqual:
625 comparison = less_than_or_equal;
626 break;
627 case IrOpcode::kJSGreaterThanOrEqual:
628 comparison = less_than_or_equal;
629 r.SwapInputs(); // a >= b => b <= a
630 break;
631 default:
632 return NoChange();
633 }
634 if (comparison->EffectInputCount() > 0) {
635 return r.ChangeToSpeculativeOperator(comparison, Type::Boolean());
636 } else {
637 return r.ChangeToPureOperator(comparison);
638 }
639 } 639 }
640 // TODO(turbofan): relax/remove effects of this operator in other cases. 640 if (comparison->EffectInputCount() > 0) {
641 return NoChange(); // Keep a generic comparison. 641 return r.ChangeToSpeculativeOperator(comparison, Type::Boolean());
642 } else {
643 return r.ChangeToPureOperator(comparison);
644 }
642 } 645 }
643 646
644 Reduction JSTypedLowering::ReduceJSEqualTypeOf(Node* node, bool invert) { 647 Reduction JSTypedLowering::ReduceJSEqualTypeOf(Node* node, bool invert) {
645 HeapObjectBinopMatcher m(node); 648 HeapObjectBinopMatcher m(node);
646 if (m.left().IsJSTypeOf() && m.right().HasValue() && 649 if (m.left().IsJSTypeOf() && m.right().HasValue() &&
647 m.right().Value()->IsString()) { 650 m.right().Value()->IsString()) {
648 Node* replacement; 651 Node* replacement;
649 Node* input = m.left().InputAt(0); 652 Node* input = m.left().InputAt(0);
650 Handle<String> value = Handle<String>::cast(m.right().Value()); 653 Handle<String> value = Handle<String>::cast(m.right().Value());
651 if (String::Equals(value, factory()->boolean_string())) { 654 if (String::Equals(value, factory()->boolean_string())) {
(...skipping 1444 matching lines...) Expand 10 before | Expand all | Expand 10 after
2096 } 2099 }
2097 2100
2098 2101
2099 CompilationDependencies* JSTypedLowering::dependencies() const { 2102 CompilationDependencies* JSTypedLowering::dependencies() const {
2100 return dependencies_; 2103 return dependencies_;
2101 } 2104 }
2102 2105
2103 } // namespace compiler 2106 } // namespace compiler
2104 } // namespace internal 2107 } // namespace internal
2105 } // namespace v8 2108 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/js-typed-lowering.h ('k') | src/compiler/simplified-lowering.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698