summaryrefslogtreecommitdiff
path: root/compiler/optimizing/nodes.h
diff options
context:
space:
mode:
author Alex Light <allight@google.com> 2020-07-09 13:24:56 -0700
committer Treehugger Robot <treehugger-gerrit@google.com> 2020-11-12 02:08:44 +0000
commitbb6cda60e4418c0ab557ea4090e046bed8206763 (patch)
treef6b94510108cb653a80e0ea14d50ad6616c9f44a /compiler/optimizing/nodes.h
parent670ff8854cf075617e0abee77b2259903757d86e (diff)
Partial LSE analysis & store removal
This is the first piece of partial LSE for art. This CL adds analysis tools needed to implement partial LSE. More immediately, it improves LSE so that it will remove stores that are provably non-observable based on the location they occur. For example: ``` Foo o = new Foo(); if (xyz) { check(foo); foo.x++; } else { foo.x = 12; } return foo.x; ``` The store of 12 can be removed because the only escape in this method is unreachable and was not executed by the point we reach the store. The main purpose of this CL is to add the analysis tools needed to implement partial Load-Store elimination. Namely it includes tracking of which blocks are escaping and the groups of blocks that we cannot remove allocations from. The actual impact of this change is incredibly minor, being triggered only once in a AOSP code. go/lem shows only minor effects to compile-time and no effect on the compiled code. See go/lem-allight-partial-lse-2 for numbers. Compile time shows an average of 1.4% regression (max regression is 7% with 0.2 noise). This CL adds a new 'reachability' concept to the HGraph. If this has been calculated it allows one to quickly query whether there is any execution path containing two blocks in a given order. This is used to define a notion of sections of graph from which the escape of some allocation is inevitable. Test: art_compiler_tests Test: treehugger Bug: 67037140 Change-Id: I0edc8d6b73f7dd329cb1ea7923080a0abe913ea6
Diffstat (limited to 'compiler/optimizing/nodes.h')
-rw-r--r--compiler/optimizing/nodes.h12
1 files changed, 12 insertions, 0 deletions
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index ad56d31667..9fa21d5006 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -21,6 +21,7 @@
#include <array>
#include <type_traits>
+#include "base/arena_allocator.h"
#include "base/arena_bit_vector.h"
#include "base/arena_containers.h"
#include "base/arena_object.h"
@@ -387,6 +388,7 @@ class HGraph : public ArenaObject<kArenaAllocGraph> {
blocks_(allocator->Adapter(kArenaAllocBlockList)),
reverse_post_order_(allocator->Adapter(kArenaAllocReversePostOrder)),
linear_order_(allocator->Adapter(kArenaAllocLinearOrder)),
+ reachability_graph_(allocator, 0, 0, true, kArenaAllocReachabilityGraph),
entry_block_(nullptr),
exit_block_(nullptr),
maximum_number_of_out_vregs_(0),
@@ -442,6 +444,8 @@ class HGraph : public ArenaObject<kArenaAllocGraph> {
void ComputeDominanceInformation();
void ClearDominanceInformation();
+ void ComputeReachabilityInformation();
+ void ClearReachabilityInformation();
void ClearLoopInformation();
void FindBackEdges(ArenaBitVector* visited);
GraphAnalysisResult BuildDominatorTree();
@@ -590,6 +594,10 @@ class HGraph : public ArenaObject<kArenaAllocGraph> {
has_bounds_checks_ = value;
}
+ // Returns true if dest is reachable from source, using either blocks or block-ids.
+ bool PathBetween(const HBasicBlock* source, const HBasicBlock* dest) const;
+ bool PathBetween(uint32_t source_id, uint32_t dest_id) const;
+
// Is the code known to be robust against eliminating dead references
// and the effects of early finalization?
bool IsDeadReferenceSafe() const { return dead_reference_safe_; }
@@ -746,6 +754,10 @@ class HGraph : public ArenaObject<kArenaAllocGraph> {
// post order, this order is not incrementally kept up-to-date.
ArenaVector<HBasicBlock*> linear_order_;
+ // Reachability graph for checking connectedness between nodes. Acts as a partitioned vector where
+ // each RoundUp(blocks_.size(), BitVector::kWordBits) is the reachability of each node.
+ ArenaBitVectorArray reachability_graph_;
+
HBasicBlock* entry_block_;
HBasicBlock* exit_block_;