43 auto b1 =
H.flow_graph()->graph_entry()->normal_entry();
44 auto b2 =
H.JoinEntry();
45 auto b3 =
H.TargetEntry();
46 auto b4 =
H.TargetEntry();
55 v1 =
H.Phi(b2, {{b1, v0}, {b3, &v1}});
59 new Value(v0), kSmiCid,
S.GetNextDeoptId()));
63 false,
S.GetNextDeoptId()),
82 H.flow_graph()->disallow_licm();
88 auto& blocks =
H.flow_graph()->reverse_postorder();
89 EXPECT_EQ(2, blocks.length());
94 it.value()->definition() == v0);
99#if defined(ARCH_IS_64_BIT)
101struct FoldingResult {
102 static FoldingResult NoFold() {
return {
false, 0}; }
104 static FoldingResult FoldsTo(int64_t
result) {
return {
true,
result}; }
110static void ConstantPropagatorUnboxedOpTest(
114 std::function<Definition*(Definition*, Definition*, intptr_t)> make_op,
116 FoldingResult expected) {
117 using compiler::BlockBuilder;
119 CompilerState
S(thread,
false,
true);
120 FlowGraphBuilderHelper
H(1);
145 auto b1 =
H.flow_graph()->graph_entry()->normal_entry();
146 auto b2 =
H.TargetEntry();
147 auto b3 =
H.TargetEntry();
148 auto b4 =
H.JoinEntry();
149 DartReturnInstr* ret;
152 BlockBuilder
builder(
H.flow_graph(), b1);
153 auto v0 =
builder.AddParameter(0, kTagged);
155 new StrictCompareInstr(
156 InstructionSource(), Token::kEQ_STRICT,
new Value(
H.IntConstant(1)),
157 new Value(redundant_phi ?
H.IntConstant(1) : v0),
158 false,
S.GetNextDeoptId()),
163 BlockBuilder
builder(
H.flow_graph(), b2);
164 builder.AddInstruction(
new GotoInstr(b4,
S.GetNextDeoptId()));
168 BlockBuilder
builder(
H.flow_graph(), b3);
169 builder.AddInstruction(
new GotoInstr(b4,
S.GetNextDeoptId()));
175 BlockBuilder
builder(
H.flow_graph(), b4);
176 v1 =
H.Phi(b4, {{b2,
H.IntConstant(lhs)},
177 {b3,
H.IntConstant(redundant_phi ? -1 : lhs)}});
180 make_op(v1,
H.IntConstant(rhs),
S.GetNextDeoptId()));
186 FlowGraphTypePropagator::Propagate(
H.flow_graph());
189 v1->set_representation(op->representation());
190 H.flow_graph()->SelectRepresentations();
192 H.flow_graph()->Canonicalize();
194 if (!expected.should_fold) {
196 it.IsBoxInteger() && it.RequiredInputRepresentation(0) ==
197 op->representation());
212 auto ret_val = ret->value()->definition();
213 if (expected.should_fold) {
215 it.IsConstant() && it.representation() == kTagged);
216 EXPECT_EQ(expected.result,
217 Integer::Cast(ret_val->AsConstant()->value()).AsInt64Value());
220 it.IsBoxInteger() && it.RequiredInputRepresentation(0) ==
221 op->representation());
222 auto boxed_value = ret_val->AsBoxInteger()->value()->definition();
228void ConstantPropagatorUnboxedOpTest(
232 std::function<Definition*(Definition*, Definition*, intptr_t)> make_op,
233 FoldingResult expected) {
234 ConstantPropagatorUnboxedOpTest(thread, lhs, rhs, make_op,
236 ConstantPropagatorUnboxedOpTest(thread, lhs, rhs, make_op,
245 auto make_int64_add = [](Definition* lhs, Definition* rhs,
247 return new BinaryInt64OpInstr(Token::kADD,
new Value(lhs),
new Value(rhs),
251 auto make_int32_add = [](Definition* lhs, Definition* rhs,
253 return new BinaryInt32OpInstr(Token::kADD,
new Value(lhs),
new Value(rhs),
257 auto make_int32_truncating_add = [](Definition* lhs, Definition* rhs,
259 auto op =
new BinaryInt32OpInstr(Token::kADD,
new Value(lhs),
260 new Value(rhs), deopt_id);
261 op->mark_truncating();
265 ConstantPropagatorUnboxedOpTest(thread, 1, 2, make_int64_add,
266 FoldingResult::FoldsTo(3));
267 ConstantPropagatorUnboxedOpTest(thread,
kMaxInt64, 1,
271 ConstantPropagatorUnboxedOpTest(thread, 1, 2, make_int32_add,
272 FoldingResult::FoldsTo(3));
273 ConstantPropagatorUnboxedOpTest(thread,
kMaxInt32 - 1, 1,
279 ConstantPropagatorUnboxedOpTest(thread,
kMaxInt32, 1,
280 make_int32_add, FoldingResult::NoFold());
283 ConstantPropagatorUnboxedOpTest(thread,
kMaxInt32, 1,
284 make_int32_truncating_add,
291 bool non_sentinel_on_left) {
292 const char* kScript = R
"(
293 late final int x = 4;
296 const auto& root_library = Library::CheckedHandle(
Z,
LoadTestScript(kScript));
297 const auto& toplevel =
Class::Handle(
Z, root_library.toplevel_class());
305 auto b1 =
H.flow_graph()->graph_entry()->normal_entry();
311 true,
S.GetNextDeoptId()));
312 auto v_sentinel =
H.flow_graph()->GetConstant(Object::sentinel());
313 Value*
const left_value =
314 non_sentinel_on_left ?
new Value(v_load) :
new Value(v_sentinel);
315 Value*
const right_value =
316 non_sentinel_on_left ?
new Value(v_sentinel) :
new Value(v_load);
318 {}, negate ? Token::kNE_STRICT : Token::kEQ_STRICT, left_value,
320 false,
S.GetNextDeoptId()));
327 FlowGraphTypePropagator::Propagate(
H.flow_graph());
336 H.flow_graph()->graph_entry()->normal_entry(),
true);
338 kMatchAndMoveFunctionEntry,
339 kMatchAndMoveLoadStaticField,
341 {kMatchDartReturn, &ret},
347 Bool::Cast(it).value() == negate);
static float next(float f)
#define RELEASE_ASSERT(cond)
static const Bool & True()
static void Optimize(FlowGraph *graph)
static void PrintGraph(const char *phase, FlowGraph *flow_graph)
bool TryMatch(std::initializer_list< MatchCode > match_codes, MatchOpCode insert_before=kInvalidMatchOpCode)
static Object & ZoneHandle()
static StringPtr New(const char *cstr, Heap::Space space=Heap::kNew)
static Thread * Current()
Dart_NativeFunction function
#define EXPECT_PROPERTY(entity, property)
constexpr int64_t kMaxInt64
constexpr int64_t kMinInt64
LibraryPtr LoadTestScript(const char *script, Dart_NativeEntryResolver resolver, const char *lib_uri)
constexpr int32_t kMinInt32
void StrictCompareSentinel(Thread *thread, bool negate, bool non_sentinel_on_left)
ISOLATE_UNIT_TEST_CASE(StackAllocatedDestruction)
constexpr int32_t kMaxInt32
#define ISOLATE_UNIT_TEST_CASE(name)