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

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

Issue 2181743004: [turbofan] Speculative optimize number operations with no feedback. Base URL: https://chromium.googlesource.com/v8/v8.git@631318
Patch Set: Created 4 years, 5 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
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/code-factory.h" 5 #include "src/code-factory.h"
6 #include "src/compilation-dependencies.h" 6 #include "src/compilation-dependencies.h"
7 #include "src/compiler/access-builder.h" 7 #include "src/compiler/access-builder.h"
8 #include "src/compiler/js-graph.h" 8 #include "src/compiler/js-graph.h"
9 #include "src/compiler/js-typed-lowering.h" 9 #include "src/compiler/js-typed-lowering.h"
10 #include "src/compiler/linkage.h" 10 #include "src/compiler/linkage.h"
11 #include "src/compiler/node-matchers.h" 11 #include "src/compiler/node-matchers.h"
12 #include "src/compiler/node-properties.h" 12 #include "src/compiler/node-properties.h"
13 #include "src/compiler/operator-properties.h" 13 #include "src/compiler/operator-properties.h"
14 #include "src/type-cache.h" 14 #include "src/type-cache.h"
15 #include "src/types.h" 15 #include "src/types.h"
16 16
17 namespace v8 { 17 namespace v8 {
18 namespace internal { 18 namespace internal {
19 namespace compiler { 19 namespace compiler {
20 20
21 // A helper class to simplify the process of reducing a single binop node with a 21 // 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 22 // JSOperator. This class manages the rewriting of context, control, and effect
23 // dependencies during lowering of a binop and contains numerous helper 23 // dependencies during lowering of a binop and contains numerous helper
24 // functions for matching the types of inputs to an operation. 24 // functions for matching the types of inputs to an operation.
25 class JSBinopReduction final { 25 class JSBinopReduction final {
26 public: 26 public:
27 JSBinopReduction(JSTypedLowering* lowering, Node* node) 27 JSBinopReduction(JSTypedLowering* lowering, Node* node)
28 : lowering_(lowering), node_(node) {} 28 : lowering_(lowering), node_(node) {}
29 29
30 BinaryOperationHints::Hint GetNumberBinaryOperationFeedback() { 30 bool GetBinaryNumberOperationHint(NumberOperationHint* hint) {
31 if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) { 31 if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) {
32 DCHECK_NE(0, node_->op()->ControlOutputCount()); 32 DCHECK_NE(0, node_->op()->ControlOutputCount());
33 DCHECK_EQ(1, node_->op()->EffectOutputCount()); 33 DCHECK_EQ(1, node_->op()->EffectOutputCount());
34 DCHECK_LE(1, OperatorProperties::GetFrameStateInputCount(node_->op())); 34 DCHECK_LE(1, OperatorProperties::GetFrameStateInputCount(node_->op()));
35 BinaryOperationHints hints = BinaryOperationHintsOf(node_->op()); 35 BinaryOperationHints hints = BinaryOperationHintsOf(node_->op());
36 BinaryOperationHints::Hint combined = hints.combined(); 36 switch (hints.combined()) {
37 if (combined == BinaryOperationHints::kSignedSmall || 37 case BinaryOperationHints::kNone:
38 combined == BinaryOperationHints::kSigned32 || 38 *hint = NumberOperationHint::kNone;
39 combined == BinaryOperationHints::kNumberOrOddball) { 39 return true;
40 return combined; 40 case BinaryOperationHints::kSignedSmall:
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::kString:
48 case BinaryOperationHints::kAny:
49 return false;
41 } 50 }
42 } 51 }
43 return BinaryOperationHints::kAny; 52 return false;
44 } 53 }
45 54
46 CompareOperationHints::Hint GetNumberCompareOperationFeedback() { 55 bool GetCompareNumberOperationHint(NumberOperationHint* hint) {
47 if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) { 56 if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) {
48 DCHECK_NE(0, node_->op()->ControlOutputCount()); 57 DCHECK_NE(0, node_->op()->ControlOutputCount());
49 DCHECK_EQ(1, node_->op()->EffectOutputCount()); 58 DCHECK_EQ(1, node_->op()->EffectOutputCount());
50 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node_->op())); 59 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node_->op()));
51 CompareOperationHints hints = CompareOperationHintsOf(node_->op()); 60 CompareOperationHints hints = CompareOperationHintsOf(node_->op());
52 CompareOperationHints::Hint combined = hints.combined(); 61 CompareOperationHints::Hint combined = hints.combined();
53 if (combined == CompareOperationHints::kSignedSmall || 62 if (combined == CompareOperationHints::kNone) {
54 combined == CompareOperationHints::kNumberOrOddball) { 63 *hint = NumberOperationHint::kNone;
55 return combined; 64 return true;
65 } else if (combined == CompareOperationHints::kSignedSmall) {
66 *hint = NumberOperationHint::kSigned32;
67 return true;
68 } else if (combined == CompareOperationHints::kNumberOrOddball) {
69 *hint = NumberOperationHint::kNumberOrOddball;
70 return true;
56 } 71 }
57 } 72 }
58 return CompareOperationHints::kAny; 73 return false;
59 } 74 }
60 75
61 void ConvertInputsToNumber() { 76 void ConvertInputsToNumber() {
62 // To convert the inputs to numbers, we have to provide frame states 77 // To convert the inputs to numbers, we have to provide frame states
63 // for lazy bailouts in the ToNumber conversions. 78 // for lazy bailouts in the ToNumber conversions.
64 // We use a little hack here: we take the frame state before the binary 79 // 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 80 // operation and use it to construct the frame states for the conversion
66 // so that after the deoptimization, the binary operation IC gets 81 // so that after the deoptimization, the binary operation IC gets
67 // already converted values from full code. This way we are sure that we 82 // already converted values from full code. This way we are sure that we
68 // will not re-do any of the side effects. 83 // will not re-do any of the side effects.
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 // Insert an boolean not to invert the value. 146 // Insert an boolean not to invert the value.
132 Node* value = graph()->NewNode(simplified()->BooleanNot(), node_); 147 Node* value = graph()->NewNode(simplified()->BooleanNot(), node_);
133 node_->ReplaceUses(value); 148 node_->ReplaceUses(value);
134 // Note: ReplaceUses() smashes all uses, so smash it back here. 149 // Note: ReplaceUses() smashes all uses, so smash it back here.
135 value->ReplaceInput(0, node_); 150 value->ReplaceInput(0, node_);
136 return lowering_->Replace(value); 151 return lowering_->Replace(value);
137 } 152 }
138 return lowering_->Changed(node_); 153 return lowering_->Changed(node_);
139 } 154 }
140 155
141 Reduction ChangeToSpeculativeOperator(const Operator* op, Type* upper_bound) { 156 Reduction ChangeToPureOperator(const Operator* op, Type* type) {
157 return ChangeToPureOperator(op, false, type);
158 }
159
160 Reduction ChangeToSpeculativeOperator(const Operator* op,
161 Type* type = Type::Any()) {
142 DCHECK_EQ(1, op->EffectInputCount()); 162 DCHECK_EQ(1, op->EffectInputCount());
143 DCHECK_EQ(1, op->EffectOutputCount()); 163 DCHECK_EQ(1, op->EffectOutputCount());
144 DCHECK_EQ(false, OperatorProperties::HasContextInput(op)); 164 DCHECK_EQ(false, OperatorProperties::HasContextInput(op));
145 DCHECK_EQ(1, op->ControlInputCount()); 165 DCHECK_EQ(1, op->ControlInputCount());
146 DCHECK_EQ(0, op->ControlOutputCount()); 166 DCHECK_EQ(0, op->ControlOutputCount());
147 DCHECK_EQ(0, OperatorProperties::GetFrameStateInputCount(op)); 167 DCHECK_EQ(0, OperatorProperties::GetFrameStateInputCount(op));
148 DCHECK_EQ(2, op->ValueInputCount()); 168 DCHECK_EQ(2, op->ValueInputCount());
149 169
150 DCHECK_EQ(1, node_->op()->EffectInputCount()); 170 DCHECK_EQ(1, node_->op()->EffectInputCount());
151 DCHECK_EQ(1, node_->op()->EffectOutputCount()); 171 DCHECK_EQ(1, node_->op()->EffectOutputCount());
(...skipping 22 matching lines...) Expand all
174 if (OperatorProperties::GetFrameStateInputCount(node_->op()) == 2) { 194 if (OperatorProperties::GetFrameStateInputCount(node_->op()) == 2) {
175 node_->RemoveInput(NodeProperties::FirstFrameStateIndex(node_) + 1); 195 node_->RemoveInput(NodeProperties::FirstFrameStateIndex(node_) + 1);
176 } 196 }
177 node_->RemoveInput(NodeProperties::FirstFrameStateIndex(node_)); 197 node_->RemoveInput(NodeProperties::FirstFrameStateIndex(node_));
178 node_->RemoveInput(NodeProperties::FirstContextIndex(node_)); 198 node_->RemoveInput(NodeProperties::FirstContextIndex(node_));
179 199
180 NodeProperties::ChangeOp(node_, op); 200 NodeProperties::ChangeOp(node_, op);
181 201
182 // Update the type to number. 202 // Update the type to number.
183 Type* node_type = NodeProperties::GetType(node_); 203 Type* node_type = NodeProperties::GetType(node_);
184 NodeProperties::SetType(node_, 204 NodeProperties::SetType(node_, Type::Intersect(node_type, type, zone()));
185 Type::Intersect(node_type, upper_bound, zone()));
186 205
187 return lowering_->Changed(node_); 206 return lowering_->Changed(node_);
188 } 207 }
189 208
190 Reduction ChangeToPureOperator(const Operator* op, Type* type) {
191 return ChangeToPureOperator(op, false, type);
192 }
193
194 bool LeftInputIs(Type* t) { return left_type()->Is(t); } 209 bool LeftInputIs(Type* t) { return left_type()->Is(t); }
195 210
196 bool RightInputIs(Type* t) { return right_type()->Is(t); } 211 bool RightInputIs(Type* t) { return right_type()->Is(t); }
197 212
198 bool OneInputIs(Type* t) { return LeftInputIs(t) || RightInputIs(t); } 213 bool OneInputIs(Type* t) { return LeftInputIs(t) || RightInputIs(t); }
199 214
200 bool BothInputsAre(Type* t) { return LeftInputIs(t) && RightInputIs(t); } 215 bool BothInputsAre(Type* t) { return LeftInputIs(t) && RightInputIs(t); }
201 216
202 bool OneInputCannotBe(Type* t) { 217 bool OneInputCannotBe(Type* t) {
203 return !left_type()->Maybe(t) || !right_type()->Maybe(t); 218 return !left_type()->Maybe(t) || !right_type()->Maybe(t);
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
422 for (size_t k = 0; k < arraysize(shifted_int32_ranges_); ++k) { 437 for (size_t k = 0; k < arraysize(shifted_int32_ranges_); ++k) {
423 double min = kMinInt / (1 << k); 438 double min = kMinInt / (1 << k);
424 double max = kMaxInt / (1 << k); 439 double max = kMaxInt / (1 << k);
425 shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone()); 440 shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone());
426 } 441 }
427 } 442 }
428 443
429 444
430 Reduction JSTypedLowering::ReduceJSAdd(Node* node) { 445 Reduction JSTypedLowering::ReduceJSAdd(Node* node) {
431 JSBinopReduction r(this, node); 446 JSBinopReduction r(this, node);
432 BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback();
433 if (feedback == BinaryOperationHints::kNumberOrOddball &&
434 r.BothInputsAre(Type::PlainPrimitive()) &&
435 r.NeitherInputCanBe(Type::StringOrReceiver())) {
436 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y))
437 r.ConvertInputsToNumber();
438 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
439 }
440 if (feedback != BinaryOperationHints::kAny) {
441 // Lower to the optimistic number binop.
442 return r.ChangeToSpeculativeOperator(
443 simplified()->SpeculativeNumberAdd(feedback), Type::Number());
444 }
445 if (r.BothInputsAre(Type::Number())) {
446 // JSAdd(x:number, y:number) => NumberAdd(x, y)
447 r.ConvertInputsToNumber();
448 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
449 }
450 if ((r.BothInputsAre(Type::PlainPrimitive()) ||
451 !(flags() & kDeoptimizationEnabled)) &&
452 r.NeitherInputCanBe(Type::StringOrReceiver())) {
453 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y))
454 r.ConvertInputsToNumber();
455 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
456 }
457 if (r.OneInputIs(Type::String())) { 447 if (r.OneInputIs(Type::String())) {
458 StringAddFlags flags = STRING_ADD_CHECK_NONE; 448 StringAddFlags flags = STRING_ADD_CHECK_NONE;
459 if (!r.LeftInputIs(Type::String())) { 449 if (!r.LeftInputIs(Type::String())) {
460 flags = STRING_ADD_CONVERT_LEFT; 450 flags = STRING_ADD_CONVERT_LEFT;
461 } else if (!r.RightInputIs(Type::String())) { 451 } else if (!r.RightInputIs(Type::String())) {
462 flags = STRING_ADD_CONVERT_RIGHT; 452 flags = STRING_ADD_CONVERT_RIGHT;
463 } 453 }
464 // JSAdd(x:string, y) => CallStub[StringAdd](x, y) 454 // JSAdd(x:string, y) => CallStub[StringAdd](x, y)
465 // JSAdd(x, y:string) => CallStub[StringAdd](x, y) 455 // JSAdd(x, y:string) => CallStub[StringAdd](x, y)
466 Callable const callable = 456 Callable const callable =
467 CodeFactory::StringAdd(isolate(), flags, NOT_TENURED); 457 CodeFactory::StringAdd(isolate(), flags, NOT_TENURED);
468 CallDescriptor const* const desc = Linkage::GetStubCallDescriptor( 458 CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
469 isolate(), graph()->zone(), callable.descriptor(), 0, 459 isolate(), graph()->zone(), callable.descriptor(), 0,
470 CallDescriptor::kNeedsFrameState, node->op()->properties()); 460 CallDescriptor::kNeedsFrameState, node->op()->properties());
471 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op())); 461 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
472 node->InsertInput(graph()->zone(), 0, 462 node->InsertInput(graph()->zone(), 0,
473 jsgraph()->HeapConstant(callable.code())); 463 jsgraph()->HeapConstant(callable.code()));
474 NodeProperties::ChangeOp(node, common()->Call(desc)); 464 NodeProperties::ChangeOp(node, common()->Call(desc));
475 return Changed(node); 465 return Changed(node);
476 } 466 }
467 NumberOperationHint hint;
468 if (r.GetBinaryNumberOperationHint(&hint)) {
469 if (hint == NumberOperationHint::kNumberOrOddball &&
470 r.BothInputsAre(Type::PlainPrimitive()) &&
471 r.NeitherInputCanBe(Type::StringOrReceiver())) {
472 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y))
473 r.ConvertInputsToNumber();
474 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
475 }
476 // Lower to the optimistic number binop.
477 return r.ChangeToSpeculativeOperator(
478 simplified()->SpeculativeNumberAdd(hint), Type::Number());
479 }
480 if (r.BothInputsAre(Type::Number())) {
481 // JSAdd(x:number, y:number) => NumberAdd(x, y)
482 r.ConvertInputsToNumber();
483 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
484 }
485 if ((r.BothInputsAre(Type::PlainPrimitive()) ||
486 !(flags() & kDeoptimizationEnabled)) &&
487 r.NeitherInputCanBe(Type::StringOrReceiver())) {
488 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y))
489 r.ConvertInputsToNumber();
490 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
491 }
477 return NoChange(); 492 return NoChange();
478 } 493 }
479 494
480 495
481 Reduction JSTypedLowering::ReduceJSSubtract(Node* node) { 496 Reduction JSTypedLowering::ReduceJSSubtract(Node* node) {
482 JSBinopReduction r(this, node); 497 JSBinopReduction r(this, node);
483 BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); 498 NumberOperationHint hint;
484 if (feedback == BinaryOperationHints::kNumberOrOddball && 499 if (r.GetBinaryNumberOperationHint(&hint)) {
485 r.BothInputsAre(Type::PlainPrimitive())) { 500 if (hint == NumberOperationHint::kNumberOrOddball &&
486 // JSSubtract(x:plain-primitive, y:plain-primitive) 501 r.BothInputsAre(Type::PlainPrimitive())) {
487 // => NumberSubtract(ToNumber(x), ToNumber(y)) 502 // JSSubtract(x:plain-primitive, y:plain-primitive)
488 r.ConvertInputsToNumber(); 503 // => NumberSubtract(ToNumber(x), ToNumber(y))
489 return r.ChangeToPureOperator(simplified()->NumberSubtract(), 504 r.ConvertInputsToNumber();
490 Type::Number()); 505 return r.ChangeToPureOperator(simplified()->NumberSubtract(),
491 } 506 Type::Number());
492 if (feedback != BinaryOperationHints::kAny) { 507 }
493 // Lower to the optimistic number binop. 508 // Lower to the optimistic number binop.
494 return r.ChangeToSpeculativeOperator( 509 return r.ChangeToSpeculativeOperator(
495 simplified()->SpeculativeNumberSubtract(feedback), Type::Number()); 510 simplified()->SpeculativeNumberSubtract(hint));
496 } 511 }
497 512
498 // If deoptimization is enabled we rely on type feedback. 513 // If deoptimization is enabled we rely on type feedback.
499 if (r.BothInputsAre(Type::PlainPrimitive()) || 514 if (r.BothInputsAre(Type::PlainPrimitive()) ||
500 !(flags() & kDeoptimizationEnabled)) { 515 !(flags() & kDeoptimizationEnabled)) {
501 r.ConvertInputsToNumber(); 516 r.ConvertInputsToNumber();
502 return r.ChangeToPureOperator(simplified()->NumberSubtract(), 517 return r.ChangeToPureOperator(simplified()->NumberSubtract(),
503 Type::Number()); 518 Type::Number());
504 } 519 }
505 520
506 return NoChange(); 521 return NoChange();
507 } 522 }
508 523
509 Reduction JSTypedLowering::ReduceJSMultiply(Node* node) { 524 Reduction JSTypedLowering::ReduceJSMultiply(Node* node) {
510 JSBinopReduction r(this, node); 525 JSBinopReduction r(this, node);
511 BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); 526 NumberOperationHint hint;
512 if (feedback == BinaryOperationHints::kNumberOrOddball && 527 if (r.GetBinaryNumberOperationHint(&hint)) {
513 r.BothInputsAre(Type::PlainPrimitive())) { 528 if (hint == NumberOperationHint::kNumberOrOddball &&
514 // JSMultiply(x:plain-primitive, 529 r.BothInputsAre(Type::PlainPrimitive())) {
515 // y:plain-primitive) => NumberMultiply(ToNumber(x), ToNumber(y)) 530 // JSMultiply(x:plain-primitive, y:plain-primitive)
516 r.ConvertInputsToNumber(); 531 // => NumberMultiply(ToNumber(x), ToNumber(y))
517 return r.ChangeToPureOperator(simplified()->NumberMultiply(), 532 r.ConvertInputsToNumber();
518 Type::Number()); 533 return r.ChangeToPureOperator(simplified()->NumberMultiply(),
519 } 534 Type::Number());
520 if (feedback != BinaryOperationHints::kAny) { 535 }
521 return r.ChangeToSpeculativeOperator( 536 return r.ChangeToSpeculativeOperator(
522 simplified()->SpeculativeNumberMultiply(feedback), Type::Number()); 537 simplified()->SpeculativeNumberMultiply(hint));
523 } 538 }
524 539
525 // If deoptimization is enabled we rely on type feedback. 540 // If deoptimization is enabled we rely on type feedback.
526 if (r.BothInputsAre(Type::PlainPrimitive()) || 541 if (r.BothInputsAre(Type::PlainPrimitive()) ||
527 !(flags() & kDeoptimizationEnabled)) { 542 !(flags() & kDeoptimizationEnabled)) {
528 r.ConvertInputsToNumber(); 543 r.ConvertInputsToNumber();
529 return r.ChangeToPureOperator(simplified()->NumberMultiply(), 544 return r.ChangeToPureOperator(simplified()->NumberMultiply(),
530 Type::Number()); 545 Type::Number());
531 } 546 }
532 547
533 return NoChange(); 548 return NoChange();
534 } 549 }
535 550
536 Reduction JSTypedLowering::ReduceJSDivide(Node* node) { 551 Reduction JSTypedLowering::ReduceJSDivide(Node* node) {
537 JSBinopReduction r(this, node); 552 JSBinopReduction r(this, node);
538 BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); 553 NumberOperationHint hint;
539 if (feedback == BinaryOperationHints::kNumberOrOddball && 554 if (r.GetBinaryNumberOperationHint(&hint)) {
540 r.BothInputsAre(Type::PlainPrimitive())) { 555 if (hint == NumberOperationHint::kNumberOrOddball &&
541 // JSDivide(x:plain-primitive, 556 r.BothInputsAre(Type::PlainPrimitive())) {
542 // y:plain-primitive) => NumberDivide(ToNumber(x), ToNumber(y)) 557 // JSDivide(x:plain-primitive,
543 r.ConvertInputsToNumber(); 558 // y:plain-primitive) => NumberDivide(ToNumber(x), ToNumber(y))
544 return r.ChangeToPureOperator(simplified()->NumberDivide(), Type::Number()); 559 r.ConvertInputsToNumber();
545 } 560 return r.ChangeToPureOperator(simplified()->NumberDivide(),
546 if (feedback != BinaryOperationHints::kAny) { 561 Type::Number());
562 }
547 return r.ChangeToSpeculativeOperator( 563 return r.ChangeToSpeculativeOperator(
548 simplified()->SpeculativeNumberDivide(feedback), Type::Number()); 564 simplified()->SpeculativeNumberDivide(hint));
549 } 565 }
550 if (r.BothInputsAre(Type::PlainPrimitive())) { 566 if (r.BothInputsAre(Type::PlainPrimitive())) {
551 // JSDivide(x:plain-primitive, 567 // JSDivide(x:plain-primitive,
552 // y:plain-primitive) => NumberDivide(ToNumber(x), ToNumber(y)) 568 // y:plain-primitive) => NumberDivide(ToNumber(x), ToNumber(y))
553 r.ConvertInputsToNumber(); 569 r.ConvertInputsToNumber();
554 return r.ChangeToPureOperator(simplified()->NumberDivide(), Type::Number()); 570 return r.ChangeToPureOperator(simplified()->NumberDivide(), Type::Number());
555 } 571 }
556 return NoChange(); 572 return NoChange();
557 } 573 }
558 574
559 Reduction JSTypedLowering::ReduceJSModulus(Node* node) { 575 Reduction JSTypedLowering::ReduceJSModulus(Node* node) {
560 JSBinopReduction r(this, node); 576 JSBinopReduction r(this, node);
561 BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); 577 NumberOperationHint hint;
562 if (feedback == BinaryOperationHints::kNumberOrOddball && 578 if (r.GetBinaryNumberOperationHint(&hint)) {
563 r.BothInputsAre(Type::PlainPrimitive())) { 579 if (hint == NumberOperationHint::kNumberOrOddball &&
564 // JSModulus(x:plain-primitive, 580 r.BothInputsAre(Type::PlainPrimitive())) {
565 // y:plain-primitive) => NumberModulus(ToNumber(x), ToNumber(y)) 581 // JSModulus(x:plain-primitive,
566 r.ConvertInputsToNumber(); 582 // y:plain-primitive) => NumberModulus(ToNumber(x), ToNumber(y))
567 return r.ChangeToPureOperator(simplified()->NumberModulus(), 583 r.ConvertInputsToNumber();
568 Type::Number()); 584 return r.ChangeToPureOperator(simplified()->NumberModulus(),
569 } 585 Type::Number());
570 if (feedback != BinaryOperationHints::kAny) { 586 }
571 return r.ChangeToSpeculativeOperator( 587 return r.ChangeToSpeculativeOperator(
572 simplified()->SpeculativeNumberModulus(feedback), Type::Number()); 588 simplified()->SpeculativeNumberModulus(hint));
573 } 589 }
574 if (r.BothInputsAre(Type::PlainPrimitive())) { 590 if (r.BothInputsAre(Type::PlainPrimitive())) {
575 // JSModulus(x:plain-primitive, 591 // JSModulus(x:plain-primitive,
576 // y:plain-primitive) => NumberModulus(ToNumber(x), ToNumber(y)) 592 // y:plain-primitive) => NumberModulus(ToNumber(x), ToNumber(y))
577 r.ConvertInputsToNumber(); 593 r.ConvertInputsToNumber();
578 return r.ChangeToPureOperator(simplified()->NumberModulus(), 594 return r.ChangeToPureOperator(simplified()->NumberModulus(),
579 Type::Number()); 595 Type::Number());
580 } 596 }
581 return NoChange(); 597 return NoChange();
582 } 598 }
583 599
584 Reduction JSTypedLowering::ReduceInt32Binop(Node* node, const Operator* intOp) { 600 Reduction JSTypedLowering::ReduceInt32Binop(Node* node, const Operator* intOp) {
585 if (flags() & kDisableIntegerBinaryOpReduction) return NoChange(); 601 if (flags() & kDisableIntegerBinaryOpReduction) return NoChange();
586 602
587 JSBinopReduction r(this, node); 603 JSBinopReduction r(this, node);
588 r.ConvertInputsToNumber(); 604 r.ConvertInputsToNumber();
589 r.ConvertInputsToUI32(kSigned, kSigned); 605 r.ConvertInputsToUI32(kSigned, kSigned);
590 return r.ChangeToPureOperator(intOp, Type::Integral32()); 606 return r.ChangeToPureOperator(intOp, Type::Integral32());
591 } 607 }
592 608
593 Reduction JSTypedLowering::ReduceShiftLeft(Node* node) { 609 Reduction JSTypedLowering::ReduceShiftLeft(Node* node) {
594 if (flags() & kDisableIntegerBinaryOpReduction) return NoChange(); 610 if (flags() & kDisableIntegerBinaryOpReduction) return NoChange();
595 611
596 JSBinopReduction r(this, node); 612 JSBinopReduction r(this, node);
597 BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); 613 NumberOperationHint hint;
598 if (feedback == BinaryOperationHints::kSigned32 || 614 if (r.GetBinaryNumberOperationHint(&hint)) {
599 feedback == BinaryOperationHints::kSignedSmall) { 615 if (hint == NumberOperationHint::kSigned32) {
600 return r.ChangeToSpeculativeOperator( 616 return r.ChangeToSpeculativeOperator(
601 simplified()->SpeculativeNumberShiftLeft(feedback), Type::Signed32()); 617 simplified()->SpeculativeNumberShiftLeft(hint));
618 }
602 } 619 }
603 620
604 // If deoptimization is enabled we rely on type feedback. 621 // If deoptimization is enabled we rely on type feedback.
605 if (r.BothInputsAre(Type::PlainPrimitive()) || 622 if (r.BothInputsAre(Type::PlainPrimitive()) ||
606 !(flags() & kDeoptimizationEnabled)) { 623 !(flags() & kDeoptimizationEnabled)) {
607 r.ConvertInputsToNumber(); 624 r.ConvertInputsToNumber();
608 r.ConvertInputsToUI32(kSigned, kUnsigned); 625 r.ConvertInputsToUI32(kSigned, kUnsigned);
609 return r.ChangeToPureOperator(simplified()->NumberShiftLeft(), 626 return r.ChangeToPureOperator(simplified()->NumberShiftLeft(),
610 Type::Number()); 627 Type::Signed32());
611 } 628 }
612 return NoChange(); 629 return NoChange();
613 } 630 }
614 631
615 Reduction JSTypedLowering::ReduceUI32Shift(Node* node, 632 Reduction JSTypedLowering::ReduceUI32Shift(Node* node,
616 Signedness left_signedness, 633 Signedness left_signedness,
617 const Operator* shift_op) { 634 const Operator* shift_op) {
618 if (flags() & kDisableIntegerBinaryOpReduction) return NoChange(); 635 if (flags() & kDisableIntegerBinaryOpReduction) return NoChange();
619 636
620 JSBinopReduction r(this, node); 637 JSBinopReduction r(this, node);
621 r.ConvertInputsToNumber(); 638 r.ConvertInputsToNumber();
622 r.ConvertInputsToUI32(left_signedness, kUnsigned); 639 r.ConvertInputsToUI32(left_signedness, kUnsigned);
623 return r.ChangeToPureOperator(shift_op); 640 return r.ChangeToPureOperator(shift_op);
624 } 641 }
625 642
626
627 Reduction JSTypedLowering::ReduceJSComparison(Node* node) { 643 Reduction JSTypedLowering::ReduceJSComparison(Node* node) {
628 JSBinopReduction r(this, node); 644 JSBinopReduction r(this, node);
629 if (r.BothInputsAre(Type::String())) { 645 if (r.BothInputsAre(Type::String())) {
630 // If both inputs are definitely strings, perform a string comparison. 646 // If both inputs are definitely strings, perform a string comparison.
631 const Operator* stringOp; 647 const Operator* stringOp;
632 switch (node->opcode()) { 648 switch (node->opcode()) {
633 case IrOpcode::kJSLessThan: 649 case IrOpcode::kJSLessThan:
634 stringOp = simplified()->StringLessThan(); 650 stringOp = simplified()->StringLessThan();
635 break; 651 break;
636 case IrOpcode::kJSGreaterThan: 652 case IrOpcode::kJSGreaterThan:
637 stringOp = simplified()->StringLessThan(); 653 stringOp = simplified()->StringLessThan();
638 r.SwapInputs(); // a > b => b < a 654 r.SwapInputs(); // a > b => b < a
639 break; 655 break;
640 case IrOpcode::kJSLessThanOrEqual: 656 case IrOpcode::kJSLessThanOrEqual:
641 stringOp = simplified()->StringLessThanOrEqual(); 657 stringOp = simplified()->StringLessThanOrEqual();
642 break; 658 break;
643 case IrOpcode::kJSGreaterThanOrEqual: 659 case IrOpcode::kJSGreaterThanOrEqual:
644 stringOp = simplified()->StringLessThanOrEqual(); 660 stringOp = simplified()->StringLessThanOrEqual();
645 r.SwapInputs(); // a >= b => b <= a 661 r.SwapInputs(); // a >= b => b <= a
646 break; 662 break;
647 default: 663 default:
648 return NoChange(); 664 return NoChange();
649 } 665 }
650 r.ChangeToPureOperator(stringOp); 666 r.ChangeToPureOperator(stringOp);
651 return Changed(node); 667 return Changed(node);
652 } 668 }
653 669
654 CompareOperationHints::Hint hint = r.GetNumberCompareOperationFeedback(); 670 NumberOperationHint hint;
655 if (hint != CompareOperationHints::kAny || 671 const Operator* less_than;
656 r.OneInputCannotBe(Type::StringOrReceiver())) { 672 const Operator* less_than_or_equal;
657 const Operator* less_than; 673 if (r.GetCompareNumberOperationHint(&hint)) {
658 const Operator* less_than_or_equal; 674 less_than = simplified()->SpeculativeNumberLessThan(hint);
659 if (hint != CompareOperationHints::kAny) { 675 less_than_or_equal = simplified()->SpeculativeNumberLessThanOrEqual(hint);
660 less_than = simplified()->SpeculativeNumberLessThan(hint); 676 } else if (r.OneInputCannotBe(Type::StringOrReceiver()) &&
661 less_than_or_equal = simplified()->SpeculativeNumberLessThanOrEqual(hint); 677 (!(flags() & kDeoptimizationEnabled) ||
662 } else if (r.BothInputsAre(Type::PlainPrimitive()) || 678 r.BothInputsAre(Type::PlainPrimitive()))) {
663 !(flags() & kDeoptimizationEnabled)) { 679 r.ConvertInputsToNumber();
664 r.ConvertInputsToNumber(); 680 less_than = simplified()->NumberLessThan();
665 less_than = simplified()->NumberLessThan(); 681 less_than_or_equal = simplified()->NumberLessThanOrEqual();
666 less_than_or_equal = simplified()->NumberLessThanOrEqual(); 682 } else {
667 } else { 683 return NoChange();
684 }
685 const Operator* comparison;
686 switch (node->opcode()) {
687 case IrOpcode::kJSLessThan:
688 comparison = less_than;
689 break;
690 case IrOpcode::kJSGreaterThan:
691 comparison = less_than;
692 r.SwapInputs(); // a > b => b < a
693 break;
694 case IrOpcode::kJSLessThanOrEqual:
695 comparison = less_than_or_equal;
696 break;
697 case IrOpcode::kJSGreaterThanOrEqual:
698 comparison = less_than_or_equal;
699 r.SwapInputs(); // a >= b => b <= a
700 break;
701 default:
668 return NoChange(); 702 return NoChange();
669 }
670 const Operator* comparison;
671 switch (node->opcode()) {
672 case IrOpcode::kJSLessThan:
673 comparison = less_than;
674 break;
675 case IrOpcode::kJSGreaterThan:
676 comparison = less_than;
677 r.SwapInputs(); // a > b => b < a
678 break;
679 case IrOpcode::kJSLessThanOrEqual:
680 comparison = less_than_or_equal;
681 break;
682 case IrOpcode::kJSGreaterThanOrEqual:
683 comparison = less_than_or_equal;
684 r.SwapInputs(); // a >= b => b <= a
685 break;
686 default:
687 return NoChange();
688 }
689 if (comparison->EffectInputCount() > 0) {
690 return r.ChangeToSpeculativeOperator(comparison, Type::Boolean());
691 } else {
692 return r.ChangeToPureOperator(comparison);
693 }
694 } 703 }
695 // TODO(turbofan): relax/remove effects of this operator in other cases. 704 if (comparison->EffectInputCount() > 0) {
696 return NoChange(); // Keep a generic comparison. 705 return r.ChangeToSpeculativeOperator(comparison);
706 } else {
707 return r.ChangeToPureOperator(comparison);
708 }
697 } 709 }
698 710
699 Reduction JSTypedLowering::ReduceJSEqualTypeOf(Node* node, bool invert) { 711 Reduction JSTypedLowering::ReduceJSEqualTypeOf(Node* node, bool invert) {
700 HeapObjectBinopMatcher m(node); 712 HeapObjectBinopMatcher m(node);
701 if (m.left().IsJSTypeOf() && m.right().HasValue() && 713 if (m.left().IsJSTypeOf() && m.right().HasValue() &&
702 m.right().Value()->IsString()) { 714 m.right().Value()->IsString()) {
703 Node* replacement; 715 Node* replacement;
704 Node* input = m.left().InputAt(0); 716 Node* input = m.left().InputAt(0);
705 Handle<String> value = Handle<String>::cast(m.right().Value()); 717 Handle<String> value = Handle<String>::cast(m.right().Value());
706 if (String::Equals(value, factory()->boolean_string())) { 718 if (String::Equals(value, factory()->boolean_string())) {
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
766 if (invert) { 778 if (invert) {
767 // Insert an boolean not to invert the value. 779 // Insert an boolean not to invert the value.
768 Node* value = graph()->NewNode(simplified()->BooleanNot(), node); 780 Node* value = graph()->NewNode(simplified()->BooleanNot(), node);
769 node->ReplaceUses(value); 781 node->ReplaceUses(value);
770 // Note: ReplaceUses() smashes all uses, so smash it back here. 782 // Note: ReplaceUses() smashes all uses, so smash it back here.
771 value->ReplaceInput(0, node); 783 value->ReplaceInput(0, node);
772 return Replace(value); 784 return Replace(value);
773 } 785 }
774 return Changed(node); 786 return Changed(node);
775 } 787 }
788 // TODO(turbofan): Add support for comparison type feedback.
776 return NoChange(); 789 return NoChange();
777 } 790 }
778 791
779 792
780 Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) { 793 Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) {
781 JSBinopReduction r(this, node); 794 JSBinopReduction r(this, node);
782 if (r.left() == r.right()) { 795 if (r.left() == r.right()) {
783 // x === x is always true if x != NaN 796 // x === x is always true if x != NaN
784 if (!r.left_type()->Maybe(Type::NaN())) { 797 if (!r.left_type()->Maybe(Type::NaN())) {
785 Node* replacement = jsgraph()->BooleanConstant(!invert); 798 Node* replacement = jsgraph()->BooleanConstant(!invert);
(...skipping 1277 matching lines...) Expand 10 before | Expand all | Expand 10 after
2063 } 2076 }
2064 2077
2065 2078
2066 CompilationDependencies* JSTypedLowering::dependencies() const { 2079 CompilationDependencies* JSTypedLowering::dependencies() const {
2067 return dependencies_; 2080 return dependencies_;
2068 } 2081 }
2069 2082
2070 } // namespace compiler 2083 } // namespace compiler
2071 } // namespace internal 2084 } // namespace internal
2072 } // namespace v8 2085 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | src/compiler/redundancy-elimination.h » ('j') | src/compiler/redundancy-elimination.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698