Allow CSE of ArrayGet by converting to IncRef

ArrayGet has fairly minimal side-effects: IncRef of its
result, and raising a warning if the element is undefined.  To CSE
ArrayGet, replace it with an IncRef of its destination.  Raising
multiple warnings for repeated accesses doesn't seem to have much
value, so just ignore them.
Esse commit está contido em:
Bert Maher
2013-05-31 09:01:57 -07:00
commit de sgolemon
commit 8e34cbdf15
5 arquivos alterados com 19 adições e 3 exclusões
-1
Ver Arquivo
@@ -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();
}
+1 -1
Ver Arquivo
@@ -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) \
@@ -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;
}
}
}
+10
Ver Arquivo
@@ -0,0 +1,10 @@
<?php
// Copyright 2004-present Facebook. All Rights Reserved.
function array_cse() {
$a = array(0,1,2,3,4);
$x = $a[2] + $a[2];
return $x;
}
var_dump(array_cse());
+1
Ver Arquivo
@@ -0,0 +1 @@
int(4)