C++: IR: Fix performance of value-init ranges

On a snapshot of Postgres, evaluation of
`getNextExplicitlyInitializedElementAfter#fff#antijoin_rhs#1` took
forever, preventing the computation of the IR. I haven't been able to
reproduce it with a small test case, but the implementation of
`getNextExplicitlyInitializedElementAfter` was fragile because it called
the inline predicate `ArrayAggregateLiteral.isInitialized`. It also
seemed inefficient that `getNextExplicitlyInitializedElementAfter` was
computed for many values of its parameters that were never needed by the
caller.

This commit replaces `getNextExplicitlyInitializedElementAfter` with a
new predicate named `getEndOfValueInitializedRange`, which should have
the same behavior but a more efficient implementation. It uses a helper
predicate `getNextExplicitlyInitializedElementAfter`, which shares its
name with the now-deleted predicate but has behavior that I think
matches the name.
This commit is contained in:
Jonas Jensen
2018-09-11 11:28:50 +02:00
parent 4051e348eb
commit b2571c8d63

View File

@@ -270,7 +270,7 @@ newtype TTranslatedElement =
not ignoreExpr(initList) and
isFirstValueInitializedElementInRange(initList, elementIndex) and
elementCount =
getNextExplicitlyInitializedElementAfter(initList, elementIndex) -
getEndOfValueInitializedRange(initList, elementIndex) -
elementIndex
} or
// The initialization of a base class from within a constructor.
@@ -322,23 +322,28 @@ newtype TTranslatedElement =
/**
* Gets the index of the first explicitly initialized element in `initList`
* whose index is greater than `afterElementIndex`. If there are no remaining
* explicitly initialized elements in `initList`, the result is the total number
* of elements in the array being initialized.
* whose index is greater than `afterElementIndex`, where `afterElementIndex`
* is a first value-initialized element in a value-initialized range in
* `initList`. If there are no remaining explicitly initialized elements in
* `initList`, the result is the total number of elements in the array being
* initialized.
*/
private int getNextExplicitlyInitializedElementAfter(
ArrayAggregateLiteral initList, int afterElementIndex) {
if exists(int x |
x > afterElementIndex and
exists(initList.getElementExpr(x)))
then (
if exists(initList.getElementExpr(afterElementIndex + 1))
then result = afterElementIndex + 1
else result = getNextExplicitlyInitializedElementAfter(initList, afterElementIndex+1))
else
result = initList.getType().getUnspecifiedType().(ArrayType).getArraySize() and
// required for binding
initList.isInitialized(afterElementIndex)
private int getEndOfValueInitializedRange(ArrayAggregateLiteral initList, int afterElementIndex) {
isFirstValueInitializedElementInRange(initList, afterElementIndex) and
not exists(getNextExplicitlyInitializedElementAfter(initList, afterElementIndex)) and
result = initList.getType().getUnspecifiedType().(ArrayType).getArraySize()
}
/**
* Gets the index of the first explicitly initialized element in `initList`
* whose index is greater than `afterElementIndex`, where `afterElementIndex`
* is a first value-initialized element in a value-initialized range in
* `initList`.
*/
private int getNextExplicitlyInitializedElementAfter(
ArrayAggregateLiteral initList, int afterElementIndex) {
isFirstValueInitializedElementInRange(initList, afterElementIndex) and
result = min(int i | exists(initList.getElementExpr(i)) and i > afterElementIndex)
}
/**