summaryrefslogtreecommitdiff
path: root/compiler/optimizing/scheduler.cc
diff options
context:
space:
mode:
author Alex Light <allight@google.com> 2020-11-02 08:48:33 -0800
committer Alex Light <allight@google.com> 2021-01-21 17:58:10 +0000
commitb8686ce4c93eba7192ed7ef89e7ffd9f3aa6cd07 (patch)
tree1721ee940f978736a2212d693271ee698897cb0b /compiler/optimizing/scheduler.cc
parent625048049558d394d50b6e98885b8c210e481bf1 (diff)
Partial Load Store Elimination
Add partial load-store elimination to the LSE pass. Partial LSE will move object allocations which only escape along certain execution paths closer to the escape point and allow more values to be eliminated. It does this by creating new predicated load and store instructions that are used when an object has only escaped some of the time. In cases where the object has not escaped a default value will be used. Test: ./test.py --host Test: ./test.py --target Bug: 67037140 Change-Id: Idde67eb59ec90de79747cde17b552eec05b58497
Diffstat (limited to 'compiler/optimizing/scheduler.cc')
-rw-r--r--compiler/optimizing/scheduler.cc82
1 files changed, 38 insertions, 44 deletions
diff --git a/compiler/optimizing/scheduler.cc b/compiler/optimizing/scheduler.cc
index c1891de69a..7140e2424a 100644
--- a/compiler/optimizing/scheduler.cc
+++ b/compiler/optimizing/scheduler.cc
@@ -14,13 +14,14 @@
* limitations under the License.
*/
-#include <string>
-
#include "scheduler.h"
+#include <string>
+
#include "base/scoped_arena_allocator.h"
#include "base/scoped_arena_containers.h"
#include "data_type-inl.h"
+#include "optimizing/load_store_analysis.h"
#include "prepare_for_register_allocation.h"
#ifdef ART_ENABLE_CODEGEN_arm64
@@ -107,6 +108,7 @@ static bool IsArrayAccess(const HInstruction* instruction) {
static bool IsInstanceFieldAccess(const HInstruction* instruction) {
return instruction->IsInstanceFieldGet() ||
instruction->IsInstanceFieldSet() ||
+ instruction->IsPredicatedInstanceFieldGet() ||
instruction->IsUnresolvedInstanceFieldGet() ||
instruction->IsUnresolvedInstanceFieldSet();
}
@@ -121,6 +123,7 @@ static bool IsStaticFieldAccess(const HInstruction* instruction) {
static bool IsResolvedFieldAccess(const HInstruction* instruction) {
return instruction->IsInstanceFieldGet() ||
instruction->IsInstanceFieldSet() ||
+ instruction->IsPredicatedInstanceFieldGet() ||
instruction->IsStaticFieldGet() ||
instruction->IsStaticFieldSet();
}
@@ -137,18 +140,7 @@ static bool IsFieldAccess(const HInstruction* instruction) {
}
static const FieldInfo* GetFieldInfo(const HInstruction* instruction) {
- if (instruction->IsInstanceFieldGet()) {
- return &instruction->AsInstanceFieldGet()->GetFieldInfo();
- } else if (instruction->IsInstanceFieldSet()) {
- return &instruction->AsInstanceFieldSet()->GetFieldInfo();
- } else if (instruction->IsStaticFieldGet()) {
- return &instruction->AsStaticFieldGet()->GetFieldInfo();
- } else if (instruction->IsStaticFieldSet()) {
- return &instruction->AsStaticFieldSet()->GetFieldInfo();
- } else {
- LOG(FATAL) << "Unexpected field access type";
- UNREACHABLE();
- }
+ return &instruction->GetFieldInfo();
}
size_t SideEffectDependencyAnalysis::MemoryDependencyAnalysis::FieldAccessHeapLocation(
@@ -560,7 +552,7 @@ void HScheduler::Schedule(HGraph* graph) {
// should run the analysis or not.
const HeapLocationCollector* heap_location_collector = nullptr;
ScopedArenaAllocator allocator(graph->GetArenaStack());
- LoadStoreAnalysis lsa(graph, /*stats=*/nullptr, &allocator, /*for_elimination=*/false);
+ LoadStoreAnalysis lsa(graph, /*stats=*/nullptr, &allocator, LoadStoreAnalysisType::kBasic);
if (!only_optimize_loop_blocks_ || graph->HasLoops()) {
lsa.Run();
heap_location_collector = &lsa.GetHeapLocationCollector();
@@ -730,35 +722,37 @@ bool HScheduler::IsSchedulable(const HInstruction* instruction) const {
// TODO: Some of the instructions above may be safe to schedule (maybe as
// scheduling barriers).
return instruction->IsArrayGet() ||
- instruction->IsArraySet() ||
- instruction->IsArrayLength() ||
- instruction->IsBoundType() ||
- instruction->IsBoundsCheck() ||
- instruction->IsCheckCast() ||
- instruction->IsClassTableGet() ||
- instruction->IsCurrentMethod() ||
- instruction->IsDivZeroCheck() ||
- (instruction->IsInstanceFieldGet() && !instruction->AsInstanceFieldGet()->IsVolatile()) ||
- (instruction->IsInstanceFieldSet() && !instruction->AsInstanceFieldSet()->IsVolatile()) ||
- instruction->IsInstanceOf() ||
- instruction->IsInvokeInterface() ||
- instruction->IsInvokeStaticOrDirect() ||
- instruction->IsInvokeUnresolved() ||
- instruction->IsInvokeVirtual() ||
- instruction->IsLoadString() ||
- instruction->IsNewArray() ||
- instruction->IsNewInstance() ||
- instruction->IsNullCheck() ||
- instruction->IsPackedSwitch() ||
- instruction->IsParameterValue() ||
- instruction->IsPhi() ||
- instruction->IsReturn() ||
- instruction->IsReturnVoid() ||
- instruction->IsSelect() ||
- (instruction->IsStaticFieldGet() && !instruction->AsStaticFieldGet()->IsVolatile()) ||
- (instruction->IsStaticFieldSet() && !instruction->AsStaticFieldSet()->IsVolatile()) ||
- instruction->IsSuspendCheck() ||
- instruction->IsTypeConversion();
+ instruction->IsArraySet() ||
+ instruction->IsArrayLength() ||
+ instruction->IsBoundType() ||
+ instruction->IsBoundsCheck() ||
+ instruction->IsCheckCast() ||
+ instruction->IsClassTableGet() ||
+ instruction->IsCurrentMethod() ||
+ instruction->IsDivZeroCheck() ||
+ (instruction->IsInstanceFieldGet() && !instruction->AsInstanceFieldGet()->IsVolatile()) ||
+ (instruction->IsPredicatedInstanceFieldGet() &&
+ !instruction->AsPredicatedInstanceFieldGet()->IsVolatile()) ||
+ (instruction->IsInstanceFieldSet() && !instruction->AsInstanceFieldSet()->IsVolatile()) ||
+ instruction->IsInstanceOf() ||
+ instruction->IsInvokeInterface() ||
+ instruction->IsInvokeStaticOrDirect() ||
+ instruction->IsInvokeUnresolved() ||
+ instruction->IsInvokeVirtual() ||
+ instruction->IsLoadString() ||
+ instruction->IsNewArray() ||
+ instruction->IsNewInstance() ||
+ instruction->IsNullCheck() ||
+ instruction->IsPackedSwitch() ||
+ instruction->IsParameterValue() ||
+ instruction->IsPhi() ||
+ instruction->IsReturn() ||
+ instruction->IsReturnVoid() ||
+ instruction->IsSelect() ||
+ (instruction->IsStaticFieldGet() && !instruction->AsStaticFieldGet()->IsVolatile()) ||
+ (instruction->IsStaticFieldSet() && !instruction->AsStaticFieldSet()->IsVolatile()) ||
+ instruction->IsSuspendCheck() ||
+ instruction->IsTypeConversion();
}
bool HScheduler::IsSchedulable(const HBasicBlock* block) const {