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

Unified Diff: runtime/vm/flow_graph_optimizer.cc

Issue 345563007: Add Uint32 representation (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 5 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
Index: runtime/vm/flow_graph_optimizer.cc
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index 3eddfed877f518322c6946de1c925e75a0f0ef53..22765cbdaf8ac8db7ee204bab6c0890dedb3bbdf 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -44,6 +44,8 @@ DEFINE_FLAG(bool, trace_range_analysis, false, "Trace range analysis progress");
DEFINE_FLAG(bool, truncating_left_shift, true,
"Optimize left shift to truncate if possible");
DEFINE_FLAG(bool, use_cha, true, "Use class hierarchy analysis.");
+DEFINE_FLAG(bool, trace_integer_ir_selection, false,
+ "Print integer IR selection optimization pass.");
DECLARE_FLAG(bool, enable_type_checks);
DECLARE_FLAG(bool, source_lines);
DECLARE_FLAG(bool, trace_type_check_elimination);
@@ -608,10 +610,12 @@ void FlowGraphOptimizer::InsertConversion(Representation from,
const intptr_t deopt_id = (deopt_target != NULL) ?
deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId;
converted = new(I) UnboxIntegerInstr(use->CopyWithType(), deopt_id);
-
} else if ((from == kUnboxedMint) && (to == kTagged)) {
converted = new(I) BoxIntegerInstr(use->CopyWithType());
-
+ } else if ((from == kUnboxedMint) && (to == kUnboxedUint32)) {
+ converted = new(I) UnboxedIntConverterInstr(from, to, use->CopyWithType());
+ } else if ((from == kUnboxedUint32) && (to == kUnboxedMint)) {
+ converted = new(I) UnboxedIntConverterInstr(from, to, use->CopyWithType());
} else if (from == kUnboxedMint && to == kUnboxedDouble) {
ASSERT(CanUnboxDouble());
// Convert by boxing/unboxing.
@@ -5147,6 +5151,292 @@ void FlowGraphOptimizer::InferIntRanges() {
}
+// Replaces Mint IL instructions with Uint32 IL instructions
+// when possible. Uses output of RangeAnalysis.
+class IntegerInstructionSelector : public ValueObject {
+ public:
+ explicit IntegerInstructionSelector(FlowGraph* flow_graph)
+ : flow_graph_(flow_graph),
+ isolate_(NULL),
+ changed_(true) {
+ ASSERT(flow_graph_ != NULL);
+ isolate_ = flow_graph_->isolate();
+ ASSERT(isolate_ != NULL);
+ selected_uint32_defs_ =
+ new(I) BitVector(flow_graph_->current_ssa_temp_index());
+ }
+
+ void Select();
+
+ private:
+ bool IsPotentialUint32Definition(Definition* def);
+ void FindPotentialUint32Definitions();
+ bool IsUint32NarrowingDefinition(Definition* def);
+ void FindUint32NarrowingDefinitions();
+ bool CanBecomeUint32(Definition* def);
+ void Propagate();
+ Definition* ConstructReplacementFor(Definition* def);
+ void ReplaceInstructions();
+
+ Isolate* isolate() const { return isolate_; }
+
+ GrowableArray<Definition*> potential_uint32_defs_;
+ BitVector* selected_uint32_defs_;
+
+ FlowGraph* flow_graph_;
+ Isolate* isolate_;
+ bool changed_;
+};
+
+
+void IntegerInstructionSelector::Select() {
+ if (FLAG_trace_integer_ir_selection) {
+ OS::Print("---- starting integer ir selection -------\n");
+ }
+ FindPotentialUint32Definitions();
+ FindUint32NarrowingDefinitions();
+ Propagate();
+ ReplaceInstructions();
+ if (FLAG_trace_integer_ir_selection) {
+ OS::Print("---- after integer ir selection -------\n");
+ FlowGraphPrinter printer(*flow_graph_);
+ printer.PrintBlocks();
+ }
+}
+
+
+bool IntegerInstructionSelector::IsPotentialUint32Definition(Definition* def) {
+ // TODO(johnmccutchan): Consider Smi operations, to avoid unnecessary tagging
+ // & untagged of intermediate results.
+ return def->IsBoxInteger() || // BoxMint.
+ def->IsUnboxInteger() || // UnboxMint.
+ def->IsBinaryMintOp() ||
+ def->IsShiftMintOp() ||
+ def->IsUnaryMintOp();
+}
+
+
+void IntegerInstructionSelector::FindPotentialUint32Definitions() {
+ if (FLAG_trace_integer_ir_selection) {
+ OS::Print("++++ Finding potential Uint32 definitions:\n");
+ }
+
+ for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator();
+ !block_it.Done();
+ block_it.Advance()) {
+ BlockEntryInstr* block = block_it.Current();
+
+ for (ForwardInstructionIterator instr_it(block);
+ !instr_it.Done();
+ instr_it.Advance()) {
+ Instruction* current = instr_it.Current();
+ Definition* defn = current->AsDefinition();
+ if ((defn != NULL) && (defn->ssa_temp_index() != -1)) {
+ if (IsPotentialUint32Definition(defn)) {
+ if (FLAG_trace_integer_ir_selection) {
+ OS::Print("Adding %s\n", current->ToCString());
+ }
+ potential_uint32_defs_.Add(defn);
+ }
+ }
+ }
+ }
+}
+
+
+// BinaryMintOp masks and stores into unsigned typed arrays that truncate the
+// value into a Uint32 range.
+bool IntegerInstructionSelector::IsUint32NarrowingDefinition(Definition* def) {
+ if (def->IsBinaryMintOp()) {
+ BinaryMintOpInstr* op = def->AsBinaryMintOp();
+ // Must be a mask operation.
+ if (op->op_kind() != Token::kBIT_AND) {
+ return false;
+ }
+ Range* range = op->range();
+ if ((range == NULL) ||
+ !range->IsWithin(0, static_cast<int64_t>(kMaxUint32))) {
+ return false;
+ }
+ return true;
+ }
+ // TODO(johnmccutchan): Add typed array stores.
+ return false;
+}
+
+
+void IntegerInstructionSelector::FindUint32NarrowingDefinitions() {
+ ASSERT(selected_uint32_defs_ != NULL);
+ if (FLAG_trace_integer_ir_selection) {
+ OS::Print("++++ Selecting Uint32 definitions:\n");
+ OS::Print("++++ Initial set:\n");
+ }
+ for (intptr_t i = 0; i < potential_uint32_defs_.length(); i++) {
+ Definition* defn = potential_uint32_defs_[i];
+ if (IsUint32NarrowingDefinition(defn)) {
+ if (FLAG_trace_integer_ir_selection) {
+ OS::Print("Adding %s\n", defn->ToCString());
+ }
+ selected_uint32_defs_->Add(defn->ssa_temp_index());
+ }
+ }
+}
+
+
+bool IntegerInstructionSelector::CanBecomeUint32(Definition* def) {
+ ASSERT(IsPotentialUint32Definition(def));
+ if (def->IsBoxInteger()) {
+ // If a BoxInteger's input is a candidate, the box is a candidate.
+ BoxIntegerInstr* box = def->AsBoxInteger();
+ Definition* box_input = box->value()->definition();
+ return selected_uint32_defs_->Contains(box_input->ssa_temp_index());
+ }
+ // A right shift with an input outside of Uint32 range cannot be converted
+ // because we need the high bits.
+ if (def->IsShiftMintOp()) {
+ ShiftMintOpInstr* op = def->AsShiftMintOp();
+ if (op->op_kind() == Token::kSHR) {
+ Definition* shift_input = op->left()->definition();
+ ASSERT(shift_input != NULL);
+ Range* range = shift_input->range();
+ if ((range == NULL) ||
+ !range->IsWithin(0, static_cast<int64_t>(kMaxUint32))) {
+ return false;
+ }
+ }
+ }
+ if (!def->HasUses()) {
+ // No uses, skip.
+ return false;
+ }
+ // All input uses are candidates.
+ for (Value* use = def->input_use_list(); use != NULL; use = use->next_use()) {
Florian Schneider 2014/07/10 13:05:05 Use Value::Iterator for iterating the use list.
Cutch 2014/07/10 17:12:53 Done.
+ Definition* defn = use->instruction()->AsDefinition();
+ if ((defn == NULL) ||
+ (defn->ssa_temp_index() == -1) ||
+ !selected_uint32_defs_->Contains(defn->ssa_temp_index())) {
+ return false;
+ }
+ }
+
+ // All environment uses are candidates.
+ for (Value* use = def->env_use_list(); use != NULL; use = use->next_use()) {
Florian Schneider 2014/07/10 13:05:05 Use Value::Iterator for iterating the use list.
Cutch 2014/07/10 17:12:53 Done.
+ Definition* defn = use->instruction()->AsDefinition();
+ if ((defn == NULL) ||
+ (defn->ssa_temp_index() == -1) ||
+ !selected_uint32_defs_->Contains(defn->ssa_temp_index())) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+void IntegerInstructionSelector::Propagate() {
+ ASSERT(selected_uint32_defs_ != NULL);
+ ASSERT(changed_);
+ intptr_t iteration = 0;
+ while (changed_) {
+ if (FLAG_trace_integer_ir_selection) {
+ OS::Print("+++ Iteration: %" Pd "\n", iteration++);
+ }
+ changed_ = false;
+ for (intptr_t i = 0; i < potential_uint32_defs_.length(); i++) {
+ Definition* defn = potential_uint32_defs_[i];
+ if (selected_uint32_defs_->Contains(defn->ssa_temp_index())) {
+ // Already marked as a candidate, skip.
+ continue;
+ }
+ if (defn->IsConstant()) {
+ // Skip constants.
+ continue;
+ }
+ if (CanBecomeUint32(defn)) {
+ if (FLAG_trace_integer_ir_selection) {
+ OS::Print("Adding %s\n", defn->ToCString());
+ }
+ // Found a new candidate.
+ selected_uint32_defs_->Add(defn->ssa_temp_index());
+ // Haven't reached fixed point yet.
+ changed_ = true;
+ }
+ }
+ }
+ if (FLAG_trace_integer_ir_selection) {
+ OS::Print("Reached fixed point\n");
+ }
+}
+
+
+Definition* IntegerInstructionSelector::ConstructReplacementFor(
+ Definition* def) {
+ // Should only see mint definitions.
+ ASSERT(IsPotentialUint32Definition(def));
+ // Should not see constant instructions.
+ ASSERT(!def->IsConstant());
+ if (def->IsBinaryMintOp()) {
+ BinaryMintOpInstr* op = def->AsBinaryMintOp();
+ Token::Kind op_kind = op->op_kind();
+ Value* left = op->left()->CopyWithType();
+ Value* right = op->right()->CopyWithType();
+ intptr_t deopt_id = op->DeoptimizationTarget();
+ return new(I) BinaryUint32OpInstr(op_kind, left, right, deopt_id);
+ } else if (def->IsBoxInteger()) {
+ BoxIntegerInstr* box = def->AsBoxInteger();
+ Value* value = box->value()->CopyWithType();
+ return new(I) BoxUint32Instr(value);
+ } else if (def->IsUnboxInteger()) {
+ UnboxIntegerInstr* unbox = def->AsUnboxInteger();
+ Value* value = unbox->value()->CopyWithType();
+ intptr_t deopt_id = unbox->deopt_id();
+ return new(I) UnboxUint32Instr(value, deopt_id);
+ } else if (def->IsUnaryMintOp()) {
+ UnaryMintOpInstr* op = def->AsUnaryMintOp();
+ Token::Kind op_kind = op->op_kind();
+ Value* value = op->value()->CopyWithType();
+ intptr_t deopt_id = op->DeoptimizationTarget();
+ return new(I) UnaryUint32OpInstr(op_kind, value, deopt_id);
+ } else if (def->IsShiftMintOp()) {
+ ShiftMintOpInstr* op = def->AsShiftMintOp();
+ Token::Kind op_kind = op->op_kind();
+ Value* left = op->left()->CopyWithType();
+ Value* right = op->right()->CopyWithType();
+ intptr_t deopt_id = op->DeoptimizationTarget();
+ return new(I) ShiftUint32OpInstr(op_kind, left, right, deopt_id);
+ }
+ UNREACHABLE();
+ return NULL;
+}
+
+
+void IntegerInstructionSelector::ReplaceInstructions() {
+ if (FLAG_trace_integer_ir_selection) {
+ OS::Print("++++ Replacing instructions:\n");
+ }
+ for (intptr_t i = 0; i < potential_uint32_defs_.length(); i++) {
+ Definition* defn = potential_uint32_defs_[i];
+ if (!selected_uint32_defs_->Contains(defn->ssa_temp_index())) {
+ // Not a candidate.
+ continue;
+ }
+ Definition* replacement = ConstructReplacementFor(defn);
+ ASSERT(replacement != NULL);
+ if (FLAG_trace_integer_ir_selection) {
+ OS::Print("Replacing %s with %s\n", defn->ToCString(),
+ replacement->ToCString());
+ }
+ defn->ReplaceWith(replacement, NULL);
+ ASSERT(flow_graph_->VerifyUseLists());
+ }
+}
+
+void FlowGraphOptimizer::SelectIntegerInstructions() {
+ IntegerInstructionSelector iis(flow_graph_);
+ iis.Select();
+}
+
+
void TryCatchAnalyzer::Optimize(FlowGraph* flow_graph) {
// For every catch-block: Iterate over all call instructions inside the
// corresponding try-block and figure out for each environment value if it
@@ -8917,6 +9207,40 @@ void ConstantPropagator::VisitBoxInt32x4(BoxInt32x4Instr* instr) {
}
+void ConstantPropagator::VisitBoxUint32(BoxUint32Instr* instr) {
+ // TODO(kmillikin): Handle box operation.
+ SetValue(instr, non_constant_);
+}
+
+
+void ConstantPropagator::VisitUnboxUint32(UnboxUint32Instr* instr) {
+ // TODO(kmillikin): Handle unbox operation.
+ SetValue(instr, non_constant_);
+}
+
+
+void ConstantPropagator::VisitUnboxedIntConverter(
+ UnboxedIntConverterInstr* instr) {
+ SetValue(instr, non_constant_);
+}
+
+
+void ConstantPropagator::VisitBinaryUint32Op(BinaryUint32OpInstr* instr) {
+ HandleBinaryOp(instr, instr->op_kind(), *instr->left(), *instr->right());
+}
+
+
+void ConstantPropagator::VisitShiftUint32Op(ShiftUint32OpInstr* instr) {
+ HandleBinaryOp(instr, instr->op_kind(), *instr->left(), *instr->right());
+}
+
+
+void ConstantPropagator::VisitUnaryUint32Op(UnaryUint32OpInstr* instr) {
+ // TODO(kmillikin): Handle unary operations.
+ SetValue(instr, non_constant_);
+}
+
+
void ConstantPropagator::Analyze() {
GraphEntryInstr* entry = graph_->graph_entry();
reachable_->Add(entry->preorder_number());

Powered by Google App Engine
This is Rietveld 408576698