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:
@@ -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()) {
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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) \
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário