mirror of
https://github.com/corda/corda.git
synced 2025-01-21 03:55:00 +00:00
move CombineEvent out of compiler.cpp
This commit is contained in:
parent
5ad0eb86d3
commit
8a61b38a01
@ -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,
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user