mirror of
https://github.com/corda/corda.git
synced 2025-01-08 14:03:06 +00:00
optimize op,move sequences where op can place its result directly into the move's destination
This commit is contained in:
parent
44b3a7c36d
commit
c1ba7a7d58
340
src/compiler.cpp
340
src/compiler.cpp
@ -37,7 +37,7 @@ class Site {
|
||||
|
||||
virtual ~Site() { }
|
||||
|
||||
virtual Site* readTarget(Context*, Read*) { return this; }
|
||||
virtual Site* readTarget(Context*, Read*, Event*) { return this; }
|
||||
|
||||
virtual unsigned copyCost(Context*, Site*) = 0;
|
||||
|
||||
@ -186,6 +186,130 @@ class Context {
|
||||
uint8_t* machineCode;
|
||||
};
|
||||
|
||||
class PoolPromise: public Promise {
|
||||
public:
|
||||
PoolPromise(Context* c, int key): c(c), key(key) { }
|
||||
|
||||
virtual int64_t value() {
|
||||
if (resolved()) {
|
||||
return reinterpret_cast<intptr_t>
|
||||
(c->machineCode + pad(c->assembler->length()) + (key * BytesPerWord));
|
||||
}
|
||||
|
||||
abort(c);
|
||||
}
|
||||
|
||||
virtual bool resolved() {
|
||||
return c->machineCode != 0;
|
||||
}
|
||||
|
||||
Context* c;
|
||||
int key;
|
||||
};
|
||||
|
||||
class CodePromise: public Promise {
|
||||
public:
|
||||
CodePromise(Context* c, CodePromise* next): c(c), offset(-1), next(next) { }
|
||||
|
||||
CodePromise(Context* c, int offset): c(c), offset(offset), next(0) { }
|
||||
|
||||
virtual int64_t value() {
|
||||
if (resolved()) {
|
||||
return reinterpret_cast<intptr_t>(c->machineCode + offset);
|
||||
}
|
||||
|
||||
abort(c);
|
||||
}
|
||||
|
||||
virtual bool resolved() {
|
||||
return c->machineCode != 0 and offset >= 0;
|
||||
}
|
||||
|
||||
Context* c;
|
||||
int offset;
|
||||
CodePromise* next;
|
||||
};
|
||||
|
||||
class IpPromise: public Promise {
|
||||
public:
|
||||
IpPromise(Context* c, int logicalIp):
|
||||
c(c),
|
||||
logicalIp(logicalIp)
|
||||
{ }
|
||||
|
||||
virtual int64_t value() {
|
||||
if (resolved()) {
|
||||
return reinterpret_cast<intptr_t>
|
||||
(c->machineCode + c->logicalCode[logicalIp].machineOffset);
|
||||
}
|
||||
|
||||
abort(c);
|
||||
}
|
||||
|
||||
virtual bool resolved() {
|
||||
return c->machineCode != 0;
|
||||
}
|
||||
|
||||
Context* c;
|
||||
int logicalIp;
|
||||
};
|
||||
|
||||
inline void NO_RETURN
|
||||
abort(Context* c)
|
||||
{
|
||||
abort(c->system);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
inline void
|
||||
assert(Context* c, bool v)
|
||||
{
|
||||
assert(c->system, v);
|
||||
}
|
||||
#endif // not NDEBUG
|
||||
|
||||
inline void
|
||||
expect(Context* c, bool v)
|
||||
{
|
||||
expect(c->system, v);
|
||||
}
|
||||
|
||||
class Event {
|
||||
public:
|
||||
Event(Context* c):
|
||||
next(0), stack(c->state->stack), promises(0), reads(0),
|
||||
logicalIp(c->logicalIp)
|
||||
{
|
||||
assert(c, c->logicalIp >= 0);
|
||||
|
||||
if (c->lastEvent) {
|
||||
c->lastEvent->next = this;
|
||||
sequence = c->lastEvent->sequence + 1;
|
||||
} else {
|
||||
c->firstEvent = this;
|
||||
sequence = 0;
|
||||
}
|
||||
|
||||
c->lastEvent = this;
|
||||
}
|
||||
|
||||
Event(Context*, Event* next):
|
||||
next(next), stack(next->stack), promises(0), reads(0),
|
||||
sequence(next->sequence), logicalIp(next->logicalIp)
|
||||
{ }
|
||||
|
||||
virtual ~Event() { }
|
||||
|
||||
virtual void compile(Context* c) = 0;
|
||||
|
||||
Event* next;
|
||||
Stack* stack;
|
||||
CodePromise* promises;
|
||||
Read* reads;
|
||||
unsigned sequence;
|
||||
unsigned logicalIp;
|
||||
};
|
||||
|
||||
void
|
||||
addSite(Context* c, Stack* stack, unsigned size, Value* v, Site* s)
|
||||
{
|
||||
@ -388,13 +512,38 @@ class AbstractSite: public Site {
|
||||
}
|
||||
};
|
||||
|
||||
Site*
|
||||
targetOrNull(Context* c, Value* v, Event* event)
|
||||
{
|
||||
if (v->sites) {
|
||||
assert(c, v->sites->next == 0);
|
||||
return v->sites;
|
||||
} else if (v->reads and v->reads->target) {
|
||||
return v->reads->target->readTarget(c, v->reads, event);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
Site*
|
||||
targetOrRegister(Context* c, unsigned size, Value* v, Event* event)
|
||||
{
|
||||
Site* s = targetOrNull(c, v, event);
|
||||
if (s) {
|
||||
return s;
|
||||
} else {
|
||||
return freeRegister(c, size, true);
|
||||
}
|
||||
}
|
||||
|
||||
class ValueSite: public AbstractSite {
|
||||
public:
|
||||
ValueSite(Value* value): value(value) { }
|
||||
|
||||
virtual Site* readTarget(Context* c, Read*) {
|
||||
if (value->reads and value->reads->target) {
|
||||
return value->reads->target->readTarget(c, value->reads);
|
||||
virtual Site* readTarget(Context* c, Read*, Event* event) {
|
||||
Site* s = targetOrNull(c, value, event);
|
||||
if (s->type(c) == RegisterOperand) {
|
||||
return s;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
@ -409,9 +558,30 @@ 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 (read->event->sequence == event->sequence + 1) {
|
||||
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) {
|
||||
virtual Site* readTarget(Context* c, Read* r, Event*) {
|
||||
for (Site* s = r->value->sites; s; s = s->next) {
|
||||
if (s->type(c) == RegisterOperand) {
|
||||
return 0;
|
||||
@ -429,26 +599,6 @@ anyRegisterSite(Context* c)
|
||||
return new (c->zone->allocate(sizeof(AnyRegisterSite))) AnyRegisterSite();
|
||||
}
|
||||
|
||||
inline void NO_RETURN
|
||||
abort(Context* c)
|
||||
{
|
||||
abort(c->system);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
inline void
|
||||
assert(Context* c, bool v)
|
||||
{
|
||||
assert(c->system, v);
|
||||
}
|
||||
#endif // not NDEBUG
|
||||
|
||||
inline void
|
||||
expect(Context* c, bool v)
|
||||
{
|
||||
expect(c->system, v);
|
||||
}
|
||||
|
||||
Value*
|
||||
value(Context* c, Site* site = 0)
|
||||
{
|
||||
@ -571,110 +721,6 @@ apply(Context* c, BinaryOperation op, unsigned size, Site* a, Site* b)
|
||||
c->assembler->apply(op, size, aType, aOperand, bType, bOperand);
|
||||
}
|
||||
|
||||
class PoolPromise: public Promise {
|
||||
public:
|
||||
PoolPromise(Context* c, int key): c(c), key(key) { }
|
||||
|
||||
virtual int64_t value() {
|
||||
if (resolved()) {
|
||||
return reinterpret_cast<intptr_t>
|
||||
(c->machineCode + pad(c->assembler->length()) + (key * BytesPerWord));
|
||||
}
|
||||
|
||||
abort(c);
|
||||
}
|
||||
|
||||
virtual bool resolved() {
|
||||
return c->machineCode != 0;
|
||||
}
|
||||
|
||||
Context* c;
|
||||
int key;
|
||||
};
|
||||
|
||||
class CodePromise: public Promise {
|
||||
public:
|
||||
CodePromise(Context* c, CodePromise* next): c(c), offset(-1), next(next) { }
|
||||
|
||||
CodePromise(Context* c, int offset): c(c), offset(offset), next(0) { }
|
||||
|
||||
virtual int64_t value() {
|
||||
if (resolved()) {
|
||||
return reinterpret_cast<intptr_t>(c->machineCode + offset);
|
||||
}
|
||||
|
||||
abort(c);
|
||||
}
|
||||
|
||||
virtual bool resolved() {
|
||||
return c->machineCode != 0 and offset >= 0;
|
||||
}
|
||||
|
||||
Context* c;
|
||||
int offset;
|
||||
CodePromise* next;
|
||||
};
|
||||
|
||||
class IpPromise: public Promise {
|
||||
public:
|
||||
IpPromise(Context* c, int logicalIp):
|
||||
c(c),
|
||||
logicalIp(logicalIp)
|
||||
{ }
|
||||
|
||||
virtual int64_t value() {
|
||||
if (resolved()) {
|
||||
return reinterpret_cast<intptr_t>
|
||||
(c->machineCode + c->logicalCode[logicalIp].machineOffset);
|
||||
}
|
||||
|
||||
abort(c);
|
||||
}
|
||||
|
||||
virtual bool resolved() {
|
||||
return c->machineCode != 0;
|
||||
}
|
||||
|
||||
Context* c;
|
||||
int logicalIp;
|
||||
};
|
||||
|
||||
class Event {
|
||||
public:
|
||||
Event(Context* c):
|
||||
next(0), stack(c->state->stack), promises(0), reads(0),
|
||||
logicalIp(c->logicalIp)
|
||||
{
|
||||
assert(c, c->logicalIp >= 0);
|
||||
|
||||
if (c->lastEvent) {
|
||||
c->lastEvent->next = this;
|
||||
sequence = c->lastEvent->sequence + 1;
|
||||
} else {
|
||||
c->firstEvent = this;
|
||||
sequence = 0;
|
||||
}
|
||||
|
||||
c->lastEvent = this;
|
||||
}
|
||||
|
||||
Event(Context*, Event* next):
|
||||
next(next), stack(next->stack), promises(0), reads(0),
|
||||
sequence(next->sequence), logicalIp(next->logicalIp)
|
||||
{ }
|
||||
|
||||
virtual ~Event() { }
|
||||
|
||||
virtual void compile(Context* c) = 0;
|
||||
|
||||
Event* next;
|
||||
Stack* stack;
|
||||
CodePromise* promises;
|
||||
Read* reads;
|
||||
unsigned sequence;
|
||||
unsigned logicalIp;
|
||||
};
|
||||
|
||||
void
|
||||
insertRead(Context* c, Event* thisEvent, Event* before, Value* v,
|
||||
unsigned size, Site* target)
|
||||
@ -820,33 +866,28 @@ appendReturn(Context* c, unsigned size, Value* value)
|
||||
new (c->zone->allocate(sizeof(ReturnEvent))) ReturnEvent(c, size, value);
|
||||
}
|
||||
|
||||
Site*
|
||||
writeTarget(Context* c, unsigned size, Value* v)
|
||||
{
|
||||
if (v->sites) {
|
||||
assert(c, v->sites->next == 0);
|
||||
return v->sites;
|
||||
} else if (v->reads and v->reads->target) {
|
||||
Site* s = v->reads->target->readTarget(c, v->reads);
|
||||
if (s) return s;
|
||||
}
|
||||
return freeRegister(c, size, true);
|
||||
}
|
||||
|
||||
class MoveEvent: public Event {
|
||||
public:
|
||||
MoveEvent(Context* c, BinaryOperation type, unsigned size, Value* src,
|
||||
Value* dst):
|
||||
Event(c), type(type), size(size), src(src), dst(dst)
|
||||
{
|
||||
addRead(c, src, size, 0);
|
||||
Site* target;
|
||||
if (type == Move and size >= BytesPerWord) {
|
||||
target = moveSite(c, dst);
|
||||
} else {
|
||||
target = 0;
|
||||
}
|
||||
addRead(c, src, size, target);
|
||||
}
|
||||
|
||||
virtual void compile(Context* c) {
|
||||
fprintf(stderr, "MoveEvent.compile\n");
|
||||
|
||||
Site* target = writeTarget(c, size, dst);
|
||||
apply(c, type, size, src->source, target);
|
||||
Site* target = targetOrRegister(c, size, dst, this);
|
||||
if (src->source->copyCost(c, target)) {
|
||||
apply(c, type, size, src->source, target);
|
||||
}
|
||||
addSite(c, stack, size, dst, target);
|
||||
}
|
||||
|
||||
@ -1153,7 +1194,8 @@ class PopEvent: public Event {
|
||||
|
||||
fprintf(stderr, "pop %p\n", s);
|
||||
|
||||
Site* target = writeTarget(c, s->size * BytesPerWord, s->value);
|
||||
Site* target = targetOrRegister
|
||||
(c, s->size * BytesPerWord, s->value, this);
|
||||
|
||||
apply(c, Pop, BytesPerWord * s->size, target);
|
||||
-- s->value->pushCount;
|
||||
@ -1195,9 +1237,9 @@ appendPop(Context* c, unsigned count, bool ignore)
|
||||
}
|
||||
|
||||
Site*
|
||||
readSource(Context* c, Stack* stack, Read* r)
|
||||
readSource(Context* c, Stack* stack, Read* r, Event* e)
|
||||
{
|
||||
Site* target = (r->target ? r->target->readTarget(c, r) : 0);
|
||||
Site* target = (r->target ? r->target->readTarget(c, r, e) : 0);
|
||||
|
||||
unsigned copyCost;
|
||||
Site* site = pick(c, r->value->sites, target, ©Cost);
|
||||
@ -1237,7 +1279,7 @@ compile(Context* c)
|
||||
li->machineOffset = a->length();
|
||||
|
||||
for (Read* r = e->reads; r; r = r->eventNext) {
|
||||
r->value->source = readSource(c, e->stack, r);
|
||||
r->value->source = readSource(c, e->stack, r, e);
|
||||
|
||||
r->value->reads = r->value->reads->next;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user