summaryrefslogtreecommitdiff
path: root/compiler/optimizing
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/optimizing')
-rw-r--r--compiler/optimizing/gvn.cc9
-rw-r--r--compiler/optimizing/instruction_simplifier.cc3
-rw-r--r--compiler/optimizing/optimization.cc8
-rw-r--r--compiler/optimizing/optimization.h1
-rw-r--r--compiler/optimizing/optimizing_compiler.cc3
5 files changed, 22 insertions, 2 deletions
diff --git a/compiler/optimizing/gvn.cc b/compiler/optimizing/gvn.cc
index cd3b07065c..8a5a4742ba 100644
--- a/compiler/optimizing/gvn.cc
+++ b/compiler/optimizing/gvn.cc
@@ -359,7 +359,8 @@ class GlobalValueNumberer : public ValueObject {
side_effects_(side_effects),
sets_(graph->GetBlocks().size(), nullptr, allocator_.Adapter(kArenaAllocGvn)),
visited_blocks_(
- &allocator_, graph->GetBlocks().size(), /* expandable= */ false, kArenaAllocGvn) {}
+ &allocator_, graph->GetBlocks().size(), /* expandable= */ false, kArenaAllocGvn),
+ did_optimization_(false) {}
bool Run();
@@ -403,6 +404,9 @@ class GlobalValueNumberer : public ValueObject {
// visited/unvisited Boolean.
ArenaBitVector visited_blocks_;
+ // True if GVN did at least one removal.
+ bool did_optimization_;
+
DISALLOW_COPY_AND_ASSIGN(GlobalValueNumberer);
};
@@ -415,7 +419,7 @@ bool GlobalValueNumberer::Run() {
for (HBasicBlock* block : graph_->GetReversePostOrder()) {
VisitBasicBlock(block);
}
- return true;
+ return did_optimization_;
}
void GlobalValueNumberer::VisitBasicBlock(HBasicBlock* block) {
@@ -508,6 +512,7 @@ void GlobalValueNumberer::VisitBasicBlock(HBasicBlock* block) {
// Or current is used by a phi, and we don't do OrderInputs() on a phi anyway.
current->ReplaceWith(existing);
current->GetBlock()->RemoveInstruction(current);
+ did_optimization_ = true;
} else {
set->Kill(current->GetSideEffects());
set->Add(current);
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc
index abc5dae016..931050855c 100644
--- a/compiler/optimizing/instruction_simplifier.cc
+++ b/compiler/optimizing/instruction_simplifier.cc
@@ -709,6 +709,9 @@ bool InstructionSimplifierVisitor::TryReplaceWithRotateRegisterSubPattern(HBinar
void InstructionSimplifierVisitor::VisitNullCheck(HNullCheck* null_check) {
HInstruction* obj = null_check->InputAt(0);
+ // Note we don't do `CanEnsureNotNullAt` here. If we do that, we may get rid of a NullCheck but
+ // what we should do instead is coalesce them. This is what GVN does, and so InstructionSimplifier
+ // doesn't do this.
if (!obj->CanBeNull()) {
null_check->ReplaceWith(obj);
null_check->GetBlock()->RemoveInstruction(null_check);
diff --git a/compiler/optimizing/optimization.cc b/compiler/optimizing/optimization.cc
index ef1f36ab08..bd8fbdf1d2 100644
--- a/compiler/optimizing/optimization.cc
+++ b/compiler/optimizing/optimization.cc
@@ -55,6 +55,7 @@
#include "licm.h"
#include "load_store_elimination.h"
#include "loop_optimization.h"
+#include "reference_type_propagation.h"
#include "scheduler.h"
#include "select_generator.h"
#include "sharpening.h"
@@ -98,6 +99,8 @@ const char* OptimizationPassName(OptimizationPass pass) {
return CodeSinking::kCodeSinkingPassName;
case OptimizationPass::kConstructorFenceRedundancyElimination:
return ConstructorFenceRedundancyElimination::kCFREPassName;
+ case OptimizationPass::kReferenceTypePropagation:
+ return ReferenceTypePropagation::kReferenceTypePropagationPassName;
case OptimizationPass::kScheduling:
return HInstructionScheduling::kInstructionSchedulingPassName;
case OptimizationPass::kWriteBarrierElimination:
@@ -154,6 +157,7 @@ OptimizationPass OptimizationPassByName(const std::string& pass_name) {
X(OptimizationPass::kInvariantCodeMotion);
X(OptimizationPass::kLoadStoreElimination);
X(OptimizationPass::kLoopOptimization);
+ X(OptimizationPass::kReferenceTypePropagation);
X(OptimizationPass::kScheduling);
X(OptimizationPass::kSelectGenerator);
X(OptimizationPass::kSideEffectsAnalysis);
@@ -287,6 +291,10 @@ ArenaVector<HOptimization*> ConstructOptimizations(
case OptimizationPass::kLoadStoreElimination:
opt = new (allocator) LoadStoreElimination(graph, stats, pass_name);
break;
+ case OptimizationPass::kReferenceTypePropagation:
+ opt = new (allocator) ReferenceTypePropagation(
+ graph, dex_compilation_unit.GetDexCache(), /* is_first_run= */ false, pass_name);
+ break;
case OptimizationPass::kWriteBarrierElimination:
opt = new (allocator) WriteBarrierElimination(graph, stats, pass_name);
break;
diff --git a/compiler/optimizing/optimization.h b/compiler/optimizing/optimization.h
index 8bc9da49fc..abc4361b44 100644
--- a/compiler/optimizing/optimization.h
+++ b/compiler/optimizing/optimization.h
@@ -81,6 +81,7 @@ enum class OptimizationPass {
kInvariantCodeMotion,
kLoadStoreElimination,
kLoopOptimization,
+ kReferenceTypePropagation,
kScheduling,
kSelectGenerator,
kSideEffectsAnalysis,
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index 89edbed54d..b15657355f 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -665,6 +665,9 @@ void OptimizingCompiler::RunOptimizations(HGraph* graph,
OptDef(OptimizationPass::kSideEffectsAnalysis,
"side_effects$before_gvn"),
OptDef(OptimizationPass::kGlobalValueNumbering),
+ OptDef(OptimizationPass::kReferenceTypePropagation,
+ "reference_type_propagation$after_gvn",
+ OptimizationPass::kGlobalValueNumbering),
// Simplification (TODO: only if GVN occurred).
OptDef(OptimizationPass::kSelectGenerator),
OptDef(OptimizationPass::kConstantFolding,