summaryrefslogtreecommitdiffstats
path: root/compiler/optimizing/code_generator.cc
diff options
context:
space:
mode:
authorNicolas Geoffray <ngeoffray@google.com>2014-04-28 17:47:12 +0100
committerNicolas Geoffray <ngeoffray@google.com>2014-04-29 10:55:30 +0100
commita7aca370a7d62ca04a1e24423d90e8020d6f1a58 (patch)
tree65d501b0f9711abddbea1a9d06623baafa4ae2b3 /compiler/optimizing/code_generator.cc
parent5dee5df89aa2cefef6c886d5b9b642cc6f1c595b (diff)
downloadart-a7aca370a7d62ca04a1e24423d90e8020d6f1a58.zip
art-a7aca370a7d62ca04a1e24423d90e8020d6f1a58.tar.gz
art-a7aca370a7d62ca04a1e24423d90e8020d6f1a58.tar.bz2
Setup policies for register allocation.
Change-Id: I857e77530fca3e2fb872fc142a916af1b48400dc
Diffstat (limited to 'compiler/optimizing/code_generator.cc')
-rw-r--r--compiler/optimizing/code_generator.cc100
1 files changed, 98 insertions, 2 deletions
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index babb1f5..ff316e5 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -55,9 +55,105 @@ void CodeGenerator::CompileBlock(HBasicBlock* block) {
}
}
+size_t CodeGenerator::AllocateFreeRegisterInternal(
+ bool* blocked_registers, size_t number_of_registers) const {
+ for (size_t regno = 0; regno < number_of_registers; regno++) {
+ if (!blocked_registers[regno]) {
+ blocked_registers[regno] = true;
+ return regno;
+ }
+ }
+ LOG(FATAL) << "Unreachable";
+ return -1;
+}
+
+
+void CodeGenerator::AllocateRegistersLocally(HInstruction* instruction) const {
+ LocationSummary* locations = instruction->GetLocations();
+ if (locations == nullptr) return;
+
+ for (size_t i = 0, e = GetNumberOfRegisters(); i < e; ++i) {
+ blocked_registers_[i] = false;
+ }
+
+ // Mark all fixed input, temp and output registers as used.
+ for (size_t i = 0, e = locations->GetInputCount(); i < e; ++i) {
+ Location loc = locations->InAt(i);
+ if (loc.IsRegister()) {
+ // Check that a register is not specified twice in the summary.
+ DCHECK(!blocked_registers_[loc.GetEncoding()]);
+ blocked_registers_[loc.GetEncoding()] = true;
+ }
+ }
+
+ for (size_t i = 0, e = locations->GetTempCount(); i < e; ++i) {
+ Location loc = locations->GetTemp(i);
+ if (loc.IsRegister()) {
+ // Check that a register is not specified twice in the summary.
+ DCHECK(!blocked_registers_[loc.GetEncoding()]);
+ blocked_registers_[loc.GetEncoding()] = true;
+ }
+ }
+
+ SetupBlockedRegisters(blocked_registers_);
+
+ // Allocate all unallocated input locations.
+ for (size_t i = 0, e = locations->GetInputCount(); i < e; ++i) {
+ Location loc = locations->InAt(i);
+ HInstruction* input = instruction->InputAt(i);
+ if (loc.IsUnallocated()) {
+ if (loc.GetPolicy() == Location::kRequiresRegister) {
+ loc = Location::RegisterLocation(
+ AllocateFreeRegister(input->GetType(), blocked_registers_));
+ } else {
+ DCHECK_EQ(loc.GetPolicy(), Location::kAny);
+ HLoadLocal* load = input->AsLoadLocal();
+ if (load != nullptr) {
+ loc = GetStackLocation(load);
+ } else {
+ loc = Location::RegisterLocation(
+ AllocateFreeRegister(input->GetType(), blocked_registers_));
+ }
+ }
+ locations->SetInAt(i, loc);
+ }
+ }
+
+ // Allocate all unallocated temp locations.
+ for (size_t i = 0, e = locations->GetTempCount(); i < e; ++i) {
+ Location loc = locations->GetTemp(i);
+ if (loc.IsUnallocated()) {
+ DCHECK_EQ(loc.GetPolicy(), Location::kRequiresRegister);
+ // TODO: Adjust handling of temps. We currently consider temps to use
+ // core registers. They may also use floating point registers at some point.
+ loc = Location::RegisterLocation(static_cast<ManagedRegister>(
+ AllocateFreeRegister(Primitive::kPrimInt, blocked_registers_)));
+ locations->SetTempAt(i, loc);
+ }
+ }
+
+ Location result_location = locations->Out();
+ if (result_location.IsUnallocated()) {
+ switch (result_location.GetPolicy()) {
+ case Location::kAny:
+ case Location::kRequiresRegister:
+ result_location = Location::RegisterLocation(
+ AllocateFreeRegister(instruction->GetType(), blocked_registers_));
+ break;
+ case Location::kSameAsFirstInput:
+ result_location = locations->InAt(0);
+ break;
+ }
+ locations->SetOut(result_location);
+ }
+}
+
void CodeGenerator::InitLocations(HInstruction* instruction) {
- if (instruction->GetLocations() == nullptr) return;
- for (size_t i = 0; i < instruction->InputCount(); i++) {
+ if (instruction->GetLocations() == nullptr) {
+ return;
+ }
+ AllocateRegistersLocally(instruction);
+ for (size_t i = 0, e = instruction->InputCount(); i < e; ++i) {
Location location = instruction->GetLocations()->InAt(i);
if (location.IsValid()) {
// Move the input to the desired location.