Chromium Code Reviews| 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/flow_graph_optimizer.h" | 5 #include "vm/flow_graph_optimizer.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/cha.h" | 8 #include "vm/cha.h" |
| 9 #include "vm/cpu.h" | 9 #include "vm/cpu.h" |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 284 BinarySmiOpInstr* smi_shift_left = NULL; | 284 BinarySmiOpInstr* smi_shift_left = NULL; |
| 285 if (bit_and_instr->InputAt(0)->IsSingleUse()) { | 285 if (bit_and_instr->InputAt(0)->IsSingleUse()) { |
| 286 smi_shift_left = AsSmiShiftLeftInstruction(left_instr); | 286 smi_shift_left = AsSmiShiftLeftInstruction(left_instr); |
| 287 } | 287 } |
| 288 if ((smi_shift_left == NULL) && (bit_and_instr->InputAt(1)->IsSingleUse())) { | 288 if ((smi_shift_left == NULL) && (bit_and_instr->InputAt(1)->IsSingleUse())) { |
| 289 smi_shift_left = AsSmiShiftLeftInstruction(right_instr); | 289 smi_shift_left = AsSmiShiftLeftInstruction(right_instr); |
| 290 } | 290 } |
| 291 if (smi_shift_left == NULL) return; | 291 if (smi_shift_left == NULL) return; |
| 292 | 292 |
| 293 // Pattern recognized. | 293 // Pattern recognized. |
| 294 smi_shift_left->set_is_truncating(true); | 294 smi_shift_left->mark_truncating(); |
| 295 ASSERT(bit_and_instr->IsBinarySmiOp() || bit_and_instr->IsBinaryMintOp()); | 295 ASSERT(bit_and_instr->IsBinarySmiOp() || bit_and_instr->IsBinaryMintOp()); |
| 296 if (bit_and_instr->IsBinaryMintOp()) { | 296 if (bit_and_instr->IsBinaryMintOp()) { |
| 297 // Replace Mint op with Smi op. | 297 // Replace Mint op with Smi op. |
| 298 BinarySmiOpInstr* smi_op = new(I) BinarySmiOpInstr( | 298 BinarySmiOpInstr* smi_op = new(I) BinarySmiOpInstr( |
| 299 Token::kBIT_AND, | 299 Token::kBIT_AND, |
| 300 new(I) Value(left_instr), | 300 new(I) Value(left_instr), |
| 301 new(I) Value(right_instr), | 301 new(I) Value(right_instr), |
| 302 Isolate::kNoDeoptId, // BIT_AND cannot deoptimize. | 302 Isolate::kNoDeoptId); // BIT_AND cannot deoptimize. |
| 303 Scanner::kNoSourcePos); | |
| 304 bit_and_instr->ReplaceWith(smi_op, current_iterator()); | 303 bit_and_instr->ReplaceWith(smi_op, current_iterator()); |
| 305 } | 304 } |
| 306 } | 305 } |
| 307 | 306 |
| 308 | 307 |
| 309 | 308 |
| 310 // Used by TryMergeDivMod. | 309 // Used by TryMergeDivMod. |
| 311 // Inserts a load-indexed instruction between a TRUNCDIV or MOD instruction, | 310 // Inserts a load-indexed instruction between a TRUNCDIV or MOD instruction, |
| 312 // and the using instruction. This is an intermediate step before merging. | 311 // and the using instruction. This is an intermediate step before merging. |
| 313 void FlowGraphOptimizer::AppendLoadIndexedForMerged(Definition* instr, | 312 void FlowGraphOptimizer::AppendLoadIndexedForMerged(Definition* instr, |
| (...skipping 1928 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2242 call->token_pos()), | 2241 call->token_pos()), |
| 2243 call->env(), | 2242 call->env(), |
| 2244 FlowGraph::kEffect); | 2243 FlowGraph::kEffect); |
| 2245 ConstantInstr* constant = | 2244 ConstantInstr* constant = |
| 2246 flow_graph()->GetConstant(Smi::Handle(I, | 2245 flow_graph()->GetConstant(Smi::Handle(I, |
| 2247 Smi::New(Smi::Cast(obj).Value() - 1))); | 2246 Smi::New(Smi::Cast(obj).Value() - 1))); |
| 2248 BinarySmiOpInstr* bin_op = | 2247 BinarySmiOpInstr* bin_op = |
| 2249 new(I) BinarySmiOpInstr(Token::kBIT_AND, | 2248 new(I) BinarySmiOpInstr(Token::kBIT_AND, |
| 2250 new(I) Value(left), | 2249 new(I) Value(left), |
| 2251 new(I) Value(constant), | 2250 new(I) Value(constant), |
| 2252 call->deopt_id(), | 2251 call->deopt_id()); |
| 2253 call->token_pos()); | |
|
Cutch
2014/09/11 17:41:53
Why are we dropping the token position?
Vyacheslav Egorov (Google)
2014/09/11 19:50:47
Because it was not used anywhere. Remains of ancie
| |
| 2254 ReplaceCall(call, bin_op); | 2252 ReplaceCall(call, bin_op); |
| 2255 return true; | 2253 return true; |
| 2256 } | 2254 } |
| 2257 } | 2255 } |
| 2258 // Insert two smi checks and attach a copy of the original | 2256 // Insert two smi checks and attach a copy of the original |
| 2259 // environment because the smi operation can still deoptimize. | 2257 // environment because the smi operation can still deoptimize. |
| 2260 AddCheckSmi(left, call->deopt_id(), call->env(), call); | 2258 AddCheckSmi(left, call->deopt_id(), call->env(), call); |
| 2261 AddCheckSmi(right, call->deopt_id(), call->env(), call); | 2259 AddCheckSmi(right, call->deopt_id(), call->env(), call); |
| 2262 BinarySmiOpInstr* bin_op = | 2260 BinarySmiOpInstr* bin_op = |
| 2263 new(I) BinarySmiOpInstr(op_kind, | 2261 new(I) BinarySmiOpInstr(op_kind, |
| 2264 new(I) Value(left), | 2262 new(I) Value(left), |
| 2265 new(I) Value(right), | 2263 new(I) Value(right), |
| 2266 call->deopt_id(), call->token_pos()); | 2264 call->deopt_id()); |
| 2267 ReplaceCall(call, bin_op); | 2265 ReplaceCall(call, bin_op); |
| 2268 } else { | 2266 } else { |
| 2269 ASSERT(operands_type == kSmiCid); | 2267 ASSERT(operands_type == kSmiCid); |
| 2270 // Insert two smi checks and attach a copy of the original | 2268 // Insert two smi checks and attach a copy of the original |
| 2271 // environment because the smi operation can still deoptimize. | 2269 // environment because the smi operation can still deoptimize. |
| 2272 AddCheckSmi(left, call->deopt_id(), call->env(), call); | 2270 AddCheckSmi(left, call->deopt_id(), call->env(), call); |
| 2273 AddCheckSmi(right, call->deopt_id(), call->env(), call); | 2271 AddCheckSmi(right, call->deopt_id(), call->env(), call); |
| 2274 if (left->IsConstant() && | 2272 if (left->IsConstant() && |
| 2275 ((op_kind == Token::kADD) || (op_kind == Token::kMUL))) { | 2273 ((op_kind == Token::kADD) || (op_kind == Token::kMUL))) { |
| 2276 // Constant should be on the right side. | 2274 // Constant should be on the right side. |
| 2277 Definition* temp = left; | 2275 Definition* temp = left; |
| 2278 left = right; | 2276 left = right; |
| 2279 right = temp; | 2277 right = temp; |
| 2280 } | 2278 } |
| 2281 BinarySmiOpInstr* bin_op = | 2279 BinarySmiOpInstr* bin_op = |
| 2282 new(I) BinarySmiOpInstr( | 2280 new(I) BinarySmiOpInstr( |
| 2283 op_kind, new(I) Value(left), new(I) Value(right), | 2281 op_kind, |
| 2284 call->deopt_id(), call->token_pos()); | 2282 new(I) Value(left), |
| 2283 new(I) Value(right), | |
| 2284 call->deopt_id()); | |
| 2285 ReplaceCall(call, bin_op); | 2285 ReplaceCall(call, bin_op); |
| 2286 } | 2286 } |
| 2287 return true; | 2287 return true; |
| 2288 } | 2288 } |
| 2289 | 2289 |
| 2290 | 2290 |
| 2291 bool FlowGraphOptimizer::TryReplaceWithUnaryOp(InstanceCallInstr* call, | 2291 bool FlowGraphOptimizer::TryReplaceWithUnaryOp(InstanceCallInstr* call, |
| 2292 Token::Kind op_kind) { | 2292 Token::Kind op_kind) { |
| 2293 ASSERT(call->ArgumentCount() == 1); | 2293 ASSERT(call->ArgumentCount() == 1); |
| 2294 Definition* input = call->ArgumentAt(0); | 2294 Definition* input = call->ArgumentAt(0); |
| (...skipping 869 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3164 const int64_t mask_value = mask_literal.AsInt64Value(); | 3164 const int64_t mask_value = mask_literal.AsInt64Value(); |
| 3165 ASSERT(mask_value >= 0); | 3165 ASSERT(mask_value >= 0); |
| 3166 if (mask_value > Smi::kMaxValue) { | 3166 if (mask_value > Smi::kMaxValue) { |
| 3167 // The result will not be Smi. | 3167 // The result will not be Smi. |
| 3168 return false; | 3168 return false; |
| 3169 } | 3169 } |
| 3170 BinarySmiOpInstr* left_shift = | 3170 BinarySmiOpInstr* left_shift = |
| 3171 new(I) BinarySmiOpInstr(Token::kSHL, | 3171 new(I) BinarySmiOpInstr(Token::kSHL, |
| 3172 new(I) Value(value), | 3172 new(I) Value(value), |
| 3173 new(I) Value(count), | 3173 new(I) Value(count), |
| 3174 call->deopt_id(), call->token_pos()); | 3174 call->deopt_id()); |
| 3175 left_shift->set_is_truncating(true); | 3175 left_shift->mark_truncating(); |
| 3176 if ((kBitsPerWord == 32) && (mask_value == 0xffffffffLL)) { | 3176 if ((kBitsPerWord == 32) && (mask_value == 0xffffffffLL)) { |
| 3177 // No BIT_AND operation needed. | 3177 // No BIT_AND operation needed. |
| 3178 ReplaceCall(call, left_shift); | 3178 ReplaceCall(call, left_shift); |
| 3179 } else { | 3179 } else { |
| 3180 InsertBefore(call, left_shift, call->env(), FlowGraph::kValue); | 3180 InsertBefore(call, left_shift, call->env(), FlowGraph::kValue); |
| 3181 BinarySmiOpInstr* bit_and = | 3181 BinarySmiOpInstr* bit_and = |
| 3182 new(I) BinarySmiOpInstr(Token::kBIT_AND, | 3182 new(I) BinarySmiOpInstr(Token::kBIT_AND, |
| 3183 new(I) Value(left_shift), | 3183 new(I) Value(left_shift), |
| 3184 new(I) Value(int32_mask), | 3184 new(I) Value(int32_mask), |
| 3185 call->deopt_id(), | 3185 call->deopt_id()); |
| 3186 call->token_pos()); | |
| 3187 ReplaceCall(call, bit_and); | 3186 ReplaceCall(call, bit_and); |
| 3188 } | 3187 } |
| 3189 return true; | 3188 return true; |
| 3190 } | 3189 } |
| 3191 | 3190 |
| 3192 if (HasTwoMintOrSmi(ic_data) && | 3191 if (HasTwoMintOrSmi(ic_data) && |
| 3193 HasOnlyOneSmi(ICData::Handle(I, | 3192 HasOnlyOneSmi(ICData::Handle(I, |
| 3194 ic_data.AsUnaryClassChecksForArgNr(1)))) { | 3193 ic_data.AsUnaryClassChecksForArgNr(1)))) { |
| 3195 if (!FlowGraphCompiler::SupportsUnboxedMints() || | 3194 if (!FlowGraphCompiler::SupportsUnboxedMints() || |
| 3196 ic_data.HasDeoptReason(ICData::kDeoptShiftMintOp)) { | 3195 ic_data.HasDeoptReason(ICData::kDeoptShiftMintOp)) { |
| (...skipping 658 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3855 NULL, | 3854 NULL, |
| 3856 FlowGraph::kValue); | 3855 FlowGraph::kValue); |
| 3857 | 3856 |
| 3858 intptr_t element_size = Instance::ElementSizeFor(array_cid); | 3857 intptr_t element_size = Instance::ElementSizeFor(array_cid); |
| 3859 ConstantInstr* bytes_per_element = | 3858 ConstantInstr* bytes_per_element = |
| 3860 flow_graph()->GetConstant(Smi::Handle(I, Smi::New(element_size))); | 3859 flow_graph()->GetConstant(Smi::Handle(I, Smi::New(element_size))); |
| 3861 BinarySmiOpInstr* len_in_bytes = | 3860 BinarySmiOpInstr* len_in_bytes = |
| 3862 new(I) BinarySmiOpInstr(Token::kMUL, | 3861 new(I) BinarySmiOpInstr(Token::kMUL, |
| 3863 new(I) Value(length), | 3862 new(I) Value(length), |
| 3864 new(I) Value(bytes_per_element), | 3863 new(I) Value(bytes_per_element), |
| 3865 call->deopt_id(), call->token_pos()); | 3864 call->deopt_id()); |
| 3866 *cursor = flow_graph()->AppendTo(*cursor, len_in_bytes, call->env(), | 3865 *cursor = flow_graph()->AppendTo(*cursor, len_in_bytes, call->env(), |
| 3867 FlowGraph::kValue); | 3866 FlowGraph::kValue); |
| 3868 | 3867 |
| 3869 // adjusted_length = len_in_bytes - (element_size - 1). | 3868 // adjusted_length = len_in_bytes - (element_size - 1). |
| 3870 Definition* adjusted_length = len_in_bytes; | 3869 Definition* adjusted_length = len_in_bytes; |
| 3871 intptr_t adjustment = Instance::ElementSizeFor(view_cid) - 1; | 3870 intptr_t adjustment = Instance::ElementSizeFor(view_cid) - 1; |
| 3872 if (adjustment > 0) { | 3871 if (adjustment > 0) { |
| 3873 ConstantInstr* length_adjustment = | 3872 ConstantInstr* length_adjustment = |
| 3874 flow_graph()->GetConstant(Smi::Handle(I, Smi::New(adjustment))); | 3873 flow_graph()->GetConstant(Smi::Handle(I, Smi::New(adjustment))); |
| 3875 adjusted_length = | 3874 adjusted_length = |
| 3876 new(I) BinarySmiOpInstr(Token::kSUB, | 3875 new(I) BinarySmiOpInstr(Token::kSUB, |
| 3877 new(I) Value(len_in_bytes), | 3876 new(I) Value(len_in_bytes), |
| 3878 new(I) Value(length_adjustment), | 3877 new(I) Value(length_adjustment), |
| 3879 call->deopt_id(), call->token_pos()); | 3878 call->deopt_id()); |
| 3880 *cursor = flow_graph()->AppendTo(*cursor, adjusted_length, call->env(), | 3879 *cursor = flow_graph()->AppendTo(*cursor, adjusted_length, call->env(), |
| 3881 FlowGraph::kValue); | 3880 FlowGraph::kValue); |
| 3882 } | 3881 } |
| 3883 | 3882 |
| 3884 // Check adjusted_length > 0. | 3883 // Check adjusted_length > 0. |
| 3885 ConstantInstr* zero = | 3884 ConstantInstr* zero = |
| 3886 flow_graph()->GetConstant(Smi::Handle(I, Smi::New(0))); | 3885 flow_graph()->GetConstant(Smi::Handle(I, Smi::New(0))); |
| 3887 *cursor = flow_graph()->AppendTo(*cursor, | 3886 *cursor = flow_graph()->AppendTo(*cursor, |
| 3888 new(I) CheckArrayBoundInstr( | 3887 new(I) CheckArrayBoundInstr( |
| 3889 new(I) Value(adjusted_length), | 3888 new(I) Value(adjusted_length), |
| (...skipping 3800 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7690 // cannot have constant values. | 7689 // cannot have constant values. |
| 7691 void ConstantPropagator::VisitStoreContext(StoreContextInstr* instr) { } | 7690 void ConstantPropagator::VisitStoreContext(StoreContextInstr* instr) { } |
| 7692 | 7691 |
| 7693 | 7692 |
| 7694 void ConstantPropagator::VisitCheckStackOverflow( | 7693 void ConstantPropagator::VisitCheckStackOverflow( |
| 7695 CheckStackOverflowInstr* instr) { } | 7694 CheckStackOverflowInstr* instr) { } |
| 7696 | 7695 |
| 7697 | 7696 |
| 7698 void ConstantPropagator::VisitCheckClass(CheckClassInstr* instr) { } | 7697 void ConstantPropagator::VisitCheckClass(CheckClassInstr* instr) { } |
| 7699 | 7698 |
| 7699 | |
| 7700 void ConstantPropagator::VisitCheckClassId(CheckClassIdInstr* instr) { } | 7700 void ConstantPropagator::VisitCheckClassId(CheckClassIdInstr* instr) { } |
| 7701 | 7701 |
| 7702 | |
| 7702 void ConstantPropagator::VisitGuardFieldClass(GuardFieldClassInstr* instr) { } | 7703 void ConstantPropagator::VisitGuardFieldClass(GuardFieldClassInstr* instr) { } |
| 7703 | 7704 |
| 7705 | |
| 7704 void ConstantPropagator::VisitGuardFieldLength(GuardFieldLengthInstr* instr) { } | 7706 void ConstantPropagator::VisitGuardFieldLength(GuardFieldLengthInstr* instr) { } |
| 7705 | 7707 |
| 7708 | |
| 7706 void ConstantPropagator::VisitCheckSmi(CheckSmiInstr* instr) { } | 7709 void ConstantPropagator::VisitCheckSmi(CheckSmiInstr* instr) { } |
| 7707 | 7710 |
| 7708 | 7711 |
| 7709 void ConstantPropagator::VisitCheckEitherNonSmi( | 7712 void ConstantPropagator::VisitCheckEitherNonSmi( |
| 7710 CheckEitherNonSmiInstr* instr) { } | 7713 CheckEitherNonSmiInstr* instr) { } |
| 7711 | 7714 |
| 7712 | 7715 |
| 7713 void ConstantPropagator::VisitCheckArrayBound(CheckArrayBoundInstr* instr) { } | 7716 void ConstantPropagator::VisitCheckArrayBound(CheckArrayBoundInstr* instr) { } |
| 7714 | 7717 |
| 7715 | 7718 |
| 7719 void ConstantPropagator::VisitDeoptimize(DeoptimizeInstr* instr) { | |
| 7720 // TODO(vegorov) remove all code after DeoptimizeInstr as dead. | |
| 7721 } | |
| 7722 | |
| 7723 | |
| 7716 // -------------------------------------------------------------------------- | 7724 // -------------------------------------------------------------------------- |
| 7717 // Analysis of definitions. Compute the constant value. If it has changed | 7725 // Analysis of definitions. Compute the constant value. If it has changed |
| 7718 // and the definition has input uses, add the definition to the definition | 7726 // and the definition has input uses, add the definition to the definition |
| 7719 // worklist so that the used can be processed. | 7727 // worklist so that the used can be processed. |
| 7720 void ConstantPropagator::VisitPhi(PhiInstr* instr) { | 7728 void ConstantPropagator::VisitPhi(PhiInstr* instr) { |
| 7721 // Compute the join over all the reachable predecessor values. | 7729 // Compute the join over all the reachable predecessor values. |
| 7722 JoinEntryInstr* block = instr->block(); | 7730 JoinEntryInstr* block = instr->block(); |
| 7723 Object& value = Object::ZoneHandle(I, Unknown()); | 7731 Object& value = Object::ZoneHandle(I, Unknown()); |
| 7724 for (intptr_t pred_idx = 0; pred_idx < instr->InputCount(); ++pred_idx) { | 7732 for (intptr_t pred_idx = 0; pred_idx < instr->InputCount(); ++pred_idx) { |
| 7725 if (reachable_->Contains( | 7733 if (reachable_->Contains( |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8012 if (o.IsNull() || IsNonConstant(o)) { | 8020 if (o.IsNull() || IsNonConstant(o)) { |
| 8013 SetValue(instr, non_constant_); | 8021 SetValue(instr, non_constant_); |
| 8014 } else if (IsConstant(o)) { | 8022 } else if (IsConstant(o)) { |
| 8015 const String& str = String::Cast(o); | 8023 const String& str = String::Cast(o); |
| 8016 const intptr_t result = (str.Length() == 1) ? str.CharAt(0) : -1; | 8024 const intptr_t result = (str.Length() == 1) ? str.CharAt(0) : -1; |
| 8017 SetValue(instr, Smi::ZoneHandle(I, Smi::New(result))); | 8025 SetValue(instr, Smi::ZoneHandle(I, Smi::New(result))); |
| 8018 } | 8026 } |
| 8019 } | 8027 } |
| 8020 | 8028 |
| 8021 | 8029 |
| 8022 | |
| 8023 | |
| 8024 void ConstantPropagator::VisitStringInterpolate(StringInterpolateInstr* instr) { | 8030 void ConstantPropagator::VisitStringInterpolate(StringInterpolateInstr* instr) { |
| 8025 SetValue(instr, non_constant_); | 8031 SetValue(instr, non_constant_); |
| 8026 return; | |
| 8027 } | 8032 } |
| 8028 | 8033 |
| 8029 | 8034 |
| 8030 void ConstantPropagator::VisitLoadIndexed(LoadIndexedInstr* instr) { | 8035 void ConstantPropagator::VisitLoadIndexed(LoadIndexedInstr* instr) { |
| 8031 const Object& array_obj = instr->array()->definition()->constant_value(); | 8036 const Object& array_obj = instr->array()->definition()->constant_value(); |
| 8032 const Object& index_obj = instr->index()->definition()->constant_value(); | 8037 const Object& index_obj = instr->index()->definition()->constant_value(); |
| 8033 if (IsNonConstant(array_obj) || IsNonConstant(index_obj)) { | 8038 if (IsNonConstant(array_obj) || IsNonConstant(index_obj)) { |
| 8034 SetValue(instr, non_constant_); | 8039 SetValue(instr, non_constant_); |
| 8035 } else if (IsConstant(array_obj) && IsConstant(index_obj)) { | 8040 } else if (IsConstant(array_obj) && IsConstant(index_obj)) { |
| 8036 // Need index to be Smi and array to be either String or an immutable array. | 8041 // Need index to be Smi and array to be either String or an immutable array. |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8258 AllocateUninitializedContextInstr* instr) { | 8263 AllocateUninitializedContextInstr* instr) { |
| 8259 SetValue(instr, non_constant_); | 8264 SetValue(instr, non_constant_); |
| 8260 } | 8265 } |
| 8261 | 8266 |
| 8262 | 8267 |
| 8263 void ConstantPropagator::VisitCloneContext(CloneContextInstr* instr) { | 8268 void ConstantPropagator::VisitCloneContext(CloneContextInstr* instr) { |
| 8264 SetValue(instr, non_constant_); | 8269 SetValue(instr, non_constant_); |
| 8265 } | 8270 } |
| 8266 | 8271 |
| 8267 | 8272 |
| 8268 void ConstantPropagator::HandleBinaryOp(Definition* instr, | 8273 void ConstantPropagator::VisitBinaryIntegerOp(BinaryIntegerOpInstr* binary_op) { |
| 8269 Token::Kind op_kind, | 8274 const Object& left = binary_op->left()->definition()->constant_value(); |
| 8270 const Value& left_val, | 8275 const Object& right = binary_op->right()->definition()->constant_value(); |
| 8271 const Value& right_val) { | 8276 if (IsConstant(left) && IsConstant(right)) { |
| 8272 const Object& left = left_val.definition()->constant_value(); | |
| 8273 const Object& right = right_val.definition()->constant_value(); | |
| 8274 if (IsNonConstant(left) || IsNonConstant(right)) { | |
| 8275 // TODO(srdjan): Add arithmetic simplifications, e.g, add with 0. | |
| 8276 SetValue(instr, non_constant_); | |
| 8277 } else if (IsConstant(left) && IsConstant(right)) { | |
| 8278 if (left.IsInteger() && right.IsInteger()) { | 8277 if (left.IsInteger() && right.IsInteger()) { |
| 8279 const Integer& left_int = Integer::Cast(left); | 8278 const Integer& left_int = Integer::Cast(left); |
| 8280 const Integer& right_int = Integer::Cast(right); | 8279 const Integer& right_int = Integer::Cast(right); |
| 8281 switch (op_kind) { | 8280 const Integer& result = |
| 8282 case Token::kTRUNCDIV: | 8281 Integer::Handle(I, binary_op->Evaluate(left_int, right_int)); |
| 8283 case Token::kMOD: | 8282 if (!result.IsNull()) { |
| 8284 // Check right value for zero. | 8283 SetValue(binary_op, Integer::ZoneHandle(I, result.raw())); |
| 8285 if (right_int.AsInt64Value() == 0) { | 8284 return; |
| 8286 SetValue(instr, non_constant_); | |
| 8287 break; | |
| 8288 } | |
| 8289 // Fall through. | |
| 8290 case Token::kADD: | |
| 8291 case Token::kSUB: | |
| 8292 case Token::kMUL: { | |
| 8293 Instance& result = Integer::ZoneHandle(I, | |
| 8294 left_int.ArithmeticOp(op_kind, right_int)); | |
| 8295 if (result.IsNull()) { | |
| 8296 // TODO(regis): A bigint operation is required. Invoke dart? | |
| 8297 // Punt for now. | |
| 8298 SetValue(instr, non_constant_); | |
| 8299 break; | |
| 8300 } | |
| 8301 result = result.CheckAndCanonicalize(NULL); | |
| 8302 ASSERT(!result.IsNull()); | |
| 8303 SetValue(instr, result); | |
| 8304 break; | |
| 8305 } | |
| 8306 case Token::kSHL: | |
| 8307 case Token::kSHR: | |
| 8308 if (left.IsSmi() && | |
| 8309 right.IsSmi() && | |
| 8310 (Smi::Cast(right).Value() >= 0)) { | |
| 8311 Instance& result = Integer::ZoneHandle(I, | |
| 8312 Smi::Cast(left_int).ShiftOp(op_kind, Smi::Cast(right_int))); | |
| 8313 result = result.CheckAndCanonicalize(NULL); | |
| 8314 ASSERT(!result.IsNull()); | |
| 8315 SetValue(instr, result); | |
| 8316 } else { | |
| 8317 SetValue(instr, non_constant_); | |
| 8318 } | |
| 8319 break; | |
| 8320 case Token::kBIT_AND: | |
| 8321 case Token::kBIT_OR: | |
| 8322 case Token::kBIT_XOR: { | |
| 8323 Instance& result = Integer::ZoneHandle(I, | |
| 8324 left_int.BitOp(op_kind, right_int)); | |
| 8325 result = result.CheckAndCanonicalize(NULL); | |
| 8326 ASSERT(!result.IsNull()); | |
| 8327 SetValue(instr, result); | |
| 8328 break; | |
| 8329 } | |
| 8330 case Token::kDIV: | |
| 8331 SetValue(instr, non_constant_); | |
| 8332 break; | |
| 8333 default: | |
| 8334 UNREACHABLE(); | |
| 8335 } | 8285 } |
| 8336 } else { | |
| 8337 // TODO(kmillikin): support other types. | |
| 8338 SetValue(instr, non_constant_); | |
| 8339 } | 8286 } |
| 8340 } | 8287 } |
| 8341 } | |
| 8342 | 8288 |
| 8343 | 8289 SetValue(binary_op, non_constant_); |
| 8344 void ConstantPropagator::TruncateInteger(Definition* defn, int64_t mask) { | |
| 8345 const Object& value = defn->constant_value(); | |
| 8346 if (IsNonConstant(value)) { | |
| 8347 return; | |
| 8348 } | |
| 8349 ASSERT(IsConstant(value)); | |
| 8350 if (!value.IsInteger()) { | |
| 8351 return; | |
| 8352 } | |
| 8353 const Integer& value_int = Integer::Cast(value); | |
| 8354 int64_t truncated = value_int.AsInt64Value() & mask; | |
| 8355 Instance& result = Integer::ZoneHandle(I, Integer::New(truncated)); | |
| 8356 result = result.CheckAndCanonicalize(NULL); | |
| 8357 ASSERT(!result.IsNull()); | |
| 8358 SetValue(defn, result); | |
| 8359 } | 8290 } |
| 8360 | 8291 |
| 8361 | 8292 |
| 8362 void ConstantPropagator::VisitBinarySmiOp(BinarySmiOpInstr* instr) { | 8293 void ConstantPropagator::VisitBinarySmiOp(BinarySmiOpInstr* instr) { |
| 8363 HandleBinaryOp(instr, instr->op_kind(), *instr->left(), *instr->right()); | 8294 VisitBinaryIntegerOp(instr); |
| 8364 } | 8295 } |
| 8365 | 8296 |
| 8366 | 8297 |
| 8367 void ConstantPropagator::VisitBinaryInt32Op(BinaryInt32OpInstr* instr) { | 8298 void ConstantPropagator::VisitBinaryInt32Op(BinaryInt32OpInstr* instr) { |
| 8368 HandleBinaryOp(instr, instr->op_kind(), *instr->left(), *instr->right()); | 8299 VisitBinaryIntegerOp(instr); |
| 8300 } | |
| 8301 | |
| 8302 | |
| 8303 void ConstantPropagator::VisitBinaryUint32Op(BinaryUint32OpInstr* instr) { | |
| 8304 VisitBinaryIntegerOp(instr); | |
| 8305 } | |
| 8306 | |
| 8307 | |
| 8308 void ConstantPropagator::VisitShiftUint32Op(ShiftUint32OpInstr* instr) { | |
| 8309 VisitBinaryIntegerOp(instr); | |
| 8310 } | |
| 8311 | |
| 8312 | |
| 8313 void ConstantPropagator::VisitBinaryMintOp(BinaryMintOpInstr* instr) { | |
| 8314 VisitBinaryIntegerOp(instr); | |
| 8315 } | |
| 8316 | |
| 8317 | |
| 8318 void ConstantPropagator::VisitShiftMintOp(ShiftMintOpInstr* instr) { | |
| 8319 VisitBinaryIntegerOp(instr); | |
| 8369 } | 8320 } |
| 8370 | 8321 |
| 8371 | 8322 |
| 8372 void ConstantPropagator::VisitBoxInteger(BoxIntegerInstr* instr) { | 8323 void ConstantPropagator::VisitBoxInteger(BoxIntegerInstr* instr) { |
| 8373 // TODO(kmillikin): Handle box operation. | 8324 // TODO(kmillikin): Handle box operation. |
| 8374 SetValue(instr, non_constant_); | 8325 SetValue(instr, non_constant_); |
| 8375 } | 8326 } |
| 8376 | 8327 |
| 8377 | 8328 |
| 8378 void ConstantPropagator::VisitUnboxInteger(UnboxIntegerInstr* instr) { | 8329 void ConstantPropagator::VisitUnboxInteger(UnboxIntegerInstr* instr) { |
| 8379 // TODO(kmillikin): Handle unbox operation. | 8330 // TODO(kmillikin): Handle unbox operation. |
| 8380 SetValue(instr, non_constant_); | 8331 SetValue(instr, non_constant_); |
| 8381 } | 8332 } |
| 8382 | 8333 |
| 8383 | 8334 |
| 8384 void ConstantPropagator::VisitBinaryMintOp(BinaryMintOpInstr* instr) { | |
| 8385 HandleBinaryOp(instr, instr->op_kind(), *instr->left(), *instr->right()); | |
| 8386 } | |
| 8387 | |
| 8388 | |
| 8389 void ConstantPropagator::VisitShiftMintOp(ShiftMintOpInstr* instr) { | |
| 8390 HandleBinaryOp(instr, instr->op_kind(), *instr->left(), *instr->right()); | |
| 8391 } | |
| 8392 | |
| 8393 | |
| 8394 void ConstantPropagator::VisitUnaryMintOp(UnaryMintOpInstr* instr) { | 8335 void ConstantPropagator::VisitUnaryMintOp(UnaryMintOpInstr* instr) { |
| 8395 // TODO(kmillikin): Handle unary operations. | 8336 // TODO(kmillikin): Handle unary operations. |
| 8396 SetValue(instr, non_constant_); | 8337 SetValue(instr, non_constant_); |
| 8397 } | 8338 } |
| 8398 | 8339 |
| 8399 | 8340 |
| 8400 void ConstantPropagator::VisitUnarySmiOp(UnarySmiOpInstr* instr) { | 8341 void ConstantPropagator::VisitUnarySmiOp(UnarySmiOpInstr* instr) { |
| 8401 const Object& value = instr->value()->definition()->constant_value(); | 8342 const Object& value = instr->value()->definition()->constant_value(); |
| 8402 if (IsNonConstant(value)) { | 8343 if (IsNonConstant(value)) { |
| 8403 SetValue(instr, non_constant_); | 8344 SetValue(instr, non_constant_); |
| (...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8859 SetValue(instr, non_constant_); | 8800 SetValue(instr, non_constant_); |
| 8860 } | 8801 } |
| 8861 | 8802 |
| 8862 | 8803 |
| 8863 void ConstantPropagator::VisitUnboxedIntConverter( | 8804 void ConstantPropagator::VisitUnboxedIntConverter( |
| 8864 UnboxedIntConverterInstr* instr) { | 8805 UnboxedIntConverterInstr* instr) { |
| 8865 SetValue(instr, non_constant_); | 8806 SetValue(instr, non_constant_); |
| 8866 } | 8807 } |
| 8867 | 8808 |
| 8868 | 8809 |
| 8869 void ConstantPropagator::VisitBinaryUint32Op(BinaryUint32OpInstr* instr) { | |
| 8870 HandleBinaryOp(instr, instr->op_kind(), *instr->left(), *instr->right()); | |
| 8871 TruncateInteger(instr, static_cast<int64_t>(0xFFFFFFFF)); | |
| 8872 } | |
| 8873 | |
| 8874 | |
| 8875 void ConstantPropagator::VisitShiftUint32Op(ShiftUint32OpInstr* instr) { | |
| 8876 HandleBinaryOp(instr, instr->op_kind(), *instr->left(), *instr->right()); | |
| 8877 TruncateInteger(instr, static_cast<int64_t>(0xFFFFFFFF)); | |
| 8878 } | |
| 8879 | |
| 8880 | |
| 8881 void ConstantPropagator::VisitUnaryUint32Op(UnaryUint32OpInstr* instr) { | 8810 void ConstantPropagator::VisitUnaryUint32Op(UnaryUint32OpInstr* instr) { |
| 8882 // TODO(kmillikin): Handle unary operations. | 8811 // TODO(kmillikin): Handle unary operations. |
| 8883 SetValue(instr, non_constant_); | 8812 SetValue(instr, non_constant_); |
| 8884 } | 8813 } |
| 8885 | 8814 |
| 8886 | 8815 |
| 8887 void ConstantPropagator::Analyze() { | 8816 void ConstantPropagator::Analyze() { |
| 8888 GraphEntryInstr* entry = graph_->graph_entry(); | 8817 GraphEntryInstr* entry = graph_->graph_entry(); |
| 8889 reachable_->Add(entry->preorder_number()); | 8818 reachable_->Add(entry->preorder_number()); |
| 8890 block_worklist_.Add(entry); | 8819 block_worklist_.Add(entry); |
| (...skipping 1202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 10093 | 10022 |
| 10094 // Insert materializations at environment uses. | 10023 // Insert materializations at environment uses. |
| 10095 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { | 10024 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { |
| 10096 CreateMaterializationAt( | 10025 CreateMaterializationAt( |
| 10097 exits_collector_.exits()[i], alloc, alloc->cls(), *slots); | 10026 exits_collector_.exits()[i], alloc, alloc->cls(), *slots); |
| 10098 } | 10027 } |
| 10099 } | 10028 } |
| 10100 | 10029 |
| 10101 | 10030 |
| 10102 } // namespace dart | 10031 } // namespace dart |
| OLD | NEW |