progress towards more flexible register allocation in compiler

This commit is contained in:
Joel Dice 2008-05-04 14:55:34 -06:00
parent 2e108861da
commit efb30b2256

View File

@ -165,9 +165,6 @@ class Context {
stackOffset(0), stackOffset(0),
registers(static_cast<Register*> registers(static_cast<Register*>
(zone->allocate(sizeof(Register) * assembler->registerCount()))), (zone->allocate(sizeof(Register) * assembler->registerCount()))),
freeRegisterCount(assembler->registerCount() - 3),
freeRegisters(static_cast<int*>
(zone->allocate(sizeof(int) * freeRegisterCount))),
firstConstant(0), firstConstant(0),
lastConstant(0), lastConstant(0),
constantCount(0), constantCount(0),
@ -184,13 +181,6 @@ class Context {
registers[assembler->stack()].reserved = true; registers[assembler->stack()].reserved = true;
registers[assembler->thread()].refCount = 1; registers[assembler->thread()].refCount = 1;
registers[assembler->thread()].reserved = true; registers[assembler->thread()].reserved = true;
unsigned fri = 0;
for (int i = assembler->registerCount() - 1; i >= 0; --i) {
if (not registers[i].reserved) {
freeRegisters[fri++] = i;
}
}
} }
System* system; System* system;
@ -202,8 +192,6 @@ class Context {
unsigned logicalCodeLength; unsigned logicalCodeLength;
unsigned stackOffset; unsigned stackOffset;
Register* registers; Register* registers;
unsigned freeRegisterCount;
int* freeRegisters;
ConstantPoolNode* firstConstant; ConstantPoolNode* firstConstant;
ConstantPoolNode* lastConstant; ConstantPoolNode* lastConstant;
unsigned constantCount; unsigned constantCount;
@ -557,7 +545,8 @@ registerSite(Context* c, int low, int high = NoRegister)
} }
RegisterSite* RegisterSite*
freeRegister(Context* c, unsigned size); freeRegister(Context* c, unsigned size,
uint64_t mask = ~static_cast<uint64_t>(0));
void void
increment(Context* c, int r) increment(Context* c, int r)
@ -633,8 +622,58 @@ memorySite(Context* c, int base, int offset, int index, unsigned scale)
MemorySite(base, offset, index, scale); MemorySite(base, offset, index, scale);
} }
bool
matchRegister(Context* c, Site* s, uint64_t mask)
{
assert(c, s->type(c) == RegisterOperand);
RegisterSite* r = static_cast<RegisterSite*>(s);
return ((static_cast<uint64_t>(1) << r->low) & mask)
and (r->high == NoRegister
or ((static_cast<uint64_t>(1) << (r->high + 32)) & mask));
}
bool
match(Context* c, Site* s, uint8_t typeMask, uint64_t registerMask)
{
OperandType t = s->type(c);
return ((1 << t) & typeMask)
and (t != RegisterOperand or matchRegister(c, s, registerMask));
}
class AbstractSite: public Site { class AbstractSite: public Site {
public: public:
AbstractSite(Value* value, uint8_t typeMask, uint64_t registerMask):
value(value), registerMask(registerMask), typeMask(typeMask)
{ }
virtual Site* readTarget(Context* c, Read* r, Event*) {
if (value) {
Site* s = targetOrNull(c, value, event);
if (s and match(c, s, typeMask, registerMask)) {
return s;
}
}
Site* site = 0;
unsigned copyCost = 0xFFFFFFFF;
for (Site* s = r->value->sites; s; s = s->next) {
if (match(c, s, typeMask, registerMask)) {
unsigned v = s->copyCost(c, 0);
if (v < copyCost) {
site = s;
copyCost = v;
}
}
}
if (site) {
return site;
} else {
return freeRegister(c, r->size, registerMask);
}
}
virtual unsigned copyCost(Context* c, Site*) { virtual unsigned copyCost(Context* c, Site*) {
abort(c); abort(c);
} }
@ -650,8 +689,27 @@ class AbstractSite: public Site {
virtual Assembler::Operand* asAssemblerOperand(Context* c) { virtual Assembler::Operand* asAssemblerOperand(Context* c) {
abort(c); abort(c);
} }
Value* value;
uint64_t registerMask;
uint8_t typeMask;
}; };
AbstractSite*
abstractSite(Context* c, Value* v = 0,
uint8_t typeMask = ~static_cast<uint8_t>(0),
uint64_t registerMask = ~static_cast<uint64_t>(0))
{
return new (c->zone->allocate(sizeof(AbstractSite)))
AbstractSite(v, typeMask, registerMask);
}
AbstractSite*
anyRegisterSite(Context* c)
{
return abstractSite(c, 0, 1 << RegisterOperand, ~static_cast<uint64_t>(0));
}
Site* Site*
targetOrNull(Context* c, Read* r, Event* event) targetOrNull(Context* c, Read* r, Event* event)
{ {
@ -714,92 +772,6 @@ targetOrRegister(Context* c, unsigned size, Value* v, Event* event)
} }
} }
class ValueSite: public AbstractSite {
public:
ValueSite(Value* value): value(value) { }
virtual Site* readTarget(Context* c, Read* r, Event* event) {
Site* s = targetOrNull(c, value, event);
if (s and s->type(c) == RegisterOperand) {
return s;
} else {
for (Site* s = r->value->sites; s; s = s->next) {
if (s->type(c) == RegisterOperand) {
return s;
}
}
return freeRegister(c, r->size);
}
}
Value* value;
};
ValueSite*
valueSite(Context* c, Value* v)
{
return new (c->zone->allocate(sizeof(ValueSite))) ValueSite(v);
}
class MoveSite: public AbstractSite {
public:
MoveSite(Value* value): value(value) { }
virtual Site* readTarget(Context* c, Read* read, Event* event) {
if (event->next == read->event) {
return targetOrNull(c, value, event);
} else {
return 0;
}
}
Value* value;
};
MoveSite*
moveSite(Context* c, Value* v)
{
return new (c->zone->allocate(sizeof(MoveSite))) MoveSite(v);
}
class AnyRegisterSite: public AbstractSite {
public:
virtual Site* readTarget(Context* c, Read* r, Event*) {
for (Site* s = r->value->sites; s; s = s->next) {
if (s->type(c) == RegisterOperand) {
return s;
}
}
return freeRegister(c, r->size);
}
};
AnyRegisterSite*
anyRegisterSite(Context* c)
{
return new (c->zone->allocate(sizeof(AnyRegisterSite))) AnyRegisterSite();
}
class ConstantOrRegisterSite: public AbstractSite {
public:
virtual Site* readTarget(Context* c, Read* r, Event*) {
for (Site* s = r->value->sites; s; s = s->next) {
OperandType t = s->type(c);
if (t == ConstantOperand or t == RegisterOperand) {
return s;
}
}
return freeRegister(c, r->size);
}
};
ConstantOrRegisterSite*
constantOrRegisterSite(Context* c)
{
return new (c->zone->allocate(sizeof(ConstantOrRegisterSite)))
ConstantOrRegisterSite();
}
Site* Site*
pick(Context* c, Site* sites, Site* target = 0, unsigned* cost = 0) pick(Context* c, Site* sites, Site* target = 0, unsigned* cost = 0)
{ {
@ -1214,15 +1186,9 @@ appendReturn(Context* c, unsigned size, Value* value)
class MoveEvent: public Event { class MoveEvent: public Event {
public: public:
MoveEvent(Context* c, BinaryOperation type, unsigned size, Value* src, MoveEvent(Context* c, BinaryOperation type, unsigned size, Value* src,
Value* dst): Value* dst, Site* srcTarget):
Event(c), type(type), size(size), src(src), dst(dst) Event(c), type(type), size(size), src(src), dst(dst)
{ {
Site* target;
if (type == Move and size >= BytesPerWord) {
target = moveSite(c, dst);
} else {
target = 0;
}
addRead(c, src, size, target); addRead(c, src, size, target);
} }
@ -1274,8 +1240,26 @@ appendMove(Context* c, BinaryOperation type, unsigned size, Value* src,
fprintf(stderr, "appendMove\n"); fprintf(stderr, "appendMove\n");
} }
Site* target;
if (type == Move and size >= BytesPerWord) {
target = moveSite(c, dst);
} else {
target = 0;
}
AbstractSite* srcTarget = abstractSite(c, dst);
AbstractSite* dstTarget = abstractSite(c);
uintptr_t procedure;
c->assembler->plan(type, size,
&(srcTarget->typeMask), &(srcTarget->registerMask),
&(dstTarget->typeMask), &(dstTarget->registerMask),
&procedure);
assert(c, procedure == 0); // todo
new (c->zone->allocate(sizeof(MoveEvent))) new (c->zone->allocate(sizeof(MoveEvent)))
MoveEvent(c, type, size, src, dst); MoveEvent(c, type, size, src, dst, srcTarget, dstTarget);
} }
class CompareEvent: public Event { class CompareEvent: public Event {
@ -1328,20 +1312,13 @@ maybePreserve(Context* c, Stack* stack, unsigned size, Value* v, Site* s)
class CombineEvent: public Event { class CombineEvent: public Event {
public: public:
CombineEvent(Context* c, BinaryOperation type, unsigned size, Value* first, CombineEvent(Context* c, BinaryOperation type, unsigned size, Value* first,
Value* second, Value* result, Assembler::Register* r1, Value* second, Value* result, Site* firstTarget,
Assembler::Register* r2): Site* secondTarget):
Event(c), type(type), size(size), first(first), second(second), Event(c), type(type), size(size), first(first), second(second),
result(result) result(result)
{ {
addRead(c, first, size, addRead(c, first, size, firstTarget);
r1->low == NoRegister ? addRead(c, second, size, secondTarget);
constantOrRegisterSite(c) :
static_cast<Site*>(registerSite(c, r1->low, r1->high)));
addRead(c, second, size,
r2->low == NoRegister ?
valueSite(c, result) :
static_cast<Site*>(registerSite(c, r2->low, r2->high)));
} }
virtual void compile(Context* c) { virtual void compile(Context* c) {
@ -1376,30 +1353,45 @@ void
appendCombine(Context* c, BinaryOperation type, unsigned size, Value* first, appendCombine(Context* c, BinaryOperation type, unsigned size, Value* first,
Value* second, Value* result) Value* second, Value* result)
{ {
Assembler::Register r1(NoRegister); AbstractSite* firstTarget = abstractSite(c);
Assembler::Register r2(NoRegister); AbstractSite* secondTarget = abstractSite(c, result);
bool syncStack; uintptr_t procedure;
c->assembler->getTargets(type, size, &r1, &r2, &syncStack);
if (syncStack) { c->assembler->plan(type, size,
appendStackSync(c); &(firstTarget->typeMask), &(firstTarget->registerMask),
&(secondTarget->typeMask), &(secondTarget->registerMask),
&procedure);
if (procedure) {
Stack* oldStack = c.state->stack;
::push(&c, size, second);
::push(&c, size, first);
Stack* argumentStack = c.state->stack;
c.state->stack = oldStack;
Value* result = value(c);
appendCall(&c, constant(c, procedure), Compiler::Indirect,
0, result, size, argumentStack, 2);
} else {
if (DebugAppend) {
fprintf(stderr, "appendCombine\n");
}
new (c->zone->allocate(sizeof(CombineEvent)))
CombineEvent(c, type, size, first, second, result, firstTarget,
secondTarget);
} }
if (DebugAppend) {
fprintf(stderr, "appendCombine\n");
}
new (c->zone->allocate(sizeof(CombineEvent)))
CombineEvent(c, type, size, first, second, result, &r1, &r2);
} }
class TranslateEvent: public Event { class TranslateEvent: public Event {
public: public:
TranslateEvent(Context* c, UnaryOperation type, unsigned size, Value* value, TranslateEvent(Context* c, UnaryOperation type, unsigned size, Value* value,
Value* result): Value* result, Site* target):
Event(c), type(type), size(size), value(value), result(result) Event(c), type(type), size(size), value(value), result(result)
{ {
addRead(c, value, size, valueSite(c, result)); addRead(c, value, size, target);
} }
virtual void compile(Context* c) { virtual void compile(Context* c) {
@ -1433,8 +1425,16 @@ appendTranslate(Context* c, UnaryOperation type, unsigned size, Value* value,
fprintf(stderr, "appendTranslate\n"); fprintf(stderr, "appendTranslate\n");
} }
AbstractSite* target = abstractSite(c, result);
uintptr_t procedure;
c->assembler->plan
(type, size, &(target->typeMask), &(target->registerMask), &procedure);
assert(c, procedure == 0); // todo
new (c->zone->allocate(sizeof(TranslateEvent))) new (c->zone->allocate(sizeof(TranslateEvent)))
TranslateEvent(c, type, size, value, result); TranslateEvent(c, type, size, value, result, target);
} }
class MemoryEvent: public Event { class MemoryEvent: public Event {
@ -1466,6 +1466,10 @@ class MemoryEvent: public Event {
nextRead(c, base); nextRead(c, base);
if (index) { if (index) {
nextRead(c, index); nextRead(c, index);
if (BytesPerWord == 8) {
apply(c, Move4To8, 0, index->source, index->source);
}
} }
result->target = memorySite result->target = memorySite
@ -1895,38 +1899,6 @@ updateJunctions(Context* c)
} }
} }
int
freeRegisterExcept(Context* c, int except)
{
for (int i = c->assembler->registerCount() - 1; i >= 0; --i) {
if (i != except
and c->registers[i].refCount == 0
and (not used(c, i)))
{
return i;
}
}
for (int i = c->assembler->registerCount() - 1; i >= 0; --i) {
if (i != except
and c->registers[i].refCount == 0
and (not usedExclusively(c, i)))
{
return i;
}
}
for (int i = c->assembler->registerCount() - 1; i >= 0; --i) {
if (i != except
and c->registers[i].refCount == 0)
{
return i;
}
}
abort(c);
}
void void
visit(Context* c, unsigned logicalIp) visit(Context* c, unsigned logicalIp)
{ {
@ -1940,21 +1912,45 @@ visit(Context* c, unsigned logicalIp)
} }
int int
freeRegister(Context* c) freeRegister2(Context* c, int32_t mask)
{ {
int r = freeRegisterExcept(c, NoRegister); for (int i = c->assembler->registerCount() - 1; i >= 0; --i) {
// fprintf(stderr, "free reg: %d\n", r); if (((1 << i) & mask)
return r; and c->registers[i].refCount == 0
and (not used(c, i)))
{
return i;
}
}
for (int i = c->assembler->registerCount() - 1; i >= 0; --i) {
if (((1 << i) & mask)
and c->registers[i].refCount == 0
and (not usedExclusively(c, i)))
{
return i;
}
}
for (int i = c->assembler->registerCount() - 1; i >= 0; --i) {
if (((1 << i) & mask)
and not c->registers[i].reserved)
{
return i;
}
}
abort(c);
} }
RegisterSite* RegisterSite*
freeRegister(Context* c, unsigned size) freeRegister(Context* c, unsigned size, uint64_t mask)
{ {
if (BytesPerWord == 4 and size == 8) { if (BytesPerWord == 4 and size == 8) {
int low = freeRegister(c); int low = freeRegister2(c, mask);
return registerSite(c, low, freeRegisterExcept(c, low)); return registerSite(c, low, freeRegister2(c, (mask >> 32) & ~(1 << low)));
} else { } else {
return registerSite(c, freeRegister(c)); return registerSite(c, freeRegister2(c, mask));
} }
} }
@ -1963,7 +1959,7 @@ class Client: public Assembler::Client {
Client(Context* c): c(c) { } Client(Context* c): c(c) { }
virtual int acquireTemporary() { virtual int acquireTemporary() {
int r = freeRegisterExcept(c, NoRegister); int r = freeRegister2(c, ~static_cast<uint64_t>(0));
save(r); save(r);
increment(c, r); increment(c, r);
return r; return r;