Split ConvToInt into subopcodes specialized by argument type.
We now have ConvArrToInt, ConvDblToInt, ConvObjToInt, ConvStrToInt and ConvGenToInt. This allows these opcodes to have separate flags.
Esse commit está contido em:
@@ -400,11 +400,15 @@ D:Dbl = ConvIntToDbl S0:Int
|
||||
D:Dbl = ConvObjToDbl S0:Obj
|
||||
D:Dbl = ConvStrToDbl S0:Str
|
||||
D:Dbl = ConvGenToDbl S0:Gen
|
||||
D:Int = ConvToInt S0:Gen
|
||||
D:Int = ConvArrToInt S0:Arr
|
||||
D:Int = ConvDblToInt S0:Dbl
|
||||
D:Int = ConvObjToInt S0:Obj
|
||||
D:Int = ConvStrToInt S0:Str
|
||||
D:Int = ConvGenToInt S0:Gen
|
||||
D:Obj = ConvoObj S0:Gen
|
||||
D:Str = ConvToStr S0:Gen
|
||||
|
||||
Convert S0 from its current type to destination type, according to the PHP
|
||||
Convert S0 from its current type to the destination type, according to the PHP
|
||||
semantics of such a conversion.
|
||||
|
||||
|
||||
|
||||
@@ -1808,44 +1808,93 @@ void CodeGenerator::cgConvGenToDbl(IRInstruction* inst) {
|
||||
cgCallHelper(m_as, (TCA)fPtr, dst, kSyncPoint, args);
|
||||
}
|
||||
|
||||
void CodeGenerator::cgConvToInt(IRInstruction* inst) {
|
||||
Type fromType = inst->getSrc(0)->getType();
|
||||
static int64_t arrayToIntHelper(ArrayData* value) {
|
||||
return value->empty() ? 0 : 1;
|
||||
}
|
||||
|
||||
void CodeGenerator::cgConvArrToInt(IRInstruction* inst) {
|
||||
SSATmp* dst = inst->getDst();
|
||||
SSATmp* src = inst->getSrc(0);
|
||||
ArgGroup args;
|
||||
args.ssa(src);
|
||||
int64_t (*fPtr)(ArrayData*) = arrayToIntHelper;
|
||||
cgCallHelper(m_as, (TCA)fPtr, dst, kNoSyncPoint, args);
|
||||
}
|
||||
|
||||
void CodeGenerator::cgConvBoolToInt(IRInstruction* inst) {
|
||||
SSATmp* dst = inst->getDst();
|
||||
auto dstReg = dst->getReg();
|
||||
assert(dstReg != InvalidReg);
|
||||
SSATmp* src = inst->getSrc(0);
|
||||
auto srcReg = src->getReg();
|
||||
|
||||
bool srcIsConst = src->isConst();
|
||||
|
||||
if (fromType == Type::Bool) {
|
||||
// Bool -> Int is just a move
|
||||
if (srcIsConst) {
|
||||
int64_t constVal = src->getValRawInt();
|
||||
if (constVal == 0) {
|
||||
m_as.xor_reg64_reg64(dstReg, dstReg);
|
||||
} else {
|
||||
m_as.mov_imm64_reg(1, dstReg);
|
||||
}
|
||||
assert(src->isConst() == (srcReg == InvalidReg));
|
||||
if (srcReg == InvalidReg) {
|
||||
int64_t constVal = src->getValRawInt();
|
||||
if (constVal == 0) {
|
||||
m_as.xor_reg64_reg64(dstReg, dstReg);
|
||||
} else {
|
||||
m_as.movzbl (rbyte(srcReg), r32(dstReg));
|
||||
m_as.mov_imm64_reg(1, dstReg);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
m_as.movzbl(rbyte(srcReg), r32(dstReg));
|
||||
}
|
||||
if (fromType.isString()) {
|
||||
if (srcIsConst) {
|
||||
auto val = src->getValStr()->toInt64();
|
||||
m_as.mov_imm64_reg(val, dstReg);
|
||||
} else {
|
||||
ArgGroup args;
|
||||
args.ssa(src).imm(10);
|
||||
cgCallHelper(m_as,
|
||||
Transl::Call(getMethodPtr(&StringData::toInt64)),
|
||||
dstReg, kNoSyncPoint, args);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
HOT_FUNC_VM static int64_t doubleToIntHelper(int64_t value) {
|
||||
union {
|
||||
int64_t intval;
|
||||
double dblval;
|
||||
} u;
|
||||
u.intval = value;
|
||||
double d = u.dblval;
|
||||
return (d >= 0 ? d > std::numeric_limits<uint64_t>::max() ? 0u :
|
||||
(uint64_t)d : (int64_t)d);
|
||||
}
|
||||
|
||||
void CodeGenerator::cgConvDblToInt(IRInstruction* inst) {
|
||||
SSATmp* dst = inst->getDst();
|
||||
SSATmp* src = inst->getSrc(0);
|
||||
ArgGroup args;
|
||||
args.typedValue(src);
|
||||
int64_t (*fPtr)(int64_t) = doubleToIntHelper;
|
||||
cgCallHelper(m_as, (TCA)fPtr, dst, kNoSyncPoint, args);
|
||||
}
|
||||
|
||||
void CodeGenerator::cgConvObjToInt(IRInstruction* inst) {
|
||||
// Never cheap, so just use the general logic.
|
||||
cgConvGenToInt(inst);
|
||||
}
|
||||
|
||||
void CodeGenerator::cgConvStrToInt(IRInstruction* inst) {
|
||||
SSATmp* dst = inst->getDst();
|
||||
auto dstReg = dst->getReg();
|
||||
assert(dstReg != InvalidReg);
|
||||
SSATmp* src = inst->getSrc(0);
|
||||
if (src->isConst()) {
|
||||
auto val = src->getValStr()->toInt64();
|
||||
m_as.mov_imm64_reg(val, dstReg);
|
||||
} else {
|
||||
ArgGroup args;
|
||||
args.ssa(src).imm(10);
|
||||
cgCallHelper(m_as,
|
||||
Transl::Call(getMethodPtr(&StringData::toInt64)),
|
||||
dstReg, kNoSyncPoint, args);
|
||||
}
|
||||
CG_PUNT(Conv);
|
||||
}
|
||||
|
||||
static int64_t genToIntHelper(TypedValue value) {
|
||||
tvCastToInt64InPlace(&value); // this will decrease the ref count
|
||||
// of the current object in value.
|
||||
return value.m_data.num;
|
||||
}
|
||||
|
||||
void CodeGenerator::cgConvGenToInt(IRInstruction* inst) {
|
||||
SSATmp* dst = inst->getDst();
|
||||
SSATmp* src = inst->getSrc(0);
|
||||
ArgGroup args;
|
||||
args.typedValue(src);
|
||||
int64_t (*fPtr)(TypedValue) = genToIntHelper;
|
||||
cgCallHelper(m_as, (TCA)fPtr, dst, kSyncPoint, args);
|
||||
}
|
||||
|
||||
void CodeGenerator::cgConvToObj(IRInstruction* inst) {
|
||||
|
||||
@@ -845,7 +845,7 @@ void HhbcTranslator::emitStrlen() {
|
||||
push(m_tb->genDefConst<int64_t>(0));
|
||||
} else if (inType == Type::Bool) {
|
||||
// strlen(true) == 1, strlen(false) == 0.
|
||||
push(m_tb->genConvToInt(popC()));
|
||||
push(m_tb->gen(ConvBoolToInt, popC()));
|
||||
} else {
|
||||
emitInterpOne(Type::Int | Type::InitNull, 1);
|
||||
}
|
||||
@@ -2064,8 +2064,28 @@ void HhbcTranslator::emitCastDouble() {
|
||||
|
||||
void HhbcTranslator::emitCastInt() {
|
||||
SSATmp* src = popC();
|
||||
push(m_tb->genConvToInt(src));
|
||||
m_tb->genDecRef(src);
|
||||
Type fromType = src->getType();
|
||||
if (fromType.isInt()) {
|
||||
push(src);
|
||||
} else if (fromType.isNull()) {
|
||||
push(m_tb->genDefConst(0));
|
||||
} else if (fromType.isArray()) {
|
||||
push(m_tb->gen(ConvArrToInt, src));
|
||||
m_tb->genDecRef(src);
|
||||
} else if (fromType.isBool()) {
|
||||
push(m_tb->gen(ConvBoolToInt, src));
|
||||
} else if (fromType.isDbl()) {
|
||||
push(m_tb->gen(ConvDblToInt, src));
|
||||
} else if (fromType.isString()) {
|
||||
push(m_tb->gen(ConvStrToInt, src));
|
||||
m_tb->genDecRef(src);
|
||||
} else if (fromType.isObj()) {
|
||||
spillStack(); // may throw
|
||||
push(m_tb->gen(ConvObjToInt, src));
|
||||
} else {
|
||||
spillStack(); // may throw
|
||||
push(m_tb->gen(ConvGenToInt, src));
|
||||
}
|
||||
}
|
||||
|
||||
void HhbcTranslator::emitCastString() {
|
||||
|
||||
@@ -457,6 +457,8 @@ bool IRInstruction::killsSource(int idx) const {
|
||||
case ConvObjToDbl:
|
||||
case ConvStrToDbl:
|
||||
case ConvGenToDbl:
|
||||
case ConvObjToInt:
|
||||
case ConvGenToInt:
|
||||
assert(idx == 0);
|
||||
return true;
|
||||
case ArraySet:
|
||||
|
||||
@@ -184,7 +184,12 @@ 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(ConvArrToInt, D(Int), S(Arr), N) \
|
||||
O(ConvBoolToInt, D(Int), S(Bool), C|Rm) \
|
||||
O(ConvDblToInt, D(Int), S(Dbl), C|N|Rm) \
|
||||
O(ConvObjToInt, D(Int), S(Obj), N|Er|CRc|K) \
|
||||
O(ConvStrToInt, D(Int), S(Str), N) \
|
||||
O(ConvGenToInt, D(Int), S(Gen), N|Er|CRc|K) \
|
||||
\
|
||||
O(ConvToObj, D(Obj), S(Gen), C|N) \
|
||||
\
|
||||
|
||||
@@ -676,15 +676,18 @@ void LinearScan::computePreColoringHint() {
|
||||
case ConvStrToDbl:
|
||||
case ConvGenToDbl:
|
||||
break;
|
||||
case ConvToInt:
|
||||
case ConvBoolToInt:
|
||||
case ConvDblToInt:
|
||||
case ConvObjToInt:
|
||||
break;
|
||||
case ConvStrToInt:
|
||||
{
|
||||
SSATmp* src = inst->getSrc(0);
|
||||
Type fromType = src->getType();
|
||||
if (fromType.isString()) {
|
||||
m_preColoringHint.add(src, 0, 0);
|
||||
}
|
||||
m_preColoringHint.add(src, 0, 0);
|
||||
break;
|
||||
}
|
||||
case ConvGenToInt:
|
||||
break;
|
||||
case ConvToObj:
|
||||
break;
|
||||
case ConvToStr:
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <sstream>
|
||||
#include <type_traits>
|
||||
|
||||
#include <runtime/base/type_conversions.h>
|
||||
#include "runtime/vm/translator/hopt/tracebuilder.h"
|
||||
#include "runtime/vm/runtime.h"
|
||||
|
||||
@@ -104,7 +105,10 @@ SSATmp* Simplifier::simplify(IRInstruction* inst) {
|
||||
case ConvBoolToDbl: return simplifyConvBoolToDbl(inst);
|
||||
case ConvIntToDbl: return simplifyConvIntToDbl(inst);
|
||||
case ConvStrToDbl: return simplifyConvStrToDbl(inst);
|
||||
case ConvToInt: return simplifyConvToInt(inst);
|
||||
case ConvArrToInt: return simplifyConvArrToInt(inst);
|
||||
case ConvBoolToInt: return simplifyConvBoolToInt(inst);
|
||||
case ConvDblToInt: return simplifyConvDblToInt(inst);
|
||||
case ConvStrToInt: return simplifyConvStrToInt(inst);
|
||||
case ConvToObj: return simplifyConvToObj(inst);
|
||||
case ConvToStr: return simplifyConvToStr(inst);
|
||||
case Unbox: return simplifyUnbox(inst);
|
||||
@@ -636,7 +640,7 @@ SSATmp* Simplifier::simplifyAdd(SSATmp* src1, SSATmp* src2) {
|
||||
// X + 0 --> X
|
||||
if (src2Val == 0) {
|
||||
if (src1->getType() == Type::Bool) {
|
||||
return m_tb->genConvToInt(src1);
|
||||
return m_tb->gen(ConvBoolToInt, src1);
|
||||
}
|
||||
return src1;
|
||||
}
|
||||
@@ -669,7 +673,7 @@ SSATmp* Simplifier::simplifySub(SSATmp* src1, SSATmp* src2) {
|
||||
// X - 0 --> X
|
||||
if (src2Val == 0) {
|
||||
if (src1->getType() == Type::Bool) {
|
||||
return m_tb->genConvToInt(src1);
|
||||
return m_tb->gen(ConvBoolToInt, src1);
|
||||
}
|
||||
return src1;
|
||||
}
|
||||
@@ -709,7 +713,7 @@ SSATmp* Simplifier::simplifyMul(SSATmp* src1, SSATmp* src2) {
|
||||
// X * 1 --> X
|
||||
if (src2->getValInt() == 1) {
|
||||
if (src1->getType() == Type::Bool) {
|
||||
return m_tb->genConvToInt(src1);
|
||||
return m_tb->gen(ConvBoolToInt, src1);
|
||||
}
|
||||
return src1;
|
||||
}
|
||||
@@ -1173,32 +1177,41 @@ SSATmp* Simplifier::simplifyConvStrToDbl(IRInstruction* inst) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SSATmp* Simplifier::simplifyConvToInt(IRInstruction* inst) {
|
||||
SSATmp* Simplifier::simplifyConvArrToInt(IRInstruction* inst) {
|
||||
SSATmp* src = inst->getSrc(0);
|
||||
Type srcType = src->getType();
|
||||
if (srcType == Type::Int) {
|
||||
return src;
|
||||
}
|
||||
if (srcType.isNull()) {
|
||||
return genDefInt(0);
|
||||
}
|
||||
if (src->isConst()) {
|
||||
if (src->getType() == Type::Bool) {
|
||||
return genDefInt(int(src->getValBool()));
|
||||
}
|
||||
if (srcType == Type::StaticStr) {
|
||||
const StringData *str = src->getValStr();
|
||||
if (str->isInteger()) {
|
||||
return genDefInt(str->toInt64());
|
||||
}
|
||||
if (src->getValArr()->empty()) {
|
||||
return genDefInt(0);
|
||||
}
|
||||
if (srcType.isArray()) {
|
||||
if (src->getValArr()->empty()) {
|
||||
return genDefInt(0);
|
||||
}
|
||||
return genDefInt(1);
|
||||
return genDefInt(1);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SSATmp* Simplifier::simplifyConvBoolToInt(IRInstruction* inst) {
|
||||
SSATmp* src = inst->getSrc(0);
|
||||
if (src->isConst()) {
|
||||
return genDefInt(int(src->getValBool()));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SSATmp* Simplifier::simplifyConvDblToInt(IRInstruction* inst) {
|
||||
SSATmp* src = inst->getSrc(0);
|
||||
if (src->isConst()) {
|
||||
return genDefInt(toInt64(src->getValDbl()));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SSATmp* Simplifier::simplifyConvStrToInt(IRInstruction* inst) {
|
||||
SSATmp* src = inst->getSrc(0);
|
||||
if (src->isConst()) {
|
||||
const StringData *str = src->getValStr();
|
||||
if (str->isInteger()) {
|
||||
return genDefInt(str->toInt64());
|
||||
}
|
||||
return genDefInt(0);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -68,7 +68,11 @@ private:
|
||||
SSATmp* simplifyConvBoolToDbl(IRInstruction*);
|
||||
SSATmp* simplifyConvIntToDbl(IRInstruction*);
|
||||
SSATmp* simplifyConvStrToDbl(IRInstruction*);
|
||||
SSATmp* simplifyConvToInt(IRInstruction*);
|
||||
SSATmp* simplifyConvArrToInt(IRInstruction*);
|
||||
SSATmp* simplifyConvBoolToInt(IRInstruction*);
|
||||
SSATmp* simplifyConvDblToInt(IRInstruction*);
|
||||
SSATmp* simplifyConvObjToInt(IRInstruction*);
|
||||
SSATmp* simplifyConvStrToInt(IRInstruction*);
|
||||
SSATmp* simplifyConvToObj(IRInstruction*);
|
||||
SSATmp* simplifyConvToStr(IRInstruction*);
|
||||
SSATmp* simplifyUnbox(IRInstruction*);
|
||||
|
||||
@@ -396,10 +396,6 @@ SSATmp* TraceBuilder::genDefNone() {
|
||||
return gen(DefConst, Type::None, &cdata);
|
||||
}
|
||||
|
||||
SSATmp* TraceBuilder::genConvToInt(SSATmp* src) {
|
||||
return gen(ConvToInt, Type::Int, src);
|
||||
}
|
||||
|
||||
SSATmp* TraceBuilder::genConvToStr(SSATmp* src) {
|
||||
if (src->getType() == Type::Bool) {
|
||||
// Bool to string code sequence loads static strings
|
||||
|
||||
@@ -176,7 +176,6 @@ public:
|
||||
SSATmp* genCmp(Opcode opc, SSATmp* src1, SSATmp* src2);
|
||||
SSATmp* genCastStk(uint32_t id, Type type);
|
||||
SSATmp* genConvToBool(SSATmp* src);
|
||||
SSATmp* genConvToInt(SSATmp* src);
|
||||
SSATmp* genConvToDbl(SSATmp* src);
|
||||
SSATmp* genConvToStr(SSATmp* src);
|
||||
SSATmp* genConvToArr(SSATmp* src);
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário