26using compiler::BlockBuilder;
34 auto normal_entry =
H.flow_graph()->graph_entry()->normal_entry();
48 auto b2 =
H.TargetEntry();
49 auto b3 =
H.TargetEntry();
53 v0 =
builder.AddParameter(0, kTagged);
58 false,
S.GetNextDeoptId()),
74 FlowGraphTypePropagator::Propagate(
H.flow_graph());
82 auto b2_value = b2->last_instruction()->AsDartReturn()->value();
83 EXPECT(b2_value->Type()->IsNullableInt());
88 auto b3_value = b3->last_instruction()->AsDartReturn()->value();
89 EXPECT(b3_value->Type()->IsInt());
90 EXPECT(b3_value->definition()->IsRedefinition());
91 EXPECT(b3_value->definition()->GetBlock() == b3);
95 TypePropagator_RedefinitionAfterStrictCompareWithLoadClassId) {
114 auto b1 =
H.flow_graph()->graph_entry()->normal_entry();
115 auto b2 =
H.TargetEntry();
116 auto b3 =
H.TargetEntry();
120 v0 =
builder.AddParameter(0, kTagged);
125 new Value(
H.IntConstant(kDoubleCid)),
126 false,
S.GetNextDeoptId()),
142 FlowGraphTypePropagator::Propagate(
H.flow_graph());
147 auto b3_value = b3->last_instruction()->AsDartReturn()->value();
153 auto b2_value = b2->last_instruction()->AsDartReturn()->value();
162 const Class& object_class =
163 Class::Handle(thread->isolate_group()->object_store()->object_class());
168 UntaggedFunction::kRegularFunction,
173 true, object_class, TokenPosition::kNoSource));
182 false, object_class, Object::dynamic_type(),
183 TokenPosition::kNoSource, TokenPosition::kNoSource));
186 thread->isolate_group()->program_lock());
187 thread->isolate_group()->RegisterStaticField(field,
Object::Handle());
212 auto b1 =
H.flow_graph()->graph_entry()->normal_entry();
213 auto b2 =
H.TargetEntry();
214 auto b3 =
H.TargetEntry();
215 auto b4 =
H.JoinEntry();
219 v0 =
builder.AddParameter(0, kTagged);
222 new Value(
H.IntConstant(1)),
223 false,
S.GetNextDeoptId()),
232 Array::empty_array(),
234 0, ICData::RebindRule::kStatic));
245 v3 =
H.Phi(b4, {{b2,
v2}, {b3,
H.IntConstant(0)}});
251 FlowGraphTypePropagator::Propagate(
H.flow_graph());
258 v2->ReplaceUsesWith(
v4);
259 v2->RemoveFromGraph();
261 FlowGraphTypePropagator::Propagate(
H.flow_graph());
300 auto b1 =
H.flow_graph()->graph_entry()->normal_entry();
301 auto b2 =
H.TargetEntry();
302 auto b3 =
H.TargetEntry();
303 auto b4 =
H.TargetEntry();
304 auto b5 =
H.JoinEntry();
305 auto b6 =
H.TargetEntry();
306 auto b7 =
H.JoinEntry();
310 v0 =
builder.AddParameter(0, kTagged);
313 new Value(
H.IntConstant(1)),
314 false,
S.GetNextDeoptId()),
322 new Value(
H.IntConstant(2)),
323 false,
S.GetNextDeoptId()),
339 v3 =
H.Phi(b5, {{b3,
H.IntConstant(42)}, {b4,
H.IntConstant(24)}});
351 v5 =
H.Phi(b7, {{b5, v3}, {b6,
H.DoubleConstant(1.0)}});
359 FlowGraphTypePropagator::Propagate(
H.flow_graph());
376 H.flow_graph()->InsertBefore(
379 input->BindTo(unbox);
384 H.flow_graph()->InsertBefore(b4->last_instruction(), box,
nullptr,
389 FlowGraphTypePropagator::Propagate(
H.flow_graph());
403 const char* script_chars = R
"(
409 NumBound extends num,
410 ComparableBound extends Comparable,
411 StringBound extends String> {
412 // Simple instantiated types.
413 @pragma('vm-test:can-be-smi') late int t1;
414 @pragma('vm-test:can-be-smi') late num t2;
415 @pragma('vm-test:can-be-smi') late Object t3;
419 @pragma('vm-test:can-be-smi') late NoBound tp1;
420 @pragma('vm-test:can-be-smi') late NumBound tp2;
421 @pragma('vm-test:can-be-smi') late ComparableBound tp3;
422 late StringBound tp4;
424 // Comparable<T> instantiations.
425 @pragma('vm-test:can-be-smi') late Comparable c1;
426 late Comparable<String> c2;
427 @pragma('vm-test:can-be-smi') late Comparable<num> c3;
428 late Comparable<int> c4; // int is not a subtype of Comparable<int>.
429 @pragma('vm-test:can-be-smi') late Comparable<NoBound> c5;
430 @pragma('vm-test:can-be-smi') late Comparable<NumBound> c6;
431 @pragma('vm-test:can-be-smi') late Comparable<ComparableBound> c7;
432 late Comparable<StringBound> c8;
434 // FutureOr<T> instantiations.
435 @pragma('vm-test:can-be-smi') late FutureOr fo1;
436 late FutureOr<String> fo2;
437 @pragma('vm-test:can-be-smi') late FutureOr<num> fo3;
438 @pragma('vm-test:can-be-smi') late FutureOr<int> fo4;
439 @pragma('vm-test:can-be-smi') late FutureOr<NoBound> fo5;
440 @pragma('vm-test:can-be-smi') late FutureOr<NumBound> fo6;
441 @pragma('vm-test:can-be-smi') late FutureOr<ComparableBound> fo7;
442 late FutureOr<StringBound> fo8;
444 // Other generic classes.
452 const auto& pragma_can_be_smi =
454 auto expected_can_be_smi = [&](
const Field&
f) {
456 return lib.FindPragma(thread,
false,
f, pragma_can_be_smi,
461 const auto& err =
Error::Handle(cls.EnsureIsFinalized(thread));
467 for (intptr_t
i = 0;
i < fields.Length();
i++) {
468 field ^= fields.At(
i);
473 if (compile_type.CanBeSmi() != expected_can_be_smi(field)) {
475 .
Fail(
"expected that CanBeSmi() returns %s for compile type %s\n",
476 expected_can_be_smi(field) ?
"true" :
"false",
477 compile_type.ToCString());
491 auto normal_entry =
H.flow_graph()->graph_entry()->normal_entry();
505 auto null_value =
builder.AddNullDefinition();
510 new Value(null_value),
new Value(null_value), Symbols::Value(),
511 S.GetNextDeoptId()));
519 H.flow_graph()->EliminateEnvironments();
520 FlowGraphTypePropagator::Propagate(
H.flow_graph());
523#if defined(DART_PRECOMPILER)
529 const char* kScript = R
"(
530 const y = 0xDEADBEEF;
531 final int x = int.parse('0xFEEDFEED');
533 void main(List<String> args) {
543 FlowGraph* flow_graph = pipeline.RunPasses({});
545 auto entry = flow_graph->graph_entry()->normal_entry();
546 ILMatcher cursor(flow_graph, entry,
true,
549 Instruction*
load =
nullptr;
553 {kMatchAndMoveLoadStaticField, &load},
554 kMatchAndMoveMoveArgument,
555 kMatchAndMoveStaticCall,
556 kMatchAndMoveUnboxInt64,
557 kMatchAndMoveBinaryInt64Op,
558 kMatchAndMoveBoxInt64,
559 kMatchAndMoveMoveArgument,
560 kMatchAndMoveStaticCall,
568 const char* kScript = R
"(
571 Zone* const Z = Thread::Current()->zone();
572 const auto& root_library = Library::CheckedHandle(
Z,
LoadTestScript(kScript));
573 const auto& toplevel = Class::Handle(
Z, root_library.toplevel_class());
574 const auto& field_x = Field::Handle(
575 Z, toplevel.LookupStaticField(String::Handle(
Z, String::New(
"x"))));
577 using compiler::BlockBuilder;
578 CompilerState
S(thread,
false,
true);
579 FlowGraphBuilderHelper
H;
600 Definition*
v2 =
H.IntConstant(3);
604 auto b1 =
H.flow_graph()->graph_entry()->normal_entry();
605 auto b2 =
H.TargetEntry();
606 auto b3 =
H.TargetEntry();
607 auto b4 =
H.JoinEntry();
610 BlockBuilder
builder(
H.flow_graph(), b1);
611 v3 =
builder.AddDefinition(
new LoadStaticFieldInstr(
613 false,
S.GetNextDeoptId()));
614 auto v5 =
builder.AddDefinition(
new ConstantInstr(Object::sentinel()));
615 builder.AddBranch(
new StrictCompareInstr(
616 {}, Token::kEQ_STRICT,
new Value(v3),
new Value(v5),
617 false,
S.GetNextDeoptId()),
622 BlockBuilder
builder(
H.flow_graph(), b2);
623 builder.AddInstruction(
new GotoInstr(b4,
S.GetNextDeoptId()));
627 BlockBuilder
builder(
H.flow_graph(), b3);
628 v7 =
builder.AddDefinition(
new RedefinitionInstr(
new Value(v3)));
629 CompileType int_type =
633 v7->AsRedefinition()->set_constrained_type(
new CompileType(int_type));
634 builder.AddInstruction(
new GotoInstr(b4,
S.GetNextDeoptId()));
638 BlockBuilder
builder(
H.flow_graph(), b4);
639 v9 =
H.Phi(b4, {{b2,
v2}, {b3, v7}});
646 FlowGraphPrinter::PrintGraph(
"Before TypePropagator",
H.flow_graph());
647 FlowGraphTypePropagator::Propagate(
H.flow_graph());
648 FlowGraphPrinter::PrintGraph(
"After TypePropagator",
H.flow_graph());
650 auto& blocks =
H.flow_graph()->reverse_postorder();
651 EXPECT_EQ(5, blocks.length());
665 it.can_be_sentinel());
674 !it.can_be_sentinel());
682 EXPECT_PROPERTY(blocks[4]->AsJoinEntry()->phis()->At(0), it.HasType());
684 !it.can_be_sentinel());
692 const char* kScript = R
"(
693 @pragma('vm:never-inline')
694 (int, {String foo}) bar() => (42, foo: 'hi');
695 @pragma('vm:never-inline')
705 const auto& root_library = Library::Handle(
LoadTestScript(kScript));
706 Invoke(root_library,
"main");
713 ILMatcher cursor(flow_graph, entry,
true,
714 ParallelMovesHandling::kSkip);
721 kMatchAndMoveStaticCall,
722 {kMatchAndMoveLoadField, &load1},
723 kMatchAndMoveCheckSmi,
724 kMatchAndMoveBinarySmiOp,
725 kMatchAndMoveMoveArgument,
726 kMatchAndMoveStaticCall,
727 {kMatchAndMoveLoadField, &load2},
728 kMatchAndMoveMoveArgument,
729 kMatchAndMoveStaticCall,
static float next(float f)
static SkV4 v4(SkV3 v, SkScalar w)
#define RELEASE_ASSERT(cond)
bool IsObjectType() const
bool IsDynamicType() const
Instruction * last_instruction() const
static constexpr bool kCannotBeSentinel
static constexpr bool kCanBeNull
static CompileType FromAbstractType(const AbstractType &type, bool can_be_null, bool can_be_sentinel)
const AbstractType * ToAbstractType()
void ReplaceUsesWith(Definition *other)
void Fail(const char *format,...) const PRINTF_ATTRIBUTE(2
GraphEntryInstr * graph_entry() const
void set_result_type(const AbstractType &value) const
static FunctionTypePtr New(intptr_t num_parent_type_arguments=0, Nullability nullability=Nullability::kNonNullable, Heap::Space space=Heap::kOld)
static FunctionPtr New(const FunctionType &signature, const String &name, UntaggedFunction::Kind kind, bool is_static, bool is_const, bool is_abstract, bool is_external, bool is_native, const Object &owner, TokenPosition token_pos, Heap::Space space=Heap::kOld)
FunctionEntryInstr * normal_entry() const
bool TryMatch(std::initializer_list< MatchCode > match_codes, MatchOpCode insert_before=kInvalidMatchOpCode)
virtual BlockEntryInstr * PredecessorAt(intptr_t index) const
static Object & ZoneHandle()
JoinEntryInstr * block() const
virtual void set_representation(Representation r)
static StringPtr New(Thread *thread, const char *cstr)
FlowGraph * RunPasses(std::initializer_list< CompilerPass::Id > passes)
static TypePtr DynamicType()
intptr_t InputCount() const
Value * InputAt(intptr_t i) const
Dart_NativeFunction function
#define EXPECT_PROPERTY(entity, property)
SI void load2(const uint16_t *ptr, U16 *r, U16 *g)
LibraryPtr LoadTestScript(const char *script, Dart_NativeEntryResolver resolver, const char *lib_uri)
GrowableArray< Value * > InputsArray
ObjectPtr Invoke(const Library &lib, const char *name)
FunctionPtr GetFunction(const Library &lib, const char *name)
ISOLATE_UNIT_TEST_CASE(StackAllocatedDestruction)
ClassPtr GetClass(const Library &lib, const char *name)
#define ISOLATE_UNIT_TEST_CASE(name)