19DEFINE_FLAG(
bool, remove_redundant_phis,
true,
"Remove redundant phis.");
21 trace_constant_propagation,
23 "Print constant propagation and useless code elimination.");
26#define Z (graph_->zone())
27#define T (graph_->thread())
34 unknown_(
Object::unknown_constant()),
35 non_constant_(
Object::non_constant()),
36 constant_value_(
Object::Handle(
Z)),
38 unwrapped_phis_(new(
Z)
BitVector(
Z, graph->current_ssa_temp_index())),
40 definition_worklist_(graph, 10) {}
54 cp.EliminateRedundantBranches();
60 block_worklist_.Add(block);
64bool ConstantPropagator::SetValue(Definition* definition,
const Object&
value) {
73 if (definition->constant_value().ptr() !=
value.ptr()) {
74 definition->constant_value() =
value.ptr();
75 if (definition->input_use_list() !=
nullptr) {
76 definition_worklist_.
Add(definition);
87 if (left.ptr() == right.ptr())
return true;
88 if (left.GetClassId() != right.GetClassId())
return false;
89 if (left.IsInteger()) {
90 return Integer::Cast(left).Equals(Integer::Cast(right));
92 if (left.IsDouble()) {
93 return Double::Cast(left).BitwiseEqualsToDouble(
94 Double::Cast(right).
value());
100void ConstantPropagator::Join(Object* left,
const Object& right) {
103 if (IsNonConstant(*left) || IsUnknown(right))
return;
107 if (IsUnknown(*left) || IsNonConstant(right)) {
122void ConstantPropagator::VisitGraphEntry(GraphEntryInstr* block) {
123 for (
auto def : *block->initial_definitions()) {
126 ASSERT(ForwardInstructionIterator(block).
Done());
130 for (intptr_t
i = 0;
i < block->SuccessorCount(); ++
i) {
131 SetReachable(block->SuccessorAt(
i));
135void ConstantPropagator::VisitFunctionEntry(FunctionEntryInstr* block) {
136 for (
auto def : *block->initial_definitions()) {
139 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
140 it.Current()->Accept(
this);
144void ConstantPropagator::VisitNativeEntry(NativeEntryInstr* block) {
145 VisitFunctionEntry(block);
148void ConstantPropagator::VisitOsrEntry(OsrEntryInstr* block) {
149 for (
auto def : *block->initial_definitions()) {
152 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
153 it.Current()->Accept(
this);
157void ConstantPropagator::VisitCatchBlockEntry(CatchBlockEntryInstr* block) {
158 for (
auto def : *block->initial_definitions()) {
161 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
162 it.Current()->Accept(
this);
166void ConstantPropagator::VisitJoinEntry(JoinEntryInstr* block) {
168 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
169 it.Current()->Accept(
this);
173void ConstantPropagator::VisitTargetEntry(TargetEntryInstr* block) {
174 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
175 it.Current()->Accept(
this);
179void ConstantPropagator::VisitIndirectEntry(IndirectEntryInstr* block) {
180 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
181 it.Current()->Accept(
this);
185void ConstantPropagator::VisitParallelMove(ParallelMoveInstr* instr) {
194void ConstantPropagator::VisitDartReturn(DartReturnInstr* instr) {
198void ConstantPropagator::VisitNativeReturn(NativeReturnInstr* instr) {
202void ConstantPropagator::VisitThrow(ThrowInstr* instr) {
206void ConstantPropagator::VisitReThrow(ReThrowInstr* instr) {
210void ConstantPropagator::VisitStop(StopInstr* instr) {
214void ConstantPropagator::VisitGoto(GotoInstr* instr) {
215 SetReachable(instr->successor());
219 for (PhiIterator it(instr->successor()); !it.Done(); it.Advance()) {
220 PhiInstr* phi = it.Current();
225 if (unwrapped_phis_->
Contains(phi->ssa_temp_index()) &&
226 (UnwrapPhi(phi) == phi)) {
227 unwrapped_phis_->
Remove(phi->ssa_temp_index());
228 definition_worklist_.
Add(phi);
233void ConstantPropagator::VisitIndirectGoto(IndirectGotoInstr* instr) {
234 if (reachable_->
Contains(instr->GetBlock()->preorder_number())) {
235 for (intptr_t
i = 0;
i < instr->SuccessorCount();
i++) {
236 SetReachable(instr->SuccessorAt(
i));
241void ConstantPropagator::VisitBranch(BranchInstr* instr) {
242 instr->comparison()->Accept(
this);
247 if (reachable_->
Contains(instr->GetBlock()->preorder_number())) {
248 if (instr->constant_target() !=
nullptr) {
249 ASSERT((instr->constant_target() == instr->true_successor()) ||
250 (instr->constant_target() == instr->false_successor()));
251 SetReachable(instr->constant_target());
253 const Object&
value = instr->comparison()->constant_value();
254 if (IsNonConstant(
value)) {
255 SetReachable(instr->true_successor());
256 SetReachable(instr->false_successor());
258 SetReachable(instr->true_successor());
259 }
else if (!IsUnknown(
value)) {
260 SetReachable(instr->false_successor());
269void ConstantPropagator::VisitCheckStackOverflow(
270 CheckStackOverflowInstr* instr) {}
272void ConstantPropagator::VisitCheckClass(CheckClassInstr* instr) {}
274void ConstantPropagator::VisitCheckCondition(CheckConditionInstr* instr) {}
276void ConstantPropagator::VisitCheckClassId(CheckClassIdInstr* instr) {}
278void ConstantPropagator::VisitGuardFieldClass(GuardFieldClassInstr* instr) {}
280void ConstantPropagator::VisitGuardFieldLength(GuardFieldLengthInstr* instr) {}
282void ConstantPropagator::VisitGuardFieldType(GuardFieldTypeInstr* instr) {}
284void ConstantPropagator::VisitCheckSmi(CheckSmiInstr* instr) {}
286void ConstantPropagator::VisitTailCall(TailCallInstr* instr) {}
288void ConstantPropagator::VisitCheckEitherNonSmi(CheckEitherNonSmiInstr* instr) {
291void ConstantPropagator::VisitStoreIndexedUnsafe(
292 StoreIndexedUnsafeInstr* instr) {}
294void ConstantPropagator::VisitStoreIndexed(StoreIndexedInstr* instr) {}
296void ConstantPropagator::VisitStoreField(StoreFieldInstr* instr) {}
298void ConstantPropagator::VisitMemoryCopy(MemoryCopyInstr* instr) {}
300void ConstantPropagator::VisitDeoptimize(DeoptimizeInstr* instr) {
304Definition* ConstantPropagator::UnwrapPhi(Definition* defn) {
306 JoinEntryInstr* block = defn->AsPhi()->block();
308 Definition* input =
nullptr;
309 for (intptr_t
i = 0;
i < defn->InputCount(); ++
i) {
310 if (reachable_->
Contains(block->PredecessorAt(
i)->preorder_number())) {
311 if (input ==
nullptr) {
312 input = defn->InputAt(
i)->definition();
325void ConstantPropagator::MarkUnwrappedPhi(Definition* phi) {
327 unwrapped_phis_->
Add(phi->ssa_temp_index());
330ConstantPropagator::PhiInfo* ConstantPropagator::GetPhiInfo(PhiInstr* phi) {
331 if (phi->HasPassSpecificId(CompilerPass::kConstantPropagation)) {
333 phi->GetPassSpecificId(CompilerPass::kConstantPropagation);
336 if (
id < phis_.
length() && phis_[
id].phi == phi) {
341 phi->SetPassSpecificId(CompilerPass::kConstantPropagation, phis_.
length());
343 return &phis_.
Last();
350void ConstantPropagator::VisitPhi(PhiInstr* instr) {
360 auto info = GetPhiInfo(instr);
362 const intptr_t kMaxVisitsExpected = 5 * instr->InputCount();
363 if (
info->visit_count > kMaxVisitsExpected) {
365 "ConstantPropagation pass is failing to converge on graph for %s\n",
367 OS::PrintErr(
"Phi %s was visited %" Pd " times\n", instr->ToCString(),
371 FATAL(
"Aborting due to non-convergence.");
375 JoinEntryInstr* block = instr->block();
377 for (intptr_t pred_idx = 0; pred_idx < instr->InputCount(); ++pred_idx) {
379 block->PredecessorAt(pred_idx)->preorder_number())) {
380 Join(&
value, instr->InputAt(pred_idx)->definition()->constant_value());
383 SetValue(instr,
value);
386void ConstantPropagator::VisitRedefinition(RedefinitionInstr* instr) {
387 if (instr->inserted_by_constant_propagation()) {
391 const Object&
value = instr->value()->definition()->constant_value();
392 if (IsConstant(
value)) {
393 SetValue(instr,
value);
395 SetValue(instr, non_constant_);
399void ConstantPropagator::VisitReachabilityFence(ReachabilityFenceInstr* instr) {
403void ConstantPropagator::VisitCheckArrayBound(CheckArrayBoundInstr* instr) {
407 SetValue(instr, non_constant_);
410void ConstantPropagator::VisitGenericCheckBound(GenericCheckBoundInstr* instr) {
414 SetValue(instr, non_constant_);
417void ConstantPropagator::VisitCheckWritable(CheckWritableInstr* instr) {
421 SetValue(instr, non_constant_);
424void ConstantPropagator::VisitCheckNull(CheckNullInstr* instr) {
428 SetValue(instr, non_constant_);
431void ConstantPropagator::VisitParameter(ParameterInstr* instr) {
432 SetValue(instr, non_constant_);
435void ConstantPropagator::VisitNativeParameter(NativeParameterInstr* instr) {
436 SetValue(instr, non_constant_);
439void ConstantPropagator::VisitMoveArgument(MoveArgumentInstr* instr) {
443void ConstantPropagator::VisitAssertAssignable(AssertAssignableInstr* instr) {
444 const auto&
value = instr->value()->definition()->constant_value();
445 const auto& dst_type = instr->dst_type()->definition()->constant_value();
447 if (IsNonConstant(
value) || IsNonConstant(dst_type)) {
448 SetValue(instr, non_constant_);
450 }
else if (IsUnknown(
value) || IsUnknown(dst_type)) {
454 if (dst_type.IsAbstractType()) {
457 if (instr->value()->Type()->IsAssignableTo(AbstractType::Cast(dst_type))) {
458 SetValue(instr,
value);
462 SetValue(instr, non_constant_);
465void ConstantPropagator::VisitAssertSubtype(AssertSubtypeInstr* instr) {}
467void ConstantPropagator::VisitAssertBoolean(AssertBooleanInstr* instr) {
468 const Object&
value = instr->value()->definition()->constant_value();
469 if (IsUnknown(
value)) {
472 if (
value.IsBool()) {
473 SetValue(instr,
value);
475 SetValue(instr, non_constant_);
479void ConstantPropagator::VisitClosureCall(ClosureCallInstr* instr) {
480 SetValue(instr, non_constant_);
483void ConstantPropagator::VisitInstanceCall(InstanceCallInstr* instr) {
484 SetValue(instr, non_constant_);
487void ConstantPropagator::VisitPolymorphicInstanceCall(
488 PolymorphicInstanceCallInstr* instr) {
489 SetValue(instr, non_constant_);
492void ConstantPropagator::VisitDispatchTableCall(DispatchTableCallInstr* instr) {
493 SetValue(instr, non_constant_);
496void ConstantPropagator::VisitStaticCall(StaticCallInstr* instr) {
497 const auto kind = instr->function().recognized_kind();
499 if (instr->ArgumentCount() == 1) {
500 const Object& argument = instr->ArgumentAt(0)->constant_value();
501 if (IsUnknown(argument)) {
504 if (IsConstant(argument)) {
506 if (instr->Evaluate(graph_, argument, &
value)) {
507 SetValue(instr,
value);
511 }
else if (instr->ArgumentCount() == 2) {
512 const Object& argument1 = instr->ArgumentAt(0)->constant_value();
513 const Object& argument2 = instr->ArgumentAt(1)->constant_value();
514 if (IsUnknown(argument1) || IsUnknown(argument2)) {
517 if (IsConstant(argument1) && IsConstant(argument2)) {
519 if (instr->Evaluate(graph_, argument1, argument2, &
value)) {
520 SetValue(instr,
value);
528 case MethodRecognizer::kOneByteString_equality:
529 case MethodRecognizer::kTwoByteString_equality: {
530 ASSERT(instr->FirstArgIndex() == 0);
532 if (instr->ArgumentAt(0)->OriginalDefinition() ==
533 instr->ArgumentAt(1)->OriginalDefinition()) {
542 SetValue(instr, non_constant_);
545void ConstantPropagator::VisitCachableIdempotentCall(
546 CachableIdempotentCallInstr* instr) {
548 SetValue(instr, non_constant_);
551void ConstantPropagator::VisitLoadLocal(LoadLocalInstr* instr) {
556void ConstantPropagator::VisitDropTemps(DropTempsInstr* instr) {
561void ConstantPropagator::VisitMakeTemp(MakeTempInstr* instr) {
566void ConstantPropagator::VisitStoreLocal(StoreLocalInstr* instr) {
571void ConstantPropagator::VisitIfThenElse(IfThenElseInstr* instr) {
572 instr->comparison()->Accept(
this);
573 const Object&
value = instr->comparison()->constant_value();
575 if (IsUnknown(
value)) {
578 if (
value.IsBool()) {
581 : instr->if_false())));
583 SetValue(instr, non_constant_);
587void ConstantPropagator::VisitStrictCompare(StrictCompareInstr* instr) {
588 Definition* left_defn = instr->left()->definition();
589 Definition* right_defn = instr->right()->definition();
591 Definition* unwrapped_left_defn = UnwrapPhi(left_defn);
592 Definition* unwrapped_right_defn = UnwrapPhi(right_defn);
593 if (unwrapped_left_defn == unwrapped_right_defn) {
595 if (SetValue(instr,
Bool::Get(instr->kind() == Token::kEQ_STRICT))) {
596 if (unwrapped_left_defn != left_defn) {
597 MarkUnwrappedPhi(left_defn);
599 if (unwrapped_right_defn != right_defn) {
600 MarkUnwrappedPhi(right_defn);
606 const Object&
left = left_defn->constant_value();
607 const Object&
right = right_defn->constant_value();
608 if (IsNonConstant(left) || IsNonConstant(right)) {
609 if ((
left.ptr() == Object::sentinel().ptr() &&
610 !instr->right()->Type()->can_be_sentinel()) ||
611 (
right.ptr() == Object::sentinel().ptr() &&
612 !instr->left()->Type()->can_be_sentinel())) {
614 SetValue(instr,
Bool::Get(instr->kind() != Token::kEQ_STRICT));
615 }
else if ((
left.IsNull() &&
616 instr->right()->Type()->HasDecidableNullability()) ||
618 instr->left()->Type()->HasDecidableNullability())) {
620 bool result =
left.IsNull() ? instr->right()->Type()->IsNull()
621 : instr->left()->Type()->IsNull();
622 if (instr->kind() == Token::kNE_STRICT) {
627 const intptr_t left_cid = instr->left()->Type()->ToCid();
628 const intptr_t right_cid = instr->right()->Type()->ToCid();
632 (left_cid != right_cid)) {
633 const bool result = (instr->kind() != Token::kEQ_STRICT);
636 SetValue(instr, non_constant_);
639 }
else if (IsConstant(left) && IsConstant(right)) {
641 if (instr->kind() == Token::kNE_STRICT) {
651 const int result = left.CompareWith(right);
673void ConstantPropagator::VisitTestInt(TestIntInstr* instr) {
674 const Object& left = instr->left()->definition()->constant_value();
675 const Object& right = instr->right()->definition()->constant_value();
676 if (IsNonConstant(left) || IsNonConstant(right)) {
677 SetValue(instr, non_constant_);
679 }
else if (IsUnknown(left) || IsUnknown(right)) {
682 ASSERT(IsConstant(left) && IsConstant(right));
683 if (
left.IsInteger() &&
right.IsInteger()) {
687 Integer::Cast(right))),
691 SetValue(instr, non_constant_);
695void ConstantPropagator::VisitTestCids(TestCidsInstr* instr) {
697 SetValue(instr, non_constant_);
700void ConstantPropagator::VisitTestRange(TestRangeInstr* instr) {
701 const Object& input = instr->value()->definition()->constant_value();
702 if (IsNonConstant(input)) {
703 SetValue(instr, non_constant_);
704 }
else if (IsConstant(input) && input.IsSmi()) {
706 bool in_range = (instr->lower() <=
value) && (value <= instr->upper());
707 ASSERT((instr->kind() == Token::kIS) || (instr->kind() == Token::kISNOT));
708 SetValue(instr,
Bool::Get(in_range == (instr->kind() == Token::kIS)));
712void ConstantPropagator::VisitEqualityCompare(EqualityCompareInstr* instr) {
713 Definition* left_defn = instr->left()->definition();
714 Definition* right_defn = instr->right()->definition();
718 Definition* unwrapped_left_defn = UnwrapPhi(left_defn);
719 Definition* unwrapped_right_defn = UnwrapPhi(right_defn);
720 if (unwrapped_left_defn == unwrapped_right_defn) {
722 if (SetValue(instr,
Bool::Get(instr->kind() == Token::kEQ))) {
723 if (unwrapped_left_defn != left_defn) {
724 MarkUnwrappedPhi(left_defn);
726 if (unwrapped_right_defn != right_defn) {
727 MarkUnwrappedPhi(right_defn);
734 const Object&
left = left_defn->constant_value();
735 const Object&
right = right_defn->constant_value();
736 if (IsNonConstant(left) || IsNonConstant(right)) {
737 SetValue(instr, non_constant_);
738 }
else if (IsConstant(left) && IsConstant(right)) {
739 if (
left.IsInteger() &&
right.IsInteger()) {
741 Integer::Cast(right));
743 }
else if (
left.IsString() &&
right.IsString()) {
744 const bool result = String::Cast(left).Equals(String::Cast(right));
747 SetValue(instr, non_constant_);
752void ConstantPropagator::VisitRelationalOp(RelationalOpInstr* instr) {
753 const Object&
left = instr->left()->definition()->constant_value();
754 const Object&
right = instr->right()->definition()->constant_value();
755 if (IsNonConstant(left) || IsNonConstant(right)) {
756 SetValue(instr, non_constant_);
757 }
else if (IsConstant(left) && IsConstant(right)) {
758 if (
left.IsInteger() &&
right.IsInteger()) {
760 Integer::Cast(right));
762 }
else if (
left.IsDouble() &&
right.IsDouble()) {
764 SetValue(instr, non_constant_);
766 SetValue(instr, non_constant_);
771void ConstantPropagator::VisitNativeCall(NativeCallInstr* instr) {
772 SetValue(instr, non_constant_);
775void ConstantPropagator::VisitFfiCall(FfiCallInstr* instr) {
776 SetValue(instr, non_constant_);
779void ConstantPropagator::VisitLeafRuntimeCall(LeafRuntimeCallInstr* instr) {
780 SetValue(instr, non_constant_);
783void ConstantPropagator::VisitDebugStepCheck(DebugStepCheckInstr* instr) {
787void ConstantPropagator::VisitRecordCoverage(RecordCoverageInstr* instr) {
791void ConstantPropagator::VisitOneByteStringFromCharCode(
792 OneByteStringFromCharCodeInstr* instr) {
793 const Object& o = instr->char_code()->definition()->constant_value();
798 const intptr_t ch_code = Smi::Cast(o).Value();
806 SetValue(instr, non_constant_);
809void ConstantPropagator::VisitStringToCharCode(StringToCharCodeInstr* instr) {
810 const Object& o = instr->str()->definition()->constant_value();
815 const String& str = String::Cast(o);
817 (str.Length() == 1) ?
static_cast<intptr_t
>(str.CharAt(0)) : -1;
820 SetValue(instr, non_constant_);
824void ConstantPropagator::VisitUtf8Scan(Utf8ScanInstr* instr) {
825 SetValue(instr, non_constant_);
828void ConstantPropagator::VisitLoadIndexed(LoadIndexedInstr* instr) {
829 const Object& array_obj = instr->array()->definition()->constant_value();
830 const Object& index_obj = instr->index()->definition()->constant_value();
831 if (IsNonConstant(array_obj) || IsNonConstant(index_obj)) {
832 SetValue(instr, non_constant_);
833 }
else if (IsConstant(array_obj) && IsConstant(index_obj)) {
835 if (!index_obj.IsSmi()) {
837 SetValue(instr, non_constant_);
840 const intptr_t index = Smi::Cast(index_obj).Value();
842 if (array_obj.IsString()) {
843 const String& str = String::Cast(array_obj);
844 if (str.Length() > index) {
847 Z,
Smi::New(
static_cast<intptr_t
>(str.CharAt(index)))));
850 }
else if (array_obj.IsArray()) {
851 const Array&
a = Array::Cast(array_obj);
852 if ((
a.Length() > index) &&
a.IsImmutable()) {
860 SetValue(instr, non_constant_);
864void ConstantPropagator::VisitLoadCodeUnits(LoadCodeUnitsInstr* instr) {
866 SetValue(instr, non_constant_);
869void ConstantPropagator::VisitLoadIndexedUnsafe(LoadIndexedUnsafeInstr* instr) {
870 SetValue(instr, non_constant_);
873void ConstantPropagator::VisitLoadStaticField(LoadStaticFieldInstr* instr) {
877 SetValue(instr, non_constant_);
880void ConstantPropagator::VisitStoreStaticField(StoreStaticFieldInstr* instr) {
881 SetValue(instr, instr->value()->definition()->constant_value());
884void ConstantPropagator::VisitBooleanNegate(BooleanNegateInstr* instr) {
885 const Object&
value = instr->value()->definition()->constant_value();
886 if (IsUnknown(
value)) {
889 if (
value.IsBool()) {
893 SetValue(instr, non_constant_);
897void ConstantPropagator::VisitBoolToInt(BoolToIntInstr* instr) {
899 SetValue(instr, non_constant_);
902void ConstantPropagator::VisitIntToBool(IntToBoolInstr* instr) {
904 SetValue(instr, non_constant_);
907void ConstantPropagator::VisitInstanceOf(InstanceOfInstr* instr) {
908 Definition* def = instr->value()->definition();
909 const Object&
value = def->constant_value();
910 const AbstractType& checked_type = instr->type();
912 if (checked_type.IsTopTypeForInstanceOf()) {
914 }
else if (IsNonConstant(
value)) {
915 intptr_t value_cid = instr->value()->definition()->Type()->ToCid();
917 if ((checked_type.IsFloat32x4Type() && (rep == kUnboxedFloat32x4)) ||
918 (checked_type.IsInt32x4Type() && (rep == kUnboxedInt32x4)) ||
919 (checked_type.IsDoubleType() && (rep == kUnboxedDouble)) ||
920 (checked_type.IsIntType() && (rep == kUnboxedInt64))) {
922 ASSERT(((rep == kUnboxedFloat32x4) && (value_cid == kFloat32x4Cid)) ||
923 ((rep == kUnboxedInt32x4) && (value_cid == kInt32x4Cid)) ||
924 ((rep == kUnboxedDouble) && (value_cid == kDoubleCid)) ||
925 ((rep == kUnboxedInt64) && (value_cid == kMintCid)));
929 SetValue(instr, non_constant_);
931 }
else if (IsConstant(
value)) {
932 if (
value.IsInstance() && (
value.ptr() != Object::sentinel().ptr())) {
934 if (instr->instantiator_type_arguments()->BindsToConstantNull() &&
935 instr->function_type_arguments()->BindsToConstantNull()) {
937 instance.IsInstanceOf(checked_type, Object::null_type_arguments(),
938 Object::null_type_arguments());
943 SetValue(instr, non_constant_);
947void ConstantPropagator::VisitCreateArray(CreateArrayInstr* instr) {
948 SetValue(instr, non_constant_);
951void ConstantPropagator::VisitAllocateTypedData(AllocateTypedDataInstr* instr) {
952 SetValue(instr, non_constant_);
955void ConstantPropagator::VisitAllocateObject(AllocateObjectInstr* instr) {
956 SetValue(instr, non_constant_);
959void ConstantPropagator::VisitAllocateClosure(AllocateClosureInstr* instr) {
960 SetValue(instr, non_constant_);
963void ConstantPropagator::VisitAllocateRecord(AllocateRecordInstr* instr) {
964 SetValue(instr, non_constant_);
967void ConstantPropagator::VisitAllocateSmallRecord(
968 AllocateSmallRecordInstr* instr) {
969 SetValue(instr, non_constant_);
972void ConstantPropagator::VisitLoadUntagged(LoadUntaggedInstr* instr) {
973 SetValue(instr, non_constant_);
976void ConstantPropagator::VisitCalculateElementAddress(
977 CalculateElementAddressInstr* instr) {
978 SetValue(instr, non_constant_);
981void ConstantPropagator::VisitLoadClassId(LoadClassIdInstr* instr) {
991 intptr_t
cid = instr->object()->Type()->ToCid();
996 const Object&
object = instr->object()->definition()->constant_value();
997 if (IsConstant(
object)) {
998 cid =
object.GetClassId();
1002 SetValue(instr, non_constant_);
1005void ConstantPropagator::VisitLoadField(LoadFieldInstr* instr) {
1007 if ((instr->slot().kind() == Slot::Kind::kArray_length) &&
1008 instance->definition()->OriginalDefinition()->IsCreateArray()) {
1010 ->OriginalDefinition()
1013 if (num_elements->BindsToConstant() &&
1014 num_elements->BoundConstant().IsSmi()) {
1015 intptr_t
length = Smi::Cast(num_elements->BoundConstant()).Value();
1022 const Object& constant =
instance->definition()->constant_value();
1023 if (IsConstant(constant)) {
1024 if (instr->IsImmutableLengthLoad()) {
1025 if (constant.IsString()) {
1030 if (constant.IsArray()) {
1035 if (constant.IsTypedData()) {
1037 Z,
Smi::New(TypedData::Cast(constant).Length())));
1042 if (instr->Evaluate(constant, &
value)) {
1049 SetValue(instr, non_constant_);
1052void ConstantPropagator::VisitInstantiateType(InstantiateTypeInstr* instr) {
1057 const Object& instantiator_type_args_obj =
1058 instr->instantiator_type_arguments()->definition()->constant_value();
1059 if (IsUnknown(instantiator_type_args_obj)) {
1062 if (instantiator_type_args_obj.IsTypeArguments()) {
1063 instantiator_type_args ^= instantiator_type_args_obj.ptr();
1065 SetValue(instr, non_constant_);
1069 if (!instr->type().IsInstantiated(
kFunctions)) {
1071 const Object& function_type_args_obj =
1072 instr->function_type_arguments()->definition()->constant_value();
1073 if (IsUnknown(function_type_args_obj)) {
1076 if (function_type_args_obj.IsTypeArguments()) {
1077 function_type_args ^= function_type_args_obj.ptr();
1079 SetValue(instr, non_constant_);
1084 Z, instr->type().InstantiateFrom(
1091void ConstantPropagator::VisitInstantiateTypeArguments(
1092 InstantiateTypeArgumentsInstr* instr) {
1093 const auto& type_arguments_obj =
1094 instr->type_arguments()->definition()->constant_value();
1095 if (IsUnknown(type_arguments_obj)) {
1098 if (type_arguments_obj.IsNull()) {
1099 SetValue(instr, type_arguments_obj);
1102 if (!type_arguments_obj.IsTypeArguments()) {
1103 SetValue(instr, non_constant_);
1106 const auto& type_arguments = TypeArguments::Cast(type_arguments_obj);
1107 if (type_arguments.IsInstantiated()) {
1108 ASSERT(type_arguments.IsCanonical());
1109 SetValue(instr, type_arguments);
1115 const Object& instantiator_type_args_obj =
1116 instr->instantiator_type_arguments()->definition()->constant_value();
1117 if (IsUnknown(instantiator_type_args_obj)) {
1120 if (!instantiator_type_args_obj.IsNull() &&
1121 !instantiator_type_args_obj.IsTypeArguments()) {
1122 SetValue(instr, non_constant_);
1125 instantiator_type_args ^= instantiator_type_args_obj.ptr();
1126 if (instr->CanShareInstantiatorTypeArguments()) {
1127 SetValue(instr, instantiator_type_args);
1132 if (!type_arguments.IsInstantiated(
kFunctions)) {
1134 const Object& function_type_args_obj =
1135 instr->function_type_arguments()->definition()->constant_value();
1136 if (IsUnknown(function_type_args_obj)) {
1139 if (!function_type_args_obj.IsNull() &&
1140 !function_type_args_obj.IsTypeArguments()) {
1141 SetValue(instr, non_constant_);
1144 function_type_args ^= function_type_args_obj.ptr();
1145 if (instr->CanShareFunctionTypeArguments()) {
1146 SetValue(instr, function_type_args);
1151 Z, type_arguments.InstantiateFrom(
1158void ConstantPropagator::VisitAllocateContext(AllocateContextInstr* instr) {
1159 SetValue(instr, non_constant_);
1162void ConstantPropagator::VisitAllocateUninitializedContext(
1163 AllocateUninitializedContextInstr* instr) {
1164 SetValue(instr, non_constant_);
1167void ConstantPropagator::VisitCloneContext(CloneContextInstr* instr) {
1168 SetValue(instr, non_constant_);
1171void ConstantPropagator::VisitBinaryIntegerOp(BinaryIntegerOpInstr* binary_op) {
1172 const Object&
left = binary_op->left()->definition()->constant_value();
1173 const Object&
right = binary_op->right()->definition()->constant_value();
1174 if (IsNonConstant(left) || IsNonConstant(right)) {
1175 SetValue(binary_op, non_constant_);
1177 }
else if (IsUnknown(left) || IsUnknown(right)) {
1180 ASSERT(IsConstant(left) && IsConstant(right));
1181 if (
left.IsInteger() &&
right.IsInteger()) {
1184 binary_op->is_truncating(),
1185 binary_op->representation(),
T));
1191 SetValue(binary_op, non_constant_);
1194void ConstantPropagator::VisitBinarySmiOp(BinarySmiOpInstr* instr) {
1195 VisitBinaryIntegerOp(instr);
1198void ConstantPropagator::VisitBinaryInt32Op(BinaryInt32OpInstr* instr) {
1199 VisitBinaryIntegerOp(instr);
1202void ConstantPropagator::VisitBinaryUint32Op(BinaryUint32OpInstr* instr) {
1203 VisitBinaryIntegerOp(instr);
1206void ConstantPropagator::VisitBinaryInt64Op(BinaryInt64OpInstr* instr) {
1207 VisitBinaryIntegerOp(instr);
1210void ConstantPropagator::VisitShiftInt64Op(ShiftInt64OpInstr* instr) {
1211 VisitBinaryIntegerOp(instr);
1214void ConstantPropagator::VisitSpeculativeShiftInt64Op(
1215 SpeculativeShiftInt64OpInstr* instr) {
1216 VisitBinaryIntegerOp(instr);
1219void ConstantPropagator::VisitShiftUint32Op(ShiftUint32OpInstr* instr) {
1220 VisitBinaryIntegerOp(instr);
1223void ConstantPropagator::VisitSpeculativeShiftUint32Op(
1224 SpeculativeShiftUint32OpInstr* instr) {
1225 VisitBinaryIntegerOp(instr);
1228void ConstantPropagator::VisitBoxInt64(BoxInt64Instr* instr) {
1232void ConstantPropagator::VisitUnboxInt64(UnboxInt64Instr* instr) {
1236void ConstantPropagator::VisitHashDoubleOp(HashDoubleOpInstr* instr) {
1237 const Object&
value = instr->value()->definition()->constant_value();
1238 if (IsUnknown(
value)) {
1241 if (
value.IsDouble()) {
1244 SetValue(instr, non_constant_);
1247void ConstantPropagator::VisitHashIntegerOp(HashIntegerOpInstr* instr) {
1248 const Object&
value = instr->value()->definition()->constant_value();
1249 if (IsUnknown(
value)) {
1252 if (
value.IsInteger()) {
1255 SetValue(instr, non_constant_);
1258void ConstantPropagator::VisitUnaryIntegerOp(UnaryIntegerOpInstr* unary_op) {
1259 const Object&
value = unary_op->value()->definition()->constant_value();
1260 if (IsUnknown(
value)) {
1263 if (
value.IsInteger()) {
1266 unary_op->representation(),
T));
1272 SetValue(unary_op, non_constant_);
1275void ConstantPropagator::VisitUnaryInt64Op(UnaryInt64OpInstr* instr) {
1276 VisitUnaryIntegerOp(instr);
1279void ConstantPropagator::VisitUnarySmiOp(UnarySmiOpInstr* instr) {
1280 VisitUnaryIntegerOp(instr);
1284 return value.IsInteger() ||
value.IsDouble();
1288 return value.IsInteger() ? Integer::Cast(
value).AsDoubleValue()
1289 : Double::Cast(
value).value();
1292void ConstantPropagator::VisitUnaryDoubleOp(UnaryDoubleOpInstr* instr) {
1293 const Object&
value = instr->value()->definition()->constant_value();
1294 if (IsUnknown(
value)) {
1297 if (
value.IsDouble()) {
1299 ToDouble(
value), instr->op_kind(), instr->representation());
1304 SetValue(instr, non_constant_);
1307void ConstantPropagator::VisitSmiToDouble(SmiToDoubleInstr* instr) {
1308 const Object&
value = instr->value()->definition()->constant_value();
1309 if (IsUnknown(
value)) {
1312 if (
value.IsInteger()) {
1317 SetValue(instr, non_constant_);
1321void ConstantPropagator::VisitInt64ToDouble(Int64ToDoubleInstr* instr) {
1322 const Object&
value = instr->value()->definition()->constant_value();
1323 if (IsUnknown(
value)) {
1326 if (
value.IsInteger()) {
1331 SetValue(instr, non_constant_);
1335void ConstantPropagator::VisitInt32ToDouble(Int32ToDoubleInstr* instr) {
1336 const Object&
value = instr->value()->definition()->constant_value();
1337 if (IsUnknown(
value)) {
1340 if (
value.IsInteger()) {
1345 SetValue(instr, non_constant_);
1349void ConstantPropagator::VisitDoubleToInteger(DoubleToIntegerInstr* instr) {
1351 SetValue(instr, non_constant_);
1354void ConstantPropagator::VisitDoubleToSmi(DoubleToSmiInstr* instr) {
1356 SetValue(instr, non_constant_);
1359void ConstantPropagator::VisitDoubleToFloat(DoubleToFloatInstr* instr) {
1361 SetValue(instr, non_constant_);
1364void ConstantPropagator::VisitFloatToDouble(FloatToDoubleInstr* instr) {
1366 SetValue(instr, non_constant_);
1369void ConstantPropagator::VisitFloatCompare(FloatCompareInstr* instr) {
1371 SetValue(instr, non_constant_);
1374void ConstantPropagator::VisitInvokeMathCFunction(
1375 InvokeMathCFunctionInstr* instr) {
1377 SetValue(instr, non_constant_);
1380void ConstantPropagator::VisitTruncDivMod(TruncDivModInstr* instr) {
1382 SetValue(instr, non_constant_);
1385void ConstantPropagator::VisitExtractNthOutput(ExtractNthOutputInstr* instr) {
1386 SetValue(instr, non_constant_);
1389void ConstantPropagator::VisitMakePair(MakePairInstr* instr) {
1390 SetValue(instr, non_constant_);
1393void ConstantPropagator::VisitUnboxLane(UnboxLaneInstr* instr) {
1394 if (BoxLanesInstr* box = instr->value()->definition()->AsBoxLanes()) {
1395 const Object&
value =
1396 box->InputAt(instr->lane())->definition()->constant_value();
1397 if (IsUnknown(
value)) {
1400 SetValue(instr,
value);
1404 SetValue(instr, non_constant_);
1407void ConstantPropagator::VisitBoxLanes(BoxLanesInstr* instr) {
1409 SetValue(instr, non_constant_);
1412void ConstantPropagator::VisitConstant(ConstantInstr* instr) {
1413 SetValue(instr, instr->value());
1416void ConstantPropagator::VisitUnboxedConstant(UnboxedConstantInstr* instr) {
1417 SetValue(instr, instr->value());
1420void ConstantPropagator::VisitConstraint(ConstraintInstr* instr) {
1425void ConstantPropagator::VisitMaterializeObject(MaterializeObjectInstr* instr) {
1430void ConstantPropagator::VisitBinaryDoubleOp(BinaryDoubleOpInstr* instr) {
1431 const Object&
left = instr->left()->definition()->constant_value();
1432 const Object&
right = instr->right()->definition()->constant_value();
1433 if (IsNonConstant(left) || IsNonConstant(right)) {
1434 SetValue(instr, non_constant_);
1436 }
else if (IsUnknown(left) || IsUnknown(right)) {
1439 ASSERT(IsConstant(left) && IsConstant(right));
1440 const bool both_are_integers =
left.IsInteger() &&
right.IsInteger();
1442 !both_are_integers) {
1445 instr->representation());
1450 SetValue(instr, non_constant_);
1453void ConstantPropagator::VisitDoubleTestOp(DoubleTestOpInstr* instr) {
1454 const Object&
value = instr->value()->definition()->constant_value();
1455 if (IsUnknown(
value)) {
1459 if (
value.IsInteger()) {
1460 switch (instr->op_kind()) {
1461 case MethodRecognizer::kDouble_getIsNaN:
1463 case MethodRecognizer::kDouble_getIsInfinite:
1466 case MethodRecognizer::kDouble_getIsNegative: {
1473 }
else if (
value.IsDouble()) {
1475 switch (instr->op_kind()) {
1476 case MethodRecognizer::kDouble_getIsNaN: {
1477 result = isnan(double_value);
1480 case MethodRecognizer::kDouble_getIsInfinite: {
1481 result = isinf(double_value);
1484 case MethodRecognizer::kDouble_getIsNegative: {
1485 result = signbit(double_value) && !isnan(double_value);
1492 SetValue(instr, non_constant_);
1495 const bool is_negated = instr->kind() != Token::kEQ;
1499void ConstantPropagator::VisitSimdOp(SimdOpInstr* instr) {
1500 SetValue(instr, non_constant_);
1503void ConstantPropagator::VisitMathMinMax(MathMinMaxInstr* instr) {
1505 SetValue(instr, non_constant_);
1508void ConstantPropagator::VisitCaseInsensitiveCompare(
1509 CaseInsensitiveCompareInstr* instr) {
1510 SetValue(instr, non_constant_);
1513void ConstantPropagator::VisitUnbox(UnboxInstr* instr) {
1514 const Object&
value = instr->value()->definition()->constant_value();
1515 if (IsUnknown(
value)) {
1519 SetValue(instr,
value);
1522void ConstantPropagator::VisitBox(BoxInstr* instr) {
1523 const Object&
value = instr->value()->definition()->constant_value();
1524 if (IsUnknown(
value)) {
1528 if (instr->value()->definition()->representation() ==
1529 instr->from_representation()) {
1530 SetValue(instr,
value);
1532 SetValue(instr, non_constant_);
1536void ConstantPropagator::VisitBoxSmallInt(BoxSmallIntInstr* instr) {
1540void ConstantPropagator::VisitBoxUint32(BoxUint32Instr* instr) {
1544void ConstantPropagator::VisitUnboxUint32(UnboxUint32Instr* instr) {
1548void ConstantPropagator::VisitBoxInt32(BoxInt32Instr* instr) {
1552void ConstantPropagator::VisitUnboxInt32(UnboxInt32Instr* instr) {
1556void ConstantPropagator::VisitIntConverter(IntConverterInstr* instr) {
1557 SetValue(instr, non_constant_);
1560void ConstantPropagator::VisitBitCast(BitCastInstr* instr) {
1561 SetValue(instr, non_constant_);
1564void ConstantPropagator::VisitCall1ArgStub(Call1ArgStubInstr* instr) {
1565 SetValue(instr, non_constant_);
1568void ConstantPropagator::VisitSuspend(SuspendInstr* instr) {
1569 SetValue(instr, non_constant_);
1572void ConstantPropagator::VisitLoadThread(LoadThreadInstr* instr) {
1573 SetValue(instr, non_constant_);
1576void ConstantPropagator::VisitUnaryUint32Op(UnaryUint32OpInstr* instr) {
1578 SetValue(instr, non_constant_);
1586 const Object& constant_value) {
1593 if (redef->input_use_list() ==
nullptr) {
1595 redef->RemoveFromGraph();
1599 redef->constant_value() = constant_value.
ptr();
1613void ConstantPropagator::InsertRedefinitionsAfterEqualityComparisons() {
1615 if (
auto branch = block->last_instruction()->AsBranch()) {
1616 auto comparison = branch->comparison();
1617 if (comparison->IsStrictCompare() ||
1618 (comparison->IsEqualityCompare() &&
1619 comparison->operation_cid() != kDoubleCid)) {
1621 ConstantInstr* constant_defn;
1622 if (comparison->IsComparisonWithConstant(&
value, &constant_defn) &&
1623 !
value->BindsToConstant()) {
1624 const Object& constant_value = constant_defn->value();
1627 ASSERT(comparison->kind() == Token::kNE_STRICT ||
1628 comparison->kind() == Token::kNE ||
1629 comparison->kind() == Token::kEQ_STRICT ||
1630 comparison->kind() == Token::kEQ);
1631 const bool negated = (comparison->kind() == Token::kNE_STRICT ||
1632 comparison->kind() == Token::kNE);
1633 const auto true_successor =
1634 negated ? branch->false_successor() : branch->true_successor();
1641 if (constant_value.IsBool() &&
value->Type()->IsBool()) {
1642 const auto false_successor =
1643 negated ? branch->true_successor() : branch->false_successor();
1645 Bool::Get(!Bool::Cast(constant_value).value()));
1653void ConstantPropagator::Analyze() {
1654 InsertRedefinitionsAfterEqualityComparisons();
1657 reachable_->
Add(entry->preorder_number());
1658 block_worklist_.Add(entry);
1661 if (block_worklist_.is_empty()) {
1662 if (definition_worklist_.
IsEmpty())
break;
1663 Definition* definition = definition_worklist_.
RemoveLast();
1664 for (
Value* use = definition->input_use_list(); use !=
nullptr;
1665 use = use->next_use()) {
1666 use->instruction()->
Accept(
this);
1669 BlockEntryInstr* block = block_worklist_.RemoveLast();
1670 block->Accept(
this);
1676 if (
auto*
join = block->AsJoinEntry()) {
1677 return (
join->phis() !=
nullptr) && !
join->phis()->is_empty();
1686 return block->
next()->IsGoto() &&
1687 block->
next()->AsGoto()->successor() != block && !
HasPhis(block) &&
1688 !block->IsIndirectEntry();
1700 current = current->
next()->AsGoto()->successor();
1705void ConstantPropagator::EliminateRedundantBranches() {
1708 bool changed =
false;
1709 BitVector* empty_blocks =
new (
Z) BitVector(
Z, graph_->
preorder().length());
1711 BlockEntryInstr* block =
b.Current();
1712 BranchInstr* branch = block->last_instruction()->AsBranch();
1713 empty_blocks->Clear();
1714 if ((branch !=
nullptr) && !branch->HasUnknownSideEffects()) {
1715 ASSERT(branch->previous() !=
nullptr);
1716 BlockEntryInstr* if_true =
1718 BlockEntryInstr* if_false =
1720 if (if_true == if_false) {
1723 JoinEntryInstr*
join = if_true->AsJoinEntry();
1728 Instruction* previous = branch->previous();
1729 branch->set_previous(
nullptr);
1730 previous->LinkTo(jump);
1734 branch->UnuseAllInputs();
1735 for (BitVector::Iterator it(empty_blocks); !it.Done(); it.Advance()) {
1736 BlockEntryInstr* empty_block = graph_->
preorder()[it.Current()];
1737 empty_block->ClearAllInstructions();
1742 if (FLAG_trace_constant_propagation && graph_->
should_print()) {
1743 THR_Print(
"Eliminated branch in B%" Pd " common target B%" Pd "\n",
1744 block->block_id(),
join->block_id());
1755 GrowableArray<BitVector*> dominance_frontier;
1760void ConstantPropagator::Transform() {
1767 BlockEntryInstr* block =
b.Current();
1768 if (!reachable_->
Contains(block->preorder_number())) {
1769 if (FLAG_trace_constant_propagation && graph_->
should_print()) {
1770 THR_Print(
"Unreachable B%" Pd "\n", block->block_id());
1773 block->ClearAllInstructions();
1777 JoinEntryInstr*
join = block->AsJoinEntry();
1778 if (
join !=
nullptr) {
1782 ZoneGrowableArray<PhiInstr*>* phis =
join->phis();
1783 if ((phis !=
nullptr) && !phis->is_empty()) {
1784 intptr_t pred_count =
join->PredecessorCount();
1785 intptr_t live_count = 0;
1786 for (intptr_t pred_idx = 0; pred_idx < pred_count; ++pred_idx) {
1788 join->PredecessorAt(pred_idx)->preorder_number())) {
1789 if (live_count < pred_idx) {
1790 for (PhiIterator it(
join); !it.Done(); it.Advance()) {
1791 PhiInstr* phi = it.Current();
1793 phi->SetInputAt(live_count, phi->InputAt(pred_idx));
1798 for (PhiIterator it(
join); !it.Done(); it.Advance()) {
1799 PhiInstr* phi = it.Current();
1801 phi->InputAt(pred_idx)->RemoveFromUseList();
1805 if (live_count < pred_count) {
1806 intptr_t to_idx = 0;
1807 for (intptr_t from_idx = 0; from_idx < phis->length(); ++from_idx) {
1808 PhiInstr* phi = (*phis)[from_idx];
1810 if (FLAG_remove_redundant_phis && (live_count == 1)) {
1811 Value* input = phi->InputAt(0);
1812 phi->ReplaceUsesWith(input->definition());
1813 input->RemoveFromUseList();
1815 phi->inputs_.TruncateTo(live_count);
1816 (*phis)[to_idx++] = phi;
1820 join->phis_ =
nullptr;
1822 phis->TruncateTo(to_idx);
1828 if (
join !=
nullptr) {
1829 for (PhiIterator it(
join); !it.Done(); it.Advance()) {
1830 auto phi = it.Current();
1831 if (TransformDefinition(phi)) {
1832 it.RemoveCurrentFromGraph();
1836 for (ForwardInstructionIterator
i(block); !
i.Done();
i.Advance()) {
1837 Definition* defn =
i.Current()->AsDefinition();
1838 if (TransformDefinition(defn)) {
1839 i.RemoveCurrentFromGraph();
1844 BranchInstr* branch = block->last_instruction()->AsBranch();
1845 if (branch !=
nullptr) {
1846 TargetEntryInstr* if_true = branch->true_successor();
1847 TargetEntryInstr* if_false = branch->false_successor();
1848 JoinEntryInstr*
join =
nullptr;
1849 Instruction*
next =
nullptr;
1851 if (!reachable_->
Contains(if_true->preorder_number())) {
1853 ASSERT(if_false->parallel_move() ==
nullptr);
1854 join =
new (
Z) JoinEntryInstr(if_false->block_id(),
1857 if_false->UnuseAllInputs();
1858 next = if_false->next();
1859 }
else if (!reachable_->
Contains(if_false->preorder_number())) {
1860 ASSERT(if_true->parallel_move() ==
nullptr);
1861 join =
new (
Z) JoinEntryInstr(if_true->block_id(), if_true->try_index(),
1864 if_true->UnuseAllInputs();
1865 next = if_true->next();
1868 if (
join !=
nullptr) {
1876 Instruction* previous = branch->previous();
1877 branch->set_previous(
nullptr);
1878 previous->LinkTo(jump);
1883 branch->UnuseAllInputs();
1890 GrowableArray<BitVector*> dominance_frontier;
1894bool ConstantPropagator::TransformDefinition(Definition* defn) {
1895 if (defn ==
nullptr) {
1899 if (
auto redef = defn->AsRedefinition()) {
1900 if (redef->inserted_by_constant_propagation()) {
1901 redef->ReplaceUsesWith(redef->value()->definition());
1905 if (IsConstant(defn->constant_value()) &&
1906 !IsConstant(defn->OriginalDefinition()->constant_value())) {
1917 if (IsConstant(defn->constant_value()) &&
1918 (defn->constant_value().IsSmi() || defn->constant_value().IsOld()) &&
1919 !defn->IsConstant() && !defn->IsStoreIndexed() && !defn->IsStoreField() &&
1920 !defn->IsStoreStaticField()) {
1921 if (FLAG_trace_constant_propagation && graph_->
should_print()) {
1922 THR_Print(
"Constant v%" Pd " = %s\n", defn->ssa_temp_index(),
1923 defn->constant_value().ToCString());
1925 constant_value_ = defn->constant_value().
ptr();
1926 if ((constant_value_.IsString() || constant_value_.IsMint() ||
1927 constant_value_.IsDouble()) &&
1929 constant_value_ = Instance::Cast(constant_value_).Canonicalize(
T);
1932 if (
auto call = defn->AsStaticCall()) {
1935 Definition* replacement =
1937 if (replacement != defn) {
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
static float next(float f)
bool Contains(intptr_t i) const
intptr_t preorder_number() const
bool Dominates(BlockEntryInstr *other) const
static const Bool & False()
static const Bool & Get(bool value)
static const Bool & True()
static void Optimize(FlowGraph *graph)
static ObjectPtr Unknown()
ConstantPropagator(FlowGraph *graph, const GrowableArray< BlockEntryInstr * > &ignored)
static void OptimizeBranches(FlowGraph *graph)
void Add(Definition *defn)
Definition * RemoveLast()
void ReplaceUsesWith(Definition *other)
static constexpr intptr_t kNone
static DoublePtr New(double d, Heap::Space space=Heap::kNew)
static DoublePtr NewCanonical(double d)
static double EvaluateUnaryDoubleOp(const double value, Token::Kind token_kind, Representation representation)
static IntegerPtr UnaryIntegerEvaluate(const Object &value, Token::Kind token_kind, Representation representation, Thread *thread)
static IntegerPtr BinaryIntegerEvaluate(const Object &left, const Object &right, Token::Kind token_kind, bool is_truncating, Representation representation, Thread *thread)
static double EvaluateBinaryDoubleOp(const double left, const double right, Token::Kind token_kind, Representation representation)
static void PrintGraph(const char *phase, FlowGraph *flow_graph)
const GrowableArray< BlockEntryInstr * > & reverse_postorder() const
GraphEntryInstr * graph_entry() const
bool should_print() const
const GrowableArray< BlockEntryInstr * > & preorder() const
BlockIterator postorder_iterator() const
void ComputeDominators(GrowableArray< BitVector * > *dominance_frontier)
const ParsedFunction & parsed_function() const
Definition * TryCreateConstantReplacementFor(Definition *op, const Object &value)
void CopyDeoptTarget(Instruction *to, Instruction *from)
BlockIterator reverse_postorder_iterator() const
static void RenameDominatedUses(Definition *def, Instruction *dom, Definition *other)
void InsertAfter(Instruction *prev, Instruction *instr, Environment *env, UseKind use_kind)
virtual void Accept(InstructionVisitor *visitor)=0
Instruction * next() const
static void static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
virtual const char * ToCString() const
static Object & ZoneHandle()
const Function & function() const
static SmiPtr New(intptr_t value)
static StringPtr * PredefinedAddress()
#define THR_Print(format,...)
static bool IsIdenticalConstants(const Object &left, const Object &right)
static double ToDouble(const Object &value)
static bool CompareIntegers(Token::Kind kind, const Integer &left, const Integer &right)
static RedefinitionInstr * InsertRedefinition(FlowGraph *graph, BlockEntryInstr *dom, Definition *original, const Object &constant_value)
static bool HasPhis(BlockEntryInstr *block)
static BlockEntryInstr * FindFirstNonEmptySuccessor(TargetEntryInstr *block, BitVector *empty_blocks)
DEFINE_FLAG(bool, print_cluster_information, false, "Print information about clusters written to snapshot")
static bool IsEmptyBlock(BlockEntryInstr *block)
bool IsIntegerClassId(intptr_t index)
static bool IsIntegerOrDouble(const Object &value)
NOT_IN_PRODUCT(LibraryPtr ReloadTestScript(const char *script))
static SkString join(const CommandLineFlags::StringArray &)