diff --git a/hphp/runtime/vm/translator/hopt/ir.cpp b/hphp/runtime/vm/translator/hopt/ir.cpp index 9e1fc4387..79fa020b8 100644 --- a/hphp/runtime/vm/translator/hopt/ir.cpp +++ b/hphp/runtime/vm/translator/hopt/ir.cpp @@ -363,7 +363,6 @@ bool IRInstruction::canCSE() const { // count or consume reference counts. CheckType is special because it can // refine a maybeCounted type to a notCounted type, so it logically consumes // and produces a reference without doing any work. - assert(!canCSE || !producesReference() || m_op == CheckType); assert(!canCSE || !consumesReferences() || m_op == CheckType); return canCSE && !mayReenterHelper(); } diff --git a/hphp/runtime/vm/translator/hopt/ir.h b/hphp/runtime/vm/translator/hopt/ir.h index e465d1249..5e06f6cff 100644 --- a/hphp/runtime/vm/translator/hopt/ir.h +++ b/hphp/runtime/vm/translator/hopt/ir.h @@ -554,7 +554,7 @@ O_STK(ElemUX, D(PtrToGen), C(TCA) \ S(PtrToCell),VElem|E|N|Mem|Refs|Er) \ O(ArrayGet, D(Cell), C(TCA) \ S(Arr) \ - S(Int,Str), E|N|PRc|Refs|Mem|Er) \ + S(Int,Str), C|N|PRc|Refs|Mem|Er)\ O(CGetElem, D(Cell), C(TCA) \ S(PtrToGen) \ S(Cell) \ diff --git a/hphp/runtime/vm/translator/hopt/tracebuilder.cpp b/hphp/runtime/vm/translator/hopt/tracebuilder.cpp index 73d7ed9ac..48bc66f5a 100644 --- a/hphp/runtime/vm/translator/hopt/tracebuilder.cpp +++ b/hphp/runtime/vm/translator/hopt/tracebuilder.cpp @@ -768,7 +768,13 @@ SSATmp* TraceBuilder::optimizeWork(IRInstruction* inst) { // Found a dominating instruction that can be used instead of inst FTRACE(1, " {}cse found: {}\n", indent(), result->inst()->toString()); - return result; + if (inst->producesReference()) { + // Replace with an IncRef + FTRACE(1, " {}cse of refcount-producing instruction\n", indent()); + return gen(IncRef, result); + } else { + return result; + } } } diff --git a/hphp/test/quick/array_cse.php b/hphp/test/quick/array_cse.php new file mode 100644 index 000000000..a4334e781 --- /dev/null +++ b/hphp/test/quick/array_cse.php @@ -0,0 +1,10 @@ +