From 15020d77a6ec1b72f65b85049aa4bc432227327f Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 17 Oct 2009 19:26:14 -0600 Subject: [PATCH] refactor intrinsic support This ensures that the low-level, architecture specific code need not be aware of the semantics and names of Java methods. --- src/assembler.h | 16 +--- src/compile.cpp | 203 +++++++++++++++++++++++++---------------------- src/compiler.cpp | 34 ++++---- src/compiler.h | 9 +-- src/thunks.cpp | 2 + src/x86.cpp | 36 ++++----- 6 files changed, 156 insertions(+), 144 deletions(-) diff --git a/src/assembler.h b/src/assembler.h index 0334c716ea..9a7f19724d 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -56,14 +56,14 @@ enum BinaryOperation { Float2Float, Float2Int, Int2Float, - FloatSqrt, - FloatAbs, - Abs, + FloatSquareRoot, + FloatAbsolute, + Absolute, NoBinaryOperation = -1 }; -const unsigned BinaryOperationCount = Abs + 1; +const unsigned BinaryOperationCount = Absolute + 1; enum TernaryOperation { Add, @@ -343,14 +343,6 @@ class Assembler { virtual int returnAddressOffset() = 0; virtual int framePointerOffset() = 0; virtual void nextFrame(void** stack, void** base) = 0; - - virtual BinaryOperation binaryIntrinsic(const char* className, - const char* methodName, - const char* parameterSpec) = 0; - - virtual TernaryOperation ternaryIntrinsic(const char* className, - const char* methodName, - const char* parameterSpec) = 0; virtual void plan (UnaryOperation op, diff --git a/src/compile.cpp b/src/compile.cpp index e123bac0ed..c704e18160 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -783,51 +783,76 @@ class Context { virtual intptr_t getThunk(BinaryOperation op, unsigned size, unsigned resultSize) { - switch(op) { - case FloatNegate: - if (size == 4) { - return local::getThunk(t, negateFloatThunk); - } else { + if (size == 8) { + switch(op) { + case FloatNegate: + assert(t, resultSize == 8); return local::getThunk(t, negateDoubleThunk); - } - case Float2Float: - if (size == 4 and resultSize == 8) { - return local::getThunk(t, floatToDoubleThunk); - } else if (size == 8 and resultSize == 4) { + case FloatSquareRoot: + assert(t, resultSize == 8); + return local::getThunk(t, squareRootDoubleThunk); + + case Float2Float: + assert(t, resultSize == 4); return local::getThunk(t, doubleToFloatThunk); - } - case Float2Int: - if (size == 4 and resultSize == 4) { - return local::getThunk(t, floatToIntThunk); - } else if (size == 4 and resultSize == 8) { - return local::getThunk(t, floatToLongThunk); - } else if (size == 8 and resultSize == 4) { - return local::getThunk(t, doubleToIntThunk); - } else if (size == 8 and resultSize == 8) { - return local::getThunk(t, doubleToLongThunk); - } + case Float2Int: + if (resultSize == 8) { + return local::getThunk(t, doubleToLongThunk); + } else { + assert(t, resultSize == 4); + return local::getThunk(t, doubleToIntThunk); + } - case Int2Float: - if (size == 4 and resultSize == 4) { - return local::getThunk(t, intToFloatThunk); - } else if (size == 4 and resultSize == 8) { - return local::getThunk(t, intToDoubleThunk); - } else if (size == 8 and resultSize == 4) { - return local::getThunk(t, longToFloatThunk); - } else if (size == 8 and resultSize == 8) { - return local::getThunk(t, longToDoubleThunk); - } + case Int2Float: + if (resultSize == 8) { + return local::getThunk(t, longToDoubleThunk); + } else { + assert(t, resultSize == 4); + return local::getThunk(t, longToFloatThunk); + } - default: break; + default: abort(t); + } + } else { + assert(t, size == 4); + + switch(op) { + case FloatNegate: + assert(t, size == 4); + return local::getThunk(t, negateFloatThunk); + + case FloatAbsolute: + assert(t, size == 4); + return local::getThunk(t, absoluteFloatThunk); + + case Float2Float: + assert(t, resultSize == 8); + return local::getThunk(t, floatToDoubleThunk); + + case Float2Int: + if (resultSize == 4) { + return local::getThunk(t, floatToIntThunk); + } else { + assert(t, resultSize == 8); + return local::getThunk(t, floatToLongThunk); + } + + case Int2Float: + if (resultSize == 4) { + return local::getThunk(t, intToFloatThunk); + } else { + assert(t, resultSize == 8); + return local::getThunk(t, intToDoubleThunk); + } + + default: abort(t); + } } - - abort(t); } - virtual intptr_t getThunk(TernaryOperation op, unsigned size, unsigned) - { + virtual intptr_t getThunk(TernaryOperation op, unsigned size, unsigned) { if (size == 8) { switch (op) { case Divide: @@ -862,9 +887,10 @@ class Context { case JumpIfFloatLessOrEqualOrUnordered: return local::getThunk(t, compareDoublesLThunk); - default: break; + default: abort(t); } - } else if (size == 4) { + } else { + assert(t, size == 4); switch (op) { case FloatAdd: return local::getThunk(t, addFloatThunk); @@ -889,11 +915,9 @@ class Context { case JumpIfFloatLessOrEqualOrUnordered: return local::getThunk(t, compareFloatsLThunk); - default: break; + default: abort(t); } } - - abort(t); } MyThread* t; @@ -2055,6 +2079,12 @@ negateDouble(uint64_t a) return doubleToBits(- bitsToDouble(a)); } +uint64_t +squareRootDouble(uint64_t a) +{ + return doubleToBits(sqrt(bitsToDouble(a))); +} + uint64_t doubleToFloat(int64_t a) { @@ -2109,6 +2139,12 @@ negateFloat(uint32_t a) return floatToBits(- bitsToFloat(a)); } +uint64_t +absoluteFloat(uint32_t a) +{ + return floatToBits(fabsf(bitsToFloat(a))); +} + int64_t divideLong(int64_t b, int64_t a) { @@ -2868,6 +2904,38 @@ floatBranch(MyThread* t, Frame* frame, object code, unsigned& ip, return t->exception == 0; } +bool +intrinsic(MyThread* t, Frame* frame, object target) +{ +#define MATCH(name, constant) \ + (byteArrayLength(t, name) - 1 == sizeof(constant) \ + and strcmp(reinterpret_cast(&byteArrayBody(t, name, 0)), \ + constant) == 0) + + object className = vm::className(t, methodClass(t, target)); + if (UNLIKELY(MATCH(className, "java/lang/Math"))) { + Compiler* c = frame->c; + if (MATCH(methodName(t, target), "sqrt") + and MATCH(methodSpec(t, target), "(D)D")) + { + frame->pushLong(c->fsqrt(8, frame->popLong())); + return true; + } else if (MATCH(methodName(t, target), "abs")) { + if (MATCH(methodSpec(t, target), "(I)I")) { + frame->pushInt(c->abs(4, frame->popInt())); + return true; + } else if (MATCH(methodSpec(t, target), "(J)J")) { + frame->pushLong(c->abs(8, frame->popLong())); + return true; + } else if (MATCH(methodSpec(t, target), "(F)F")) { + frame->pushInt(c->fabs(4, frame->popInt())); + return true; + } + } + } + return false; +} + void compile(MyThread* t, Frame* initialFrame, unsigned ip, int exceptionHandlerStart) @@ -3878,58 +3946,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, assert(t, methodFlags(t, target) & ACC_STATIC); - bool usedIntrinsic = false; - int params = methodParameterCount(t, target); - if (params == 1) { - BinaryOperation op = t->arch->binaryIntrinsic - (reinterpret_cast - (&byteArrayBody(t, className(t, methodClass(t, target)), 0)), - reinterpret_cast - (&byteArrayBody(t, methodName(t, target), 0)), - reinterpret_cast - (&byteArrayBody(t, methodSpec(t, target), 0))); - - if (op != NoBinaryOperation) { - if (DebugIntrinsics) { - fprintf(stderr, "Using binary intrinsic %i.\n", op); - } - int opSize = methodParameterFootprint(t, target) * 4; - int resSize = resultSize(t, methodReturnCode(t, target)); - Compiler::Operand* param; - if (opSize == 4) { - param = frame->popInt(); - } else { - param = frame->popLong(); - } - Compiler::Operand* operand = c->operation - (op, opSize, resSize, operandTypeForFieldCode - (t, methodReturnCode(t, target)), param); - if (resSize == 4) { - frame->pushInt(operand); - } else { - frame->pushLong(operand); - } - usedIntrinsic = true; - } - } else if (params == 2) { - TernaryOperation op = t->arch->ternaryIntrinsic - (reinterpret_cast - (&byteArrayBody(t, className(t, methodClass(t, target)), 0)), - reinterpret_cast - (&byteArrayBody(t, methodName(t, target), 0)), - reinterpret_cast - (&byteArrayBody(t, methodSpec(t, target), 0))); - - if (op != NoTernaryOperation) { - if (DebugIntrinsics) { - fprintf(stderr, "Could use ternary intrinsic %i.\n", op); - } - //int aSize, bSize; - //int resSize = resultSize(t, methodReturnCode(t, target)); - //TODO: use intrinsic - } - } - if (not usedIntrinsic) { + if (not intrinsic(t, frame, target)) { bool tailCall = isTailCall(t, code, ip, context->method, target); compileDirectInvoke(t, frame, target, tailCall); } diff --git a/src/compiler.cpp b/src/compiler.cpp index c832ebb28d..9494ecf391 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -6370,23 +6370,27 @@ class MyCompiler: public Compiler { (&c, FloatNegate, size, static_cast(a), size, result); return result; } - - virtual Operand* operation(BinaryOperation op, unsigned aSize, - unsigned resSize, OperandType resType, Operand* a) - { - Value* result = value(&c, valueType(&c, resType)); - appendTranslate(&c, op, aSize, static_cast(a), resSize, result); + + virtual Operand* abs(unsigned size, Operand* a) { + assert(&c, static_cast(a)->type == ValueGeneral); + Value* result = value(&c, ValueGeneral); + appendTranslate(&c, Absolute, size, static_cast(a), size, result); return result; } - - virtual Operand* operation(TernaryOperation op, unsigned aSize, - unsigned bSize, unsigned resSize, - OperandType resType, Operand* a, Operand* b) - { - Value* result = value(&c, valueType(&c, resType)); - appendCombine - (&c, op, aSize, static_cast(a), bSize, static_cast(b), - resSize, result); + + virtual Operand* fabs(unsigned size, Operand* a) { + assert(&c, static_cast(a)->type == ValueFloat); + Value* result = value(&c, ValueFloat); + appendTranslate + (&c, FloatAbsolute, size, static_cast(a), size, result); + return result; + } + + virtual Operand* fsqrt(unsigned size, Operand* a) { + assert(&c, static_cast(a)->type == ValueFloat); + Value* result = value(&c, ValueFloat); + appendTranslate + (&c, FloatSquareRoot, size, static_cast(a), size, result); return result; } diff --git a/src/compiler.h b/src/compiler.h index 71d53d6622..a513e1e06b 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -176,12 +176,9 @@ class Compiler { virtual Operand* xor_(unsigned size, Operand* a, Operand* b) = 0; virtual Operand* neg(unsigned size, Operand* a) = 0; virtual Operand* fneg(unsigned size, Operand* a) = 0; - virtual Operand* operation(BinaryOperation op, unsigned aSize, - unsigned resSize, OperandType resType, - Operand* a) = 0; - virtual Operand* operation(TernaryOperation op, unsigned aSize, - unsigned bSize, unsigned resSize, - OperandType resType, Operand* a, Operand* b) = 0; + virtual Operand* abs(unsigned size, Operand* a) = 0; + virtual Operand* fabs(unsigned size, Operand* a) = 0; + virtual Operand* fsqrt(unsigned size, Operand* a) = 0; virtual Operand* f2f(unsigned aSize, unsigned resSize, Operand* a) = 0; virtual Operand* f2i(unsigned aSize, unsigned resSize, Operand* a) = 0; virtual Operand* i2f(unsigned aSize, unsigned resSize, Operand* a) = 0; diff --git a/src/thunks.cpp b/src/thunks.cpp index ec1e9caddd..26d77b4917 100644 --- a/src/thunks.cpp +++ b/src/thunks.cpp @@ -11,6 +11,7 @@ THUNK(multiplyDouble) THUNK(divideDouble) THUNK(moduloDouble) THUNK(negateDouble) +THUNK(squareRootDouble) THUNK(doubleToFloat) THUNK(doubleToInt) THUNK(doubleToLong) @@ -20,6 +21,7 @@ THUNK(multiplyFloat) THUNK(divideFloat) THUNK(moduloFloat) THUNK(negateFloat) +THUNK(absoluteFloat) THUNK(divideLong) THUNK(moduloLong) THUNK(floatToDouble) diff --git a/src/x86.cpp b/src/x86.cpp index 71287544a7..4695880619 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -2446,7 +2446,7 @@ floatNegateRR(Context* c, unsigned aSize, Assembler::Register* a, } void -floatAbsRR(Context* c, unsigned aSize UNUSED, Assembler::Register* a, +floatAbsoluteRR(Context* c, unsigned aSize UNUSED, Assembler::Register* a, unsigned bSize UNUSED, Assembler::Register* b) { assert(c, floatReg(a) and floatReg(b)); @@ -2471,7 +2471,7 @@ floatAbsRR(Context* c, unsigned aSize UNUSED, Assembler::Register* a, } void -absRR(Context* c, unsigned aSize, Assembler::Register* a, +absoluteRR(Context* c, unsigned aSize, Assembler::Register* a, unsigned bSize UNUSED, Assembler::Register* b UNUSED) { assert(c, aSize == bSize and a->low == rax and b->low == rax); @@ -2533,8 +2533,8 @@ populateTables(ArchitectureContext* c) bo[index(c, Move, C, M)] = CAST2(moveCM); bo[index(c, Move, A, R)] = CAST2(moveAR); - bo[index(c, FloatSqrt, R, R)] = CAST2(floatSqrtRR); - bo[index(c, FloatSqrt, M, R)] = CAST2(floatSqrtMR); + bo[index(c, FloatSquareRoot, R, R)] = CAST2(floatSqrtRR); + bo[index(c, FloatSquareRoot, M, R)] = CAST2(floatSqrtMR); bo[index(c, MoveZ, R, R)] = CAST2(moveZRR); bo[index(c, MoveZ, M, R)] = CAST2(moveZMR); @@ -2591,8 +2591,8 @@ populateTables(ArchitectureContext* c) bo[index(c, Int2Float, R, R)] = CAST2(int2FloatRR); bo[index(c, Int2Float, M, R)] = CAST2(int2FloatMR); - bo[index(c, Abs, R, R)] = CAST2(absRR); - bo[index(c, FloatAbs, R, R)] = CAST2(floatAbsRR); + bo[index(c, Absolute, R, R)] = CAST2(absoluteRR); + bo[index(c, FloatAbsolute, R, R)] = CAST2(floatAbsoluteRR); bro[branchIndex(c, R, R)] = CAST_BRANCH(branchRR); bro[branchIndex(c, C, R)] = CAST_BRANCH(branchCR); @@ -2839,13 +2839,13 @@ class MyArchitecture: public Assembler::Architecture { case Float2Float: case Float2Int: case Int2Float: - case FloatAbs: + case FloatAbsolute: case FloatNegate: - case FloatSqrt: + case FloatSquareRoot: return false; case Negate: - case Abs: + case Absolute: return true; default: @@ -2892,16 +2892,16 @@ class MyArchitecture: public Assembler::Architecture { and strcmp(methodName, "sqrt") == 0 and strcmp(parameterSpec, "(D)D") == 0) { - return FloatSqrt; + return FloatSquareRoot; } else if (strcmp(methodName, "abs")) { if (strcmp(parameterSpec, "(I)I") == 0 or strcmp(parameterSpec, "(J)J") == 0) { - return Abs; + return Absolute; } else if (useSSE(&c) and strcmp(parameterSpec, "(F)F") == 0) { - return FloatAbs; + return FloatAbsolute; } } } @@ -2933,12 +2933,12 @@ class MyArchitecture: public Assembler::Architecture { | (static_cast(1) << rax); break; - case Abs: + case Absolute: *aTypeMask = (1 << RegisterOperand); *aRegisterMask = (static_cast(1) << rax); break; - case FloatAbs: + case FloatAbsolute: *aTypeMask = (1 << RegisterOperand); *aRegisterMask = (static_cast(FloatRegisterMask) << 32) | FloatRegisterMask; @@ -2954,7 +2954,7 @@ class MyArchitecture: public Assembler::Architecture { } break; - case FloatSqrt: + case FloatSquareRoot: *aTypeMask = (1 << RegisterOperand) | (1 << MemoryOperand); *aRegisterMask = (static_cast(FloatRegisterMask) << 32) | FloatRegisterMask; @@ -3025,12 +3025,12 @@ class MyArchitecture: public Assembler::Architecture { | (static_cast(GeneralRegisterMask) << 32); switch (op) { - case Abs: + case Absolute: *bTypeMask = (1 << RegisterOperand); *bRegisterMask = (static_cast(1) << rax); break; - case FloatAbs: + case FloatAbsolute: *bTypeMask = (1 << RegisterOperand); *bRegisterMask = aRegisterMask; break; @@ -3041,7 +3041,7 @@ class MyArchitecture: public Assembler::Architecture { break; case FloatNegate: - case FloatSqrt: + case FloatSquareRoot: case Float2Float: case Int2Float: *bTypeMask = (1 << RegisterOperand);