move BranchEvent out of compiler.cpp

This commit is contained in:
Joshua Warner 2013-02-13 20:43:42 -07:00
parent 18e6f28ff4
commit 65b7cf047c
3 changed files with 239 additions and 237 deletions

View File

@ -1586,243 +1586,6 @@ register_(Context* c, int number)
return value(c, type, s, s);
}
double
asFloat(unsigned size, int64_t v)
{
if (size == 4) {
return bitsToFloat(v);
} else {
return bitsToDouble(v);
}
}
bool
unordered(double a, double b)
{
return not (a >= b or a < b);
}
bool
shouldJump(Context* c, lir::TernaryOperation type, unsigned size, int64_t b,
int64_t a)
{
switch (type) {
case lir::JumpIfEqual:
return a == b;
case lir::JumpIfNotEqual:
return a != b;
case lir::JumpIfLess:
return a < b;
case lir::JumpIfGreater:
return a > b;
case lir::JumpIfLessOrEqual:
return a <= b;
case lir::JumpIfGreaterOrEqual:
return a >= b;
case lir::JumpIfFloatEqual:
return asFloat(size, a) == asFloat(size, b);
case lir::JumpIfFloatNotEqual:
return asFloat(size, a) != asFloat(size, b);
case lir::JumpIfFloatLess:
return asFloat(size, a) < asFloat(size, b);
case lir::JumpIfFloatGreater:
return asFloat(size, a) > asFloat(size, b);
case lir::JumpIfFloatLessOrEqual:
return asFloat(size, a) <= asFloat(size, b);
case lir::JumpIfFloatGreaterOrEqual:
return asFloat(size, a) >= asFloat(size, b);
case lir::JumpIfFloatLessOrUnordered:
return asFloat(size, a) < asFloat(size, b)
or unordered(asFloat(size, a), asFloat(size, b));
case lir::JumpIfFloatGreaterOrUnordered:
return asFloat(size, a) > asFloat(size, b)
or unordered(asFloat(size, a), asFloat(size, b));
case lir::JumpIfFloatLessOrEqualOrUnordered:
return asFloat(size, a) <= asFloat(size, b)
or unordered(asFloat(size, a), asFloat(size, b));
case lir::JumpIfFloatGreaterOrEqualOrUnordered:
return asFloat(size, a) >= asFloat(size, b)
or unordered(asFloat(size, a), asFloat(size, b));
default:
abort(c);
}
}
lir::TernaryOperation
thunkBranch(Context* c, lir::TernaryOperation type)
{
switch (type) {
case lir::JumpIfFloatEqual:
return lir::JumpIfEqual;
case lir::JumpIfFloatNotEqual:
return lir::JumpIfNotEqual;
case lir::JumpIfFloatLess:
case lir::JumpIfFloatLessOrUnordered:
return lir::JumpIfLess;
case lir::JumpIfFloatGreater:
case lir::JumpIfFloatGreaterOrUnordered:
return lir::JumpIfGreater;
case lir::JumpIfFloatLessOrEqual:
case lir::JumpIfFloatLessOrEqualOrUnordered:
return lir::JumpIfLessOrEqual;
case lir::JumpIfFloatGreaterOrEqual:
case lir::JumpIfFloatGreaterOrEqualOrUnordered:
return lir::JumpIfGreaterOrEqual;
default:
abort(c);
}
}
class BranchEvent: public Event {
public:
BranchEvent(Context* c, lir::TernaryOperation type, unsigned size,
Value* first, Value* second, Value* address,
const SiteMask& firstLowMask,
const SiteMask& firstHighMask,
const SiteMask& secondLowMask,
const SiteMask& secondHighMask):
Event(c), type(type), size(size), first(first), second(second),
address(address)
{
this->addReads(c, first, size, firstLowMask, firstHighMask);
this->addReads(c, second, size, secondLowMask, secondHighMask);
uint8_t typeMask;
uint64_t registerMask;
c->arch->planDestination(type, size, 0, 0, size, 0, 0, TargetBytesPerWord,
&typeMask, &registerMask);
this->addRead(c, address, SiteMask(typeMask, registerMask, AnyFrameIndex));
}
virtual const char* name() {
return "BranchEvent";
}
virtual void compile(Context* c) {
ConstantSite* firstConstant = findConstantSite(c, first);
ConstantSite* secondConstant = findConstantSite(c, second);
if (not this->isUnreachable()) {
if (firstConstant
and secondConstant
and firstConstant->value->resolved()
and secondConstant->value->resolved())
{
int64_t firstValue = firstConstant->value->value();
int64_t secondValue = secondConstant->value->value();
if (size > TargetBytesPerWord) {
firstValue |= findConstantSite
(c, first->nextWord)->value->value() << 32;
secondValue |= findConstantSite
(c, second->nextWord)->value->value() << 32;
}
if (shouldJump(c, type, size, firstValue, secondValue)) {
apply(c, lir::Jump, TargetBytesPerWord, address->source, address->source);
}
} else {
freezeSource(c, size, first);
freezeSource(c, size, second);
freezeSource(c, TargetBytesPerWord, address);
apply(c, type, size, first->source, first->nextWord->source,
size, second->source, second->nextWord->source,
TargetBytesPerWord, address->source, address->source);
thawSource(c, TargetBytesPerWord, address);
thawSource(c, size, second);
thawSource(c, size, first);
}
}
for (Read* r = reads; r; r = r->eventNext) {
popRead(c, this, r->value);
}
}
virtual bool isBranch() { return true; }
lir::TernaryOperation type;
unsigned size;
Value* first;
Value* second;
Value* address;
};
void
appendBranch(Context* c, lir::TernaryOperation type, unsigned size, Value* first,
Value* second, Value* address)
{
bool thunk;
uint8_t firstTypeMask;
uint64_t firstRegisterMask;
uint8_t secondTypeMask;
uint64_t secondRegisterMask;
c->arch->planSource(type, size, &firstTypeMask, &firstRegisterMask,
size, &secondTypeMask, &secondRegisterMask,
TargetBytesPerWord, &thunk);
if (thunk) {
Stack* oldStack = c->stack;
bool threadParameter;
intptr_t handler = c->client->getThunk
(type, size, size, &threadParameter);
assert(c, not threadParameter);
compiler::push(c, ceilingDivide(size, TargetBytesPerWord), second);
compiler::push(c, ceilingDivide(size, TargetBytesPerWord), first);
Stack* argumentStack = c->stack;
c->stack = oldStack;
Value* result = value(c, lir::ValueGeneral);
appendCall
(c, value
(c, lir::ValueGeneral, constantSite(c, handler)), 0, 0, result, 4,
argumentStack, ceilingDivide(size, TargetBytesPerWord) * 2, 0);
appendBranch(c, thunkBranch(c, type), 4, value
(c, lir::ValueGeneral, constantSite(c, static_cast<int64_t>(0))),
result, address);
} else {
append
(c, new(c->zone)
BranchEvent
(c, type, size, first, second, address,
SiteMask(firstTypeMask, firstRegisterMask, AnyFrameIndex),
SiteMask(firstTypeMask, firstRegisterMask >> 32, AnyFrameIndex),
SiteMask(secondTypeMask, secondRegisterMask, AnyFrameIndex),
SiteMask(secondTypeMask, secondRegisterMask >> 32, AnyFrameIndex)));
}
}
class JumpEvent: public Event {
public:
JumpEvent(Context* c, lir::UnaryOperation type, Value* address, bool exit,

View File

@ -1174,6 +1174,241 @@ appendMemory(Context* c, Value* base, int displacement, Value* index,
MemoryEvent(c, base, displacement, index, scale, result));
}
double asFloat(unsigned size, int64_t v) {
if (size == 4) {
return vm::bitsToFloat(v);
} else {
return vm::bitsToDouble(v);
}
}
bool
unordered(double a, double b)
{
return not (a >= b or a < b);
}
bool
shouldJump(Context* c, lir::TernaryOperation type, unsigned size, int64_t b,
int64_t a)
{
switch (type) {
case lir::JumpIfEqual:
return a == b;
case lir::JumpIfNotEqual:
return a != b;
case lir::JumpIfLess:
return a < b;
case lir::JumpIfGreater:
return a > b;
case lir::JumpIfLessOrEqual:
return a <= b;
case lir::JumpIfGreaterOrEqual:
return a >= b;
case lir::JumpIfFloatEqual:
return asFloat(size, a) == asFloat(size, b);
case lir::JumpIfFloatNotEqual:
return asFloat(size, a) != asFloat(size, b);
case lir::JumpIfFloatLess:
return asFloat(size, a) < asFloat(size, b);
case lir::JumpIfFloatGreater:
return asFloat(size, a) > asFloat(size, b);
case lir::JumpIfFloatLessOrEqual:
return asFloat(size, a) <= asFloat(size, b);
case lir::JumpIfFloatGreaterOrEqual:
return asFloat(size, a) >= asFloat(size, b);
case lir::JumpIfFloatLessOrUnordered:
return asFloat(size, a) < asFloat(size, b)
or unordered(asFloat(size, a), asFloat(size, b));
case lir::JumpIfFloatGreaterOrUnordered:
return asFloat(size, a) > asFloat(size, b)
or unordered(asFloat(size, a), asFloat(size, b));
case lir::JumpIfFloatLessOrEqualOrUnordered:
return asFloat(size, a) <= asFloat(size, b)
or unordered(asFloat(size, a), asFloat(size, b));
case lir::JumpIfFloatGreaterOrEqualOrUnordered:
return asFloat(size, a) >= asFloat(size, b)
or unordered(asFloat(size, a), asFloat(size, b));
default:
abort(c);
}
}
lir::TernaryOperation
thunkBranch(Context* c, lir::TernaryOperation type)
{
switch (type) {
case lir::JumpIfFloatEqual:
return lir::JumpIfEqual;
case lir::JumpIfFloatNotEqual:
return lir::JumpIfNotEqual;
case lir::JumpIfFloatLess:
case lir::JumpIfFloatLessOrUnordered:
return lir::JumpIfLess;
case lir::JumpIfFloatGreater:
case lir::JumpIfFloatGreaterOrUnordered:
return lir::JumpIfGreater;
case lir::JumpIfFloatLessOrEqual:
case lir::JumpIfFloatLessOrEqualOrUnordered:
return lir::JumpIfLessOrEqual;
case lir::JumpIfFloatGreaterOrEqual:
case lir::JumpIfFloatGreaterOrEqualOrUnordered:
return lir::JumpIfGreaterOrEqual;
default:
abort(c);
}
}
class BranchEvent: public Event {
public:
BranchEvent(Context* c, lir::TernaryOperation type, unsigned size,
Value* first, Value* second, Value* address,
const SiteMask& firstLowMask,
const SiteMask& firstHighMask,
const SiteMask& secondLowMask,
const SiteMask& secondHighMask):
Event(c), type(type), size(size), first(first), second(second),
address(address)
{
this->addReads(c, first, size, firstLowMask, firstHighMask);
this->addReads(c, second, size, secondLowMask, secondHighMask);
uint8_t typeMask;
uint64_t registerMask;
c->arch->planDestination(type, size, 0, 0, size, 0, 0, vm::TargetBytesPerWord,
&typeMask, &registerMask);
this->addRead(c, address, SiteMask(typeMask, registerMask, AnyFrameIndex));
}
virtual const char* name() {
return "BranchEvent";
}
virtual void compile(Context* c) {
ConstantSite* firstConstant = findConstantSite(c, first);
ConstantSite* secondConstant = findConstantSite(c, second);
if (not this->isUnreachable()) {
if (firstConstant
and secondConstant
and firstConstant->value->resolved()
and secondConstant->value->resolved())
{
int64_t firstValue = firstConstant->value->value();
int64_t secondValue = secondConstant->value->value();
if (size > vm::TargetBytesPerWord) {
firstValue |= findConstantSite
(c, first->nextWord)->value->value() << 32;
secondValue |= findConstantSite
(c, second->nextWord)->value->value() << 32;
}
if (shouldJump(c, type, size, firstValue, secondValue)) {
apply(c, lir::Jump, vm::TargetBytesPerWord, address->source, address->source);
}
} else {
freezeSource(c, size, first);
freezeSource(c, size, second);
freezeSource(c, vm::TargetBytesPerWord, address);
apply(c, type, size, first->source, first->nextWord->source,
size, second->source, second->nextWord->source,
vm::TargetBytesPerWord, address->source, address->source);
thawSource(c, vm::TargetBytesPerWord, address);
thawSource(c, size, second);
thawSource(c, size, first);
}
}
for (Read* r = reads; r; r = r->eventNext) {
popRead(c, this, r->value);
}
}
virtual bool isBranch() { return true; }
lir::TernaryOperation type;
unsigned size;
Value* first;
Value* second;
Value* address;
};
void
appendBranch(Context* c, lir::TernaryOperation type, unsigned size, Value* first,
Value* second, Value* address)
{
bool thunk;
uint8_t firstTypeMask;
uint64_t firstRegisterMask;
uint8_t secondTypeMask;
uint64_t secondRegisterMask;
c->arch->planSource(type, size, &firstTypeMask, &firstRegisterMask,
size, &secondTypeMask, &secondRegisterMask,
vm::TargetBytesPerWord, &thunk);
if (thunk) {
Stack* oldStack = c->stack;
bool threadParameter;
intptr_t handler = c->client->getThunk
(type, size, size, &threadParameter);
assert(c, not threadParameter);
compiler::push(c, vm::ceilingDivide(size, vm::TargetBytesPerWord), second);
compiler::push(c, vm::ceilingDivide(size, vm::TargetBytesPerWord), first);
Stack* argumentStack = c->stack;
c->stack = oldStack;
Value* result = value(c, lir::ValueGeneral);
appendCall
(c, value
(c, lir::ValueGeneral, constantSite(c, handler)), 0, 0, result, 4,
argumentStack, vm::ceilingDivide(size, vm::TargetBytesPerWord) * 2, 0);
appendBranch(c, thunkBranch(c, type), 4, value
(c, lir::ValueGeneral, constantSite(c, static_cast<int64_t>(0))),
result, address);
} else {
append
(c, new(c->zone)
BranchEvent
(c, type, size, first, second, address,
SiteMask(firstTypeMask, firstRegisterMask, AnyFrameIndex),
SiteMask(firstTypeMask, firstRegisterMask >> 32, AnyFrameIndex),
SiteMask(secondTypeMask, secondRegisterMask, AnyFrameIndex),
SiteMask(secondTypeMask, secondRegisterMask >> 32, AnyFrameIndex)));
}
}
} // namespace compiler
} // namespace codegen
} // namespace avian

View File

@ -139,6 +139,10 @@ void
appendMemory(Context* c, Value* base, int displacement, Value* index,
unsigned scale, Value* result);
void
appendBranch(Context* c, lir::TernaryOperation type, unsigned size, Value* first,
Value* second, Value* address);
} // namespace compiler
} // namespace codegen
} // namespace avian