diff --git a/src/assembler.h b/src/assembler.h index b61ed3e70a..bb619040ca 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -38,22 +38,11 @@ enum UnaryOperation { Jump, LongJump, AlignedJump, - JumpIfLess, - JumpIfGreater, - JumpIfLessOrEqual, - JumpIfGreaterOrEqual, - JumpIfEqual, - JumpIfNotEqual, - JumpIfFloatUnordered, - JumpIfFloatLess, - JumpIfFloatGreater, - JumpIfFloatLessOrEqual, - JumpIfFloatGreaterOrEqual, - JumpIfFloatEqual, - JumpIfFloatNotEqual, + + NoUnaryOperation = -1 }; -const unsigned UnaryOperationCount = JumpIfNotEqual + 1; +const unsigned UnaryOperationCount = AlignedJump + 1; enum BinaryOperation { Move, @@ -62,15 +51,11 @@ enum BinaryOperation { MoveZ, Compare, Negate, - - //extensions: FloatNegate, FloatCompare, Float2Float, Float2Int, Int2Float, - - //intrinsic functions: FloatSqrt, FloatAbs, Abs, @@ -81,7 +66,6 @@ enum BinaryOperation { const unsigned BinaryOperationCount = Abs + 1; enum TernaryOperation { - LongCompare, Add, Subtract, Multiply, @@ -93,22 +77,35 @@ enum TernaryOperation { And, Or, Xor, - - //extensions: FloatAdd, FloatSubtract, FloatMultiply, FloatDivide, FloatRemainder, - - //intrinsic functions: FloatMax, FloatMin, + JumpIfLess, + JumpIfGreater, + JumpIfLessOrEqual, + JumpIfGreaterOrEqual, + JumpIfEqual, + JumpIfNotEqual, + JumpIfFloatEqual, + JumpIfFloatNotEqual, + JumpIfFloatLess, + JumpIfFloatGreater, + JumpIfFloatLessOrEqual, + JumpIfFloatGreaterOrEqual, + JumpIfFloatLessOrUnordered, + JumpIfFloatGreaterOrUnordered, + JumpIfFloatLessOrEqualOrUnordered, + JumpIfFloatGreaterOrEqualOrUnordered, NoTernaryOperation = -1 }; -const unsigned TernaryOperationCount = FloatMin + 1; +const unsigned TernaryOperationCount += JumpIfFloatGreaterOrEqualOrUnordered + 1; enum OperandType { ConstantOperand, @@ -315,8 +312,6 @@ class Assembler { virtual unsigned registerSize(ValueType type) = 0; - virtual bool supportsFloatCompare(unsigned size) = 0; - virtual bool alwaysCondensed(BinaryOperation op) = 0; virtual bool alwaysCondensed(TernaryOperation op) = 0; diff --git a/src/compile.cpp b/src/compile.cpp index 5d55a2ae2e..0c22da31f5 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -1971,6 +1971,18 @@ compareFloatsL(uint32_t bi, uint32_t ai) } } +int64_t +compareLongs(uint64_t b, uint64_t a) +{ + if (a < b) { + return -1; + } else if (a > b) { + return 1; + } else { + return 0; + } +} + uint64_t addDouble(uint64_t b, uint64_t a) { @@ -2677,17 +2689,111 @@ saveStateAndCompile(MyThread* t, Frame* initialFrame, unsigned ip) } bool -isCJump(unsigned instruction) +integerBranch(Frame* frame, object code, unsigned& ip, unsigned size, + Compiler::Operand* a, Compiler::Operand* b) { - switch(instruction) { + if (ip + 3 > codeLength(t, code)) { + return false; + } + + Compiler* c = frame->c; + unsigned instruction = codeBody(t, code, ip++); + uint32_t offset = codeReadInt16(t, code, ip); + uint32_t newIp = (ip - 3) + offset; + assert(t, newIp < codeLength(t, code)); + + Compiler::Operand* target = frame->machineIp(newIp); + + switch (instruction) { case ifeq: - case ifne: - case ifgt: - case ifge: - case iflt: - case ifle: + c->jumpIfEqual(size, a, b, target); return true; + + case ifne: + c->jumpIfNotEqual(size, a, b, target); + return true; + + case ifgt: + c->jumpIfGreater(size, a, b, target); + return true; + + case ifge: + c->jumpIfGreaterOrEqual(size, a, b, target); + return true; + + case iflt: + c->jumpIfLessOrUnordered(size, a, b, target); + return true; + + case ifle: + c->jumpIfLessOrEqualOrUnordered(size, a, b, target); + return true; + default: + ip -= 3; + return false; + } +} + +bool +floatBranch(Frame* frame, object code, unsigned& ip, unsigned size, + bool lessIfUnordered, Compiler::Operand* a, Compiler::Operand* b) +{ + if (ip + 3 > codeLength(t, code)) { + return false; + } + + Compiler* c = frame->c; + unsigned instruction = codeBody(t, code, ip++); + uint32_t offset = codeReadInt16(t, code, ip); + uint32_t newIp = (ip - 3) + offset; + assert(t, newIp < codeLength(t, code)); + + Compiler::Operand* target = frame->machineIp(newIp); + + switch (instruction) { + case ifeq: + c->jumpIfFloatEqual(size, a, b, target); + return true; + + case ifne: + c->jumpIfFloatNotEqual(size, a, b, target); + return true; + + case ifgt: + if (lessIfUnordered) { + c->jumpIfFloatGreater(size, a, b, target); + } else { + c->jumpIfFloatGreaterOrUnordered(size, a, b, target); + } + return true; + + case ifge: + if (lessIfUnordered) { + c->jumpIfFloatGreaterOrEqual(size, a, b, target); + } else { + c->jumpIfFloatGreaterOrEqualOrUnordered(size, a, b, target); + } + return true; + + case iflt: + if (lessIfUnordered) { + c->jumpIfFloatLessOrUnordered(size, a, b, target); + } else { + c->jumpIfFloatLess(size, a, b, target); + } + return true; + + case ifle: + if (lessIfUnordered) { + c->jumpIfFloatLessOrEqualOrUnordered(size, a, b, target); + } else { + c->jumpIfFloatLessOrEqual(size, a, b, target); + } + return true; + + default: + ip -= 3; return false; } } @@ -2706,8 +2812,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, object code = methodCode(t, context->method); PROTECT(t, code); - int lastFcmpl = 1, lastFcmpg = 1; - while (ip < codeLength(t, code)) { if (context->visitTable[ip] ++) { // we've already visited this part of the code @@ -2733,9 +2837,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, 1, c->register_(t->arch->thread())); } - ++ lastFcmpl; - ++ lastFcmpg; - // fprintf(stderr, "ip: %d map: %ld\n", ip, *(frame->map)); unsigned instruction = codeBody(t, code, ip++); @@ -3043,10 +3144,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, Compiler::Operand* a = frame->popLong(); Compiler::Operand* b = frame->popLong(); - if(t->arch->supportsFloatCompare(8) and isCJump(codeBody(t, code, ip))) { - c->fcmp(8, a, b); - lastFcmpg = 0; - } else { + if (not floatBranch(frame, ip, 8, false, a, b)) { frame->pushInt (c->call (c->constant @@ -3061,10 +3159,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, Compiler::Operand* a = frame->popLong(); Compiler::Operand* b = frame->popLong(); - if(t->arch->supportsFloatCompare(8) and isCJump(codeBody(t, code, ip))) { - c->fcmp(8, a, b); - lastFcmpl = 0; - } else { + if (not floatBranch(frame, ip, 8, true, a, b)) { frame->pushInt (c->call (c->constant @@ -3162,10 +3257,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, Compiler::Operand* a = frame->popInt(); Compiler::Operand* b = frame->popInt(); - if(t->arch->supportsFloatCompare(4) and isCJump(codeBody(t, code, ip))) { - c->fcmp(4, a, b); - lastFcmpg = 0; - } else { + if (not floatBranch(frame, ip, 4, false, a, b)) { frame->pushInt (c->call (c->constant @@ -3178,10 +3270,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, Compiler::Operand* a = frame->popInt(); Compiler::Operand* b = frame->popInt(); - if(t->arch->supportsFloatCompare(4) and isCJump(codeBody(t, code, ip))) { - c->fcmp(4, a, b); - lastFcmpl = 0; - } else { + if (not floatBranch(frame, ip, 4, true, a, b)) { frame->pushInt (c->call (c->constant @@ -3473,11 +3562,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, Compiler::Operand* b = frame->popObject(); Compiler::Operand* target = frame->machineIp(newIp); - c->cmp(BytesPerWord, a, b); if (instruction == if_acmpeq) { - c->je(target); + c->jumpIfEqual(BytesPerWord, a, btarget); } else { - c->jne(target); + c->jumpIfNotEqual(BytesPerWord, a, btarget); } saveStateAndCompile(t, frame, newIp); @@ -3498,26 +3586,27 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, Compiler::Operand* b = frame->popInt(); Compiler::Operand* target = frame->machineIp(newIp); - c->cmp(4, a, b); switch (instruction) { case if_icmpeq: - c->je(target); + c->jumpIfEqual(4, a, b, target); break; case if_icmpne: - c->jne(target); + c->jumpIfNotEqual(4, a, b, target); break; case if_icmpgt: - c->jg(target); + c->jumpIfGreater(4, a, b, target); break; case if_icmpge: - c->jge(target); + c->jumpIfGreaterOrEqual(4, a, b, target); break; case if_icmplt: - c->jl(target); + c->jumpIfLess(4, a, b, target); break; case if_icmple: - c->jle(target); + c->jumpIfLessOrEqual(4, a, b, target); break; + default: + abort(t); } saveStateAndCompile(t, frame, newIp); @@ -3537,67 +3626,30 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, Compiler::Operand* target = frame->machineIp(newIp); Compiler::Operand* cont = frame->machineIp(ip); - if (lastFcmpl != 1 and lastFcmpg != 1) { - Compiler::Operand* a = frame->popInt(); - c->cmp(4, c->constant(0, Compiler::IntegerType), a); - } + Compiler::Operand* a = c->constant(0, Compiler::IntegerType); + Compiler::Operand* b = frame->popInt(); + switch (instruction) { case ifeq: - if (lastFcmpl == 1 or lastFcmpg == 1) { - c->fjuo(cont); - c->fje(target); - } else { - c->je(target); - } + c->jumpIfEqual(4, a, b, target); break; case ifne: - if (lastFcmpl == 1 or lastFcmpg == 1) { - c->fjuo(cont); - c->fjne(target); - } else { - c->jne(target); - } + c->jumpIfNotEqual(4, a, b, target); break; case ifgt: - if (lastFcmpl == 1) { - c->fjuo(cont); - c->fjg(target); - } else if (lastFcmpg == 1) { - c->fjg(target); - } else { - c->jg(target); - } + c->jumpIfGreater(4, a, b, target); break; case ifge: - if (lastFcmpl == 1) { - c->fjuo(cont); - c->fjge(target); - } else if (lastFcmpg == 1) { - c->fjge(target); - } else { - c->jge(target); - } + c->jumpIfGreaterOrEqual(4, a, b, target); break; case iflt: - if (lastFcmpg == 1) { - c->fjuo(cont); - c->fjl(target); - } else if (lastFcmpl == 1) { - c->fjl(target); - } else { - c->jl(target); - } + c->jumpIfLess(4, a, b, target); break; case ifle: - if(lastFcmpg == 1) { - c->fjuo(cont); - c->fjle(target); - } else if (lastFcmpl == 1) { - c->fjle(target); - } else { - c->jle(target); - } + c->jumpIfLessOrEqual(4, a, b, target); break; + default: + abort(t); } saveStateAndCompile(t, frame, newIp); @@ -3610,14 +3662,14 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, uint32_t newIp = (ip - 3) + offset; assert(t, newIp < codeLength(t, code)); - Compiler::Operand* a = frame->popObject(); + Compiler::Operand* a = c->constant(0, Compiler::ObjectType); + Compiler::Operand* b = frame->popObject(); Compiler::Operand* target = frame->machineIp(newIp); - c->cmp(BytesPerWord, c->constant(0, Compiler::ObjectType), a); if (instruction == ifnull) { - c->je(target); + c->jumpIfEqual(BytesPerWord, a, btarget); } else { - c->jne(target); + c->jumpIfNotEqual(BytesPerWord, a, btarget); } saveStateAndCompile(t, frame, newIp); @@ -3971,7 +4023,15 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, Compiler::Operand* a = frame->popLong(); Compiler::Operand* b = frame->popLong(); - frame->pushInt(c->lcmp(a, b)); + if (not integerBranch(frame, ip, 8, a, b)) { + frame->pushInt + (c->call + (c->constant + (getThunk(t, compareLongsThunk), Compiler::AddressType), + 0, 0, 4, Compiler::IntegerType, 4, + static_cast(0), a, + static_cast(0), b)); + } } break; case lconst_0: @@ -4522,15 +4582,15 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, Compiler::Operand* key = frame->popInt(); - c->cmp(4, c->constant(bottom, Compiler::IntegerType), key); - c->jl(frame->machineIp(defaultIp)); + c->jumpIfLess(4, c->constant(bottom, Compiler::IntegerType), key, + frame->machineIp(defaultIp)); c->save(1, key); saveStateAndCompile(t, frame, defaultIp); - c->cmp(4, c->constant(top, Compiler::IntegerType), key); - c->jg(frame->machineIp(defaultIp)); + c->jumpIfGreater(4, c->constant(top, Compiler::IntegerType), key, + frame->machineIp(defaultIp)); c->save(1, key); diff --git a/src/compiler.cpp b/src/compiler.cpp index d5e1db2bd9..1ddcbd4f9d 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -66,13 +66,6 @@ apply(Context* c, TernaryOperation op, unsigned s2Size, Site* s2Low, Site* s2High, unsigned s3Size, Site* s3Low, Site* s3High); -enum ConstantCompare { - CompareNone, - CompareLess, - CompareGreater, - CompareEqual -}; - class Cell { public: Cell(Cell* next, void* value): next(next), value(value) { } @@ -385,8 +378,7 @@ class Context { localFootprint(0), machineCodeSize(0), alignedFrameSize(0), - availableGeneralRegisterCount(generalRegisterLimit - generalRegisterStart), - constantCompare(CompareNone) + availableGeneralRegisterCount(generalRegisterLimit - generalRegisterStart) { for (unsigned i = generalRegisterStart; i < generalRegisterLimit; ++i) { new (registerResources + i) RegisterResource(arch->reserved(i)); @@ -433,7 +425,6 @@ class Context { unsigned machineCodeSize; unsigned alignedFrameSize; unsigned availableGeneralRegisterCount; - ConstantCompare constantCompare; }; unsigned @@ -3459,82 +3450,6 @@ findConstantSite(Context* c, Value* v) return 0; } -class CompareEvent: public Event { - public: - CompareEvent(Context* c, BinaryOperation type, unsigned size, Value* first, - Value* second, const SiteMask& firstMask, - const SiteMask& secondMask): - Event(c), type(type), size(size), first(first), second(second) - { - assert(c, type != FloatCompare or - (first->type == ValueFloat and first->type == ValueFloat)); - - addReads(c, this, first, size, firstMask, firstMask); - addReads(c, this, second, size, secondMask, secondMask); - } - - virtual const char* name() { - return "CompareEvent"; - } - - virtual void compile(Context* c) { - ConstantSite* firstConstant = findConstantSite(c, first); - ConstantSite* secondConstant = findConstantSite(c, second); - - if (firstConstant and secondConstant) { - int64_t d = firstConstant->value->value() - - secondConstant->value->value(); - - if (d < 0) { - c->constantCompare = CompareLess; - } else if (d > 0) { - c->constantCompare = CompareGreater; - } else { - c->constantCompare = CompareEqual; - } - } else { - c->constantCompare = CompareNone; - - apply(c, type, size, first->source, first->source, - size, second->source, second->source); - } - - for (Read* r = reads; r; r = r->eventNext) { - popRead(c, this, r->value); - } - } - - BinaryOperation type; - unsigned size; - Value* first; - Value* second; -}; - -void -appendCompare(Context* c, BinaryOperation op, unsigned size, Value* first, - Value* second) -{ - bool thunk; - uint8_t firstTypeMask; - uint64_t firstRegisterMask; - uint8_t secondTypeMask; - uint64_t secondRegisterMask; - - c->arch->planSource - (op, size, &firstTypeMask, &firstRegisterMask, size, &thunk); - - assert(c, not thunk); // todo - - c->arch->planDestination - (op, size, 0, 0, size, &secondTypeMask, &secondRegisterMask); - - append(c, new (c->zone->allocate(sizeof(CompareEvent))) - CompareEvent - (c, op, size, first, second, - SiteMask(firstTypeMask, firstRegisterMask, AnyFrameIndex), - SiteMask(secondTypeMask, secondRegisterMask, AnyFrameIndex))); -} - void preserve(Context* c, Value* v, Site* s, Read* r) { @@ -3576,12 +3491,6 @@ getTarget(Context* c, Value* value, Value* result, const SiteMask& resultMask) return s; } -Site* -source(Value* v, Site* site) -{ - return v ? v->source : site; -} - void freezeSource(Context* c, unsigned size, Value* v) { @@ -3674,8 +3583,8 @@ class CombineEvent: public Event { // fprintf(stderr, "combine %p and %p into %p\n", first, second, result); apply(c, type, - firstSize, first->source, source(first->next, first->source), - secondSize, second->source, source(second->next, second->source), + firstSize, first->source, first->next->source), + secondSize, second->source, second->next->source), resultSize, low, high); thawSource(c, firstSize, first); @@ -4095,8 +4004,7 @@ class TranslateEvent: public Event { ? getTarget(c, value->next, result->next, resultHighMask) : low); - apply(c, type, - valueSize, value->source, source(value->next, value->source), + apply(c, type, valueSize, value->source, value->next->source), resultSize, low, high); for (Read* r = reads; r; r = r->eventNext) { @@ -4264,20 +4172,96 @@ 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 bitsToFloat(v); + } else { + return bitsToDouble(v); + } +} + +bool +unordered(double a, double b) +{ + return not (a >= b or a < b); +} + +bool +shouldJump(TernaryOperation type, unsigned size, int64_t a, int64_t b) +{ + switch (type) { + case JumpIfEqual: + return a == b; + + case JumpIfNotEqual: + return a != b; + + case JumpIfLess: + return a < b; + + case JumpIfGreater: + return a > b; + + case JumpIfLessOrEqual: + return a <= b; + + case JumpIfGreaterOrEqual: + return a >= b; + + case JumpIfFloatEqual: + return asFloat(size, a) == asFloat(size, b); + + case JumpIfFloatNotEqual: + return asFloat(size, a) != asFloat(size, b); + + case JumpIfFloatLess: + return asFloat(size, a) < asFloat(size, b); + + case JumpIfFloatGreater: + return asFloat(size, a) > asFloat(size, b); + + case JumpIfFloatLessOrEqual: + return asFloat(size, a) <= asFloat(size, b); + + case JumpIfFloatGreaterOrEqual: + return asFloat(size, a) >= asFloat(size, b); + + case JumpIfFloatLessOrUnordered: + return asFloat(size, a) < asFloat(size, b) + or unordered(asFloat(size, a), asFloat(size, b)); + + case JumpIfFloatGreaterOrUnordered: + return asFloat(size, a) > asFloat(size, b) + or unordered(asFloat(size, a), asFloat(size, b)); + + case JumpIfFloatLessOrEqualOrUnordered: + return asFloat(size, a) <= asFloat(size, b) + or unordered(asFloat(size, a), asFloat(size, b)); + + case JumpIfFloatGreaterOrEqualOrUnordered: + return asFloat(size, a) >= asFloat(size, b) + or unordered(asFloat(size, a), asFloat(size, b)); + + default: + jump = false; + } +} + class BranchEvent: public Event { public: - BranchEvent(Context* c, UnaryOperation type, Value* address, bool exit): - Event(c), type(type), address(address), exit(exit) + BranchEvent(Context* c, TernaryOperation type, unsigned size, + Value* first, Value* second, Value* address, bool exit, + const SiteMask& firstLowMask, + const SiteMask& firstHighMask, + const SiteMask& secondLowMask, + const SiteMask& secondHighMask): + Event(c), type(type), size(size), first(first), second(second), + address(address), exit(exit) { - bool thunk; - uint8_t typeMask; - uint64_t registerMask; - - c->arch->plan(type, BytesPerWord, &typeMask, ®isterMask, &thunk); - - assert(c, not thunk); - - addRead(c, this, address, SiteMask(typeMask, registerMask, AnyFrameIndex)); + addReads(c, this, first, firstSize, firstLowMask, firstHighMask); + addReads(c, this, second, secondSize, secondLowMask, secondHighMask); } virtual const char* name() { @@ -4285,67 +4269,27 @@ class BranchEvent: public Event { } virtual void compile(Context* c) { - bool jump; - UnaryOperation type = this->type; - if (type != Jump) { - switch (c->constantCompare) { - case CompareLess: - switch (type) { - case JumpIfLess: - case JumpIfLessOrEqual: - case JumpIfNotEqual: - jump = true; - type = Jump; - break; + ConstantSite* firstConstant = findConstantSite(c, first); + ConstantSite* secondConstant = findConstantSite(c, second); - default: - jump = false; - } - break; - - case CompareGreater: - switch (type) { - case JumpIfGreater: - case JumpIfGreaterOrEqual: - case JumpIfNotEqual: - jump = true; - type = Jump; - break; - - default: - jump = false; - } - break; - - case CompareEqual: - switch (type) { - case JumpIfEqual: - case JumpIfLessOrEqual: - case JumpIfGreaterOrEqual: - jump = true; - type = Jump; - break; - - default: - jump = false; - } - break; - - case CompareNone: - jump = true; - break; - - default: abort(c); + if (not unreachable(this)) { + if (firstConstant and secondConstant) { + if (shouldJump(type, firstConstant->value->value(), + secondConstant->value->value()) + and reachable) + { + apply(c, Jump, BytesPerWord, address->source, address->source); + } + } else { + apply(c, type, size, first->source, first->next->source, + size, second->source, second->next->sourcem + BytesPerWord, address->source, address->source); } - } else { - jump = true; } - if (jump and not unreachable(this)) { - apply(c, type, BytesPerWord, address->source, address->source); + for (Read* r = reads; r; r = r->eventNext) { + popRead(c, this, r->value); } - - popRead(c, this, address); } virtual bool isBranch() { return true; } @@ -4355,10 +4299,57 @@ class BranchEvent: public Event { } UnaryOperation type; + unsigned size; + Value* first; + Value* second; Value* address; bool exit; }; +void +appendBranch(Context* c, TernaryOperation type, unsigned size, Value* first, + Value* second, Value* address, bool exit = false) +{ + bool thunk; + uint8_t firstTypeMask; + uint64_t firstRegisterMask; + uint8_t secondTypeMask; + uint64_t secondRegisterMask; + + c->arch->planSource(type, size, &firstTypeMask, &firstRegisterMask, + size, &secondTypeMask, &secondRegisterMask, + resultSize, &thunk); + + if (thunk) { + Stack* oldStack = c->stack; + + local::push(c, ceiling(size, BytesPerWord), second, false); + local::push(c, ceiling(size, BytesPerWord), first, false); + + Stack* argumentStack = c->stack; + c->stack = oldStack; + + Value* result = value(&c, ValueGeneral); + appendCall + (c, value + (c, ValueGeneral, constantSite(c, c->client->getThunk(type, size, 4))), + 0, 0, result, resultSize, argumentStack, + ceiling(size, BytesPerWord) * 2, 0); + + appendBranch(c, JumpIfEqual, 4, value(c, ValueGeneral, constantSite(c, 0)), + result, address); + } else { + append + (c, new (c->zone->allocate(sizeof(BranchEvent))) + BranchEvent + (c, type, size, first, second, address, exit, + SiteMask(firstTypeMask, firstRegisterMask, AnyFrameIndex), + SiteMask(firstTypeMask, firstRegisterMask >> 32, AnyFrameIndex), + SiteMask(secondTypeMask, secondRegisterMask, AnyFrameIndex), + SiteMask(secondTypeMask, secondRegisterMask >> 32, AnyFrameIndex))); + } +} + void appendBranch(Context* c, UnaryOperation type, Value* address, bool exit = false) @@ -4396,11 +4387,10 @@ class BoundsCheckEvent: public Event { outOfBoundsPromise = codePromise(c, static_cast(0)); Site* zero = constantSite(c, resolved(c, 0)); - apply(c, Compare, 4, zero, zero, 4, index->source, index->source); - Assembler::Constant outOfBoundsConstant(outOfBoundsPromise); a->apply - (JumpIfLess, BytesPerWord, ConstantOperand, &outOfBoundsConstant); + (JumpIfLess, 4, zero, zero, 4, index->source, index->source, + BytesPerWord, ConstantOperand, &outOfBoundsConstant); } assert(c, object->source->type(c) == RegisterOperand); @@ -4408,10 +4398,9 @@ class BoundsCheckEvent: public Event { lengthOffset, NoRegister, 1); length.acquired = true; - apply(c, Compare, 4, index->source, index->source, 4, &length, &length); - Assembler::Constant nextConstant(nextPromise); - a->apply(JumpIfGreater, BytesPerWord, ConstantOperand, &nextConstant); + a->apply(JumpIfGreater, 4, index->source, index->source, 4, &length, + &length, BytesPerWord, ConstantOperand, &nextConstant); if (constant == 0) { outOfBoundsPromise->offset = a->offset(); @@ -5953,88 +5942,176 @@ class MyCompiler: public Compiler { return dst; } - virtual Operand* lcmp(Operand* a, Operand* b) { + virtual void jumpIfEqual(unsigned size, Operand* a, Operand* b, + Operand* address) + { assert(&c, static_cast(a)->type == ValueGeneral and static_cast(b)->type == ValueGeneral); - Value* result = value(&c, ValueGeneral); - appendCombine(&c, LongCompare, 8, static_cast(a), - 8, static_cast(b), 8, result); - return result; + + appendBranch(&c, JumpIfEqual, size, static_cast(a), + static_cast(b), static_cast(address)); } - virtual void cmp(unsigned size, Operand* a, Operand* b) { + virtual void jumpIfNotEqual(unsigned size, Operand* a, Operand* b, + Operand* address) + { assert(&c, static_cast(a)->type == ValueGeneral and static_cast(b)->type == ValueGeneral); - appendCompare(&c, Compare, size, static_cast(a), - static_cast(b)); + + appendBranch(&c, JumpIfNotEqual, size, static_cast(a), + static_cast(b), static_cast(address)); } - virtual void fcmp(unsigned size, Operand* a, Operand* b) { + virtual void jumpIfLess(unsigned size, Operand* a, Operand* b, + Operand* address) + { + assert(&c, static_cast(a)->type == ValueGeneral + and static_cast(b)->type == ValueGeneral); + + appendBranch(&c, JumpIfLess, size, static_cast(a), + static_cast(b), static_cast(address)); + } + + virtual void jumpIfGreater(unsigned size, Operand* a, Operand* b, + Operand* address) + { + assert(&c, static_cast(a)->type == ValueGeneral + and static_cast(b)->type == ValueGeneral); + + appendBranch(&c, JumpIfGreater, size, static_cast(a), + static_cast(b), static_cast(address)); + } + + virtual void jumpIfLessOrEqual(unsigned size, Operand* a, Operand* b, + Operand* address) + { + assert(&c, static_cast(a)->type == ValueGeneral + and static_cast(b)->type == ValueGeneral); + + appendBranch(&c, JumpIfLessOrEqual, size, static_cast(a), + static_cast(b), static_cast(address)); + } + + virtual void jumpIfGreaterOrEqual(unsigned size, Operand* a, Operand* b, + Operand* address) + { + assert(&c, static_cast(a)->type == ValueGeneral + and static_cast(b)->type == ValueGeneral); + + appendBranch(&c, JumpIfGreaterOrEqual, size, static_cast(a), + static_cast(b), static_cast(address)); + } + + virtual void jumpIfFloatEqual(unsigned size, Operand* a, Operand* b, + Operand* address) + { assert(&c, static_cast(a)->type == ValueFloat and static_cast(b)->type == ValueFloat); - appendCompare(&c, FloatCompare, size, static_cast(a), - static_cast(b)); - } - - virtual void jl(Operand* address) { - appendBranch(&c, JumpIfLess, static_cast(address)); + appendBranch(&c, JumpIfFloatEqual, size, static_cast(a), + static_cast(b), static_cast(address)); } - virtual void jg(Operand* address) { - appendBranch(&c, JumpIfGreater, static_cast(address)); + virtual void jumpIfFloatNotEqual(unsigned size, Operand* a, Operand* b, + Operand* address) + { + assert(&c, static_cast(a)->type == ValueFloat + and static_cast(b)->type == ValueFloat); + + appendBranch(&c, JumpIfFloatNotEqual, size, static_cast(a), + static_cast(b), static_cast(address)); } - virtual void jle(Operand* address) { - appendBranch(&c, JumpIfLessOrEqual, static_cast(address)); + virtual void jumpIfFloatLess(unsigned size, Operand* a, Operand* b, + Operand* address) + { + assert(&c, static_cast(a)->type == ValueFloat + and static_cast(b)->type == ValueFloat); + + appendBranch(&c, JumpIfFloatLess, size, static_cast(a), + static_cast(b), static_cast(address)); } - virtual void jge(Operand* address) { - appendBranch(&c, JumpIfGreaterOrEqual, static_cast(address)); + virtual void jumpIfFloatGreater(unsigned size, Operand* a, Operand* b, + Operand* address) + { + assert(&c, static_cast(a)->type == ValueFloat + and static_cast(b)->type == ValueFloat); + + appendBranch(&c, JumpIfFloatGreater, size, static_cast(a), + static_cast(b), static_cast(address)); } - virtual void je(Operand* address) { - appendBranch(&c, JumpIfEqual, static_cast(address)); + virtual void jumpIfFloatLessOrEqual(unsigned size, Operand* a, Operand* b, + Operand* address) + { + assert(&c, static_cast(a)->type == ValueFloat + and static_cast(b)->type == ValueFloat); + + appendBranch(&c, JumpIfFloatLessOrEqual, size, static_cast(a), + static_cast(b), static_cast(address)); } - virtual void jne(Operand* address) { - appendBranch(&c, JumpIfNotEqual, static_cast(address)); + virtual void jumpIfFloatGreaterOrEqual(unsigned size, Operand* a, Operand* b, + Operand* address) + { + assert(&c, static_cast(a)->type == ValueFloat + and static_cast(b)->type == ValueFloat); + + appendBranch(&c, JumpIfFloatGreaterOrEqual, size, static_cast(a), + static_cast(b), static_cast(address)); } - virtual void fjl(Operand* address) { - appendBranch(&c, JumpIfFloatLess, static_cast(address)); + virtual void jumpIfFloatLessOrUnordered(unsigned size, Operand* a, + Operand* b, Operand* address) + { + assert(&c, static_cast(a)->type == ValueFloat + and static_cast(b)->type == ValueFloat); + + appendBranch(&c, JumpIfFloatLessOrUnordered, size, static_cast(a), + static_cast(b), static_cast(address)); } - virtual void fjg(Operand* address) { - appendBranch(&c, JumpIfFloatGreater, static_cast(address)); + virtual void jumpIfFloatGreaterOrUnordered(unsigned size, Operand* a, + Operand* b, Operand* address) + { + assert(&c, static_cast(a)->type == ValueFloat + and static_cast(b)->type == ValueFloat); + + appendBranch(&c, JumpIfFloatGreaterOrUnordered, size, + static_cast(a), static_cast(b), + static_cast(address)); } - virtual void fjle(Operand* address) { - appendBranch(&c, JumpIfFloatLessOrEqual, static_cast(address)); + virtual void jumpIfFloatLessOrEqualOrUnordered(unsigned size, Operand* a, + Operand* b, Operand* address) + { + assert(&c, static_cast(a)->type == ValueFloat + and static_cast(b)->type == ValueFloat); + + appendBranch(&c, JumpIfFloatLessOrEqualOrUnordered, size, + static_cast(a), static_cast(b), + static_cast(address)); } - virtual void fjge(Operand* address) { - appendBranch(&c, JumpIfFloatGreaterOrEqual, static_cast(address)); - } + virtual void jumpIfFloatGreaterOrEqualOrUnordered(unsigned size, Operand* a, + Operand* b, + Operand* address) + { + assert(&c, static_cast(a)->type == ValueFloat + and static_cast(b)->type == ValueFloat); - virtual void fje(Operand* address) { - appendBranch(&c, JumpIfFloatEqual, static_cast(address)); - } - - virtual void fjne(Operand* address) { - appendBranch(&c, JumpIfFloatNotEqual, static_cast(address)); - } - - virtual void fjuo(Operand* address) { - appendBranch(&c, JumpIfFloatUnordered, static_cast(address)); + appendBranch(&c, JumpIfFloatGreaterOrEqualOrUnordered, size, + static_cast(a), static_cast(b), + static_cast(address)); } virtual void jmp(Operand* address) { - appendBranch(&c, Jump, static_cast(address)); + appendBranch(&c, Jump, 0, 0, 0, static_cast(address)); } virtual void exit(Operand* address) { - appendBranch(&c, Jump, static_cast(address), true); + appendBranch(&c, Jump, 0, 0, 0, static_cast(address), true); } virtual Operand* add(unsigned size, Operand* a, Operand* b) { diff --git a/src/compiler.h b/src/compiler.h index 0d4f9fa8fc..2a1b197cf4 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -120,22 +120,41 @@ class Compiler { unsigned dstSize) = 0; virtual Operand* loadz(unsigned size, unsigned srcSelectSize, Operand* src, unsigned dstSize) = 0; - virtual Operand* lcmp(Operand* a, Operand* b) = 0; - virtual void cmp(unsigned size, Operand* a, Operand* b) = 0; - virtual void fcmp(unsigned size, Operand* a, Operand* b) = 0; - virtual void jl(Operand* address) = 0; - virtual void jg(Operand* address) = 0; - virtual void jle(Operand* address) = 0; - virtual void jge(Operand* address) = 0; - virtual void je(Operand* address) = 0; - virtual void jne(Operand* address) = 0; - virtual void fjl(Operand* address) = 0; - virtual void fjg(Operand* address) = 0; - virtual void fjle(Operand* address) = 0; - virtual void fjge(Operand* address) = 0; - virtual void fje(Operand* address) = 0; - virtual void fjne(Operand* address) = 0; - virtual void fjuo(Operand* address) = 0; + + virtual void jumpIfEqual + (unsigned size, Operand* a, Operand* b, Operand* address) = 0; + virtual void jumpIfNotEqual + (unsigned size, Operand* a, Operand* b, Operand* address) = 0; + virtual void jumpIfLess + (unsigned size, Operand* a, Operand* b, Operand* address) = 0; + virtual void jumpIfGreater + (unsigned size, Operand* a, Operand* b, Operand* address) = 0; + virtual void jumpIfLessOrEqual + (unsigned size, Operand* a, Operand* b, Operand* address) = 0; + virtual void jumpIfGreaterOrEqual + (unsigned size, Operand* a, Operand* b, Operand* address) = 0; + + virtual void jumpIfFloatEqual + (unsigned size, Operand* a, Operand* b, Operand* address) = 0; + virtual void jumpIfFloatNotEqual + (unsigned size, Operand* a, Operand* b, Operand* address) = 0; + virtual void jumpIfFloatLess + (unsigned size, Operand* a, Operand* b, Operand* address) = 0; + virtual void jumpIfFloatGreater + (unsigned size, Operand* a, Operand* b, Operand* address) = 0; + virtual void jumpIfFloatLessOrEqual + (unsigned size, Operand* a, Operand* b, Operand* address) = 0; + virtual void jumpIfFloatGreaterOrEqual + (unsigned size, Operand* a, Operand* b, Operand* address) = 0; + virtual void jumpIfFloatLessOrUnordered + (unsigned size, Operand* a, Operand* b, Operand* address) = 0; + virtual void jumpIfFloatGreaterOrUnordered + (unsigned size, Operand* a, Operand* b, Operand* address) = 0; + virtual void jumpIfFloatLessOrEqualOrUnordered + (unsigned size, Operand* a, Operand* b, Operand* address) = 0; + virtual void jumpIfFloatGreaterOrEqualOrUnordered + (unsigned size, Operand* a, Operand* b, Operand* address) = 0; + virtual void jmp(Operand* address) = 0; virtual void exit(Operand* address) = 0; virtual Operand* add(unsigned size, Operand* a, Operand* b) = 0; diff --git a/src/powerpc.cpp b/src/powerpc.cpp index f11efa9d12..76c48921a7 100644 --- a/src/powerpc.cpp +++ b/src/powerpc.cpp @@ -1847,10 +1847,6 @@ class MyArchitecture: public Assembler::Architecture { return NoTernaryOperation; } - virtual bool supportsFloatCompare(unsigned) { - return false; - } - virtual bool alwaysCondensed(BinaryOperation) { return false; } diff --git a/src/thunks.cpp b/src/thunks.cpp index bb1721ffe1..ec1e9caddd 100644 --- a/src/thunks.cpp +++ b/src/thunks.cpp @@ -4,6 +4,7 @@ THUNK(compareDoublesG) THUNK(compareDoublesL) THUNK(compareFloatsG) THUNK(compareFloatsL) +THUNK(compareLongs) THUNK(addDouble) THUNK(subtractDouble) THUNK(multiplyDouble) diff --git a/src/x86.cpp b/src/x86.cpp index d492285387..b7d39bf993 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -2713,10 +2713,6 @@ class MyArchitecture: public Assembler::Architecture { return 0; } - virtual bool supportsFloatCompare(unsigned) { - return supportsSSE(); - } - virtual bool alwaysCondensed(BinaryOperation op) { switch(op) {