diff --git a/hphp/runtime/vm/translator/hopt/hhbctranslator.cpp b/hphp/runtime/vm/translator/hopt/hhbctranslator.cpp index 85c82cd81..5a72208eb 100644 --- a/hphp/runtime/vm/translator/hopt/hhbctranslator.cpp +++ b/hphp/runtime/vm/translator/hopt/hhbctranslator.cpp @@ -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); } diff --git a/hphp/runtime/vm/translator/hopt/ir.cpp b/hphp/runtime/vm/translator/hopt/ir.cpp index 645efa092..fed95071c 100644 --- a/hphp/runtime/vm/translator/hopt/ir.cpp +++ b/hphp/runtime/vm/translator/hopt/ir.cpp @@ -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 diff --git a/hphp/runtime/vm/translator/hopt/ir.h b/hphp/runtime/vm/translator/hopt/ir.h index 7fa953caf..96faa95cd 100644 --- a/hphp/runtime/vm/translator/hopt/ir.h +++ b/hphp/runtime/vm/translator/hopt/ir.h @@ -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); } diff --git a/hphp/runtime/vm/translator/hopt/simplifier.cpp b/hphp/runtime/vm/translator/hopt/simplifier.cpp index 5bd3f107b..e56ea29f6 100644 --- a/hphp/runtime/vm/translator/hopt/simplifier.cpp +++ b/hphp/runtime/vm/translator/hopt/simplifier.cpp @@ -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::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 diff --git a/hphp/runtime/vm/translator/hopt/tracebuilder.cpp b/hphp/runtime/vm/translator/hopt/tracebuilder.cpp index 5ecc8bc47..bca5cb496 100644 --- a/hphp/runtime/vm/translator/hopt/tracebuilder.cpp +++ b/hphp/runtime/vm/translator/hopt/tracebuilder.cpp @@ -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(1))); + return genConvToBool(gen(OpXor, src, genDefConst(1))); } SSATmp* TraceBuilder::genDefUninit() { diff --git a/hphp/runtime/vm/translator/hopt/tracebuilder.h b/hphp/runtime/vm/translator/hopt/tracebuilder.h index 975da2fea..38a00f942 100644 --- a/hphp/runtime/vm/translator/hopt/tracebuilder.h +++ b/hphp/runtime/vm/translator/hopt/tracebuilder.h @@ -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(); diff --git a/hphp/runtime/vm/translator/hopt/type.cpp b/hphp/runtime/vm/translator/hopt/type.cpp index bfa4758ed..63606737f 100644 --- a/hphp/runtime/vm/translator/hopt/type.cpp +++ b/hphp/runtime/vm/translator/hopt/type.cpp @@ -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 }