Specialized code generation for more of the ConvXxxToDbl instructions.

Rather than using just two general purpose helpers, there are now some specialized helpers and more inline code. Also, the flags in ir.h are now more accurate.
Esse commit está contido em:
hermanv
2013-03-30 19:11:49 -07:00
commit de Sara Golemon
commit 090bc82fa2
4 arquivos alterados com 76 adições e 17 exclusões
+59 -11
Ver Arquivo
@@ -1708,16 +1708,72 @@ void CodeGenerator::cgConvToBool(IRInstruction* inst) {
}
}
static int64_t arrayToDoubleHelper(ArrayData* value) {
union {
int64_t intval;
double dblval;
} u;
u.dblval = value->empty() ? 0 : 1;
return u.intval;
}
void CodeGenerator::cgConvArrToDbl(IRInstruction* inst) {
cgConvGenToDbl(inst);
SSATmp* dst = inst->getDst();
SSATmp* src = inst->getSrc(0);
ArgGroup args;
args.ssa(src);
int64_t (*fPtr)(ArrayData*) = arrayToDoubleHelper;
cgCallHelper(m_as, (TCA)fPtr, dst, kNoSyncPoint, args);
}
void CodeGenerator::cgConvBoolToDbl(IRInstruction* inst) {
cgConvPrimitiveToDbl(inst);
// cvtsi2sd doesn't modify the high bits of its target, which can
// cause false dependencies to prevent register renaming from kicking
// in. Break the dependency chain by zeroing out xmm0.
m_as.pxor_xmm_xmm(xmm0, xmm0);
SSATmp* dst = inst->getDst();
auto dstReg = dst->getReg();
assert(dstReg != InvalidReg);
SSATmp* src = inst->getSrc(0);
auto srcReg = src->getReg();
if (srcReg == InvalidReg) {
assert(src->isConst());
int64_t constVal = src->getValRawInt();
if (constVal == 0) {
m_as.xor_reg64_reg64(dstReg, dstReg);
} else {
m_as.mov_imm64_reg(1, dstReg);
}
} else {
m_as.movzbl(rbyte(srcReg), r32(dstReg));
}
m_as.cvtsi2sd_reg64_xmm(dstReg, xmm0);
m_as.mov_xmm_reg64(xmm0, dstReg);
}
void CodeGenerator::cgConvIntToDbl(IRInstruction* inst) {
cgConvPrimitiveToDbl(inst);
// cvtsi2sd doesn't modify the high bits of its target, which can
// cause false dependencies to prevent register renaming from kicking
// in. Break the dependency chain by zeroing out xmm0.
m_as.pxor_xmm_xmm(xmm0, xmm0);
SSATmp* dst = inst->getDst();
auto dstReg = dst->getReg();
assert(dstReg != InvalidReg);
SSATmp* src = inst->getSrc(0);
auto srcReg = src->getReg();
if (srcReg == InvalidReg) {
assert(src->isConst());
int64_t constVal = src->getValRawInt();
if (constVal == 0) {
m_as.xor_reg64_reg64(dstReg, dstReg);
} else {
m_as.mov_imm64_reg(constVal, dstReg);
}
m_as.cvtsi2sd_reg64_xmm(dstReg, xmm0);
} else {
m_as.cvtsi2sd_reg64_xmm(srcReg, xmm0);
}
m_as.mov_xmm_reg64(xmm0, dstReg);
}
void CodeGenerator::cgConvObjToDbl(IRInstruction* inst) {
@@ -1743,14 +1799,6 @@ void CodeGenerator::cgConvGenToDbl(IRInstruction* inst) {
cgCallHelper(m_as, (TCA)fPtr, dst, kSyncPoint, args);
}
void CodeGenerator::cgConvPrimitiveToDbl(IRInstruction* inst) {
SSATmp* dst = inst->getDst();
SSATmp* src = inst->getSrc(0);
prepUnaryXmmOp(m_as, src, xmm0);
m_as.mov_xmm_reg64(xmm0, dst->getReg());
return;
}
void CodeGenerator::cgConvToInt(IRInstruction* inst) {
Type fromType = inst->getSrc(0)->getType();
SSATmp* dst = inst->getDst();
@@ -2046,6 +2046,7 @@ void HhbcTranslator::emitCastDouble() {
push(m_tb->genDefConst(0.0));
} else if (fromType.isArray()) {
push(m_tb->gen(ConvArrToDbl, src));
m_tb->genDecRef(src);
} else if (fromType.isBool()) {
push(m_tb->gen(ConvBoolToDbl, src));
} else if (fromType.isInt()) {
+3
Ver Arquivo
@@ -454,6 +454,9 @@ bool IRInstruction::killsSource(int idx) const {
case DecRef:
case ConvObjToArr:
case ConvGenToArr:
case ConvObjToDbl:
case ConvStrToDbl:
case ConvGenToDbl:
assert(idx == 0);
return true;
case ArraySet:
+13 -6
Ver Arquivo
@@ -167,22 +167,29 @@ O(OpAnd, D(Int), SNumInt SNumInt, C) \
O(OpOr, D(Int), SNum SNum, C) \
O(OpXor, D(Int), SNumInt SNumInt, C) \
O(OpMul, DParam, SNum SNum, C) \
\
O(ConvBoolToArr, D(Arr), S(Bool), C|N) \
O(ConvDblToArr, D(Arr), S(Dbl), C|N) \
O(ConvIntToArr, D(Arr), S(Int), C|N) \
O(ConvObjToArr, D(Arr), S(Obj), N|CRc|K) \
O(ConvStrToArr, D(Arr), S(Str), N|CRc) \
O(ConvGenToArr, D(Arr), S(Gen), N|CRc|K) \
\
O(ConvToBool, D(Bool), S(Gen), C|N) \
O(ConvArrToDbl, D(Dbl), S(Arr), N|CRc) \
O(ConvBoolToDbl, D(Dbl), S(Bool), C|N) \
O(ConvIntToDbl, D(Dbl), S(Int), C|N) \
O(ConvObjToDbl, D(Dbl), S(Obj), N|Er|CRc) \
O(ConvStrToDbl, D(Dbl), S(Str), N|CRc) \
O(ConvGenToDbl, D(Dbl), S(Gen), N|Er|CRc) \
\
O(ConvArrToDbl, D(Dbl), S(Arr), N) \
O(ConvBoolToDbl, D(Dbl), S(Bool), C|Rm) \
O(ConvIntToDbl, D(Dbl), S(Int), C|Rm) \
O(ConvObjToDbl, D(Dbl), S(Obj), N|Er|CRc|K) \
O(ConvStrToDbl, D(Dbl), S(Str), N|CRc|K) \
O(ConvGenToDbl, D(Dbl), S(Gen), N|Er|CRc|K) \
\
O(ConvToInt, D(Int), S(Gen), C|N) \
\
O(ConvToObj, D(Obj), S(Gen), C|N) \
\
O(ConvToStr, D(Str), S(Gen), C|N) \
\
O(ExtendsClass, D(Bool), S(Cls) C(Cls), C) \
O(IsTypeMem, D(Bool), S(PtrToGen), NA) \
O(IsNTypeMem, D(Bool), S(PtrToGen), NA) \