ART: Try to statically evaluate some conditions.
If a condition 'cond' is evaluated in an HIf instruction then in
the successors of the this HIF_BLOCK we statically know the value
of the condition (TRUE in TRUE_SUCC, FALSE in FALSE_SUCC). Using
that we could replace another evaluation (use) EVAL of the same
'cond' with TRUE value (FALSE value) if every path from the
ENTRY_BLOCK to EVAL_BLOCK contains the edge HIF_BLOCK->TRUE_SUCC
(HIF_BLOCK->FALSE_SUCC).
if (cond) {
...
if (cond) {
...
}
...
int a = cond ? 5 : 105;
...
}
The patch is a prerequisite step for "Loop peeling to eliminate
invariant exits" however it brings some value on its own with
a tiny code size reduction in boot-framework.oat (-8Kb).
Test: 458-checker-instruct-simplification
Test: test-art-target, test-art-host.
Change-Id: Ifbe45097dc2b5f098176fa1a1d023ea90b76d396
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index fa580d9..dda0243 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -1110,10 +1110,10 @@
return true;
}
-bool HInstruction::StrictlyDominates(HInstruction* other_instruction) const {
+bool HInstruction::Dominates(HInstruction* other_instruction, bool strictly) const {
if (other_instruction == this) {
// An instruction does not strictly dominate itself.
- return false;
+ return !strictly;
}
HBasicBlock* block = GetBlock();
HBasicBlock* other_block = other_instruction->GetBlock();
@@ -1147,6 +1147,10 @@
}
}
+bool HInstruction::StrictlyDominates(HInstruction* other_instruction) const {
+ return Dominates(other_instruction, /* strictly */ true);
+}
+
void HInstruction::RemoveEnvironment() {
RemoveEnvironmentUses(this);
environment_ = nullptr;
@@ -1169,14 +1173,16 @@
DCHECK(env_uses_.empty());
}
-void HInstruction::ReplaceUsesDominatedBy(HInstruction* dominator, HInstruction* replacement) {
+void HInstruction::ReplaceUsesDominatedBy(HInstruction* dominator,
+ HInstruction* replacement,
+ bool strictly) {
const HUseList<HInstruction*>& uses = GetUses();
for (auto it = uses.begin(), end = uses.end(); it != end; /* ++it below */) {
HInstruction* user = it->GetUser();
size_t index = it->GetIndex();
// Increment `it` now because `*it` may disappear thanks to user->ReplaceInput().
++it;
- if (dominator->StrictlyDominates(user)) {
+ if (dominator->Dominates(user, strictly)) {
user->ReplaceInput(replacement, index);
}
}