diff --git a/src/codegen/compiler.cpp b/src/codegen/compiler.cpp index ab16fb5446..d44426b46f 100644 --- a/src/codegen/compiler.cpp +++ b/src/codegen/compiler.cpp @@ -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, ®isterMask); - - 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(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, diff --git a/src/codegen/compiler/event.cpp b/src/codegen/compiler/event.cpp index 4073bcad69..1722714df4 100644 --- a/src/codegen/compiler/event.cpp +++ b/src/codegen/compiler/event.cpp @@ -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, ®isterMask); + + 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(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 diff --git a/src/codegen/compiler/event.h b/src/codegen/compiler/event.h index 89188a245b..97686c22cf 100644 --- a/src/codegen/compiler/event.h +++ b/src/codegen/compiler/event.h @@ -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