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(
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)) {
453 ASSERT(IsConstant(value) && IsConstant(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()) {
579 bool result = Bool::Cast(value).value();
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) {
673void ConstantPropagator::VisitTestSmi(TestSmiInstr* 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)) {
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()) {
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) &&
921 (checked_type.IsIntType() && (rep == kUnboxedInt64))) {
923 ASSERT(((rep == kUnboxedFloat32x4) && (value_cid == kFloat32x4Cid)) ||
924 ((rep == kUnboxedInt32x4) && (value_cid == kInt32x4Cid)) ||
925 ((rep == kUnboxedDouble) && (value_cid == kDoubleCid)) ||
926 ((rep == kUnboxedInt64) && (value_cid == kMintCid)));
930 SetValue(instr, non_constant_);
932 }
else if (IsConstant(value)) {
933 if (
value.IsInstance() && (
value.ptr() != Object::sentinel().ptr())) {
934 const Instance&
instance = Instance::Cast(value);
935 if (instr->instantiator_type_arguments()->BindsToConstantNull() &&
936 instr->function_type_arguments()->BindsToConstantNull()) {
938 instance.IsInstanceOf(checked_type, Object::null_type_arguments(),
939 Object::null_type_arguments());
944 SetValue(instr, non_constant_);
948void ConstantPropagator::VisitCreateArray(CreateArrayInstr* instr) {
949 SetValue(instr, non_constant_);
952void ConstantPropagator::VisitAllocateTypedData(AllocateTypedDataInstr* instr) {
953 SetValue(instr, non_constant_);
956void ConstantPropagator::VisitAllocateObject(AllocateObjectInstr* instr) {
957 SetValue(instr, non_constant_);
960void ConstantPropagator::VisitAllocateClosure(AllocateClosureInstr* instr) {
961 SetValue(instr, non_constant_);
964void ConstantPropagator::VisitAllocateRecord(AllocateRecordInstr* instr) {
965 SetValue(instr, non_constant_);
968void ConstantPropagator::VisitAllocateSmallRecord(
969 AllocateSmallRecordInstr* instr) {
970 SetValue(instr, non_constant_);
973void ConstantPropagator::VisitLoadUntagged(LoadUntaggedInstr* instr) {
974 SetValue(instr, non_constant_);
977void ConstantPropagator::VisitCalculateElementAddress(
978 CalculateElementAddressInstr* instr) {
979 SetValue(instr, non_constant_);
982void ConstantPropagator::VisitLoadClassId(LoadClassIdInstr* instr) {
992 intptr_t
cid = instr->object()->Type()->ToCid();
997 const Object&
object = instr->object()->definition()->constant_value();
998 if (IsConstant(
object)) {
999 cid =
object.GetClassId();
1003 SetValue(instr, non_constant_);
1006void ConstantPropagator::VisitLoadField(LoadFieldInstr* instr) {
1008 if ((instr->slot().kind() == Slot::Kind::kArray_length) &&
1009 instance->definition()->OriginalDefinition()->IsCreateArray()) {
1011 ->OriginalDefinition()
1014 if (num_elements->BindsToConstant() &&
1015 num_elements->BoundConstant().IsSmi()) {
1016 intptr_t
length = Smi::Cast(num_elements->BoundConstant()).
Value();
1023 const Object& constant =
instance->definition()->constant_value();
1024 if (IsConstant(constant)) {
1025 if (instr->IsImmutableLengthLoad()) {
1026 if (constant.IsString()) {
1031 if (constant.IsArray()) {
1036 if (constant.IsTypedData()) {
1038 Z,
Smi::New(TypedData::Cast(constant).Length())));
1043 if (instr->Evaluate(constant, &value)) {
1050 SetValue(instr, non_constant_);
1053void ConstantPropagator::VisitInstantiateType(InstantiateTypeInstr* instr) {
1058 const Object& instantiator_type_args_obj =
1059 instr->instantiator_type_arguments()->definition()->constant_value();
1060 if (IsUnknown(instantiator_type_args_obj)) {
1063 if (instantiator_type_args_obj.IsTypeArguments()) {
1064 instantiator_type_args ^= instantiator_type_args_obj.ptr();
1066 SetValue(instr, non_constant_);
1070 if (!instr->type().IsInstantiated(
kFunctions)) {
1072 const Object& function_type_args_obj =
1073 instr->function_type_arguments()->definition()->constant_value();
1074 if (IsUnknown(function_type_args_obj)) {
1077 if (function_type_args_obj.IsTypeArguments()) {
1078 function_type_args ^= function_type_args_obj.ptr();
1080 SetValue(instr, non_constant_);
1085 Z, instr->type().InstantiateFrom(
1092void ConstantPropagator::VisitInstantiateTypeArguments(
1093 InstantiateTypeArgumentsInstr* instr) {
1094 const auto& type_arguments_obj =
1095 instr->type_arguments()->definition()->constant_value();
1096 if (IsUnknown(type_arguments_obj)) {
1099 if (type_arguments_obj.IsNull()) {
1100 SetValue(instr, type_arguments_obj);
1103 if (!type_arguments_obj.IsTypeArguments()) {
1104 SetValue(instr, non_constant_);
1107 const auto& type_arguments = TypeArguments::Cast(type_arguments_obj);
1108 if (type_arguments.IsInstantiated()) {
1109 ASSERT(type_arguments.IsCanonical());
1110 SetValue(instr, type_arguments);
1116 const Object& instantiator_type_args_obj =
1117 instr->instantiator_type_arguments()->definition()->constant_value();
1118 if (IsUnknown(instantiator_type_args_obj)) {
1121 if (!instantiator_type_args_obj.IsNull() &&
1122 !instantiator_type_args_obj.IsTypeArguments()) {
1123 SetValue(instr, non_constant_);
1126 instantiator_type_args ^= instantiator_type_args_obj.ptr();
1127 if (instr->CanShareInstantiatorTypeArguments()) {
1128 SetValue(instr, instantiator_type_args);
1133 if (!type_arguments.IsInstantiated(
kFunctions)) {
1135 const Object& function_type_args_obj =
1136 instr->function_type_arguments()->definition()->constant_value();
1137 if (IsUnknown(function_type_args_obj)) {
1140 if (!function_type_args_obj.IsNull() &&
1141 !function_type_args_obj.IsTypeArguments()) {
1142 SetValue(instr, non_constant_);
1145 function_type_args ^= function_type_args_obj.ptr();
1146 if (instr->CanShareFunctionTypeArguments()) {
1147 SetValue(instr, function_type_args);
1152 Z, type_arguments.InstantiateFrom(
1159void ConstantPropagator::VisitAllocateContext(AllocateContextInstr* instr) {
1160 SetValue(instr, non_constant_);
1163void ConstantPropagator::VisitAllocateUninitializedContext(
1164 AllocateUninitializedContextInstr* instr) {
1165 SetValue(instr, non_constant_);
1168void ConstantPropagator::VisitCloneContext(CloneContextInstr* instr) {
1169 SetValue(instr, non_constant_);
1172void ConstantPropagator::VisitBinaryIntegerOp(BinaryIntegerOpInstr* binary_op) {
1173 const Object&
left = binary_op->left()->definition()->constant_value();
1174 const Object&
right = binary_op->right()->definition()->constant_value();
1175 if (IsNonConstant(
left) || IsNonConstant(
right)) {
1176 SetValue(binary_op, non_constant_);
1178 }
else if (IsUnknown(
left) || IsUnknown(
right)) {
1182 if (
left.IsInteger() &&
right.IsInteger()) {
1185 binary_op->is_truncating(),
1186 binary_op->representation(),
T));
1192 SetValue(binary_op, non_constant_);
1195void ConstantPropagator::VisitBinarySmiOp(BinarySmiOpInstr* instr) {
1196 VisitBinaryIntegerOp(instr);
1199void ConstantPropagator::VisitBinaryInt32Op(BinaryInt32OpInstr* instr) {
1200 VisitBinaryIntegerOp(instr);
1203void ConstantPropagator::VisitBinaryUint32Op(BinaryUint32OpInstr* instr) {
1204 VisitBinaryIntegerOp(instr);
1207void ConstantPropagator::VisitBinaryInt64Op(BinaryInt64OpInstr* instr) {
1208 VisitBinaryIntegerOp(instr);
1211void ConstantPropagator::VisitShiftInt64Op(ShiftInt64OpInstr* instr) {
1212 VisitBinaryIntegerOp(instr);
1215void ConstantPropagator::VisitSpeculativeShiftInt64Op(
1216 SpeculativeShiftInt64OpInstr* instr) {
1217 VisitBinaryIntegerOp(instr);
1220void ConstantPropagator::VisitShiftUint32Op(ShiftUint32OpInstr* instr) {
1221 VisitBinaryIntegerOp(instr);
1224void ConstantPropagator::VisitSpeculativeShiftUint32Op(
1225 SpeculativeShiftUint32OpInstr* instr) {
1226 VisitBinaryIntegerOp(instr);
1229void ConstantPropagator::VisitBoxInt64(BoxInt64Instr* instr) {
1233void ConstantPropagator::VisitUnboxInt64(UnboxInt64Instr* instr) {
1237void ConstantPropagator::VisitHashDoubleOp(HashDoubleOpInstr* instr) {
1238 const Object&
value = instr->value()->definition()->constant_value();
1239 if (IsUnknown(value)) {
1242 if (
value.IsDouble()) {
1245 SetValue(instr, non_constant_);
1248void ConstantPropagator::VisitHashIntegerOp(HashIntegerOpInstr* instr) {
1249 const Object&
value = instr->value()->definition()->constant_value();
1250 if (IsUnknown(value)) {
1253 if (
value.IsInteger()) {
1256 SetValue(instr, non_constant_);
1259void ConstantPropagator::VisitUnaryIntegerOp(UnaryIntegerOpInstr* unary_op) {
1260 const Object&
value = unary_op->value()->definition()->constant_value();
1261 if (IsUnknown(value)) {
1264 if (
value.IsInteger()) {
1267 unary_op->representation(),
T));
1273 SetValue(unary_op, non_constant_);
1276void ConstantPropagator::VisitUnaryInt64Op(UnaryInt64OpInstr* instr) {
1277 VisitUnaryIntegerOp(instr);
1280void ConstantPropagator::VisitUnarySmiOp(UnarySmiOpInstr* instr) {
1281 VisitUnaryIntegerOp(instr);
1285 return value.IsInteger() ||
value.IsDouble();
1289 return value.IsInteger() ? Integer::Cast(
value).AsDoubleValue()
1290 : Double::Cast(
value).value();
1293void ConstantPropagator::VisitUnaryDoubleOp(UnaryDoubleOpInstr* instr) {
1294 const Object&
value = instr->value()->definition()->constant_value();
1295 if (IsUnknown(value)) {
1298 if (
value.IsDouble()) {
1300 ToDouble(value), instr->op_kind(), instr->representation());
1305 SetValue(instr, non_constant_);
1308void ConstantPropagator::VisitSmiToDouble(SmiToDoubleInstr* instr) {
1309 const Object&
value = instr->value()->definition()->constant_value();
1310 if (IsUnknown(value)) {
1313 if (
value.IsInteger()) {
1318 SetValue(instr, non_constant_);
1322void ConstantPropagator::VisitInt64ToDouble(Int64ToDoubleInstr* instr) {
1323 const Object&
value = instr->value()->definition()->constant_value();
1324 if (IsUnknown(value)) {
1327 if (
value.IsInteger()) {
1332 SetValue(instr, non_constant_);
1336void ConstantPropagator::VisitInt32ToDouble(Int32ToDoubleInstr* instr) {
1337 const Object&
value = instr->value()->definition()->constant_value();
1338 if (IsUnknown(value)) {
1341 if (
value.IsInteger()) {
1346 SetValue(instr, non_constant_);
1350void ConstantPropagator::VisitDoubleToInteger(DoubleToIntegerInstr* instr) {
1352 SetValue(instr, non_constant_);
1355void ConstantPropagator::VisitDoubleToSmi(DoubleToSmiInstr* instr) {
1357 SetValue(instr, non_constant_);
1360void ConstantPropagator::VisitDoubleToFloat(DoubleToFloatInstr* instr) {
1362 SetValue(instr, non_constant_);
1365void ConstantPropagator::VisitFloatToDouble(FloatToDoubleInstr* instr) {
1367 SetValue(instr, non_constant_);
1370void ConstantPropagator::VisitFloatCompare(FloatCompareInstr* instr) {
1372 SetValue(instr, non_constant_);
1375void ConstantPropagator::VisitInvokeMathCFunction(
1376 InvokeMathCFunctionInstr* instr) {
1378 SetValue(instr, non_constant_);
1381void ConstantPropagator::VisitTruncDivMod(TruncDivModInstr* instr) {
1383 SetValue(instr, non_constant_);
1386void ConstantPropagator::VisitExtractNthOutput(ExtractNthOutputInstr* instr) {
1387 SetValue(instr, non_constant_);
1390void ConstantPropagator::VisitMakePair(MakePairInstr* instr) {
1391 SetValue(instr, non_constant_);
1394void ConstantPropagator::VisitUnboxLane(UnboxLaneInstr* instr) {
1395 if (BoxLanesInstr* box = instr->value()->definition()->AsBoxLanes()) {
1396 const Object&
value =
1397 box->InputAt(instr->lane())->definition()->constant_value();
1398 if (IsUnknown(value)) {
1401 SetValue(instr, value);
1405 SetValue(instr, non_constant_);
1408void ConstantPropagator::VisitBoxLanes(BoxLanesInstr* instr) {
1410 SetValue(instr, non_constant_);
1413void ConstantPropagator::VisitConstant(ConstantInstr* instr) {
1414 SetValue(instr, instr->value());
1417void ConstantPropagator::VisitUnboxedConstant(UnboxedConstantInstr* instr) {
1418 SetValue(instr, instr->value());
1421void ConstantPropagator::VisitConstraint(ConstraintInstr* instr) {
1426void ConstantPropagator::VisitMaterializeObject(MaterializeObjectInstr* instr) {
1431void ConstantPropagator::VisitBinaryDoubleOp(BinaryDoubleOpInstr* instr) {
1432 const Object&
left = instr->left()->definition()->constant_value();
1433 const Object&
right = instr->right()->definition()->constant_value();
1434 if (IsNonConstant(
left) || IsNonConstant(
right)) {
1435 SetValue(instr, non_constant_);
1437 }
else if (IsUnknown(
left) || IsUnknown(
right)) {
1441 const bool both_are_integers =
left.IsInteger() &&
right.IsInteger();
1443 !both_are_integers) {
1446 instr->representation());
1451 SetValue(instr, non_constant_);
1454void ConstantPropagator::VisitDoubleTestOp(DoubleTestOpInstr* instr) {
1455 const Object&
value = instr->value()->definition()->constant_value();
1456 if (IsUnknown(value)) {
1460 if (
value.IsInteger()) {
1461 switch (instr->op_kind()) {
1462 case MethodRecognizer::kDouble_getIsNaN:
1464 case MethodRecognizer::kDouble_getIsInfinite:
1467 case MethodRecognizer::kDouble_getIsNegative: {
1468 result = Integer::Cast(value).IsNegative();
1474 }
else if (
value.IsDouble()) {
1475 const double double_value =
ToDouble(value);
1476 switch (instr->op_kind()) {
1477 case MethodRecognizer::kDouble_getIsNaN: {
1478 result = isnan(double_value);
1481 case MethodRecognizer::kDouble_getIsInfinite: {
1482 result = isinf(double_value);
1485 case MethodRecognizer::kDouble_getIsNegative: {
1486 result = signbit(double_value) && !isnan(double_value);
1493 SetValue(instr, non_constant_);
1496 const bool is_negated = instr->kind() != Token::kEQ;
1500void ConstantPropagator::VisitSimdOp(SimdOpInstr* instr) {
1501 SetValue(instr, non_constant_);
1504void ConstantPropagator::VisitMathMinMax(MathMinMaxInstr* instr) {
1506 SetValue(instr, non_constant_);
1509void ConstantPropagator::VisitCaseInsensitiveCompare(
1510 CaseInsensitiveCompareInstr* instr) {
1511 SetValue(instr, non_constant_);
1514void ConstantPropagator::VisitUnbox(UnboxInstr* instr) {
1515 const Object&
value = instr->value()->definition()->constant_value();
1516 if (IsUnknown(value)) {
1520 SetValue(instr, value);
1523void ConstantPropagator::VisitBox(BoxInstr* instr) {
1524 const Object&
value = instr->value()->definition()->constant_value();
1525 if (IsUnknown(value)) {
1529 if (instr->value()->definition()->representation() ==
1530 instr->from_representation()) {
1531 SetValue(instr, value);
1533 SetValue(instr, non_constant_);
1537void ConstantPropagator::VisitBoxSmallInt(BoxSmallIntInstr* instr) {
1541void ConstantPropagator::VisitBoxUint32(BoxUint32Instr* instr) {
1545void ConstantPropagator::VisitUnboxUint32(UnboxUint32Instr* instr) {
1549void ConstantPropagator::VisitBoxInt32(BoxInt32Instr* instr) {
1553void ConstantPropagator::VisitUnboxInt32(UnboxInt32Instr* instr) {
1557void ConstantPropagator::VisitIntConverter(IntConverterInstr* instr) {
1558 SetValue(instr, non_constant_);
1561void ConstantPropagator::VisitBitCast(BitCastInstr* instr) {
1562 SetValue(instr, non_constant_);
1565void ConstantPropagator::VisitCall1ArgStub(Call1ArgStubInstr* instr) {
1566 SetValue(instr, non_constant_);
1569void ConstantPropagator::VisitSuspend(SuspendInstr* instr) {
1570 SetValue(instr, non_constant_);
1573void ConstantPropagator::VisitLoadThread(LoadThreadInstr* instr) {
1574 SetValue(instr, non_constant_);
1577void ConstantPropagator::VisitUnaryUint32Op(UnaryUint32OpInstr* instr) {
1579 SetValue(instr, non_constant_);
1587 const Object& constant_value) {
1594 if (redef->input_use_list() ==
nullptr) {
1596 redef->RemoveFromGraph();
1600 redef->constant_value() = constant_value.
ptr();
1614void ConstantPropagator::InsertRedefinitionsAfterEqualityComparisons() {
1615 for (
auto block : graph_->reverse_postorder()) {
1616 if (
auto branch = block->last_instruction()->AsBranch()) {
1617 auto comparison = branch->comparison();
1618 if (comparison->IsStrictCompare() ||
1619 (comparison->IsEqualityCompare() &&
1620 comparison->operation_cid() != kDoubleCid)) {
1622 ConstantInstr* constant_defn;
1623 if (comparison->IsComparisonWithConstant(&value, &constant_defn) &&
1624 !
value->BindsToConstant()) {
1625 const Object& constant_value = constant_defn->value();
1628 ASSERT(comparison->kind() == Token::kNE_STRICT ||
1629 comparison->kind() == Token::kNE ||
1630 comparison->kind() == Token::kEQ_STRICT ||
1631 comparison->kind() == Token::kEQ);
1632 const bool negated = (comparison->kind() == Token::kNE_STRICT ||
1633 comparison->kind() == Token::kNE);
1634 const auto true_successor =
1635 negated ? branch->false_successor() : branch->true_successor();
1642 if (constant_value.IsBool() &&
value->Type()->IsBool()) {
1643 const auto false_successor =
1644 negated ? branch->true_successor() : branch->false_successor();
1646 Bool::Get(!Bool::Cast(constant_value).value()));
1654void ConstantPropagator::Analyze() {
1655 InsertRedefinitionsAfterEqualityComparisons();
1658 reachable_->
Add(entry->preorder_number());
1659 block_worklist_.Add(entry);
1662 if (block_worklist_.is_empty()) {
1663 if (definition_worklist_.
IsEmpty())
break;
1664 Definition* definition = definition_worklist_.
RemoveLast();
1665 for (
Value* use = definition->input_use_list(); use !=
nullptr;
1666 use = use->next_use()) {
1667 use->instruction()->
Accept(
this);
1670 BlockEntryInstr* block = block_worklist_.RemoveLast();
1671 block->Accept(
this);
1677 if (
auto* join = block->AsJoinEntry()) {
1678 return (join->phis() !=
nullptr) && !join->phis()->is_empty();
1687 return block->next()->IsGoto() &&
1688 block->next()->AsGoto()->successor() != block && !
HasPhis(block) &&
1689 !block->IsIndirectEntry();
1701 current = current->next()->AsGoto()->successor();
1706void ConstantPropagator::EliminateRedundantBranches() {
1709 bool changed =
false;
1710 BitVector* empty_blocks =
new (
Z) BitVector(
Z, graph_->
preorder().length());
1712 BlockEntryInstr* block =
b.Current();
1714 empty_blocks->Clear();
1715 if ((branch !=
nullptr) && !branch->HasUnknownSideEffects()) {
1716 ASSERT(branch->previous() !=
nullptr);
1717 BlockEntryInstr* if_true =
1719 BlockEntryInstr* if_false =
1721 if (if_true == if_false) {
1724 JoinEntryInstr* join = if_true->AsJoinEntry();
1729 Instruction* previous = branch->previous();
1730 branch->set_previous(
nullptr);
1731 previous->LinkTo(jump);
1735 branch->UnuseAllInputs();
1736 for (BitVector::Iterator it(empty_blocks); !it.Done(); it.Advance()) {
1737 BlockEntryInstr* empty_block = graph_->
preorder()[it.Current()];
1738 empty_block->ClearAllInstructions();
1743 if (FLAG_trace_constant_propagation && graph_->
should_print()) {
1744 THR_Print(
"Eliminated branch in B%" Pd " common target B%" Pd "\n",
1745 block->block_id(),
join->block_id());
1756 GrowableArray<BitVector*> dominance_frontier;
1761void ConstantPropagator::Transform() {
1768 BlockEntryInstr* block =
b.Current();
1769 if (!reachable_->
Contains(block->preorder_number())) {
1770 if (FLAG_trace_constant_propagation && graph_->
should_print()) {
1771 THR_Print(
"Unreachable B%" Pd "\n", block->block_id());
1774 block->ClearAllInstructions();
1778 JoinEntryInstr*
join = block->AsJoinEntry();
1779 if (join !=
nullptr) {
1783 ZoneGrowableArray<PhiInstr*>* phis =
join->phis();
1784 if ((phis !=
nullptr) && !phis->is_empty()) {
1785 intptr_t pred_count =
join->PredecessorCount();
1786 intptr_t live_count = 0;
1787 for (intptr_t pred_idx = 0; pred_idx < pred_count; ++pred_idx) {
1789 join->PredecessorAt(pred_idx)->preorder_number())) {
1790 if (live_count < pred_idx) {
1791 for (PhiIterator it(join); !it.Done(); it.Advance()) {
1792 PhiInstr* phi = it.Current();
1794 phi->SetInputAt(live_count, phi->InputAt(pred_idx));
1799 for (PhiIterator it(join); !it.Done(); it.Advance()) {
1800 PhiInstr* phi = it.Current();
1802 phi->InputAt(pred_idx)->RemoveFromUseList();
1806 if (live_count < pred_count) {
1807 intptr_t to_idx = 0;
1808 for (intptr_t from_idx = 0; from_idx < phis->length(); ++from_idx) {
1809 PhiInstr* phi = (*phis)[from_idx];
1811 if (FLAG_remove_redundant_phis && (live_count == 1)) {
1812 Value* input = phi->InputAt(0);
1813 phi->ReplaceUsesWith(input->definition());
1814 input->RemoveFromUseList();
1816 phi->inputs_.TruncateTo(live_count);
1817 (*phis)[to_idx++] = phi;
1821 join->phis_ =
nullptr;
1823 phis->TruncateTo(to_idx);
1829 if (join !=
nullptr) {
1830 for (PhiIterator it(join); !it.Done(); it.Advance()) {
1831 auto phi = it.Current();
1832 if (TransformDefinition(phi)) {
1833 it.RemoveCurrentFromGraph();
1837 for (ForwardInstructionIterator i(block); !i.Done(); i.Advance()) {
1838 Definition* defn = i.Current()->AsDefinition();
1839 if (TransformDefinition(defn)) {
1840 i.RemoveCurrentFromGraph();
1845 BranchInstr* branch = block->last_instruction()->AsBranch();
1846 if (branch !=
nullptr) {
1847 TargetEntryInstr* if_true = branch->true_successor();
1848 TargetEntryInstr* if_false = branch->false_successor();
1849 JoinEntryInstr*
join =
nullptr;
1850 Instruction*
next =
nullptr;
1852 if (!reachable_->
Contains(if_true->preorder_number())) {
1854 ASSERT(if_false->parallel_move() ==
nullptr);
1855 join =
new (
Z) JoinEntryInstr(if_false->block_id(),
1858 if_false->UnuseAllInputs();
1859 next = if_false->next();
1860 }
else if (!reachable_->
Contains(if_false->preorder_number())) {
1861 ASSERT(if_true->parallel_move() ==
nullptr);
1862 join =
new (
Z) JoinEntryInstr(if_true->block_id(), if_true->try_index(),
1865 if_true->UnuseAllInputs();
1866 next = if_true->next();
1869 if (join !=
nullptr) {
1877 Instruction* previous = branch->previous();
1878 branch->set_previous(
nullptr);
1879 previous->LinkTo(jump);
1884 branch->UnuseAllInputs();
1891 GrowableArray<BitVector*> dominance_frontier;
1895bool ConstantPropagator::TransformDefinition(Definition* defn) {
1896 if (defn ==
nullptr) {
1900 if (
auto redef = defn->AsRedefinition()) {
1901 if (redef->inserted_by_constant_propagation()) {
1902 redef->ReplaceUsesWith(redef->value()->definition());
1906 if (IsConstant(defn->constant_value()) &&
1907 !IsConstant(defn->OriginalDefinition()->constant_value())) {
1918 if (IsConstant(defn->constant_value()) &&
1919 (defn->constant_value().IsSmi() || defn->constant_value().IsOld()) &&
1920 !defn->IsConstant() && !defn->IsStoreIndexed() && !defn->IsStoreField() &&
1921 !defn->IsStoreStaticField()) {
1922 if (FLAG_trace_constant_propagation && graph_->
should_print()) {
1923 THR_Print(
"Constant v%" Pd " = %s\n", defn->ssa_temp_index(),
1924 defn->constant_value().ToCString());
1926 constant_value_ = defn->constant_value().
ptr();
1927 if ((constant_value_.IsString() || constant_value_.IsMint() ||
1928 constant_value_.IsDouble()) &&
1930 constant_value_ = Instance::Cast(constant_value_).Canonicalize(
T);
1933 if (
auto call = defn->AsStaticCall()) {
1936 Definition* replacement =
1938 if (replacement != defn) {
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
static float next(float f)
static bool left(const SkPoint &p0, const SkPoint &p1)
static bool right(const SkPoint &p0, const SkPoint &p1)
bool Contains(intptr_t i) const
intptr_t preorder_number() const
bool Dominates(BlockEntryInstr *other) const
Instruction * last_instruction() const
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 bool SupportsUnboxedDoubles()
static void PrintGraph(const char *phase, FlowGraph *flow_graph)
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
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,...)
#define DEFINE_FLAG(type, name, default_value, comment)
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)
static bool IsEmptyBlock(BlockEntryInstr *block)
bool IsIntegerClassId(intptr_t index)
static bool IsIntegerOrDouble(const Object &value)
SINT Vec< 2 *N, T > join(const Vec< N, T > &lo, const Vec< N, T > &hi)
Value(int value, int *counter)
#define NOT_IN_PRODUCT(code)