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:
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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());
|
||||
@@ -0,0 +1 @@
|
||||
int(4)
|
||||
Referência em uma Nova Issue
Bloquear um usuário