| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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/constant_propagator.h" | 5 #include "vm/constant_propagator.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/flow_graph_builder.h" | 8 #include "vm/flow_graph_builder.h" |
| 9 #include "vm/flow_graph_compiler.h" | 9 #include "vm/flow_graph_compiler.h" |
| 10 #include "vm/flow_graph_range_analysis.h" | 10 #include "vm/flow_graph_range_analysis.h" |
| 11 #include "vm/il_printer.h" | 11 #include "vm/il_printer.h" |
| 12 #include "vm/intermediate_language.h" | 12 #include "vm/intermediate_language.h" |
| 13 #include "vm/parser.h" | 13 #include "vm/parser.h" |
| 14 #include "vm/symbols.h" | 14 #include "vm/symbols.h" |
| 15 | 15 |
| 16 namespace dart { | 16 namespace dart { |
| 17 | 17 |
| 18 DEFINE_FLAG(bool, remove_redundant_phis, true, "Remove redundant phis."); | 18 DEFINE_FLAG(bool, remove_redundant_phis, true, "Remove redundant phis."); |
| 19 DEFINE_FLAG(bool, | 19 DEFINE_FLAG(bool, |
| 20 trace_constant_propagation, | 20 trace_constant_propagation, |
| 21 false, | 21 false, |
| 22 "Print constant propagation and useless code elimination."); | 22 "Print constant propagation and useless code elimination."); |
| 23 | 23 |
| 24 // Quick access to the current zone and isolate. | 24 // Quick access to the current zone and isolate. |
| 25 #define I (isolate()) | 25 #define I (isolate()) |
| 26 #define Z (graph_->zone()) | 26 #define Z (graph_->zone()) |
| 27 | 27 |
| 28 | |
| 29 ConstantPropagator::ConstantPropagator( | 28 ConstantPropagator::ConstantPropagator( |
| 30 FlowGraph* graph, | 29 FlowGraph* graph, |
| 31 const GrowableArray<BlockEntryInstr*>& ignored) | 30 const GrowableArray<BlockEntryInstr*>& ignored) |
| 32 : FlowGraphVisitor(ignored), | 31 : FlowGraphVisitor(ignored), |
| 33 graph_(graph), | 32 graph_(graph), |
| 34 unknown_(Object::unknown_constant()), | 33 unknown_(Object::unknown_constant()), |
| 35 non_constant_(Object::non_constant()), | 34 non_constant_(Object::non_constant()), |
| 36 reachable_(new (Z) BitVector(Z, graph->preorder().length())), | 35 reachable_(new (Z) BitVector(Z, graph->preorder().length())), |
| 37 marked_phis_(new (Z) BitVector(Z, graph->max_virtual_register_number())), | 36 marked_phis_(new (Z) BitVector(Z, graph->max_virtual_register_number())), |
| 38 block_worklist_(), | 37 block_worklist_(), |
| 39 definition_worklist_(graph, 10) {} | 38 definition_worklist_(graph, 10) {} |
| 40 | 39 |
| 41 | |
| 42 void ConstantPropagator::Optimize(FlowGraph* graph) { | 40 void ConstantPropagator::Optimize(FlowGraph* graph) { |
| 43 GrowableArray<BlockEntryInstr*> ignored; | 41 GrowableArray<BlockEntryInstr*> ignored; |
| 44 ConstantPropagator cp(graph, ignored); | 42 ConstantPropagator cp(graph, ignored); |
| 45 cp.Analyze(); | 43 cp.Analyze(); |
| 46 cp.Transform(); | 44 cp.Transform(); |
| 47 } | 45 } |
| 48 | 46 |
| 49 | |
| 50 void ConstantPropagator::OptimizeBranches(FlowGraph* graph) { | 47 void ConstantPropagator::OptimizeBranches(FlowGraph* graph) { |
| 51 GrowableArray<BlockEntryInstr*> ignored; | 48 GrowableArray<BlockEntryInstr*> ignored; |
| 52 ConstantPropagator cp(graph, ignored); | 49 ConstantPropagator cp(graph, ignored); |
| 53 cp.Analyze(); | 50 cp.Analyze(); |
| 54 cp.Transform(); | 51 cp.Transform(); |
| 55 cp.EliminateRedundantBranches(); | 52 cp.EliminateRedundantBranches(); |
| 56 } | 53 } |
| 57 | 54 |
| 58 | |
| 59 void ConstantPropagator::SetReachable(BlockEntryInstr* block) { | 55 void ConstantPropagator::SetReachable(BlockEntryInstr* block) { |
| 60 if (!reachable_->Contains(block->preorder_number())) { | 56 if (!reachable_->Contains(block->preorder_number())) { |
| 61 reachable_->Add(block->preorder_number()); | 57 reachable_->Add(block->preorder_number()); |
| 62 block_worklist_.Add(block); | 58 block_worklist_.Add(block); |
| 63 } | 59 } |
| 64 } | 60 } |
| 65 | 61 |
| 66 | |
| 67 bool ConstantPropagator::SetValue(Definition* definition, const Object& value) { | 62 bool ConstantPropagator::SetValue(Definition* definition, const Object& value) { |
| 68 // We would like to assert we only go up (toward non-constant) in the lattice. | 63 // We would like to assert we only go up (toward non-constant) in the lattice. |
| 69 // | 64 // |
| 70 // ASSERT(IsUnknown(definition->constant_value()) || | 65 // ASSERT(IsUnknown(definition->constant_value()) || |
| 71 // IsNonConstant(value) || | 66 // IsNonConstant(value) || |
| 72 // (definition->constant_value().raw() == value.raw())); | 67 // (definition->constant_value().raw() == value.raw())); |
| 73 // | 68 // |
| 74 // But the final disjunct is not true (e.g., mint or double constants are | 69 // But the final disjunct is not true (e.g., mint or double constants are |
| 75 // heap-allocated and so not necessarily pointer-equal on each iteration). | 70 // heap-allocated and so not necessarily pointer-equal on each iteration). |
| 76 if (definition->constant_value().raw() != value.raw()) { | 71 if (definition->constant_value().raw() != value.raw()) { |
| 77 definition->constant_value() = value.raw(); | 72 definition->constant_value() = value.raw(); |
| 78 if (definition->input_use_list() != NULL) { | 73 if (definition->input_use_list() != NULL) { |
| 79 definition_worklist_.Add(definition); | 74 definition_worklist_.Add(definition); |
| 80 } | 75 } |
| 81 return true; | 76 return true; |
| 82 } | 77 } |
| 83 return false; | 78 return false; |
| 84 } | 79 } |
| 85 | 80 |
| 86 | |
| 87 // Compute the join of two values in the lattice, assign it to the first. | 81 // Compute the join of two values in the lattice, assign it to the first. |
| 88 void ConstantPropagator::Join(Object* left, const Object& right) { | 82 void ConstantPropagator::Join(Object* left, const Object& right) { |
| 89 // Join(non-constant, X) = non-constant | 83 // Join(non-constant, X) = non-constant |
| 90 // Join(X, unknown) = X | 84 // Join(X, unknown) = X |
| 91 if (IsNonConstant(*left) || IsUnknown(right)) return; | 85 if (IsNonConstant(*left) || IsUnknown(right)) return; |
| 92 | 86 |
| 93 // Join(unknown, X) = X | 87 // Join(unknown, X) = X |
| 94 // Join(X, non-constant) = non-constant | 88 // Join(X, non-constant) = non-constant |
| 95 if (IsUnknown(*left) || IsNonConstant(right)) { | 89 if (IsUnknown(*left) || IsNonConstant(right)) { |
| 96 *left = right.raw(); | 90 *left = right.raw(); |
| 97 return; | 91 return; |
| 98 } | 92 } |
| 99 | 93 |
| 100 // Join(X, X) = X | 94 // Join(X, X) = X |
| 101 // TODO(kmillikin): support equality for doubles, mints, etc. | 95 // TODO(kmillikin): support equality for doubles, mints, etc. |
| 102 if (left->raw() == right.raw()) return; | 96 if (left->raw() == right.raw()) return; |
| 103 | 97 |
| 104 // Join(X, Y) = non-constant | 98 // Join(X, Y) = non-constant |
| 105 *left = non_constant_.raw(); | 99 *left = non_constant_.raw(); |
| 106 } | 100 } |
| 107 | 101 |
| 108 | |
| 109 // -------------------------------------------------------------------------- | 102 // -------------------------------------------------------------------------- |
| 110 // Analysis of blocks. Called at most once per block. The block is already | 103 // Analysis of blocks. Called at most once per block. The block is already |
| 111 // marked as reachable. All instructions in the block are analyzed. | 104 // marked as reachable. All instructions in the block are analyzed. |
| 112 void ConstantPropagator::VisitGraphEntry(GraphEntryInstr* block) { | 105 void ConstantPropagator::VisitGraphEntry(GraphEntryInstr* block) { |
| 113 const GrowableArray<Definition*>& defs = *block->initial_definitions(); | 106 const GrowableArray<Definition*>& defs = *block->initial_definitions(); |
| 114 for (intptr_t i = 0; i < defs.length(); ++i) { | 107 for (intptr_t i = 0; i < defs.length(); ++i) { |
| 115 defs[i]->Accept(this); | 108 defs[i]->Accept(this); |
| 116 } | 109 } |
| 117 ASSERT(ForwardInstructionIterator(block).Done()); | 110 ASSERT(ForwardInstructionIterator(block).Done()); |
| 118 | 111 |
| 119 // TODO(fschneider): Improve this approximation. The catch entry is only | 112 // TODO(fschneider): Improve this approximation. The catch entry is only |
| 120 // reachable if a call in the try-block is reachable. | 113 // reachable if a call in the try-block is reachable. |
| 121 for (intptr_t i = 0; i < block->SuccessorCount(); ++i) { | 114 for (intptr_t i = 0; i < block->SuccessorCount(); ++i) { |
| 122 SetReachable(block->SuccessorAt(i)); | 115 SetReachable(block->SuccessorAt(i)); |
| 123 } | 116 } |
| 124 } | 117 } |
| 125 | 118 |
| 126 | |
| 127 void ConstantPropagator::VisitJoinEntry(JoinEntryInstr* block) { | 119 void ConstantPropagator::VisitJoinEntry(JoinEntryInstr* block) { |
| 128 // Phis are visited when visiting Goto at a predecessor. See VisitGoto. | 120 // Phis are visited when visiting Goto at a predecessor. See VisitGoto. |
| 129 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { | 121 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { |
| 130 it.Current()->Accept(this); | 122 it.Current()->Accept(this); |
| 131 } | 123 } |
| 132 } | 124 } |
| 133 | 125 |
| 134 | |
| 135 void ConstantPropagator::VisitTargetEntry(TargetEntryInstr* block) { | 126 void ConstantPropagator::VisitTargetEntry(TargetEntryInstr* block) { |
| 136 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { | 127 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { |
| 137 it.Current()->Accept(this); | 128 it.Current()->Accept(this); |
| 138 } | 129 } |
| 139 } | 130 } |
| 140 | 131 |
| 141 | |
| 142 void ConstantPropagator::VisitIndirectEntry(IndirectEntryInstr* block) { | 132 void ConstantPropagator::VisitIndirectEntry(IndirectEntryInstr* block) { |
| 143 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { | 133 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { |
| 144 it.Current()->Accept(this); | 134 it.Current()->Accept(this); |
| 145 } | 135 } |
| 146 } | 136 } |
| 147 | 137 |
| 148 | |
| 149 void ConstantPropagator::VisitCatchBlockEntry(CatchBlockEntryInstr* block) { | 138 void ConstantPropagator::VisitCatchBlockEntry(CatchBlockEntryInstr* block) { |
| 150 const GrowableArray<Definition*>& defs = *block->initial_definitions(); | 139 const GrowableArray<Definition*>& defs = *block->initial_definitions(); |
| 151 for (intptr_t i = 0; i < defs.length(); ++i) { | 140 for (intptr_t i = 0; i < defs.length(); ++i) { |
| 152 defs[i]->Accept(this); | 141 defs[i]->Accept(this); |
| 153 } | 142 } |
| 154 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { | 143 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { |
| 155 it.Current()->Accept(this); | 144 it.Current()->Accept(this); |
| 156 } | 145 } |
| 157 } | 146 } |
| 158 | 147 |
| 159 | |
| 160 void ConstantPropagator::VisitParallelMove(ParallelMoveInstr* instr) { | 148 void ConstantPropagator::VisitParallelMove(ParallelMoveInstr* instr) { |
| 161 // Parallel moves have not yet been inserted in the graph. | 149 // Parallel moves have not yet been inserted in the graph. |
| 162 UNREACHABLE(); | 150 UNREACHABLE(); |
| 163 } | 151 } |
| 164 | 152 |
| 165 | |
| 166 // -------------------------------------------------------------------------- | 153 // -------------------------------------------------------------------------- |
| 167 // Analysis of control instructions. Unconditional successors are | 154 // Analysis of control instructions. Unconditional successors are |
| 168 // reachable. Conditional successors are reachable depending on the | 155 // reachable. Conditional successors are reachable depending on the |
| 169 // constant value of the condition. | 156 // constant value of the condition. |
| 170 void ConstantPropagator::VisitReturn(ReturnInstr* instr) { | 157 void ConstantPropagator::VisitReturn(ReturnInstr* instr) { |
| 171 // Nothing to do. | 158 // Nothing to do. |
| 172 } | 159 } |
| 173 | 160 |
| 174 | |
| 175 void ConstantPropagator::VisitThrow(ThrowInstr* instr) { | 161 void ConstantPropagator::VisitThrow(ThrowInstr* instr) { |
| 176 // Nothing to do. | 162 // Nothing to do. |
| 177 } | 163 } |
| 178 | 164 |
| 179 | |
| 180 void ConstantPropagator::VisitReThrow(ReThrowInstr* instr) { | 165 void ConstantPropagator::VisitReThrow(ReThrowInstr* instr) { |
| 181 // Nothing to do. | 166 // Nothing to do. |
| 182 } | 167 } |
| 183 | 168 |
| 184 | |
| 185 void ConstantPropagator::VisitStop(StopInstr* instr) { | 169 void ConstantPropagator::VisitStop(StopInstr* instr) { |
| 186 // Nothing to do. | 170 // Nothing to do. |
| 187 } | 171 } |
| 188 | 172 |
| 189 | |
| 190 void ConstantPropagator::VisitGoto(GotoInstr* instr) { | 173 void ConstantPropagator::VisitGoto(GotoInstr* instr) { |
| 191 SetReachable(instr->successor()); | 174 SetReachable(instr->successor()); |
| 192 | 175 |
| 193 // Phi value depends on the reachability of a predecessor. We have | 176 // Phi value depends on the reachability of a predecessor. We have |
| 194 // to revisit phis every time a predecessor becomes reachable. | 177 // to revisit phis every time a predecessor becomes reachable. |
| 195 for (PhiIterator it(instr->successor()); !it.Done(); it.Advance()) { | 178 for (PhiIterator it(instr->successor()); !it.Done(); it.Advance()) { |
| 196 it.Current()->Accept(this); | 179 it.Current()->Accept(this); |
| 197 } | 180 } |
| 198 } | 181 } |
| 199 | 182 |
| 200 | |
| 201 void ConstantPropagator::VisitIndirectGoto(IndirectGotoInstr* instr) { | 183 void ConstantPropagator::VisitIndirectGoto(IndirectGotoInstr* instr) { |
| 202 for (intptr_t i = 0; i < instr->SuccessorCount(); i++) { | 184 for (intptr_t i = 0; i < instr->SuccessorCount(); i++) { |
| 203 SetReachable(instr->SuccessorAt(i)); | 185 SetReachable(instr->SuccessorAt(i)); |
| 204 } | 186 } |
| 205 } | 187 } |
| 206 | 188 |
| 207 | |
| 208 void ConstantPropagator::VisitBranch(BranchInstr* instr) { | 189 void ConstantPropagator::VisitBranch(BranchInstr* instr) { |
| 209 instr->comparison()->Accept(this); | 190 instr->comparison()->Accept(this); |
| 210 | 191 |
| 211 // The successors may be reachable, but only if this instruction is. (We | 192 // The successors may be reachable, but only if this instruction is. (We |
| 212 // might be analyzing it because the constant value of one of its inputs | 193 // might be analyzing it because the constant value of one of its inputs |
| 213 // has changed.) | 194 // has changed.) |
| 214 if (reachable_->Contains(instr->GetBlock()->preorder_number())) { | 195 if (reachable_->Contains(instr->GetBlock()->preorder_number())) { |
| 215 if (instr->constant_target() != NULL) { | 196 if (instr->constant_target() != NULL) { |
| 216 ASSERT((instr->constant_target() == instr->true_successor()) || | 197 ASSERT((instr->constant_target() == instr->true_successor()) || |
| 217 (instr->constant_target() == instr->false_successor())); | 198 (instr->constant_target() == instr->false_successor())); |
| 218 SetReachable(instr->constant_target()); | 199 SetReachable(instr->constant_target()); |
| 219 } else { | 200 } else { |
| 220 const Object& value = instr->comparison()->constant_value(); | 201 const Object& value = instr->comparison()->constant_value(); |
| 221 if (IsNonConstant(value)) { | 202 if (IsNonConstant(value)) { |
| 222 SetReachable(instr->true_successor()); | 203 SetReachable(instr->true_successor()); |
| 223 SetReachable(instr->false_successor()); | 204 SetReachable(instr->false_successor()); |
| 224 } else if (value.raw() == Bool::True().raw()) { | 205 } else if (value.raw() == Bool::True().raw()) { |
| 225 SetReachable(instr->true_successor()); | 206 SetReachable(instr->true_successor()); |
| 226 } else if (!IsUnknown(value)) { // Any other constant. | 207 } else if (!IsUnknown(value)) { // Any other constant. |
| 227 SetReachable(instr->false_successor()); | 208 SetReachable(instr->false_successor()); |
| 228 } | 209 } |
| 229 } | 210 } |
| 230 } | 211 } |
| 231 } | 212 } |
| 232 | 213 |
| 233 | |
| 234 // -------------------------------------------------------------------------- | 214 // -------------------------------------------------------------------------- |
| 235 // Analysis of non-definition instructions. They do not have values so they | 215 // Analysis of non-definition instructions. They do not have values so they |
| 236 // cannot have constant values. | 216 // cannot have constant values. |
| 237 void ConstantPropagator::VisitCheckStackOverflow( | 217 void ConstantPropagator::VisitCheckStackOverflow( |
| 238 CheckStackOverflowInstr* instr) {} | 218 CheckStackOverflowInstr* instr) {} |
| 239 | 219 |
| 240 | |
| 241 void ConstantPropagator::VisitCheckClass(CheckClassInstr* instr) {} | 220 void ConstantPropagator::VisitCheckClass(CheckClassInstr* instr) {} |
| 242 | 221 |
| 243 | |
| 244 void ConstantPropagator::VisitCheckClassId(CheckClassIdInstr* instr) {} | 222 void ConstantPropagator::VisitCheckClassId(CheckClassIdInstr* instr) {} |
| 245 | 223 |
| 246 | |
| 247 void ConstantPropagator::VisitGuardFieldClass(GuardFieldClassInstr* instr) {} | 224 void ConstantPropagator::VisitGuardFieldClass(GuardFieldClassInstr* instr) {} |
| 248 | 225 |
| 249 | |
| 250 void ConstantPropagator::VisitGuardFieldLength(GuardFieldLengthInstr* instr) {} | 226 void ConstantPropagator::VisitGuardFieldLength(GuardFieldLengthInstr* instr) {} |
| 251 | 227 |
| 252 | |
| 253 void ConstantPropagator::VisitCheckSmi(CheckSmiInstr* instr) {} | 228 void ConstantPropagator::VisitCheckSmi(CheckSmiInstr* instr) {} |
| 254 | 229 |
| 255 | |
| 256 void ConstantPropagator::VisitGenericCheckBound(GenericCheckBoundInstr* instr) { | 230 void ConstantPropagator::VisitGenericCheckBound(GenericCheckBoundInstr* instr) { |
| 257 } | 231 } |
| 258 | 232 |
| 259 | |
| 260 void ConstantPropagator::VisitCheckEitherNonSmi(CheckEitherNonSmiInstr* instr) { | 233 void ConstantPropagator::VisitCheckEitherNonSmi(CheckEitherNonSmiInstr* instr) { |
| 261 } | 234 } |
| 262 | 235 |
| 263 | |
| 264 void ConstantPropagator::VisitCheckArrayBound(CheckArrayBoundInstr* instr) {} | 236 void ConstantPropagator::VisitCheckArrayBound(CheckArrayBoundInstr* instr) {} |
| 265 | 237 |
| 266 | |
| 267 void ConstantPropagator::VisitDeoptimize(DeoptimizeInstr* instr) { | 238 void ConstantPropagator::VisitDeoptimize(DeoptimizeInstr* instr) { |
| 268 // TODO(vegorov) remove all code after DeoptimizeInstr as dead. | 239 // TODO(vegorov) remove all code after DeoptimizeInstr as dead. |
| 269 } | 240 } |
| 270 | 241 |
| 271 | |
| 272 Definition* ConstantPropagator::UnwrapPhi(Definition* defn) { | 242 Definition* ConstantPropagator::UnwrapPhi(Definition* defn) { |
| 273 if (defn->IsPhi()) { | 243 if (defn->IsPhi()) { |
| 274 JoinEntryInstr* block = defn->AsPhi()->block(); | 244 JoinEntryInstr* block = defn->AsPhi()->block(); |
| 275 | 245 |
| 276 Definition* input = NULL; | 246 Definition* input = NULL; |
| 277 for (intptr_t i = 0; i < defn->InputCount(); ++i) { | 247 for (intptr_t i = 0; i < defn->InputCount(); ++i) { |
| 278 if (reachable_->Contains(block->PredecessorAt(i)->preorder_number())) { | 248 if (reachable_->Contains(block->PredecessorAt(i)->preorder_number())) { |
| 279 if (input == NULL) { | 249 if (input == NULL) { |
| 280 input = defn->InputAt(i)->definition(); | 250 input = defn->InputAt(i)->definition(); |
| 281 } else { | 251 } else { |
| 282 return defn; | 252 return defn; |
| 283 } | 253 } |
| 284 } | 254 } |
| 285 } | 255 } |
| 286 | 256 |
| 287 return input; | 257 return input; |
| 288 } | 258 } |
| 289 | 259 |
| 290 return defn; | 260 return defn; |
| 291 } | 261 } |
| 292 | 262 |
| 293 | |
| 294 void ConstantPropagator::MarkPhi(Definition* phi) { | 263 void ConstantPropagator::MarkPhi(Definition* phi) { |
| 295 ASSERT(phi->IsPhi()); | 264 ASSERT(phi->IsPhi()); |
| 296 marked_phis_->Add(phi->ssa_temp_index()); | 265 marked_phis_->Add(phi->ssa_temp_index()); |
| 297 } | 266 } |
| 298 | 267 |
| 299 | |
| 300 // -------------------------------------------------------------------------- | 268 // -------------------------------------------------------------------------- |
| 301 // Analysis of definitions. Compute the constant value. If it has changed | 269 // Analysis of definitions. Compute the constant value. If it has changed |
| 302 // and the definition has input uses, add the definition to the definition | 270 // and the definition has input uses, add the definition to the definition |
| 303 // worklist so that the used can be processed. | 271 // worklist so that the used can be processed. |
| 304 void ConstantPropagator::VisitPhi(PhiInstr* instr) { | 272 void ConstantPropagator::VisitPhi(PhiInstr* instr) { |
| 305 // Compute the join over all the reachable predecessor values. | 273 // Compute the join over all the reachable predecessor values. |
| 306 JoinEntryInstr* block = instr->block(); | 274 JoinEntryInstr* block = instr->block(); |
| 307 Object& value = Object::ZoneHandle(Z, Unknown()); | 275 Object& value = Object::ZoneHandle(Z, Unknown()); |
| 308 for (intptr_t pred_idx = 0; pred_idx < instr->InputCount(); ++pred_idx) { | 276 for (intptr_t pred_idx = 0; pred_idx < instr->InputCount(); ++pred_idx) { |
| 309 if (reachable_->Contains( | 277 if (reachable_->Contains( |
| 310 block->PredecessorAt(pred_idx)->preorder_number())) { | 278 block->PredecessorAt(pred_idx)->preorder_number())) { |
| 311 Join(&value, instr->InputAt(pred_idx)->definition()->constant_value()); | 279 Join(&value, instr->InputAt(pred_idx)->definition()->constant_value()); |
| 312 } | 280 } |
| 313 } | 281 } |
| 314 if (!SetValue(instr, value) && | 282 if (!SetValue(instr, value) && |
| 315 marked_phis_->Contains(instr->ssa_temp_index())) { | 283 marked_phis_->Contains(instr->ssa_temp_index())) { |
| 316 marked_phis_->Remove(instr->ssa_temp_index()); | 284 marked_phis_->Remove(instr->ssa_temp_index()); |
| 317 definition_worklist_.Add(instr); | 285 definition_worklist_.Add(instr); |
| 318 } | 286 } |
| 319 } | 287 } |
| 320 | 288 |
| 321 | |
| 322 void ConstantPropagator::VisitRedefinition(RedefinitionInstr* instr) { | 289 void ConstantPropagator::VisitRedefinition(RedefinitionInstr* instr) { |
| 323 // Ensure that we never remove redefinition of a constant unless we are also | 290 // Ensure that we never remove redefinition of a constant unless we are also |
| 324 // are guaranteed to fold away code paths that correspond to non-matching | 291 // are guaranteed to fold away code paths that correspond to non-matching |
| 325 // class ids. Otherwise LICM might potentially hoist incorrect code. | 292 // class ids. Otherwise LICM might potentially hoist incorrect code. |
| 326 const Object& value = instr->value()->definition()->constant_value(); | 293 const Object& value = instr->value()->definition()->constant_value(); |
| 327 if (IsConstant(value) && !Field::IsExternalizableCid(value.GetClassId())) { | 294 if (IsConstant(value) && !Field::IsExternalizableCid(value.GetClassId())) { |
| 328 SetValue(instr, value); | 295 SetValue(instr, value); |
| 329 } else { | 296 } else { |
| 330 SetValue(instr, non_constant_); | 297 SetValue(instr, non_constant_); |
| 331 } | 298 } |
| 332 } | 299 } |
| 333 | 300 |
| 334 | |
| 335 void ConstantPropagator::VisitParameter(ParameterInstr* instr) { | 301 void ConstantPropagator::VisitParameter(ParameterInstr* instr) { |
| 336 SetValue(instr, non_constant_); | 302 SetValue(instr, non_constant_); |
| 337 } | 303 } |
| 338 | 304 |
| 339 | |
| 340 void ConstantPropagator::VisitPushArgument(PushArgumentInstr* instr) { | 305 void ConstantPropagator::VisitPushArgument(PushArgumentInstr* instr) { |
| 341 SetValue(instr, instr->value()->definition()->constant_value()); | 306 SetValue(instr, instr->value()->definition()->constant_value()); |
| 342 } | 307 } |
| 343 | 308 |
| 344 | |
| 345 void ConstantPropagator::VisitAssertAssignable(AssertAssignableInstr* instr) { | 309 void ConstantPropagator::VisitAssertAssignable(AssertAssignableInstr* instr) { |
| 346 const Object& value = instr->value()->definition()->constant_value(); | 310 const Object& value = instr->value()->definition()->constant_value(); |
| 347 if (IsNonConstant(value)) { | 311 if (IsNonConstant(value)) { |
| 348 SetValue(instr, non_constant_); | 312 SetValue(instr, non_constant_); |
| 349 } else if (IsConstant(value)) { | 313 } else if (IsConstant(value)) { |
| 350 // We are ignoring the instantiator and instantiator_type_arguments, but | 314 // We are ignoring the instantiator and instantiator_type_arguments, but |
| 351 // still monotonic and safe. | 315 // still monotonic and safe. |
| 352 if (instr->value()->Type()->IsAssignableTo(instr->dst_type())) { | 316 if (instr->value()->Type()->IsAssignableTo(instr->dst_type())) { |
| 353 SetValue(instr, value); | 317 SetValue(instr, value); |
| 354 } else { | 318 } else { |
| 355 SetValue(instr, non_constant_); | 319 SetValue(instr, non_constant_); |
| 356 } | 320 } |
| 357 } | 321 } |
| 358 } | 322 } |
| 359 | 323 |
| 360 | |
| 361 void ConstantPropagator::VisitAssertBoolean(AssertBooleanInstr* instr) { | 324 void ConstantPropagator::VisitAssertBoolean(AssertBooleanInstr* instr) { |
| 362 const Object& value = instr->value()->definition()->constant_value(); | 325 const Object& value = instr->value()->definition()->constant_value(); |
| 363 if (IsNonConstant(value)) { | 326 if (IsNonConstant(value)) { |
| 364 SetValue(instr, non_constant_); | 327 SetValue(instr, non_constant_); |
| 365 } else if (IsConstant(value)) { | 328 } else if (IsConstant(value)) { |
| 366 if (value.IsBool()) { | 329 if (value.IsBool()) { |
| 367 SetValue(instr, value); | 330 SetValue(instr, value); |
| 368 } else { | 331 } else { |
| 369 SetValue(instr, non_constant_); | 332 SetValue(instr, non_constant_); |
| 370 } | 333 } |
| 371 } | 334 } |
| 372 } | 335 } |
| 373 | 336 |
| 374 | |
| 375 void ConstantPropagator::VisitSpecialParameter(SpecialParameterInstr* instr) { | 337 void ConstantPropagator::VisitSpecialParameter(SpecialParameterInstr* instr) { |
| 376 SetValue(instr, non_constant_); | 338 SetValue(instr, non_constant_); |
| 377 } | 339 } |
| 378 | 340 |
| 379 | |
| 380 void ConstantPropagator::VisitClosureCall(ClosureCallInstr* instr) { | 341 void ConstantPropagator::VisitClosureCall(ClosureCallInstr* instr) { |
| 381 SetValue(instr, non_constant_); | 342 SetValue(instr, non_constant_); |
| 382 } | 343 } |
| 383 | 344 |
| 384 | |
| 385 void ConstantPropagator::VisitInstanceCall(InstanceCallInstr* instr) { | 345 void ConstantPropagator::VisitInstanceCall(InstanceCallInstr* instr) { |
| 386 SetValue(instr, non_constant_); | 346 SetValue(instr, non_constant_); |
| 387 } | 347 } |
| 388 | 348 |
| 389 | |
| 390 void ConstantPropagator::VisitPolymorphicInstanceCall( | 349 void ConstantPropagator::VisitPolymorphicInstanceCall( |
| 391 PolymorphicInstanceCallInstr* instr) { | 350 PolymorphicInstanceCallInstr* instr) { |
| 392 SetValue(instr, non_constant_); | 351 SetValue(instr, non_constant_); |
| 393 } | 352 } |
| 394 | 353 |
| 395 | |
| 396 void ConstantPropagator::VisitStaticCall(StaticCallInstr* instr) { | 354 void ConstantPropagator::VisitStaticCall(StaticCallInstr* instr) { |
| 397 SetValue(instr, non_constant_); | 355 SetValue(instr, non_constant_); |
| 398 } | 356 } |
| 399 | 357 |
| 400 | |
| 401 void ConstantPropagator::VisitLoadLocal(LoadLocalInstr* instr) { | 358 void ConstantPropagator::VisitLoadLocal(LoadLocalInstr* instr) { |
| 402 // Instruction is eliminated when translating to SSA. | 359 // Instruction is eliminated when translating to SSA. |
| 403 UNREACHABLE(); | 360 UNREACHABLE(); |
| 404 } | 361 } |
| 405 | 362 |
| 406 | |
| 407 void ConstantPropagator::VisitDropTemps(DropTempsInstr* instr) { | 363 void ConstantPropagator::VisitDropTemps(DropTempsInstr* instr) { |
| 408 // Instruction is eliminated when translating to SSA. | 364 // Instruction is eliminated when translating to SSA. |
| 409 UNREACHABLE(); | 365 UNREACHABLE(); |
| 410 } | 366 } |
| 411 | 367 |
| 412 | |
| 413 void ConstantPropagator::VisitStoreLocal(StoreLocalInstr* instr) { | 368 void ConstantPropagator::VisitStoreLocal(StoreLocalInstr* instr) { |
| 414 // Instruction is eliminated when translating to SSA. | 369 // Instruction is eliminated when translating to SSA. |
| 415 UNREACHABLE(); | 370 UNREACHABLE(); |
| 416 } | 371 } |
| 417 | 372 |
| 418 | |
| 419 void ConstantPropagator::VisitIfThenElse(IfThenElseInstr* instr) { | 373 void ConstantPropagator::VisitIfThenElse(IfThenElseInstr* instr) { |
| 420 instr->comparison()->Accept(this); | 374 instr->comparison()->Accept(this); |
| 421 const Object& value = instr->comparison()->constant_value(); | 375 const Object& value = instr->comparison()->constant_value(); |
| 422 if (IsNonConstant(value)) { | 376 if (IsNonConstant(value)) { |
| 423 SetValue(instr, non_constant_); | 377 SetValue(instr, non_constant_); |
| 424 } else if (IsConstant(value)) { | 378 } else if (IsConstant(value)) { |
| 425 ASSERT(!value.IsNull()); | 379 ASSERT(!value.IsNull()); |
| 426 ASSERT(value.IsBool()); | 380 ASSERT(value.IsBool()); |
| 427 bool result = Bool::Cast(value).value(); | 381 bool result = Bool::Cast(value).value(); |
| 428 SetValue(instr, Smi::Handle(Z, Smi::New(result ? instr->if_true() | 382 SetValue(instr, Smi::Handle(Z, Smi::New(result ? instr->if_true() |
| 429 : instr->if_false()))); | 383 : instr->if_false()))); |
| 430 } | 384 } |
| 431 } | 385 } |
| 432 | 386 |
| 433 | |
| 434 void ConstantPropagator::VisitStrictCompare(StrictCompareInstr* instr) { | 387 void ConstantPropagator::VisitStrictCompare(StrictCompareInstr* instr) { |
| 435 Definition* left_defn = instr->left()->definition(); | 388 Definition* left_defn = instr->left()->definition(); |
| 436 Definition* right_defn = instr->right()->definition(); | 389 Definition* right_defn = instr->right()->definition(); |
| 437 | 390 |
| 438 Definition* unwrapped_left_defn = UnwrapPhi(left_defn); | 391 Definition* unwrapped_left_defn = UnwrapPhi(left_defn); |
| 439 Definition* unwrapped_right_defn = UnwrapPhi(right_defn); | 392 Definition* unwrapped_right_defn = UnwrapPhi(right_defn); |
| 440 if (unwrapped_left_defn == unwrapped_right_defn) { | 393 if (unwrapped_left_defn == unwrapped_right_defn) { |
| 441 // Fold x === x, and x !== x to true/false. | 394 // Fold x === x, and x !== x to true/false. |
| 442 SetValue(instr, Bool::Get(instr->kind() == Token::kEQ_STRICT)); | 395 SetValue(instr, Bool::Get(instr->kind() == Token::kEQ_STRICT)); |
| 443 if (unwrapped_left_defn != left_defn) { | 396 if (unwrapped_left_defn != left_defn) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 476 } | 429 } |
| 477 } else if (IsConstant(left) && IsConstant(right)) { | 430 } else if (IsConstant(left) && IsConstant(right)) { |
| 478 bool result = (left.raw() == right.raw()); | 431 bool result = (left.raw() == right.raw()); |
| 479 if (instr->kind() == Token::kNE_STRICT) { | 432 if (instr->kind() == Token::kNE_STRICT) { |
| 480 result = !result; | 433 result = !result; |
| 481 } | 434 } |
| 482 SetValue(instr, Bool::Get(result)); | 435 SetValue(instr, Bool::Get(result)); |
| 483 } | 436 } |
| 484 } | 437 } |
| 485 | 438 |
| 486 | |
| 487 static bool CompareIntegers(Token::Kind kind, | 439 static bool CompareIntegers(Token::Kind kind, |
| 488 const Integer& left, | 440 const Integer& left, |
| 489 const Integer& right) { | 441 const Integer& right) { |
| 490 const int result = left.CompareWith(right); | 442 const int result = left.CompareWith(right); |
| 491 switch (kind) { | 443 switch (kind) { |
| 492 case Token::kEQ: | 444 case Token::kEQ: |
| 493 return (result == 0); | 445 return (result == 0); |
| 494 case Token::kNE: | 446 case Token::kNE: |
| 495 return (result != 0); | 447 return (result != 0); |
| 496 case Token::kLT: | 448 case Token::kLT: |
| 497 return (result < 0); | 449 return (result < 0); |
| 498 case Token::kGT: | 450 case Token::kGT: |
| 499 return (result > 0); | 451 return (result > 0); |
| 500 case Token::kLTE: | 452 case Token::kLTE: |
| 501 return (result <= 0); | 453 return (result <= 0); |
| 502 case Token::kGTE: | 454 case Token::kGTE: |
| 503 return (result >= 0); | 455 return (result >= 0); |
| 504 default: | 456 default: |
| 505 UNREACHABLE(); | 457 UNREACHABLE(); |
| 506 return false; | 458 return false; |
| 507 } | 459 } |
| 508 } | 460 } |
| 509 | 461 |
| 510 | |
| 511 // Comparison instruction that is equivalent to the (left & right) == 0 | 462 // Comparison instruction that is equivalent to the (left & right) == 0 |
| 512 // comparison pattern. | 463 // comparison pattern. |
| 513 void ConstantPropagator::VisitTestSmi(TestSmiInstr* instr) { | 464 void ConstantPropagator::VisitTestSmi(TestSmiInstr* instr) { |
| 514 const Object& left = instr->left()->definition()->constant_value(); | 465 const Object& left = instr->left()->definition()->constant_value(); |
| 515 const Object& right = instr->right()->definition()->constant_value(); | 466 const Object& right = instr->right()->definition()->constant_value(); |
| 516 if (IsNonConstant(left) || IsNonConstant(right)) { | 467 if (IsNonConstant(left) || IsNonConstant(right)) { |
| 517 SetValue(instr, non_constant_); | 468 SetValue(instr, non_constant_); |
| 518 } else if (IsConstant(left) && IsConstant(right)) { | 469 } else if (IsConstant(left) && IsConstant(right)) { |
| 519 // BitOp does not work on Bigints. | 470 // BitOp does not work on Bigints. |
| 520 if (left.IsInteger() && right.IsInteger() && !left.IsBigint() && | 471 if (left.IsInteger() && right.IsInteger() && !left.IsBigint() && |
| 521 !right.IsBigint()) { | 472 !right.IsBigint()) { |
| 522 const bool result = CompareIntegers( | 473 const bool result = CompareIntegers( |
| 523 instr->kind(), | 474 instr->kind(), |
| 524 Integer::Handle(Z, Integer::Cast(left).BitOp(Token::kBIT_AND, | 475 Integer::Handle(Z, Integer::Cast(left).BitOp(Token::kBIT_AND, |
| 525 Integer::Cast(right))), | 476 Integer::Cast(right))), |
| 526 Smi::Handle(Z, Smi::New(0))); | 477 Smi::Handle(Z, Smi::New(0))); |
| 527 SetValue(instr, result ? Bool::True() : Bool::False()); | 478 SetValue(instr, result ? Bool::True() : Bool::False()); |
| 528 } else { | 479 } else { |
| 529 SetValue(instr, non_constant_); | 480 SetValue(instr, non_constant_); |
| 530 } | 481 } |
| 531 } | 482 } |
| 532 } | 483 } |
| 533 | 484 |
| 534 | |
| 535 void ConstantPropagator::VisitTestCids(TestCidsInstr* instr) { | 485 void ConstantPropagator::VisitTestCids(TestCidsInstr* instr) { |
| 536 // TODO(sra): Constant fold test. | 486 // TODO(sra): Constant fold test. |
| 537 SetValue(instr, non_constant_); | 487 SetValue(instr, non_constant_); |
| 538 } | 488 } |
| 539 | 489 |
| 540 | |
| 541 void ConstantPropagator::VisitEqualityCompare(EqualityCompareInstr* instr) { | 490 void ConstantPropagator::VisitEqualityCompare(EqualityCompareInstr* instr) { |
| 542 Definition* left_defn = instr->left()->definition(); | 491 Definition* left_defn = instr->left()->definition(); |
| 543 Definition* right_defn = instr->right()->definition(); | 492 Definition* right_defn = instr->right()->definition(); |
| 544 | 493 |
| 545 if (RawObject::IsIntegerClassId(instr->operation_cid())) { | 494 if (RawObject::IsIntegerClassId(instr->operation_cid())) { |
| 546 // Fold x == x, and x != x to true/false for numbers comparisons. | 495 // Fold x == x, and x != x to true/false for numbers comparisons. |
| 547 Definition* unwrapped_left_defn = UnwrapPhi(left_defn); | 496 Definition* unwrapped_left_defn = UnwrapPhi(left_defn); |
| 548 Definition* unwrapped_right_defn = UnwrapPhi(right_defn); | 497 Definition* unwrapped_right_defn = UnwrapPhi(right_defn); |
| 549 if (unwrapped_left_defn == unwrapped_right_defn) { | 498 if (unwrapped_left_defn == unwrapped_right_defn) { |
| 550 // Fold x === x, and x !== x to true/false. | 499 // Fold x === x, and x !== x to true/false. |
| (...skipping 19 matching lines...) Expand all Loading... |
| 570 SetValue(instr, Bool::Get(result)); | 519 SetValue(instr, Bool::Get(result)); |
| 571 } else if (left.IsString() && right.IsString()) { | 520 } else if (left.IsString() && right.IsString()) { |
| 572 const bool result = String::Cast(left).Equals(String::Cast(right)); | 521 const bool result = String::Cast(left).Equals(String::Cast(right)); |
| 573 SetValue(instr, Bool::Get((instr->kind() == Token::kEQ) == result)); | 522 SetValue(instr, Bool::Get((instr->kind() == Token::kEQ) == result)); |
| 574 } else { | 523 } else { |
| 575 SetValue(instr, non_constant_); | 524 SetValue(instr, non_constant_); |
| 576 } | 525 } |
| 577 } | 526 } |
| 578 } | 527 } |
| 579 | 528 |
| 580 | |
| 581 void ConstantPropagator::VisitRelationalOp(RelationalOpInstr* instr) { | 529 void ConstantPropagator::VisitRelationalOp(RelationalOpInstr* instr) { |
| 582 const Object& left = instr->left()->definition()->constant_value(); | 530 const Object& left = instr->left()->definition()->constant_value(); |
| 583 const Object& right = instr->right()->definition()->constant_value(); | 531 const Object& right = instr->right()->definition()->constant_value(); |
| 584 if (IsNonConstant(left) || IsNonConstant(right)) { | 532 if (IsNonConstant(left) || IsNonConstant(right)) { |
| 585 SetValue(instr, non_constant_); | 533 SetValue(instr, non_constant_); |
| 586 } else if (IsConstant(left) && IsConstant(right)) { | 534 } else if (IsConstant(left) && IsConstant(right)) { |
| 587 if (left.IsInteger() && right.IsInteger()) { | 535 if (left.IsInteger() && right.IsInteger()) { |
| 588 const bool result = CompareIntegers(instr->kind(), Integer::Cast(left), | 536 const bool result = CompareIntegers(instr->kind(), Integer::Cast(left), |
| 589 Integer::Cast(right)); | 537 Integer::Cast(right)); |
| 590 SetValue(instr, Bool::Get(result)); | 538 SetValue(instr, Bool::Get(result)); |
| 591 } else if (left.IsDouble() && right.IsDouble()) { | 539 } else if (left.IsDouble() && right.IsDouble()) { |
| 592 // TODO(srdjan): Implement. | 540 // TODO(srdjan): Implement. |
| 593 SetValue(instr, non_constant_); | 541 SetValue(instr, non_constant_); |
| 594 } else { | 542 } else { |
| 595 SetValue(instr, non_constant_); | 543 SetValue(instr, non_constant_); |
| 596 } | 544 } |
| 597 } | 545 } |
| 598 } | 546 } |
| 599 | 547 |
| 600 | |
| 601 void ConstantPropagator::VisitNativeCall(NativeCallInstr* instr) { | 548 void ConstantPropagator::VisitNativeCall(NativeCallInstr* instr) { |
| 602 SetValue(instr, non_constant_); | 549 SetValue(instr, non_constant_); |
| 603 } | 550 } |
| 604 | 551 |
| 605 | |
| 606 void ConstantPropagator::VisitDebugStepCheck(DebugStepCheckInstr* instr) { | 552 void ConstantPropagator::VisitDebugStepCheck(DebugStepCheckInstr* instr) { |
| 607 // Nothing to do. | 553 // Nothing to do. |
| 608 } | 554 } |
| 609 | 555 |
| 610 | |
| 611 void ConstantPropagator::VisitOneByteStringFromCharCode( | 556 void ConstantPropagator::VisitOneByteStringFromCharCode( |
| 612 OneByteStringFromCharCodeInstr* instr) { | 557 OneByteStringFromCharCodeInstr* instr) { |
| 613 const Object& o = instr->char_code()->definition()->constant_value(); | 558 const Object& o = instr->char_code()->definition()->constant_value(); |
| 614 if (o.IsNull() || IsNonConstant(o)) { | 559 if (o.IsNull() || IsNonConstant(o)) { |
| 615 SetValue(instr, non_constant_); | 560 SetValue(instr, non_constant_); |
| 616 } else if (IsConstant(o)) { | 561 } else if (IsConstant(o)) { |
| 617 const intptr_t ch_code = Smi::Cast(o).Value(); | 562 const intptr_t ch_code = Smi::Cast(o).Value(); |
| 618 ASSERT(ch_code >= 0); | 563 ASSERT(ch_code >= 0); |
| 619 if (ch_code < Symbols::kMaxOneCharCodeSymbol) { | 564 if (ch_code < Symbols::kMaxOneCharCodeSymbol) { |
| 620 RawString** table = Symbols::PredefinedAddress(); | 565 RawString** table = Symbols::PredefinedAddress(); |
| 621 SetValue(instr, String::ZoneHandle(Z, table[ch_code])); | 566 SetValue(instr, String::ZoneHandle(Z, table[ch_code])); |
| 622 } else { | 567 } else { |
| 623 SetValue(instr, non_constant_); | 568 SetValue(instr, non_constant_); |
| 624 } | 569 } |
| 625 } | 570 } |
| 626 } | 571 } |
| 627 | 572 |
| 628 | |
| 629 void ConstantPropagator::VisitStringToCharCode(StringToCharCodeInstr* instr) { | 573 void ConstantPropagator::VisitStringToCharCode(StringToCharCodeInstr* instr) { |
| 630 const Object& o = instr->str()->definition()->constant_value(); | 574 const Object& o = instr->str()->definition()->constant_value(); |
| 631 if (o.IsNull() || IsNonConstant(o)) { | 575 if (o.IsNull() || IsNonConstant(o)) { |
| 632 SetValue(instr, non_constant_); | 576 SetValue(instr, non_constant_); |
| 633 } else if (IsConstant(o)) { | 577 } else if (IsConstant(o)) { |
| 634 const String& str = String::Cast(o); | 578 const String& str = String::Cast(o); |
| 635 const intptr_t result = | 579 const intptr_t result = |
| 636 (str.Length() == 1) ? static_cast<intptr_t>(str.CharAt(0)) : -1; | 580 (str.Length() == 1) ? static_cast<intptr_t>(str.CharAt(0)) : -1; |
| 637 SetValue(instr, Smi::ZoneHandle(Z, Smi::New(result))); | 581 SetValue(instr, Smi::ZoneHandle(Z, Smi::New(result))); |
| 638 } | 582 } |
| 639 } | 583 } |
| 640 | 584 |
| 641 | |
| 642 void ConstantPropagator::VisitStringInterpolate(StringInterpolateInstr* instr) { | 585 void ConstantPropagator::VisitStringInterpolate(StringInterpolateInstr* instr) { |
| 643 SetValue(instr, non_constant_); | 586 SetValue(instr, non_constant_); |
| 644 } | 587 } |
| 645 | 588 |
| 646 | |
| 647 void ConstantPropagator::VisitLoadIndexed(LoadIndexedInstr* instr) { | 589 void ConstantPropagator::VisitLoadIndexed(LoadIndexedInstr* instr) { |
| 648 const Object& array_obj = instr->array()->definition()->constant_value(); | 590 const Object& array_obj = instr->array()->definition()->constant_value(); |
| 649 const Object& index_obj = instr->index()->definition()->constant_value(); | 591 const Object& index_obj = instr->index()->definition()->constant_value(); |
| 650 if (IsNonConstant(array_obj) || IsNonConstant(index_obj)) { | 592 if (IsNonConstant(array_obj) || IsNonConstant(index_obj)) { |
| 651 SetValue(instr, non_constant_); | 593 SetValue(instr, non_constant_); |
| 652 } else if (IsConstant(array_obj) && IsConstant(index_obj)) { | 594 } else if (IsConstant(array_obj) && IsConstant(index_obj)) { |
| 653 // Need index to be Smi and array to be either String or an immutable array. | 595 // Need index to be Smi and array to be either String or an immutable array. |
| 654 if (!index_obj.IsSmi()) { | 596 if (!index_obj.IsSmi()) { |
| 655 // Should not occur. | 597 // Should not occur. |
| 656 SetValue(instr, non_constant_); | 598 SetValue(instr, non_constant_); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 673 result ^= a.At(index); | 615 result ^= a.At(index); |
| 674 SetValue(instr, result); | 616 SetValue(instr, result); |
| 675 return; | 617 return; |
| 676 } | 618 } |
| 677 } | 619 } |
| 678 } | 620 } |
| 679 SetValue(instr, non_constant_); | 621 SetValue(instr, non_constant_); |
| 680 } | 622 } |
| 681 } | 623 } |
| 682 | 624 |
| 683 | |
| 684 void ConstantPropagator::VisitLoadCodeUnits(LoadCodeUnitsInstr* instr) { | 625 void ConstantPropagator::VisitLoadCodeUnits(LoadCodeUnitsInstr* instr) { |
| 685 // TODO(zerny): Implement constant propagation. | 626 // TODO(zerny): Implement constant propagation. |
| 686 SetValue(instr, non_constant_); | 627 SetValue(instr, non_constant_); |
| 687 } | 628 } |
| 688 | 629 |
| 689 | |
| 690 void ConstantPropagator::VisitStoreIndexed(StoreIndexedInstr* instr) { | 630 void ConstantPropagator::VisitStoreIndexed(StoreIndexedInstr* instr) { |
| 691 SetValue(instr, instr->value()->definition()->constant_value()); | 631 SetValue(instr, instr->value()->definition()->constant_value()); |
| 692 } | 632 } |
| 693 | 633 |
| 694 | |
| 695 void ConstantPropagator::VisitStoreInstanceField( | 634 void ConstantPropagator::VisitStoreInstanceField( |
| 696 StoreInstanceFieldInstr* instr) { | 635 StoreInstanceFieldInstr* instr) { |
| 697 SetValue(instr, instr->value()->definition()->constant_value()); | 636 SetValue(instr, instr->value()->definition()->constant_value()); |
| 698 } | 637 } |
| 699 | 638 |
| 700 | |
| 701 void ConstantPropagator::VisitInitStaticField(InitStaticFieldInstr* instr) { | 639 void ConstantPropagator::VisitInitStaticField(InitStaticFieldInstr* instr) { |
| 702 // Nothing to do. | 640 // Nothing to do. |
| 703 } | 641 } |
| 704 | 642 |
| 705 | |
| 706 void ConstantPropagator::VisitLoadStaticField(LoadStaticFieldInstr* instr) { | 643 void ConstantPropagator::VisitLoadStaticField(LoadStaticFieldInstr* instr) { |
| 707 if (!FLAG_fields_may_be_reset) { | 644 if (!FLAG_fields_may_be_reset) { |
| 708 const Field& field = instr->StaticField(); | 645 const Field& field = instr->StaticField(); |
| 709 ASSERT(field.is_static()); | 646 ASSERT(field.is_static()); |
| 710 Instance& obj = Instance::Handle(Z, field.StaticValue()); | 647 Instance& obj = Instance::Handle(Z, field.StaticValue()); |
| 711 if (field.is_final() && (obj.raw() != Object::sentinel().raw()) && | 648 if (field.is_final() && (obj.raw() != Object::sentinel().raw()) && |
| 712 (obj.raw() != Object::transition_sentinel().raw())) { | 649 (obj.raw() != Object::transition_sentinel().raw())) { |
| 713 if (obj.IsSmi() || obj.IsOld()) { | 650 if (obj.IsSmi() || obj.IsOld()) { |
| 714 SetValue(instr, obj); | 651 SetValue(instr, obj); |
| 715 return; | 652 return; |
| 716 } | 653 } |
| 717 } | 654 } |
| 718 } | 655 } |
| 719 SetValue(instr, non_constant_); | 656 SetValue(instr, non_constant_); |
| 720 } | 657 } |
| 721 | 658 |
| 722 | |
| 723 void ConstantPropagator::VisitStoreStaticField(StoreStaticFieldInstr* instr) { | 659 void ConstantPropagator::VisitStoreStaticField(StoreStaticFieldInstr* instr) { |
| 724 SetValue(instr, instr->value()->definition()->constant_value()); | 660 SetValue(instr, instr->value()->definition()->constant_value()); |
| 725 } | 661 } |
| 726 | 662 |
| 727 | |
| 728 void ConstantPropagator::VisitBooleanNegate(BooleanNegateInstr* instr) { | 663 void ConstantPropagator::VisitBooleanNegate(BooleanNegateInstr* instr) { |
| 729 const Object& value = instr->value()->definition()->constant_value(); | 664 const Object& value = instr->value()->definition()->constant_value(); |
| 730 if (IsNonConstant(value)) { | 665 if (IsNonConstant(value)) { |
| 731 SetValue(instr, non_constant_); | 666 SetValue(instr, non_constant_); |
| 732 } else if (IsConstant(value)) { | 667 } else if (IsConstant(value)) { |
| 733 bool val = value.raw() != Bool::True().raw(); | 668 bool val = value.raw() != Bool::True().raw(); |
| 734 SetValue(instr, Bool::Get(val)); | 669 SetValue(instr, Bool::Get(val)); |
| 735 } | 670 } |
| 736 } | 671 } |
| 737 | 672 |
| 738 | |
| 739 void ConstantPropagator::VisitInstanceOf(InstanceOfInstr* instr) { | 673 void ConstantPropagator::VisitInstanceOf(InstanceOfInstr* instr) { |
| 740 Definition* def = instr->value()->definition(); | 674 Definition* def = instr->value()->definition(); |
| 741 const Object& value = def->constant_value(); | 675 const Object& value = def->constant_value(); |
| 742 if (IsNonConstant(value)) { | 676 if (IsNonConstant(value)) { |
| 743 const AbstractType& checked_type = instr->type(); | 677 const AbstractType& checked_type = instr->type(); |
| 744 intptr_t value_cid = instr->value()->definition()->Type()->ToCid(); | 678 intptr_t value_cid = instr->value()->definition()->Type()->ToCid(); |
| 745 Representation rep = def->representation(); | 679 Representation rep = def->representation(); |
| 746 if ((checked_type.IsFloat32x4Type() && (rep == kUnboxedFloat32x4)) || | 680 if ((checked_type.IsFloat32x4Type() && (rep == kUnboxedFloat32x4)) || |
| 747 (checked_type.IsInt32x4Type() && (rep == kUnboxedInt32x4)) || | 681 (checked_type.IsInt32x4Type() && (rep == kUnboxedInt32x4)) || |
| 748 (checked_type.IsDoubleType() && (rep == kUnboxedDouble) && | 682 (checked_type.IsDoubleType() && (rep == kUnboxedDouble) && |
| (...skipping 22 matching lines...) Expand all Loading... |
| 771 // Can only have bound error with generics. | 705 // Can only have bound error with generics. |
| 772 ASSERT(bound_error.IsNull()); | 706 ASSERT(bound_error.IsNull()); |
| 773 SetValue(instr, Bool::Get(is_instance)); | 707 SetValue(instr, Bool::Get(is_instance)); |
| 774 return; | 708 return; |
| 775 } | 709 } |
| 776 } | 710 } |
| 777 SetValue(instr, non_constant_); | 711 SetValue(instr, non_constant_); |
| 778 } | 712 } |
| 779 } | 713 } |
| 780 | 714 |
| 781 | |
| 782 void ConstantPropagator::VisitCreateArray(CreateArrayInstr* instr) { | 715 void ConstantPropagator::VisitCreateArray(CreateArrayInstr* instr) { |
| 783 SetValue(instr, non_constant_); | 716 SetValue(instr, non_constant_); |
| 784 } | 717 } |
| 785 | 718 |
| 786 | |
| 787 void ConstantPropagator::VisitAllocateObject(AllocateObjectInstr* instr) { | 719 void ConstantPropagator::VisitAllocateObject(AllocateObjectInstr* instr) { |
| 788 SetValue(instr, non_constant_); | 720 SetValue(instr, non_constant_); |
| 789 } | 721 } |
| 790 | 722 |
| 791 | |
| 792 void ConstantPropagator::VisitLoadUntagged(LoadUntaggedInstr* instr) { | 723 void ConstantPropagator::VisitLoadUntagged(LoadUntaggedInstr* instr) { |
| 793 SetValue(instr, non_constant_); | 724 SetValue(instr, non_constant_); |
| 794 } | 725 } |
| 795 | 726 |
| 796 | |
| 797 void ConstantPropagator::VisitLoadClassId(LoadClassIdInstr* instr) { | 727 void ConstantPropagator::VisitLoadClassId(LoadClassIdInstr* instr) { |
| 798 intptr_t cid = instr->object()->Type()->ToCid(); | 728 intptr_t cid = instr->object()->Type()->ToCid(); |
| 799 if (cid != kDynamicCid) { | 729 if (cid != kDynamicCid) { |
| 800 SetValue(instr, Smi::ZoneHandle(Z, Smi::New(cid))); | 730 SetValue(instr, Smi::ZoneHandle(Z, Smi::New(cid))); |
| 801 return; | 731 return; |
| 802 } | 732 } |
| 803 | 733 |
| 804 const Object& object = instr->object()->definition()->constant_value(); | 734 const Object& object = instr->object()->definition()->constant_value(); |
| 805 if (IsConstant(object)) { | 735 if (IsConstant(object)) { |
| 806 cid = object.GetClassId(); | 736 cid = object.GetClassId(); |
| 807 if (!Field::IsExternalizableCid(cid)) { | 737 if (!Field::IsExternalizableCid(cid)) { |
| 808 SetValue(instr, Smi::ZoneHandle(Z, Smi::New(cid))); | 738 SetValue(instr, Smi::ZoneHandle(Z, Smi::New(cid))); |
| 809 return; | 739 return; |
| 810 } | 740 } |
| 811 } | 741 } |
| 812 SetValue(instr, non_constant_); | 742 SetValue(instr, non_constant_); |
| 813 } | 743 } |
| 814 | 744 |
| 815 | |
| 816 void ConstantPropagator::VisitLoadField(LoadFieldInstr* instr) { | 745 void ConstantPropagator::VisitLoadField(LoadFieldInstr* instr) { |
| 817 Value* instance = instr->instance(); | 746 Value* instance = instr->instance(); |
| 818 if ((instr->recognized_kind() == MethodRecognizer::kObjectArrayLength) && | 747 if ((instr->recognized_kind() == MethodRecognizer::kObjectArrayLength) && |
| 819 instance->definition()->OriginalDefinition()->IsCreateArray()) { | 748 instance->definition()->OriginalDefinition()->IsCreateArray()) { |
| 820 Value* num_elements = instance->definition() | 749 Value* num_elements = instance->definition() |
| 821 ->OriginalDefinition() | 750 ->OriginalDefinition() |
| 822 ->AsCreateArray() | 751 ->AsCreateArray() |
| 823 ->num_elements(); | 752 ->num_elements(); |
| 824 if (num_elements->BindsToConstant() && | 753 if (num_elements->BindsToConstant() && |
| 825 num_elements->BoundConstant().IsSmi()) { | 754 num_elements->BoundConstant().IsSmi()) { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 853 if (instr->Evaluate(constant, &value)) { | 782 if (instr->Evaluate(constant, &value)) { |
| 854 SetValue(instr, Object::ZoneHandle(Z, value.raw())); | 783 SetValue(instr, Object::ZoneHandle(Z, value.raw())); |
| 855 return; | 784 return; |
| 856 } | 785 } |
| 857 } | 786 } |
| 858 } | 787 } |
| 859 | 788 |
| 860 SetValue(instr, non_constant_); | 789 SetValue(instr, non_constant_); |
| 861 } | 790 } |
| 862 | 791 |
| 863 | |
| 864 void ConstantPropagator::VisitInstantiateType(InstantiateTypeInstr* instr) { | 792 void ConstantPropagator::VisitInstantiateType(InstantiateTypeInstr* instr) { |
| 865 const Object& object = | 793 const Object& object = |
| 866 instr->instantiator_type_arguments()->definition()->constant_value(); | 794 instr->instantiator_type_arguments()->definition()->constant_value(); |
| 867 if (IsNonConstant(object)) { | 795 if (IsNonConstant(object)) { |
| 868 SetValue(instr, non_constant_); | 796 SetValue(instr, non_constant_); |
| 869 return; | 797 return; |
| 870 } | 798 } |
| 871 if (IsConstant(object)) { | 799 if (IsConstant(object)) { |
| 872 if (instr->type().IsTypeParameter() && | 800 if (instr->type().IsTypeParameter() && |
| 873 TypeParameter::Cast(instr->type()).IsClassTypeParameter()) { | 801 TypeParameter::Cast(instr->type()).IsClassTypeParameter()) { |
| 874 if (object.IsNull()) { | 802 if (object.IsNull()) { |
| 875 SetValue(instr, Object::dynamic_type()); | 803 SetValue(instr, Object::dynamic_type()); |
| 876 return; | 804 return; |
| 877 } | 805 } |
| 878 // We could try to instantiate the type parameter and return it if no | 806 // We could try to instantiate the type parameter and return it if no |
| 879 // malformed error is reported. | 807 // malformed error is reported. |
| 880 } | 808 } |
| 881 SetValue(instr, non_constant_); | 809 SetValue(instr, non_constant_); |
| 882 } | 810 } |
| 883 // TODO(regis): We can do the same as above for a function type parameter. | 811 // TODO(regis): We can do the same as above for a function type parameter. |
| 884 // Better: If both instantiator type arguments and function type arguments are | 812 // Better: If both instantiator type arguments and function type arguments are |
| 885 // constant, instantiate the type if no bound error is reported. | 813 // constant, instantiate the type if no bound error is reported. |
| 886 } | 814 } |
| 887 | 815 |
| 888 | |
| 889 void ConstantPropagator::VisitInstantiateTypeArguments( | 816 void ConstantPropagator::VisitInstantiateTypeArguments( |
| 890 InstantiateTypeArgumentsInstr* instr) { | 817 InstantiateTypeArgumentsInstr* instr) { |
| 891 const Object& instantiator_type_args = | 818 const Object& instantiator_type_args = |
| 892 instr->instantiator_type_arguments()->definition()->constant_value(); | 819 instr->instantiator_type_arguments()->definition()->constant_value(); |
| 893 const Object& function_type_args = | 820 const Object& function_type_args = |
| 894 instr->function_type_arguments()->definition()->constant_value(); | 821 instr->function_type_arguments()->definition()->constant_value(); |
| 895 if (IsNonConstant(instantiator_type_args) || | 822 if (IsNonConstant(instantiator_type_args) || |
| 896 IsNonConstant(function_type_args)) { | 823 IsNonConstant(function_type_args)) { |
| 897 SetValue(instr, non_constant_); | 824 SetValue(instr, non_constant_); |
| 898 return; | 825 return; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 915 } | 842 } |
| 916 // TODO(regis): If both instantiator type arguments and function type | 843 // TODO(regis): If both instantiator type arguments and function type |
| 917 // arguments are constant, instantiate the type arguments if no bound error | 844 // arguments are constant, instantiate the type arguments if no bound error |
| 918 // is reported. | 845 // is reported. |
| 919 // TODO(regis): If either instantiator type arguments or function type | 846 // TODO(regis): If either instantiator type arguments or function type |
| 920 // arguments are constant null, check | 847 // arguments are constant null, check |
| 921 // type_arguments().IsRawWhenInstantiatedFromRaw() separately for each | 848 // type_arguments().IsRawWhenInstantiatedFromRaw() separately for each |
| 922 // genericity. | 849 // genericity. |
| 923 } | 850 } |
| 924 | 851 |
| 925 | |
| 926 void ConstantPropagator::VisitAllocateContext(AllocateContextInstr* instr) { | 852 void ConstantPropagator::VisitAllocateContext(AllocateContextInstr* instr) { |
| 927 SetValue(instr, non_constant_); | 853 SetValue(instr, non_constant_); |
| 928 } | 854 } |
| 929 | 855 |
| 930 | |
| 931 void ConstantPropagator::VisitAllocateUninitializedContext( | 856 void ConstantPropagator::VisitAllocateUninitializedContext( |
| 932 AllocateUninitializedContextInstr* instr) { | 857 AllocateUninitializedContextInstr* instr) { |
| 933 SetValue(instr, non_constant_); | 858 SetValue(instr, non_constant_); |
| 934 } | 859 } |
| 935 | 860 |
| 936 | |
| 937 void ConstantPropagator::VisitCloneContext(CloneContextInstr* instr) { | 861 void ConstantPropagator::VisitCloneContext(CloneContextInstr* instr) { |
| 938 SetValue(instr, non_constant_); | 862 SetValue(instr, non_constant_); |
| 939 } | 863 } |
| 940 | 864 |
| 941 | |
| 942 void ConstantPropagator::VisitBinaryIntegerOp(BinaryIntegerOpInstr* binary_op) { | 865 void ConstantPropagator::VisitBinaryIntegerOp(BinaryIntegerOpInstr* binary_op) { |
| 943 const Object& left = binary_op->left()->definition()->constant_value(); | 866 const Object& left = binary_op->left()->definition()->constant_value(); |
| 944 const Object& right = binary_op->right()->definition()->constant_value(); | 867 const Object& right = binary_op->right()->definition()->constant_value(); |
| 945 if (IsConstant(left) && IsConstant(right)) { | 868 if (IsConstant(left) && IsConstant(right)) { |
| 946 if (left.IsInteger() && right.IsInteger()) { | 869 if (left.IsInteger() && right.IsInteger()) { |
| 947 const Integer& left_int = Integer::Cast(left); | 870 const Integer& left_int = Integer::Cast(left); |
| 948 const Integer& right_int = Integer::Cast(right); | 871 const Integer& right_int = Integer::Cast(right); |
| 949 const Integer& result = | 872 const Integer& result = |
| 950 Integer::Handle(Z, binary_op->Evaluate(left_int, right_int)); | 873 Integer::Handle(Z, binary_op->Evaluate(left_int, right_int)); |
| 951 if (!result.IsNull()) { | 874 if (!result.IsNull()) { |
| 952 SetValue(binary_op, Integer::ZoneHandle(Z, result.raw())); | 875 SetValue(binary_op, Integer::ZoneHandle(Z, result.raw())); |
| 953 return; | 876 return; |
| 954 } | 877 } |
| 955 } | 878 } |
| 956 } | 879 } |
| 957 | 880 |
| 958 SetValue(binary_op, non_constant_); | 881 SetValue(binary_op, non_constant_); |
| 959 } | 882 } |
| 960 | 883 |
| 961 | |
| 962 void ConstantPropagator::VisitCheckedSmiOp(CheckedSmiOpInstr* instr) { | 884 void ConstantPropagator::VisitCheckedSmiOp(CheckedSmiOpInstr* instr) { |
| 963 SetValue(instr, non_constant_); | 885 SetValue(instr, non_constant_); |
| 964 } | 886 } |
| 965 | 887 |
| 966 | |
| 967 void ConstantPropagator::VisitCheckedSmiComparison( | 888 void ConstantPropagator::VisitCheckedSmiComparison( |
| 968 CheckedSmiComparisonInstr* instr) { | 889 CheckedSmiComparisonInstr* instr) { |
| 969 SetValue(instr, non_constant_); | 890 SetValue(instr, non_constant_); |
| 970 } | 891 } |
| 971 | 892 |
| 972 | |
| 973 void ConstantPropagator::VisitBinarySmiOp(BinarySmiOpInstr* instr) { | 893 void ConstantPropagator::VisitBinarySmiOp(BinarySmiOpInstr* instr) { |
| 974 VisitBinaryIntegerOp(instr); | 894 VisitBinaryIntegerOp(instr); |
| 975 } | 895 } |
| 976 | 896 |
| 977 | |
| 978 void ConstantPropagator::VisitBinaryInt32Op(BinaryInt32OpInstr* instr) { | 897 void ConstantPropagator::VisitBinaryInt32Op(BinaryInt32OpInstr* instr) { |
| 979 VisitBinaryIntegerOp(instr); | 898 VisitBinaryIntegerOp(instr); |
| 980 } | 899 } |
| 981 | 900 |
| 982 | |
| 983 void ConstantPropagator::VisitBinaryUint32Op(BinaryUint32OpInstr* instr) { | 901 void ConstantPropagator::VisitBinaryUint32Op(BinaryUint32OpInstr* instr) { |
| 984 VisitBinaryIntegerOp(instr); | 902 VisitBinaryIntegerOp(instr); |
| 985 } | 903 } |
| 986 | 904 |
| 987 | |
| 988 void ConstantPropagator::VisitShiftUint32Op(ShiftUint32OpInstr* instr) { | 905 void ConstantPropagator::VisitShiftUint32Op(ShiftUint32OpInstr* instr) { |
| 989 VisitBinaryIntegerOp(instr); | 906 VisitBinaryIntegerOp(instr); |
| 990 } | 907 } |
| 991 | 908 |
| 992 | |
| 993 void ConstantPropagator::VisitBinaryMintOp(BinaryMintOpInstr* instr) { | 909 void ConstantPropagator::VisitBinaryMintOp(BinaryMintOpInstr* instr) { |
| 994 VisitBinaryIntegerOp(instr); | 910 VisitBinaryIntegerOp(instr); |
| 995 } | 911 } |
| 996 | 912 |
| 997 | |
| 998 void ConstantPropagator::VisitShiftMintOp(ShiftMintOpInstr* instr) { | 913 void ConstantPropagator::VisitShiftMintOp(ShiftMintOpInstr* instr) { |
| 999 VisitBinaryIntegerOp(instr); | 914 VisitBinaryIntegerOp(instr); |
| 1000 } | 915 } |
| 1001 | 916 |
| 1002 | |
| 1003 void ConstantPropagator::VisitBoxInt64(BoxInt64Instr* instr) { | 917 void ConstantPropagator::VisitBoxInt64(BoxInt64Instr* instr) { |
| 1004 // TODO(kmillikin): Handle box operation. | 918 // TODO(kmillikin): Handle box operation. |
| 1005 SetValue(instr, non_constant_); | 919 SetValue(instr, non_constant_); |
| 1006 } | 920 } |
| 1007 | 921 |
| 1008 | |
| 1009 void ConstantPropagator::VisitUnboxInt64(UnboxInt64Instr* instr) { | 922 void ConstantPropagator::VisitUnboxInt64(UnboxInt64Instr* instr) { |
| 1010 // TODO(kmillikin): Handle unbox operation. | 923 // TODO(kmillikin): Handle unbox operation. |
| 1011 SetValue(instr, non_constant_); | 924 SetValue(instr, non_constant_); |
| 1012 } | 925 } |
| 1013 | 926 |
| 1014 | |
| 1015 void ConstantPropagator::VisitUnaryIntegerOp(UnaryIntegerOpInstr* unary_op) { | 927 void ConstantPropagator::VisitUnaryIntegerOp(UnaryIntegerOpInstr* unary_op) { |
| 1016 const Object& value = unary_op->value()->definition()->constant_value(); | 928 const Object& value = unary_op->value()->definition()->constant_value(); |
| 1017 if (IsConstant(value) && value.IsInteger()) { | 929 if (IsConstant(value) && value.IsInteger()) { |
| 1018 const Integer& value_int = Integer::Cast(value); | 930 const Integer& value_int = Integer::Cast(value); |
| 1019 const Integer& result = Integer::Handle(Z, unary_op->Evaluate(value_int)); | 931 const Integer& result = Integer::Handle(Z, unary_op->Evaluate(value_int)); |
| 1020 if (!result.IsNull()) { | 932 if (!result.IsNull()) { |
| 1021 SetValue(unary_op, Integer::ZoneHandle(Z, result.raw())); | 933 SetValue(unary_op, Integer::ZoneHandle(Z, result.raw())); |
| 1022 return; | 934 return; |
| 1023 } | 935 } |
| 1024 } | 936 } |
| 1025 | 937 |
| 1026 SetValue(unary_op, non_constant_); | 938 SetValue(unary_op, non_constant_); |
| 1027 } | 939 } |
| 1028 | 940 |
| 1029 | |
| 1030 void ConstantPropagator::VisitUnaryMintOp(UnaryMintOpInstr* instr) { | 941 void ConstantPropagator::VisitUnaryMintOp(UnaryMintOpInstr* instr) { |
| 1031 VisitUnaryIntegerOp(instr); | 942 VisitUnaryIntegerOp(instr); |
| 1032 } | 943 } |
| 1033 | 944 |
| 1034 | |
| 1035 void ConstantPropagator::VisitUnarySmiOp(UnarySmiOpInstr* instr) { | 945 void ConstantPropagator::VisitUnarySmiOp(UnarySmiOpInstr* instr) { |
| 1036 VisitUnaryIntegerOp(instr); | 946 VisitUnaryIntegerOp(instr); |
| 1037 } | 947 } |
| 1038 | 948 |
| 1039 | |
| 1040 void ConstantPropagator::VisitUnaryDoubleOp(UnaryDoubleOpInstr* instr) { | 949 void ConstantPropagator::VisitUnaryDoubleOp(UnaryDoubleOpInstr* instr) { |
| 1041 const Object& value = instr->value()->definition()->constant_value(); | 950 const Object& value = instr->value()->definition()->constant_value(); |
| 1042 if (IsNonConstant(value)) { | 951 if (IsNonConstant(value)) { |
| 1043 SetValue(instr, non_constant_); | 952 SetValue(instr, non_constant_); |
| 1044 } else if (IsConstant(value)) { | 953 } else if (IsConstant(value)) { |
| 1045 // TODO(kmillikin): Handle unary operations. | 954 // TODO(kmillikin): Handle unary operations. |
| 1046 SetValue(instr, non_constant_); | 955 SetValue(instr, non_constant_); |
| 1047 } | 956 } |
| 1048 } | 957 } |
| 1049 | 958 |
| 1050 | |
| 1051 void ConstantPropagator::VisitSmiToDouble(SmiToDoubleInstr* instr) { | 959 void ConstantPropagator::VisitSmiToDouble(SmiToDoubleInstr* instr) { |
| 1052 const Object& value = instr->value()->definition()->constant_value(); | 960 const Object& value = instr->value()->definition()->constant_value(); |
| 1053 if (IsConstant(value) && value.IsInteger()) { | 961 if (IsConstant(value) && value.IsInteger()) { |
| 1054 SetValue(instr, | 962 SetValue(instr, |
| 1055 Double::Handle(Z, Double::New(Integer::Cast(value).AsDoubleValue(), | 963 Double::Handle(Z, Double::New(Integer::Cast(value).AsDoubleValue(), |
| 1056 Heap::kOld))); | 964 Heap::kOld))); |
| 1057 } else if (!IsUnknown(value)) { | 965 } else if (!IsUnknown(value)) { |
| 1058 SetValue(instr, non_constant_); | 966 SetValue(instr, non_constant_); |
| 1059 } | 967 } |
| 1060 } | 968 } |
| 1061 | 969 |
| 1062 | |
| 1063 void ConstantPropagator::VisitMintToDouble(MintToDoubleInstr* instr) { | 970 void ConstantPropagator::VisitMintToDouble(MintToDoubleInstr* instr) { |
| 1064 const Object& value = instr->value()->definition()->constant_value(); | 971 const Object& value = instr->value()->definition()->constant_value(); |
| 1065 if (IsConstant(value) && value.IsInteger()) { | 972 if (IsConstant(value) && value.IsInteger()) { |
| 1066 SetValue(instr, | 973 SetValue(instr, |
| 1067 Double::Handle(Z, Double::New(Integer::Cast(value).AsDoubleValue(), | 974 Double::Handle(Z, Double::New(Integer::Cast(value).AsDoubleValue(), |
| 1068 Heap::kOld))); | 975 Heap::kOld))); |
| 1069 } else if (!IsUnknown(value)) { | 976 } else if (!IsUnknown(value)) { |
| 1070 SetValue(instr, non_constant_); | 977 SetValue(instr, non_constant_); |
| 1071 } | 978 } |
| 1072 } | 979 } |
| 1073 | 980 |
| 1074 | |
| 1075 void ConstantPropagator::VisitInt32ToDouble(Int32ToDoubleInstr* instr) { | 981 void ConstantPropagator::VisitInt32ToDouble(Int32ToDoubleInstr* instr) { |
| 1076 const Object& value = instr->value()->definition()->constant_value(); | 982 const Object& value = instr->value()->definition()->constant_value(); |
| 1077 if (IsConstant(value) && value.IsInteger()) { | 983 if (IsConstant(value) && value.IsInteger()) { |
| 1078 SetValue(instr, | 984 SetValue(instr, |
| 1079 Double::Handle(Z, Double::New(Integer::Cast(value).AsDoubleValue(), | 985 Double::Handle(Z, Double::New(Integer::Cast(value).AsDoubleValue(), |
| 1080 Heap::kOld))); | 986 Heap::kOld))); |
| 1081 } else if (!IsUnknown(value)) { | 987 } else if (!IsUnknown(value)) { |
| 1082 SetValue(instr, non_constant_); | 988 SetValue(instr, non_constant_); |
| 1083 } | 989 } |
| 1084 } | 990 } |
| 1085 | 991 |
| 1086 | |
| 1087 void ConstantPropagator::VisitDoubleToInteger(DoubleToIntegerInstr* instr) { | 992 void ConstantPropagator::VisitDoubleToInteger(DoubleToIntegerInstr* instr) { |
| 1088 // TODO(kmillikin): Handle conversion. | 993 // TODO(kmillikin): Handle conversion. |
| 1089 SetValue(instr, non_constant_); | 994 SetValue(instr, non_constant_); |
| 1090 } | 995 } |
| 1091 | 996 |
| 1092 | |
| 1093 void ConstantPropagator::VisitDoubleToSmi(DoubleToSmiInstr* instr) { | 997 void ConstantPropagator::VisitDoubleToSmi(DoubleToSmiInstr* instr) { |
| 1094 // TODO(kmillikin): Handle conversion. | 998 // TODO(kmillikin): Handle conversion. |
| 1095 SetValue(instr, non_constant_); | 999 SetValue(instr, non_constant_); |
| 1096 } | 1000 } |
| 1097 | 1001 |
| 1098 | |
| 1099 void ConstantPropagator::VisitDoubleToDouble(DoubleToDoubleInstr* instr) { | 1002 void ConstantPropagator::VisitDoubleToDouble(DoubleToDoubleInstr* instr) { |
| 1100 // TODO(kmillikin): Handle conversion. | 1003 // TODO(kmillikin): Handle conversion. |
| 1101 SetValue(instr, non_constant_); | 1004 SetValue(instr, non_constant_); |
| 1102 } | 1005 } |
| 1103 | 1006 |
| 1104 | |
| 1105 void ConstantPropagator::VisitDoubleToFloat(DoubleToFloatInstr* instr) { | 1007 void ConstantPropagator::VisitDoubleToFloat(DoubleToFloatInstr* instr) { |
| 1106 // TODO(kmillikin): Handle conversion. | 1008 // TODO(kmillikin): Handle conversion. |
| 1107 SetValue(instr, non_constant_); | 1009 SetValue(instr, non_constant_); |
| 1108 } | 1010 } |
| 1109 | 1011 |
| 1110 | |
| 1111 void ConstantPropagator::VisitFloatToDouble(FloatToDoubleInstr* instr) { | 1012 void ConstantPropagator::VisitFloatToDouble(FloatToDoubleInstr* instr) { |
| 1112 // TODO(kmillikin): Handle conversion. | 1013 // TODO(kmillikin): Handle conversion. |
| 1113 SetValue(instr, non_constant_); | 1014 SetValue(instr, non_constant_); |
| 1114 } | 1015 } |
| 1115 | 1016 |
| 1116 | |
| 1117 void ConstantPropagator::VisitInvokeMathCFunction( | 1017 void ConstantPropagator::VisitInvokeMathCFunction( |
| 1118 InvokeMathCFunctionInstr* instr) { | 1018 InvokeMathCFunctionInstr* instr) { |
| 1119 // TODO(kmillikin): Handle conversion. | 1019 // TODO(kmillikin): Handle conversion. |
| 1120 SetValue(instr, non_constant_); | 1020 SetValue(instr, non_constant_); |
| 1121 } | 1021 } |
| 1122 | 1022 |
| 1123 | |
| 1124 void ConstantPropagator::VisitTruncDivMod(TruncDivModInstr* instr) { | 1023 void ConstantPropagator::VisitTruncDivMod(TruncDivModInstr* instr) { |
| 1125 // TODO(srdjan): Handle merged instruction. | 1024 // TODO(srdjan): Handle merged instruction. |
| 1126 SetValue(instr, non_constant_); | 1025 SetValue(instr, non_constant_); |
| 1127 } | 1026 } |
| 1128 | 1027 |
| 1129 | |
| 1130 void ConstantPropagator::VisitExtractNthOutput(ExtractNthOutputInstr* instr) { | 1028 void ConstantPropagator::VisitExtractNthOutput(ExtractNthOutputInstr* instr) { |
| 1131 SetValue(instr, non_constant_); | 1029 SetValue(instr, non_constant_); |
| 1132 } | 1030 } |
| 1133 | 1031 |
| 1134 | |
| 1135 void ConstantPropagator::VisitConstant(ConstantInstr* instr) { | 1032 void ConstantPropagator::VisitConstant(ConstantInstr* instr) { |
| 1136 SetValue(instr, instr->value()); | 1033 SetValue(instr, instr->value()); |
| 1137 } | 1034 } |
| 1138 | 1035 |
| 1139 | |
| 1140 void ConstantPropagator::VisitUnboxedConstant(UnboxedConstantInstr* instr) { | 1036 void ConstantPropagator::VisitUnboxedConstant(UnboxedConstantInstr* instr) { |
| 1141 SetValue(instr, instr->value()); | 1037 SetValue(instr, instr->value()); |
| 1142 } | 1038 } |
| 1143 | 1039 |
| 1144 | |
| 1145 void ConstantPropagator::VisitConstraint(ConstraintInstr* instr) { | 1040 void ConstantPropagator::VisitConstraint(ConstraintInstr* instr) { |
| 1146 // Should not be used outside of range analysis. | 1041 // Should not be used outside of range analysis. |
| 1147 UNREACHABLE(); | 1042 UNREACHABLE(); |
| 1148 } | 1043 } |
| 1149 | 1044 |
| 1150 | |
| 1151 void ConstantPropagator::VisitMaterializeObject(MaterializeObjectInstr* instr) { | 1045 void ConstantPropagator::VisitMaterializeObject(MaterializeObjectInstr* instr) { |
| 1152 // Should not be used outside of allocation elimination pass. | 1046 // Should not be used outside of allocation elimination pass. |
| 1153 UNREACHABLE(); | 1047 UNREACHABLE(); |
| 1154 } | 1048 } |
| 1155 | 1049 |
| 1156 | |
| 1157 static bool IsIntegerOrDouble(const Object& value) { | 1050 static bool IsIntegerOrDouble(const Object& value) { |
| 1158 return value.IsInteger() || value.IsDouble(); | 1051 return value.IsInteger() || value.IsDouble(); |
| 1159 } | 1052 } |
| 1160 | 1053 |
| 1161 | |
| 1162 static double ToDouble(const Object& value) { | 1054 static double ToDouble(const Object& value) { |
| 1163 return value.IsInteger() ? Integer::Cast(value).AsDoubleValue() | 1055 return value.IsInteger() ? Integer::Cast(value).AsDoubleValue() |
| 1164 : Double::Cast(value).value(); | 1056 : Double::Cast(value).value(); |
| 1165 } | 1057 } |
| 1166 | 1058 |
| 1167 | |
| 1168 void ConstantPropagator::VisitBinaryDoubleOp(BinaryDoubleOpInstr* instr) { | 1059 void ConstantPropagator::VisitBinaryDoubleOp(BinaryDoubleOpInstr* instr) { |
| 1169 const Object& left = instr->left()->definition()->constant_value(); | 1060 const Object& left = instr->left()->definition()->constant_value(); |
| 1170 const Object& right = instr->right()->definition()->constant_value(); | 1061 const Object& right = instr->right()->definition()->constant_value(); |
| 1171 if (IsNonConstant(left) || IsNonConstant(right)) { | 1062 if (IsNonConstant(left) || IsNonConstant(right)) { |
| 1172 SetValue(instr, non_constant_); | 1063 SetValue(instr, non_constant_); |
| 1173 } else if (left.IsInteger() && right.IsInteger()) { | 1064 } else if (left.IsInteger() && right.IsInteger()) { |
| 1174 SetValue(instr, non_constant_); | 1065 SetValue(instr, non_constant_); |
| 1175 } else if (IsIntegerOrDouble(left) && IsIntegerOrDouble(right)) { | 1066 } else if (IsIntegerOrDouble(left) && IsIntegerOrDouble(right)) { |
| 1176 const double left_val = ToDouble(left); | 1067 const double left_val = ToDouble(left); |
| 1177 const double right_val = ToDouble(right); | 1068 const double right_val = ToDouble(right); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1190 result_val = left_val / right_val; | 1081 result_val = left_val / right_val; |
| 1191 break; | 1082 break; |
| 1192 default: | 1083 default: |
| 1193 UNREACHABLE(); | 1084 UNREACHABLE(); |
| 1194 } | 1085 } |
| 1195 const Double& result = Double::ZoneHandle(Double::NewCanonical(result_val)); | 1086 const Double& result = Double::ZoneHandle(Double::NewCanonical(result_val)); |
| 1196 SetValue(instr, result); | 1087 SetValue(instr, result); |
| 1197 } | 1088 } |
| 1198 } | 1089 } |
| 1199 | 1090 |
| 1200 | |
| 1201 void ConstantPropagator::VisitDoubleTestOp(DoubleTestOpInstr* instr) { | 1091 void ConstantPropagator::VisitDoubleTestOp(DoubleTestOpInstr* instr) { |
| 1202 const Object& value = instr->value()->definition()->constant_value(); | 1092 const Object& value = instr->value()->definition()->constant_value(); |
| 1203 const bool is_negated = instr->kind() != Token::kEQ; | 1093 const bool is_negated = instr->kind() != Token::kEQ; |
| 1204 if (value.IsInteger()) { | 1094 if (value.IsInteger()) { |
| 1205 SetValue(instr, is_negated ? Bool::True() : Bool::False()); | 1095 SetValue(instr, is_negated ? Bool::True() : Bool::False()); |
| 1206 } else if (IsIntegerOrDouble(value)) { | 1096 } else if (IsIntegerOrDouble(value)) { |
| 1207 switch (instr->op_kind()) { | 1097 switch (instr->op_kind()) { |
| 1208 case MethodRecognizer::kDouble_getIsNaN: { | 1098 case MethodRecognizer::kDouble_getIsNaN: { |
| 1209 const bool is_nan = isnan(ToDouble(value)); | 1099 const bool is_nan = isnan(ToDouble(value)); |
| 1210 SetValue(instr, Bool::Get(is_negated ? !is_nan : is_nan)); | 1100 SetValue(instr, Bool::Get(is_negated ? !is_nan : is_nan)); |
| 1211 break; | 1101 break; |
| 1212 } | 1102 } |
| 1213 case MethodRecognizer::kDouble_getIsInfinite: { | 1103 case MethodRecognizer::kDouble_getIsInfinite: { |
| 1214 const bool is_inf = isinf(ToDouble(value)); | 1104 const bool is_inf = isinf(ToDouble(value)); |
| 1215 SetValue(instr, Bool::Get(is_negated ? !is_inf : is_inf)); | 1105 SetValue(instr, Bool::Get(is_negated ? !is_inf : is_inf)); |
| 1216 break; | 1106 break; |
| 1217 } | 1107 } |
| 1218 default: | 1108 default: |
| 1219 UNREACHABLE(); | 1109 UNREACHABLE(); |
| 1220 } | 1110 } |
| 1221 } else { | 1111 } else { |
| 1222 SetValue(instr, non_constant_); | 1112 SetValue(instr, non_constant_); |
| 1223 } | 1113 } |
| 1224 } | 1114 } |
| 1225 | 1115 |
| 1226 | |
| 1227 void ConstantPropagator::VisitBinaryFloat32x4Op(BinaryFloat32x4OpInstr* instr) { | 1116 void ConstantPropagator::VisitBinaryFloat32x4Op(BinaryFloat32x4OpInstr* instr) { |
| 1228 const Object& left = instr->left()->definition()->constant_value(); | 1117 const Object& left = instr->left()->definition()->constant_value(); |
| 1229 const Object& right = instr->right()->definition()->constant_value(); | 1118 const Object& right = instr->right()->definition()->constant_value(); |
| 1230 if (IsNonConstant(left) || IsNonConstant(right)) { | 1119 if (IsNonConstant(left) || IsNonConstant(right)) { |
| 1231 SetValue(instr, non_constant_); | 1120 SetValue(instr, non_constant_); |
| 1232 } else if (IsConstant(left) && IsConstant(right)) { | 1121 } else if (IsConstant(left) && IsConstant(right)) { |
| 1233 // TODO(kmillikin): Handle binary operation. | 1122 // TODO(kmillikin): Handle binary operation. |
| 1234 SetValue(instr, non_constant_); | 1123 SetValue(instr, non_constant_); |
| 1235 } | 1124 } |
| 1236 } | 1125 } |
| 1237 | 1126 |
| 1238 | |
| 1239 void ConstantPropagator::VisitFloat32x4Constructor( | 1127 void ConstantPropagator::VisitFloat32x4Constructor( |
| 1240 Float32x4ConstructorInstr* instr) { | 1128 Float32x4ConstructorInstr* instr) { |
| 1241 SetValue(instr, non_constant_); | 1129 SetValue(instr, non_constant_); |
| 1242 } | 1130 } |
| 1243 | 1131 |
| 1244 | |
| 1245 void ConstantPropagator::VisitSimd32x4Shuffle(Simd32x4ShuffleInstr* instr) { | 1132 void ConstantPropagator::VisitSimd32x4Shuffle(Simd32x4ShuffleInstr* instr) { |
| 1246 SetValue(instr, non_constant_); | 1133 SetValue(instr, non_constant_); |
| 1247 } | 1134 } |
| 1248 | 1135 |
| 1249 | |
| 1250 void ConstantPropagator::VisitSimd32x4ShuffleMix( | 1136 void ConstantPropagator::VisitSimd32x4ShuffleMix( |
| 1251 Simd32x4ShuffleMixInstr* instr) { | 1137 Simd32x4ShuffleMixInstr* instr) { |
| 1252 SetValue(instr, non_constant_); | 1138 SetValue(instr, non_constant_); |
| 1253 } | 1139 } |
| 1254 | 1140 |
| 1255 | |
| 1256 void ConstantPropagator::VisitSimd32x4GetSignMask( | 1141 void ConstantPropagator::VisitSimd32x4GetSignMask( |
| 1257 Simd32x4GetSignMaskInstr* instr) { | 1142 Simd32x4GetSignMaskInstr* instr) { |
| 1258 SetValue(instr, non_constant_); | 1143 SetValue(instr, non_constant_); |
| 1259 } | 1144 } |
| 1260 | 1145 |
| 1261 | |
| 1262 void ConstantPropagator::VisitFloat32x4Zero(Float32x4ZeroInstr* instr) { | 1146 void ConstantPropagator::VisitFloat32x4Zero(Float32x4ZeroInstr* instr) { |
| 1263 SetValue(instr, non_constant_); | 1147 SetValue(instr, non_constant_); |
| 1264 } | 1148 } |
| 1265 | 1149 |
| 1266 | |
| 1267 void ConstantPropagator::VisitFloat32x4Splat(Float32x4SplatInstr* instr) { | 1150 void ConstantPropagator::VisitFloat32x4Splat(Float32x4SplatInstr* instr) { |
| 1268 SetValue(instr, non_constant_); | 1151 SetValue(instr, non_constant_); |
| 1269 } | 1152 } |
| 1270 | 1153 |
| 1271 | |
| 1272 void ConstantPropagator::VisitFloat32x4Comparison( | 1154 void ConstantPropagator::VisitFloat32x4Comparison( |
| 1273 Float32x4ComparisonInstr* instr) { | 1155 Float32x4ComparisonInstr* instr) { |
| 1274 SetValue(instr, non_constant_); | 1156 SetValue(instr, non_constant_); |
| 1275 } | 1157 } |
| 1276 | 1158 |
| 1277 | |
| 1278 void ConstantPropagator::VisitFloat32x4MinMax(Float32x4MinMaxInstr* instr) { | 1159 void ConstantPropagator::VisitFloat32x4MinMax(Float32x4MinMaxInstr* instr) { |
| 1279 SetValue(instr, non_constant_); | 1160 SetValue(instr, non_constant_); |
| 1280 } | 1161 } |
| 1281 | 1162 |
| 1282 | |
| 1283 void ConstantPropagator::VisitFloat32x4Scale(Float32x4ScaleInstr* instr) { | 1163 void ConstantPropagator::VisitFloat32x4Scale(Float32x4ScaleInstr* instr) { |
| 1284 SetValue(instr, non_constant_); | 1164 SetValue(instr, non_constant_); |
| 1285 } | 1165 } |
| 1286 | 1166 |
| 1287 | |
| 1288 void ConstantPropagator::VisitFloat32x4Sqrt(Float32x4SqrtInstr* instr) { | 1167 void ConstantPropagator::VisitFloat32x4Sqrt(Float32x4SqrtInstr* instr) { |
| 1289 SetValue(instr, non_constant_); | 1168 SetValue(instr, non_constant_); |
| 1290 } | 1169 } |
| 1291 | 1170 |
| 1292 | |
| 1293 void ConstantPropagator::VisitFloat32x4ZeroArg(Float32x4ZeroArgInstr* instr) { | 1171 void ConstantPropagator::VisitFloat32x4ZeroArg(Float32x4ZeroArgInstr* instr) { |
| 1294 SetValue(instr, non_constant_); | 1172 SetValue(instr, non_constant_); |
| 1295 } | 1173 } |
| 1296 | 1174 |
| 1297 | |
| 1298 void ConstantPropagator::VisitFloat32x4Clamp(Float32x4ClampInstr* instr) { | 1175 void ConstantPropagator::VisitFloat32x4Clamp(Float32x4ClampInstr* instr) { |
| 1299 SetValue(instr, non_constant_); | 1176 SetValue(instr, non_constant_); |
| 1300 } | 1177 } |
| 1301 | 1178 |
| 1302 | |
| 1303 void ConstantPropagator::VisitFloat32x4With(Float32x4WithInstr* instr) { | 1179 void ConstantPropagator::VisitFloat32x4With(Float32x4WithInstr* instr) { |
| 1304 SetValue(instr, non_constant_); | 1180 SetValue(instr, non_constant_); |
| 1305 } | 1181 } |
| 1306 | 1182 |
| 1307 | |
| 1308 void ConstantPropagator::VisitFloat32x4ToInt32x4( | 1183 void ConstantPropagator::VisitFloat32x4ToInt32x4( |
| 1309 Float32x4ToInt32x4Instr* instr) { | 1184 Float32x4ToInt32x4Instr* instr) { |
| 1310 SetValue(instr, non_constant_); | 1185 SetValue(instr, non_constant_); |
| 1311 } | 1186 } |
| 1312 | 1187 |
| 1313 | |
| 1314 void ConstantPropagator::VisitInt32x4Constructor( | 1188 void ConstantPropagator::VisitInt32x4Constructor( |
| 1315 Int32x4ConstructorInstr* instr) { | 1189 Int32x4ConstructorInstr* instr) { |
| 1316 SetValue(instr, non_constant_); | 1190 SetValue(instr, non_constant_); |
| 1317 } | 1191 } |
| 1318 | 1192 |
| 1319 | |
| 1320 void ConstantPropagator::VisitInt32x4BoolConstructor( | 1193 void ConstantPropagator::VisitInt32x4BoolConstructor( |
| 1321 Int32x4BoolConstructorInstr* instr) { | 1194 Int32x4BoolConstructorInstr* instr) { |
| 1322 SetValue(instr, non_constant_); | 1195 SetValue(instr, non_constant_); |
| 1323 } | 1196 } |
| 1324 | 1197 |
| 1325 | |
| 1326 void ConstantPropagator::VisitInt32x4GetFlag(Int32x4GetFlagInstr* instr) { | 1198 void ConstantPropagator::VisitInt32x4GetFlag(Int32x4GetFlagInstr* instr) { |
| 1327 SetValue(instr, non_constant_); | 1199 SetValue(instr, non_constant_); |
| 1328 } | 1200 } |
| 1329 | 1201 |
| 1330 | |
| 1331 void ConstantPropagator::VisitInt32x4SetFlag(Int32x4SetFlagInstr* instr) { | 1202 void ConstantPropagator::VisitInt32x4SetFlag(Int32x4SetFlagInstr* instr) { |
| 1332 SetValue(instr, non_constant_); | 1203 SetValue(instr, non_constant_); |
| 1333 } | 1204 } |
| 1334 | 1205 |
| 1335 | |
| 1336 void ConstantPropagator::VisitInt32x4Select(Int32x4SelectInstr* instr) { | 1206 void ConstantPropagator::VisitInt32x4Select(Int32x4SelectInstr* instr) { |
| 1337 SetValue(instr, non_constant_); | 1207 SetValue(instr, non_constant_); |
| 1338 } | 1208 } |
| 1339 | 1209 |
| 1340 | |
| 1341 void ConstantPropagator::VisitInt32x4ToFloat32x4( | 1210 void ConstantPropagator::VisitInt32x4ToFloat32x4( |
| 1342 Int32x4ToFloat32x4Instr* instr) { | 1211 Int32x4ToFloat32x4Instr* instr) { |
| 1343 SetValue(instr, non_constant_); | 1212 SetValue(instr, non_constant_); |
| 1344 } | 1213 } |
| 1345 | 1214 |
| 1346 | |
| 1347 void ConstantPropagator::VisitBinaryInt32x4Op(BinaryInt32x4OpInstr* instr) { | 1215 void ConstantPropagator::VisitBinaryInt32x4Op(BinaryInt32x4OpInstr* instr) { |
| 1348 SetValue(instr, non_constant_); | 1216 SetValue(instr, non_constant_); |
| 1349 } | 1217 } |
| 1350 | 1218 |
| 1351 | |
| 1352 void ConstantPropagator::VisitSimd64x2Shuffle(Simd64x2ShuffleInstr* instr) { | 1219 void ConstantPropagator::VisitSimd64x2Shuffle(Simd64x2ShuffleInstr* instr) { |
| 1353 SetValue(instr, non_constant_); | 1220 SetValue(instr, non_constant_); |
| 1354 } | 1221 } |
| 1355 | 1222 |
| 1356 | |
| 1357 void ConstantPropagator::VisitBinaryFloat64x2Op(BinaryFloat64x2OpInstr* instr) { | 1223 void ConstantPropagator::VisitBinaryFloat64x2Op(BinaryFloat64x2OpInstr* instr) { |
| 1358 SetValue(instr, non_constant_); | 1224 SetValue(instr, non_constant_); |
| 1359 } | 1225 } |
| 1360 | 1226 |
| 1361 | |
| 1362 void ConstantPropagator::VisitFloat32x4ToFloat64x2( | 1227 void ConstantPropagator::VisitFloat32x4ToFloat64x2( |
| 1363 Float32x4ToFloat64x2Instr* instr) { | 1228 Float32x4ToFloat64x2Instr* instr) { |
| 1364 SetValue(instr, non_constant_); | 1229 SetValue(instr, non_constant_); |
| 1365 } | 1230 } |
| 1366 | 1231 |
| 1367 | |
| 1368 void ConstantPropagator::VisitFloat64x2ToFloat32x4( | 1232 void ConstantPropagator::VisitFloat64x2ToFloat32x4( |
| 1369 Float64x2ToFloat32x4Instr* instr) { | 1233 Float64x2ToFloat32x4Instr* instr) { |
| 1370 SetValue(instr, non_constant_); | 1234 SetValue(instr, non_constant_); |
| 1371 } | 1235 } |
| 1372 | 1236 |
| 1373 | |
| 1374 void ConstantPropagator::VisitFloat64x2Zero(Float64x2ZeroInstr* instr) { | 1237 void ConstantPropagator::VisitFloat64x2Zero(Float64x2ZeroInstr* instr) { |
| 1375 SetValue(instr, non_constant_); | 1238 SetValue(instr, non_constant_); |
| 1376 } | 1239 } |
| 1377 | 1240 |
| 1378 | |
| 1379 void ConstantPropagator::VisitFloat64x2Splat(Float64x2SplatInstr* instr) { | 1241 void ConstantPropagator::VisitFloat64x2Splat(Float64x2SplatInstr* instr) { |
| 1380 SetValue(instr, non_constant_); | 1242 SetValue(instr, non_constant_); |
| 1381 } | 1243 } |
| 1382 | 1244 |
| 1383 | |
| 1384 void ConstantPropagator::VisitFloat64x2Constructor( | 1245 void ConstantPropagator::VisitFloat64x2Constructor( |
| 1385 Float64x2ConstructorInstr* instr) { | 1246 Float64x2ConstructorInstr* instr) { |
| 1386 SetValue(instr, non_constant_); | 1247 SetValue(instr, non_constant_); |
| 1387 } | 1248 } |
| 1388 | 1249 |
| 1389 | |
| 1390 void ConstantPropagator::VisitFloat64x2ZeroArg(Float64x2ZeroArgInstr* instr) { | 1250 void ConstantPropagator::VisitFloat64x2ZeroArg(Float64x2ZeroArgInstr* instr) { |
| 1391 // TODO(johnmccutchan): Implement constant propagation. | 1251 // TODO(johnmccutchan): Implement constant propagation. |
| 1392 SetValue(instr, non_constant_); | 1252 SetValue(instr, non_constant_); |
| 1393 } | 1253 } |
| 1394 | 1254 |
| 1395 | |
| 1396 void ConstantPropagator::VisitFloat64x2OneArg(Float64x2OneArgInstr* instr) { | 1255 void ConstantPropagator::VisitFloat64x2OneArg(Float64x2OneArgInstr* instr) { |
| 1397 // TODO(johnmccutchan): Implement constant propagation. | 1256 // TODO(johnmccutchan): Implement constant propagation. |
| 1398 SetValue(instr, non_constant_); | 1257 SetValue(instr, non_constant_); |
| 1399 } | 1258 } |
| 1400 | 1259 |
| 1401 | |
| 1402 void ConstantPropagator::VisitMathUnary(MathUnaryInstr* instr) { | 1260 void ConstantPropagator::VisitMathUnary(MathUnaryInstr* instr) { |
| 1403 const Object& value = instr->value()->definition()->constant_value(); | 1261 const Object& value = instr->value()->definition()->constant_value(); |
| 1404 if (IsNonConstant(value)) { | 1262 if (IsNonConstant(value)) { |
| 1405 SetValue(instr, non_constant_); | 1263 SetValue(instr, non_constant_); |
| 1406 } else if (IsConstant(value)) { | 1264 } else if (IsConstant(value)) { |
| 1407 // TODO(kmillikin): Handle Math's unary operations (sqrt, cos, sin). | 1265 // TODO(kmillikin): Handle Math's unary operations (sqrt, cos, sin). |
| 1408 SetValue(instr, non_constant_); | 1266 SetValue(instr, non_constant_); |
| 1409 } | 1267 } |
| 1410 } | 1268 } |
| 1411 | 1269 |
| 1412 | |
| 1413 void ConstantPropagator::VisitMathMinMax(MathMinMaxInstr* instr) { | 1270 void ConstantPropagator::VisitMathMinMax(MathMinMaxInstr* instr) { |
| 1414 const Object& left = instr->left()->definition()->constant_value(); | 1271 const Object& left = instr->left()->definition()->constant_value(); |
| 1415 const Object& right = instr->right()->definition()->constant_value(); | 1272 const Object& right = instr->right()->definition()->constant_value(); |
| 1416 if (IsNonConstant(left) || IsNonConstant(right)) { | 1273 if (IsNonConstant(left) || IsNonConstant(right)) { |
| 1417 SetValue(instr, non_constant_); | 1274 SetValue(instr, non_constant_); |
| 1418 } else if (IsConstant(left) && IsConstant(right)) { | 1275 } else if (IsConstant(left) && IsConstant(right)) { |
| 1419 // TODO(srdjan): Handle min and max. | 1276 // TODO(srdjan): Handle min and max. |
| 1420 SetValue(instr, non_constant_); | 1277 SetValue(instr, non_constant_); |
| 1421 } | 1278 } |
| 1422 } | 1279 } |
| 1423 | 1280 |
| 1424 | |
| 1425 void ConstantPropagator::VisitCaseInsensitiveCompareUC16( | 1281 void ConstantPropagator::VisitCaseInsensitiveCompareUC16( |
| 1426 CaseInsensitiveCompareUC16Instr* instr) { | 1282 CaseInsensitiveCompareUC16Instr* instr) { |
| 1427 SetValue(instr, non_constant_); | 1283 SetValue(instr, non_constant_); |
| 1428 } | 1284 } |
| 1429 | 1285 |
| 1430 | |
| 1431 void ConstantPropagator::VisitUnbox(UnboxInstr* instr) { | 1286 void ConstantPropagator::VisitUnbox(UnboxInstr* instr) { |
| 1432 const Object& value = instr->value()->definition()->constant_value(); | 1287 const Object& value = instr->value()->definition()->constant_value(); |
| 1433 if (IsNonConstant(value)) { | 1288 if (IsNonConstant(value)) { |
| 1434 SetValue(instr, non_constant_); | 1289 SetValue(instr, non_constant_); |
| 1435 } else if (IsConstant(value)) { | 1290 } else if (IsConstant(value)) { |
| 1436 // TODO(kmillikin): Handle conversion. | 1291 // TODO(kmillikin): Handle conversion. |
| 1437 SetValue(instr, non_constant_); | 1292 SetValue(instr, non_constant_); |
| 1438 } | 1293 } |
| 1439 } | 1294 } |
| 1440 | 1295 |
| 1441 | |
| 1442 void ConstantPropagator::VisitBox(BoxInstr* instr) { | 1296 void ConstantPropagator::VisitBox(BoxInstr* instr) { |
| 1443 const Object& value = instr->value()->definition()->constant_value(); | 1297 const Object& value = instr->value()->definition()->constant_value(); |
| 1444 if (IsNonConstant(value)) { | 1298 if (IsNonConstant(value)) { |
| 1445 SetValue(instr, non_constant_); | 1299 SetValue(instr, non_constant_); |
| 1446 } else if (IsConstant(value)) { | 1300 } else if (IsConstant(value)) { |
| 1447 // TODO(kmillikin): Handle conversion. | 1301 // TODO(kmillikin): Handle conversion. |
| 1448 SetValue(instr, non_constant_); | 1302 SetValue(instr, non_constant_); |
| 1449 } | 1303 } |
| 1450 } | 1304 } |
| 1451 | 1305 |
| 1452 | |
| 1453 void ConstantPropagator::VisitBoxUint32(BoxUint32Instr* instr) { | 1306 void ConstantPropagator::VisitBoxUint32(BoxUint32Instr* instr) { |
| 1454 // TODO(kmillikin): Handle box operation. | 1307 // TODO(kmillikin): Handle box operation. |
| 1455 SetValue(instr, non_constant_); | 1308 SetValue(instr, non_constant_); |
| 1456 } | 1309 } |
| 1457 | 1310 |
| 1458 | |
| 1459 void ConstantPropagator::VisitUnboxUint32(UnboxUint32Instr* instr) { | 1311 void ConstantPropagator::VisitUnboxUint32(UnboxUint32Instr* instr) { |
| 1460 // TODO(kmillikin): Handle unbox operation. | 1312 // TODO(kmillikin): Handle unbox operation. |
| 1461 SetValue(instr, non_constant_); | 1313 SetValue(instr, non_constant_); |
| 1462 } | 1314 } |
| 1463 | 1315 |
| 1464 | |
| 1465 void ConstantPropagator::VisitBoxInt32(BoxInt32Instr* instr) { | 1316 void ConstantPropagator::VisitBoxInt32(BoxInt32Instr* instr) { |
| 1466 // TODO(kmillikin): Handle box operation. | 1317 // TODO(kmillikin): Handle box operation. |
| 1467 SetValue(instr, non_constant_); | 1318 SetValue(instr, non_constant_); |
| 1468 } | 1319 } |
| 1469 | 1320 |
| 1470 | |
| 1471 void ConstantPropagator::VisitUnboxInt32(UnboxInt32Instr* instr) { | 1321 void ConstantPropagator::VisitUnboxInt32(UnboxInt32Instr* instr) { |
| 1472 // TODO(kmillikin): Handle unbox operation. | 1322 // TODO(kmillikin): Handle unbox operation. |
| 1473 SetValue(instr, non_constant_); | 1323 SetValue(instr, non_constant_); |
| 1474 } | 1324 } |
| 1475 | 1325 |
| 1476 | |
| 1477 void ConstantPropagator::VisitUnboxedIntConverter( | 1326 void ConstantPropagator::VisitUnboxedIntConverter( |
| 1478 UnboxedIntConverterInstr* instr) { | 1327 UnboxedIntConverterInstr* instr) { |
| 1479 SetValue(instr, non_constant_); | 1328 SetValue(instr, non_constant_); |
| 1480 } | 1329 } |
| 1481 | 1330 |
| 1482 | |
| 1483 void ConstantPropagator::VisitUnaryUint32Op(UnaryUint32OpInstr* instr) { | 1331 void ConstantPropagator::VisitUnaryUint32Op(UnaryUint32OpInstr* instr) { |
| 1484 // TODO(kmillikin): Handle unary operations. | 1332 // TODO(kmillikin): Handle unary operations. |
| 1485 SetValue(instr, non_constant_); | 1333 SetValue(instr, non_constant_); |
| 1486 } | 1334 } |
| 1487 | 1335 |
| 1488 | |
| 1489 void ConstantPropagator::Analyze() { | 1336 void ConstantPropagator::Analyze() { |
| 1490 GraphEntryInstr* entry = graph_->graph_entry(); | 1337 GraphEntryInstr* entry = graph_->graph_entry(); |
| 1491 reachable_->Add(entry->preorder_number()); | 1338 reachable_->Add(entry->preorder_number()); |
| 1492 block_worklist_.Add(entry); | 1339 block_worklist_.Add(entry); |
| 1493 | 1340 |
| 1494 while (true) { | 1341 while (true) { |
| 1495 if (block_worklist_.is_empty()) { | 1342 if (block_worklist_.is_empty()) { |
| 1496 if (definition_worklist_.IsEmpty()) break; | 1343 if (definition_worklist_.IsEmpty()) break; |
| 1497 Definition* definition = definition_worklist_.RemoveLast(); | 1344 Definition* definition = definition_worklist_.RemoveLast(); |
| 1498 Value* use = definition->input_use_list(); | 1345 Value* use = definition->input_use_list(); |
| 1499 while (use != NULL) { | 1346 while (use != NULL) { |
| 1500 use->instruction()->Accept(this); | 1347 use->instruction()->Accept(this); |
| 1501 use = use->next_use(); | 1348 use = use->next_use(); |
| 1502 } | 1349 } |
| 1503 } else { | 1350 } else { |
| 1504 BlockEntryInstr* block = block_worklist_.RemoveLast(); | 1351 BlockEntryInstr* block = block_worklist_.RemoveLast(); |
| 1505 block->Accept(this); | 1352 block->Accept(this); |
| 1506 } | 1353 } |
| 1507 } | 1354 } |
| 1508 } | 1355 } |
| 1509 | 1356 |
| 1510 | |
| 1511 static bool IsEmptyBlock(BlockEntryInstr* block) { | 1357 static bool IsEmptyBlock(BlockEntryInstr* block) { |
| 1512 return block->next()->IsGoto() && | 1358 return block->next()->IsGoto() && |
| 1513 (!block->IsJoinEntry() || (block->AsJoinEntry()->phis() == NULL)) && | 1359 (!block->IsJoinEntry() || (block->AsJoinEntry()->phis() == NULL)) && |
| 1514 !block->IsIndirectEntry(); | 1360 !block->IsIndirectEntry(); |
| 1515 } | 1361 } |
| 1516 | 1362 |
| 1517 | |
| 1518 // Traverses a chain of empty blocks and returns the first reachable non-empty | 1363 // Traverses a chain of empty blocks and returns the first reachable non-empty |
| 1519 // block that is not dominated by the start block. The empty blocks are added | 1364 // block that is not dominated by the start block. The empty blocks are added |
| 1520 // to the supplied bit vector. | 1365 // to the supplied bit vector. |
| 1521 static BlockEntryInstr* FindFirstNonEmptySuccessor(TargetEntryInstr* block, | 1366 static BlockEntryInstr* FindFirstNonEmptySuccessor(TargetEntryInstr* block, |
| 1522 BitVector* empty_blocks) { | 1367 BitVector* empty_blocks) { |
| 1523 BlockEntryInstr* current = block; | 1368 BlockEntryInstr* current = block; |
| 1524 while (IsEmptyBlock(current) && block->Dominates(current)) { | 1369 while (IsEmptyBlock(current) && block->Dominates(current)) { |
| 1525 ASSERT(!block->IsJoinEntry() || (block->AsJoinEntry()->phis() == NULL)); | 1370 ASSERT(!block->IsJoinEntry() || (block->AsJoinEntry()->phis() == NULL)); |
| 1526 empty_blocks->Add(current->preorder_number()); | 1371 empty_blocks->Add(current->preorder_number()); |
| 1527 current = current->next()->AsGoto()->successor(); | 1372 current = current->next()->AsGoto()->successor(); |
| 1528 } | 1373 } |
| 1529 return current; | 1374 return current; |
| 1530 } | 1375 } |
| 1531 | 1376 |
| 1532 | |
| 1533 void ConstantPropagator::EliminateRedundantBranches() { | 1377 void ConstantPropagator::EliminateRedundantBranches() { |
| 1534 // Canonicalize branches that have no side-effects and where true- and | 1378 // Canonicalize branches that have no side-effects and where true- and |
| 1535 // false-targets are the same. | 1379 // false-targets are the same. |
| 1536 bool changed = false; | 1380 bool changed = false; |
| 1537 BitVector* empty_blocks = new (Z) BitVector(Z, graph_->preorder().length()); | 1381 BitVector* empty_blocks = new (Z) BitVector(Z, graph_->preorder().length()); |
| 1538 for (BlockIterator b = graph_->postorder_iterator(); !b.Done(); b.Advance()) { | 1382 for (BlockIterator b = graph_->postorder_iterator(); !b.Done(); b.Advance()) { |
| 1539 BlockEntryInstr* block = b.Current(); | 1383 BlockEntryInstr* block = b.Current(); |
| 1540 BranchInstr* branch = block->last_instruction()->AsBranch(); | 1384 BranchInstr* branch = block->last_instruction()->AsBranch(); |
| 1541 empty_blocks->Clear(); | 1385 empty_blocks->Clear(); |
| 1542 if ((branch != NULL) && branch->Effects().IsNone()) { | 1386 if ((branch != NULL) && branch->Effects().IsNone()) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1579 } | 1423 } |
| 1580 | 1424 |
| 1581 if (changed) { | 1425 if (changed) { |
| 1582 graph_->DiscoverBlocks(); | 1426 graph_->DiscoverBlocks(); |
| 1583 // TODO(fschneider): Update dominator tree in place instead of recomputing. | 1427 // TODO(fschneider): Update dominator tree in place instead of recomputing. |
| 1584 GrowableArray<BitVector*> dominance_frontier; | 1428 GrowableArray<BitVector*> dominance_frontier; |
| 1585 graph_->ComputeDominators(&dominance_frontier); | 1429 graph_->ComputeDominators(&dominance_frontier); |
| 1586 } | 1430 } |
| 1587 } | 1431 } |
| 1588 | 1432 |
| 1589 | |
| 1590 void ConstantPropagator::Transform() { | 1433 void ConstantPropagator::Transform() { |
| 1591 if (FLAG_trace_constant_propagation && | 1434 if (FLAG_trace_constant_propagation && |
| 1592 FlowGraphPrinter::ShouldPrint(graph_->function())) { | 1435 FlowGraphPrinter::ShouldPrint(graph_->function())) { |
| 1593 FlowGraphPrinter::PrintGraph("Before CP", graph_); | 1436 FlowGraphPrinter::PrintGraph("Before CP", graph_); |
| 1594 } | 1437 } |
| 1595 | 1438 |
| 1596 // We will recompute dominators, block ordering, block ids, block last | 1439 // We will recompute dominators, block ordering, block ids, block last |
| 1597 // instructions, previous pointers, predecessors, etc. after eliminating | 1440 // instructions, previous pointers, predecessors, etc. after eliminating |
| 1598 // unreachable code. We do not maintain those properties during the | 1441 // unreachable code. We do not maintain those properties during the |
| 1599 // transformation. | 1442 // transformation. |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1734 GrowableArray<BitVector*> dominance_frontier; | 1577 GrowableArray<BitVector*> dominance_frontier; |
| 1735 graph_->ComputeDominators(&dominance_frontier); | 1578 graph_->ComputeDominators(&dominance_frontier); |
| 1736 | 1579 |
| 1737 if (FLAG_trace_constant_propagation && | 1580 if (FLAG_trace_constant_propagation && |
| 1738 FlowGraphPrinter::ShouldPrint(graph_->function())) { | 1581 FlowGraphPrinter::ShouldPrint(graph_->function())) { |
| 1739 FlowGraphPrinter::PrintGraph("After CP", graph_); | 1582 FlowGraphPrinter::PrintGraph("After CP", graph_); |
| 1740 } | 1583 } |
| 1741 } | 1584 } |
| 1742 | 1585 |
| 1743 } // namespace dart | 1586 } // namespace dart |
| OLD | NEW |