begin moving register allocator out of compiler.cpp

This commit is contained in:
Joshua Warner 2013-02-11 21:31:19 -07:00
parent 34471e5d60
commit ef5e534e1e
11 changed files with 225 additions and 109 deletions

View File

@ -953,6 +953,8 @@ 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/registers.cpp \
$(src)/codegen/targets.cpp
ifeq ($(codegen-targets),native)

View File

@ -8,11 +8,12 @@
There is NO WARRANTY for this software. See license.txt for
details. */
#include "codegen/assembler.h"
#include "codegen/registers.h"
#include "alloc-vector.h"
#include "util/abort.h"
#include "codegen/assembler.h"
#include "util/runtime-array.h"
#define CAST1(x) reinterpret_cast<UnaryOperationType>(x)
@ -210,6 +211,9 @@ const uint64_t GPR_MASK64 = GPR_MASK | (uint64_t)GPR_MASK << 32;
// making the following const somehow breaks debug symbol output in GDB
/* const */ uint64_t FPR_MASK64 = FPR_MASK | (uint64_t)FPR_MASK << 32;
const RegisterFile MyRegisterFileWithoutFloats(GPR_MASK, 0);
const RegisterFile MyRegisterFileWithFloats(GPR_MASK, FPR_MASK);
inline bool isFpr(lir::Register* reg) {
return reg->low >= N_GPRS;
}
@ -2057,12 +2061,8 @@ class MyArchitecture: public Assembler::Architecture {
return vfpSupported() ? 8 : 0;
}
virtual uint32_t generalRegisterMask() {
return GPR_MASK;
}
virtual uint32_t floatRegisterMask() {
return vfpSupported() ? FPR_MASK : 0;
virtual const RegisterFile* registerFile() {
return vfpSupported() ? &MyRegisterFileWithFloats : &MyRegisterFileWithoutFloats;
}
virtual int scratch() {

View File

@ -20,6 +20,8 @@
namespace avian {
namespace codegen {
class RegisterFile;
class OperandInfo {
public:
const unsigned size;
@ -66,8 +68,7 @@ class Assembler {
public:
virtual unsigned floatRegisterSize() = 0;
virtual uint32_t generalRegisterMask() = 0;
virtual uint32_t floatRegisterMask() = 0;
virtual const RegisterFile* registerFile() = 0;
virtual int scratch() = 0;
virtual int stack() = 0;

View File

@ -8,12 +8,14 @@
There is NO WARRANTY for this software. See license.txt for
details. */
#include "compiler.h"
#include "assembler.h"
#include "target.h"
#include "util/runtime-array.h"
#include "codegen/compiler.h"
#include "codegen/assembler.h"
#include "codegen/regalloc.h"
using namespace vm;
using namespace avian::codegen;
@ -338,30 +340,6 @@ class Value: public Compiler::Operand {
uint8_t wordIndex;
};
uint32_t
registerMask(Assembler::Architecture* arch)
{
return arch->generalRegisterMask() | arch->floatRegisterMask();
}
unsigned
maskStart(uint32_t mask)
{
for (int i = 0; i <= 31; ++i) {
if (mask & (1 << i)) return i;
}
return 32;
}
unsigned
maskLimit(uint32_t mask)
{
for (int i = 31; i >= 0; --i) {
if (mask & (1 << i)) return i + 1;
}
return 0;
}
class Context {
public:
Context(System* system, Assembler* assembler, Zone* zone,
@ -376,15 +354,11 @@ class Context {
saved(0),
predecessor(0),
logicalCode(0),
registerStart(maskStart(registerMask(arch))),
registerLimit(maskLimit(registerMask(arch))),
generalRegisterStart(maskStart(arch->generalRegisterMask())),
generalRegisterLimit(maskLimit(arch->generalRegisterMask())),
floatRegisterStart(maskStart(arch->floatRegisterMask())),
floatRegisterLimit(maskLimit(arch->floatRegisterMask())),
regFile(arch->registerFile()),
regAlloc(system, arch->registerFile()),
registerResources
(static_cast<RegisterResource*>
(zone->allocate(sizeof(RegisterResource) * registerLimit))),
(zone->allocate(sizeof(RegisterResource) * regFile->allRegisters.limit))),
frameResources(0),
acquiredResources(0),
firstConstant(0),
@ -402,16 +376,16 @@ class Context {
localFootprint(0),
machineCodeSize(0),
alignedFrameSize(0),
availableGeneralRegisterCount(generalRegisterLimit - generalRegisterStart)
availableGeneralRegisterCount(regFile->generalRegisters.limit - regFile->generalRegisters.start)
{
for (unsigned i = generalRegisterStart; i < generalRegisterLimit; ++i) {
for (unsigned i = regFile->generalRegisters.start; i < regFile->generalRegisters.limit; ++i) {
new (registerResources + i) RegisterResource(arch->reserved(i));
if (registerResources[i].reserved) {
-- availableGeneralRegisterCount;
}
}
for (unsigned i = floatRegisterStart; i < floatRegisterLimit; ++i) {
for (unsigned i = regFile->floatRegisters.start; i < regFile->floatRegisters.limit; ++i) {
new (registerResources + i) RegisterResource(arch->reserved(i));
}
}
@ -426,12 +400,8 @@ class Context {
Cell* saved;
Event* predecessor;
LogicalInstruction** logicalCode;
uint8_t registerStart;
uint8_t registerLimit;
uint8_t generalRegisterStart;
uint8_t generalRegisterLimit;
uint8_t floatRegisterStart;
uint8_t floatRegisterLimit;
const RegisterFile* regFile;
regalloc::RegisterAllocator regAlloc;
RegisterResource* registerResources;
FrameResource* frameResources;
Resource* acquiredResources;
@ -1158,7 +1128,7 @@ increment(Context* c, RegisterResource* r)
++ r->referenceCount;
if (r->referenceCount == 1
and ((1 << r->index(c)) & c->arch->generalRegisterMask()))
and ((1 << r->index(c)) & c->regFile->generalRegisters.mask))
{
decrementAvailableGeneralRegisterCount(c);
}
@ -1179,7 +1149,7 @@ decrement(Context* c, RegisterResource* r)
-- r->referenceCount;
if (r->referenceCount == 0
and ((1 << r->index(c)) & c->arch->generalRegisterMask()))
and ((1 << r->index(c)) & c->regFile->generalRegisters.mask))
{
incrementAvailableGeneralRegisterCount(c);
}
@ -1204,7 +1174,7 @@ RegisterResource::freeze(Context* c, Value* v)
freezeResource(c, this, v);
if (freezeCount == 1
and ((1 << index(c)) & c->arch->generalRegisterMask()))
and ((1 << index(c)) & c->regFile->generalRegisters.mask))
{
decrementAvailableGeneralRegisterCount(c);
}
@ -1239,7 +1209,7 @@ RegisterResource::thaw(Context* c, Value* v)
thawResource(c, this, v);
if (freezeCount == 0
and ((1 << index(c)) & c->arch->generalRegisterMask()))
and ((1 << index(c)) & c->regFile->generalRegisters.mask))
{
incrementAvailableGeneralRegisterCount(c);
}
@ -1291,20 +1261,18 @@ valueType(Context* c, Compiler::OperandType type)
class CostCalculator {
public:
virtual unsigned cost(Context* c, uint8_t typeMask, uint32_t registerMask,
int frameIndex) = 0;
virtual unsigned cost(Context* c, SiteMask mask) = 0;
};
unsigned
resourceCost(Context* c, Value* v, Resource* r, uint8_t typeMask,
uint32_t registerMask, int frameIndex,
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, typeMask, registerMask, frameIndex) : 0;
unsigned baseCost =
costCalculator ? costCalculator->cost(c, mask) : 0;
if (r->value) {
assert(c, findSite(c, r->value, r->site));
@ -1329,7 +1297,7 @@ pickRegisterTarget(Context* c, int i, Value* v, uint32_t mask, int* target,
if ((1 << i) & mask) {
RegisterResource* r = c->registerResources + i;
unsigned myCost = resourceCost
(c, v, r, 1 << lir::RegisterOperand, 1 << i, NoFrameIndex, costCalculator)
(c, v, r, SiteMask(1 << lir::RegisterOperand, 1 << i, NoFrameIndex), costCalculator)
+ Target::MinimumRegisterCost;
if ((static_cast<uint32_t>(1) << i) == mask) {
@ -1350,9 +1318,9 @@ pickRegisterTarget(Context* c, Value* v, uint32_t mask, unsigned* cost,
int target = lir::NoRegister;
*cost = Target::Impossible;
if (mask & c->arch->generalRegisterMask()) {
for (int i = c->generalRegisterLimit - 1;
i >= c->generalRegisterStart; --i)
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;
@ -1360,9 +1328,9 @@ pickRegisterTarget(Context* c, Value* v, uint32_t mask, unsigned* cost,
}
}
if (mask & c->arch->floatRegisterMask()) {
for (int i = c->floatRegisterStart;
i < static_cast<int>(c->floatRegisterLimit); ++i)
if (mask & c->regFile->floatRegisters.mask) {
for (int i = c->regFile->floatRegisters.start;
i < static_cast<int>(c->regFile->floatRegisters.limit); ++i)
{
if (pickRegisterTarget(c, i, v, mask, &target, cost, costCalculator)) {
return i;
@ -1386,7 +1354,7 @@ unsigned
frameCost(Context* c, Value* v, int frameIndex, CostCalculator* costCalculator)
{
return resourceCost
(c, v, c->frameResources + frameIndex, 1 << lir::MemoryOperand, 0, frameIndex,
(c, v, c->frameResources + frameIndex, SiteMask(1 << lir::MemoryOperand, 0, frameIndex),
costCalculator)
+ Target::MinimumFrameCost;
}
@ -1482,13 +1450,13 @@ pickTarget(Context* c, Read* read, bool intersectRead,
Value* value = read->value;
uint32_t registerMask
= (value->type == lir::ValueFloat ? ~0 : c->arch->generalRegisterMask());
= (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->arch->floatRegisterMask();
uint32_t floatMask = mask.registerMask & c->regFile->floatRegisters.mask;
if (floatMask) {
mask.registerMask = floatMask;
}
@ -1813,7 +1781,7 @@ class RegisterSite: public Site {
assert(c, number != lir::NoRegister);
return number == rs->number;
} else {
uint32_t mask = c->arch->generalRegisterMask();
uint32_t mask = c->regFile->generalRegisters.mask;
return ((1 << number) & mask) and ((1 << rs->number) & mask);
}
}
@ -1899,9 +1867,9 @@ class RegisterSite: public Site {
virtual Site* makeNextWord(Context* c, unsigned) {
assert(c, number != lir::NoRegister);
assert(c, ((1 << number) & c->arch->generalRegisterMask()));
assert(c, ((1 << number) & c->regFile->generalRegisters.mask));
return freeRegisterSite(c, c->arch->generalRegisterMask());
return freeRegisterSite(c, c->regFile->generalRegisters.mask);
}
virtual SiteMask mask(Context* c UNUSED) {
@ -1916,14 +1884,14 @@ class RegisterSite: public Site {
(1 << lir::RegisterOperand, number, NoFrameIndex);
} else {
return SiteMask
(1 << lir::RegisterOperand, c->arch->generalRegisterMask(), NoFrameIndex);
(1 << lir::RegisterOperand, c->regFile->generalRegisters.mask, NoFrameIndex);
}
}
virtual unsigned registerSize(Context* c) {
assert(c, number != lir::NoRegister);
if ((1 << number) & c->arch->floatRegisterMask()) {
if ((1 << number) & c->regFile->floatRegisters.mask) {
return c->arch->floatRegisterSize();
} else {
return TargetBytesPerWord;
@ -1944,8 +1912,8 @@ RegisterSite*
registerSite(Context* c, int number)
{
assert(c, number >= 0);
assert(c, (1 << number) & (c->arch->generalRegisterMask()
| c->arch->floatRegisterMask()));
assert(c, (1 << number) & (c->regFile->generalRegisters.mask
| c->regFile->floatRegisters.mask));
return new(c->zone) RegisterSite(1 << number, number);
}
@ -2382,8 +2350,7 @@ maybeMove(Context* c, Read* read, bool intersectRead, bool includeNextWord,
includeNextWord(includeNextWord)
{ }
virtual unsigned cost(Context* c, uint8_t typeMask, uint32_t registerMask,
int frameIndex)
virtual unsigned cost(Context* c, SiteMask dstMask)
{
uint8_t srcTypeMask;
uint64_t srcRegisterMask;
@ -2392,10 +2359,9 @@ maybeMove(Context* c, Read* read, bool intersectRead, bool includeNextWord,
c->arch->planMove
(size, &srcTypeMask, &srcRegisterMask,
&tmpTypeMask, &tmpRegisterMask,
typeMask, registerMask);
dstMask.typeMask, dstMask.registerMask);
SiteMask srcMask(srcTypeMask, srcRegisterMask, AnyFrameIndex);
SiteMask dstMask(typeMask, registerMask, frameIndex);
for (SiteIterator it(c, value, true, includeNextWord); it.hasMore();) {
Site* s = it.next();
if (s->match(c, srcMask) or s->match(c, dstMask)) {
@ -2615,7 +2581,7 @@ SiteMask
generalRegisterMask(Context* c)
{
return SiteMask
(1 << lir::RegisterOperand, c->arch->generalRegisterMask(), NoFrameIndex);
(1 << lir::RegisterOperand, c->regFile->generalRegisters.mask, NoFrameIndex);
}
SiteMask
@ -2623,7 +2589,7 @@ generalRegisterOrConstantMask(Context* c)
{
return SiteMask
((1 << lir::RegisterOperand) | (1 << lir::ConstantOperand),
c->arch->generalRegisterMask(), NoFrameIndex);
c->regFile->generalRegisters.mask, NoFrameIndex);
}
SiteMask
@ -3143,7 +3109,7 @@ class CallEvent: public Event {
resultSize(resultSize),
stackArgumentFootprint(stackArgumentFootprint)
{
uint32_t registerMask = c->arch->generalRegisterMask();
uint32_t registerMask = c->regFile->generalRegisters.mask;
if (argumentCount) {
assert(c, (flags & Compiler::TailJump) == 0);
@ -3564,7 +3530,7 @@ maybeMove(Context* c, lir::BinaryOperation type, unsigned srcSize,
dstSize, &thunk);
if (src->type == lir::ValueGeneral) {
srcRegisterMask &= c->arch->generalRegisterMask();
srcRegisterMask &= c->regFile->generalRegisters.mask;
}
assert(c, thunk == 0);
@ -4374,11 +4340,11 @@ loadLocal(Context* c, unsigned footprint, unsigned index)
Value*
register_(Context* c, int number)
{
assert(c, (1 << number) & (c->arch->generalRegisterMask()
| c->arch->floatRegisterMask()));
assert(c, (1 << number) & (c->regFile->generalRegisters.mask
| c->regFile->floatRegisters.mask));
Site* s = registerSite(c, number);
lir::ValueType type = ((1 << number) & c->arch->floatRegisterMask())
lir::ValueType type = ((1 << number) & c->regFile->floatRegisters.mask)
? lir::ValueFloat: lir::ValueGeneral;
return value(c, type, s, s);
@ -5415,7 +5381,7 @@ resolveSourceSites(Context* c, Event* e, SiteRecordList* frozen, Site** sites)
if (r and sites[el.localIndex] == 0) {
SiteMask mask((1 << lir::RegisterOperand) | (1 << lir::MemoryOperand),
c->arch->generalRegisterMask(), AnyFrameIndex);
c->regFile->generalRegisters.mask, AnyFrameIndex);
Site* s = pickSourceSite
(c, r, 0, 0, &mask, true, false, true, acceptForResolve);
@ -5449,7 +5415,7 @@ resolveTargetSites(Context* c, Event* e, SiteRecordList* frozen, Site** sites)
if (r and sites[el.localIndex] == 0) {
SiteMask mask((1 << lir::RegisterOperand) | (1 << lir::MemoryOperand),
c->arch->generalRegisterMask(), AnyFrameIndex);
c->regFile->generalRegisters.mask, AnyFrameIndex);
Site* s = pickSourceSite
(c, r, 0, 0, &mask, false, true, true, acceptForResolve);

View File

@ -8,8 +8,8 @@
There is NO WARRANTY for this software. See license.txt for
details. */
#ifndef COMPILER_H
#define COMPILER_H
#ifndef AVIAN_CODEGEN_COMPILER_H
#define AVIAN_CODEGEN_COMPILER_H
#include "system.h"
#include "zone.h"
@ -207,4 +207,4 @@ makeCompiler(vm::System* system, Assembler* assembler, vm::Zone* zone,
} // namespace codegen
} // namespace avian
#endif//COMPILER_H
#endif // AVIAN_CODEGEN_COMPILER_H

View File

@ -9,6 +9,8 @@
details. */
#include "codegen/assembler.h"
#include "codegen/registers.h"
#include "alloc-vector.h"
#include "util/abort.h"
@ -153,6 +155,8 @@ inline int unha16(int32_t high, int32_t low) {
return ((high - ((low & 0x8000) ? 1 : 0)) << 16) | low;
}
const RegisterFile MyRegisterFile(0xFFFFFFFF, 0);
inline bool
isInt16(target_intptr_t v)
{
@ -2061,12 +2065,8 @@ class MyArchitecture: public Assembler::Architecture {
return 0;
}
virtual uint32_t generalRegisterMask() {
return 0xFFFFFFFF;
}
virtual uint32_t floatRegisterMask() {
return 0;
virtual const RegisterFile* registerFile() {
return &MyRegisterFile;
}
virtual int scratch() {

24
src/codegen/regalloc.cpp Normal file
View File

@ -0,0 +1,24 @@
/* 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

37
src/codegen/regalloc.h Normal file
View File

@ -0,0 +1,37 @@
/* 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

35
src/codegen/registers.cpp Normal file
View File

@ -0,0 +1,35 @@
/* 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/registers.h"
namespace avian {
namespace codegen {
unsigned
RegisterMask::maskStart(uint32_t mask)
{
for (int i = 0; i <= 31; ++i) {
if (mask & (1 << i)) return i;
}
return 32;
}
unsigned
RegisterMask::maskLimit(uint32_t mask)
{
for (int i = 31; i >= 0; --i) {
if (mask & (1 << i)) return i + 1;
}
return 0;
}
} // namespace codegen
} // namespace avian

51
src/codegen/registers.h Normal file
View File

@ -0,0 +1,51 @@
/* 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_REGISTERS_H
#define AVIAN_CODEGEN_REGISTERS_H
#include "common.h"
namespace avian {
namespace codegen {
class RegisterMask {
public:
uint32_t mask;
uint8_t start;
uint8_t limit;
static unsigned maskStart(uint32_t mask);
static unsigned maskLimit(uint32_t mask);
inline RegisterMask(uint32_t mask):
mask(mask),
start(maskStart(mask)),
limit(maskLimit(mask))
{ }
};
class RegisterFile {
public:
RegisterMask allRegisters;
RegisterMask generalRegisters;
RegisterMask floatRegisters;
inline RegisterFile(uint32_t generalRegisterMask, uint32_t floatRegisterMask):
allRegisters(generalRegisterMask | floatRegisterMask),
generalRegisters(generalRegisterMask),
floatRegisters(floatRegisterMask)
{ }
};
} // namespace codegen
} // namespace avian
#endif // AVIAN_CODEGEN_REGISTERS_H

View File

@ -13,6 +13,7 @@
#include "alloc-vector.h"
#include "codegen/assembler.h"
#include "codegen/registers.h"
#include "util/runtime-array.h"
#include "util/abort.h"
@ -72,6 +73,8 @@ const unsigned GeneralRegisterMask
const unsigned FloatRegisterMask
= TargetBytesPerWord == 4 ? 0x00ff0000 : 0xffff0000;
const RegisterFile MyRegisterFile(GeneralRegisterMask, FloatRegisterMask);
const unsigned FrameHeaderSize = (UseFramePointer ? 2 : 1);
const int LongJumpRegister = r10;
@ -2714,7 +2717,8 @@ populateTables(ArchitectureContext* c)
class MyArchitecture: public Assembler::Architecture {
public:
MyArchitecture(System* system, bool useNativeFeatures):
c(system, useNativeFeatures), referenceCount(0)
c(system, useNativeFeatures),
referenceCount(0)
{
populateTables(&c);
}
@ -2726,13 +2730,9 @@ class MyArchitecture: public Assembler::Architecture {
return 0;
}
}
virtual uint32_t generalRegisterMask() {
return GeneralRegisterMask;
}
virtual uint32_t floatRegisterMask() {
return useSSE(&c) ? FloatRegisterMask : 0;
virtual const RegisterFile* registerFile() {
return &MyRegisterFile;
}
virtual int scratch() {