Chromium Code Reviews| Index: runtime/vm/intermediate_language_dbc.cc |
| diff --git a/runtime/vm/intermediate_language_dbc.cc b/runtime/vm/intermediate_language_dbc.cc |
| index ea9c9d8018624e0de891a80c48c28b431b037863..519c8fc4717f908854acad07472c1ca028e95d76 100644 |
| --- a/runtime/vm/intermediate_language_dbc.cc |
| +++ b/runtime/vm/intermediate_language_dbc.cc |
| @@ -483,6 +483,13 @@ static void EmitBranchOnCondition(FlowGraphCompiler* compiler, |
| } |
| +Condition StrictCompareInstr::GetPredictedCondition(FlowGraphCompiler* compiler, |
|
Vyacheslav Egorov (Google)
2017/06/15 11:32:46
The name GetPredicatedCondition(...) is very confu
erikcorry
2017/06/19 07:15:09
Done.
|
| + BranchLabels labels) { |
| + return (labels.fall_through == labels.false_label) ? NEXT_IS_TRUE |
| + : NEXT_IS_FALSE; |
| +} |
| + |
| + |
| Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| BranchLabels labels) { |
| ASSERT((kind() == Token::kNE_STRICT) || (kind() == Token::kEQ_STRICT)); |
| @@ -526,47 +533,91 @@ Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| } |
| -void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| - BranchInstr* branch) { |
| - ASSERT((kind() == Token::kEQ_STRICT) || (kind() == Token::kNE_STRICT)); |
| +DEFINE_MAKE_LOCATION_SUMMARY(StrictCompare, |
| + 2, |
| + Location::RequiresRegister(), |
| + needs_number_check() ? LocationSummary::kCall |
| + : LocationSummary::kNoCall) |
| + |
| +template <intptr_t N, |
| + typename ThrowsTrait, |
| + template <typename Impure, typename Pure> class CSETrait> |
| +void TemplateComparison<N, ThrowsTrait, CSETrait>::EmitBranchCode( |
| + FlowGraphCompiler* compiler, |
| + BranchInstr* branch) { |
| BranchLabels labels = compiler->CreateBranchLabels(branch); |
| Condition true_condition = EmitComparisonCode(compiler, labels); |
| - EmitBranchOnCondition(compiler, true_condition, labels); |
| + if (true_condition != INVALID_CONDITION) { |
| + EmitBranchOnCondition(compiler, true_condition, labels); |
| + } |
| } |
| -EMIT_NATIVE_CODE(StrictCompare, |
| - 2, |
| - Location::RequiresRegister(), |
| - needs_number_check() ? LocationSummary::kCall |
| - : LocationSummary::kNoCall) { |
| - ASSERT((kind() == Token::kEQ_STRICT) || (kind() == Token::kNE_STRICT)); |
| +// IA32 compiler needs this to link. |
| +template <> |
| +void TemplateComparison<2, Throws, NoCSE>::EmitBranchCode( |
| + FlowGraphCompiler* compiler, |
| + BranchInstr* branch) { |
| + UNREACHABLE(); |
| +} |
| + |
| +template <intptr_t N, |
| + typename ThrowsTrait, |
| + template <typename Impure, typename Pure> class CSETrait> |
| +void TemplateComparison<N, ThrowsTrait, CSETrait>::EmitNativeCode( |
| + FlowGraphCompiler* compiler) { |
| Label is_true, is_false; |
| BranchLabels labels = {&is_true, &is_false, &is_false}; |
| - Condition true_condition = EmitComparisonCode(compiler, labels); |
| - EmitBranchOnCondition(compiler, true_condition, labels); |
| - Label done; |
| - if (compiler->is_optimizing()) { |
| - const Register result = locs()->out(0).reg(); |
| - __ Bind(&is_false); |
| - __ LoadConstant(result, Bool::False()); |
| - __ Jump(&done); |
| - __ Bind(&is_true); |
| - __ LoadConstant(result, Bool::True()); |
| - __ Bind(&done); |
| - } else { |
| + Condition true_condition = this->GetPredictedCondition(compiler, labels); |
| + if (true_condition == INVALID_CONDITION || !compiler->is_optimizing() || |
| + is_true.IsLinked() || is_false.IsLinked()) { |
| + Condition actual_condition = EmitComparisonCode(compiler, labels); |
| + ASSERT(actual_condition == true_condition); |
| + if (true_condition != INVALID_CONDITION) { |
| + EmitBranchOnCondition(compiler, true_condition, labels); |
| + } |
| + Label done; |
| __ Bind(&is_false); |
| __ PushConstant(Bool::False()); |
| __ Jump(&done); |
| __ Bind(&is_true); |
| __ PushConstant(Bool::True()); |
| __ Bind(&done); |
| + } else { |
| + const Register result = this->locs()->out(0).reg(); |
| + __ LoadConstant( |
| + result, true_condition == NEXT_IS_TRUE ? Bool::False() : Bool::True()); |
| + Condition actual_condition = EmitComparisonCode(compiler, labels); |
| + ASSERT(actual_condition == true_condition); |
| + __ LoadConstant( |
| + result, true_condition == NEXT_IS_TRUE ? Bool::True() : Bool::False()); |
| } |
| } |
| +// IA32 compiler needs this to link (for the simmips config). |
| +template <> |
| +void TemplateComparison<2, Throws, NoCSE>::EmitNativeCode( |
| + FlowGraphCompiler* compiler) { |
| + UNREACHABLE(); |
| +} |
| + |
| + |
| +// Explicit template instantiations. |
| +template void TemplateComparison<1, NoThrow, Pure>::EmitNativeCode( |
| + FlowGraphCompiler*); |
| +template void TemplateComparison<2, NoThrow, Pure>::EmitNativeCode( |
| + FlowGraphCompiler*); |
| +template void TemplateComparison<1, NoThrow, Pure>::EmitBranchCode( |
| + FlowGraphCompiler* compiler, |
| + BranchInstr* branch); |
| +template void TemplateComparison<2, NoThrow, Pure>::EmitBranchCode( |
| + FlowGraphCompiler* compiler, |
| + BranchInstr* branch); |
| + |
| + |
| LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| comparison()->InitializeLocationSummary(zone, opt); |
| if (!comparison()->HasLocs()) { |
| @@ -601,6 +652,13 @@ EMIT_NATIVE_CODE(Goto, 0) { |
| } |
| +Condition TestSmiInstr::GetPredictedCondition(FlowGraphCompiler* compiler, |
| + BranchLabels labels) { |
| + ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); |
| + return (kind() == Token::kEQ) ? NEXT_IS_TRUE : NEXT_IS_FALSE; |
| +} |
| + |
| + |
| Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| BranchLabels labels) { |
| ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); |
| @@ -611,21 +669,10 @@ Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| } |
| -void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| - BranchInstr* branch) { |
| - BranchLabels labels = compiler->CreateBranchLabels(branch); |
| - Condition true_condition = EmitComparisonCode(compiler, labels); |
| - EmitBranchOnCondition(compiler, true_condition, labels); |
| -} |
| - |
| - |
| -EMIT_NATIVE_CODE(TestSmi, |
| - 2, |
| - Location::RequiresRegister(), |
| - LocationSummary::kNoCall) { |
| - // Never emitted outside of the BranchInstr. |
| - UNREACHABLE(); |
| -} |
| +DEFINE_MAKE_LOCATION_SUMMARY(TestSmi, |
| + 2, |
| + Location::RequiresRegister(), |
| + LocationSummary::kNoCall) |
| Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| @@ -662,30 +709,16 @@ Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| } |
| -void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| - BranchInstr* branch) { |
| - BranchLabels labels = compiler->CreateBranchLabels(branch); |
| - Condition true_condition = EmitComparisonCode(compiler, labels); |
| - EmitBranchOnCondition(compiler, true_condition, labels); |
| +Condition TestCidsInstr::GetPredictedCondition(FlowGraphCompiler* compiler, |
| + BranchLabels labels) { |
| + return NEXT_IS_TRUE; |
| } |
| -EMIT_NATIVE_CODE(TestCids, |
| - 1, |
| - Location::RequiresRegister(), |
| - LocationSummary::kNoCall) { |
| - Register result_reg = locs()->out(0).reg(); |
| - Label is_true, is_false, done; |
| - BranchLabels labels = {&is_true, &is_false, &is_false}; |
| - EmitComparisonCode(compiler, labels); |
| - __ Jump(&is_true); |
| - __ Bind(&is_false); |
| - __ LoadConstant(result_reg, Bool::False()); |
| - __ Jump(&done); |
| - __ Bind(&is_true); |
| - __ LoadConstant(result_reg, Bool::True()); |
| - __ Bind(&done); |
| -} |
| +DEFINE_MAKE_LOCATION_SUMMARY(TestCids, |
| + 1, |
| + Location::RequiresRegister(), |
| + LocationSummary::kNoCall) |
| EMIT_NATIVE_CODE(CreateArray, |
| @@ -1753,15 +1786,7 @@ EMIT_NATIVE_CODE(BinaryDoubleOp, 2, Location::RequiresRegister()) { |
| Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| BranchLabels labels) { |
| - UNREACHABLE(); |
| - return Condition(); |
| -} |
| - |
| - |
| -void DoubleTestOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| - BranchInstr* branch) { |
| ASSERT(compiler->is_optimizing()); |
| - BranchLabels labels = compiler->CreateBranchLabels(branch); |
| const Register value = locs()->in(0).reg(); |
| switch (op_kind()) { |
| case MethodRecognizer::kDouble_getIsNaN: |
| @@ -1774,31 +1799,20 @@ void DoubleTestOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| UNREACHABLE(); |
| } |
| const bool is_negated = kind() != Token::kEQ; |
|
Vyacheslav Egorov (Google)
2017/06/15 11:32:46
return GetPredictedCondition();
erikcorry
2017/06/19 07:15:09
See above
|
| - EmitBranchOnCondition(compiler, is_negated ? NEXT_IS_FALSE : NEXT_IS_TRUE, |
| - labels); |
| + return is_negated ? NEXT_IS_FALSE : NEXT_IS_TRUE; |
| } |
| -EMIT_NATIVE_CODE(DoubleTestOp, 1, Location::RequiresRegister()) { |
| - ASSERT(compiler->is_optimizing()); |
| - const Register value = locs()->in(0).reg(); |
| - const Register result = locs()->out(0).reg(); |
| +Condition DoubleTestOpInstr::GetPredictedCondition(FlowGraphCompiler* compiler, |
| + BranchLabels labels) { |
| const bool is_negated = kind() != Token::kEQ; |
| - __ LoadConstant(result, is_negated ? Bool::True() : Bool::False()); |
| - switch (op_kind()) { |
| - case MethodRecognizer::kDouble_getIsNaN: |
| - __ DoubleIsNaN(value); |
| - break; |
| - case MethodRecognizer::kDouble_getIsInfinite: |
| - __ DoubleIsInfinite(value); |
| - break; |
| - default: |
| - UNREACHABLE(); |
| - } |
| - __ LoadConstant(result, is_negated ? Bool::False() : Bool::True()); |
| + return is_negated ? NEXT_IS_FALSE : NEXT_IS_TRUE; |
| } |
| +DEFINE_MAKE_LOCATION_SUMMARY(DoubleTestOp, 1, Location::RequiresRegister()) |
| + |
| + |
| EMIT_NATIVE_CODE(UnaryDoubleOp, 1, Location::RequiresRegister()) { |
| const Register value = locs()->in(0).reg(); |
| const Register result = locs()->out(0).reg(); |
| @@ -1973,7 +1987,8 @@ static Condition EmitSmiComparisonOp(FlowGraphCompiler* compiler, |
| // If we aren't falling through to the false label, we can save a Jump |
| // instruction in the case that the true case is the fall through by |
| // flipping the sense of the test such that the instruction following the |
| - // test is the Jump to the false label. |
| + // test is the Jump to the false label. In the case where both labels are |
| + // null we don't flip the sense of the test. |
| condition = NEXT_IS_FALSE; |
| comparison = FlipCondition(kind); |
| } |
| @@ -2010,29 +2025,20 @@ Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| } |
| -EMIT_NATIVE_CODE(EqualityCompare, 2, Location::RequiresRegister()) { |
| - ASSERT(compiler->is_optimizing()); |
| - ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); |
| - Label is_true, is_false; |
| - // These labels are not used. They are arranged so that EmitComparisonCode |
| - // emits a test that executes the following instruction when the test |
| - // succeeds. |
| - BranchLabels labels = {&is_true, &is_false, &is_false}; |
| - const Register result = locs()->out(0).reg(); |
| - __ LoadConstant(result, Bool::False()); |
| - Condition true_condition = EmitComparisonCode(compiler, labels); |
| - ASSERT(true_condition == NEXT_IS_TRUE); |
| - __ LoadConstant(result, Bool::True()); |
| +Condition EqualityCompareInstr::GetPredictedCondition( |
| + FlowGraphCompiler* compiler, |
| + BranchLabels labels) { |
| + if (operation_cid() == kSmiCid) { |
| + return (labels.fall_through != labels.false_label) ? NEXT_IS_FALSE |
| + : NEXT_IS_TRUE; |
| + } else { |
| + ASSERT(operation_cid() == kDoubleCid); |
| + return NEXT_IS_TRUE; |
| + } |
| } |
| -void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| - BranchInstr* branch) { |
| - ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| - BranchLabels labels = compiler->CreateBranchLabels(branch); |
| - Condition true_condition = EmitComparisonCode(compiler, labels); |
| - EmitBranchOnCondition(compiler, true_condition, labels); |
| -} |
| +DEFINE_MAKE_LOCATION_SUMMARY(EqualityCompare, 2, Location::RequiresRegister()); |
| Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| @@ -2046,24 +2052,19 @@ Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| } |
| -EMIT_NATIVE_CODE(RelationalOp, 2, Location::RequiresRegister()) { |
| - ASSERT(compiler->is_optimizing()); |
| - Label is_true, is_false; |
| - BranchLabels labels = {&is_true, &is_false, &is_false}; |
| - const Register result = locs()->out(0).reg(); |
| - __ LoadConstant(result, Bool::False()); |
| - Condition true_condition = EmitComparisonCode(compiler, labels); |
| - ASSERT(true_condition == NEXT_IS_TRUE); |
| - __ LoadConstant(result, Bool::True()); |
| +Condition RelationalOpInstr::GetPredictedCondition(FlowGraphCompiler* compiler, |
| + BranchLabels labels) { |
| + if (operation_cid() == kSmiCid) { |
| + return (labels.fall_through != labels.false_label) ? NEXT_IS_FALSE |
| + : NEXT_IS_TRUE; |
| + } else { |
| + ASSERT(operation_cid() == kDoubleCid); |
| + return NEXT_IS_TRUE; |
| + } |
| } |
| -void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| - BranchInstr* branch) { |
| - BranchLabels labels = compiler->CreateBranchLabels(branch); |
| - Condition true_condition = EmitComparisonCode(compiler, labels); |
| - EmitBranchOnCondition(compiler, true_condition, labels); |
| -} |
| +DEFINE_MAKE_LOCATION_SUMMARY(RelationalOp, 2, Location::RequiresRegister()) |
| EMIT_NATIVE_CODE(CheckArrayBound, 2) { |