Commit 2111d18d authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Add frame state before JavaScript comparisons.

Use these check points to optimize comparisons where we already know
that one side cannot be a String (or turn into a string via
ToPrimitive).

Also remove bunch of useless DoNotCrash tests for the scheduler that are
painful to maintain and add almost no value.

R=jarin@chromium.org

Review URL: https://codereview.chromium.org/1140583004

Cr-Commit-Position: refs/heads/master@{#28383}
parent b57428e9
......@@ -1311,10 +1311,12 @@ void AstGraphBuilder::VisitForInBody(ForInStatement* stmt) {
Node* obj = environment()->Peek(4);
// Check loop termination condition.
FrameStateBeforeAndAfter states(this, BailoutId::None());
Node* exit_cond = NewNode(javascript()->LessThan(LanguageMode::SLOPPY),
index, cache_length);
// TODO(jarin): provide real bailout id.
PrepareFrameState(exit_cond, BailoutId::None());
states.AddToNode(exit_cond, BailoutId::None(),
OutputFrameStateCombine::Ignore());
for_loop.BreakUnless(exit_cond);
Node* pair = NewNode(javascript()->CallRuntime(Runtime::kForInNext, 4), obj,
cache_array, cache_type, index);
......@@ -2531,10 +2533,11 @@ void AstGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
}
VisitForValue(expr->left());
VisitForValue(expr->right());
FrameStateBeforeAndAfter states(this, expr->right()->id());
Node* right = environment()->Pop();
Node* left = environment()->Pop();
Node* value = NewNode(op, left, right);
PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
ast_context()->ProduceValue(value);
}
......
......@@ -121,11 +121,6 @@ class JSBinopReduction final {
JSBinopReduction(JSTypedLowering* lowering, Node* node)
: lowering_(lowering), node_(node) {}
void ConvertPrimitiveInputsToNumber() {
node_->ReplaceInput(0, ConvertPrimitiveToNumber(left()));
node_->ReplaceInput(1, ConvertPrimitiveToNumber(right()));
}
void ConvertInputsToNumber(Node* frame_state) {
// To convert the inputs to numbers, we have to provide frame states
// for lazy bailouts in the ToNumber conversions.
......@@ -137,13 +132,13 @@ class JSBinopReduction final {
Node* left_input =
left_type()->Is(Type::PlainPrimitive())
? ConvertPrimitiveToNumber(left())
? ConvertPlainPrimitiveToNumber(left())
: ConvertToNumber(left(),
CreateFrameStateForLeftInput(frame_state));
Node* right_input =
right_type()->Is(Type::PlainPrimitive())
? ConvertPrimitiveToNumber(right())
? ConvertPlainPrimitiveToNumber(right())
: ConvertToNumber(right(), CreateFrameStateForRightInput(
frame_state, left_input));
......@@ -164,9 +159,10 @@ class JSBinopReduction final {
// Convert inputs for bitwise shift operation (ES5 spec 11.7).
void ConvertInputsForShift(Signedness left_signedness) {
node_->ReplaceInput(
0, ConvertToUI32(ConvertPrimitiveToNumber(left()), left_signedness));
Node* rnum = ConvertToUI32(ConvertPrimitiveToNumber(right()), kUnsigned);
node_->ReplaceInput(0, ConvertToUI32(ConvertPlainPrimitiveToNumber(left()),
left_signedness));
Node* rnum =
ConvertToUI32(ConvertPlainPrimitiveToNumber(right()), kUnsigned);
Type* rnum_type = NodeProperties::GetBounds(rnum).upper;
if (!rnum_type->Is(lowering_->zero_thirtyone_range_)) {
rnum = graph()->NewNode(machine()->Word32And(), rnum,
......@@ -333,13 +329,20 @@ class JSBinopReduction final {
frame_state->InputAt(3), frame_state->InputAt(4));
}
Node* ConvertPrimitiveToNumber(Node* node) {
return lowering_->ConvertPrimitiveToNumber(node);
Node* ConvertPlainPrimitiveToNumber(Node* node) {
DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::PlainPrimitive()));
// Avoid inserting too many eager ToNumber() operations.
Reduction const reduction = lowering_->ReduceJSToNumberInput(node);
if (reduction.Changed()) return reduction.replacement();
// TODO(jarin) Use PlainPrimitiveToNumber once we have it.
return graph()->NewNode(
javascript()->ToNumber(), node, jsgraph()->NoContextConstant(),
jsgraph()->EmptyFrameState(), graph()->start(), graph()->start());
}
Node* ConvertToNumber(Node* node, Node* frame_state) {
if (NodeProperties::GetBounds(node).upper->Is(Type::PlainPrimitive())) {
return ConvertPrimitiveToNumber(node);
return ConvertPlainPrimitiveToNumber(node);
} else {
Node* const n =
graph()->NewNode(javascript()->ToNumber(), node, context(),
......@@ -470,21 +473,7 @@ Reduction JSTypedLowering::ReduceJSComparison(Node* node) {
}
return r.ChangeToPureOperator(stringOp);
}
if (r.IsStrong() && !r.BothInputsAre(Type::Number())) {
return NoChange();
}
#if 0
// TODO(turbofan): General ToNumber disabled for now because:
// a) The inserted ToNumber operation screws up observability of valueOf.
// b) Deoptimization at ToNumber doesn't have corresponding bailout id.
Type* maybe_string = Type::Union(Type::String(), Type::Receiver(), zone());
if (r.OneInputCannotBe(maybe_string)) {
// If one input cannot be a string, then emit a number comparison.
...
}
#endif
if (r.BothInputsAre(Type::PlainPrimitive()) &&
r.OneInputCannotBe(Type::StringOrReceiver())) {
if (r.OneInputCannotBe(Type::StringOrReceiver())) {
const Operator* less_than;
const Operator* less_than_or_equal;
if (r.BothInputsAre(Type::Unsigned32())) {
......@@ -495,7 +484,11 @@ Reduction JSTypedLowering::ReduceJSComparison(Node* node) {
less_than_or_equal = machine()->Int32LessThanOrEqual();
} else {
// TODO(turbofan): mixed signed/unsigned int32 comparisons.
r.ConvertPrimitiveInputsToNumber();
if (r.IsStrong() && !r.BothInputsAre(Type::Number())) {
return NoChange();
}
Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
r.ConvertInputsToNumber(frame_state);
less_than = simplified()->NumberLessThan();
less_than_or_equal = simplified()->NumberLessThanOrEqual();
}
......@@ -1192,18 +1185,6 @@ Reduction JSTypedLowering::Reduce(Node* node) {
}
Node* JSTypedLowering::ConvertPrimitiveToNumber(Node* input) {
DCHECK(NodeProperties::GetBounds(input).upper->Is(Type::PlainPrimitive()));
// Avoid inserting too many eager ToNumber() operations.
Reduction const reduction = ReduceJSToNumberInput(input);
if (reduction.Changed()) return reduction.replacement();
// TODO(jarin) Use PlainPrimitiveToNumber once we have it.
return graph()->NewNode(
javascript()->ToNumber(), input, jsgraph()->NoContextConstant(),
jsgraph()->EmptyFrameState(), graph()->start(), graph()->start());
}
Node* JSTypedLowering::Word32Shl(Node* const lhs, int32_t const rhs) {
if (rhs == 0) return lhs;
return graph()->NewNode(machine()->Word32Shl(), lhs,
......
......@@ -64,8 +64,6 @@ class JSTypedLowering final : public Reducer {
Reduction ReduceUI32Shift(Node* node, Signedness left_signedness,
const Operator* shift_op);
Node* ConvertPrimitiveToNumber(Node* input);
Node* Word32Shl(Node* const lhs, int32_t const rhs);
Factory* factory() const;
......
......@@ -40,13 +40,9 @@ int OperatorProperties::GetFrameStateInputCount(const Operator* op) {
// Compare operations
case IrOpcode::kJSEqual:
case IrOpcode::kJSGreaterThan:
case IrOpcode::kJSGreaterThanOrEqual:
case IrOpcode::kJSNotEqual:
case IrOpcode::kJSHasProperty:
case IrOpcode::kJSInstanceOf:
case IrOpcode::kJSLessThan:
case IrOpcode::kJSLessThanOrEqual:
case IrOpcode::kJSNotEqual:
// Object operations
case IrOpcode::kJSCreateLiteralArray:
......@@ -93,6 +89,15 @@ int OperatorProperties::GetFrameStateInputCount(const Operator* op) {
case IrOpcode::kJSSubtract:
return 2;
// Compare operators that can deopt in the middle the operation (e.g.,
// as a result of lazy deopt in ToNumber conversion) need a second frame
// state so that we can resume before the operation.
case IrOpcode::kJSGreaterThan:
case IrOpcode::kJSGreaterThanOrEqual:
case IrOpcode::kJSLessThan:
case IrOpcode::kJSLessThanOrEqual:
return 2;
default:
return 0;
}
......
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax
var m = (function() {
"use asm";
function f(x) {
return x < 0;
}
function g(x) {
return 0 < x;
}
return { f: f, g: g };
})();
var f = m.f;
var g = m.g;
var counter = 0;
function deopt(f) {
return {
toString : function() {
%DeoptimizeFunction(f);
counter++;
return "2";
}
};
}
assertEquals(false, f(deopt(f)));
assertEquals(1, counter);
assertEquals(true, g(deopt(g)));
assertEquals(2, counter);
%OptimizeFunctionOnNextCall(f);
assertEquals(false, f(deopt(f)));
assertEquals(3, counter);
%OptimizeFunctionOnNextCall(g);
assertEquals(true, g(deopt(g)));
assertEquals(4, counter);
......@@ -186,10 +186,10 @@ const SharedOperatorWithLanguageMode kSharedOperatorsWithLanguageMode[] = {
control_input_count, value_output_count, effect_output_count, \
control_output_count \
}
SHARED(LessThan, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2),
SHARED(GreaterThan, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2),
SHARED(LessThanOrEqual, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2),
SHARED(GreaterThanOrEqual, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2),
SHARED(LessThan, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
SHARED(GreaterThan, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
SHARED(LessThanOrEqual, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
SHARED(GreaterThanOrEqual, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
SHARED(BitwiseOr, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
SHARED(BitwiseXor, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
SHARED(BitwiseAnd, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
......
......@@ -650,7 +650,7 @@ TEST_F(SchedulerTest, BuildScheduleOneParameter) {
TEST_F(SchedulerTest, BuildScheduleIfSplit) {
graph()->SetStart(graph()->NewNode(common()->Start(3)));
graph()->SetStart(graph()->NewNode(common()->Start(5)));
Node* p1 = graph()->NewNode(common()->Parameter(0), graph()->start());
Node* p2 = graph()->NewNode(common()->Parameter(1), graph()->start());
......@@ -658,7 +658,7 @@ TEST_F(SchedulerTest, BuildScheduleIfSplit) {
Node* p4 = graph()->NewNode(common()->Parameter(3), graph()->start());
Node* p5 = graph()->NewNode(common()->Parameter(4), graph()->start());
Node* cmp = graph()->NewNode(js()->LessThanOrEqual(LanguageMode::SLOPPY), p1,
p2, p3, graph()->start(), graph()->start());
p2, p3, p4, graph()->start(), graph()->start());
Node* branch = graph()->NewNode(common()->Branch(), cmp, graph()->start());
Node* true_branch = graph()->NewNode(common()->IfTrue(), branch);
Node* false_branch = graph()->NewNode(common()->IfFalse(), branch);
......@@ -674,1334 +674,6 @@ TEST_F(SchedulerTest, BuildScheduleIfSplit) {
}
TEST_F(SchedulerTest, BuildScheduleIfSplitWithEffects) {
const Operator* op;
Unique<HeapObject> unique_constant =
Unique<HeapObject>::CreateImmovable(factory()->undefined_value());
// Manually transcripted code for:
// function turbo_fan_test(a, b, c, y) {
// if (a < b) {
// return a + b - c * c - a + y;
// } else {
// return c * c - a;
// }
// }
Node* nil = graph()->NewNode(common()->Dead());
op = common()->End();
Node* n39 = graph()->NewNode(op, nil);
USE(n39);
op = common()->Merge(2);
Node* n37 = graph()->NewNode(op, nil, nil);
USE(n37);
op = common()->Return();
Node* n29 = graph()->NewNode(op, nil, nil, nil);
USE(n29);
op = common()->Return();
Node* n36 = graph()->NewNode(op, nil, nil, nil);
USE(n36);
op = js()->Add(LanguageMode::SLOPPY);
Node* n27 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil);
USE(n27);
op = common()->IfSuccess();
Node* n28 = graph()->NewNode(op, nil);
USE(n28);
op = js()->Subtract(LanguageMode::SLOPPY);
Node* n34 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil);
USE(n34);
op = common()->IfSuccess();
Node* n35 = graph()->NewNode(op, nil);
USE(n35);
op = js()->Subtract(LanguageMode::SLOPPY);
Node* n25 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil);
USE(n25);
op = common()->Parameter(4);
Node* n5 = graph()->NewNode(op, nil);
USE(n5);
op = common()->Parameter(5);
Node* n7 = graph()->NewNode(op, nil);
USE(n7);
op = common()->FrameState(JS_FRAME, BailoutId(-1),
OutputFrameStateCombine::Ignore());
Node* n13 = graph()->NewNode(op, nil, nil, nil, nil, nil);
USE(n13);
op = common()->IfSuccess();
Node* n26 = graph()->NewNode(op, nil);
USE(n26);
op = js()->Multiply(LanguageMode::SLOPPY);
Node* n32 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil);
USE(n32);
op = common()->Parameter(1);
Node* n2 = graph()->NewNode(op, nil);
USE(n2);
op = common()->IfSuccess();
Node* n33 = graph()->NewNode(op, nil);
USE(n33);
op = js()->Subtract(LanguageMode::SLOPPY);
Node* n23 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil);
USE(n23);
op = common()->IfSuccess();
Node* n24 = graph()->NewNode(op, nil);
USE(n24);
op = common()->Start(4);
Node* n0 = graph()->NewNode(op);
USE(n0);
op = common()->StateValues(0);
Node* n11 = graph()->NewNode(op);
USE(n11);
op = common()->NumberConstant(0);
Node* n12 = graph()->NewNode(op);
USE(n12);
op = common()->HeapConstant(unique_constant);
Node* n6 = graph()->NewNode(op);
USE(n6);
op = common()->Parameter(3);
Node* n4 = graph()->NewNode(op, nil);
USE(n4);
op = js()->LessThan(LanguageMode::SLOPPY);
Node* n15 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil);
USE(n15);
op = common()->IfFalse();
Node* n31 = graph()->NewNode(op, nil);
USE(n31);
op = js()->Add(LanguageMode::SLOPPY);
Node* n19 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil);
USE(n19);
op = js()->Multiply(LanguageMode::SLOPPY);
Node* n21 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil);
USE(n21);
op = common()->IfSuccess();
Node* n22 = graph()->NewNode(op, nil);
USE(n22);
op = common()->Parameter(2);
Node* n3 = graph()->NewNode(op, nil);
USE(n3);
op = js()->StackCheck();
Node* n9 = graph()->NewNode(op, nil, nil, nil, nil);
USE(n9);
op = common()->IfSuccess();
Node* n10 = graph()->NewNode(op, nil);
USE(n10);
op = common()->Branch();
Node* n17 = graph()->NewNode(op, nil, nil);
USE(n17);
op = common()->IfTrue();
Node* n18 = graph()->NewNode(op, nil);
USE(n18);
op = common()->IfSuccess();
Node* n20 = graph()->NewNode(op, nil);
USE(n20);
op = common()->IfSuccess();
Node* n16 = graph()->NewNode(op, nil);
USE(n16);
n39->ReplaceInput(0, n37);
n37->ReplaceInput(0, n29);
n37->ReplaceInput(1, n36);
n29->ReplaceInput(0, n27);
n29->ReplaceInput(1, n27);
n29->ReplaceInput(2, n28);
n36->ReplaceInput(0, n34);
n36->ReplaceInput(1, n34);
n36->ReplaceInput(2, n35);
n27->ReplaceInput(0, n25);
n27->ReplaceInput(1, n5);
n27->ReplaceInput(2, n7);
n27->ReplaceInput(3, n13);
n27->ReplaceInput(4, n13);
n27->ReplaceInput(5, n25);
n27->ReplaceInput(6, n26);
n28->ReplaceInput(0, n27);
n34->ReplaceInput(0, n32);
n34->ReplaceInput(1, n2);
n34->ReplaceInput(2, n7);
n34->ReplaceInput(3, n13);
n34->ReplaceInput(4, n13);
n34->ReplaceInput(5, n32);
n34->ReplaceInput(6, n33);
n35->ReplaceInput(0, n34);
n25->ReplaceInput(0, n23);
n25->ReplaceInput(1, n2);
n25->ReplaceInput(2, n7);
n25->ReplaceInput(3, n13);
n25->ReplaceInput(4, n13);
n25->ReplaceInput(5, n23);
n25->ReplaceInput(6, n24);
n5->ReplaceInput(0, n0);
n7->ReplaceInput(0, n0);
n13->ReplaceInput(0, n11);
n13->ReplaceInput(1, n11);
n13->ReplaceInput(2, n11);
n13->ReplaceInput(3, n12);
n13->ReplaceInput(4, n6);
n26->ReplaceInput(0, n25);
n32->ReplaceInput(0, n4);
n32->ReplaceInput(1, n4);
n32->ReplaceInput(2, n7);
n32->ReplaceInput(3, n13);
n32->ReplaceInput(4, n13);
n32->ReplaceInput(5, n15);
n32->ReplaceInput(6, n31);
n2->ReplaceInput(0, n0);
n33->ReplaceInput(0, n32);
n23->ReplaceInput(0, n19);
n23->ReplaceInput(1, n21);
n23->ReplaceInput(2, n7);
n23->ReplaceInput(3, n13);
n23->ReplaceInput(4, n13);
n23->ReplaceInput(5, n21);
n23->ReplaceInput(6, n22);
n24->ReplaceInput(0, n23);
n4->ReplaceInput(0, n0);
n15->ReplaceInput(0, n2);
n15->ReplaceInput(1, n3);
n15->ReplaceInput(2, n7);
n15->ReplaceInput(3, n13);
n15->ReplaceInput(4, n9);
n15->ReplaceInput(5, n10);
n31->ReplaceInput(0, n17);
n19->ReplaceInput(0, n2);
n19->ReplaceInput(1, n3);
n19->ReplaceInput(2, n7);
n19->ReplaceInput(3, n13);
n19->ReplaceInput(4, n13);
n19->ReplaceInput(5, n15);
n19->ReplaceInput(6, n18);
n21->ReplaceInput(0, n4);
n21->ReplaceInput(1, n4);
n21->ReplaceInput(2, n7);
n21->ReplaceInput(3, n13);
n21->ReplaceInput(4, n13);
n21->ReplaceInput(5, n19);
n21->ReplaceInput(6, n20);
n22->ReplaceInput(0, n21);
n3->ReplaceInput(0, n0);
n9->ReplaceInput(0, n7);
n9->ReplaceInput(1, n13);
n9->ReplaceInput(2, n0);
n9->ReplaceInput(3, n0);
n10->ReplaceInput(0, n9);
n17->ReplaceInput(0, n15);
n17->ReplaceInput(1, n16);
n18->ReplaceInput(0, n17);
n20->ReplaceInput(0, n19);
n16->ReplaceInput(0, n15);
graph()->SetStart(n0);
graph()->SetEnd(n39);
ComputeAndVerifySchedule(34);
}
TEST_F(SchedulerTest, BuildScheduleSimpleLoop) {
const Operator* op;
Unique<HeapObject> unique_constant =
Unique<HeapObject>::CreateImmovable(factory()->undefined_value());
// Manually transcripted code for:
// function turbo_fan_test(a, b) {
// while (a < b) {
// a++;
// }
// return a;
// }
Node* nil = graph()->NewNode(common()->Dead());
op = common()->End();
Node* n34 = graph()->NewNode(op, nil);
USE(n34);
op = common()->Return();
Node* n32 = graph()->NewNode(op, nil, nil, nil);
USE(n32);
op = common()->Phi(kMachAnyTagged, 2);
Node* n13 = graph()->NewNode(op, nil, nil, nil);
USE(n13);
op = js()->LessThan(LanguageMode::SLOPPY);
Node* n16 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil);
USE(n16);
op = common()->IfFalse();
Node* n22 = graph()->NewNode(op, nil);
USE(n22);
op = common()->Parameter(1);
Node* n2 = graph()->NewNode(op, nil);
USE(n2);
op = js()->Add(LanguageMode::SLOPPY);
Node* n29 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil);
USE(n29);
op = common()->Loop(2);
Node* n12 = graph()->NewNode(op, nil, nil);
USE(n12);
op = common()->Parameter(2);
Node* n3 = graph()->NewNode(op, nil);
USE(n3);
op = common()->Parameter(3);
Node* n5 = graph()->NewNode(op, nil);
USE(n5);
op = common()->FrameState(JS_FRAME, BailoutId(-1),
OutputFrameStateCombine::Ignore());
Node* n11 = graph()->NewNode(op, nil, nil, nil, nil, nil);
USE(n11);
op = common()->EffectPhi(2);
Node* n14 = graph()->NewNode(op, nil, nil, nil);
USE(n14);
op = common()->Branch();
Node* n19 = graph()->NewNode(op, nil, nil);
USE(n19);
op = common()->Start(2);
Node* n0 = graph()->NewNode(op);
USE(n0);
op = js()->ToNumber();
Node* n26 = graph()->NewNode(op, nil, nil, nil, nil, nil);
USE(n26);
op = common()->NumberConstant(1);
Node* n28 = graph()->NewNode(op);
USE(n28);
op = common()->IfSuccess();
Node* n27 = graph()->NewNode(op, nil);
USE(n27);
op = common()->IfSuccess();
Node* n8 = graph()->NewNode(op, nil);
USE(n8);
op = common()->IfSuccess();
Node* n30 = graph()->NewNode(op, nil);
USE(n30);
op = common()->StateValues(0);
Node* n9 = graph()->NewNode(op);
USE(n9);
op = common()->NumberConstant(0);
Node* n10 = graph()->NewNode(op);
USE(n10);
op = common()->HeapConstant(unique_constant);
Node* n4 = graph()->NewNode(op);
USE(n4);
op = js()->StackCheck();
Node* n7 = graph()->NewNode(op, nil, nil, nil, nil);
USE(n7);
op = js()->ToBoolean();
Node* n18 = graph()->NewNode(op, nil, nil);
USE(n18);
op = common()->IfSuccess();
Node* n17 = graph()->NewNode(op, nil);
USE(n17);
op = js()->StackCheck();
Node* n24 = graph()->NewNode(op, nil, nil, nil, nil);
USE(n24);
op = common()->IfSuccess();
Node* n25 = graph()->NewNode(op, nil);
USE(n25);
op = common()->IfTrue();
Node* n20 = graph()->NewNode(op, nil);
USE(n20);
n34->ReplaceInput(0, n32);
n32->ReplaceInput(0, n13);
n32->ReplaceInput(1, n16);
n32->ReplaceInput(2, n22);
n13->ReplaceInput(0, n2);
n13->ReplaceInput(1, n29);
n13->ReplaceInput(2, n12);
n16->ReplaceInput(0, n13);
n16->ReplaceInput(1, n3);
n16->ReplaceInput(2, n5);
n16->ReplaceInput(3, n11);
n16->ReplaceInput(4, n14);
n16->ReplaceInput(5, n12);
n22->ReplaceInput(0, n19);
n2->ReplaceInput(0, n0);
n29->ReplaceInput(0, n26);
n29->ReplaceInput(1, n28);
n29->ReplaceInput(2, n5);
n29->ReplaceInput(3, n11);
n29->ReplaceInput(4, n11);
n29->ReplaceInput(5, n26);
n29->ReplaceInput(6, n27);
n12->ReplaceInput(0, n8);
n12->ReplaceInput(1, n30);
n3->ReplaceInput(0, n0);
n5->ReplaceInput(0, n0);
n11->ReplaceInput(0, n9);
n11->ReplaceInput(1, n9);
n11->ReplaceInput(2, n9);
n11->ReplaceInput(3, n10);
n11->ReplaceInput(4, n4);
n14->ReplaceInput(0, n7);
n14->ReplaceInput(1, n29);
n14->ReplaceInput(2, n12);
n19->ReplaceInput(0, n18);
n19->ReplaceInput(1, n17);
n26->ReplaceInput(0, n13);
n26->ReplaceInput(1, n5);
n26->ReplaceInput(2, n11);
n26->ReplaceInput(3, n24);
n26->ReplaceInput(4, n25);
n27->ReplaceInput(0, n26);
n8->ReplaceInput(0, n7);
n30->ReplaceInput(0, n29);
n7->ReplaceInput(0, n5);
n7->ReplaceInput(1, n11);
n7->ReplaceInput(2, n0);
n7->ReplaceInput(3, n0);
n18->ReplaceInput(0, n16);
n18->ReplaceInput(1, n5);
n17->ReplaceInput(0, n16);
n24->ReplaceInput(0, n5);
n24->ReplaceInput(1, n11);
n24->ReplaceInput(2, n16);
n24->ReplaceInput(3, n20);
n25->ReplaceInput(0, n24);
n20->ReplaceInput(0, n19);
graph()->SetStart(n0);
graph()->SetEnd(n34);
ComputeAndVerifySchedule(30);
}
TEST_F(SchedulerTest, BuildScheduleComplexLoops) {
const Operator* op;
Unique<HeapObject> unique_constant =
Unique<HeapObject>::CreateImmovable(factory()->undefined_value());
// Manually transcripted code for:
// function turbo_fan_test(a, b, c) {
// while (a < b) {
// a++;
// while (c < b) {
// c++;
// }
// }
// while (a < b) {
// a += 2;
// }
// return a;
// }
Node* nil = graph()->NewNode(common()->Dead());
op = common()->End();
Node* n71 = graph()->NewNode(op, nil);
USE(n71);
op = common()->Return();
Node* n69 = graph()->NewNode(op, nil, nil, nil);
USE(n69);
op = common()->Phi(kMachAnyTagged, 2);
Node* n53 = graph()->NewNode(op, nil, nil, nil);
USE(n53);
op = js()->LessThan(LanguageMode::SLOPPY);
Node* n55 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil);
USE(n55);
op = common()->IfFalse();
Node* n61 = graph()->NewNode(op, nil);
USE(n61);
op = common()->Phi(kMachAnyTagged, 2);
Node* n14 = graph()->NewNode(op, nil, nil, nil);
USE(n14);
op = js()->Add(LanguageMode::SLOPPY);
Node* n66 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil);
USE(n66);
op = common()->Loop(2);
Node* n52 = graph()->NewNode(op, nil, nil);
USE(n52);
op = common()->Parameter(2);
Node* n3 = graph()->NewNode(op, nil);
USE(n3);
op = common()->Parameter(4);
Node* n6 = graph()->NewNode(op, nil);
USE(n6);
op = common()->FrameState(JS_FRAME, BailoutId(-1),
OutputFrameStateCombine::Ignore());
Node* n12 = graph()->NewNode(op, nil, nil, nil, nil, nil);
USE(n12);
op = common()->EffectPhi(2);
Node* n54 = graph()->NewNode(op, nil, nil, nil);
USE(n54);
op = common()->Branch();
Node* n58 = graph()->NewNode(op, nil, nil);
USE(n58);
op = common()->Parameter(1);
Node* n2 = graph()->NewNode(op, nil);
USE(n2);
op = js()->Add(LanguageMode::SLOPPY);
Node* n31 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil);
USE(n31);
op = common()->Loop(2);
Node* n13 = graph()->NewNode(op, nil, nil);
USE(n13);
op = common()->NumberConstant(2);
Node* n65 = graph()->NewNode(op);
USE(n65);
op = js()->StackCheck();
Node* n63 = graph()->NewNode(op, nil, nil, nil, nil);
USE(n63);
op = common()->IfSuccess();
Node* n64 = graph()->NewNode(op, nil);
USE(n64);
op = common()->IfFalse();
Node* n24 = graph()->NewNode(op, nil);
USE(n24);
op = common()->IfSuccess();
Node* n67 = graph()->NewNode(op, nil);
USE(n67);
op = common()->Start(3);
Node* n0 = graph()->NewNode(op);
USE(n0);
op = common()->StateValues(0);
Node* n10 = graph()->NewNode(op);
USE(n10);
op = common()->NumberConstant(0);
Node* n11 = graph()->NewNode(op);
USE(n11);
op = common()->HeapConstant(unique_constant);
Node* n5 = graph()->NewNode(op);
USE(n5);
op = js()->LessThan(LanguageMode::SLOPPY);
Node* n18 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil);
USE(n18);
op = js()->ToBoolean();
Node* n57 = graph()->NewNode(op, nil, nil);
USE(n57);
op = common()->IfSuccess();
Node* n56 = graph()->NewNode(op, nil);
USE(n56);
op = js()->ToNumber();
Node* n28 = graph()->NewNode(op, nil, nil, nil, nil, nil);
USE(n28);
op = common()->NumberConstant(1);
Node* n30 = graph()->NewNode(op);
USE(n30);
op = common()->IfSuccess();
Node* n29 = graph()->NewNode(op, nil);
USE(n29);
op = common()->IfSuccess();
Node* n9 = graph()->NewNode(op, nil);
USE(n9);
op = common()->IfFalse();
Node* n42 = graph()->NewNode(op, nil);
USE(n42);
op = common()->IfTrue();
Node* n59 = graph()->NewNode(op, nil);
USE(n59);
op = common()->Branch();
Node* n21 = graph()->NewNode(op, nil, nil);
USE(n21);
op = common()->EffectPhi(2);
Node* n16 = graph()->NewNode(op, nil, nil, nil);
USE(n16);
op = js()->StackCheck();
Node* n26 = graph()->NewNode(op, nil, nil, nil, nil);
USE(n26);
op = common()->IfSuccess();
Node* n27 = graph()->NewNode(op, nil);
USE(n27);
op = js()->StackCheck();
Node* n8 = graph()->NewNode(op, nil, nil, nil, nil);
USE(n8);
op = common()->Branch();
Node* n39 = graph()->NewNode(op, nil, nil);
USE(n39);
op = js()->ToBoolean();
Node* n20 = graph()->NewNode(op, nil, nil);
USE(n20);
op = common()->IfSuccess();
Node* n19 = graph()->NewNode(op, nil);
USE(n19);
op = js()->LessThan(LanguageMode::SLOPPY);
Node* n36 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil);
USE(n36);
op = common()->IfTrue();
Node* n22 = graph()->NewNode(op, nil);
USE(n22);
op = js()->ToBoolean();
Node* n38 = graph()->NewNode(op, nil, nil);
USE(n38);
op = common()->IfSuccess();
Node* n37 = graph()->NewNode(op, nil);
USE(n37);
op = common()->Phi(kMachAnyTagged, 2);
Node* n34 = graph()->NewNode(op, nil, nil, nil);
USE(n34);
op = common()->EffectPhi(2);
Node* n35 = graph()->NewNode(op, nil, nil, nil);
USE(n35);
op = common()->Loop(2);
Node* n33 = graph()->NewNode(op, nil, nil);
USE(n33);
op = common()->Phi(kMachAnyTagged, 2);
Node* n15 = graph()->NewNode(op, nil, nil, nil);
USE(n15);
op = js()->Add(LanguageMode::SLOPPY);
Node* n48 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil);
USE(n48);
op = common()->IfSuccess();
Node* n32 = graph()->NewNode(op, nil);
USE(n32);
op = common()->IfSuccess();
Node* n49 = graph()->NewNode(op, nil);
USE(n49);
op = common()->Parameter(3);
Node* n4 = graph()->NewNode(op, nil);
USE(n4);
op = js()->ToNumber();
Node* n46 = graph()->NewNode(op, nil, nil, nil, nil, nil);
USE(n46);
op = common()->IfSuccess();
Node* n47 = graph()->NewNode(op, nil);
USE(n47);
op = js()->StackCheck();
Node* n44 = graph()->NewNode(op, nil, nil, nil, nil);
USE(n44);
op = common()->IfSuccess();
Node* n45 = graph()->NewNode(op, nil);
USE(n45);
op = common()->IfTrue();
Node* n40 = graph()->NewNode(op, nil);
USE(n40);
n71->ReplaceInput(0, n69);
n69->ReplaceInput(0, n53);
n69->ReplaceInput(1, n55);
n69->ReplaceInput(2, n61);
n53->ReplaceInput(0, n14);
n53->ReplaceInput(1, n66);
n53->ReplaceInput(2, n52);
n55->ReplaceInput(0, n53);
n55->ReplaceInput(1, n3);
n55->ReplaceInput(2, n6);
n55->ReplaceInput(3, n12);
n55->ReplaceInput(4, n54);
n55->ReplaceInput(5, n52);
n61->ReplaceInput(0, n58);
n14->ReplaceInput(0, n2);
n14->ReplaceInput(1, n31);
n14->ReplaceInput(2, n13);
n66->ReplaceInput(0, n53);
n66->ReplaceInput(1, n65);
n66->ReplaceInput(2, n6);
n66->ReplaceInput(3, n12);
n66->ReplaceInput(4, n12);
n66->ReplaceInput(5, n63);
n66->ReplaceInput(6, n64);
n52->ReplaceInput(0, n24);
n52->ReplaceInput(1, n67);
n3->ReplaceInput(0, n0);
n6->ReplaceInput(0, n0);
n12->ReplaceInput(0, n10);
n12->ReplaceInput(1, n10);
n12->ReplaceInput(2, n10);
n12->ReplaceInput(3, n11);
n12->ReplaceInput(4, n5);
n54->ReplaceInput(0, n18);
n54->ReplaceInput(1, n66);
n54->ReplaceInput(2, n52);
n58->ReplaceInput(0, n57);
n58->ReplaceInput(1, n56);
n2->ReplaceInput(0, n0);
n31->ReplaceInput(0, n28);
n31->ReplaceInput(1, n30);
n31->ReplaceInput(2, n6);
n31->ReplaceInput(3, n12);
n31->ReplaceInput(4, n12);
n31->ReplaceInput(5, n28);
n31->ReplaceInput(6, n29);
n13->ReplaceInput(0, n9);
n13->ReplaceInput(1, n42);
n63->ReplaceInput(0, n6);
n63->ReplaceInput(1, n12);
n63->ReplaceInput(2, n55);
n63->ReplaceInput(3, n59);
n64->ReplaceInput(0, n63);
n24->ReplaceInput(0, n21);
n67->ReplaceInput(0, n66);
n18->ReplaceInput(0, n14);
n18->ReplaceInput(1, n3);
n18->ReplaceInput(2, n6);
n18->ReplaceInput(3, n12);
n18->ReplaceInput(4, n16);
n18->ReplaceInput(5, n13);
n57->ReplaceInput(0, n55);
n57->ReplaceInput(1, n6);
n56->ReplaceInput(0, n55);
n28->ReplaceInput(0, n14);
n28->ReplaceInput(1, n6);
n28->ReplaceInput(2, n12);
n28->ReplaceInput(3, n26);
n28->ReplaceInput(4, n27);
n29->ReplaceInput(0, n28);
n9->ReplaceInput(0, n8);
n42->ReplaceInput(0, n39);
n59->ReplaceInput(0, n58);
n21->ReplaceInput(0, n20);
n21->ReplaceInput(1, n19);
n16->ReplaceInput(0, n8);
n16->ReplaceInput(1, n36);
n16->ReplaceInput(2, n13);
n26->ReplaceInput(0, n6);
n26->ReplaceInput(1, n12);
n26->ReplaceInput(2, n18);
n26->ReplaceInput(3, n22);
n27->ReplaceInput(0, n26);
n8->ReplaceInput(0, n6);
n8->ReplaceInput(1, n12);
n8->ReplaceInput(2, n0);
n8->ReplaceInput(3, n0);
n39->ReplaceInput(0, n38);
n39->ReplaceInput(1, n37);
n20->ReplaceInput(0, n18);
n20->ReplaceInput(1, n6);
n19->ReplaceInput(0, n18);
n36->ReplaceInput(0, n34);
n36->ReplaceInput(1, n3);
n36->ReplaceInput(2, n6);
n36->ReplaceInput(3, n12);
n36->ReplaceInput(4, n35);
n36->ReplaceInput(5, n33);
n22->ReplaceInput(0, n21);
n38->ReplaceInput(0, n36);
n38->ReplaceInput(1, n6);
n37->ReplaceInput(0, n36);
n34->ReplaceInput(0, n15);
n34->ReplaceInput(1, n48);
n34->ReplaceInput(2, n33);
n35->ReplaceInput(0, n31);
n35->ReplaceInput(1, n48);
n35->ReplaceInput(2, n33);
n33->ReplaceInput(0, n32);
n33->ReplaceInput(1, n49);
n15->ReplaceInput(0, n4);
n15->ReplaceInput(1, n34);
n15->ReplaceInput(2, n13);
n48->ReplaceInput(0, n46);
n48->ReplaceInput(1, n30);
n48->ReplaceInput(2, n6);
n48->ReplaceInput(3, n12);
n48->ReplaceInput(4, n12);
n48->ReplaceInput(5, n46);
n48->ReplaceInput(6, n47);
n32->ReplaceInput(0, n31);
n49->ReplaceInput(0, n48);
n4->ReplaceInput(0, n0);
n46->ReplaceInput(0, n34);
n46->ReplaceInput(1, n6);
n46->ReplaceInput(2, n12);
n46->ReplaceInput(3, n44);
n46->ReplaceInput(4, n45);
n47->ReplaceInput(0, n46);
n44->ReplaceInput(0, n6);
n44->ReplaceInput(1, n12);
n44->ReplaceInput(2, n36);
n44->ReplaceInput(3, n40);
n45->ReplaceInput(0, n44);
n40->ReplaceInput(0, n39);
graph()->SetStart(n0);
graph()->SetEnd(n71);
ComputeAndVerifySchedule(65);
}
TEST_F(SchedulerTest, BuildScheduleBreakAndContinue) {
const Operator* op;
Unique<HeapObject> unique_constant =
Unique<HeapObject>::CreateImmovable(factory()->undefined_value());
// Manually transcripted code for:
// function turbo_fan_test(a, b, c) {
// var d = 0;
// while (a < b) {
// a++;
// while (c < b) {
// c++;
// if (d == 0) break;
// a++;
// }
// if (a == 1) continue;
// d++;
// }
// return a + d;
// }
Node* nil = graph()->NewNode(common()->Dead());
op = common()->End();
Node* n86 = graph()->NewNode(op, nil);
USE(n86);
op = common()->Return();
Node* n84 = graph()->NewNode(op, nil, nil, nil);
USE(n84);
op = js()->Add(LanguageMode::SLOPPY);
Node* n82 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil);
USE(n82);
op = common()->IfSuccess();
Node* n83 = graph()->NewNode(op, nil);
USE(n83);
op = common()->Phi(kMachAnyTagged, 2);
Node* n15 = graph()->NewNode(op, nil, nil, nil);
USE(n15);
op = common()->Phi(kMachAnyTagged, 2);
Node* n17 = graph()->NewNode(op, nil, nil, nil);
USE(n17);
op = common()->Parameter(4);
Node* n6 = graph()->NewNode(op, nil);
USE(n6);
op = common()->FrameState(JS_FRAME, BailoutId(-1),
OutputFrameStateCombine::Ignore());
Node* n12 = graph()->NewNode(op, nil, nil, nil, nil, nil);
USE(n12);
op = js()->LessThan(LanguageMode::SLOPPY);
Node* n19 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil);
USE(n19);
op = common()->IfFalse();
Node* n25 = graph()->NewNode(op, nil);
USE(n25);
op = common()->Parameter(1);
Node* n2 = graph()->NewNode(op, nil);
USE(n2);
op = common()->Phi(kMachAnyTagged, 2);
Node* n35 = graph()->NewNode(op, nil, nil, nil);
USE(n35);
op = common()->Loop(2);
Node* n14 = graph()->NewNode(op, nil, nil);
USE(n14);
op = common()->NumberConstant(0);
Node* n11 = graph()->NewNode(op);
USE(n11);
op = common()->Phi(kMachAnyTagged, 2);
Node* n81 = graph()->NewNode(op, nil, nil, nil);
USE(n81);
op = common()->Start(3);
Node* n0 = graph()->NewNode(op);
USE(n0);
op = common()->StateValues(0);
Node* n10 = graph()->NewNode(op);
USE(n10);
op = common()->HeapConstant(unique_constant);
Node* n5 = graph()->NewNode(op);
USE(n5);
op = common()->Parameter(2);
Node* n3 = graph()->NewNode(op, nil);
USE(n3);
op = common()->EffectPhi(2);
Node* n18 = graph()->NewNode(op, nil, nil, nil);
USE(n18);
op = common()->Branch();
Node* n22 = graph()->NewNode(op, nil, nil);
USE(n22);
op = js()->Add(LanguageMode::SLOPPY);
Node* n32 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil);
USE(n32);
op = js()->Add(LanguageMode::SLOPPY);
Node* n64 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil);
USE(n64);
op = common()->Loop(2);
Node* n34 = graph()->NewNode(op, nil, nil);
USE(n34);
op = common()->IfSuccess();
Node* n9 = graph()->NewNode(op, nil);
USE(n9);
op = common()->Merge(2);
Node* n72 = graph()->NewNode(op, nil, nil);
USE(n72);
op = js()->Add(LanguageMode::SLOPPY);
Node* n78 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil);
USE(n78);
op = js()->StackCheck();
Node* n8 = graph()->NewNode(op, nil, nil, nil, nil);
USE(n8);
op = common()->EffectPhi(2);
Node* n80 = graph()->NewNode(op, nil, nil, nil);
USE(n80);
op = js()->ToBoolean();
Node* n21 = graph()->NewNode(op, nil, nil);
USE(n21);
op = common()->IfSuccess();
Node* n20 = graph()->NewNode(op, nil);
USE(n20);
op = js()->ToNumber();
Node* n29 = graph()->NewNode(op, nil, nil, nil, nil, nil);
USE(n29);
op = common()->NumberConstant(1);
Node* n31 = graph()->NewNode(op);
USE(n31);
op = common()->IfSuccess();
Node* n30 = graph()->NewNode(op, nil);
USE(n30);
op = js()->ToNumber();
Node* n62 = graph()->NewNode(op, nil, nil, nil, nil, nil);
USE(n62);
op = common()->IfSuccess();
Node* n63 = graph()->NewNode(op, nil);
USE(n63);
op = common()->IfSuccess();
Node* n33 = graph()->NewNode(op, nil);
USE(n33);
op = common()->IfSuccess();
Node* n65 = graph()->NewNode(op, nil);
USE(n65);
op = common()->IfTrue();
Node* n71 = graph()->NewNode(op, nil);
USE(n71);
op = common()->IfSuccess();
Node* n79 = graph()->NewNode(op, nil);
USE(n79);
op = js()->ToNumber();
Node* n76 = graph()->NewNode(op, nil, nil, nil, nil, nil);
USE(n76);
op = common()->IfSuccess();
Node* n77 = graph()->NewNode(op, nil);
USE(n77);
op = js()->Equal();
Node* n67 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil);
USE(n67);
op = js()->StackCheck();
Node* n27 = graph()->NewNode(op, nil, nil, nil, nil);
USE(n27);
op = common()->IfSuccess();
Node* n28 = graph()->NewNode(op, nil);
USE(n28);
op = js()->Equal();
Node* n52 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil);
USE(n52);
op = common()->IfFalse();
Node* n60 = graph()->NewNode(op, nil);
USE(n60);
op = common()->Branch();
Node* n70 = graph()->NewNode(op, nil, nil);
USE(n70);
op = common()->IfFalse();
Node* n74 = graph()->NewNode(op, nil);
USE(n74);
op = common()->EffectPhi(2);
Node* n57 = graph()->NewNode(op, nil, nil, nil);
USE(n57);
op = common()->Merge(2);
Node* n45 = graph()->NewNode(op, nil, nil);
USE(n45);
op = common()->IfTrue();
Node* n23 = graph()->NewNode(op, nil);
USE(n23);
op = js()->Add(LanguageMode::SLOPPY);
Node* n50 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil);
USE(n50);
op = common()->IfSuccess();
Node* n51 = graph()->NewNode(op, nil);
USE(n51);
op = common()->Branch();
Node* n55 = graph()->NewNode(op, nil, nil);
USE(n55);
op = js()->ToBoolean();
Node* n69 = graph()->NewNode(op, nil, nil);
USE(n69);
op = common()->IfSuccess();
Node* n68 = graph()->NewNode(op, nil);
USE(n68);
op = js()->LessThan(LanguageMode::SLOPPY);
Node* n38 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil);
USE(n38);
op = common()->IfFalse();
Node* n44 = graph()->NewNode(op, nil);
USE(n44);
op = common()->IfTrue();
Node* n56 = graph()->NewNode(op, nil);
USE(n56);
op = js()->ToNumber();
Node* n48 = graph()->NewNode(op, nil, nil, nil, nil, nil);
USE(n48);
op = common()->IfSuccess();
Node* n49 = graph()->NewNode(op, nil);
USE(n49);
op = js()->ToBoolean();
Node* n54 = graph()->NewNode(op, nil, nil);
USE(n54);
op = common()->IfSuccess();
Node* n53 = graph()->NewNode(op, nil);
USE(n53);
op = common()->Phi(kMachAnyTagged, 2);
Node* n36 = graph()->NewNode(op, nil, nil, nil);
USE(n36);
op = common()->EffectPhi(2);
Node* n37 = graph()->NewNode(op, nil, nil, nil);
USE(n37);
op = common()->Branch();
Node* n41 = graph()->NewNode(op, nil, nil);
USE(n41);
op = js()->StackCheck();
Node* n46 = graph()->NewNode(op, nil, nil, nil, nil);
USE(n46);
op = common()->IfSuccess();
Node* n47 = graph()->NewNode(op, nil);
USE(n47);
op = common()->Phi(kMachAnyTagged, 2);
Node* n16 = graph()->NewNode(op, nil, nil, nil);
USE(n16);
op = js()->ToBoolean();
Node* n40 = graph()->NewNode(op, nil, nil);
USE(n40);
op = common()->IfSuccess();
Node* n39 = graph()->NewNode(op, nil);
USE(n39);
op = common()->IfTrue();
Node* n42 = graph()->NewNode(op, nil);
USE(n42);
op = common()->Parameter(3);
Node* n4 = graph()->NewNode(op, nil);
USE(n4);
op = common()->Phi(kMachAnyTagged, 2);
Node* n58 = graph()->NewNode(op, nil, nil, nil);
USE(n58);
n86->ReplaceInput(0, n84);
n84->ReplaceInput(0, n82);
n84->ReplaceInput(1, n82);
n84->ReplaceInput(2, n83);
n82->ReplaceInput(0, n15);
n82->ReplaceInput(1, n17);
n82->ReplaceInput(2, n6);
n82->ReplaceInput(3, n12);
n82->ReplaceInput(4, n12);
n82->ReplaceInput(5, n19);
n82->ReplaceInput(6, n25);
n83->ReplaceInput(0, n82);
n15->ReplaceInput(0, n2);
n15->ReplaceInput(1, n35);
n15->ReplaceInput(2, n14);
n17->ReplaceInput(0, n11);
n17->ReplaceInput(1, n81);
n17->ReplaceInput(2, n14);
n6->ReplaceInput(0, n0);
n12->ReplaceInput(0, n10);
n12->ReplaceInput(1, n10);
n12->ReplaceInput(2, n10);
n12->ReplaceInput(3, n11);
n12->ReplaceInput(4, n5);
n19->ReplaceInput(0, n15);
n19->ReplaceInput(1, n3);
n19->ReplaceInput(2, n6);
n19->ReplaceInput(3, n12);
n19->ReplaceInput(4, n18);
n19->ReplaceInput(5, n14);
n25->ReplaceInput(0, n22);
n2->ReplaceInput(0, n0);
n35->ReplaceInput(0, n32);
n35->ReplaceInput(1, n64);
n35->ReplaceInput(2, n34);
n14->ReplaceInput(0, n9);
n14->ReplaceInput(1, n72);
n81->ReplaceInput(0, n17);
n81->ReplaceInput(1, n78);
n81->ReplaceInput(2, n72);
n3->ReplaceInput(0, n0);
n18->ReplaceInput(0, n8);
n18->ReplaceInput(1, n80);
n18->ReplaceInput(2, n14);
n22->ReplaceInput(0, n21);
n22->ReplaceInput(1, n20);
n32->ReplaceInput(0, n29);
n32->ReplaceInput(1, n31);
n32->ReplaceInput(2, n6);
n32->ReplaceInput(3, n12);
n32->ReplaceInput(4, n12);
n32->ReplaceInput(5, n29);
n32->ReplaceInput(6, n30);
n64->ReplaceInput(0, n62);
n64->ReplaceInput(1, n31);
n64->ReplaceInput(2, n6);
n64->ReplaceInput(3, n12);
n64->ReplaceInput(4, n12);
n64->ReplaceInput(5, n62);
n64->ReplaceInput(6, n63);
n34->ReplaceInput(0, n33);
n34->ReplaceInput(1, n65);
n9->ReplaceInput(0, n8);
n72->ReplaceInput(0, n71);
n72->ReplaceInput(1, n79);
n78->ReplaceInput(0, n76);
n78->ReplaceInput(1, n31);
n78->ReplaceInput(2, n6);
n78->ReplaceInput(3, n12);
n78->ReplaceInput(4, n12);
n78->ReplaceInput(5, n76);
n78->ReplaceInput(6, n77);
n8->ReplaceInput(0, n6);
n8->ReplaceInput(1, n12);
n8->ReplaceInput(2, n0);
n8->ReplaceInput(3, n0);
n80->ReplaceInput(0, n67);
n80->ReplaceInput(1, n78);
n80->ReplaceInput(2, n72);
n21->ReplaceInput(0, n19);
n21->ReplaceInput(1, n6);
n20->ReplaceInput(0, n19);
n29->ReplaceInput(0, n15);
n29->ReplaceInput(1, n6);
n29->ReplaceInput(2, n12);
n29->ReplaceInput(3, n27);
n29->ReplaceInput(4, n28);
n30->ReplaceInput(0, n29);
n62->ReplaceInput(0, n35);
n62->ReplaceInput(1, n6);
n62->ReplaceInput(2, n12);
n62->ReplaceInput(3, n52);
n62->ReplaceInput(4, n60);
n63->ReplaceInput(0, n62);
n33->ReplaceInput(0, n32);
n65->ReplaceInput(0, n64);
n71->ReplaceInput(0, n70);
n79->ReplaceInput(0, n78);
n76->ReplaceInput(0, n17);
n76->ReplaceInput(1, n6);
n76->ReplaceInput(2, n12);
n76->ReplaceInput(3, n67);
n76->ReplaceInput(4, n74);
n77->ReplaceInput(0, n76);
n67->ReplaceInput(0, n35);
n67->ReplaceInput(1, n31);
n67->ReplaceInput(2, n6);
n67->ReplaceInput(3, n12);
n67->ReplaceInput(4, n57);
n67->ReplaceInput(5, n45);
n27->ReplaceInput(0, n6);
n27->ReplaceInput(1, n12);
n27->ReplaceInput(2, n19);
n27->ReplaceInput(3, n23);
n28->ReplaceInput(0, n27);
n52->ReplaceInput(0, n17);
n52->ReplaceInput(1, n11);
n52->ReplaceInput(2, n6);
n52->ReplaceInput(3, n12);
n52->ReplaceInput(4, n50);
n52->ReplaceInput(5, n51);
n60->ReplaceInput(0, n55);
n70->ReplaceInput(0, n69);
n70->ReplaceInput(1, n68);
n74->ReplaceInput(0, n70);
n57->ReplaceInput(0, n38);
n57->ReplaceInput(1, n52);
n57->ReplaceInput(2, n45);
n45->ReplaceInput(0, n44);
n45->ReplaceInput(1, n56);
n23->ReplaceInput(0, n22);
n50->ReplaceInput(0, n48);
n50->ReplaceInput(1, n31);
n50->ReplaceInput(2, n6);
n50->ReplaceInput(3, n12);
n50->ReplaceInput(4, n12);
n50->ReplaceInput(5, n48);
n50->ReplaceInput(6, n49);
n51->ReplaceInput(0, n50);
n55->ReplaceInput(0, n54);
n55->ReplaceInput(1, n53);
n69->ReplaceInput(0, n67);
n69->ReplaceInput(1, n6);
n68->ReplaceInput(0, n67);
n38->ReplaceInput(0, n36);
n38->ReplaceInput(1, n3);
n38->ReplaceInput(2, n6);
n38->ReplaceInput(3, n12);
n38->ReplaceInput(4, n37);
n38->ReplaceInput(5, n34);
n44->ReplaceInput(0, n41);
n56->ReplaceInput(0, n55);
n48->ReplaceInput(0, n36);
n48->ReplaceInput(1, n6);
n48->ReplaceInput(2, n12);
n48->ReplaceInput(3, n46);
n48->ReplaceInput(4, n47);
n49->ReplaceInput(0, n48);
n54->ReplaceInput(0, n52);
n54->ReplaceInput(1, n6);
n53->ReplaceInput(0, n52);
n36->ReplaceInput(0, n16);
n36->ReplaceInput(1, n50);
n36->ReplaceInput(2, n34);
n37->ReplaceInput(0, n32);
n37->ReplaceInput(1, n64);
n37->ReplaceInput(2, n34);
n41->ReplaceInput(0, n40);
n41->ReplaceInput(1, n39);
n46->ReplaceInput(0, n6);
n46->ReplaceInput(1, n12);
n46->ReplaceInput(2, n38);
n46->ReplaceInput(3, n42);
n47->ReplaceInput(0, n46);
n16->ReplaceInput(0, n4);
n16->ReplaceInput(1, n58);
n16->ReplaceInput(2, n14);
n40->ReplaceInput(0, n38);
n40->ReplaceInput(1, n6);
n39->ReplaceInput(0, n38);
n42->ReplaceInput(0, n41);
n4->ReplaceInput(0, n0);
n58->ReplaceInput(0, n36);
n58->ReplaceInput(1, n50);
n58->ReplaceInput(2, n45);
graph()->SetStart(n0);
graph()->SetEnd(n86);
ComputeAndVerifySchedule(83);
}
TEST_F(SchedulerTest, BuildScheduleSimpleLoopWithCodeMotion) {
const Operator* op;
Unique<HeapObject> unique_constant =
Unique<HeapObject>::CreateImmovable(factory()->undefined_value());
// Manually transcripted code for:
// function turbo_fan_test(a, b, c) {
// while (a < b) {
// a += b + c;
// }
// return a;
// }
Node* nil = graph()->NewNode(common()->Dead());
op = common()->End();
Node* n34 = graph()->NewNode(op, nil);
USE(n34);
op = common()->Return();
Node* n32 = graph()->NewNode(op, nil, nil, nil);
USE(n32);
op = common()->Phi(kMachAnyTagged, 2);
Node* n14 = graph()->NewNode(op, nil, nil, nil);
USE(n14);
op = js()->LessThan(LanguageMode::SLOPPY);
Node* n17 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil);
USE(n17);
op = common()->IfFalse();
Node* n23 = graph()->NewNode(op, nil);
USE(n23);
op = common()->Parameter(1);
Node* n2 = graph()->NewNode(op, nil);
USE(n2);
op = js()->Add(LanguageMode::SLOPPY);
Node* n29 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil);
USE(n29);
op = common()->Loop(2);
Node* n13 = graph()->NewNode(op, nil, nil);
USE(n13);
op = common()->Parameter(2);
Node* n3 = graph()->NewNode(op, nil);
USE(n3);
op = common()->Parameter(4);
Node* n6 = graph()->NewNode(op, nil);
USE(n6);
op = common()->FrameState(JS_FRAME, BailoutId(-1),
OutputFrameStateCombine::Ignore());
Node* n12 = graph()->NewNode(op, nil, nil, nil, nil, nil);
USE(n12);
op = common()->EffectPhi(2);
Node* n15 = graph()->NewNode(op, nil, nil, nil);
USE(n15);
op = common()->Branch();
Node* n20 = graph()->NewNode(op, nil, nil);
USE(n20);
op = common()->Start(3);
Node* n0 = graph()->NewNode(op);
USE(n0);
op = js()->Add(LanguageMode::SLOPPY);
Node* n27 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil);
USE(n27);
op = common()->IfSuccess();
Node* n28 = graph()->NewNode(op, nil);
USE(n28);
op = common()->IfSuccess();
Node* n9 = graph()->NewNode(op, nil);
USE(n9);
op = common()->IfSuccess();
Node* n30 = graph()->NewNode(op, nil);
USE(n30);
op = common()->StateValues(0);
Node* n10 = graph()->NewNode(op);
USE(n10);
op = common()->NumberConstant(0);
Node* n11 = graph()->NewNode(op);
USE(n11);
op = common()->HeapConstant(unique_constant);
Node* n5 = graph()->NewNode(op);
USE(n5);
op = js()->StackCheck();
Node* n8 = graph()->NewNode(op, nil, nil, nil, nil);
USE(n8);
op = js()->ToBoolean();
Node* n19 = graph()->NewNode(op, nil, nil);
USE(n19);
op = common()->IfSuccess();
Node* n18 = graph()->NewNode(op, nil);
USE(n18);
op = common()->Parameter(3);
Node* n4 = graph()->NewNode(op, nil);
USE(n4);
op = js()->StackCheck();
Node* n25 = graph()->NewNode(op, nil, nil, nil, nil);
USE(n25);
op = common()->IfSuccess();
Node* n26 = graph()->NewNode(op, nil);
USE(n26);
op = common()->IfTrue();
Node* n21 = graph()->NewNode(op, nil);
USE(n21);
n34->ReplaceInput(0, n32);
n32->ReplaceInput(0, n14);
n32->ReplaceInput(1, n17);
n32->ReplaceInput(2, n23);
n14->ReplaceInput(0, n2);
n14->ReplaceInput(1, n29);
n14->ReplaceInput(2, n13);
n17->ReplaceInput(0, n14);
n17->ReplaceInput(1, n3);
n17->ReplaceInput(2, n6);
n17->ReplaceInput(3, n12);
n17->ReplaceInput(4, n15);
n17->ReplaceInput(5, n13);
n23->ReplaceInput(0, n20);
n2->ReplaceInput(0, n0);
n29->ReplaceInput(0, n14);
n29->ReplaceInput(1, n27);
n29->ReplaceInput(2, n6);
n29->ReplaceInput(3, n12);
n29->ReplaceInput(4, n12);
n29->ReplaceInput(5, n27);
n29->ReplaceInput(6, n28);
n13->ReplaceInput(0, n9);
n13->ReplaceInput(1, n30);
n3->ReplaceInput(0, n0);
n6->ReplaceInput(0, n0);
n12->ReplaceInput(0, n10);
n12->ReplaceInput(1, n10);
n12->ReplaceInput(2, n10);
n12->ReplaceInput(3, n11);
n12->ReplaceInput(4, n5);
n15->ReplaceInput(0, n8);
n15->ReplaceInput(1, n29);
n15->ReplaceInput(2, n13);
n20->ReplaceInput(0, n19);
n20->ReplaceInput(1, n18);
n27->ReplaceInput(0, n3);
n27->ReplaceInput(1, n4);
n27->ReplaceInput(2, n6);
n27->ReplaceInput(3, n12);
n27->ReplaceInput(4, n12);
n27->ReplaceInput(5, n25);
n27->ReplaceInput(6, n26);
n28->ReplaceInput(0, n27);
n9->ReplaceInput(0, n8);
n30->ReplaceInput(0, n29);
n8->ReplaceInput(0, n6);
n8->ReplaceInput(1, n12);
n8->ReplaceInput(2, n0);
n8->ReplaceInput(3, n0);
n19->ReplaceInput(0, n17);
n19->ReplaceInput(1, n6);
n18->ReplaceInput(0, n17);
n4->ReplaceInput(0, n0);
n25->ReplaceInput(0, n6);
n25->ReplaceInput(1, n12);
n25->ReplaceInput(2, n17);
n25->ReplaceInput(3, n21);
n26->ReplaceInput(0, n25);
n21->ReplaceInput(0, n20);
graph()->SetStart(n0);
graph()->SetEnd(n34);
ComputeAndVerifySchedule(30);
}
namespace {
Node* CreateDiamond(Graph* graph, CommonOperatorBuilder* common, Node* cond) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment