refactor intrinsic support

This ensures that the low-level, architecture specific code need not
be aware of the semantics and names of Java methods.
This commit is contained in:
Joel Dice 2009-10-17 19:26:14 -06:00
parent f702795178
commit 15020d77a6
6 changed files with 156 additions and 144 deletions

View File

@ -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,

View File

@ -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<char*>(&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<char*>
(&byteArrayBody(t, className(t, methodClass(t, target)), 0)),
reinterpret_cast<char*>
(&byteArrayBody(t, methodName(t, target), 0)),
reinterpret_cast<char*>
(&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<char*>
(&byteArrayBody(t, className(t, methodClass(t, target)), 0)),
reinterpret_cast<char*>
(&byteArrayBody(t, methodName(t, target), 0)),
reinterpret_cast<char*>
(&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);
}

View File

@ -6370,23 +6370,27 @@ class MyCompiler: public Compiler {
(&c, FloatNegate, size, static_cast<Value*>(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<Value*>(a), resSize, result);
virtual Operand* abs(unsigned size, Operand* a) {
assert(&c, static_cast<Value*>(a)->type == ValueGeneral);
Value* result = value(&c, ValueGeneral);
appendTranslate(&c, Absolute, size, static_cast<Value*>(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<Value*>(a), bSize, static_cast<Value*>(b),
resSize, result);
virtual Operand* fabs(unsigned size, Operand* a) {
assert(&c, static_cast<Value*>(a)->type == ValueFloat);
Value* result = value(&c, ValueFloat);
appendTranslate
(&c, FloatAbsolute, size, static_cast<Value*>(a), size, result);
return result;
}
virtual Operand* fsqrt(unsigned size, Operand* a) {
assert(&c, static_cast<Value*>(a)->type == ValueFloat);
Value* result = value(&c, ValueFloat);
appendTranslate
(&c, FloatSquareRoot, size, static_cast<Value*>(a), size, result);
return result;
}

View File

@ -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;

View File

@ -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)

View File

@ -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<uint64_t>(1) << rax);
break;
case Abs:
case Absolute:
*aTypeMask = (1 << RegisterOperand);
*aRegisterMask = (static_cast<uint64_t>(1) << rax);
break;
case FloatAbs:
case FloatAbsolute:
*aTypeMask = (1 << RegisterOperand);
*aRegisterMask = (static_cast<uint64_t>(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<uint64_t>(FloatRegisterMask) << 32)
| FloatRegisterMask;
@ -3025,12 +3025,12 @@ class MyArchitecture: public Assembler::Architecture {
| (static_cast<uint64_t>(GeneralRegisterMask) << 32);
switch (op) {
case Abs:
case Absolute:
*bTypeMask = (1 << RegisterOperand);
*bRegisterMask = (static_cast<uint64_t>(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);