From b0abc4e1e50b7c68768e68673e8f9634d314880a Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Wed, 13 Feb 2013 16:49:46 -0700 Subject: [PATCH] further split up compiler.cpp --- makefile | 3 +- src/codegen/compiler.cpp | 705 +----------------------------- src/codegen/compiler/context.h | 5 +- src/codegen/compiler/read.h | 46 ++ src/codegen/compiler/regalloc.cpp | 301 +++++++++++++ src/codegen/compiler/regalloc.h | 106 +++++ src/codegen/compiler/resource.cpp | 66 +++ src/codegen/compiler/resource.h | 4 + src/codegen/compiler/site.cpp | 273 ++++++++++++ src/codegen/compiler/site.h | 57 +++ src/codegen/compiler/value.cpp | 43 ++ src/codegen/compiler/value.h | 13 +- src/codegen/regalloc.cpp | 24 - src/codegen/regalloc.h | 37 -- 14 files changed, 916 insertions(+), 767 deletions(-) create mode 100644 src/codegen/compiler/read.h create mode 100644 src/codegen/compiler/regalloc.cpp create mode 100644 src/codegen/compiler/regalloc.h create mode 100644 src/codegen/compiler/value.cpp delete mode 100644 src/codegen/regalloc.cpp delete mode 100644 src/codegen/regalloc.h diff --git a/makefile b/makefile index a408804b29..9f57682239 100755 --- a/makefile +++ b/makefile @@ -953,10 +953,11 @@ embed-objects = $(call cpp-objects,$(embed-sources),$(src),$(build-embed)) ifeq ($(process),compile) vm-sources += \ $(src)/codegen/compiler.cpp \ - $(src)/codegen/regalloc.cpp \ $(src)/codegen/compiler/context.cpp \ $(src)/codegen/compiler/resource.cpp \ $(src)/codegen/compiler/site.cpp \ + $(src)/codegen/compiler/regalloc.cpp \ + $(src)/codegen/compiler/value.cpp \ $(src)/codegen/registers.cpp \ $(src)/codegen/targets.cpp diff --git a/src/codegen/compiler.cpp b/src/codegen/compiler.cpp index d07caa4e7d..7b63548c42 100644 --- a/src/codegen/compiler.cpp +++ b/src/codegen/compiler.cpp @@ -14,12 +14,13 @@ #include "codegen/compiler.h" #include "codegen/assembler.h" -#include "codegen/regalloc.h" +#include "codegen/compiler/regalloc.h" #include "codegen/compiler/context.h" #include "codegen/compiler/resource.h" #include "codegen/compiler/value.h" #include "codegen/compiler/site.h" +#include "codegen/compiler/read.h" using namespace vm; @@ -156,29 +157,6 @@ class ConstantPoolNode { ConstantPoolNode* next; }; -class Read { - public: - Read(): - value(0), event(0), eventNext(0) - { } - - virtual bool intersect(SiteMask* mask, unsigned depth = 0) = 0; - - virtual Value* high(Context* c) { abort(c); } - - virtual Value* successor() = 0; - - virtual bool valid() = 0; - - virtual void append(Context* c, Read* r) = 0; - - virtual Read* next(Context* c) = 0; - - Value* value; - Event* event; - Read* eventNext; -}; - int intersectFrameIndexes(int a, int b) { @@ -524,15 +502,6 @@ hasSite(Context* c, Value* v) return it.hasMore(); } -bool -findSite(Context*, Value* v, Site* site) -{ - for (Site* s = v->sites; s; s = s->next) { - if (s == site) return true; - } - return false; -} - bool uniqueSite(Context* c, Value* v, Site* s) { @@ -561,7 +530,7 @@ uniqueSite(Context* c, Value* v, Site* s) void addSite(Context* c, Value* v, Site* s) { - if (not findSite(c, v, s)) { + if (not v->findSite(s)) { if (DebugSites) { char buffer[256]; s->toString(c, buffer, 256); fprintf(stderr, "add site %s to %p\n", buffer, v); @@ -588,7 +557,7 @@ removeSite(Context* c, Value* v, Site* s) if (DebugSites) { fprintf(stderr, "%p has more: %d\n", v, hasSite(c, v)); } - assert(c, not findSite(c, v, s)); + assert(c, not v->findSite(s)); } void @@ -745,16 +714,6 @@ popRead(Context* c, Event* e UNUSED, Value* v) } } -bool -buddies(Value* a, Value* b) -{ - if (a == b) return true; - for (Value* p = a->buddy; p != a; p = p->buddy) { - if (p == b) return true; - } - return false; -} - void addBuddy(Value* original, Value* buddy) { @@ -772,27 +731,6 @@ addBuddy(Value* original, Value* buddy) } } -class Target { - public: - static const unsigned MinimumRegisterCost = 0; - static const unsigned MinimumFrameCost = 1; - static const unsigned StealPenalty = 2; - static const unsigned StealUniquePenalty = 4; - static const unsigned IndirectMovePenalty = 4; - static const unsigned LowRegisterPenalty = 10; - static const unsigned Impossible = 20; - - Target(): cost(Impossible) { } - - Target(int index, lir::OperandType type, unsigned cost): - index(index), type(type), cost(cost) - { } - - int16_t index; - lir::OperandType type; - uint8_t cost; -}; - lir::ValueType valueType(Context* c, Compiler::OperandType type) { @@ -809,283 +747,6 @@ valueType(Context* c, Compiler::OperandType type) } } -class CostCalculator { - public: - virtual unsigned cost(Context* c, SiteMask mask) = 0; -}; - -unsigned -resourceCost(Context* c, Value* v, Resource* r, SiteMask mask, - CostCalculator* costCalculator) -{ - if (r->reserved or r->freezeCount or r->referenceCount) { - return Target::Impossible; - } else { - unsigned baseCost = - costCalculator ? costCalculator->cost(c, mask) : 0; - - if (r->value) { - assert(c, findSite(c, r->value, r->site)); - - if (v and buddies(r->value, v)) { - return baseCost; - } else if (uniqueSite(c, r->value, r->site)) { - return baseCost + Target::StealUniquePenalty; - } else { - return baseCost = Target::StealPenalty; - } - } else { - return baseCost; - } - } -} - -bool -pickRegisterTarget(Context* c, int i, Value* v, uint32_t mask, int* target, - unsigned* cost, CostCalculator* costCalculator = 0) -{ - if ((1 << i) & mask) { - RegisterResource* r = c->registerResources + i; - unsigned myCost = resourceCost - (c, v, r, SiteMask(1 << lir::RegisterOperand, 1 << i, NoFrameIndex), costCalculator) - + Target::MinimumRegisterCost; - - if ((static_cast(1) << i) == mask) { - *cost = myCost; - return true; - } else if (myCost < *cost) { - *cost = myCost; - *target = i; - } - } - return false; -} - -int -pickRegisterTarget(Context* c, Value* v, uint32_t mask, unsigned* cost, - CostCalculator* costCalculator = 0) -{ - int target = lir::NoRegister; - *cost = Target::Impossible; - - if (mask & c->regFile->generalRegisters.mask) { - for (int i = c->regFile->generalRegisters.limit - 1; - i >= c->regFile->generalRegisters.start; --i) - { - if (pickRegisterTarget(c, i, v, mask, &target, cost, costCalculator)) { - return i; - } - } - } - - if (mask & c->regFile->floatRegisters.mask) { - for (int i = c->regFile->floatRegisters.start; - i < static_cast(c->regFile->floatRegisters.limit); ++i) - { - if (pickRegisterTarget(c, i, v, mask, &target, cost, costCalculator)) { - return i; - } - } - } - - return target; -} - -Target -pickRegisterTarget(Context* c, Value* v, uint32_t mask, - CostCalculator* costCalculator = 0) -{ - unsigned cost; - int number = pickRegisterTarget(c, v, mask, &cost, costCalculator); - return Target(number, lir::RegisterOperand, cost); -} - -unsigned -frameCost(Context* c, Value* v, int frameIndex, CostCalculator* costCalculator) -{ - return resourceCost - (c, v, c->frameResources + frameIndex, SiteMask(1 << lir::MemoryOperand, 0, frameIndex), - costCalculator) - + Target::MinimumFrameCost; -} - -Target -pickFrameTarget(Context* c, Value* v, CostCalculator* costCalculator) -{ - Target best; - - Value* p = v; - do { - if (p->home >= 0) { - Target mine - (p->home, lir::MemoryOperand, frameCost(c, v, p->home, costCalculator)); - - if (mine.cost == Target::MinimumFrameCost) { - return mine; - } else if (mine.cost < best.cost) { - best = mine; - } - } - p = p->buddy; - } while (p != v); - - return best; -} - -Target -pickAnyFrameTarget(Context* c, Value* v, CostCalculator* costCalculator) -{ - Target best; - - unsigned count = totalFrameSize(c); - for (unsigned i = 0; i < count; ++i) { - Target mine(i, lir::MemoryOperand, frameCost(c, v, i, costCalculator)); - if (mine.cost == Target::MinimumFrameCost) { - return mine; - } else if (mine.cost < best.cost) { - best = mine; - } - } - - return best; -} - -Target -pickTarget(Context* c, Value* value, const SiteMask& mask, - unsigned registerPenalty, Target best, - CostCalculator* costCalculator) -{ - if (mask.typeMask & (1 << lir::RegisterOperand)) { - Target mine = pickRegisterTarget - (c, value, mask.registerMask, costCalculator); - - mine.cost += registerPenalty; - if (mine.cost == Target::MinimumRegisterCost) { - return mine; - } else if (mine.cost < best.cost) { - best = mine; - } - } - - if (mask.typeMask & (1 << lir::MemoryOperand)) { - if (mask.frameIndex >= 0) { - Target mine(mask.frameIndex, lir::MemoryOperand, - frameCost(c, value, mask.frameIndex, costCalculator)); - if (mine.cost == Target::MinimumFrameCost) { - return mine; - } else if (mine.cost < best.cost) { - best = mine; - } - } else if (mask.frameIndex == AnyFrameIndex) { - Target mine = pickFrameTarget(c, value, costCalculator); - if (mine.cost == Target::MinimumFrameCost) { - return mine; - } else if (mine.cost < best.cost) { - best = mine; - } - } - } - - return best; -} - -Target -pickTarget(Context* c, Read* read, bool intersectRead, - unsigned registerReserveCount, CostCalculator* costCalculator) -{ - unsigned registerPenalty - = (c->availableGeneralRegisterCount > registerReserveCount - ? 0 : Target::LowRegisterPenalty); - - Value* value = read->value; - - uint32_t registerMask - = (value->type == lir::ValueFloat ? ~0 : c->regFile->generalRegisters.mask); - - SiteMask mask(~0, registerMask, AnyFrameIndex); - read->intersect(&mask); - - if (value->type == lir::ValueFloat) { - uint32_t floatMask = mask.registerMask & c->regFile->floatRegisters.mask; - if (floatMask) { - mask.registerMask = floatMask; - } - } - - Target best; - - Value* successor = read->successor(); - if (successor) { - Read* r = live(c, successor); - if (r) { - SiteMask intersection = mask; - if (r->intersect(&intersection)) { - best = pickTarget - (c, value, intersection, registerPenalty, best, costCalculator); - - if (best.cost <= Target::MinimumFrameCost) { - return best; - } - } - } - } - - best = pickTarget(c, value, mask, registerPenalty, best, costCalculator); - if (best.cost <= Target::MinimumFrameCost) { - return best; - } - - if (intersectRead) { - if (best.cost == Target::Impossible) { - fprintf(stderr, "mask type %d reg %d frame %d\n", - mask.typeMask, mask.registerMask, mask.frameIndex); - abort(c); - } - return best; - } - - { Target mine = pickRegisterTarget(c, value, registerMask, costCalculator); - - mine.cost += registerPenalty; - - if (mine.cost == Target::MinimumRegisterCost) { - return mine; - } else if (mine.cost < best.cost) { - best = mine; - } - } - - { Target mine = pickFrameTarget(c, value, costCalculator); - if (mine.cost == Target::MinimumFrameCost) { - return mine; - } else if (mine.cost < best.cost) { - best = mine; - } - } - - if (best.cost >= Target::StealUniquePenalty - and c->availableGeneralRegisterCount == 0) - { - // there are no free registers left, so moving from memory to - // memory isn't an option - try harder to find an available frame - // site: - best = pickAnyFrameTarget(c, value, costCalculator); - assert(c, best.cost <= 3); - } - - if (best.cost == Target::Impossible) { - abort(c); - } - - return best; -} - -void -acquire(Context* c, Resource* resource, Value* value, Site* site); - -void -release(Context* c, Resource* resource, Value* value, Site* site); - Promise* shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask) { return new(c->zone) ShiftMaskPromise(base, shift, mask); } @@ -1094,297 +755,10 @@ Promise* combinedPromise(Context* c, Promise* low, Promise* high) { return new(c->zone) CombinedPromise(low, high); } -Promise* -resolved(Context* c, int64_t value) -{ +Promise* resolved(Context* c, int64_t value) { return new(c->zone) ResolvedPromise(value); } -AddressSite* -addressSite(Context* c, Promise* address); - -class AddressSite: public Site { - public: - AddressSite(Promise* address): address(address) { } - - virtual unsigned toString(Context*, char* buffer, unsigned bufferSize) { - if (address->resolved()) { - return vm::snprintf - (buffer, bufferSize, "address %" LLD, address->value()); - } else { - return vm::snprintf(buffer, bufferSize, "address unresolved"); - } - } - - virtual unsigned copyCost(Context*, Site* s) { - return (s == this ? 0 : AddressCopyCost); - } - - virtual bool match(Context*, const SiteMask& mask) { - return mask.typeMask & (1 << lir::AddressOperand); - } - - virtual bool loneMatch(Context*, const SiteMask&) { - return false; - } - - virtual bool matchNextWord(Context* c, Site*, unsigned) { - abort(c); - } - - virtual lir::OperandType type(Context*) { - return lir::AddressOperand; - } - - virtual void asAssemblerOperand(Context* c UNUSED, Site* high UNUSED, - lir::Operand* result) - { - assert(c, high == this); - - new (result) lir::Address(address); - } - - virtual Site* copy(Context* c) { - return addressSite(c, address); - } - - virtual Site* copyLow(Context* c) { - abort(c); - } - - virtual Site* copyHigh(Context* c) { - abort(c); - } - - virtual Site* makeNextWord(Context* c, unsigned) { - abort(c); - } - - virtual SiteMask mask(Context*) { - return SiteMask(1 << lir::AddressOperand, 0, NoFrameIndex); - } - - virtual SiteMask nextWordMask(Context* c, unsigned) { - abort(c); - } - - Promise* address; -}; - -AddressSite* -addressSite(Context* c, Promise* address) -{ - return new(c->zone) AddressSite(address); -} - -RegisterSite* -freeRegisterSite(Context* c, uint32_t mask); - -class RegisterSite: public Site { - public: - RegisterSite(uint32_t mask, int number): - mask_(mask), number(number) - { } - - virtual unsigned toString(Context*, char* buffer, unsigned bufferSize) { - if (number != lir::NoRegister) { - return vm::snprintf(buffer, bufferSize, "%p register %d", this, number); - } else { - return vm::snprintf(buffer, bufferSize, - "%p register unacquired (mask %d)", this, mask_); - } - } - - virtual unsigned copyCost(Context* c, Site* s) { - assert(c, number != lir::NoRegister); - - if (s and - (this == s or - (s->type(c) == lir::RegisterOperand - and (static_cast(s)->mask_ & (1 << number))))) - { - return 0; - } else { - return RegisterCopyCost; - } - } - - virtual bool match(Context* c UNUSED, const SiteMask& mask) { - assert(c, number != lir::NoRegister); - - if ((mask.typeMask & (1 << lir::RegisterOperand))) { - return ((static_cast(1) << number) & mask.registerMask); - } else { - return false; - } - } - - virtual bool loneMatch(Context* c UNUSED, const SiteMask& mask) { - assert(c, number != lir::NoRegister); - - if ((mask.typeMask & (1 << lir::RegisterOperand))) { - return ((static_cast(1) << number) == mask.registerMask); - } else { - return false; - } - } - - virtual bool matchNextWord(Context* c, Site* s, unsigned) { - assert(c, number != lir::NoRegister); - - if (s->type(c) != lir::RegisterOperand) { - return false; - } - - RegisterSite* rs = static_cast(s); - unsigned size = rs->registerSize(c); - if (size > TargetBytesPerWord) { - assert(c, number != lir::NoRegister); - return number == rs->number; - } else { - uint32_t mask = c->regFile->generalRegisters.mask; - return ((1 << number) & mask) and ((1 << rs->number) & mask); - } - } - - virtual void acquire(Context* c, Value* v) { - Target target; - if (number != lir::NoRegister) { - target = Target(number, lir::RegisterOperand, 0); - } else { - target = pickRegisterTarget(c, v, mask_); - expect(c, target.cost < Target::Impossible); - } - - RegisterResource* resource = c->registerResources + target.index; - compiler::acquire(c, resource, v, this); - - number = target.index; - } - - virtual void release(Context* c, Value* v) { - assert(c, number != lir::NoRegister); - - compiler::release(c, c->registerResources + number, v, this); - } - - virtual void freeze(Context* c, Value* v) { - assert(c, number != lir::NoRegister); - - c->registerResources[number].freeze(c, v); - } - - virtual void thaw(Context* c, Value* v) { - assert(c, number != lir::NoRegister); - - c->registerResources[number].thaw(c, v); - } - - virtual bool frozen(Context* c UNUSED) { - assert(c, number != lir::NoRegister); - - return c->registerResources[number].freezeCount != 0; - } - - virtual lir::OperandType type(Context*) { - return lir::RegisterOperand; - } - - virtual void asAssemblerOperand(Context* c UNUSED, Site* high, - lir::Operand* result) - { - assert(c, number != lir::NoRegister); - - int highNumber; - if (high != this) { - highNumber = static_cast(high)->number; - assert(c, highNumber != lir::NoRegister); - } else { - highNumber = lir::NoRegister; - } - - new (result) lir::Register(number, highNumber); - } - - virtual Site* copy(Context* c) { - uint32_t mask; - - if (number != lir::NoRegister) { - mask = 1 << number; - } else { - mask = mask_; - } - - return freeRegisterSite(c, mask); - } - - virtual Site* copyLow(Context* c) { - abort(c); - } - - virtual Site* copyHigh(Context* c) { - abort(c); - } - - virtual Site* makeNextWord(Context* c, unsigned) { - assert(c, number != lir::NoRegister); - assert(c, ((1 << number) & c->regFile->generalRegisters.mask)); - - return freeRegisterSite(c, c->regFile->generalRegisters.mask); - } - - virtual SiteMask mask(Context* c UNUSED) { - return SiteMask(1 << lir::RegisterOperand, mask_, NoFrameIndex); - } - - virtual SiteMask nextWordMask(Context* c, unsigned) { - assert(c, number != lir::NoRegister); - - if (registerSize(c) > TargetBytesPerWord) { - return SiteMask - (1 << lir::RegisterOperand, number, NoFrameIndex); - } else { - return SiteMask - (1 << lir::RegisterOperand, c->regFile->generalRegisters.mask, NoFrameIndex); - } - } - - virtual unsigned registerSize(Context* c) { - assert(c, number != lir::NoRegister); - - if ((1 << number) & c->regFile->floatRegisters.mask) { - return c->arch->floatRegisterSize(); - } else { - return TargetBytesPerWord; - } - } - - virtual unsigned registerMask(Context* c UNUSED) { - assert(c, number != lir::NoRegister); - - return 1 << number; - } - - uint32_t mask_; - int number; -}; - -RegisterSite* -registerSite(Context* c, int number) -{ - assert(c, number >= 0); - assert(c, (1 << number) & (c->regFile->generalRegisters.mask - | c->regFile->floatRegisters.mask)); - - return new(c->zone) RegisterSite(1 << number, number); -} - -RegisterSite* -freeRegisterSite(Context* c, uint32_t mask) -{ - return new(c->zone) RegisterSite(mask, lir::NoRegister); -} - MemorySite* memorySite(Context* c, int base, int offset = 0, int index = lir::NoRegister, unsigned scale = 1); @@ -1960,7 +1334,7 @@ steal(Context* c, Resource* r, Value* thief) thief, resourceBuffer, r->value, siteBuffer); } - if ((not (thief and buddies(thief, r->value)) + if ((not (thief and thief->isBuddyOf(r->value)) and uniqueSite(c, r->value, r->site))) { r->site->freeze(c, r->value); @@ -1973,71 +1347,6 @@ steal(Context* c, Resource* r, Value* thief) removeSite(c, r->value, r->site); } -void -acquire(Context* c, Resource* resource, Value* value, Site* site) -{ - assert(c, value); - assert(c, site); - - if (not resource->reserved) { - if (DebugResources) { - char buffer[256]; resource->toString(c, buffer, 256); - fprintf(stderr, "%p acquire %s\n", value, buffer); - } - - if (resource->value) { - assert(c, findSite(c, resource->value, resource->site)); - assert(c, not findSite(c, value, resource->site)); - - steal(c, resource, value); - } - - if (c->acquiredResources) { - c->acquiredResources->previousAcquired = resource; - resource->nextAcquired = c->acquiredResources; - } - c->acquiredResources = resource; - - resource->value = value; - resource->site = site; - } -} - -void -release(Context* c, Resource* resource, Value* value UNUSED, Site* site UNUSED) -{ - if (not resource->reserved) { - if (DebugResources) { - char buffer[256]; resource->toString(c, buffer, 256); - fprintf(stderr, "%p release %s\n", resource->value, buffer); - } - - assert(c, resource->value); - assert(c, resource->site); - - assert(c, buddies(resource->value, value)); - assert(c, site == resource->site); - - Resource* next = resource->nextAcquired; - if (next) { - next->previousAcquired = resource->previousAcquired; - resource->nextAcquired = 0; - } - - Resource* previous = resource->previousAcquired; - if (previous) { - previous->nextAcquired = next; - resource->previousAcquired = 0; - } else { - assert(c, c->acquiredResources == resource); - c->acquiredResources = next; - } - - resource->value = 0; - resource->site = 0; - } -} - SiteMask generalRegisterMask(Context* c) { @@ -2319,7 +1628,7 @@ move(Context* c, Value* value, Site* src, Site* dst) srcb, dstb, value, value); } - assert(c, findSite(c, value, dst)); + assert(c, value->findSite(dst)); src->freeze(c, value); dst->freeze(c, value); diff --git a/src/codegen/compiler/context.h b/src/codegen/compiler/context.h index df6382e68f..2605aaf64d 100644 --- a/src/codegen/compiler/context.h +++ b/src/codegen/compiler/context.h @@ -12,9 +12,10 @@ #define AVIAN_CODEGEN_COMPILER_CONTEXT_H #include "codegen/assembler.h" -#include "codegen/regalloc.h" #include "codegen/compiler.h" +#include "codegen/compiler/regalloc.h" + namespace avian { namespace codegen { namespace compiler { @@ -51,7 +52,7 @@ class Context { Event* predecessor; LogicalInstruction** logicalCode; const RegisterFile* regFile; - regalloc::RegisterAllocator regAlloc; + RegisterAllocator regAlloc; RegisterResource* registerResources; FrameResource* frameResources; Resource* acquiredResources; diff --git a/src/codegen/compiler/read.h b/src/codegen/compiler/read.h new file mode 100644 index 0000000000..a0c1d5a763 --- /dev/null +++ b/src/codegen/compiler/read.h @@ -0,0 +1,46 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_COMPILER_READ_H +#define AVIAN_CODEGEN_COMPILER_READ_H + +namespace avian { +namespace codegen { +namespace compiler { + +class Read { + public: + Read(): + value(0), event(0), eventNext(0) + { } + + virtual bool intersect(SiteMask* mask, unsigned depth = 0) = 0; + + virtual Value* high(Context* c) { abort(c); } + + virtual Value* successor() = 0; + + virtual bool valid() = 0; + + virtual void append(Context* c, Read* r) = 0; + + virtual Read* next(Context* c) = 0; + + Value* value; + Event* event; + Read* eventNext; +}; + + +} // namespace compiler +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_COMPILER_READ_H diff --git a/src/codegen/compiler/regalloc.cpp b/src/codegen/compiler/regalloc.cpp new file mode 100644 index 0000000000..2727b569c4 --- /dev/null +++ b/src/codegen/compiler/regalloc.cpp @@ -0,0 +1,301 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "target.h" + +#include "codegen/compiler/regalloc.h" +#include "codegen/compiler/context.h" +#include "codegen/compiler/site.h" +#include "codegen/compiler/resource.h" +#include "codegen/compiler/read.h" + +namespace avian { +namespace codegen { +namespace compiler { + +RegisterAllocator::RegisterAllocator(Aborter* a, const RegisterFile* registerFile): + a(a), + registerFile(registerFile) +{ } + + +bool uniqueSite(Context* c, Value* v, Site* s); +unsigned totalFrameSize(Context* c); +Read* live(Context* c UNUSED, Value* v); + +unsigned +resourceCost(Context* c, Value* v, Resource* r, SiteMask mask, + CostCalculator* costCalculator) +{ + if (r->reserved or r->freezeCount or r->referenceCount) { + return Target::Impossible; + } else { + unsigned baseCost = + costCalculator ? costCalculator->cost(c, mask) : 0; + + if (r->value) { + assert(c, r->value->findSite(r->site)); + + if (v and r->value->isBuddyOf(v)) { + return baseCost; + } else if (uniqueSite(c, r->value, r->site)) { + return baseCost + Target::StealUniquePenalty; + } else { + return baseCost = Target::StealPenalty; + } + } else { + return baseCost; + } + } +} + +bool +pickRegisterTarget(Context* c, int i, Value* v, uint32_t mask, int* target, + unsigned* cost, CostCalculator* costCalculator) +{ + if ((1 << i) & mask) { + RegisterResource* r = c->registerResources + i; + unsigned myCost = resourceCost + (c, v, r, SiteMask(1 << lir::RegisterOperand, 1 << i, NoFrameIndex), costCalculator) + + Target::MinimumRegisterCost; + + if ((static_cast(1) << i) == mask) { + *cost = myCost; + return true; + } else if (myCost < *cost) { + *cost = myCost; + *target = i; + } + } + return false; +} + +int +pickRegisterTarget(Context* c, Value* v, uint32_t mask, unsigned* cost, + CostCalculator* costCalculator) +{ + int target = lir::NoRegister; + *cost = Target::Impossible; + + if (mask & c->regFile->generalRegisters.mask) { + for (int i = c->regFile->generalRegisters.limit - 1; + i >= c->regFile->generalRegisters.start; --i) + { + if (pickRegisterTarget(c, i, v, mask, &target, cost, costCalculator)) { + return i; + } + } + } + + if (mask & c->regFile->floatRegisters.mask) { + for (int i = c->regFile->floatRegisters.start; + i < static_cast(c->regFile->floatRegisters.limit); ++i) + { + if (pickRegisterTarget(c, i, v, mask, &target, cost, costCalculator)) { + return i; + } + } + } + + return target; +} + +Target +pickRegisterTarget(Context* c, Value* v, uint32_t mask, + CostCalculator* costCalculator) +{ + unsigned cost; + int number = pickRegisterTarget(c, v, mask, &cost, costCalculator); + return Target(number, lir::RegisterOperand, cost); +} + +unsigned +frameCost(Context* c, Value* v, int frameIndex, CostCalculator* costCalculator) +{ + return resourceCost + (c, v, c->frameResources + frameIndex, SiteMask(1 << lir::MemoryOperand, 0, frameIndex), + costCalculator) + + Target::MinimumFrameCost; +} + +Target +pickFrameTarget(Context* c, Value* v, CostCalculator* costCalculator) +{ + Target best; + + Value* p = v; + do { + if (p->home >= 0) { + Target mine + (p->home, lir::MemoryOperand, frameCost(c, v, p->home, costCalculator)); + + if (mine.cost == Target::MinimumFrameCost) { + return mine; + } else if (mine.cost < best.cost) { + best = mine; + } + } + p = p->buddy; + } while (p != v); + + return best; +} + +Target +pickAnyFrameTarget(Context* c, Value* v, CostCalculator* costCalculator) +{ + Target best; + + unsigned count = totalFrameSize(c); + for (unsigned i = 0; i < count; ++i) { + Target mine(i, lir::MemoryOperand, frameCost(c, v, i, costCalculator)); + if (mine.cost == Target::MinimumFrameCost) { + return mine; + } else if (mine.cost < best.cost) { + best = mine; + } + } + + return best; +} + +Target +pickTarget(Context* c, Value* value, const SiteMask& mask, + unsigned registerPenalty, Target best, + CostCalculator* costCalculator) +{ + if (mask.typeMask & (1 << lir::RegisterOperand)) { + Target mine = pickRegisterTarget + (c, value, mask.registerMask, costCalculator); + + mine.cost += registerPenalty; + if (mine.cost == Target::MinimumRegisterCost) { + return mine; + } else if (mine.cost < best.cost) { + best = mine; + } + } + + if (mask.typeMask & (1 << lir::MemoryOperand)) { + if (mask.frameIndex >= 0) { + Target mine(mask.frameIndex, lir::MemoryOperand, + frameCost(c, value, mask.frameIndex, costCalculator)); + if (mine.cost == Target::MinimumFrameCost) { + return mine; + } else if (mine.cost < best.cost) { + best = mine; + } + } else if (mask.frameIndex == AnyFrameIndex) { + Target mine = pickFrameTarget(c, value, costCalculator); + if (mine.cost == Target::MinimumFrameCost) { + return mine; + } else if (mine.cost < best.cost) { + best = mine; + } + } + } + + return best; +} + +Target +pickTarget(Context* c, Read* read, bool intersectRead, + unsigned registerReserveCount, CostCalculator* costCalculator) +{ + unsigned registerPenalty + = (c->availableGeneralRegisterCount > registerReserveCount + ? 0 : Target::LowRegisterPenalty); + + Value* value = read->value; + + uint32_t registerMask + = (value->type == lir::ValueFloat ? ~0 : c->regFile->generalRegisters.mask); + + SiteMask mask(~0, registerMask, AnyFrameIndex); + read->intersect(&mask); + + if (value->type == lir::ValueFloat) { + uint32_t floatMask = mask.registerMask & c->regFile->floatRegisters.mask; + if (floatMask) { + mask.registerMask = floatMask; + } + } + + Target best; + + Value* successor = read->successor(); + if (successor) { + Read* r = live(c, successor); + if (r) { + SiteMask intersection = mask; + if (r->intersect(&intersection)) { + best = pickTarget + (c, value, intersection, registerPenalty, best, costCalculator); + + if (best.cost <= Target::MinimumFrameCost) { + return best; + } + } + } + } + + best = pickTarget(c, value, mask, registerPenalty, best, costCalculator); + if (best.cost <= Target::MinimumFrameCost) { + return best; + } + + if (intersectRead) { + if (best.cost == Target::Impossible) { + fprintf(stderr, "mask type %d reg %d frame %d\n", + mask.typeMask, mask.registerMask, mask.frameIndex); + abort(c); + } + return best; + } + + { Target mine = pickRegisterTarget(c, value, registerMask, costCalculator); + + mine.cost += registerPenalty; + + if (mine.cost == Target::MinimumRegisterCost) { + return mine; + } else if (mine.cost < best.cost) { + best = mine; + } + } + + { Target mine = pickFrameTarget(c, value, costCalculator); + if (mine.cost == Target::MinimumFrameCost) { + return mine; + } else if (mine.cost < best.cost) { + best = mine; + } + } + + if (best.cost >= Target::StealUniquePenalty + and c->availableGeneralRegisterCount == 0) + { + // there are no free registers left, so moving from memory to + // memory isn't an option - try harder to find an available frame + // site: + best = pickAnyFrameTarget(c, value, costCalculator); + assert(c, best.cost <= 3); + } + + if (best.cost == Target::Impossible) { + abort(c); + } + + return best; +} + +} // namespace regalloc +} // namespace codegen +} // namespace avian diff --git a/src/codegen/compiler/regalloc.h b/src/codegen/compiler/regalloc.h new file mode 100644 index 0000000000..cfbf154f1f --- /dev/null +++ b/src/codegen/compiler/regalloc.h @@ -0,0 +1,106 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_COMPILER_REGALLOC_H +#define AVIAN_CODEGEN_COMPILER_REGALLOC_H + +#include "common.h" + +#include "codegen/lir.h" +#include "codegen/registers.h" + +class Aborter; + +namespace avian { +namespace codegen { +namespace compiler { + +class Context; +class Value; +class SiteMask; +class Resource; +class Read; + + +class RegisterAllocator { +public: + Aborter* a; + const RegisterFile* registerFile; + + RegisterAllocator(Aborter* a, const RegisterFile* registerFile); + +}; + +class Target { + public: + static const unsigned MinimumRegisterCost = 0; + static const unsigned MinimumFrameCost = 1; + static const unsigned StealPenalty = 2; + static const unsigned StealUniquePenalty = 4; + static const unsigned IndirectMovePenalty = 4; + static const unsigned LowRegisterPenalty = 10; + static const unsigned Impossible = 20; + + Target(): cost(Impossible) { } + + Target(int index, lir::OperandType type, unsigned cost): + index(index), type(type), cost(cost) + { } + + int16_t index; + lir::OperandType type; + uint8_t cost; +}; + +class CostCalculator { + public: + virtual unsigned cost(Context* c, SiteMask mask) = 0; +}; + +unsigned +resourceCost(Context* c, Value* v, Resource* r, SiteMask mask, + CostCalculator* costCalculator); + + +bool +pickRegisterTarget(Context* c, int i, Value* v, uint32_t mask, int* target, + unsigned* cost, CostCalculator* costCalculator = 0); + +int +pickRegisterTarget(Context* c, Value* v, uint32_t mask, unsigned* cost, + CostCalculator* costCalculator = 0); + +Target +pickRegisterTarget(Context* c, Value* v, uint32_t mask, + CostCalculator* costCalculator = 0); + +unsigned +frameCost(Context* c, Value* v, int frameIndex, CostCalculator* costCalculator); + +Target +pickFrameTarget(Context* c, Value* v, CostCalculator* costCalculator); + +Target +pickAnyFrameTarget(Context* c, Value* v, CostCalculator* costCalculator); + +Target +pickTarget(Context* c, Value* value, const SiteMask& mask, + unsigned registerPenalty, Target best, + CostCalculator* costCalculator); + +Target +pickTarget(Context* c, Read* read, bool intersectRead, + unsigned registerReserveCount, CostCalculator* costCalculator); + +} // namespace regalloc +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_COMPILER_REGALLOC_H \ No newline at end of file diff --git a/src/codegen/compiler/resource.cpp b/src/codegen/compiler/resource.cpp index 1b549e0197..af5e917762 100644 --- a/src/codegen/compiler/resource.cpp +++ b/src/codegen/compiler/resource.cpp @@ -10,6 +10,7 @@ #include "codegen/compiler/context.h" #include "codegen/compiler/resource.h" +#include "codegen/compiler/value.h" namespace avian { namespace codegen { @@ -17,6 +18,9 @@ namespace compiler { const bool DebugResources = false; + +void steal(Context* c, Resource* r, Value* thief); + void decrementAvailableGeneralRegisterCount(Context* c) { assert(c, c->availableGeneralRegisterCount); -- c->availableGeneralRegisterCount; @@ -155,6 +159,68 @@ unsigned FrameResource::index(Context* c) { } +void acquire(Context* c, Resource* resource, Value* value, Site* site) { + assert(c, value); + assert(c, site); + + if (not resource->reserved) { + if (DebugResources) { + char buffer[256]; resource->toString(c, buffer, 256); + fprintf(stderr, "%p acquire %s\n", value, buffer); + } + + if (resource->value) { + assert(c, resource->value->findSite(resource->site)); + assert(c, not value->findSite(resource->site)); + + steal(c, resource, value); + } + + if (c->acquiredResources) { + c->acquiredResources->previousAcquired = resource; + resource->nextAcquired = c->acquiredResources; + } + c->acquiredResources = resource; + + resource->value = value; + resource->site = site; + } +} + +void release(Context* c, Resource* resource, Value* value UNUSED, Site* site UNUSED) { + if (not resource->reserved) { + if (DebugResources) { + char buffer[256]; resource->toString(c, buffer, 256); + fprintf(stderr, "%p release %s\n", resource->value, buffer); + } + + assert(c, resource->value); + assert(c, resource->site); + + assert(c, resource->value->isBuddyOf(value)); + assert(c, site == resource->site); + + Resource* next = resource->nextAcquired; + if (next) { + next->previousAcquired = resource->previousAcquired; + resource->nextAcquired = 0; + } + + Resource* previous = resource->previousAcquired; + if (previous) { + previous->nextAcquired = next; + resource->previousAcquired = 0; + } else { + assert(c, c->acquiredResources == resource); + c->acquiredResources = next; + } + + resource->value = 0; + resource->site = 0; + } +} + + } // namespace compiler } // namespace codegen } // namespace avian \ No newline at end of file diff --git a/src/codegen/compiler/resource.h b/src/codegen/compiler/resource.h index 004cbc34cc..1cc35e3445 100644 --- a/src/codegen/compiler/resource.h +++ b/src/codegen/compiler/resource.h @@ -66,6 +66,10 @@ class FrameResource: public Resource { virtual unsigned index(Context*); }; +void acquire(Context* c, Resource* resource, Value* value, Site* site); + +void release(Context* c, Resource* resource, Value* value, Site* site); + } // namespace compiler } // namespace codegen } // namespace avian diff --git a/src/codegen/compiler/site.cpp b/src/codegen/compiler/site.cpp index 1e3dcff448..1534356674 100644 --- a/src/codegen/compiler/site.cpp +++ b/src/codegen/compiler/site.cpp @@ -13,6 +13,7 @@ #include "codegen/compiler/context.h" #include "codegen/compiler/value.h" #include "codegen/compiler/site.h" +#include "codegen/compiler/resource.h" namespace avian { namespace codegen { @@ -97,6 +98,278 @@ Site* constantSite(Context* c, int64_t value) { return constantSite(c, resolved(c, value)); } + + +class AddressSite: public Site { + public: + AddressSite(Promise* address): address(address) { } + + virtual unsigned toString(Context*, char* buffer, unsigned bufferSize) { + if (address->resolved()) { + return vm::snprintf + (buffer, bufferSize, "address %" LLD, address->value()); + } else { + return vm::snprintf(buffer, bufferSize, "address unresolved"); + } + } + + virtual unsigned copyCost(Context*, Site* s) { + return (s == this ? 0 : AddressCopyCost); + } + + virtual bool match(Context*, const SiteMask& mask) { + return mask.typeMask & (1 << lir::AddressOperand); + } + + virtual bool loneMatch(Context*, const SiteMask&) { + return false; + } + + virtual bool matchNextWord(Context* c, Site*, unsigned) { + abort(c); + } + + virtual lir::OperandType type(Context*) { + return lir::AddressOperand; + } + + virtual void asAssemblerOperand(Context* c UNUSED, Site* high UNUSED, + lir::Operand* result) + { + assert(c, high == this); + + new (result) lir::Address(address); + } + + virtual Site* copy(Context* c) { + return addressSite(c, address); + } + + virtual Site* copyLow(Context* c) { + abort(c); + } + + virtual Site* copyHigh(Context* c) { + abort(c); + } + + virtual Site* makeNextWord(Context* c, unsigned) { + abort(c); + } + + virtual SiteMask mask(Context*) { + return SiteMask(1 << lir::AddressOperand, 0, NoFrameIndex); + } + + virtual SiteMask nextWordMask(Context* c, unsigned) { + abort(c); + } + + Promise* address; +}; + +Site* addressSite(Context* c, Promise* address) { + return new(c->zone) AddressSite(address); +} + + +RegisterSite::RegisterSite(uint32_t mask, int number): + mask_(mask), number(number) +{ } + +unsigned RegisterSite::toString(Context*, char* buffer, unsigned bufferSize) { + if (number != lir::NoRegister) { + return vm::snprintf(buffer, bufferSize, "%p register %d", this, number); + } else { + return vm::snprintf(buffer, bufferSize, + "%p register unacquired (mask %d)", this, mask_); + } +} + +unsigned RegisterSite::copyCost(Context* c, Site* s) { + assert(c, number != lir::NoRegister); + + if (s and + (this == s or + (s->type(c) == lir::RegisterOperand + and (static_cast(s)->mask_ & (1 << number))))) + { + return 0; + } else { + return RegisterCopyCost; + } +} + +bool RegisterSite::match(Context* c UNUSED, const SiteMask& mask) { + assert(c, number != lir::NoRegister); + + if ((mask.typeMask & (1 << lir::RegisterOperand))) { + return ((static_cast(1) << number) & mask.registerMask); + } else { + return false; + } +} + +bool RegisterSite::loneMatch(Context* c UNUSED, const SiteMask& mask) { + assert(c, number != lir::NoRegister); + + if ((mask.typeMask & (1 << lir::RegisterOperand))) { + return ((static_cast(1) << number) == mask.registerMask); + } else { + return false; + } +} + +bool RegisterSite::matchNextWord(Context* c, Site* s, unsigned) { + assert(c, number != lir::NoRegister); + + if (s->type(c) != lir::RegisterOperand) { + return false; + } + + RegisterSite* rs = static_cast(s); + unsigned size = rs->registerSize(c); + if (size > vm::TargetBytesPerWord) { + assert(c, number != lir::NoRegister); + return number == rs->number; + } else { + uint32_t mask = c->regFile->generalRegisters.mask; + return ((1 << number) & mask) and ((1 << rs->number) & mask); + } +} + +void RegisterSite::acquire(Context* c, Value* v) { + Target target; + if (number != lir::NoRegister) { + target = Target(number, lir::RegisterOperand, 0); + } else { + target = pickRegisterTarget(c, v, mask_); + expect(c, target.cost < Target::Impossible); + } + + RegisterResource* resource = c->registerResources + target.index; + compiler::acquire(c, resource, v, this); + + number = target.index; +} + +void RegisterSite::release(Context* c, Value* v) { + assert(c, number != lir::NoRegister); + + compiler::release(c, c->registerResources + number, v, this); +} + +void RegisterSite::freeze(Context* c, Value* v) { + assert(c, number != lir::NoRegister); + + c->registerResources[number].freeze(c, v); +} + +void RegisterSite::thaw(Context* c, Value* v) { + assert(c, number != lir::NoRegister); + + c->registerResources[number].thaw(c, v); +} + +bool RegisterSite::frozen(Context* c UNUSED) { + assert(c, number != lir::NoRegister); + + return c->registerResources[number].freezeCount != 0; +} + +lir::OperandType RegisterSite::type(Context*) { + return lir::RegisterOperand; +} + +void RegisterSite::asAssemblerOperand(Context* c UNUSED, Site* high, + lir::Operand* result) +{ + assert(c, number != lir::NoRegister); + + int highNumber; + if (high != this) { + highNumber = static_cast(high)->number; + assert(c, highNumber != lir::NoRegister); + } else { + highNumber = lir::NoRegister; + } + + new (result) lir::Register(number, highNumber); +} + +Site* RegisterSite::copy(Context* c) { + uint32_t mask; + + if (number != lir::NoRegister) { + mask = 1 << number; + } else { + mask = mask_; + } + + return freeRegisterSite(c, mask); +} + +Site* RegisterSite::copyLow(Context* c) { + abort(c); +} + +Site* RegisterSite::copyHigh(Context* c) { + abort(c); +} + +Site* RegisterSite::makeNextWord(Context* c, unsigned) { + assert(c, number != lir::NoRegister); + assert(c, ((1 << number) & c->regFile->generalRegisters.mask)); + + return freeRegisterSite(c, c->regFile->generalRegisters.mask); +} + +SiteMask RegisterSite::mask(Context* c UNUSED) { + return SiteMask(1 << lir::RegisterOperand, mask_, NoFrameIndex); +} + +SiteMask RegisterSite::nextWordMask(Context* c, unsigned) { + assert(c, number != lir::NoRegister); + + if (registerSize(c) > vm::TargetBytesPerWord) { + return SiteMask + (1 << lir::RegisterOperand, number, NoFrameIndex); + } else { + return SiteMask + (1 << lir::RegisterOperand, c->regFile->generalRegisters.mask, NoFrameIndex); + } +} + +unsigned RegisterSite::registerSize(Context* c) { + assert(c, number != lir::NoRegister); + + if ((1 << number) & c->regFile->floatRegisters.mask) { + return c->arch->floatRegisterSize(); + } else { + return vm::TargetBytesPerWord; + } +} + +unsigned RegisterSite::registerMask(Context* c UNUSED) { + assert(c, number != lir::NoRegister); + + return 1 << number; +} + + + +Site* registerSite(Context* c, int number) { + assert(c, number >= 0); + assert(c, (1 << number) & (c->regFile->generalRegisters.mask + | c->regFile->floatRegisters.mask)); + + return new(c->zone) RegisterSite(1 << number, number); +} + +Site* freeRegisterSite(Context* c, uint32_t mask) { + return new(c->zone) RegisterSite(mask, lir::NoRegister); +} + } // namespace compiler } // namespace codegen } // namespace avian \ No newline at end of file diff --git a/src/codegen/compiler/site.h b/src/codegen/compiler/site.h index aa66243b70..0d32b263a2 100644 --- a/src/codegen/compiler/site.h +++ b/src/codegen/compiler/site.h @@ -11,6 +11,9 @@ #ifndef AVIAN_CODEGEN_COMPILER_SITE_H #define AVIAN_CODEGEN_COMPILER_SITE_H +#include "codegen/compiler/value.h" +#include "codegen/compiler/context.h" + namespace avian { namespace codegen { namespace compiler { @@ -183,6 +186,60 @@ class ConstantSite: public Site { Promise* value; }; +Site* addressSite(Context* c, Promise* address); + +class RegisterSite: public Site { + public: + RegisterSite(uint32_t mask, int number); + + virtual unsigned toString(Context*, char* buffer, unsigned bufferSize); + + virtual unsigned copyCost(Context* c, Site* s); + + virtual bool match(Context* c UNUSED, const SiteMask& mask); + + virtual bool loneMatch(Context* c UNUSED, const SiteMask& mask); + + virtual bool matchNextWord(Context* c, Site* s, unsigned); + + virtual void acquire(Context* c, Value* v); + + virtual void release(Context* c, Value* v); + + virtual void freeze(Context* c, Value* v); + + virtual void thaw(Context* c, Value* v); + + virtual bool frozen(Context* c UNUSED); + + virtual lir::OperandType type(Context*); + + virtual void asAssemblerOperand(Context* c UNUSED, Site* high, + lir::Operand* result); + + virtual Site* copy(Context* c); + + virtual Site* copyLow(Context* c); + + virtual Site* copyHigh(Context* c); + + virtual Site* makeNextWord(Context* c, unsigned); + + virtual SiteMask mask(Context* c UNUSED); + + virtual SiteMask nextWordMask(Context* c, unsigned); + + virtual unsigned registerSize(Context* c); + + virtual unsigned registerMask(Context* c UNUSED); + + uint32_t mask_; + int number; +}; + +Site* registerSite(Context* c, int number); +Site* freeRegisterSite(Context* c, uint32_t mask); + } // namespace compiler } // namespace codegen } // namespace avian diff --git a/src/codegen/compiler/value.cpp b/src/codegen/compiler/value.cpp new file mode 100644 index 0000000000..a8f88acbca --- /dev/null +++ b/src/codegen/compiler/value.cpp @@ -0,0 +1,43 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "target.h" + +#include "codegen/compiler/regalloc.h" +#include "codegen/compiler/site.h" + +namespace avian { +namespace codegen { +namespace compiler { + +Value::Value(Site* site, Site* target, lir::ValueType type): + reads(0), lastRead(0), sites(site), source(0), target(target), buddy(this), + nextWord(this), home(NoFrameIndex), type(type), wordIndex(0) +{ } + +bool Value::findSite(Site* site) { + for (Site* s = this->sites; s; s = s->next) { + if (s == site) return true; + } + return false; +} + +bool Value::isBuddyOf(Value* b) { + Value* a = this; + if (a == b) return true; + for (Value* p = a->buddy; p != a; p = p->buddy) { + if (p == b) return true; + } + return false; +} + +} // namespace regalloc +} // namespace codegen +} // namespace avian diff --git a/src/codegen/compiler/value.h b/src/codegen/compiler/value.h index a2e8040db6..f913d89363 100644 --- a/src/codegen/compiler/value.h +++ b/src/codegen/compiler/value.h @@ -13,6 +13,8 @@ #include "codegen/lir.h" +#include "codegen/compiler.h" + namespace avian { namespace codegen { namespace compiler { @@ -25,11 +27,6 @@ const int NoFrameIndex = -1; class Value: public Compiler::Operand { public: - Value(Site* site, Site* target, lir::ValueType type): - reads(0), lastRead(0), sites(site), source(0), target(target), buddy(this), - nextWord(this), home(NoFrameIndex), type(type), wordIndex(0) - { } - Read* reads; Read* lastRead; Site* sites; @@ -40,6 +37,12 @@ class Value: public Compiler::Operand { int16_t home; lir::ValueType type; uint8_t wordIndex; + + Value(Site* site, Site* target, lir::ValueType type); + + bool findSite(Site* site); + + bool isBuddyOf(Value* b); }; } // namespace compiler diff --git a/src/codegen/regalloc.cpp b/src/codegen/regalloc.cpp deleted file mode 100644 index bc8abf926b..0000000000 --- a/src/codegen/regalloc.cpp +++ /dev/null @@ -1,24 +0,0 @@ -/* Copyright (c) 2008-2012, Avian Contributors - - Permission to use, copy, modify, and/or distribute this software - for any purpose with or without fee is hereby granted, provided - that the above copyright notice and this permission notice appear - in all copies. - - There is NO WARRANTY for this software. See license.txt for - details. */ - -#include "codegen/regalloc.h" - -namespace avian { -namespace codegen { -namespace regalloc { - -RegisterAllocator::RegisterAllocator(Aborter* a, const RegisterFile* registerFile): - a(a), - registerFile(registerFile) -{ } - -} // namespace regalloc -} // namespace codegen -} // namespace avian \ No newline at end of file diff --git a/src/codegen/regalloc.h b/src/codegen/regalloc.h deleted file mode 100644 index 83fbd878f3..0000000000 --- a/src/codegen/regalloc.h +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright (c) 2008-2012, Avian Contributors - - Permission to use, copy, modify, and/or distribute this software - for any purpose with or without fee is hereby granted, provided - that the above copyright notice and this permission notice appear - in all copies. - - There is NO WARRANTY for this software. See license.txt for - details. */ - -#ifndef AVIAN_CODEGEN_REGALLOC_H -#define AVIAN_CODEGEN_REGALLOC_H - -#include "common.h" - -#include "codegen/registers.h" - -class Aborter; - -namespace avian { -namespace codegen { -namespace regalloc { - -class RegisterAllocator { -public: - Aborter* a; - const RegisterFile* registerFile; - - RegisterAllocator(Aborter* a, const RegisterFile* registerFile); - -}; - -} // namespace regalloc -} // namespace codegen -} // namespace avian - -#endif // AVIAN_CODEGEN_REGALLOC_H \ No newline at end of file