Disambiguate memory accesses in instruction scheduling
Based on aliasing information from heap location collector,
instruction scheduling can further eliminate side-effect
dependencies between memory accesses to different locations,
and perform better scheduling on memory loads and stores.
Performance improvements of this CL, measured on Cortex-A53:
| benchmarks | ARM64 backend | ARM backend |
|----------------+---------------|-------------|
| algorithm | 0.1 % | 0.1 % |
| benchmarksgame | 0.5 % | 1.3 % |
| caffeinemark | 0.0 % | 0.0 % |
| math | 5.1 % | 5.0 % |
| stanford | 1.1 % | 0.6 % |
| testsimd | 0.4 % | 0.1 % |
Compilation time impact is negligible, because this
heap location load store analysis is only performed
on loop basic blocks that get instruction scheduled.
Test: m test-art-host
Test: m test-art-target
Test: 706-checker-scheduler
Change-Id: I43d7003c09bfab9d3a1814715df666aea9a7360b
diff --git a/compiler/optimizing/scheduler.h b/compiler/optimizing/scheduler.h
index 73e8087..930a2c8 100644
--- a/compiler/optimizing/scheduler.h
+++ b/compiler/optimizing/scheduler.h
@@ -21,6 +21,7 @@
#include "base/time_utils.h"
#include "driver/compiler_driver.h"
+#include "load_store_analysis.h"
#include "nodes.h"
#include "optimization.h"
#include "code_generator.h"
@@ -246,7 +247,8 @@
: scheduler_(scheduler),
arena_(arena),
contains_scheduling_barrier_(false),
- nodes_map_(arena_->Adapter(kArenaAllocScheduler)) {}
+ nodes_map_(arena_->Adapter(kArenaAllocScheduler)),
+ heap_location_collector_(nullptr) {}
SchedulingNode* AddNode(HInstruction* instr, bool is_scheduling_barrier = false) {
SchedulingNode* node = new (arena_) SchedulingNode(instr, arena_, is_scheduling_barrier);
@@ -261,6 +263,10 @@
contains_scheduling_barrier_ = false;
}
+ void SetHeapLocationCollector(const HeapLocationCollector& heap_location_collector) {
+ heap_location_collector_ = &heap_location_collector;
+ }
+
SchedulingNode* GetNode(const HInstruction* instr) const {
auto it = nodes_map_.Find(instr);
if (it == nodes_map_.end()) {
@@ -294,6 +300,13 @@
void AddOtherDependency(SchedulingNode* node, SchedulingNode* dependency) {
AddDependency(node, dependency, /*is_data_dependency*/false);
}
+ bool HasMemoryDependency(const HInstruction* node, const HInstruction* other) const;
+ bool HasExceptionDependency(const HInstruction* node, const HInstruction* other) const;
+ bool HasSideEffectDependency(const HInstruction* node, const HInstruction* other) const;
+ bool ArrayAccessMayAlias(const HInstruction* node, const HInstruction* other) const;
+ bool FieldAccessMayAlias(const HInstruction* node, const HInstruction* other) const;
+ size_t ArrayAccessHeapLocation(HInstruction* array, HInstruction* index) const;
+ size_t FieldAccessHeapLocation(HInstruction* obj, const FieldInfo* field) const;
// Add dependencies nodes for the given `HInstruction`: inputs, environments, and side-effects.
void AddDependencies(HInstruction* instruction, bool is_scheduling_barrier = false);
@@ -305,6 +318,8 @@
bool contains_scheduling_barrier_;
ArenaHashMap<const HInstruction*, SchedulingNode*> nodes_map_;
+
+ const HeapLocationCollector* heap_location_collector_;
};
/*
@@ -482,10 +497,9 @@
static constexpr const char* kInstructionScheduling = "scheduler";
+ private:
CodeGenerator* const codegen_;
const InstructionSet instruction_set_;
-
- private:
DISALLOW_COPY_AND_ASSIGN(HInstructionScheduling);
};