move CombineEvent out of compiler.cpp

This commit is contained in:
Joshua Warner 2013-02-13 20:28:29 -07:00
parent 5ad0eb86d3
commit 8a61b38a01
7 changed files with 321 additions and 293 deletions

View File

@ -332,31 +332,6 @@ frameIndex(Context* c, FrameIterator::Element* element)
return frameIndex(c, element->localIndex); return frameIndex(c, element->localIndex);
} }
bool
uniqueSite(Context* c, Value* v, Site* s)
{
SiteIterator it(c, v);
Site* p UNUSED = it.next();
if (it.hasMore()) {
// the site is not this word's only site, but if the site is
// shared with the next word, it may be that word's only site
if (v->nextWord != v and s->registerSize(c) > TargetBytesPerWord) {
SiteIterator nit(c, v->nextWord);
Site* p = nit.next();
if (nit.hasMore()) {
return false;
} else {
return p == s;
}
} else {
return false;
}
} else {
assert(c, p == s);
return true;
}
}
void void
clearSites(Context* c, Value* v) clearSites(Context* c, Value* v)
{ {
@ -369,39 +344,10 @@ clearSites(Context* c, Value* v)
} }
} }
bool
valid(Read* r)
{
return r and r->valid();
}
#ifndef NDEBUG
bool
hasBuddy(Context* c, Value* a, Value* b)
{
if (a == b) {
return true;
}
int i = 0;
for (Value* p = a->buddy; p != a; p = p->buddy) {
if (p == b) {
return true;
}
if (++i > 1000) {
abort(c);
}
}
return false;
}
#endif // not NDEBUG
Read* Read*
live(Context* c UNUSED, Value* v) live(Context* c UNUSED, Value* v)
{ {
assert(c, hasBuddy(c, v->buddy, v)); assert(c, v->buddy->hasBuddy(c, v));
Value* p = v; Value* p = v;
do { do {
@ -414,21 +360,6 @@ live(Context* c UNUSED, Value* v)
return 0; return 0;
} }
Read*
liveNext(Context* c, Value* v)
{
assert(c, hasBuddy(c, v->buddy, v));
Read* r = v->reads->next(c);
if (valid(r)) return r;
for (Value* p = v->buddy; p != v; p = p->buddy) {
if (valid(p->reads)) return p->reads;
}
return 0;
}
unsigned unsigned
sitesToString(Context* c, Value* v, char* buffer, unsigned size); sitesToString(Context* c, Value* v, char* buffer, unsigned size);
@ -837,7 +768,7 @@ steal(Context* c, Resource* r, Value* thief)
} }
if ((not (thief and thief->isBuddyOf(r->value)) if ((not (thief and thief->isBuddyOf(r->value))
and uniqueSite(c, r->value, r->site))) and r->value->uniqueSite(c, r->site)))
{ {
r->site->freeze(c, r->value); r->site->freeze(c, r->value);
@ -1352,175 +1283,14 @@ findConstantSite(Context* c, Value* v)
return 0; return 0;
} }
void
preserve(Context* c, Value* v, Read* r, Site* s)
{
s->freeze(c, v);
maybeMove(c, r, false, true, 0);
s->thaw(c, v);
}
Site* Site*
getTarget(Context* c, Value* value, Value* result, const SiteMask& resultMask) getTarget(Context* c, Value* value, Value* result, const SiteMask& resultMask);
{
Site* s;
Value* v;
Read* r = liveNext(c, value);
if (value->source->match
(c, static_cast<const SiteMask&>(resultMask))
and (r == 0 or value->source->loneMatch
(c, static_cast<const SiteMask&>(resultMask))))
{
s = value->source;
v = value;
if (r and uniqueSite(c, v, s)) {
preserve(c, v, r, s);
}
} else {
SingleRead r(resultMask, 0);
r.value = result;
r.successor_ = result;
s = pickTargetSite(c, &r, true);
v = result;
result->addSite(c, s);
}
v->removeSite(c, s);
s->freeze(c, v);
return s;
}
void void
freezeSource(Context* c, unsigned size, Value* v) freezeSource(Context* c, unsigned size, Value* v);
{
v->source->freeze(c, v);
if (size > TargetBytesPerWord) {
v->nextWord->source->freeze(c, v->nextWord);
}
}
void void
thawSource(Context* c, unsigned size, Value* v) thawSource(Context* c, unsigned size, Value* v);
{
v->source->thaw(c, v);
if (size > TargetBytesPerWord) {
v->nextWord->source->thaw(c, v->nextWord);
}
}
class CombineEvent: public Event {
public:
CombineEvent(Context* c, lir::TernaryOperation type,
unsigned firstSize, Value* first,
unsigned secondSize, Value* second,
unsigned resultSize, Value* result,
const SiteMask& firstLowMask,
const SiteMask& firstHighMask,
const SiteMask& secondLowMask,
const SiteMask& secondHighMask):
Event(c), type(type), firstSize(firstSize), first(first),
secondSize(secondSize), second(second), resultSize(resultSize),
result(result)
{
this->addReads(c, first, firstSize, firstLowMask, firstHighMask);
if (resultSize > TargetBytesPerWord) {
result->grow(c);
}
bool condensed = c->arch->alwaysCondensed(type);
this->addReads(c, second, secondSize,
secondLowMask, condensed ? result : 0,
secondHighMask, condensed ? result->nextWord : 0);
}
virtual const char* name() {
return "CombineEvent";
}
virtual void compile(Context* c) {
assert(c, first->source->type(c) == first->nextWord->source->type(c));
// if (second->source->type(c) != second->nextWord->source->type(c)) {
// fprintf(stderr, "%p %p %d : %p %p %d\n",
// second, second->source, second->source->type(c),
// second->nextWord, second->nextWord->source,
// second->nextWord->source->type(c));
// }
assert(c, second->source->type(c) == second->nextWord->source->type(c));
freezeSource(c, firstSize, first);
uint8_t cTypeMask;
uint64_t cRegisterMask;
c->arch->planDestination
(type,
firstSize,
1 << first->source->type(c),
(static_cast<uint64_t>(first->nextWord->source->registerMask(c)) << 32)
| static_cast<uint64_t>(first->source->registerMask(c)),
secondSize,
1 << second->source->type(c),
(static_cast<uint64_t>(second->nextWord->source->registerMask(c)) << 32)
| static_cast<uint64_t>(second->source->registerMask(c)),
resultSize,
&cTypeMask,
&cRegisterMask);
SiteMask resultLowMask(cTypeMask, cRegisterMask, AnyFrameIndex);
SiteMask resultHighMask(cTypeMask, cRegisterMask >> 32, AnyFrameIndex);
Site* low = getTarget(c, second, result, resultLowMask);
unsigned lowSize = low->registerSize(c);
Site* high
= (resultSize > lowSize
? getTarget(c, second->nextWord, result->nextWord, resultHighMask)
: low);
// fprintf(stderr, "combine %p:%p and %p:%p into %p:%p\n",
// first, first->nextWord,
// second, second->nextWord,
// result, result->nextWord);
apply(c, type,
firstSize, first->source, first->nextWord->source,
secondSize, second->source, second->nextWord->source,
resultSize, low, high);
thawSource(c, firstSize, first);
for (Read* r = reads; r; r = r->eventNext) {
popRead(c, this, r->value);
}
low->thaw(c, second);
if (resultSize > lowSize) {
high->thaw(c, second->nextWord);
}
if (live(c, result)) {
result->addSite(c, low);
if (resultSize > lowSize and live(c, result->nextWord)) {
result->nextWord->addSite(c, high);
}
}
}
lir::TernaryOperation type;
unsigned firstSize;
Value* first;
unsigned secondSize;
Value* second;
unsigned resultSize;
Value* result;
};
void void
removeBuddy(Context* c, Value* v) removeBuddy(Context* c, Value* v)
@ -1825,62 +1595,6 @@ register_(Context* c, int number)
return value(c, type, s, s); return value(c, type, s, s);
} }
void
appendCombine(Context* c, lir::TernaryOperation type,
unsigned firstSize, Value* first,
unsigned secondSize, Value* second,
unsigned resultSize, Value* result)
{
bool thunk;
uint8_t firstTypeMask;
uint64_t firstRegisterMask;
uint8_t secondTypeMask;
uint64_t secondRegisterMask;
c->arch->planSource(type, firstSize, &firstTypeMask, &firstRegisterMask,
secondSize, &secondTypeMask, &secondRegisterMask,
resultSize, &thunk);
if (thunk) {
Stack* oldStack = c->stack;
bool threadParameter;
intptr_t handler = c->client->getThunk
(type, firstSize, resultSize, &threadParameter);
unsigned stackSize = ceilingDivide(secondSize, TargetBytesPerWord)
+ ceilingDivide(firstSize, TargetBytesPerWord);
compiler::push(c, ceilingDivide(secondSize, TargetBytesPerWord), second);
compiler::push(c, ceilingDivide(firstSize, TargetBytesPerWord), first);
if (threadParameter) {
++ stackSize;
compiler::push(c, 1, register_(c, c->arch->thread()));
}
Stack* argumentStack = c->stack;
c->stack = oldStack;
appendCall
(c, value(c, lir::ValueGeneral, constantSite(c, handler)), 0, 0, result,
resultSize, argumentStack, stackSize, 0);
} else {
append
(c, new(c->zone)
CombineEvent
(c, type,
firstSize, first,
secondSize, second,
resultSize, result,
SiteMask(firstTypeMask, firstRegisterMask, AnyFrameIndex),
SiteMask(firstTypeMask, firstRegisterMask >> 32, AnyFrameIndex),
SiteMask(secondTypeMask, secondRegisterMask, AnyFrameIndex),
SiteMask(secondTypeMask, secondRegisterMask >> 32, AnyFrameIndex)));
}
}
class TranslateEvent: public Event { class TranslateEvent: public Event {
public: public:
TranslateEvent(Context* c, lir::BinaryOperation type, unsigned valueSize, TranslateEvent(Context* c, lir::BinaryOperation type, unsigned valueSize,

View File

@ -65,10 +65,27 @@ void
maybeMove(Context* c, lir::BinaryOperation type, unsigned srcSize, maybeMove(Context* c, lir::BinaryOperation type, unsigned srcSize,
unsigned srcSelectSize, Value* src, unsigned dstSize, Value* dst, unsigned srcSelectSize, Value* src, unsigned dstSize, Value* dst,
const SiteMask& dstMask); const SiteMask& dstMask);
Site*
maybeMove(Context* c, Value* v, const SiteMask& mask, bool intersectMask,
bool includeNextWord, unsigned registerReserveCount = 0);
Site*
maybeMove(Context* c, Read* read, bool intersectRead, bool includeNextWord,
unsigned registerReserveCount = 0);
Site* Site*
pickSiteOrMove(Context* c, Value* src, Value* dst, Site* nextWord, pickSiteOrMove(Context* c, Value* src, Value* dst, Site* nextWord,
unsigned index); unsigned index);
void push(Context* c, unsigned footprint, Value* v);
Site*
pickTargetSite(Context* c, Read* read, bool intersectRead = false,
unsigned registerReserveCount = 0,
CostCalculator* costCalculator = 0);
Value*
register_(Context* c, int number);
Event::Event(Context* c): Event::Event(Context* c):
next(0), stackBefore(c->stack), localsBefore(c->locals), next(0), stackBefore(c->stack), localsBefore(c->locals),
stackAfter(0), localsAfter(0), promises(0), reads(0), stackAfter(0), localsAfter(0), promises(0), reads(0),
@ -679,6 +696,242 @@ appendMove(Context* c, lir::BinaryOperation type, unsigned srcSize,
SiteMask(srcTypeMask, srcRegisterMask >> 32, AnyFrameIndex))); SiteMask(srcTypeMask, srcRegisterMask >> 32, AnyFrameIndex)));
} }
void
freezeSource(Context* c, unsigned size, Value* v)
{
v->source->freeze(c, v);
if (size > vm::TargetBytesPerWord) {
v->nextWord->source->freeze(c, v->nextWord);
}
}
void
thawSource(Context* c, unsigned size, Value* v)
{
v->source->thaw(c, v);
if (size > vm::TargetBytesPerWord) {
v->nextWord->source->thaw(c, v->nextWord);
}
}
Read* liveNext(Context* c, Value* v) {
assert(c, v->buddy->hasBuddy(c, v));
Read* r = v->reads->next(c);
if (valid(r)) return r;
for (Value* p = v->buddy; p != v; p = p->buddy) {
if (valid(p->reads)) return p->reads;
}
return 0;
}
void preserve(Context* c, Value* v, Read* r, Site* s) {
s->freeze(c, v);
maybeMove(c, r, false, true, 0);
s->thaw(c, v);
}
Site* getTarget(Context* c, Value* value, Value* result, const SiteMask& resultMask) {
Site* s;
Value* v;
Read* r = liveNext(c, value);
if (value->source->match
(c, static_cast<const SiteMask&>(resultMask))
and (r == 0 or value->source->loneMatch
(c, static_cast<const SiteMask&>(resultMask))))
{
s = value->source;
v = value;
if (r and v->uniqueSite(c, s)) {
preserve(c, v, r, s);
}
} else {
SingleRead r(resultMask, 0);
r.value = result;
r.successor_ = result;
s = pickTargetSite(c, &r, true);
v = result;
result->addSite(c, s);
}
v->removeSite(c, s);
s->freeze(c, v);
return s;
}
class CombineEvent: public Event {
public:
CombineEvent(Context* c, lir::TernaryOperation type,
unsigned firstSize, Value* first,
unsigned secondSize, Value* second,
unsigned resultSize, Value* result,
const SiteMask& firstLowMask,
const SiteMask& firstHighMask,
const SiteMask& secondLowMask,
const SiteMask& secondHighMask):
Event(c), type(type), firstSize(firstSize), first(first),
secondSize(secondSize), second(second), resultSize(resultSize),
result(result)
{
this->addReads(c, first, firstSize, firstLowMask, firstHighMask);
if (resultSize > vm::TargetBytesPerWord) {
result->grow(c);
}
bool condensed = c->arch->alwaysCondensed(type);
this->addReads(c, second, secondSize,
secondLowMask, condensed ? result : 0,
secondHighMask, condensed ? result->nextWord : 0);
}
virtual const char* name() {
return "CombineEvent";
}
virtual void compile(Context* c) {
assert(c, first->source->type(c) == first->nextWord->source->type(c));
// if (second->source->type(c) != second->nextWord->source->type(c)) {
// fprintf(stderr, "%p %p %d : %p %p %d\n",
// second, second->source, second->source->type(c),
// second->nextWord, second->nextWord->source,
// second->nextWord->source->type(c));
// }
assert(c, second->source->type(c) == second->nextWord->source->type(c));
freezeSource(c, firstSize, first);
uint8_t cTypeMask;
uint64_t cRegisterMask;
c->arch->planDestination
(type,
firstSize,
1 << first->source->type(c),
(static_cast<uint64_t>(first->nextWord->source->registerMask(c)) << 32)
| static_cast<uint64_t>(first->source->registerMask(c)),
secondSize,
1 << second->source->type(c),
(static_cast<uint64_t>(second->nextWord->source->registerMask(c)) << 32)
| static_cast<uint64_t>(second->source->registerMask(c)),
resultSize,
&cTypeMask,
&cRegisterMask);
SiteMask resultLowMask(cTypeMask, cRegisterMask, AnyFrameIndex);
SiteMask resultHighMask(cTypeMask, cRegisterMask >> 32, AnyFrameIndex);
Site* low = getTarget(c, second, result, resultLowMask);
unsigned lowSize = low->registerSize(c);
Site* high
= (resultSize > lowSize
? getTarget(c, second->nextWord, result->nextWord, resultHighMask)
: low);
// fprintf(stderr, "combine %p:%p and %p:%p into %p:%p\n",
// first, first->nextWord,
// second, second->nextWord,
// result, result->nextWord);
apply(c, type,
firstSize, first->source, first->nextWord->source,
secondSize, second->source, second->nextWord->source,
resultSize, low, high);
thawSource(c, firstSize, first);
for (Read* r = reads; r; r = r->eventNext) {
popRead(c, this, r->value);
}
low->thaw(c, second);
if (resultSize > lowSize) {
high->thaw(c, second->nextWord);
}
if (live(c, result)) {
result->addSite(c, low);
if (resultSize > lowSize and live(c, result->nextWord)) {
result->nextWord->addSite(c, high);
}
}
}
lir::TernaryOperation type;
unsigned firstSize;
Value* first;
unsigned secondSize;
Value* second;
unsigned resultSize;
Value* result;
};
void
appendCombine(Context* c, lir::TernaryOperation type,
unsigned firstSize, Value* first,
unsigned secondSize, Value* second,
unsigned resultSize, Value* result)
{
bool thunk;
uint8_t firstTypeMask;
uint64_t firstRegisterMask;
uint8_t secondTypeMask;
uint64_t secondRegisterMask;
c->arch->planSource(type, firstSize, &firstTypeMask, &firstRegisterMask,
secondSize, &secondTypeMask, &secondRegisterMask,
resultSize, &thunk);
if (thunk) {
Stack* oldStack = c->stack;
bool threadParameter;
intptr_t handler = c->client->getThunk
(type, firstSize, resultSize, &threadParameter);
unsigned stackSize = vm::ceilingDivide(secondSize, vm::TargetBytesPerWord)
+ vm::ceilingDivide(firstSize, vm::TargetBytesPerWord);
compiler::push(c, vm::ceilingDivide(secondSize, vm::TargetBytesPerWord), second);
compiler::push(c, vm::ceilingDivide(firstSize, vm::TargetBytesPerWord), first);
if (threadParameter) {
++ stackSize;
compiler::push(c, 1, register_(c, c->arch->thread()));
}
Stack* argumentStack = c->stack;
c->stack = oldStack;
appendCall
(c, value(c, lir::ValueGeneral, constantSite(c, handler)), 0, 0, result,
resultSize, argumentStack, stackSize, 0);
} else {
append
(c, new(c->zone)
CombineEvent
(c, type,
firstSize, first,
secondSize, second,
resultSize, result,
SiteMask(firstTypeMask, firstRegisterMask, AnyFrameIndex),
SiteMask(firstTypeMask, firstRegisterMask >> 32, AnyFrameIndex),
SiteMask(secondTypeMask, secondRegisterMask, AnyFrameIndex),
SiteMask(secondTypeMask, secondRegisterMask >> 32, AnyFrameIndex)));
}
}
} // namespace compiler } // namespace compiler
} // namespace codegen } // namespace codegen
} // namespace avian } // namespace avian

View File

@ -122,6 +122,12 @@ void
appendMove(Context* c, lir::BinaryOperation type, unsigned srcSize, appendMove(Context* c, lir::BinaryOperation type, unsigned srcSize,
unsigned srcSelectSize, Value* src, unsigned dstSize, Value* dst); unsigned srcSelectSize, Value* src, unsigned dstSize, Value* dst);
void
appendCombine(Context* c, lir::TernaryOperation type,
unsigned firstSize, Value* first,
unsigned secondSize, Value* second,
unsigned resultSize, Value* result);
} // namespace compiler } // namespace compiler
} // namespace codegen } // namespace codegen
} // namespace avian } // namespace avian

View File

@ -43,6 +43,10 @@ class Read {
Read* eventNext; Read* eventNext;
}; };
inline bool valid(Read* r) {
return r and r->valid();
}
class SingleRead: public Read { class SingleRead: public Read {
public: public:
SingleRead(const SiteMask& mask, Value* successor); SingleRead(const SiteMask& mask, Value* successor);

View File

@ -26,7 +26,6 @@ RegisterAllocator::RegisterAllocator(Aborter* a, const RegisterFile* registerFil
{ } { }
bool uniqueSite(Context* c, Value* v, Site* s);
unsigned totalFrameSize(Context* c); unsigned totalFrameSize(Context* c);
Read* live(Context* c UNUSED, Value* v); Read* live(Context* c UNUSED, Value* v);
@ -45,7 +44,7 @@ resourceCost(Context* c, Value* v, Resource* r, SiteMask mask,
if (v and r->value->isBuddyOf(v)) { if (v and r->value->isBuddyOf(v)) {
return baseCost; return baseCost;
} else if (uniqueSite(c, r->value, r->site)) { } else if (r->value->uniqueSite(c, r->site)) {
return baseCost + Target::StealUniquePenalty; return baseCost + Target::StealUniquePenalty;
} else { } else {
return baseCost = Target::StealPenalty; return baseCost = Target::StealPenalty;

View File

@ -100,6 +100,50 @@ bool Value::hasSite(Context* c) {
return it.hasMore(); return it.hasMore();
} }
bool Value::uniqueSite(Context* c, Site* s) {
SiteIterator it(c, this);
Site* p UNUSED = it.next();
if (it.hasMore()) {
// the site is not this word's only site, but if the site is
// shared with the next word, it may be that word's only site
if (this->nextWord != this and s->registerSize(c) > vm::TargetBytesPerWord) {
SiteIterator nit(c, this->nextWord);
Site* p = nit.next();
if (nit.hasMore()) {
return false;
} else {
return p == s;
}
} else {
return false;
}
} else {
assert(c, p == s);
return true;
}
}
#ifndef NDEBUG
bool Value::hasBuddy(Context* c, Value* b) {
Value* a = this;
if (a == b) {
return true;
}
int i = 0;
for (Value* p = a->buddy; p != a; p = p->buddy) {
if (p == b) {
return true;
}
if (++i > 1000) {
abort(c);
}
}
return false;
}
#endif // not NDEBUG
Value* value(Context* c, lir::ValueType type, Site* site, Site* target) { Value* value(Context* c, lir::ValueType type, Site* site, Site* target) {
return new(c->zone) Value(site, target, type); return new(c->zone) Value(site, target, type);

View File

@ -57,6 +57,14 @@ class Value: public Compiler::Operand {
void removeSite(Context* c, Site* s); void removeSite(Context* c, Site* s);
bool hasSite(Context* c); bool hasSite(Context* c);
bool uniqueSite(Context* c, Site* s);
#ifndef NDEBUG
bool hasBuddy(Context* c, Value* b);
#endif // not NDEBUG
}; };