summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/common_compiler_test.cc1
-rw-r--r--compiler/common_compiler_test.h1
-rw-r--r--compiler/oat_test.cc3
-rw-r--r--compiler/optimizing/optimizing_compiler.cc9
-rw-r--r--compiler/optimizing/optimizing_compiler_stats.h18
-rw-r--r--compiler/optimizing/register_allocator.cc83
-rw-r--r--compiler/optimizing/register_allocator.h7
-rw-r--r--compiler/optimizing/ssa_liveness_analysis.cc2
-rw-r--r--compiler/optimizing/ssa_liveness_analysis.h19
9 files changed, 78 insertions, 65 deletions
diff --git a/compiler/common_compiler_test.cc b/compiler/common_compiler_test.cc
index 257406a622..1d0aad5425 100644
--- a/compiler/common_compiler_test.cc
+++ b/compiler/common_compiler_test.cc
@@ -180,7 +180,6 @@ void CommonCompilerTest::SetUpRuntimeOptions(RuntimeOptions* options) {
callbacks_.reset(new QuickCompilerCallbacks(verification_results_.get(),
method_inliner_map_.get(),
CompilerCallbacks::CallbackMode::kCompileApp));
- options->push_back(std::make_pair("compilercallbacks", callbacks_.get()));
}
void CommonCompilerTest::TearDown() {
diff --git a/compiler/common_compiler_test.h b/compiler/common_compiler_test.h
index 9cffbc86f3..d7b210d571 100644
--- a/compiler/common_compiler_test.h
+++ b/compiler/common_compiler_test.h
@@ -78,7 +78,6 @@ class CommonCompilerTest : public CommonRuntimeTest {
std::unique_ptr<CompilerOptions> compiler_options_;
std::unique_ptr<VerificationResults> verification_results_;
std::unique_ptr<DexFileToMethodInlinerMap> method_inliner_map_;
- std::unique_ptr<CompilerCallbacks> callbacks_;
std::unique_ptr<CompilerDriver> compiler_driver_;
std::unique_ptr<CumulativeLogger> timer_;
std::unique_ptr<const InstructionSetFeatures> instruction_set_features_;
diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc
index d59ad6c32f..afd39e8874 100644
--- a/compiler/oat_test.cc
+++ b/compiler/oat_test.cc
@@ -85,9 +85,6 @@ TEST_F(OatTest, WriteRead) {
compiler_options_.reset(new CompilerOptions);
verification_results_.reset(new VerificationResults(compiler_options_.get()));
method_inliner_map_.reset(new DexFileToMethodInlinerMap);
- callbacks_.reset(new QuickCompilerCallbacks(verification_results_.get(),
- method_inliner_map_.get(),
- CompilerCallbacks::CallbackMode::kCompileApp));
timer_.reset(new CumulativeLogger("Compilation times"));
compiler_driver_.reset(new CompilerDriver(compiler_options_.get(),
verification_results_.get(),
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index 5ce73baef2..b2f9c65153 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -583,8 +583,13 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item,
if (method != nullptr) {
return method;
}
- return delegate_->Compile(code_item, access_flags, invoke_type, class_def_idx, method_idx,
- class_loader, dex_file);
+ method = delegate_->Compile(code_item, access_flags, invoke_type, class_def_idx, method_idx,
+ class_loader, dex_file);
+
+ if (method != nullptr) {
+ compilation_stats_.RecordStat(MethodCompilationStat::kCompiledQuick);
+ }
+ return method;
}
Compiler* CreateOptimizingCompiler(CompilerDriver* driver) {
diff --git a/compiler/optimizing/optimizing_compiler_stats.h b/compiler/optimizing/optimizing_compiler_stats.h
index 22ec2a5167..b97a66719d 100644
--- a/compiler/optimizing/optimizing_compiler_stats.h
+++ b/compiler/optimizing/optimizing_compiler_stats.h
@@ -28,6 +28,7 @@ enum MethodCompilationStat {
kAttemptCompilation = 0,
kCompiledBaseline,
kCompiledOptimized,
+ kCompiledQuick,
kInlinedInvoke,
kNotCompiledUnsupportedIsa,
kNotCompiledPathological,
@@ -65,16 +66,22 @@ class OptimizingCompilerStats {
compile_stats_[kCompiledBaseline] * 100 / compile_stats_[kAttemptCompilation];
size_t optimized_percent =
compile_stats_[kCompiledOptimized] * 100 / compile_stats_[kAttemptCompilation];
+ size_t quick_percent =
+ compile_stats_[kCompiledQuick] * 100 / compile_stats_[kAttemptCompilation];
std::ostringstream oss;
- oss << "Attempted compilation of " << compile_stats_[kAttemptCompilation] << " methods: "
- << unoptimized_percent << "% (" << compile_stats_[kCompiledBaseline] << ") unoptimized, "
- << optimized_percent << "% (" << compile_stats_[kCompiledOptimized] << ") optimized.";
+ oss << "Attempted compilation of " << compile_stats_[kAttemptCompilation] << " methods: ";
+
+ oss << unoptimized_percent << "% (" << compile_stats_[kCompiledBaseline] << ") unoptimized, ";
+ oss << optimized_percent << "% (" << compile_stats_[kCompiledOptimized] << ") optimized, ";
+ oss << quick_percent << "% (" << compile_stats_[kCompiledQuick] << ") quick.";
+
+ LOG(INFO) << oss.str();
+
for (int i = 0; i < kLastStat; i++) {
if (compile_stats_[i] != 0) {
- oss << "\n" << PrintMethodCompilationStat(i) << ": " << compile_stats_[i];
+ VLOG(compiler) << PrintMethodCompilationStat(i) << ": " << compile_stats_[i];
}
}
- LOG(INFO) << oss.str();
}
}
@@ -84,6 +91,7 @@ class OptimizingCompilerStats {
case kAttemptCompilation : return "kAttemptCompilation";
case kCompiledBaseline : return "kCompiledBaseline";
case kCompiledOptimized : return "kCompiledOptimized";
+ case kCompiledQuick : return "kCompiledQuick";
case kInlinedInvoke : return "kInlinedInvoke";
case kNotCompiledUnsupportedIsa : return "kNotCompiledUnsupportedIsa";
case kNotCompiledPathological : return "kNotCompiledPathological";
diff --git a/compiler/optimizing/register_allocator.cc b/compiler/optimizing/register_allocator.cc
index cecc210cbf..cf38bd3f8c 100644
--- a/compiler/optimizing/register_allocator.cc
+++ b/compiler/optimizing/register_allocator.cc
@@ -213,7 +213,7 @@ void RegisterAllocator::ProcessInstruction(HInstruction* instruction) {
LiveInterval* interval =
LiveInterval::MakeTempInterval(allocator_, Primitive::kPrimInt);
temp_intervals_.Add(interval);
- interval->AddRange(position, position + 1);
+ interval->AddTempUse(instruction, i);
unhandled_core_intervals_.Add(interval);
break;
}
@@ -222,7 +222,7 @@ void RegisterAllocator::ProcessInstruction(HInstruction* instruction) {
LiveInterval* interval =
LiveInterval::MakeTempInterval(allocator_, Primitive::kPrimDouble);
temp_intervals_.Add(interval);
- interval->AddRange(position, position + 1);
+ interval->AddTempUse(instruction, i);
if (codegen_->NeedsTwoRegisters(Primitive::kPrimDouble)) {
interval->AddHighInterval(true);
LiveInterval* high = interval->GetHighInterval();
@@ -851,6 +851,23 @@ bool RegisterAllocator::TrySplitNonPairOrUnalignedPairIntervalAt(size_t position
return false;
}
+bool RegisterAllocator::PotentiallyRemoveOtherHalf(LiveInterval* interval,
+ GrowableArray<LiveInterval*>* intervals,
+ size_t index) {
+ if (interval->IsLowInterval()) {
+ DCHECK_EQ(intervals->Get(index), interval->GetHighInterval());
+ intervals->DeleteAt(index);
+ return true;
+ } else if (interval->IsHighInterval()) {
+ DCHECK_GT(index, 0u);
+ DCHECK_EQ(intervals->Get(index - 1), interval->GetLowInterval());
+ intervals->DeleteAt(index - 1);
+ return true;
+ } else {
+ return false;
+ }
+}
+
// Find the register that is used the last, and spill the interval
// that holds it. If the first use of `current` is after that register
// we spill `current` instead.
@@ -974,33 +991,17 @@ bool RegisterAllocator::AllocateBlockedReg(LiveInterval* current) {
if (active->GetRegister() == reg) {
DCHECK(!active->IsFixed());
LiveInterval* split = Split(active, current->GetStart());
- active_.DeleteAt(i);
if (split != active) {
handled_.Add(active);
}
+ active_.DeleteAt(i);
+ PotentiallyRemoveOtherHalf(active, &active_, i);
AddSorted(unhandled_, split);
-
- if (active->IsLowInterval() || active->IsHighInterval()) {
- LiveInterval* other_half = active->IsLowInterval()
- ? active->GetHighInterval()
- : active->GetLowInterval();
- // We also need to remove the other half from the list of actives.
- bool found = false;
- for (size_t j = 0; j < active_.Size(); ++j) {
- if (active_.Get(j) == other_half) {
- found = true;
- active_.DeleteAt(j);
- handled_.Add(other_half);
- break;
- }
- }
- DCHECK(found);
- }
break;
}
}
- for (size_t i = 0, e = inactive_.Size(); i < e; ++i) {
+ for (size_t i = 0; i < inactive_.Size(); ++i) {
LiveInterval* inactive = inactive_.Get(i);
if (inactive->GetRegister() == reg) {
if (!current->IsSplit() && !inactive->IsFixed()) {
@@ -1024,29 +1025,14 @@ bool RegisterAllocator::AllocateBlockedReg(LiveInterval* current) {
// If it's inactive, it must start before the current interval.
DCHECK_NE(split, inactive);
inactive_.DeleteAt(i);
+ if (PotentiallyRemoveOtherHalf(inactive, &inactive_, i) && inactive->IsHighInterval()) {
+ // We have removed an entry prior to `inactive`. So we need to decrement.
+ --i;
+ }
+ // Decrement because we have removed `inactive` from the list.
--i;
- --e;
handled_.Add(inactive);
AddSorted(unhandled_, split);
-
- if (inactive->IsLowInterval() || inactive->IsHighInterval()) {
- LiveInterval* other_half = inactive->IsLowInterval()
- ? inactive->GetHighInterval()
- : inactive->GetLowInterval();
-
- // We also need to remove the other half from the list of inactives.
- bool found = false;
- for (size_t j = 0; j < inactive_.Size(); ++j) {
- if (inactive_.Get(j) == other_half) {
- found = true;
- inactive_.DeleteAt(j);
- --e;
- handled_.Add(other_half);
- break;
- }
- }
- DCHECK(found);
- }
}
}
}
@@ -1695,8 +1681,6 @@ void RegisterAllocator::Resolve() {
}
// Assign temp locations.
- HInstruction* current = nullptr;
- size_t temp_index = 0;
for (size_t i = 0; i < temp_intervals_.Size(); ++i) {
LiveInterval* temp = temp_intervals_.Get(i);
if (temp->IsHighInterval()) {
@@ -1704,25 +1688,20 @@ void RegisterAllocator::Resolve() {
continue;
}
HInstruction* at = liveness_.GetTempUser(temp);
- if (at != current) {
- temp_index = 0;
- current = at;
- }
+ size_t temp_index = liveness_.GetTempIndex(temp);
LocationSummary* locations = at->GetLocations();
switch (temp->GetType()) {
case Primitive::kPrimInt:
- locations->SetTempAt(
- temp_index++, Location::RegisterLocation(temp->GetRegister()));
+ locations->SetTempAt(temp_index, Location::RegisterLocation(temp->GetRegister()));
break;
case Primitive::kPrimDouble:
if (codegen_->NeedsTwoRegisters(Primitive::kPrimDouble)) {
Location location = Location::FpuRegisterPairLocation(
temp->GetRegister(), temp->GetHighInterval()->GetRegister());
- locations->SetTempAt(temp_index++, location);
+ locations->SetTempAt(temp_index, location);
} else {
- locations->SetTempAt(
- temp_index++, Location::FpuRegisterLocation(temp->GetRegister()));
+ locations->SetTempAt(temp_index, Location::FpuRegisterLocation(temp->GetRegister()));
}
break;
diff --git a/compiler/optimizing/register_allocator.h b/compiler/optimizing/register_allocator.h
index fcc61128a6..717be75533 100644
--- a/compiler/optimizing/register_allocator.h
+++ b/compiler/optimizing/register_allocator.h
@@ -144,6 +144,13 @@ class RegisterAllocator {
size_t first_register_use,
size_t* next_use);
+ // If `interval` has another half, remove it from the list of `intervals`.
+ // `index` holds the index at which `interval` is in `intervals`.
+ // Returns whether there is another half.
+ bool PotentiallyRemoveOtherHalf(LiveInterval* interval,
+ GrowableArray<LiveInterval*>* intervals,
+ size_t index);
+
ArenaAllocator* const allocator_;
CodeGenerator* const codegen_;
const SsaLivenessAnalysis& liveness_;
diff --git a/compiler/optimizing/ssa_liveness_analysis.cc b/compiler/optimizing/ssa_liveness_analysis.cc
index 56ccd717cf..0f3973e5fb 100644
--- a/compiler/optimizing/ssa_liveness_analysis.cc
+++ b/compiler/optimizing/ssa_liveness_analysis.cc
@@ -318,6 +318,8 @@ static int RegisterOrLowRegister(Location location) {
int LiveInterval::FindFirstRegisterHint(size_t* free_until) const {
DCHECK(!IsHighInterval());
+ if (IsTemp()) return kNoRegister;
+
if (GetParent() == this && defined_by_ != nullptr) {
// This is the first interval for the instruction. Try to find
// a register based on its definition.
diff --git a/compiler/optimizing/ssa_liveness_analysis.h b/compiler/optimizing/ssa_liveness_analysis.h
index b57029d1a7..bc78dc2e76 100644
--- a/compiler/optimizing/ssa_liveness_analysis.h
+++ b/compiler/optimizing/ssa_liveness_analysis.h
@@ -180,6 +180,15 @@ class LiveInterval : public ArenaObject<kArenaAllocMisc> {
// This interval is the result of a split.
bool IsSplit() const { return parent_ != this; }
+ void AddTempUse(HInstruction* instruction, size_t temp_index) {
+ DCHECK(IsTemp());
+ DCHECK(first_use_ == nullptr) << "A temporary can only have one user";
+ size_t position = instruction->GetLifetimePosition();
+ first_use_ = new (allocator_) UsePosition(
+ instruction, temp_index, /* is_environment */ false, position, first_use_);
+ AddRange(position, position + 1);
+ }
+
void AddUse(HInstruction* instruction, size_t input_index, bool is_environment) {
// Set the use within the instruction.
size_t position = instruction->GetLifetimePosition() + 1;
@@ -856,7 +865,15 @@ class SsaLivenessAnalysis : public ValueObject {
HInstruction* GetTempUser(LiveInterval* temp) const {
// A temporary shares the same lifetime start as the instruction that requires it.
DCHECK(temp->IsTemp());
- return GetInstructionFromPosition(temp->GetStart() / 2);
+ HInstruction* user = GetInstructionFromPosition(temp->GetStart() / 2);
+ DCHECK_EQ(user, temp->GetFirstUse()->GetUser());
+ return user;
+ }
+
+ size_t GetTempIndex(LiveInterval* temp) const {
+ // We use the input index to store the index of the temporary in the user's temporary list.
+ DCHECK(temp->IsTemp());
+ return temp->GetFirstUse()->GetInputIndex();
}
size_t GetMaxLifetimePosition() const {