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

Unified Diff: runtime/vm/aot_optimizer.cc

Issue 2265873005: VM: Remove more duplicate code between AOT and JIT compiler. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: fix comment Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/aot_optimizer.h ('k') | runtime/vm/compiler.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/aot_optimizer.cc
diff --git a/runtime/vm/aot_optimizer.cc b/runtime/vm/aot_optimizer.cc
index 8b279bdc358476984efcc8f54c712f5e2c1070e0..0fce824983e06c8838e640c7a2d3dd695d7b094f 100644
--- a/runtime/vm/aot_optimizer.cc
+++ b/runtime/vm/aot_optimizer.cc
@@ -266,262 +266,6 @@ const ICData& AotOptimizer::TrySpecializeICData(const ICData& ic_data,
}
-static BinarySmiOpInstr* AsSmiShiftLeftInstruction(Definition* d) {
- BinarySmiOpInstr* instr = d->AsBinarySmiOp();
- if ((instr != NULL) && (instr->op_kind() == Token::kSHL)) {
- return instr;
- }
- return NULL;
-}
-
-
-static bool IsPositiveOrZeroSmiConst(Definition* d) {
- ConstantInstr* const_instr = d->AsConstant();
- if ((const_instr != NULL) && (const_instr->value().IsSmi())) {
- return Smi::Cast(const_instr->value()).Value() >= 0;
- }
- return false;
-}
-
-
-void AotOptimizer::OptimizeLeftShiftBitAndSmiOp(
- Definition* bit_and_instr,
- Definition* left_instr,
- Definition* right_instr) {
- ASSERT(bit_and_instr != NULL);
- ASSERT((left_instr != NULL) && (right_instr != NULL));
-
- // Check for pattern, smi_shift_left must be single-use.
- bool is_positive_or_zero = IsPositiveOrZeroSmiConst(left_instr);
- if (!is_positive_or_zero) {
- is_positive_or_zero = IsPositiveOrZeroSmiConst(right_instr);
- }
- if (!is_positive_or_zero) return;
-
- BinarySmiOpInstr* smi_shift_left = NULL;
- if (bit_and_instr->InputAt(0)->IsSingleUse()) {
- smi_shift_left = AsSmiShiftLeftInstruction(left_instr);
- }
- if ((smi_shift_left == NULL) && (bit_and_instr->InputAt(1)->IsSingleUse())) {
- smi_shift_left = AsSmiShiftLeftInstruction(right_instr);
- }
- if (smi_shift_left == NULL) return;
-
- // Pattern recognized.
- smi_shift_left->mark_truncating();
- ASSERT(bit_and_instr->IsBinarySmiOp() || bit_and_instr->IsBinaryMintOp());
- if (bit_and_instr->IsBinaryMintOp()) {
- // Replace Mint op with Smi op.
- BinarySmiOpInstr* smi_op = new(Z) BinarySmiOpInstr(
- Token::kBIT_AND,
- new(Z) Value(left_instr),
- new(Z) Value(right_instr),
- Thread::kNoDeoptId); // BIT_AND cannot deoptimize.
- bit_and_instr->ReplaceWith(smi_op, current_iterator());
- }
-}
-
-
-void AotOptimizer::AppendExtractNthOutputForMerged(Definition* instr,
- intptr_t index,
- Representation rep,
- intptr_t cid) {
- ExtractNthOutputInstr* extract =
- new(Z) ExtractNthOutputInstr(new(Z) Value(instr), index, rep, cid);
- instr->ReplaceUsesWith(extract);
- flow_graph()->InsertAfter(instr, extract, NULL, FlowGraph::kValue);
-}
-
-
-// Dart:
-// var x = d % 10;
-// var y = d ~/ 10;
-// var z = x + y;
-//
-// IL:
-// v4 <- %(v2, v3)
-// v5 <- ~/(v2, v3)
-// v6 <- +(v4, v5)
-//
-// IL optimized:
-// v4 <- DIVMOD(v2, v3);
-// v5 <- LoadIndexed(v4, 0); // ~/ result
-// v6 <- LoadIndexed(v4, 1); // % result
-// v7 <- +(v5, v6)
-// Because of the environment it is important that merged instruction replaces
-// first original instruction encountered.
-void AotOptimizer::TryMergeTruncDivMod(
- GrowableArray<BinarySmiOpInstr*>* merge_candidates) {
- if (merge_candidates->length() < 2) {
- // Need at least a TRUNCDIV and a MOD.
- return;
- }
- for (intptr_t i = 0; i < merge_candidates->length(); i++) {
- BinarySmiOpInstr* curr_instr = (*merge_candidates)[i];
- if (curr_instr == NULL) {
- // Instruction was merged already.
- continue;
- }
- ASSERT((curr_instr->op_kind() == Token::kTRUNCDIV) ||
- (curr_instr->op_kind() == Token::kMOD));
- // Check if there is kMOD/kTRUNDIV binop with same inputs.
- const intptr_t other_kind = (curr_instr->op_kind() == Token::kTRUNCDIV) ?
- Token::kMOD : Token::kTRUNCDIV;
- Definition* left_def = curr_instr->left()->definition();
- Definition* right_def = curr_instr->right()->definition();
- for (intptr_t k = i + 1; k < merge_candidates->length(); k++) {
- BinarySmiOpInstr* other_binop = (*merge_candidates)[k];
- // 'other_binop' can be NULL if it was already merged.
- if ((other_binop != NULL) &&
- (other_binop->op_kind() == other_kind) &&
- (other_binop->left()->definition() == left_def) &&
- (other_binop->right()->definition() == right_def)) {
- (*merge_candidates)[k] = NULL; // Clear it.
- ASSERT(curr_instr->HasUses());
- AppendExtractNthOutputForMerged(
- curr_instr,
- MergedMathInstr::OutputIndexOf(curr_instr->op_kind()),
- kTagged, kSmiCid);
- ASSERT(other_binop->HasUses());
- AppendExtractNthOutputForMerged(
- other_binop,
- MergedMathInstr::OutputIndexOf(other_binop->op_kind()),
- kTagged, kSmiCid);
-
- ZoneGrowableArray<Value*>* args = new(Z) ZoneGrowableArray<Value*>(2);
- args->Add(new(Z) Value(curr_instr->left()->definition()));
- args->Add(new(Z) Value(curr_instr->right()->definition()));
-
- // Replace with TruncDivMod.
- MergedMathInstr* div_mod = new(Z) MergedMathInstr(
- args,
- curr_instr->deopt_id(),
- MergedMathInstr::kTruncDivMod);
- curr_instr->ReplaceWith(div_mod, current_iterator());
- other_binop->ReplaceUsesWith(div_mod);
- other_binop->RemoveFromGraph();
- // Only one merge possible. Because canonicalization happens later,
- // more candidates are possible.
- // TODO(srdjan): Allow merging of trunc-div/mod into truncDivMod.
- break;
- }
- }
- }
-}
-
-
-// Tries to merge MathUnary operations, in this case sinus and cosinus.
-void AotOptimizer::TryMergeMathUnary(
- GrowableArray<MathUnaryInstr*>* merge_candidates) {
- if (!FlowGraphCompiler::SupportsSinCos() || !CanUnboxDouble() ||
- !FLAG_merge_sin_cos) {
- return;
- }
- if (merge_candidates->length() < 2) {
- // Need at least a SIN and a COS.
- return;
- }
- for (intptr_t i = 0; i < merge_candidates->length(); i++) {
- MathUnaryInstr* curr_instr = (*merge_candidates)[i];
- if (curr_instr == NULL) {
- // Instruction was merged already.
- continue;
- }
- const intptr_t kind = curr_instr->kind();
- ASSERT((kind == MathUnaryInstr::kSin) ||
- (kind == MathUnaryInstr::kCos));
- // Check if there is sin/cos binop with same inputs.
- const intptr_t other_kind = (kind == MathUnaryInstr::kSin) ?
- MathUnaryInstr::kCos : MathUnaryInstr::kSin;
- Definition* def = curr_instr->value()->definition();
- for (intptr_t k = i + 1; k < merge_candidates->length(); k++) {
- MathUnaryInstr* other_op = (*merge_candidates)[k];
- // 'other_op' can be NULL if it was already merged.
- if ((other_op != NULL) && (other_op->kind() == other_kind) &&
- (other_op->value()->definition() == def)) {
- (*merge_candidates)[k] = NULL; // Clear it.
- ASSERT(curr_instr->HasUses());
- AppendExtractNthOutputForMerged(curr_instr,
- MergedMathInstr::OutputIndexOf(kind),
- kUnboxedDouble, kDoubleCid);
- ASSERT(other_op->HasUses());
- AppendExtractNthOutputForMerged(
- other_op,
- MergedMathInstr::OutputIndexOf(other_kind),
- kUnboxedDouble, kDoubleCid);
- ZoneGrowableArray<Value*>* args = new(Z) ZoneGrowableArray<Value*>(1);
- args->Add(new(Z) Value(curr_instr->value()->definition()));
- // Replace with SinCos.
- MergedMathInstr* sin_cos =
- new(Z) MergedMathInstr(args,
- curr_instr->DeoptimizationTarget(),
- MergedMathInstr::kSinCos);
- curr_instr->ReplaceWith(sin_cos, current_iterator());
- other_op->ReplaceUsesWith(sin_cos);
- other_op->RemoveFromGraph();
- // Only one merge possible. Because canonicalization happens later,
- // more candidates are possible.
- // TODO(srdjan): Allow merging of sin/cos into sincos.
- break;
- }
- }
- }
-}
-
-
-// Optimize (a << b) & c pattern: if c is a positive Smi or zero, then the
-// shift can be a truncating Smi shift-left and result is always Smi.
-// Merging occurs only per basic-block.
-void AotOptimizer::TryOptimizePatterns() {
- if (!FLAG_truncating_left_shift) return;
- ASSERT(current_iterator_ == NULL);
- GrowableArray<BinarySmiOpInstr*> div_mod_merge;
- GrowableArray<MathUnaryInstr*> sin_cos_merge;
- for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator();
- !block_it.Done();
- block_it.Advance()) {
- // Merging only per basic-block.
- div_mod_merge.Clear();
- sin_cos_merge.Clear();
- ForwardInstructionIterator it(block_it.Current());
- current_iterator_ = &it;
- for (; !it.Done(); it.Advance()) {
- if (it.Current()->IsBinarySmiOp()) {
- BinarySmiOpInstr* binop = it.Current()->AsBinarySmiOp();
- if (binop->op_kind() == Token::kBIT_AND) {
- OptimizeLeftShiftBitAndSmiOp(binop,
- binop->left()->definition(),
- binop->right()->definition());
- } else if ((binop->op_kind() == Token::kTRUNCDIV) ||
- (binop->op_kind() == Token::kMOD)) {
- if (binop->HasUses()) {
- div_mod_merge.Add(binop);
- }
- }
- } else if (it.Current()->IsBinaryMintOp()) {
- BinaryMintOpInstr* mintop = it.Current()->AsBinaryMintOp();
- if (mintop->op_kind() == Token::kBIT_AND) {
- OptimizeLeftShiftBitAndSmiOp(mintop,
- mintop->left()->definition(),
- mintop->right()->definition());
- }
- } else if (it.Current()->IsMathUnary()) {
- MathUnaryInstr* math_unary = it.Current()->AsMathUnary();
- if ((math_unary->kind() == MathUnaryInstr::kSin) ||
- (math_unary->kind() == MathUnaryInstr::kCos)) {
- if (math_unary->HasUses()) {
- sin_cos_merge.Add(math_unary);
- }
- }
- }
- }
- TryMergeTruncDivMod(&div_mod_merge);
- TryMergeMathUnary(&sin_cos_merge);
- current_iterator_ = NULL;
- }
-}
-
-
static bool ClassIdIsOneOf(intptr_t class_id,
const GrowableArray<intptr_t>& class_ids) {
for (intptr_t i = 0; i < class_ids.length(); i++) {
« no previous file with comments | « runtime/vm/aot_optimizer.h ('k') | runtime/vm/compiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698