mirror of
https://github.com/corda/corda.git
synced 2025-01-24 05:18:24 +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() { }
|
||||||
|
|
||||||
virtual Site* readTarget(Context*, Read*) { return this; }
|
virtual Site* readTarget(Context*, Read*, Event*) { return this; }
|
||||||
|
|
||||||
virtual unsigned copyCost(Context*, Site*) = 0;
|
virtual unsigned copyCost(Context*, Site*) = 0;
|
||||||
|
|
||||||
@ -186,6 +186,130 @@ class Context {
|
|||||||
uint8_t* machineCode;
|
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
|
void
|
||||||
addSite(Context* c, Stack* stack, unsigned size, Value* v, Site* s)
|
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 {
|
class ValueSite: public AbstractSite {
|
||||||
public:
|
public:
|
||||||
ValueSite(Value* value): value(value) { }
|
ValueSite(Value* value): value(value) { }
|
||||||
|
|
||||||
virtual Site* readTarget(Context* c, Read*) {
|
virtual Site* readTarget(Context* c, Read*, Event* event) {
|
||||||
if (value->reads and value->reads->target) {
|
Site* s = targetOrNull(c, value, event);
|
||||||
return value->reads->target->readTarget(c, value->reads);
|
if (s->type(c) == RegisterOperand) {
|
||||||
|
return s;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -409,9 +558,30 @@ valueSite(Context* c, Value* v)
|
|||||||
return new (c->zone->allocate(sizeof(ValueSite))) ValueSite(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 {
|
class AnyRegisterSite: public AbstractSite {
|
||||||
public:
|
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) {
|
for (Site* s = r->value->sites; s; s = s->next) {
|
||||||
if (s->type(c) == RegisterOperand) {
|
if (s->type(c) == RegisterOperand) {
|
||||||
return 0;
|
return 0;
|
||||||
@ -429,26 +599,6 @@ anyRegisterSite(Context* c)
|
|||||||
return new (c->zone->allocate(sizeof(AnyRegisterSite))) AnyRegisterSite();
|
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*
|
||||||
value(Context* c, Site* site = 0)
|
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);
|
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
|
void
|
||||||
insertRead(Context* c, Event* thisEvent, Event* before, Value* v,
|
insertRead(Context* c, Event* thisEvent, Event* before, Value* v,
|
||||||
unsigned size, Site* target)
|
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);
|
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 {
|
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):
|
||||||
Event(c), type(type), size(size), src(src), dst(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) {
|
virtual void compile(Context* c) {
|
||||||
fprintf(stderr, "MoveEvent.compile\n");
|
fprintf(stderr, "MoveEvent.compile\n");
|
||||||
|
|
||||||
Site* target = writeTarget(c, size, dst);
|
Site* target = targetOrRegister(c, size, dst, this);
|
||||||
apply(c, type, size, src->source, target);
|
if (src->source->copyCost(c, target)) {
|
||||||
|
apply(c, type, size, src->source, target);
|
||||||
|
}
|
||||||
addSite(c, stack, size, dst, target);
|
addSite(c, stack, size, dst, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1153,7 +1194,8 @@ class PopEvent: public Event {
|
|||||||
|
|
||||||
fprintf(stderr, "pop %p\n", s);
|
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);
|
apply(c, Pop, BytesPerWord * s->size, target);
|
||||||
-- s->value->pushCount;
|
-- s->value->pushCount;
|
||||||
@ -1195,9 +1237,9 @@ appendPop(Context* c, unsigned count, bool ignore)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Site*
|
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;
|
unsigned copyCost;
|
||||||
Site* site = pick(c, r->value->sites, target, ©Cost);
|
Site* site = pick(c, r->value->sites, target, ©Cost);
|
||||||
@ -1237,7 +1279,7 @@ compile(Context* c)
|
|||||||
li->machineOffset = a->length();
|
li->machineOffset = a->length();
|
||||||
|
|
||||||
for (Read* r = e->reads; r; r = r->eventNext) {
|
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;
|
r->value->reads = r->value->reads->next;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user