namespace art {
-void GlobalValueNumberer::Run() {
- ComputeSideEffects();
-
- sets_.Put(graph_->GetEntryBlock()->GetBlockId(), new (allocator_) ValueSet(allocator_));
-
- // Do reverse post order to ensure the non back-edge predecessors of a block are
- // visited before the block itself.
- for (HReversePostOrderIterator it(*graph_); !it.Done(); it.Advance()) {
- VisitBasicBlock(it.Current());
- }
-}
-
-void GlobalValueNumberer::UpdateLoopEffects(HLoopInformation* info, SideEffects effects) {
+void SideEffectsAnalysis::UpdateLoopEffects(HLoopInformation* info, SideEffects effects) {
int id = info->GetHeader()->GetBlockId();
loop_effects_.Put(id, loop_effects_.Get(id).Union(effects));
}
-void GlobalValueNumberer::ComputeSideEffects() {
+void SideEffectsAnalysis::Run() {
if (kIsDebugBuild) {
for (HReversePostOrderIterator it(*graph_); !it.Done(); it.Advance()) {
HBasicBlock* block = it.Current();
UpdateLoopEffects(block->GetLoopInformation(), effects);
}
}
+ has_run_ = true;
}
-SideEffects GlobalValueNumberer::GetLoopEffects(HBasicBlock* block) const {
+SideEffects SideEffectsAnalysis::GetLoopEffects(HBasicBlock* block) const {
DCHECK(block->IsLoopHeader());
return loop_effects_.Get(block->GetBlockId());
}
-SideEffects GlobalValueNumberer::GetBlockEffects(HBasicBlock* block) const {
+SideEffects SideEffectsAnalysis::GetBlockEffects(HBasicBlock* block) const {
return block_effects_.Get(block->GetBlockId());
}
+void GlobalValueNumberer::Run() {
+ DCHECK(side_effects_.HasRun());
+ sets_.Put(graph_->GetEntryBlock()->GetBlockId(), new (allocator_) ValueSet(allocator_));
+
+ // Use the reverse post order to ensure the non back-edge predecessors of a block are
+ // visited before the block itself.
+ for (HReversePostOrderIterator it(*graph_); !it.Done(); it.Advance()) {
+ VisitBasicBlock(it.Current());
+ }
+}
+
void GlobalValueNumberer::VisitBasicBlock(HBasicBlock* block) {
ValueSet* set = nullptr;
const GrowableArray<HBasicBlock*>& predecessors = block->GetPredecessors();
if (!set->IsEmpty()) {
if (block->IsLoopHeader()) {
DCHECK_EQ(block->GetDominator(), block->GetLoopInformation()->GetPreHeader());
- set->Kill(GetLoopEffects(block));
+ set->Kill(side_effects_.GetLoopEffects(block));
} else if (predecessors.Size() > 1) {
for (size_t i = 0, e = predecessors.Size(); i < e; ++i) {
set->IntersectionWith(sets_.Get(predecessors.Get(i)->GetBlockId()));
DISALLOW_COPY_AND_ASSIGN(ValueSet);
};
-/**
- * Optimization phase that removes redundant instruction.
- */
-class GlobalValueNumberer : public ValueObject {
+class SideEffectsAnalysis : public HOptimization {
public:
- GlobalValueNumberer(ArenaAllocator* allocator, HGraph* graph)
- : graph_(graph),
- allocator_(allocator),
- block_effects_(allocator, graph->GetBlocks().Size()),
- loop_effects_(allocator, graph->GetBlocks().Size()),
- sets_(allocator, graph->GetBlocks().Size()) {
- size_t number_of_blocks = graph->GetBlocks().Size();
- block_effects_.SetSize(number_of_blocks);
- loop_effects_.SetSize(number_of_blocks);
- sets_.SetSize(number_of_blocks);
-
- for (size_t i = 0; i < number_of_blocks; ++i) {
- block_effects_.Put(i, SideEffects::None());
- loop_effects_.Put(i, SideEffects::None());
- }
- }
+ explicit SideEffectsAnalysis(HGraph* graph)
+ : HOptimization(graph, true, "SideEffects"),
+ graph_(graph),
+ block_effects_(graph->GetArena(), graph->GetBlocks().Size(), SideEffects::None()),
+ loop_effects_(graph->GetArena(), graph->GetBlocks().Size(), SideEffects::None()) {}
- void Run();
+ SideEffects GetLoopEffects(HBasicBlock* block) const;
+ SideEffects GetBlockEffects(HBasicBlock* block) const;
- private:
- // Per-block GVN. Will also update the ValueSet of the dominated and
- // successor blocks.
- void VisitBasicBlock(HBasicBlock* block);
+ // Compute side effects of individual blocks and loops.
+ void Run();
- // Compute side effects of individual blocks and loops. The GVN algorithm
- // will use these side effects to update the ValueSet of individual blocks.
- void ComputeSideEffects();
+ bool HasRun() const { return has_run_; }
+ private:
void UpdateLoopEffects(HLoopInformation* info, SideEffects effects);
- SideEffects GetLoopEffects(HBasicBlock* block) const;
- SideEffects GetBlockEffects(HBasicBlock* block) const;
HGraph* graph_;
- ArenaAllocator* const allocator_;
+ // Checked in debug build, to ensure the pass has been run prior to
+ // running a pass that depends on it.
+ bool has_run_ = false;
// Side effects of individual blocks, that is the union of the side effects
// of the instructions in the block.
// blocks contained in that loop.
GrowableArray<SideEffects> loop_effects_;
+ ART_FRIEND_TEST(GVNTest, LoopSideEffects);
+ DISALLOW_COPY_AND_ASSIGN(SideEffectsAnalysis);
+};
+
+/**
+ * Optimization phase that removes redundant instruction.
+ */
+class GlobalValueNumberer : public ValueObject {
+ public:
+ GlobalValueNumberer(ArenaAllocator* allocator,
+ HGraph* graph,
+ const SideEffectsAnalysis& side_effects)
+ : graph_(graph),
+ allocator_(allocator),
+ side_effects_(side_effects),
+ sets_(allocator, graph->GetBlocks().Size(), nullptr) {}
+
+ void Run();
+
+ private:
+ // Per-block GVN. Will also update the ValueSet of the dominated and
+ // successor blocks.
+ void VisitBasicBlock(HBasicBlock* block);
+
+ HGraph* graph_;
+ ArenaAllocator* const allocator_;
+ const SideEffectsAnalysis& side_effects_;
+
// ValueSet for blocks. Initially null, but for an individual block they
// are allocated and populated by the dominator, and updated by all blocks
// in the path from the dominator to the block.
GrowableArray<ValueSet*> sets_;
- ART_FRIEND_TEST(GVNTest, LoopSideEffects);
DISALLOW_COPY_AND_ASSIGN(GlobalValueNumberer);
};
class GVNOptimization : public HOptimization {
public:
- explicit GVNOptimization(HGraph* graph) : HOptimization(graph, true, "GVN") {}
+ GVNOptimization(HGraph* graph, const SideEffectsAnalysis& side_effects)
+ : HOptimization(graph, true, "GVN"), side_effects_(side_effects) {}
void Run() OVERRIDE {
- GlobalValueNumberer gvn(graph_->GetArena(), graph_);
+ GlobalValueNumberer gvn(graph_->GetArena(), graph_, side_effects_);
gvn.Run();
}
private:
+ const SideEffectsAnalysis& side_effects_;
+
DISALLOW_COPY_AND_ASSIGN(GVNOptimization);
};