[vm/compiler] Avoid adding unused Redefinition instructions

Type propagator adds Redefinition instructions to provide more accurate
type information only for dominated uses (for example, to mark receiver
as non-nullable after instance calls). However, adding Redefinition
instructions may interfere with branch simplification, which looks only
at empty join blocks. This change avoids adding unused Redefinition
instructions (if there are no dominated uses).

This particular situation happens in Flutter in RenderObject.layout() where
constraints.isTight is inlined with multiple polymorphic targets, including
SliverConstraints.isTight which returns false.
Branch simplification was not happening due to Redefinition instruction
for 'constraints'. That Redefinition instruction is not used.

Change-Id: I15082bacd7cc6ea1445a4dadc8ef97853142ba74
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/103023
Commit-Queue: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
This commit is contained in:
Alexander Markov 2019-05-20 17:38:14 +00:00 committed by commit-bot@chromium.org
parent 04e329b6ed
commit 433bc1b350

View file

@ -1498,11 +1498,11 @@ RedefinitionInstr* FlowGraph::EnsureRedefinition(Instruction* prev,
Definition* original,
CompileType compile_type) {
RedefinitionInstr* first = prev->next()->AsRedefinition();
if (first != NULL && (first->constrained_type() != NULL)) {
if (first != nullptr && (first->constrained_type() != nullptr)) {
if ((first->value()->definition() == original) &&
first->constrained_type()->IsEqualTo(&compile_type)) {
// Already redefined. Do nothing.
return NULL;
return nullptr;
}
}
RedefinitionInstr* redef = new RedefinitionInstr(new Value(original));
@ -1513,8 +1513,17 @@ RedefinitionInstr* FlowGraph::EnsureRedefinition(Instruction* prev,
redef->set_constrained_type(new CompileType(compile_type));
}
InsertAfter(prev, redef, NULL, FlowGraph::kValue);
InsertAfter(prev, redef, nullptr, FlowGraph::kValue);
RenameDominatedUses(original, redef, redef);
if (redef->input_use_list() == nullptr) {
// There are no dominated uses, so the newly added Redefinition is useless.
// Remove Redefinition to avoid interfering with
// BranchSimplifier::Simplify which needs empty blocks.
redef->RemoveFromGraph();
return nullptr;
}
return redef;
}