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:
hermanv
2013-03-26 16:08:41 -07:00
commit de Sara Golemon
commit 874dee78fd
10 arquivos alterados com 166 adições e 71 exclusões
+6 -2
Ver Arquivo
@@ -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.
+78 -29
Ver Arquivo
@@ -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() {
+2
Ver Arquivo
@@ -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:
+6 -1
Ver Arquivo
@@ -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) \
\
+8 -5
Ver Arquivo
@@ -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:
+38 -25
Ver Arquivo
@@ -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;
}
+5 -1
Ver Arquivo
@@ -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);