summaryrefslogtreecommitdiff
path: root/compiler/optimizing/parallel_move_resolver.cc
diff options
context:
space:
mode:
author Nicolas Geoffray <ngeoffray@google.com> 2014-06-04 11:12:39 +0100
committer Nicolas Geoffray <ngeoffray@google.com> 2014-06-12 10:02:06 +0100
commit86dbb9a12119273039ce272b41c809fa548b37b6 (patch)
treea4626e21ae16a9a5e133ea3e5e95b58d2ea4d8e5 /compiler/optimizing/parallel_move_resolver.cc
parentc936622863a50bdda9b10062515dfc02a8c8b652 (diff)
Final CL to enable register allocation on x86.
This CL implements: 1) Resolution after allocation: connecting the locations allocated to an interval within a block and between blocks. 2) Handling of fixed registers: some instructions require inputs/output to be at a specific location, and the allocator needs to deal with them in a special way. 3) ParallelMoveResolver::EmitNativeCode for x86. Change-Id: I0da6bd7eb66877987148b87c3be6a983b4e3f858
Diffstat (limited to 'compiler/optimizing/parallel_move_resolver.cc')
-rw-r--r--compiler/optimizing/parallel_move_resolver.cc60
1 files changed, 60 insertions, 0 deletions
diff --git a/compiler/optimizing/parallel_move_resolver.cc b/compiler/optimizing/parallel_move_resolver.cc
index 3d2d136ec3..4a1b6ce446 100644
--- a/compiler/optimizing/parallel_move_resolver.cc
+++ b/compiler/optimizing/parallel_move_resolver.cc
@@ -147,4 +147,64 @@ void ParallelMoveResolver::PerformMove(size_t index) {
}
}
+bool ParallelMoveResolver::IsScratchLocation(Location loc) {
+ for (size_t i = 0; i < moves_.Size(); ++i) {
+ if (moves_.Get(i)->Blocks(loc)) {
+ return false;
+ }
+ }
+
+ for (size_t i = 0; i < moves_.Size(); ++i) {
+ if (moves_.Get(i)->GetDestination().Equals(loc)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+int ParallelMoveResolver::AllocateScratchRegister(int blocked, int register_count, bool* spilled) {
+ int scratch = -1;
+ for (int reg = 0; reg < register_count; ++reg) {
+ if ((blocked != reg) &&
+ IsScratchLocation(Location::RegisterLocation(ManagedRegister(reg)))) {
+ scratch = reg;
+ break;
+ }
+ }
+
+ if (scratch == -1) {
+ *spilled = true;
+ for (int reg = 0; reg < register_count; ++reg) {
+ if (blocked != reg) {
+ scratch = reg;
+ }
+ }
+ } else {
+ *spilled = false;
+ }
+
+ return scratch;
+}
+
+
+ParallelMoveResolver::ScratchRegisterScope::ScratchRegisterScope(
+ ParallelMoveResolver* resolver, int blocked, int number_of_registers)
+ : resolver_(resolver),
+ reg_(kNoRegister),
+ spilled_(false) {
+ reg_ = resolver_->AllocateScratchRegister(blocked, number_of_registers, &spilled_);
+
+ if (spilled_) {
+ resolver->SpillScratch(reg_);
+ }
+}
+
+
+ParallelMoveResolver::ScratchRegisterScope::~ScratchRegisterScope() {
+ if (spilled_) {
+ resolver_->RestoreScratch(reg_);
+ }
+}
+
} // namespace art