Fix arithmetic op uses of type paramters, get rid of gen{Sub,Mul,...}
These guys were determining their output type with DParam, even though the output type was a function of the input types. Fixed this and then get rid of the genFoo wrappers. Move binArithResultType out of Type. OpMod didn't need a type parameter.
Esse commit está contido em:
@@ -676,7 +676,7 @@ void HhbcTranslator::emitIncDecL(bool pre, bool inc, uint32_t id) {
|
||||
SSATmp* HhbcTranslator::emitIncDec(bool pre, bool inc, SSATmp* src) {
|
||||
assert(src->isA(Type::Int) || src->isA(Type::Dbl));
|
||||
SSATmp* one = src->isA(Type::Int) ? cns(1) : cns(1.0);
|
||||
SSATmp* res = inc ? m_tb->genAdd(src, one) : m_tb->genSub(src, one);
|
||||
SSATmp* res = inc ? gen(OpAdd, src, one) : gen(OpSub, src, one);
|
||||
// no incref necessary on push since result is an int
|
||||
push(pre ? res : src);
|
||||
return res;
|
||||
@@ -724,9 +724,7 @@ void HhbcTranslator::emitSetOpL(Opcode subOpc, uint32_t id) {
|
||||
loc->type(),
|
||||
topC()->type())) {
|
||||
SSATmp* val = popC();
|
||||
Type resultType = Type::binArithResultType(loc->type(),
|
||||
val->type());
|
||||
SSATmp* result = gen(subOpc, resultType, loc, val);
|
||||
SSATmp* result = gen(subOpc, loc, val);
|
||||
push(m_tb->genStLoc(id, result, true, true, exitTrace));
|
||||
} else {
|
||||
PUNT(SetOpL);
|
||||
@@ -2740,7 +2738,7 @@ void HhbcTranslator::emitBinaryArith(Opcode opc) {
|
||||
if (isSupportedBinaryArith(opc, type1, type2)) {
|
||||
SSATmp* tr = popC();
|
||||
SSATmp* tl = popC();
|
||||
push(gen(opc, Type::binArithResultType(type1, type2), tl, tr));
|
||||
push(gen(opc, tl, tr));
|
||||
} else if (isBitOp && (type1 == Type::Obj || type2 == Type::Obj)) {
|
||||
// raise fatal
|
||||
emitInterpOne(Type::Cell, 2);
|
||||
@@ -2771,8 +2769,8 @@ void HhbcTranslator::emitNot() {
|
||||
}
|
||||
|
||||
#define BINOP(Opp) \
|
||||
void HhbcTranslator::emit ## Opp() { \
|
||||
emitBinaryArith(Op ## Opp); \
|
||||
void HhbcTranslator::emit ## Opp() { \
|
||||
emitBinaryArith(Op ## Opp); \
|
||||
}
|
||||
|
||||
BINOP(Add)
|
||||
@@ -2824,7 +2822,7 @@ void HhbcTranslator::emitMod() {
|
||||
bcOff()
|
||||
);
|
||||
gen(JmpZero, exit, r);
|
||||
push(gen(OpMod, Type::Int, l, r));
|
||||
push(gen(OpMod, l, r));
|
||||
}
|
||||
|
||||
void HhbcTranslator::emitBitNot() {
|
||||
@@ -2832,7 +2830,7 @@ void HhbcTranslator::emitBitNot() {
|
||||
if (srcType == Type::Int) {
|
||||
SSATmp* src = popC();
|
||||
SSATmp* ones = cns(~uint64_t(0));
|
||||
push(m_tb->genXor(src, ones));
|
||||
push(gen(OpXor, src, ones));
|
||||
} else if (srcType.subtypeOf(Type::Null | Type::Bool | Type::Arr | Type::Obj)) {
|
||||
// raise fatal
|
||||
emitInterpOne(Type::Cell, 1);
|
||||
@@ -2852,7 +2850,7 @@ void HhbcTranslator::emitXor() {
|
||||
SSATmp* btl = popC();
|
||||
SSATmp* tr = m_tb->genConvToBool(btr);
|
||||
SSATmp* tl = m_tb->genConvToBool(btl);
|
||||
push(m_tb->genConvToBool(m_tb->genXor(tl, tr)));
|
||||
push(m_tb->genConvToBool(gen(OpXor, tl, tr)));
|
||||
m_tb->genDecRef(btl);
|
||||
m_tb->genDecRef(btr);
|
||||
}
|
||||
|
||||
@@ -105,6 +105,7 @@ namespace {
|
||||
#define DUnbox(n) HasDest
|
||||
#define DBox(n) HasDest
|
||||
#define DParam HasDest
|
||||
#define DArith HasDest
|
||||
#define DMulti NaryDest
|
||||
#define DVector HasDest
|
||||
#define DStk(x) ModifiesStack|(x)
|
||||
@@ -147,6 +148,7 @@ struct {
|
||||
#undef DUnbox
|
||||
#undef DBox
|
||||
#undef DParam
|
||||
#undef DArith
|
||||
#undef DMulti
|
||||
#undef DVector
|
||||
#undef DStk
|
||||
|
||||
@@ -108,6 +108,7 @@ static const TCA kIRDirectGuardActive = (TCA)0x03;
|
||||
* DUnbox(N) single dst has unboxed type of src N
|
||||
* DBox(N) single dst has boxed type of src N
|
||||
* DParam single dst has type of the instruction's type parameter
|
||||
* DArith single dst has a type based on arithmetic type rules
|
||||
* DMulti multiple dests. type and number depend on instruction
|
||||
* DVector single dst depends on semantics of the vector instruction
|
||||
* DStk(x) up to two dests. x should be another D* macro and indicates
|
||||
@@ -171,13 +172,13 @@ O(CastStk, D(StkPtr), S(StkPtr) C(Int), Mem|N|Er) \
|
||||
O(AssertStk, D(StkPtr), S(StkPtr) C(Int), E) \
|
||||
O(GuardRefs, ND, SUnk, E) \
|
||||
O(AssertLoc, ND, S(FramePtr), E) \
|
||||
O(OpAdd, DParam, SNum SNum, C) \
|
||||
O(OpSub, DParam, SNum SNum, C) \
|
||||
O(OpAdd, DArith, SNum SNum, C) \
|
||||
O(OpSub, DArith, SNum SNum, C) \
|
||||
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(OpDiv, DParam, SNum SNum, C) \
|
||||
O(OpMul, DArith, SNum SNum, C) \
|
||||
O(OpDiv, DArith, SNum SNum, C) \
|
||||
O(OpMod, D(Int), SNumInt SNumInt, C|N) \
|
||||
\
|
||||
O(ConvBoolToArr, D(Arr), S(Bool), C|N) \
|
||||
@@ -1277,13 +1278,6 @@ public:
|
||||
return t1.subtypeOf(t2) ? t1 : t2;
|
||||
}
|
||||
|
||||
static Type binArithResultType(Type t1, Type t2) {
|
||||
if (t1.subtypeOf(Type::Dbl) || t2.subtypeOf(Type::Dbl)) {
|
||||
return Type::Dbl;
|
||||
}
|
||||
return Type::Int;
|
||||
}
|
||||
|
||||
bool isArray() const {
|
||||
return subtypeOf(Arr);
|
||||
}
|
||||
|
||||
@@ -579,7 +579,7 @@ SSATmp* Simplifier::simplifyNot(SSATmp* src) {
|
||||
#define SIMPLIFY_COMMUTATIVE(OP, NAME) do { \
|
||||
SIMPLIFY_CONST(OP); \
|
||||
if (src1->isConst() && !src2->isConst()) { \
|
||||
return m_tb->gen##NAME(src2, src1); \
|
||||
return gen(Op##NAME, src2, src1); \
|
||||
} \
|
||||
if (src1->isA(Type::Int) && src2->isA(Type::Int)) { \
|
||||
IRInstruction* inst1 = src1->inst(); \
|
||||
@@ -589,14 +589,14 @@ SSATmp* Simplifier::simplifyNot(SSATmp* src) {
|
||||
if (src2->isConst()) { \
|
||||
int64_t right = inst1->getSrc(1)->getValInt(); \
|
||||
right OP##= src2->getValInt(); \
|
||||
return m_tb->gen##NAME(inst1->getSrc(0), cns(right)); \
|
||||
return gen(Op##NAME, inst1->getSrc(0), cns(right)); \
|
||||
} \
|
||||
/* (X + C1) + (Y + C2) --> X + Y + C3 */ \
|
||||
if (inst2->op() == Op##NAME && inst2->getSrc(1)->isConst()) { \
|
||||
int64_t right = inst1->getSrc(1)->getValInt(); \
|
||||
right OP##= inst2->getSrc(1)->getValInt(); \
|
||||
SSATmp* left = m_tb->gen##NAME(inst1->getSrc(0), inst2->getSrc(0)); \
|
||||
return m_tb->gen##NAME(left, cns(right)); \
|
||||
SSATmp* left = gen(Op##NAME, inst1->getSrc(0), inst2->getSrc(0)); \
|
||||
return gen(Op##NAME, left, cns(right)); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
@@ -612,20 +612,20 @@ SSATmp* Simplifier::simplifyNot(SSATmp* src) {
|
||||
/* all combinations of X * Y + X * Z --> X * (Y + Z) */ \
|
||||
if (op1 == Op##INNAME && op2 == Op##INNAME) { \
|
||||
if (inst1->getSrc(0) == inst2->getSrc(0)) { \
|
||||
SSATmp* fold = m_tb->gen##OUTNAME(inst1->getSrc(1), inst2->getSrc(1)); \
|
||||
return m_tb->gen##INNAME(inst1->getSrc(0), fold); \
|
||||
SSATmp* fold = gen(Op##OUTNAME, inst1->getSrc(1), inst2->getSrc(1)); \
|
||||
return gen(Op##INNAME, inst1->getSrc(0), fold); \
|
||||
} \
|
||||
if (inst1->getSrc(0) == inst2->getSrc(1)) { \
|
||||
SSATmp* fold = m_tb->gen##OUTNAME(inst1->getSrc(1), inst2->getSrc(0)); \
|
||||
return m_tb->gen##INNAME(inst1->getSrc(0), fold); \
|
||||
SSATmp* fold = gen(Op##OUTNAME, inst1->getSrc(1), inst2->getSrc(0)); \
|
||||
return gen(Op##INNAME, inst1->getSrc(0), fold); \
|
||||
} \
|
||||
if (inst1->getSrc(1) == inst2->getSrc(0)) { \
|
||||
SSATmp* fold = m_tb->gen##OUTNAME(inst1->getSrc(0), inst2->getSrc(1)); \
|
||||
return m_tb->gen##INNAME(inst1->getSrc(1), fold); \
|
||||
SSATmp* fold = gen(Op##OUTNAME, inst1->getSrc(0), inst2->getSrc(1)); \
|
||||
return gen(Op##INNAME, inst1->getSrc(1), fold); \
|
||||
} \
|
||||
if (inst1->getSrc(1) == inst2->getSrc(1)) { \
|
||||
SSATmp* fold = m_tb->gen##OUTNAME(inst1->getSrc(0), inst2->getSrc(0)); \
|
||||
return m_tb->gen##INNAME(inst1->getSrc(1), fold); \
|
||||
SSATmp* fold = gen(Op##OUTNAME, inst1->getSrc(0), inst2->getSrc(0)); \
|
||||
return gen(Op##INNAME, inst1->getSrc(1), fold); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
@@ -643,7 +643,7 @@ SSATmp* Simplifier::simplifyAdd(SSATmp* src1, SSATmp* src2) {
|
||||
}
|
||||
// X + -C --> X - C
|
||||
if (src2Val < 0) {
|
||||
return m_tb->genSub(src1, cns(-src2Val));
|
||||
return gen(OpSub, src1, cns(-src2Val));
|
||||
}
|
||||
}
|
||||
// X + (0 - Y) --> X - Y
|
||||
@@ -653,7 +653,7 @@ SSATmp* Simplifier::simplifyAdd(SSATmp* src1, SSATmp* src2) {
|
||||
SSATmp* src = inst2->getSrc(0);
|
||||
if (src->isConst() && src->type() == Type::Int) {
|
||||
if (src->getValInt() == 0) {
|
||||
return m_tb->genSub(src1, inst2->getSrc(1));
|
||||
return gen(OpSub, src1, inst2->getSrc(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -676,7 +676,7 @@ SSATmp* Simplifier::simplifySub(SSATmp* src1, SSATmp* src2) {
|
||||
}
|
||||
// X - -C --> X + C
|
||||
if (src2Val < 0 && src2Val > std::numeric_limits<int64_t>::min()) {
|
||||
return m_tb->genAdd(src1, cns(-src2Val));
|
||||
return gen(OpAdd, src1, cns(-src2Val));
|
||||
}
|
||||
}
|
||||
// X - (0 - Y) --> X + Y
|
||||
@@ -686,7 +686,7 @@ SSATmp* Simplifier::simplifySub(SSATmp* src1, SSATmp* src2) {
|
||||
SSATmp* src = inst2->getSrc(0);
|
||||
if (src->isConst() && src->type() == Type::Int) {
|
||||
if (src->getValInt() == 0) {
|
||||
return m_tb->genAdd(src1, inst2->getSrc(1));
|
||||
return gen(OpAdd, src1, inst2->getSrc(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -701,7 +701,7 @@ SSATmp* Simplifier::simplifyMul(SSATmp* src1, SSATmp* src2) {
|
||||
if (src2->isConst() && src2->type() == Type::Int) {
|
||||
// X * (-1) --> -X
|
||||
if (src2->getValInt() == -1) {
|
||||
return m_tb->genSub(cns(0), src1);
|
||||
return gen(OpSub, cns(0), src1);
|
||||
}
|
||||
// X * 0 --> 0
|
||||
if (src2->getValInt() == 0) {
|
||||
@@ -716,7 +716,7 @@ SSATmp* Simplifier::simplifyMul(SSATmp* src1, SSATmp* src2) {
|
||||
}
|
||||
// X * 2 --> X + X
|
||||
if (src2->getValInt() == 2) {
|
||||
return m_tb->genAdd(src1, src1);
|
||||
return gen(OpAdd, src1, src1);
|
||||
}
|
||||
// TODO once IR has shifts
|
||||
// X * 2^C --> X << C
|
||||
|
||||
@@ -240,34 +240,9 @@ Trace* TraceBuilder::genExitTrace(uint32_t bcOff,
|
||||
return exitTrace;
|
||||
}
|
||||
|
||||
SSATmp* TraceBuilder::genAdd(SSATmp* src1, SSATmp* src2) {
|
||||
Type resultType = Type::binArithResultType(src1->type(),
|
||||
src2->type());
|
||||
return gen(OpAdd, resultType, src1, src2);
|
||||
}
|
||||
SSATmp* TraceBuilder::genSub(SSATmp* src1, SSATmp* src2) {
|
||||
Type resultType = Type::binArithResultType(src1->type(),
|
||||
src2->type());
|
||||
return gen(OpSub, resultType, src1, src2);
|
||||
}
|
||||
SSATmp* TraceBuilder::genAnd(SSATmp* src1, SSATmp* src2) {
|
||||
return gen(OpAnd, src1, src2);
|
||||
}
|
||||
SSATmp* TraceBuilder::genOr(SSATmp* src1, SSATmp* src2) {
|
||||
return gen(OpOr, src1, src2);
|
||||
}
|
||||
SSATmp* TraceBuilder::genXor(SSATmp* src1, SSATmp* src2) {
|
||||
return gen(OpXor, src1, src2);
|
||||
}
|
||||
SSATmp* TraceBuilder::genMul(SSATmp* src1, SSATmp* src2) {
|
||||
Type resultType = Type::binArithResultType(src1->type(),
|
||||
src2->type());
|
||||
return gen(OpMul, resultType, src1, src2);
|
||||
}
|
||||
|
||||
SSATmp* TraceBuilder::genNot(SSATmp* src) {
|
||||
assert(src->type() == Type::Bool);
|
||||
return genConvToBool(genXor(src, genDefConst<int64_t>(1)));
|
||||
return genConvToBool(gen(OpXor, src, genDefConst<int64_t>(1)));
|
||||
}
|
||||
|
||||
SSATmp* TraceBuilder::genDefUninit() {
|
||||
|
||||
@@ -124,13 +124,7 @@ public:
|
||||
Type type,
|
||||
bool override = false); // ignores conflict w/ prev type
|
||||
|
||||
SSATmp* genAdd(SSATmp* src1, SSATmp* src2);
|
||||
|
||||
SSATmp* genSub(SSATmp* src1, SSATmp* src2);
|
||||
SSATmp* genMul(SSATmp* src1, SSATmp* src2);
|
||||
SSATmp* genAnd(SSATmp* src1, SSATmp* src2);
|
||||
SSATmp* genOr(SSATmp* src1, SSATmp* src2);
|
||||
SSATmp* genXor(SSATmp* src1, SSATmp* src2);
|
||||
// TODO(#2058865): we should have a real not opcode
|
||||
SSATmp* genNot(SSATmp* src);
|
||||
|
||||
SSATmp* genDefUninit();
|
||||
|
||||
@@ -77,6 +77,13 @@ Type stkReturn(const IRInstruction* inst, int dstId,
|
||||
return Type::StkPtr;
|
||||
}
|
||||
|
||||
Type binArithResultType(Type t1, Type t2) {
|
||||
if (t1.subtypeOf(Type::Dbl) || t2.subtypeOf(Type::Dbl)) {
|
||||
return Type::Dbl;
|
||||
}
|
||||
return Type::Int;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Type outputType(const IRInstruction* inst, int dstId) {
|
||||
@@ -92,6 +99,8 @@ Type outputType(const IRInstruction* inst, int dstId) {
|
||||
#define DVector return vectorReturn(inst);
|
||||
#define ND assert(0 && "outputType requires HasDest or NaryDest");
|
||||
#define DBuiltin return builtinReturn(inst);
|
||||
#define DArith return binArithResultType(inst->getSrc(0)->type(), \
|
||||
inst->getSrc(1)->type());
|
||||
|
||||
#define O(name, dstinfo, srcinfo, flags) case name: dstinfo not_reached();
|
||||
|
||||
@@ -112,6 +121,7 @@ Type outputType(const IRInstruction* inst, int dstId) {
|
||||
#undef DVector
|
||||
#undef ND
|
||||
#undef DBuiltin
|
||||
#undef DArith
|
||||
|
||||
}
|
||||
|
||||
@@ -261,6 +271,8 @@ void assertOperandTypes(const IRInstruction* inst) {
|
||||
#define DParam checkDst(inst->getTypeParam() != Type::None || \
|
||||
inst->op() == DefConst /* for DefNone */, \
|
||||
"DParam with paramType None");
|
||||
#define DArith checkDst(inst->getTypeParam() == Type::None, \
|
||||
"DArith should have no type parameter");
|
||||
|
||||
#define O(opcode, dstinfo, srcinfo, flags) \
|
||||
case opcode: dstinfo srcinfo countCheck(); return;
|
||||
@@ -288,6 +300,7 @@ void assertOperandTypes(const IRInstruction* inst) {
|
||||
#undef DBox
|
||||
#undef DofS
|
||||
#undef DParam
|
||||
#undef DArith
|
||||
|
||||
}
|
||||
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário