Index: runtime/vm/flow_graph_optimizer.cc |
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc |
index 1160b9f9bc53148aa4af538e99925cfb3224466e..46cb2cdb91a4d4ca161fef8c2f51ebe0eb82a399 100644 |
--- a/runtime/vm/flow_graph_optimizer.cc |
+++ b/runtime/vm/flow_graph_optimizer.cc |
@@ -267,6 +267,81 @@ static bool IsPositiveOrZeroSmiConst(Definition* d) { |
} |
+Definition* FlowGraphOptimizer::OptimizeMint32BitMasks( |
+ BinaryMintOpInstr* mask) { |
+ ASSERT(mask != NULL); |
+ ASSERT(mask->op_kind() == Token::kBIT_AND); |
+ Range* range = mask->range(); |
+ if ((range == NULL) || !range->Is32BitMask()) { |
Florian Schneider
2014/06/25 11:36:00
This should work for any positive mask value, not
|
+ // No range or range is not exactly [0, 0xFFFFFFFF]. |
+ return NULL; |
+ } |
+ // Find the mask target by looking for the input that isn't the constant |
+ // 0xFFFFFFFF. |
+ Value* target = NULL; |
+ if (mask->InputAt(0)->BindsTo32BitMaskConstant()) { |
+ target = mask->InputAt(1); |
+ } else if (mask->InputAt(1)->BindsTo32BitMaskConstant()) { |
+ target = mask->InputAt(0); |
+ } else { |
+ return NULL; |
+ } |
+ // If the target has multiple uses, we can't assume its range can be safely |
+ // constrained by this mask. |
+ if (!target->IsSingleUse()) { |
Florian Schneider
2014/06/25 11:36:00
That's too strict: It's ok as long as target is ma
|
+ return NULL; |
+ } |
+ |
+ Definition* def = target->definition(); |
+ if (!def->IsMintDefinition()) { |
+ // TODO(johnmccutchan): Should this be an ASSERT? |
+ return NULL; |
+ } |
+ def->range()->Make32BitMask(); |
+ |
+ return def; |
+} |
+ |
+ |
+bool FlowGraphOptimizer::TryMarkMint32Bit(Definition* mintop) { |
+ ASSERT(mintop != NULL); |
+ ASSERT(mintop->IsMintDefinition()); |
+ |
+ Range* range = mintop->range(); |
+ if (range == NULL) { |
+ return false; |
+ } |
+ bool is_32_bit = false; |
+ if (range->Is32BitMask()) { |
+ is_32_bit = true; |
+ } else if (range->IsWithin(0, kMaxUint32)) { |
+ is_32_bit = true; |
+ } |
+ |
+ if (!is_32_bit) { |
+ return false; |
+ } |
+ |
+ if (mintop->IsBinaryMintOp()) { |
+ BinaryMintOpInstr* instr = mintop->AsBinaryMintOp(); |
+ instr->set_is_32_bit(true); |
+ } else if (mintop->IsShiftMintOp()) { |
+ ShiftMintOpInstr* instr = mintop->AsShiftMintOp(); |
+ instr->set_is_32_bit(true); |
+ } else if (mintop->IsUnboxInteger()) { |
+ UnboxIntegerInstr* instr = mintop->AsUnboxInteger(); |
+ instr->set_is_32_bit(true); |
+ } else if (mintop->IsUnaryMintOp()) { |
+ UnaryMintOpInstr* instr = mintop->AsUnaryMintOp(); |
+ instr->set_is_32_bit(true); |
+ } else { |
+ return false; |
+ } |
+ |
+ return true; |
+} |
+ |
+ |
void FlowGraphOptimizer::OptimizeLeftShiftBitAndSmiOp( |
Definition* bit_and_instr, |
Definition* left_instr, |
@@ -279,7 +354,9 @@ void FlowGraphOptimizer::OptimizeLeftShiftBitAndSmiOp( |
if (!is_positive_or_zero) { |
is_positive_or_zero = IsPositiveOrZeroSmiConst(right_instr); |
} |
- if (!is_positive_or_zero) return; |
+ if (!is_positive_or_zero) { |
+ return; |
+ } |
BinarySmiOpInstr* smi_shift_left = NULL; |
if (bit_and_instr->InputAt(0)->IsSingleUse()) { |
@@ -288,7 +365,9 @@ void FlowGraphOptimizer::OptimizeLeftShiftBitAndSmiOp( |
if ((smi_shift_left == NULL) && (bit_and_instr->InputAt(1)->IsSingleUse())) { |
smi_shift_left = AsSmiShiftLeftInstruction(right_instr); |
} |
- if (smi_shift_left == NULL) return; |
+ if (smi_shift_left == NULL) { |
+ return; |
+ } |
// Pattern recognized. |
smi_shift_left->set_is_truncating(true); |
@@ -525,7 +604,6 @@ void FlowGraphOptimizer::TryOptimizePatterns() { |
} |
} |
- |
static void EnsureSSATempIndex(FlowGraph* graph, |
Definition* defn, |
Definition* replacement) { |
@@ -564,6 +642,58 @@ static void ReplaceCurrentInstruction(ForwardInstructionIterator* iterator, |
} |
+void FlowGraphOptimizer::TryRangeDerivedOptimizations() { |
+ ASSERT(current_iterator_ == NULL); |
+ |
+ for (intptr_t i = 0; i < block_order_.length(); ++i) { |
+ BlockEntryInstr* entry = block_order_[i]; |
+ // First set range information on inputs to a mint mask. The following two |
+ // patterns are supported: |
+ // v7 & 0xFFFFFFFF; |
+ // 0xFFFFFFFF & v7; |
+ // Afterwards, if v7 only has a single use, v7 is marked as having |
+ // a 32-bit range. Also, the mask operation is removed. |
+ { |
+ ForwardInstructionIterator it(entry); |
+ current_iterator_ = ⁢ |
+ for (; !it.Done(); it.Advance()) { |
+ // Constrain ranges of mint operations whose only use is a mint mask op. |
+ if (it.Current()->IsBinaryMintOp()) { |
+ BinaryMintOpInstr* mintop = it.Current()->AsBinaryMintOp(); |
+ if (mintop->op_kind() == Token::kBIT_AND) { |
+ Definition* masked = OptimizeMint32BitMasks(mintop); |
+ if (masked != NULL) { |
+ // Replace mask instruction with masked input. |
+ ReplaceCurrentInstruction(current_iterator(), |
+ mintop, |
+ masked, |
+ flow_graph()); |
+ } |
+ } |
+ } |
+ } |
+ current_iterator_ = NULL; |
+ } |
+ // Mark mint instructions whose range information says they are positive |
+ // and fit in 32-bits as 32-bit. |
+ { |
+ ForwardInstructionIterator it(entry); |
+ current_iterator_ = ⁢ |
+ for (; !it.Done(); it.Advance()) { |
+ if (!it.Current()->IsDefinition()) { |
+ continue; |
+ } |
+ Definition* def = it.Current()->AsDefinition(); |
+ if (def->IsMintDefinition()) { |
+ TryMarkMint32Bit(def); |
+ } |
+ } |
+ current_iterator_ = NULL; |
+ } |
+ } |
+} |
+ |
+ |
bool FlowGraphOptimizer::Canonicalize() { |
bool changed = false; |
for (intptr_t i = 0; i < block_order_.length(); ++i) { |
@@ -611,7 +741,12 @@ void FlowGraphOptimizer::InsertConversion(Representation from, |
} else if ((from == kUnboxedMint) && (to == kTagged)) { |
converted = new(I) BoxIntegerInstr(use->CopyWithType()); |
- |
+ } else if ((from == kUnboxedMint) && (to == kUnboxedMint32)) { |
+ converted = new(I) MintConverterInstr(MintConverterInstr::kMintToMint32, |
+ use->CopyWithType()); |
+ } else if ((from == kUnboxedMint32) && (to == kUnboxedMint)) { |
+ converted = new(I) MintConverterInstr(MintConverterInstr::kMint32ToMint, |
+ use->CopyWithType()); |
} else if (from == kUnboxedMint && to == kUnboxedDouble) { |
ASSERT(CanUnboxDouble()); |
// Convert by boxing/unboxing. |
@@ -8502,6 +8637,11 @@ void ConstantPropagator::VisitBinaryMintOp(BinaryMintOpInstr* instr) { |
} |
+void ConstantPropagator::VisitMintConverter(MintConverterInstr* instr) { |
+ SetValue(instr, non_constant_); |
+} |
+ |
+ |
void ConstantPropagator::VisitShiftMintOp(ShiftMintOpInstr* instr) { |
HandleBinaryOp(instr, instr->op_kind(), *instr->left(), *instr->right()); |
} |