| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/flow_graph.h" | 5 #include "vm/flow_graph.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/cha.h" | 8 #include "vm/cha.h" |
| 9 #include "vm/flow_graph_builder.h" | 9 #include "vm/flow_graph_builder.h" |
| 10 #include "vm/flow_graph_compiler.h" | 10 #include "vm/flow_graph_compiler.h" |
| (...skipping 1512 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1523 const Representation to_rep = | 1523 const Representation to_rep = |
| 1524 use->instruction()->RequiredInputRepresentation(use->use_index()); | 1524 use->instruction()->RequiredInputRepresentation(use->use_index()); |
| 1525 if (from_rep == to_rep || to_rep == kNoRepresentation) { | 1525 if (from_rep == to_rep || to_rep == kNoRepresentation) { |
| 1526 return; | 1526 return; |
| 1527 } | 1527 } |
| 1528 InsertConversion(from_rep, to_rep, use, /*is_environment_use=*/false); | 1528 InsertConversion(from_rep, to_rep, use, /*is_environment_use=*/false); |
| 1529 } | 1529 } |
| 1530 | 1530 |
| 1531 static bool IsUnboxedInteger(Representation rep) { | 1531 static bool IsUnboxedInteger(Representation rep) { |
| 1532 return (rep == kUnboxedInt32) || (rep == kUnboxedUint32) || | 1532 return (rep == kUnboxedInt32) || (rep == kUnboxedUint32) || |
| 1533 (rep == kUnboxedMint); | 1533 (rep == kUnboxedInt64); |
| 1534 } | 1534 } |
| 1535 | 1535 |
| 1536 static bool ShouldInlineSimd() { | 1536 static bool ShouldInlineSimd() { |
| 1537 return FlowGraphCompiler::SupportsUnboxedSimd128(); | 1537 return FlowGraphCompiler::SupportsUnboxedSimd128(); |
| 1538 } | 1538 } |
| 1539 | 1539 |
| 1540 static bool CanUnboxDouble() { | 1540 static bool CanUnboxDouble() { |
| 1541 return FlowGraphCompiler::SupportsUnboxedDoubles(); | 1541 return FlowGraphCompiler::SupportsUnboxedDoubles(); |
| 1542 } | 1542 } |
| 1543 | 1543 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1564 | 1564 |
| 1565 Definition* converted = NULL; | 1565 Definition* converted = NULL; |
| 1566 if (IsUnboxedInteger(from) && IsUnboxedInteger(to)) { | 1566 if (IsUnboxedInteger(from) && IsUnboxedInteger(to)) { |
| 1567 const intptr_t deopt_id = (to == kUnboxedInt32) && (deopt_target != NULL) | 1567 const intptr_t deopt_id = (to == kUnboxedInt32) && (deopt_target != NULL) |
| 1568 ? deopt_target->DeoptimizationTarget() | 1568 ? deopt_target->DeoptimizationTarget() |
| 1569 : Thread::kNoDeoptId; | 1569 : Thread::kNoDeoptId; |
| 1570 converted = new (Z) | 1570 converted = new (Z) |
| 1571 UnboxedIntConverterInstr(from, to, use->CopyWithType(), deopt_id); | 1571 UnboxedIntConverterInstr(from, to, use->CopyWithType(), deopt_id); |
| 1572 } else if ((from == kUnboxedInt32) && (to == kUnboxedDouble)) { | 1572 } else if ((from == kUnboxedInt32) && (to == kUnboxedDouble)) { |
| 1573 converted = new Int32ToDoubleInstr(use->CopyWithType()); | 1573 converted = new Int32ToDoubleInstr(use->CopyWithType()); |
| 1574 } else if ((from == kUnboxedMint) && (to == kUnboxedDouble) && | 1574 } else if ((from == kUnboxedInt64) && (to == kUnboxedDouble) && |
| 1575 CanConvertUnboxedMintToDouble()) { | 1575 CanConvertUnboxedMintToDouble()) { |
| 1576 const intptr_t deopt_id = (deopt_target != NULL) | 1576 const intptr_t deopt_id = (deopt_target != NULL) |
| 1577 ? deopt_target->DeoptimizationTarget() | 1577 ? deopt_target->DeoptimizationTarget() |
| 1578 : Thread::kNoDeoptId; | 1578 : Thread::kNoDeoptId; |
| 1579 ASSERT(CanUnboxDouble()); | 1579 ASSERT(CanUnboxDouble()); |
| 1580 converted = new MintToDoubleInstr(use->CopyWithType(), deopt_id); | 1580 converted = new MintToDoubleInstr(use->CopyWithType(), deopt_id); |
| 1581 } else if ((from == kTagged) && Boxing::Supports(to)) { | 1581 } else if ((from == kTagged) && Boxing::Supports(to)) { |
| 1582 const intptr_t deopt_id = (deopt_target != NULL) | 1582 const intptr_t deopt_id = (deopt_target != NULL) |
| 1583 ? deopt_target->DeoptimizationTarget() | 1583 ? deopt_target->DeoptimizationTarget() |
| 1584 : Thread::kNoDeoptId; | 1584 : Thread::kNoDeoptId; |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1710 | 1710 |
| 1711 if (!has_unboxed_use) { | 1711 if (!has_unboxed_use) { |
| 1712 should_unbox = false; | 1712 should_unbox = false; |
| 1713 } | 1713 } |
| 1714 } | 1714 } |
| 1715 | 1715 |
| 1716 if (should_unbox) { | 1716 if (should_unbox) { |
| 1717 unboxed = | 1717 unboxed = |
| 1718 RangeUtils::Fits(phi->range(), RangeBoundary::kRangeBoundaryInt32) | 1718 RangeUtils::Fits(phi->range(), RangeBoundary::kRangeBoundaryInt32) |
| 1719 ? kUnboxedInt32 | 1719 ? kUnboxedInt32 |
| 1720 : kUnboxedMint; | 1720 : kUnboxedInt64; |
| 1721 } | 1721 } |
| 1722 } | 1722 } |
| 1723 | 1723 |
| 1724 phi->set_representation(unboxed); | 1724 phi->set_representation(unboxed); |
| 1725 } | 1725 } |
| 1726 | 1726 |
| 1727 void FlowGraph::SelectRepresentations() { | 1727 void FlowGraph::SelectRepresentations() { |
| 1728 // Conservatively unbox all phis that were proven to be of Double, | 1728 // Conservatively unbox all phis that were proven to be of Double, |
| 1729 // Float32x4, or Int32x4 type. | 1729 // Float32x4, or Int32x4 type. |
| 1730 for (BlockIterator block_it = reverse_postorder_iterator(); !block_it.Done(); | 1730 for (BlockIterator block_it = reverse_postorder_iterator(); !block_it.Done(); |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1880 | 1880 |
| 1881 const intptr_t defn_loop = loops[defn->GetBlock()->preorder_number()]; | 1881 const intptr_t defn_loop = loops[defn->GetBlock()->preorder_number()]; |
| 1882 | 1882 |
| 1883 // Process all inputs. | 1883 // Process all inputs. |
| 1884 for (intptr_t k = 0; k < defn->InputCount(); k++) { | 1884 for (intptr_t k = 0; k < defn->InputCount(); k++) { |
| 1885 Definition* input = defn->InputAt(k)->definition(); | 1885 Definition* input = defn->InputAt(k)->definition(); |
| 1886 if (input->IsBinarySmiOp() && CanBeWidened(input->AsBinarySmiOp())) { | 1886 if (input->IsBinarySmiOp() && CanBeWidened(input->AsBinarySmiOp())) { |
| 1887 worklist.Add(input); | 1887 worklist.Add(input); |
| 1888 } else if (input->IsPhi() && (input->Type()->ToCid() == kSmiCid)) { | 1888 } else if (input->IsPhi() && (input->Type()->ToCid() == kSmiCid)) { |
| 1889 worklist.Add(input); | 1889 worklist.Add(input); |
| 1890 } else if (input->IsBinaryMintOp()) { | 1890 } else if (input->IsBinaryInt64Op()) { |
| 1891 // Mint operation produces untagged result. We avoid tagging. | 1891 // Mint operation produces untagged result. We avoid tagging. |
| 1892 gain++; | 1892 gain++; |
| 1893 if (FLAG_support_il_printer && FLAG_trace_smi_widening) { | 1893 if (FLAG_support_il_printer && FLAG_trace_smi_widening) { |
| 1894 THR_Print("^ [%" Pd "] (i) %s\n", gain, input->ToCString()); | 1894 THR_Print("^ [%" Pd "] (i) %s\n", gain, input->ToCString()); |
| 1895 } | 1895 } |
| 1896 } else if (defn_loop == loops[input->GetBlock()->preorder_number()] && | 1896 } else if (defn_loop == loops[input->GetBlock()->preorder_number()] && |
| 1897 (input->Type()->ToCid() == kSmiCid)) { | 1897 (input->Type()->ToCid() == kSmiCid)) { |
| 1898 // Input comes from the same loop, is known to be smi and requires | 1898 // Input comes from the same loop, is known to be smi and requires |
| 1899 // untagging. | 1899 // untagging. |
| 1900 // TODO(vegorov) this heuristic assumes that values that are not | 1900 // TODO(vegorov) this heuristic assumes that values that are not |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1922 use->instruction()->ToCString()); | 1922 use->instruction()->ToCString()); |
| 1923 } | 1923 } |
| 1924 } | 1924 } |
| 1925 continue; | 1925 continue; |
| 1926 } else if (use_defn->IsBinarySmiOp() && | 1926 } else if (use_defn->IsBinarySmiOp() && |
| 1927 CanBeWidened(use_defn->AsBinarySmiOp())) { | 1927 CanBeWidened(use_defn->AsBinarySmiOp())) { |
| 1928 worklist.Add(use_defn); | 1928 worklist.Add(use_defn); |
| 1929 } else if (use_defn->IsPhi() && | 1929 } else if (use_defn->IsPhi() && |
| 1930 use_defn->AsPhi()->Type()->ToCid() == kSmiCid) { | 1930 use_defn->AsPhi()->Type()->ToCid() == kSmiCid) { |
| 1931 worklist.Add(use_defn); | 1931 worklist.Add(use_defn); |
| 1932 } else if (use_defn->IsBinaryMintOp()) { | 1932 } else if (use_defn->IsBinaryInt64Op()) { |
| 1933 // BinaryMintOp requires untagging of its inputs. | 1933 // BinaryInt64Op requires untagging of its inputs. |
| 1934 // Converting kUnboxedInt32 to kUnboxedMint is essentially zero cost | 1934 // Converting kUnboxedInt32 to kUnboxedInt64 is essentially zero cost |
| 1935 // sign extension operation. | 1935 // sign extension operation. |
| 1936 gain++; | 1936 gain++; |
| 1937 if (FLAG_support_il_printer && FLAG_trace_smi_widening) { | 1937 if (FLAG_support_il_printer && FLAG_trace_smi_widening) { |
| 1938 THR_Print("^ [%" Pd "] (u) %s\n", gain, | 1938 THR_Print("^ [%" Pd "] (u) %s\n", gain, |
| 1939 use->instruction()->ToCString()); | 1939 use->instruction()->ToCString()); |
| 1940 } | 1940 } |
| 1941 } else if (defn_loop == loops[instr->GetBlock()->preorder_number()]) { | 1941 } else if (defn_loop == loops[instr->GetBlock()->preorder_number()]) { |
| 1942 gain--; | 1942 gain--; |
| 1943 if (FLAG_support_il_printer && FLAG_trace_smi_widening) { | 1943 if (FLAG_support_il_printer && FLAG_trace_smi_widening) { |
| 1944 THR_Print("v [%" Pd "] (u) %s\n", gain, | 1944 THR_Print("v [%" Pd "] (u) %s\n", gain, |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2057 BinarySmiOpInstr* binop = it.Current()->AsBinarySmiOp(); | 2057 BinarySmiOpInstr* binop = it.Current()->AsBinarySmiOp(); |
| 2058 if (binop->op_kind() == Token::kBIT_AND) { | 2058 if (binop->op_kind() == Token::kBIT_AND) { |
| 2059 OptimizeLeftShiftBitAndSmiOp(&it, binop, binop->left()->definition(), | 2059 OptimizeLeftShiftBitAndSmiOp(&it, binop, binop->left()->definition(), |
| 2060 binop->right()->definition()); | 2060 binop->right()->definition()); |
| 2061 } else if ((binop->op_kind() == Token::kTRUNCDIV) || | 2061 } else if ((binop->op_kind() == Token::kTRUNCDIV) || |
| 2062 (binop->op_kind() == Token::kMOD)) { | 2062 (binop->op_kind() == Token::kMOD)) { |
| 2063 if (binop->HasUses()) { | 2063 if (binop->HasUses()) { |
| 2064 div_mod_merge.Add(binop); | 2064 div_mod_merge.Add(binop); |
| 2065 } | 2065 } |
| 2066 } | 2066 } |
| 2067 } else if (it.Current()->IsBinaryMintOp()) { | 2067 } else if (it.Current()->IsBinaryInt64Op()) { |
| 2068 BinaryMintOpInstr* mintop = it.Current()->AsBinaryMintOp(); | 2068 BinaryInt64OpInstr* mintop = it.Current()->AsBinaryInt64Op(); |
| 2069 if (mintop->op_kind() == Token::kBIT_AND) { | 2069 if (mintop->op_kind() == Token::kBIT_AND) { |
| 2070 OptimizeLeftShiftBitAndSmiOp(&it, mintop, | 2070 OptimizeLeftShiftBitAndSmiOp(&it, mintop, |
| 2071 mintop->left()->definition(), | 2071 mintop->left()->definition(), |
| 2072 mintop->right()->definition()); | 2072 mintop->right()->definition()); |
| 2073 } | 2073 } |
| 2074 } else if (it.Current()->IsInvokeMathCFunction()) { | 2074 } else if (it.Current()->IsInvokeMathCFunction()) { |
| 2075 InvokeMathCFunctionInstr* math_unary = | 2075 InvokeMathCFunctionInstr* math_unary = |
| 2076 it.Current()->AsInvokeMathCFunction(); | 2076 it.Current()->AsInvokeMathCFunction(); |
| 2077 if ((math_unary->recognized_kind() == MethodRecognizer::kMathSin) || | 2077 if ((math_unary->recognized_kind() == MethodRecognizer::kMathSin) || |
| 2078 (math_unary->recognized_kind() == MethodRecognizer::kMathCos)) { | 2078 (math_unary->recognized_kind() == MethodRecognizer::kMathCos)) { |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2173 if (bit_and_instr->InputAt(0)->IsSingleUse()) { | 2173 if (bit_and_instr->InputAt(0)->IsSingleUse()) { |
| 2174 smi_shift_left = AsSmiShiftLeftInstruction(left_instr); | 2174 smi_shift_left = AsSmiShiftLeftInstruction(left_instr); |
| 2175 } | 2175 } |
| 2176 if ((smi_shift_left == NULL) && (bit_and_instr->InputAt(1)->IsSingleUse())) { | 2176 if ((smi_shift_left == NULL) && (bit_and_instr->InputAt(1)->IsSingleUse())) { |
| 2177 smi_shift_left = AsSmiShiftLeftInstruction(right_instr); | 2177 smi_shift_left = AsSmiShiftLeftInstruction(right_instr); |
| 2178 } | 2178 } |
| 2179 if (smi_shift_left == NULL) return; | 2179 if (smi_shift_left == NULL) return; |
| 2180 | 2180 |
| 2181 // Pattern recognized. | 2181 // Pattern recognized. |
| 2182 smi_shift_left->mark_truncating(); | 2182 smi_shift_left->mark_truncating(); |
| 2183 ASSERT(bit_and_instr->IsBinarySmiOp() || bit_and_instr->IsBinaryMintOp()); | 2183 ASSERT(bit_and_instr->IsBinarySmiOp() || bit_and_instr->IsBinaryInt64Op()); |
| 2184 if (bit_and_instr->IsBinaryMintOp()) { | 2184 if (bit_and_instr->IsBinaryInt64Op()) { |
| 2185 // Replace Mint op with Smi op. | 2185 // Replace Mint op with Smi op. |
| 2186 BinarySmiOpInstr* smi_op = new (Z) BinarySmiOpInstr( | 2186 BinarySmiOpInstr* smi_op = new (Z) BinarySmiOpInstr( |
| 2187 Token::kBIT_AND, new (Z) Value(left_instr), new (Z) Value(right_instr), | 2187 Token::kBIT_AND, new (Z) Value(left_instr), new (Z) Value(right_instr), |
| 2188 Thread::kNoDeoptId); // BIT_AND cannot deoptimize. | 2188 Thread::kNoDeoptId); // BIT_AND cannot deoptimize. |
| 2189 bit_and_instr->ReplaceWith(smi_op, current_iterator); | 2189 bit_and_instr->ReplaceWith(smi_op, current_iterator); |
| 2190 } | 2190 } |
| 2191 } | 2191 } |
| 2192 | 2192 |
| 2193 // Dart: | 2193 // Dart: |
| 2194 // var x = d % 10; | 2194 // var x = d % 10; |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2264 intptr_t index, | 2264 intptr_t index, |
| 2265 Representation rep, | 2265 Representation rep, |
| 2266 intptr_t cid) { | 2266 intptr_t cid) { |
| 2267 ExtractNthOutputInstr* extract = | 2267 ExtractNthOutputInstr* extract = |
| 2268 new (Z) ExtractNthOutputInstr(new (Z) Value(instr), index, rep, cid); | 2268 new (Z) ExtractNthOutputInstr(new (Z) Value(instr), index, rep, cid); |
| 2269 instr->ReplaceUsesWith(extract); | 2269 instr->ReplaceUsesWith(extract); |
| 2270 InsertAfter(instr, extract, NULL, FlowGraph::kValue); | 2270 InsertAfter(instr, extract, NULL, FlowGraph::kValue); |
| 2271 } | 2271 } |
| 2272 | 2272 |
| 2273 } // namespace dart | 2273 } // namespace dart |
| OLD | NEW |