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

Unified Diff: runtime/vm/flow_graph_optimizer.cc

Issue 820883004: Move ConstantPropagator from flow_graph_optimizer.cc/.h into separate files. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years 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/flow_graph_optimizer.h ('k') | runtime/vm/intermediate_language.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/flow_graph_optimizer.cc
===================================================================
--- runtime/vm/flow_graph_optimizer.cc (revision 42566)
+++ runtime/vm/flow_graph_optimizer.cc (working copy)
@@ -33,9 +33,6 @@
DEFINE_FLAG(int, max_equality_polymorphic_checks, 32,
"Maximum number of polymorphic checks in equality operator,"
" otherwise use megamorphic dispatch.");
-DEFINE_FLAG(bool, remove_redundant_phis, true, "Remove redundant phis.");
-DEFINE_FLAG(bool, trace_constant_propagation, false,
- "Print constant propagation and useless code elimination.");
DEFINE_FLAG(bool, trace_load_optimization, false,
"Print live sets for load optimization pass.");
DEFINE_FLAG(bool, trace_optimization, false, "Print optimization details.");
@@ -7500,1619 +7497,6 @@
}
-ConstantPropagator::ConstantPropagator(
- FlowGraph* graph,
- const GrowableArray<BlockEntryInstr*>& ignored)
- : FlowGraphVisitor(ignored),
- graph_(graph),
- unknown_(Object::unknown_constant()),
- non_constant_(Object::non_constant()),
- reachable_(new(graph->isolate()) BitVector(
- graph->isolate(), graph->preorder().length())),
- marked_phis_(new(graph->isolate()) BitVector(
- graph->isolate(), graph->max_virtual_register_number())),
- block_worklist_(),
- definition_worklist_(graph, 10) {}
-
-
-void ConstantPropagator::Optimize(FlowGraph* graph) {
- GrowableArray<BlockEntryInstr*> ignored;
- ConstantPropagator cp(graph, ignored);
- cp.Analyze();
- cp.Transform();
-}
-
-
-void ConstantPropagator::OptimizeBranches(FlowGraph* graph) {
- GrowableArray<BlockEntryInstr*> ignored;
- ConstantPropagator cp(graph, ignored);
- cp.Analyze();
- cp.Transform();
- cp.EliminateRedundantBranches();
-}
-
-
-void ConstantPropagator::SetReachable(BlockEntryInstr* block) {
- if (!reachable_->Contains(block->preorder_number())) {
- reachable_->Add(block->preorder_number());
- block_worklist_.Add(block);
- }
-}
-
-
-bool ConstantPropagator::SetValue(Definition* definition, const Object& value) {
- // We would like to assert we only go up (toward non-constant) in the lattice.
- //
- // ASSERT(IsUnknown(definition->constant_value()) ||
- // IsNonConstant(value) ||
- // (definition->constant_value().raw() == value.raw()));
- //
- // But the final disjunct is not true (e.g., mint or double constants are
- // heap-allocated and so not necessarily pointer-equal on each iteration).
- if (definition->constant_value().raw() != value.raw()) {
- definition->constant_value() = value.raw();
- if (definition->input_use_list() != NULL) {
- definition_worklist_.Add(definition);
- }
- return true;
- }
- return false;
-}
-
-
-// Compute the join of two values in the lattice, assign it to the first.
-void ConstantPropagator::Join(Object* left, const Object& right) {
- // Join(non-constant, X) = non-constant
- // Join(X, unknown) = X
- if (IsNonConstant(*left) || IsUnknown(right)) return;
-
- // Join(unknown, X) = X
- // Join(X, non-constant) = non-constant
- if (IsUnknown(*left) || IsNonConstant(right)) {
- *left = right.raw();
- return;
- }
-
- // Join(X, X) = X
- // TODO(kmillikin): support equality for doubles, mints, etc.
- if (left->raw() == right.raw()) return;
-
- // Join(X, Y) = non-constant
- *left = non_constant_.raw();
-}
-
-
-// --------------------------------------------------------------------------
-// Analysis of blocks. Called at most once per block. The block is already
-// marked as reachable. All instructions in the block are analyzed.
-void ConstantPropagator::VisitGraphEntry(GraphEntryInstr* block) {
- const GrowableArray<Definition*>& defs = *block->initial_definitions();
- for (intptr_t i = 0; i < defs.length(); ++i) {
- defs[i]->Accept(this);
- }
- ASSERT(ForwardInstructionIterator(block).Done());
-
- // TODO(fschneider): Improve this approximation. The catch entry is only
- // reachable if a call in the try-block is reachable.
- for (intptr_t i = 0; i < block->SuccessorCount(); ++i) {
- SetReachable(block->SuccessorAt(i));
- }
-}
-
-
-void ConstantPropagator::VisitJoinEntry(JoinEntryInstr* block) {
- // Phis are visited when visiting Goto at a predecessor. See VisitGoto.
- for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
- it.Current()->Accept(this);
- }
-}
-
-
-void ConstantPropagator::VisitTargetEntry(TargetEntryInstr* block) {
- for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
- it.Current()->Accept(this);
- }
-}
-
-
-void ConstantPropagator::VisitIndirectEntry(IndirectEntryInstr* block) {
- for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
- it.Current()->Accept(this);
- }
-}
-
-
-void ConstantPropagator::VisitCatchBlockEntry(CatchBlockEntryInstr* block) {
- const GrowableArray<Definition*>& defs = *block->initial_definitions();
- for (intptr_t i = 0; i < defs.length(); ++i) {
- defs[i]->Accept(this);
- }
- for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
- it.Current()->Accept(this);
- }
-}
-
-
-void ConstantPropagator::VisitParallelMove(ParallelMoveInstr* instr) {
- // Parallel moves have not yet been inserted in the graph.
- UNREACHABLE();
-}
-
-
-// --------------------------------------------------------------------------
-// Analysis of control instructions. Unconditional successors are
-// reachable. Conditional successors are reachable depending on the
-// constant value of the condition.
-void ConstantPropagator::VisitReturn(ReturnInstr* instr) {
- // Nothing to do.
-}
-
-
-void ConstantPropagator::VisitThrow(ThrowInstr* instr) {
- // Nothing to do.
-}
-
-
-void ConstantPropagator::VisitReThrow(ReThrowInstr* instr) {
- // Nothing to do.
-}
-
-
-void ConstantPropagator::VisitGoto(GotoInstr* instr) {
- SetReachable(instr->successor());
-
- // Phi value depends on the reachability of a predecessor. We have
- // to revisit phis every time a predecessor becomes reachable.
- for (PhiIterator it(instr->successor()); !it.Done(); it.Advance()) {
- it.Current()->Accept(this);
- }
-}
-
-
-void ConstantPropagator::VisitIndirectGoto(IndirectGotoInstr* instr) {
- for (intptr_t i = 0; i < instr->SuccessorCount(); i++) {
- SetReachable(instr->SuccessorAt(i));
- }
-}
-
-
-void ConstantPropagator::VisitBranch(BranchInstr* instr) {
- instr->comparison()->Accept(this);
-
- // The successors may be reachable, but only if this instruction is. (We
- // might be analyzing it because the constant value of one of its inputs
- // has changed.)
- if (reachable_->Contains(instr->GetBlock()->preorder_number())) {
- if (instr->constant_target() != NULL) {
- ASSERT((instr->constant_target() == instr->true_successor()) ||
- (instr->constant_target() == instr->false_successor()));
- SetReachable(instr->constant_target());
- } else {
- const Object& value = instr->comparison()->constant_value();
- if (IsNonConstant(value)) {
- SetReachable(instr->true_successor());
- SetReachable(instr->false_successor());
- } else if (value.raw() == Bool::True().raw()) {
- SetReachable(instr->true_successor());
- } else if (!IsUnknown(value)) { // Any other constant.
- SetReachable(instr->false_successor());
- }
- }
- }
-}
-
-
-// --------------------------------------------------------------------------
-// Analysis of non-definition instructions. They do not have values so they
-// cannot have constant values.
-void ConstantPropagator::VisitCheckStackOverflow(
- CheckStackOverflowInstr* instr) { }
-
-
-void ConstantPropagator::VisitCheckClass(CheckClassInstr* instr) { }
-
-
-void ConstantPropagator::VisitCheckClassId(CheckClassIdInstr* instr) { }
-
-
-void ConstantPropagator::VisitGuardFieldClass(GuardFieldClassInstr* instr) { }
-
-
-void ConstantPropagator::VisitGuardFieldLength(GuardFieldLengthInstr* instr) { }
-
-
-void ConstantPropagator::VisitCheckSmi(CheckSmiInstr* instr) { }
-
-
-void ConstantPropagator::VisitCheckEitherNonSmi(
- CheckEitherNonSmiInstr* instr) { }
-
-
-void ConstantPropagator::VisitCheckArrayBound(CheckArrayBoundInstr* instr) { }
-
-
-void ConstantPropagator::VisitDeoptimize(DeoptimizeInstr* instr) {
- // TODO(vegorov) remove all code after DeoptimizeInstr as dead.
-}
-
-
-Definition* ConstantPropagator::UnwrapPhi(Definition* defn) {
- if (defn->IsPhi()) {
- JoinEntryInstr* block = defn->AsPhi()->block();
-
- Definition* input = NULL;
- for (intptr_t i = 0; i < defn->InputCount(); ++i) {
- if (reachable_->Contains(block->PredecessorAt(i)->preorder_number())) {
- if (input == NULL) {
- input = defn->InputAt(i)->definition();
- } else {
- return defn;
- }
- }
- }
-
- return input;
- }
-
- return defn;
-}
-
-
-void ConstantPropagator::MarkPhi(Definition* phi) {
- ASSERT(phi->IsPhi());
- marked_phis_->Add(phi->ssa_temp_index());
-}
-
-
-// --------------------------------------------------------------------------
-// Analysis of definitions. Compute the constant value. If it has changed
-// and the definition has input uses, add the definition to the definition
-// worklist so that the used can be processed.
-void ConstantPropagator::VisitPhi(PhiInstr* instr) {
- // Compute the join over all the reachable predecessor values.
- JoinEntryInstr* block = instr->block();
- Object& value = Object::ZoneHandle(I, Unknown());
- for (intptr_t pred_idx = 0; pred_idx < instr->InputCount(); ++pred_idx) {
- if (reachable_->Contains(
- block->PredecessorAt(pred_idx)->preorder_number())) {
- Join(&value,
- instr->InputAt(pred_idx)->definition()->constant_value());
- }
- }
- if (!SetValue(instr, value) &&
- marked_phis_->Contains(instr->ssa_temp_index())) {
- marked_phis_->Remove(instr->ssa_temp_index());
- definition_worklist_.Add(instr);
- }
-}
-
-
-void ConstantPropagator::VisitRedefinition(RedefinitionInstr* instr) {
- SetValue(instr, instr->value()->definition()->constant_value());
-}
-
-
-void ConstantPropagator::VisitParameter(ParameterInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitPushArgument(PushArgumentInstr* instr) {
- SetValue(instr, instr->value()->definition()->constant_value());
-}
-
-
-void ConstantPropagator::VisitAssertAssignable(AssertAssignableInstr* instr) {
- const Object& value = instr->value()->definition()->constant_value();
- if (IsNonConstant(value)) {
- SetValue(instr, non_constant_);
- } else if (IsConstant(value)) {
- // We are ignoring the instantiator and instantiator_type_arguments, but
- // still monotonic and safe.
- if (instr->value()->Type()->IsAssignableTo(instr->dst_type())) {
- SetValue(instr, value);
- } else {
- SetValue(instr, non_constant_);
- }
- }
-}
-
-
-void ConstantPropagator::VisitAssertBoolean(AssertBooleanInstr* instr) {
- const Object& value = instr->value()->definition()->constant_value();
- if (IsNonConstant(value)) {
- SetValue(instr, non_constant_);
- } else if (IsConstant(value)) {
- if (value.IsBool()) {
- SetValue(instr, value);
- } else {
- SetValue(instr, non_constant_);
- }
- }
-}
-
-
-void ConstantPropagator::VisitCurrentContext(CurrentContextInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitClosureCall(ClosureCallInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitInstanceCall(InstanceCallInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitPolymorphicInstanceCall(
- PolymorphicInstanceCallInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitStaticCall(StaticCallInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitLoadLocal(LoadLocalInstr* instr) {
- // Instruction is eliminated when translating to SSA.
- UNREACHABLE();
-}
-
-
-void ConstantPropagator::VisitPushTemp(PushTempInstr* instr) {
- // Instruction is eliminated when translating to SSA.
- UNREACHABLE();
-}
-
-
-void ConstantPropagator::VisitDropTemps(DropTempsInstr* instr) {
- // Instruction is eliminated when translating to SSA.
- UNREACHABLE();
-}
-
-
-void ConstantPropagator::VisitStoreLocal(StoreLocalInstr* instr) {
- // Instruction is eliminated when translating to SSA.
- UNREACHABLE();
-}
-
-
-void ConstantPropagator::VisitIfThenElse(IfThenElseInstr* instr) {
- instr->comparison()->Accept(this);
- const Object& value = instr->comparison()->constant_value();
- if (IsNonConstant(value)) {
- SetValue(instr, non_constant_);
- } else if (IsConstant(value)) {
- ASSERT(!value.IsNull());
- ASSERT(value.IsBool());
- bool result = Bool::Cast(value).value();
- SetValue(instr,
- Smi::Handle(I, Smi::New(
- result ? instr->if_true() : instr->if_false())));
- }
-}
-
-
-void ConstantPropagator::VisitStrictCompare(StrictCompareInstr* instr) {
- Definition* left_defn = instr->left()->definition();
- Definition* right_defn = instr->right()->definition();
-
- Definition* unwrapped_left_defn = UnwrapPhi(left_defn);
- Definition* unwrapped_right_defn = UnwrapPhi(right_defn);
- if (unwrapped_left_defn == unwrapped_right_defn) {
- // Fold x === x, and x !== x to true/false.
- SetValue(instr, Bool::Get(instr->kind() == Token::kEQ_STRICT));
- if (unwrapped_left_defn != left_defn) {
- MarkPhi(left_defn);
- }
- if (unwrapped_right_defn != right_defn) {
- MarkPhi(right_defn);
- }
- return;
- }
-
- const Object& left = left_defn->constant_value();
- const Object& right = right_defn->constant_value();
- if (IsNonConstant(left) || IsNonConstant(right)) {
- // TODO(vegorov): incorporate nullability information into the lattice.
- if ((left.IsNull() && instr->right()->Type()->HasDecidableNullability()) ||
- (right.IsNull() && instr->left()->Type()->HasDecidableNullability())) {
- bool result = left.IsNull() ? instr->right()->Type()->IsNull()
- : instr->left()->Type()->IsNull();
- if (instr->kind() == Token::kNE_STRICT) {
- result = !result;
- }
- SetValue(instr, Bool::Get(result));
- } else {
- const intptr_t left_cid = instr->left()->Type()->ToCid();
- const intptr_t right_cid = instr->right()->Type()->ToCid();
- // If exact classes (cids) are known and they differ, the result
- // of strict compare can be computed.
- if ((left_cid != kDynamicCid) && (right_cid != kDynamicCid) &&
- (left_cid != right_cid)) {
- const bool result = (instr->kind() != Token::kEQ_STRICT);
- SetValue(instr, Bool::Get(result));
- } else {
- SetValue(instr, non_constant_);
- }
- }
- } else if (IsConstant(left) && IsConstant(right)) {
- bool result = (left.raw() == right.raw());
- if (instr->kind() == Token::kNE_STRICT) {
- result = !result;
- }
- SetValue(instr, Bool::Get(result));
- }
-}
-
-
-static bool CompareIntegers(Token::Kind kind,
- const Integer& left,
- const Integer& right) {
- const int result = left.CompareWith(right);
- switch (kind) {
- case Token::kEQ: return (result == 0);
- case Token::kNE: return (result != 0);
- case Token::kLT: return (result < 0);
- case Token::kGT: return (result > 0);
- case Token::kLTE: return (result <= 0);
- case Token::kGTE: return (result >= 0);
- default:
- UNREACHABLE();
- return false;
- }
-}
-
-
-void ConstantPropagator::VisitTestSmi(TestSmiInstr* instr) {
- const Object& left = instr->left()->definition()->constant_value();
- const Object& right = instr->right()->definition()->constant_value();
- if (IsNonConstant(left) || IsNonConstant(right)) {
- SetValue(instr, non_constant_);
- } else if (IsConstant(left) && IsConstant(right)) {
- if (left.IsInteger() && right.IsInteger()) {
- const bool result = CompareIntegers(
- instr->kind(),
- Integer::Handle(I, Integer::Cast(left).BitOp(Token::kBIT_AND,
- Integer::Cast(right))),
- Smi::Handle(I, Smi::New(0)));
- SetValue(instr, result ? Bool::True() : Bool::False());
- } else {
- SetValue(instr, non_constant_);
- }
- }
-}
-
-
-void ConstantPropagator::VisitTestCids(TestCidsInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitEqualityCompare(EqualityCompareInstr* instr) {
- Definition* left_defn = instr->left()->definition();
- Definition* right_defn = instr->right()->definition();
-
- if (RawObject::IsIntegerClassId(instr->operation_cid())) {
- // Fold x == x, and x != x to true/false for numbers comparisons.
- Definition* unwrapped_left_defn = UnwrapPhi(left_defn);
- Definition* unwrapped_right_defn = UnwrapPhi(right_defn);
- if (unwrapped_left_defn == unwrapped_right_defn) {
- // Fold x === x, and x !== x to true/false.
- SetValue(instr, Bool::Get(instr->kind() == Token::kEQ));
- if (unwrapped_left_defn != left_defn) {
- MarkPhi(left_defn);
- }
- if (unwrapped_right_defn != right_defn) {
- MarkPhi(right_defn);
- }
- return;
- }
- }
-
- const Object& left = left_defn->constant_value();
- const Object& right = right_defn->constant_value();
- if (IsNonConstant(left) || IsNonConstant(right)) {
- SetValue(instr, non_constant_);
- } else if (IsConstant(left) && IsConstant(right)) {
- if (left.IsInteger() && right.IsInteger()) {
- const bool result = CompareIntegers(instr->kind(),
- Integer::Cast(left),
- Integer::Cast(right));
- SetValue(instr, Bool::Get(result));
- } else if (left.IsString() && right.IsString()) {
- const bool result = String::Cast(left).Equals(String::Cast(right));
- SetValue(instr, Bool::Get((instr->kind() == Token::kEQ) == result));
- } else {
- SetValue(instr, non_constant_);
- }
- }
-}
-
-
-void ConstantPropagator::VisitRelationalOp(RelationalOpInstr* instr) {
- const Object& left = instr->left()->definition()->constant_value();
- const Object& right = instr->right()->definition()->constant_value();
- if (IsNonConstant(left) || IsNonConstant(right)) {
- SetValue(instr, non_constant_);
- } else if (IsConstant(left) && IsConstant(right)) {
- if (left.IsInteger() && right.IsInteger()) {
- const bool result = CompareIntegers(instr->kind(),
- Integer::Cast(left),
- Integer::Cast(right));
- SetValue(instr, Bool::Get(result));
- } else if (left.IsDouble() && right.IsDouble()) {
- // TODO(srdjan): Implement.
- SetValue(instr, non_constant_);
- } else {
- SetValue(instr, non_constant_);
- }
- }
-}
-
-
-void ConstantPropagator::VisitNativeCall(NativeCallInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitDebugStepCheck(DebugStepCheckInstr* instr) {
- // Nothing to do.
-}
-
-
-void ConstantPropagator::VisitStringFromCharCode(
- StringFromCharCodeInstr* instr) {
- const Object& o = instr->char_code()->definition()->constant_value();
- if (o.IsNull() || IsNonConstant(o)) {
- SetValue(instr, non_constant_);
- } else if (IsConstant(o)) {
- const intptr_t ch_code = Smi::Cast(o).Value();
- ASSERT(ch_code >= 0);
- if (ch_code < Symbols::kMaxOneCharCodeSymbol) {
- RawString** table = Symbols::PredefinedAddress();
- SetValue(instr, String::ZoneHandle(I, table[ch_code]));
- } else {
- SetValue(instr, non_constant_);
- }
- }
-}
-
-
-void ConstantPropagator::VisitStringToCharCode(StringToCharCodeInstr* instr) {
- const Object& o = instr->str()->definition()->constant_value();
- if (o.IsNull() || IsNonConstant(o)) {
- SetValue(instr, non_constant_);
- } else if (IsConstant(o)) {
- const String& str = String::Cast(o);
- const intptr_t result =
- (str.Length() == 1) ? static_cast<intptr_t>(str.CharAt(0)) : -1;
- SetValue(instr, Smi::ZoneHandle(I, Smi::New(result)));
- }
-}
-
-
-void ConstantPropagator::VisitStringInterpolate(StringInterpolateInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitLoadIndexed(LoadIndexedInstr* instr) {
- const Object& array_obj = instr->array()->definition()->constant_value();
- const Object& index_obj = instr->index()->definition()->constant_value();
- if (IsNonConstant(array_obj) || IsNonConstant(index_obj)) {
- SetValue(instr, non_constant_);
- } else if (IsConstant(array_obj) && IsConstant(index_obj)) {
- // Need index to be Smi and array to be either String or an immutable array.
- if (!index_obj.IsSmi()) {
- // Should not occur.
- SetValue(instr, non_constant_);
- return;
- }
- const intptr_t index = Smi::Cast(index_obj).Value();
- if (index >= 0) {
- if (array_obj.IsString()) {
- const String& str = String::Cast(array_obj);
- if (str.Length() > index) {
- SetValue(instr, Smi::Handle(I,
- Smi::New(static_cast<intptr_t>(str.CharAt(index)))));
- return;
- }
- } else if (array_obj.IsArray()) {
- const Array& a = Array::Cast(array_obj);
- if ((a.Length() > index) && a.IsImmutable()) {
- Instance& result = Instance::Handle(I);
- result ^= a.At(index);
- SetValue(instr, result);
- return;
- }
- }
- }
- SetValue(instr, non_constant_);
- }
-}
-
-
-void ConstantPropagator::VisitLoadCodeUnits(LoadCodeUnitsInstr* instr) {
- // TODO(zerny): Implement constant propagation.
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitStoreIndexed(StoreIndexedInstr* instr) {
- SetValue(instr, instr->value()->definition()->constant_value());
-}
-
-
-void ConstantPropagator::VisitStoreInstanceField(
- StoreInstanceFieldInstr* instr) {
- SetValue(instr, instr->value()->definition()->constant_value());
-}
-
-
-void ConstantPropagator::VisitInitStaticField(InitStaticFieldInstr* instr) {
- // Nothing to do.
-}
-
-
-void ConstantPropagator::VisitLoadStaticField(LoadStaticFieldInstr* instr) {
- const Field& field = instr->StaticField();
- ASSERT(field.is_static());
- if (field.is_final()) {
- Instance& obj = Instance::Handle(I, field.value());
- ASSERT(obj.raw() != Object::sentinel().raw());
- ASSERT(obj.raw() != Object::transition_sentinel().raw());
- if (obj.IsSmi() || obj.IsOld()) {
- SetValue(instr, obj);
- return;
- }
- }
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitStoreStaticField(StoreStaticFieldInstr* instr) {
- SetValue(instr, instr->value()->definition()->constant_value());
-}
-
-
-void ConstantPropagator::VisitBooleanNegate(BooleanNegateInstr* instr) {
- const Object& value = instr->value()->definition()->constant_value();
- if (IsNonConstant(value)) {
- SetValue(instr, non_constant_);
- } else if (IsConstant(value)) {
- bool val = value.raw() != Bool::True().raw();
- SetValue(instr, Bool::Get(val));
- }
-}
-
-
-void ConstantPropagator::VisitInstanceOf(InstanceOfInstr* instr) {
- const Definition* def = instr->value()->definition();
- const Object& value = def->constant_value();
- if (IsNonConstant(value)) {
- const AbstractType& checked_type = instr->type();
- intptr_t value_cid = instr->value()->Type()->ToCid();
- Representation rep = def->representation();
- if ((checked_type.IsFloat32x4Type() && (rep == kUnboxedFloat32x4)) ||
- (checked_type.IsInt32x4Type() && (rep == kUnboxedInt32x4)) ||
- (checked_type.IsDoubleType() && (rep == kUnboxedDouble) &&
- CanUnboxDouble()) ||
- (checked_type.IsIntType() && (rep == kUnboxedMint))) {
- // Ensure that compile time type matches representation.
- ASSERT(((rep == kUnboxedFloat32x4) && (value_cid == kFloat32x4Cid)) ||
- ((rep == kUnboxedInt32x4) && (value_cid == kInt32x4Cid)) ||
- ((rep == kUnboxedDouble) && (value_cid == kDoubleCid)) ||
- ((rep == kUnboxedMint) && (value_cid == kMintCid)));
- // The representation guarantees the type check to be true.
- SetValue(instr, instr->negate_result() ? Bool::False() : Bool::True());
- } else {
- SetValue(instr, non_constant_);
- }
- } else if (IsConstant(value)) {
- // TODO(kmillikin): Handle instanceof on constants.
- SetValue(instr, non_constant_);
- }
-}
-
-
-void ConstantPropagator::VisitCreateArray(CreateArrayInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitAllocateObject(AllocateObjectInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitLoadUntagged(LoadUntaggedInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitLoadClassId(LoadClassIdInstr* instr) {
- intptr_t cid = instr->object()->Type()->ToCid();
- if (cid != kDynamicCid) {
- SetValue(instr, Smi::ZoneHandle(I, Smi::New(cid)));
- return;
- }
- const Object& object = instr->object()->definition()->constant_value();
- if (IsConstant(object)) {
- SetValue(instr, Smi::ZoneHandle(I, Smi::New(object.GetClassId())));
- return;
- }
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitLoadField(LoadFieldInstr* instr) {
- Value* instance = instr->instance();
- if ((instr->recognized_kind() == MethodRecognizer::kObjectArrayLength) &&
- instance->definition()->OriginalDefinition()->IsCreateArray()) {
- Value* num_elements = instance->definition()->OriginalDefinition()
- ->AsCreateArray()->num_elements();
- if (num_elements->BindsToConstant() &&
- num_elements->BoundConstant().IsSmi()) {
- intptr_t length = Smi::Cast(num_elements->BoundConstant()).Value();
- const Object& result = Smi::ZoneHandle(I, Smi::New(length));
- SetValue(instr, result);
- return;
- }
- }
-
- if (instr->IsImmutableLengthLoad()) {
- ConstantInstr* constant =
- instance->definition()->OriginalDefinition()->AsConstant();
- if (constant != NULL) {
- if (constant->value().IsString()) {
- SetValue(instr, Smi::ZoneHandle(I,
- Smi::New(String::Cast(constant->value()).Length())));
- return;
- }
- if (constant->value().IsArray()) {
- SetValue(instr, Smi::ZoneHandle(I,
- Smi::New(Array::Cast(constant->value()).Length())));
- return;
- }
- }
- }
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitInstantiateType(InstantiateTypeInstr* instr) {
- const Object& object =
- instr->instantiator()->definition()->constant_value();
- if (IsNonConstant(object)) {
- SetValue(instr, non_constant_);
- return;
- }
- if (IsConstant(object)) {
- if (instr->type().IsTypeParameter()) {
- if (object.IsNull()) {
- SetValue(instr, Type::ZoneHandle(I, Type::DynamicType()));
- return;
- }
- // We could try to instantiate the type parameter and return it if no
- // malformed error is reported.
- }
- SetValue(instr, non_constant_);
- }
-}
-
-
-void ConstantPropagator::VisitInstantiateTypeArguments(
- InstantiateTypeArgumentsInstr* instr) {
- const Object& object =
- instr->instantiator()->definition()->constant_value();
- if (IsNonConstant(object)) {
- SetValue(instr, non_constant_);
- return;
- }
- if (IsConstant(object)) {
- const intptr_t len = instr->type_arguments().Length();
- if (instr->type_arguments().IsRawInstantiatedRaw(len) &&
- object.IsNull()) {
- SetValue(instr, object);
- return;
- }
- if (instr->type_arguments().IsUninstantiatedIdentity() ||
- instr->type_arguments().CanShareInstantiatorTypeArguments(
- instr->instantiator_class())) {
- SetValue(instr, object);
- return;
- }
- SetValue(instr, non_constant_);
- }
-}
-
-
-void ConstantPropagator::VisitAllocateContext(AllocateContextInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitAllocateUninitializedContext(
- AllocateUninitializedContextInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitCloneContext(CloneContextInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitBinaryIntegerOp(BinaryIntegerOpInstr* binary_op) {
- const Object& left = binary_op->left()->definition()->constant_value();
- const Object& right = binary_op->right()->definition()->constant_value();
- if (IsConstant(left) && IsConstant(right)) {
- if (left.IsInteger() && right.IsInteger()) {
- const Integer& left_int = Integer::Cast(left);
- const Integer& right_int = Integer::Cast(right);
- const Integer& result =
- Integer::Handle(I, binary_op->Evaluate(left_int, right_int));
- if (!result.IsNull()) {
- SetValue(binary_op, Integer::ZoneHandle(I, result.raw()));
- return;
- }
- }
- }
-
- SetValue(binary_op, non_constant_);
-}
-
-
-void ConstantPropagator::VisitBinarySmiOp(BinarySmiOpInstr* instr) {
- VisitBinaryIntegerOp(instr);
-}
-
-
-void ConstantPropagator::VisitBinaryInt32Op(BinaryInt32OpInstr* instr) {
- VisitBinaryIntegerOp(instr);
-}
-
-
-void ConstantPropagator::VisitBinaryUint32Op(BinaryUint32OpInstr* instr) {
- VisitBinaryIntegerOp(instr);
-}
-
-
-void ConstantPropagator::VisitShiftUint32Op(ShiftUint32OpInstr* instr) {
- VisitBinaryIntegerOp(instr);
-}
-
-
-void ConstantPropagator::VisitBinaryMintOp(BinaryMintOpInstr* instr) {
- VisitBinaryIntegerOp(instr);
-}
-
-
-void ConstantPropagator::VisitShiftMintOp(ShiftMintOpInstr* instr) {
- VisitBinaryIntegerOp(instr);
-}
-
-
-void ConstantPropagator::VisitBoxInt64(BoxInt64Instr* instr) {
- // TODO(kmillikin): Handle box operation.
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitUnboxInt64(UnboxInt64Instr* instr) {
- // TODO(kmillikin): Handle unbox operation.
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitUnaryMintOp(UnaryMintOpInstr* instr) {
- // TODO(kmillikin): Handle unary operations.
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitUnarySmiOp(UnarySmiOpInstr* instr) {
- const Object& value = instr->value()->definition()->constant_value();
- if (IsNonConstant(value)) {
- SetValue(instr, non_constant_);
- } else if (IsConstant(value)) {
- // TODO(kmillikin): Handle unary operations.
- SetValue(instr, non_constant_);
- }
-}
-
-
-void ConstantPropagator::VisitUnaryDoubleOp(UnaryDoubleOpInstr* instr) {
- const Object& value = instr->value()->definition()->constant_value();
- if (IsNonConstant(value)) {
- SetValue(instr, non_constant_);
- } else if (IsConstant(value)) {
- // TODO(kmillikin): Handle unary operations.
- SetValue(instr, non_constant_);
- }
-}
-
-
-void ConstantPropagator::VisitSmiToDouble(SmiToDoubleInstr* instr) {
- const Object& value = instr->value()->definition()->constant_value();
- if (IsConstant(value) && value.IsInteger()) {
- SetValue(instr, Double::Handle(I,
- Double::New(Integer::Cast(value).AsDoubleValue(), Heap::kOld)));
- } else if (IsNonConstant(value)) {
- SetValue(instr, non_constant_);
- }
-}
-
-
-void ConstantPropagator::VisitMintToDouble(MintToDoubleInstr* instr) {
- const Object& value = instr->value()->definition()->constant_value();
- if (IsConstant(value) && value.IsInteger()) {
- SetValue(instr, Double::Handle(I,
- Double::New(Integer::Cast(value).AsDoubleValue(), Heap::kOld)));
- } else if (IsNonConstant(value)) {
- SetValue(instr, non_constant_);
- }
-}
-
-
-void ConstantPropagator::VisitInt32ToDouble(Int32ToDoubleInstr* instr) {
- const Object& value = instr->value()->definition()->constant_value();
- if (IsConstant(value) && value.IsInteger()) {
- SetValue(instr, Double::Handle(I,
- Double::New(Integer::Cast(value).AsDoubleValue(), Heap::kOld)));
- } else if (IsNonConstant(value)) {
- SetValue(instr, non_constant_);
- }
-}
-
-
-void ConstantPropagator::VisitDoubleToInteger(DoubleToIntegerInstr* instr) {
- // TODO(kmillikin): Handle conversion.
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitDoubleToSmi(DoubleToSmiInstr* instr) {
- // TODO(kmillikin): Handle conversion.
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitDoubleToDouble(DoubleToDoubleInstr* instr) {
- // TODO(kmillikin): Handle conversion.
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitDoubleToFloat(DoubleToFloatInstr* instr) {
- // TODO(kmillikin): Handle conversion.
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitFloatToDouble(FloatToDoubleInstr* instr) {
- // TODO(kmillikin): Handle conversion.
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitInvokeMathCFunction(
- InvokeMathCFunctionInstr* instr) {
- // TODO(kmillikin): Handle conversion.
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitMergedMath(MergedMathInstr* instr) {
- // TODO(srdjan): Handle merged instruction.
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitExtractNthOutput(ExtractNthOutputInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitConstant(ConstantInstr* instr) {
- SetValue(instr, instr->value());
-}
-
-
-void ConstantPropagator::VisitUnboxedConstant(UnboxedConstantInstr* instr) {
- SetValue(instr, instr->value());
-}
-
-
-void ConstantPropagator::VisitConstraint(ConstraintInstr* instr) {
- // Should not be used outside of range analysis.
- UNREACHABLE();
-}
-
-
-void ConstantPropagator::VisitMaterializeObject(MaterializeObjectInstr* instr) {
- // Should not be used outside of allocation elimination pass.
- UNREACHABLE();
-}
-
-
-static bool IsIntegerOrDouble(const Object& value) {
- return value.IsInteger() || value.IsDouble();
-}
-
-
-static double ToDouble(const Object& value) {
- return value.IsInteger() ? Integer::Cast(value).AsDoubleValue()
- : Double::Cast(value).value();
-}
-
-
-void ConstantPropagator::VisitBinaryDoubleOp(
- BinaryDoubleOpInstr* instr) {
- const Object& left = instr->left()->definition()->constant_value();
- const Object& right = instr->right()->definition()->constant_value();
- if (IsNonConstant(left) || IsNonConstant(right)) {
- SetValue(instr, non_constant_);
- } else if (left.IsInteger() && right.IsInteger()) {
- SetValue(instr, non_constant_);
- } else if (IsIntegerOrDouble(left) && IsIntegerOrDouble(right)) {
- const double left_val = ToDouble(left);
- const double right_val = ToDouble(right);
- double result_val = 0.0;
- switch (instr->op_kind()) {
- case Token::kADD:
- result_val = left_val + right_val;
- break;
- case Token::kSUB:
- result_val = left_val - right_val;
- break;
- case Token::kMUL:
- result_val = left_val * right_val;
- break;
- case Token::kDIV:
- result_val = left_val / right_val;
- break;
- default:
- UNREACHABLE();
- }
- const Double& result = Double::ZoneHandle(Double::NewCanonical(result_val));
- SetValue(instr, result);
- }
-}
-
-
-void ConstantPropagator::VisitBinaryFloat32x4Op(
- BinaryFloat32x4OpInstr* instr) {
- const Object& left = instr->left()->definition()->constant_value();
- const Object& right = instr->right()->definition()->constant_value();
- if (IsNonConstant(left) || IsNonConstant(right)) {
- SetValue(instr, non_constant_);
- } else if (IsConstant(left) && IsConstant(right)) {
- // TODO(kmillikin): Handle binary operation.
- SetValue(instr, non_constant_);
- }
-}
-
-
-void ConstantPropagator::VisitFloat32x4Constructor(
- Float32x4ConstructorInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitSimd32x4Shuffle(Simd32x4ShuffleInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitSimd32x4ShuffleMix(
- Simd32x4ShuffleMixInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitSimd32x4GetSignMask(
- Simd32x4GetSignMaskInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitFloat32x4Zero(Float32x4ZeroInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitFloat32x4Splat(Float32x4SplatInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitFloat32x4Comparison(
- Float32x4ComparisonInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitFloat32x4MinMax(Float32x4MinMaxInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitFloat32x4Scale(Float32x4ScaleInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitFloat32x4Sqrt(Float32x4SqrtInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitFloat32x4ZeroArg(Float32x4ZeroArgInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitFloat32x4Clamp(Float32x4ClampInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitFloat32x4With(Float32x4WithInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitFloat32x4ToInt32x4(
- Float32x4ToInt32x4Instr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitInt32x4Constructor(
- Int32x4ConstructorInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitInt32x4BoolConstructor(
- Int32x4BoolConstructorInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitInt32x4GetFlag(Int32x4GetFlagInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitInt32x4SetFlag(Int32x4SetFlagInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitInt32x4Select(Int32x4SelectInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitInt32x4ToFloat32x4(
- Int32x4ToFloat32x4Instr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitBinaryInt32x4Op(BinaryInt32x4OpInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitSimd64x2Shuffle(Simd64x2ShuffleInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitBinaryFloat64x2Op(BinaryFloat64x2OpInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitFloat32x4ToFloat64x2(
- Float32x4ToFloat64x2Instr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitFloat64x2ToFloat32x4(
- Float64x2ToFloat32x4Instr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitFloat64x2Zero(
- Float64x2ZeroInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitFloat64x2Splat(
- Float64x2SplatInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitFloat64x2Constructor(
- Float64x2ConstructorInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitFloat64x2ZeroArg(Float64x2ZeroArgInstr* instr) {
- // TODO(johnmccutchan): Implement constant propagation.
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitFloat64x2OneArg(Float64x2OneArgInstr* instr) {
- // TODO(johnmccutchan): Implement constant propagation.
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitMathUnary(MathUnaryInstr* instr) {
- const Object& value = instr->value()->definition()->constant_value();
- if (IsNonConstant(value)) {
- SetValue(instr, non_constant_);
- } else if (IsConstant(value)) {
- // TODO(kmillikin): Handle Math's unary operations (sqrt, cos, sin).
- SetValue(instr, non_constant_);
- }
-}
-
-
-void ConstantPropagator::VisitMathMinMax(MathMinMaxInstr* instr) {
- const Object& left = instr->left()->definition()->constant_value();
- const Object& right = instr->right()->definition()->constant_value();
- if (IsNonConstant(left) || IsNonConstant(right)) {
- SetValue(instr, non_constant_);
- } else if (IsConstant(left) && IsConstant(right)) {
- // TODO(srdjan): Handle min and max.
- SetValue(instr, non_constant_);
- }
-}
-
-
-void ConstantPropagator::VisitCaseInsensitiveCompareUC16(
- CaseInsensitiveCompareUC16Instr *instr) {
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitUnbox(UnboxInstr* instr) {
- const Object& value = instr->value()->definition()->constant_value();
- if (IsNonConstant(value)) {
- SetValue(instr, non_constant_);
- } else if (IsConstant(value)) {
- // TODO(kmillikin): Handle conversion.
- SetValue(instr, non_constant_);
- }
-}
-
-
-void ConstantPropagator::VisitBox(BoxInstr* instr) {
- const Object& value = instr->value()->definition()->constant_value();
- if (IsNonConstant(value)) {
- SetValue(instr, non_constant_);
- } else if (IsConstant(value)) {
- // TODO(kmillikin): Handle conversion.
- SetValue(instr, non_constant_);
- }
-}
-
-
-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::VisitBoxInt32(BoxInt32Instr* instr) {
- // TODO(kmillikin): Handle box operation.
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitUnboxInt32(UnboxInt32Instr* instr) {
- // TODO(kmillikin): Handle unbox operation.
- SetValue(instr, non_constant_);
-}
-
-
-void ConstantPropagator::VisitUnboxedIntConverter(
- UnboxedIntConverterInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-
-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());
- block_worklist_.Add(entry);
-
- while (true) {
- if (block_worklist_.is_empty()) {
- if (definition_worklist_.IsEmpty()) break;
- Definition* definition = definition_worklist_.RemoveLast();
- Value* use = definition->input_use_list();
- while (use != NULL) {
- use->instruction()->Accept(this);
- use = use->next_use();
- }
- } else {
- BlockEntryInstr* block = block_worklist_.RemoveLast();
- block->Accept(this);
- }
- }
-}
-
-
-static bool IsEmptyBlock(BlockEntryInstr* block) {
- return block->next()->IsGoto() &&
- (!block->IsJoinEntry() || (block->AsJoinEntry()->phis() == NULL)) &&
- !block->IsIndirectEntry();
-}
-
-
-// Traverses a chain of empty blocks and returns the first reachable non-empty
-// block that is not dominated by the start block. The empty blocks are added
-// to the supplied bit vector.
-static BlockEntryInstr* FindFirstNonEmptySuccessor(
- TargetEntryInstr* block,
- BitVector* empty_blocks) {
- BlockEntryInstr* current = block;
- while (IsEmptyBlock(current) && block->Dominates(current)) {
- ASSERT(!block->IsJoinEntry() || (block->AsJoinEntry()->phis() == NULL));
- empty_blocks->Add(current->preorder_number());
- current = current->next()->AsGoto()->successor();
- }
- return current;
-}
-
-
-void ConstantPropagator::EliminateRedundantBranches() {
- // Canonicalize branches that have no side-effects and where true- and
- // false-targets are the same.
- bool changed = false;
- BitVector* empty_blocks = new(I) BitVector(I, graph_->preorder().length());
- for (BlockIterator b = graph_->postorder_iterator();
- !b.Done();
- b.Advance()) {
- BlockEntryInstr* block = b.Current();
- BranchInstr* branch = block->last_instruction()->AsBranch();
- empty_blocks->Clear();
- if ((branch != NULL) && branch->Effects().IsNone()) {
- ASSERT(branch->previous() != NULL); // Not already eliminated.
- BlockEntryInstr* if_true =
- FindFirstNonEmptySuccessor(branch->true_successor(), empty_blocks);
- BlockEntryInstr* if_false =
- FindFirstNonEmptySuccessor(branch->false_successor(), empty_blocks);
- if (if_true == if_false) {
- // Replace the branch with a jump to the common successor.
- // Drop the comparison, which does not have side effects
- JoinEntryInstr* join = if_true->AsJoinEntry();
- if (join->phis() == NULL) {
- GotoInstr* jump = new(I) GotoInstr(if_true->AsJoinEntry());
- jump->InheritDeoptTarget(I, branch);
-
- Instruction* previous = branch->previous();
- branch->set_previous(NULL);
- previous->LinkTo(jump);
-
- // Remove uses from branch and all the empty blocks that
- // are now unreachable.
- branch->UnuseAllInputs();
- for (BitVector::Iterator it(empty_blocks); !it.Done(); it.Advance()) {
- BlockEntryInstr* empty_block = graph_->preorder()[it.Current()];
- empty_block->ClearAllInstructions();
- }
-
- changed = true;
-
- if (FLAG_trace_constant_propagation) {
- OS::Print("Eliminated branch in B%" Pd " common target B%" Pd "\n",
- block->block_id(), join->block_id());
- }
- }
- }
- }
- }
-
- if (changed) {
- graph_->DiscoverBlocks();
- // TODO(fschneider): Update dominator tree in place instead of recomputing.
- GrowableArray<BitVector*> dominance_frontier;
- graph_->ComputeDominators(&dominance_frontier);
- }
-}
-
-
-void ConstantPropagator::Transform() {
- if (FLAG_trace_constant_propagation) {
- OS::Print("\n==== Before constant propagation ====\n");
- FlowGraphPrinter printer(*graph_);
- printer.PrintBlocks();
- }
-
- // We will recompute dominators, block ordering, block ids, block last
- // instructions, previous pointers, predecessors, etc. after eliminating
- // unreachable code. We do not maintain those properties during the
- // transformation.
- for (BlockIterator b = graph_->reverse_postorder_iterator();
- !b.Done();
- b.Advance()) {
- BlockEntryInstr* block = b.Current();
- if (!reachable_->Contains(block->preorder_number())) {
- if (FLAG_trace_constant_propagation) {
- OS::Print("Unreachable B%" Pd "\n", block->block_id());
- }
- // Remove all uses in unreachable blocks.
- block->ClearAllInstructions();
- continue;
- }
-
- JoinEntryInstr* join = block->AsJoinEntry();
- if (join != NULL) {
- // Remove phi inputs corresponding to unreachable predecessor blocks.
- // Predecessors will be recomputed (in block id order) after removing
- // unreachable code so we merely have to keep the phi inputs in order.
- ZoneGrowableArray<PhiInstr*>* phis = join->phis();
- if ((phis != NULL) && !phis->is_empty()) {
- intptr_t pred_count = join->PredecessorCount();
- intptr_t live_count = 0;
- for (intptr_t pred_idx = 0; pred_idx < pred_count; ++pred_idx) {
- if (reachable_->Contains(
- join->PredecessorAt(pred_idx)->preorder_number())) {
- if (live_count < pred_idx) {
- for (PhiIterator it(join); !it.Done(); it.Advance()) {
- PhiInstr* phi = it.Current();
- ASSERT(phi != NULL);
- phi->SetInputAt(live_count, phi->InputAt(pred_idx));
- }
- }
- ++live_count;
- } else {
- for (PhiIterator it(join); !it.Done(); it.Advance()) {
- PhiInstr* phi = it.Current();
- ASSERT(phi != NULL);
- phi->InputAt(pred_idx)->RemoveFromUseList();
- }
- }
- }
- if (live_count < pred_count) {
- intptr_t to_idx = 0;
- for (intptr_t from_idx = 0; from_idx < phis->length(); ++from_idx) {
- PhiInstr* phi = (*phis)[from_idx];
- ASSERT(phi != NULL);
- if (FLAG_remove_redundant_phis && (live_count == 1)) {
- Value* input = phi->InputAt(0);
- phi->ReplaceUsesWith(input->definition());
- input->RemoveFromUseList();
- } else {
- phi->inputs_.TruncateTo(live_count);
- (*phis)[to_idx++] = phi;
- }
- }
- if (to_idx == 0) {
- join->phis_ = NULL;
- } else {
- phis->TruncateTo(to_idx);
- }
- }
- }
- }
-
- for (ForwardInstructionIterator i(block); !i.Done(); i.Advance()) {
- Definition* defn = i.Current()->AsDefinition();
- // Replace constant-valued instructions without observable side
- // effects. Do this for smis only to avoid having to copy other
- // objects into the heap's old generation.
- if ((defn != NULL) &&
- IsConstant(defn->constant_value()) &&
- (defn->constant_value().IsSmi() || defn->constant_value().IsOld()) &&
- !defn->IsConstant() &&
- !defn->IsPushArgument() &&
- !defn->IsStoreIndexed() &&
- !defn->IsStoreInstanceField() &&
- !defn->IsStoreStaticField()) {
- if (FLAG_trace_constant_propagation) {
- OS::Print("Constant v%" Pd " = %s\n",
- defn->ssa_temp_index(),
- defn->constant_value().ToCString());
- }
- ConstantInstr* constant = graph_->GetConstant(defn->constant_value());
- defn->ReplaceUsesWith(constant);
- i.RemoveCurrentFromGraph();
- }
- }
-
- // Replace branches where one target is unreachable with jumps.
- BranchInstr* branch = block->last_instruction()->AsBranch();
- if (branch != NULL) {
- TargetEntryInstr* if_true = branch->true_successor();
- TargetEntryInstr* if_false = branch->false_successor();
- JoinEntryInstr* join = NULL;
- Instruction* next = NULL;
-
- if (!reachable_->Contains(if_true->preorder_number())) {
- ASSERT(reachable_->Contains(if_false->preorder_number()));
- ASSERT(if_false->parallel_move() == NULL);
- ASSERT(if_false->loop_info() == NULL);
- join = new(I) JoinEntryInstr(if_false->block_id(),
- if_false->try_index());
- join->InheritDeoptTarget(I, if_false);
- if_false->UnuseAllInputs();
- next = if_false->next();
- } else if (!reachable_->Contains(if_false->preorder_number())) {
- ASSERT(if_true->parallel_move() == NULL);
- ASSERT(if_true->loop_info() == NULL);
- join = new(I) JoinEntryInstr(if_true->block_id(),
- if_true->try_index());
- join->InheritDeoptTarget(I, if_true);
- if_true->UnuseAllInputs();
- next = if_true->next();
- }
-
- if (join != NULL) {
- // Replace the branch with a jump to the reachable successor.
- // Drop the comparison, which does not have side effects as long
- // as it is a strict compare (the only one we can determine is
- // constant with the current analysis).
- GotoInstr* jump = new(I) GotoInstr(join);
- jump->InheritDeoptTarget(I, branch);
-
- Instruction* previous = branch->previous();
- branch->set_previous(NULL);
- previous->LinkTo(jump);
-
- // Replace the false target entry with the new join entry. We will
- // recompute the dominators after this pass.
- join->LinkTo(next);
- branch->UnuseAllInputs();
- }
- }
- }
-
- graph_->DiscoverBlocks();
- graph_->MergeBlocks();
- GrowableArray<BitVector*> dominance_frontier;
- graph_->ComputeDominators(&dominance_frontier);
-
- if (FLAG_trace_constant_propagation) {
- OS::Print("\n==== After constant propagation ====\n");
- FlowGraphPrinter printer(*graph_);
- printer.PrintBlocks();
- }
-}
-
-
// Returns true if the given phi has a single input use and
// is used in the environments either at the corresponding block entry or
// at the same instruction where input use is.
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/intermediate_language.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698