[turbofan] Handle some arithmetic ops in early lowering.
This handles all arithmetic binary operations except addition during the early type-hint lowering (i.e. during graph construction). We still use static type information to potentially further reduce the speculative operations down to pure operations during the typed lowering phase. R=bmeurer@chromium.org Change-Id: I8b93fd7c46ec8e5b81234a49624d503520c3d082 Reviewed-on: https://chromium-review.googlesource.com/443105 Reviewed-by: Benedikt Meurer <bmeurer@chromium.org> Commit-Queue: Michael Starzinger <mstarzinger@chromium.org> Cr-Commit-Position: refs/heads/master@{#43218}
This commit is contained in:
parent
693b741f6d
commit
67d087d577
@ -2769,16 +2769,16 @@ Node* AstGraphBuilder::BuildBinaryOp(Node* left, Node* right, Token::Value op,
|
||||
js_op = javascript()->Add(hint);
|
||||
break;
|
||||
case Token::SUB:
|
||||
js_op = javascript()->Subtract(hint);
|
||||
js_op = javascript()->Subtract();
|
||||
break;
|
||||
case Token::MUL:
|
||||
js_op = javascript()->Multiply(hint);
|
||||
js_op = javascript()->Multiply();
|
||||
break;
|
||||
case Token::DIV:
|
||||
js_op = javascript()->Divide(hint);
|
||||
js_op = javascript()->Divide();
|
||||
break;
|
||||
case Token::MOD:
|
||||
js_op = javascript()->Modulus(hint);
|
||||
js_op = javascript()->Modulus();
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
|
@ -1557,23 +1557,17 @@ void BytecodeGraphBuilder::VisitAdd() {
|
||||
}
|
||||
|
||||
void BytecodeGraphBuilder::VisitSub() {
|
||||
BuildBinaryOp(javascript()->Subtract(
|
||||
GetBinaryOperationHint(kBinaryOperationHintIndex)));
|
||||
BuildBinaryOp(javascript()->Subtract());
|
||||
}
|
||||
|
||||
void BytecodeGraphBuilder::VisitMul() {
|
||||
BuildBinaryOp(javascript()->Multiply(
|
||||
GetBinaryOperationHint(kBinaryOperationHintIndex)));
|
||||
BuildBinaryOp(javascript()->Multiply());
|
||||
}
|
||||
|
||||
void BytecodeGraphBuilder::VisitDiv() {
|
||||
BuildBinaryOp(
|
||||
javascript()->Divide(GetBinaryOperationHint(kBinaryOperationHintIndex)));
|
||||
}
|
||||
void BytecodeGraphBuilder::VisitDiv() { BuildBinaryOp(javascript()->Divide()); }
|
||||
|
||||
void BytecodeGraphBuilder::VisitMod() {
|
||||
BuildBinaryOp(
|
||||
javascript()->Modulus(GetBinaryOperationHint(kBinaryOperationHintIndex)));
|
||||
BuildBinaryOp(javascript()->Modulus());
|
||||
}
|
||||
|
||||
void BytecodeGraphBuilder::VisitBitwiseOr() {
|
||||
@ -1605,10 +1599,10 @@ void BytecodeGraphBuilder::BuildBinaryOpWithImmediate(const Operator* op) {
|
||||
Node* left =
|
||||
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
|
||||
Node* right = jsgraph()->Constant(bytecode_iterator().GetImmediateOperand(0));
|
||||
FeedbackSlot slot = feedback_vector()->ToSlot(
|
||||
bytecode_iterator().GetIndexOperand(kBinaryOperationSmiHintIndex));
|
||||
|
||||
Node* node = nullptr;
|
||||
FeedbackSlot slot = feedback_vector()->ToSlot(
|
||||
bytecode_iterator().GetIndexOperand(kBinaryOperationSmiHintIndex));
|
||||
if (Node* simplified = TryBuildSimplifiedBinaryOp(op, left, right, slot)) {
|
||||
node = simplified;
|
||||
} else {
|
||||
@ -1624,8 +1618,7 @@ void BytecodeGraphBuilder::VisitAddSmi() {
|
||||
}
|
||||
|
||||
void BytecodeGraphBuilder::VisitSubSmi() {
|
||||
BuildBinaryOpWithImmediate(javascript()->Subtract(
|
||||
GetBinaryOperationHint(kBinaryOperationSmiHintIndex)));
|
||||
BuildBinaryOpWithImmediate(javascript()->Subtract());
|
||||
}
|
||||
|
||||
void BytecodeGraphBuilder::VisitBitwiseOrSmi() {
|
||||
@ -1648,19 +1641,37 @@ void BytecodeGraphBuilder::VisitInc() {
|
||||
PrepareEagerCheckpoint();
|
||||
// Note: Use subtract -1 here instead of add 1 to ensure we always convert to
|
||||
// a number, not a string.
|
||||
const Operator* js_op =
|
||||
javascript()->Subtract(GetBinaryOperationHint(kCountOperationHintIndex));
|
||||
Node* node = NewNode(js_op, environment()->LookupAccumulator(),
|
||||
jsgraph()->Constant(-1));
|
||||
Node* left = environment()->LookupAccumulator();
|
||||
Node* right = jsgraph()->Constant(-1);
|
||||
const Operator* op = javascript()->Subtract();
|
||||
|
||||
Node* node = nullptr;
|
||||
FeedbackSlot slot = feedback_vector()->ToSlot(
|
||||
bytecode_iterator().GetIndexOperand(kCountOperationHintIndex));
|
||||
if (Node* simplified = TryBuildSimplifiedBinaryOp(op, left, right, slot)) {
|
||||
node = simplified;
|
||||
} else {
|
||||
node = NewNode(op, left, right);
|
||||
}
|
||||
|
||||
environment()->BindAccumulator(node, Environment::kAttachFrameState);
|
||||
}
|
||||
|
||||
void BytecodeGraphBuilder::VisitDec() {
|
||||
PrepareEagerCheckpoint();
|
||||
const Operator* js_op =
|
||||
javascript()->Subtract(GetBinaryOperationHint(kCountOperationHintIndex));
|
||||
Node* node = NewNode(js_op, environment()->LookupAccumulator(),
|
||||
jsgraph()->OneConstant());
|
||||
Node* left = environment()->LookupAccumulator();
|
||||
Node* right = jsgraph()->OneConstant();
|
||||
const Operator* op = javascript()->Subtract();
|
||||
|
||||
Node* node = nullptr;
|
||||
FeedbackSlot slot = feedback_vector()->ToSlot(
|
||||
bytecode_iterator().GetIndexOperand(kCountOperationHintIndex));
|
||||
if (Node* simplified = TryBuildSimplifiedBinaryOp(op, left, right, slot)) {
|
||||
node = simplified;
|
||||
} else {
|
||||
node = NewNode(op, left, right);
|
||||
}
|
||||
|
||||
environment()->BindAccumulator(node, Environment::kAttachFrameState);
|
||||
}
|
||||
|
||||
|
@ -545,6 +545,10 @@ CompareOperationHint CompareOperationHintOf(const Operator* op) {
|
||||
V(ShiftLeft, Operator::kNoProperties, 2, 1) \
|
||||
V(ShiftRight, Operator::kNoProperties, 2, 1) \
|
||||
V(ShiftRightLogical, Operator::kNoProperties, 2, 1) \
|
||||
V(Subtract, Operator::kNoProperties, 2, 1) \
|
||||
V(Multiply, Operator::kNoProperties, 2, 1) \
|
||||
V(Divide, Operator::kNoProperties, 2, 1) \
|
||||
V(Modulus, Operator::kNoProperties, 2, 1) \
|
||||
V(ToInteger, Operator::kNoProperties, 1, 1) \
|
||||
V(ToLength, Operator::kNoProperties, 1, 1) \
|
||||
V(ToName, Operator::kNoProperties, 1, 1) \
|
||||
@ -568,12 +572,7 @@ CompareOperationHint CompareOperationHintOf(const Operator* op) {
|
||||
V(Debugger, Operator::kNoProperties, 0, 0) \
|
||||
V(GetSuperConstructor, Operator::kNoWrite, 1, 1)
|
||||
|
||||
#define BINARY_OP_LIST(V) \
|
||||
V(Add) \
|
||||
V(Subtract) \
|
||||
V(Multiply) \
|
||||
V(Divide) \
|
||||
V(Modulus)
|
||||
#define BINARY_OP_LIST(V) V(Add)
|
||||
|
||||
#define COMPARE_OP_LIST(V) \
|
||||
V(Equal, Operator::kNoProperties) \
|
||||
|
@ -579,10 +579,10 @@ class V8_EXPORT_PRIVATE JSOperatorBuilder final
|
||||
const Operator* ShiftRight();
|
||||
const Operator* ShiftRightLogical();
|
||||
const Operator* Add(BinaryOperationHint hint);
|
||||
const Operator* Subtract(BinaryOperationHint hint);
|
||||
const Operator* Multiply(BinaryOperationHint hint);
|
||||
const Operator* Divide(BinaryOperationHint hint);
|
||||
const Operator* Modulus(BinaryOperationHint hint);
|
||||
const Operator* Subtract();
|
||||
const Operator* Multiply();
|
||||
const Operator* Divide();
|
||||
const Operator* Modulus();
|
||||
|
||||
const Operator* ToBoolean(ToBooleanHints hints);
|
||||
const Operator* ToInteger();
|
||||
|
@ -127,7 +127,11 @@ Reduction JSTypeHintLowering::ReduceBinaryOperation(const Operator* op,
|
||||
case IrOpcode::kJSBitwiseAnd:
|
||||
case IrOpcode::kJSShiftLeft:
|
||||
case IrOpcode::kJSShiftRight:
|
||||
case IrOpcode::kJSShiftRightLogical: {
|
||||
case IrOpcode::kJSShiftRightLogical:
|
||||
case IrOpcode::kJSSubtract:
|
||||
case IrOpcode::kJSMultiply:
|
||||
case IrOpcode::kJSDivide:
|
||||
case IrOpcode::kJSModulus: {
|
||||
JSSpeculativeBinopBuilder b(this, op, left, right, effect, control, slot);
|
||||
NumberOperationHint hint;
|
||||
if (b.GetBinaryNumberOperationHint(&hint)) {
|
||||
@ -137,10 +141,6 @@ Reduction JSTypeHintLowering::ReduceBinaryOperation(const Operator* op,
|
||||
break;
|
||||
}
|
||||
case IrOpcode::kJSAdd:
|
||||
case IrOpcode::kJSSubtract:
|
||||
case IrOpcode::kJSMultiply:
|
||||
case IrOpcode::kJSDivide:
|
||||
case IrOpcode::kJSModulus:
|
||||
// TODO(mstarzinger): Implement speculative lowering.
|
||||
break;
|
||||
default:
|
||||
|
@ -370,6 +370,25 @@ class JSBinopReduction final {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const Operator* NumberOpFromSpeculativeNumberOp() {
|
||||
switch (node_->opcode()) {
|
||||
case IrOpcode::kSpeculativeNumberAdd:
|
||||
return simplified()->NumberAdd();
|
||||
case IrOpcode::kSpeculativeNumberSubtract:
|
||||
return simplified()->NumberSubtract();
|
||||
case IrOpcode::kSpeculativeNumberMultiply:
|
||||
return simplified()->NumberMultiply();
|
||||
case IrOpcode::kSpeculativeNumberDivide:
|
||||
return simplified()->NumberDivide();
|
||||
case IrOpcode::kSpeculativeNumberModulus:
|
||||
return simplified()->NumberModulus();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
UNREACHABLE();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const Operator* SpeculativeNumberOp(NumberOperationHint hint) {
|
||||
switch (node_->opcode()) {
|
||||
case IrOpcode::kJSAdd:
|
||||
@ -632,16 +651,6 @@ Reduction JSTypedLowering::ReduceJSAdd(Node* node) {
|
||||
|
||||
Reduction JSTypedLowering::ReduceNumberBinop(Node* node) {
|
||||
JSBinopReduction r(this, node);
|
||||
NumberOperationHint hint;
|
||||
if (r.GetBinaryNumberOperationHint(&hint)) {
|
||||
if (hint == NumberOperationHint::kNumberOrOddball &&
|
||||
r.BothInputsAre(Type::NumberOrOddball())) {
|
||||
r.ConvertInputsToNumber();
|
||||
return r.ChangeToPureOperator(r.NumberOp(), Type::Number());
|
||||
}
|
||||
return r.ChangeToSpeculativeOperator(r.SpeculativeNumberOp(hint),
|
||||
Type::Number());
|
||||
}
|
||||
if (r.BothInputsAre(Type::PlainPrimitive()) ||
|
||||
!(flags() & kDeoptimizationEnabled)) {
|
||||
r.ConvertInputsToNumber();
|
||||
@ -650,6 +659,18 @@ Reduction JSTypedLowering::ReduceNumberBinop(Node* node) {
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
Reduction JSTypedLowering::ReduceSpeculativeNumberBinop(Node* node) {
|
||||
JSBinopReduction r(this, node);
|
||||
NumberOperationHint hint = NumberOperationHintOf(node->op());
|
||||
if (hint == NumberOperationHint::kNumberOrOddball &&
|
||||
r.BothInputsAre(Type::NumberOrOddball())) {
|
||||
r.ConvertInputsToNumber();
|
||||
return r.ChangeToPureOperator(r.NumberOpFromSpeculativeNumberOp(),
|
||||
Type::Number());
|
||||
}
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
Reduction JSTypedLowering::ReduceInt32Binop(Node* node) {
|
||||
JSBinopReduction r(this, node);
|
||||
if (r.BothInputsAre(Type::PlainPrimitive()) ||
|
||||
@ -2473,6 +2494,13 @@ Reduction JSTypedLowering::Reduce(Node* node) {
|
||||
return ReduceJSGeneratorRestoreContinuation(node);
|
||||
case IrOpcode::kJSGeneratorRestoreRegister:
|
||||
return ReduceJSGeneratorRestoreRegister(node);
|
||||
// TODO(mstarzinger): Simplified operations hiding in JS-level reducer not
|
||||
// fooling anyone. Consider moving this into a separate reducer.
|
||||
case IrOpcode::kSpeculativeNumberSubtract:
|
||||
case IrOpcode::kSpeculativeNumberMultiply:
|
||||
case IrOpcode::kSpeculativeNumberDivide:
|
||||
case IrOpcode::kSpeculativeNumberModulus:
|
||||
return ReduceSpeculativeNumberBinop(node);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -84,6 +84,7 @@ class V8_EXPORT_PRIVATE JSTypedLowering final
|
||||
Reduction ReduceInt32Binop(Node* node);
|
||||
Reduction ReduceUI32Shift(Node* node, Signedness signedness);
|
||||
Reduction ReduceCreateConsString(Node* node);
|
||||
Reduction ReduceSpeculativeNumberBinop(Node* node);
|
||||
|
||||
Factory* factory() const;
|
||||
Graph* graph() const;
|
||||
|
@ -264,11 +264,11 @@ TEST(AddNumber1) {
|
||||
TEST(NumberBinops) {
|
||||
JSTypedLoweringTester R;
|
||||
const Operator* ops[] = {
|
||||
R.javascript.Add(R.binop_hints), R.simplified.NumberAdd(),
|
||||
R.javascript.Subtract(R.binop_hints), R.simplified.NumberSubtract(),
|
||||
R.javascript.Multiply(R.binop_hints), R.simplified.NumberMultiply(),
|
||||
R.javascript.Divide(R.binop_hints), R.simplified.NumberDivide(),
|
||||
R.javascript.Modulus(R.binop_hints), R.simplified.NumberModulus(),
|
||||
R.javascript.Add(R.binop_hints), R.simplified.NumberAdd(),
|
||||
R.javascript.Subtract(), R.simplified.NumberSubtract(),
|
||||
R.javascript.Multiply(), R.simplified.NumberMultiply(),
|
||||
R.javascript.Divide(), R.simplified.NumberDivide(),
|
||||
R.javascript.Modulus(), R.simplified.NumberModulus(),
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < arraysize(kNumberTypes); ++i) {
|
||||
@ -899,13 +899,13 @@ TEST(RemovePureNumberBinopEffects) {
|
||||
R.simplified.NumberEqual(),
|
||||
R.javascript.Add(R.binop_hints),
|
||||
R.simplified.NumberAdd(),
|
||||
R.javascript.Subtract(R.binop_hints),
|
||||
R.javascript.Subtract(),
|
||||
R.simplified.NumberSubtract(),
|
||||
R.javascript.Multiply(R.binop_hints),
|
||||
R.javascript.Multiply(),
|
||||
R.simplified.NumberMultiply(),
|
||||
R.javascript.Divide(R.binop_hints),
|
||||
R.javascript.Divide(),
|
||||
R.simplified.NumberDivide(),
|
||||
R.javascript.Modulus(R.binop_hints),
|
||||
R.javascript.Modulus(),
|
||||
R.simplified.NumberModulus(),
|
||||
R.javascript.LessThan(R.compare_hints),
|
||||
R.simplified.NumberLessThan(),
|
||||
@ -931,8 +931,8 @@ TEST(OrderNumberBinopEffects1) {
|
||||
JSTypedLoweringTester R;
|
||||
|
||||
const Operator* ops[] = {
|
||||
R.javascript.Subtract(R.binop_hints), R.simplified.NumberSubtract(),
|
||||
R.javascript.Multiply(R.binop_hints), R.simplified.NumberMultiply(),
|
||||
R.javascript.Subtract(), R.simplified.NumberSubtract(),
|
||||
R.javascript.Multiply(), R.simplified.NumberMultiply(),
|
||||
};
|
||||
|
||||
for (size_t j = 0; j < arraysize(ops); j += 2) {
|
||||
@ -956,9 +956,9 @@ TEST(OrderNumberBinopEffects2) {
|
||||
JSTypedLoweringTester R;
|
||||
|
||||
const Operator* ops[] = {
|
||||
R.javascript.Add(R.binop_hints), R.simplified.NumberAdd(),
|
||||
R.javascript.Subtract(R.binop_hints), R.simplified.NumberSubtract(),
|
||||
R.javascript.Multiply(R.binop_hints), R.simplified.NumberMultiply(),
|
||||
R.javascript.Add(R.binop_hints), R.simplified.NumberAdd(),
|
||||
R.javascript.Subtract(), R.simplified.NumberSubtract(),
|
||||
R.javascript.Multiply(), R.simplified.NumberMultiply(),
|
||||
};
|
||||
|
||||
for (size_t j = 0; j < arraysize(ops); j += 2) {
|
||||
|
@ -717,25 +717,6 @@ TEST_F(JSTypedLoweringTest, JSAddSmis) {
|
||||
rhs, effect, control));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// JSSubtract
|
||||
|
||||
TEST_F(JSTypedLoweringTest, JSSubtractSmis) {
|
||||
BinaryOperationHint const hint = BinaryOperationHint::kSignedSmall;
|
||||
Node* lhs = Parameter(Type::Number(), 0);
|
||||
Node* rhs = Parameter(Type::Number(), 1);
|
||||
Node* context = Parameter(Type::Any(), 2);
|
||||
Node* frame_state = EmptyFrameState();
|
||||
Node* effect = graph()->start();
|
||||
Node* control = graph()->start();
|
||||
Reduction r = Reduce(graph()->NewNode(javascript()->Subtract(hint), lhs, rhs,
|
||||
context, frame_state, effect, control));
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(),
|
||||
IsSpeculativeNumberSubtract(NumberOperationHint::kSignedSmall,
|
||||
lhs, rhs, effect, control));
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -245,22 +245,22 @@ TEST_F(TyperTest, TypeJSAdd) {
|
||||
|
||||
|
||||
TEST_F(TyperTest, TypeJSSubtract) {
|
||||
TestBinaryArithOp(javascript_.Subtract(hints_), std::minus<double>());
|
||||
TestBinaryArithOp(javascript_.Subtract(), std::minus<double>());
|
||||
}
|
||||
|
||||
|
||||
TEST_F(TyperTest, TypeJSMultiply) {
|
||||
TestBinaryArithOp(javascript_.Multiply(hints_), std::multiplies<double>());
|
||||
TestBinaryArithOp(javascript_.Multiply(), std::multiplies<double>());
|
||||
}
|
||||
|
||||
|
||||
TEST_F(TyperTest, TypeJSDivide) {
|
||||
TestBinaryArithOp(javascript_.Divide(hints_), std::divides<double>());
|
||||
TestBinaryArithOp(javascript_.Divide(), std::divides<double>());
|
||||
}
|
||||
|
||||
|
||||
TEST_F(TyperTest, TypeJSModulus) {
|
||||
TestBinaryArithOp(javascript_.Modulus(hints_), modulo);
|
||||
TestBinaryArithOp(javascript_.Modulus(), modulo);
|
||||
}
|
||||
|
||||
|
||||
@ -366,6 +366,10 @@ TEST_BINARY_MONOTONICITY(BitwiseAnd)
|
||||
TEST_BINARY_MONOTONICITY(ShiftLeft)
|
||||
TEST_BINARY_MONOTONICITY(ShiftRight)
|
||||
TEST_BINARY_MONOTONICITY(ShiftRightLogical)
|
||||
TEST_BINARY_MONOTONICITY(Subtract)
|
||||
TEST_BINARY_MONOTONICITY(Multiply)
|
||||
TEST_BINARY_MONOTONICITY(Divide)
|
||||
TEST_BINARY_MONOTONICITY(Modulus)
|
||||
#undef TEST_BINARY_MONOTONICITY
|
||||
|
||||
#define TEST_BINARY_MONOTONICITY(name) \
|
||||
@ -373,10 +377,6 @@ TEST_BINARY_MONOTONICITY(ShiftRightLogical)
|
||||
TestBinaryMonotonicity(javascript_.name(BinaryOperationHint::kAny)); \
|
||||
}
|
||||
TEST_BINARY_MONOTONICITY(Add)
|
||||
TEST_BINARY_MONOTONICITY(Subtract)
|
||||
TEST_BINARY_MONOTONICITY(Multiply)
|
||||
TEST_BINARY_MONOTONICITY(Divide)
|
||||
TEST_BINARY_MONOTONICITY(Modulus)
|
||||
#undef TEST_BINARY_MONOTONICITY
|
||||
|
||||
} // namespace compiler
|
||||
|
Loading…
Reference in New Issue
Block a user