Skip to content

Commit c9cb2a0

Browse files
Merge pull request #177 from jbj/ir-array-init-perf
C++: IR: Fix performance of value-init ranges
2 parents 1459b98 + df948ec commit c9cb2a0

File tree

7 files changed

+200
-17
lines changed

7 files changed

+200
-17
lines changed

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ newtype TTranslatedElement =
270270
not ignoreExpr(initList) and
271271
isFirstValueInitializedElementInRange(initList, elementIndex) and
272272
elementCount =
273-
getNextExplicitlyInitializedElementAfter(initList, elementIndex) -
273+
getEndOfValueInitializedRange(initList, elementIndex) -
274274
elementIndex
275275
} or
276276
// The initialization of a base class from within a constructor.
@@ -322,23 +322,30 @@ newtype TTranslatedElement =
322322

323323
/**
324324
* Gets the index of the first explicitly initialized element in `initList`
325-
* whose index is greater than `afterElementIndex`. If there are no remaining
326-
* explicitly initialized elements in `initList`, the result is the total number
327-
* of elements in the array being initialized.
325+
* whose index is greater than `afterElementIndex`, where `afterElementIndex`
326+
* is a first value-initialized element in a value-initialized range in
327+
* `initList`. If there are no remaining explicitly initialized elements in
328+
* `initList`, the result is the total number of elements in the array being
329+
* initialized.
328330
*/
329-
private int getNextExplicitlyInitializedElementAfter(
330-
ArrayAggregateLiteral initList, int afterElementIndex) {
331-
if exists(int x |
332-
x > afterElementIndex and
333-
exists(initList.getElementExpr(x)))
334-
then (
335-
if exists(initList.getElementExpr(afterElementIndex + 1))
336-
then result = afterElementIndex + 1
337-
else result = getNextExplicitlyInitializedElementAfter(initList, afterElementIndex+1))
338-
else
339-
result = initList.getType().getUnspecifiedType().(ArrayType).getArraySize() and
340-
// required for binding
341-
initList.isInitialized(afterElementIndex)
331+
private int getEndOfValueInitializedRange(ArrayAggregateLiteral initList, int afterElementIndex) {
332+
result = getNextExplicitlyInitializedElementAfter(initList, afterElementIndex)
333+
or
334+
isFirstValueInitializedElementInRange(initList, afterElementIndex) and
335+
not exists(getNextExplicitlyInitializedElementAfter(initList, afterElementIndex)) and
336+
result = initList.getType().getUnspecifiedType().(ArrayType).getArraySize()
337+
}
338+
339+
/**
340+
* Gets the index of the first explicitly initialized element in `initList`
341+
* whose index is greater than `afterElementIndex`, where `afterElementIndex`
342+
* is a first value-initialized element in a value-initialized range in
343+
* `initList`.
344+
*/
345+
private int getNextExplicitlyInitializedElementAfter(
346+
ArrayAggregateLiteral initList, int afterElementIndex) {
347+
isFirstValueInitializedElementInRange(initList, afterElementIndex) and
348+
result = min(int i | exists(initList.getElementExpr(i)) and i > afterElementIndex)
342349
}
343350

344351
/**

cpp/ql/test/library-tests/ir/ir/PrintAST.expected

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6303,3 +6303,35 @@ ir.cpp:
63036303
# 958| Type = int
63046304
# 958| ValueCategory = prvalue(load)
63056305
# 959| 8: return ...
6306+
# 961| designatedInit() -> int
6307+
# 961| params:
6308+
# 961| body: { ... }
6309+
# 962| 0: declaration
6310+
# 962| 0: definition of a1
6311+
# 962| Type = int[1000]
6312+
# 962| init: initializer for a1
6313+
# 962| expr: {...}
6314+
# 962| Type = int[1000]
6315+
# 962| ValueCategory = prvalue
6316+
# 962| 0: 10002
6317+
# 962| Type = int
6318+
# 962| Value = 10002
6319+
# 962| ValueCategory = prvalue
6320+
# 962| 1: 10900
6321+
# 962| Type = int
6322+
# 962| Value = 10900
6323+
# 962| ValueCategory = prvalue
6324+
# 963| 1: return ...
6325+
# 963| 0: access to array
6326+
# 963| Type = int
6327+
# 963| ValueCategory = prvalue(load)
6328+
# 963| 0: array to pointer conversion
6329+
# 963| Type = int *
6330+
# 963| ValueCategory = prvalue
6331+
# 963| expr: a1
6332+
# 963| Type = int[1000]
6333+
# 963| ValueCategory = lvalue
6334+
# 963| 1: 900
6335+
# 963| Type = int
6336+
# 963| Value = 900
6337+
# 963| ValueCategory = prvalue

cpp/ql/test/library-tests/ir/ir/aliased_ssa_ir.expected

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3906,3 +3906,49 @@ ir.cpp:
39063906
# 950| v0_65(void) = ReturnVoid :
39073907
# 950| v0_66(void) = UnmodeledUse : mu*
39083908
# 950| v0_67(void) = ExitFunction :
3909+
3910+
# 961| designatedInit() -> int
3911+
# 961| Block 0
3912+
# 961| v0_0(void) = EnterFunction :
3913+
# 961| mu0_1(unknown) = UnmodeledDefinition :
3914+
# 962| r0_2(glval<int[1000]>) = VariableAddress[a1] :
3915+
# 962| r0_3(int) = Constant[0] :
3916+
# 962| r0_4(glval<int>) = PointerAdd : r0_2, r0_3
3917+
# 962| r0_5(unknown[8]) = Constant[0] :
3918+
# 962| mu0_6(unknown[8]) = Store : r0_4, r0_5
3919+
#-----| Goto -> Block 2
3920+
3921+
# 962| Block 1
3922+
# 962| r1_0(int) = Constant[900] :
3923+
# 962| r1_1(glval<int>) = PointerAdd : r0_2, r1_0
3924+
# 962| r1_2(int) = Constant[10900] :
3925+
# 962| mu1_3(int) = Store : r1_1, r1_2
3926+
# 962| r1_4(int) = Constant[901] :
3927+
# 962| r1_5(glval<int>) = PointerAdd : r0_2, r1_4
3928+
# 962| r1_6(unknown[396]) = Constant[0] :
3929+
# 962| mu1_7(unknown[396]) = Store : r1_5, r1_6
3930+
#-----| Goto -> Block 2
3931+
3932+
# 963| Block 2
3933+
# 963| r2_0(glval<int>) = VariableAddress[#return] :
3934+
# 963| r2_1(glval<int[1000]>) = VariableAddress[a1] :
3935+
# 963| r2_2(int *) = Convert : r2_1
3936+
# 963| r2_3(int) = Constant[900] :
3937+
# 963| r2_4(int *) = PointerAdd[4] : r2_2, r2_3
3938+
# 963| r2_5(int) = Load : r2_4, mu0_1
3939+
# 963| m2_6(int) = Store : r2_0, r2_5
3940+
# 961| r2_7(glval<int>) = VariableAddress[#return] :
3941+
# 961| v2_8(void) = ReturnValue : r2_7, m2_6
3942+
# 961| v2_9(void) = UnmodeledUse : mu*
3943+
# 961| v2_10(void) = ExitFunction :
3944+
3945+
# 962| Block 3
3946+
# 962| r3_0(int) = Constant[2] :
3947+
# 962| r3_1(glval<int>) = PointerAdd : r0_2, r3_0
3948+
# 962| r3_2(int) = Constant[10002] :
3949+
# 962| mu3_3(int) = Store : r3_1, r3_2
3950+
# 962| r3_4(int) = Constant[3] :
3951+
# 962| r3_5(glval<int>) = PointerAdd : r0_2, r3_4
3952+
# 962| r3_6(unknown[3588]) = Constant[0] :
3953+
# 962| mu3_7(unknown[3588]) = Store : r3_5, r3_6
3954+
#-----| Goto -> Block 2

cpp/ql/test/library-tests/ir/ir/ir.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -958,6 +958,11 @@ void OperatorNewArray(int n) {
958958
new int[n] { 0, 1, 2 };
959959
}
960960

961+
int designatedInit() {
962+
int a1[1000] = { [2] = 10002, [900] = 10900 };
963+
return a1[900];
964+
}
965+
961966
#if 0
962967
void OperatorDelete() {
963968
delete static_cast<int*>(nullptr); // No destructor

cpp/ql/test/library-tests/ir/ir/raw_ir.expected

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3885,3 +3885,49 @@ ir.cpp:
38853885
# 950| v0_65(void) = ReturnVoid :
38863886
# 950| v0_66(void) = UnmodeledUse : mu*
38873887
# 950| v0_67(void) = ExitFunction :
3888+
3889+
# 961| designatedInit() -> int
3890+
# 961| Block 0
3891+
# 961| v0_0(void) = EnterFunction :
3892+
# 961| mu0_1(unknown) = UnmodeledDefinition :
3893+
# 962| r0_2(glval<int[1000]>) = VariableAddress[a1] :
3894+
# 962| r0_3(int) = Constant[0] :
3895+
# 962| r0_4(glval<int>) = PointerAdd : r0_2, r0_3
3896+
# 962| r0_5(unknown[8]) = Constant[0] :
3897+
# 962| mu0_6(unknown[8]) = Store : r0_4, r0_5
3898+
#-----| Goto -> Block 2
3899+
3900+
# 962| Block 1
3901+
# 962| r1_0(int) = Constant[900] :
3902+
# 962| r1_1(glval<int>) = PointerAdd : r0_2, r1_0
3903+
# 962| r1_2(int) = Constant[10900] :
3904+
# 962| mu1_3(int) = Store : r1_1, r1_2
3905+
# 962| r1_4(int) = Constant[901] :
3906+
# 962| r1_5(glval<int>) = PointerAdd : r0_2, r1_4
3907+
# 962| r1_6(unknown[396]) = Constant[0] :
3908+
# 962| mu1_7(unknown[396]) = Store : r1_5, r1_6
3909+
#-----| Goto -> Block 2
3910+
3911+
# 963| Block 2
3912+
# 963| r2_0(glval<int>) = VariableAddress[#return] :
3913+
# 963| r2_1(glval<int[1000]>) = VariableAddress[a1] :
3914+
# 963| r2_2(int *) = Convert : r2_1
3915+
# 963| r2_3(int) = Constant[900] :
3916+
# 963| r2_4(int *) = PointerAdd[4] : r2_2, r2_3
3917+
# 963| r2_5(int) = Load : r2_4, mu0_1
3918+
# 963| mu2_6(int) = Store : r2_0, r2_5
3919+
# 961| r2_7(glval<int>) = VariableAddress[#return] :
3920+
# 961| v2_8(void) = ReturnValue : r2_7, mu0_1
3921+
# 961| v2_9(void) = UnmodeledUse : mu*
3922+
# 961| v2_10(void) = ExitFunction :
3923+
3924+
# 962| Block 3
3925+
# 962| r3_0(int) = Constant[2] :
3926+
# 962| r3_1(glval<int>) = PointerAdd : r0_2, r3_0
3927+
# 962| r3_2(int) = Constant[10002] :
3928+
# 962| mu3_3(int) = Store : r3_1, r3_2
3929+
# 962| r3_4(int) = Constant[3] :
3930+
# 962| r3_5(glval<int>) = PointerAdd : r0_2, r3_4
3931+
# 962| r3_6(unknown[3588]) = Constant[0] :
3932+
# 962| mu3_7(unknown[3588]) = Store : r3_5, r3_6
3933+
#-----| Goto -> Block 2

cpp/ql/test/library-tests/ir/ir/ssa_block_count.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
| IR: VarArgs | 1 |
9393
| IR: VirtualMemberFunction | 1 |
9494
| IR: WhileStatements | 4 |
95+
| IR: designatedInit | 4 |
9596
| IR: min | 4 |
9697
| IR: operator= | 1 |
9798
| IR: ~Base | 1 |

cpp/ql/test/library-tests/ir/ir/unaliased_ssa_ir.expected

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3906,3 +3906,49 @@ ir.cpp:
39063906
# 950| v0_65(void) = ReturnVoid :
39073907
# 950| v0_66(void) = UnmodeledUse : mu*
39083908
# 950| v0_67(void) = ExitFunction :
3909+
3910+
# 961| designatedInit() -> int
3911+
# 961| Block 0
3912+
# 961| v0_0(void) = EnterFunction :
3913+
# 961| mu0_1(unknown) = UnmodeledDefinition :
3914+
# 962| r0_2(glval<int[1000]>) = VariableAddress[a1] :
3915+
# 962| r0_3(int) = Constant[0] :
3916+
# 962| r0_4(glval<int>) = PointerAdd : r0_2, r0_3
3917+
# 962| r0_5(unknown[8]) = Constant[0] :
3918+
# 962| mu0_6(unknown[8]) = Store : r0_4, r0_5
3919+
#-----| Goto -> Block 2
3920+
3921+
# 962| Block 1
3922+
# 962| r1_0(int) = Constant[900] :
3923+
# 962| r1_1(glval<int>) = PointerAdd : r0_2, r1_0
3924+
# 962| r1_2(int) = Constant[10900] :
3925+
# 962| mu1_3(int) = Store : r1_1, r1_2
3926+
# 962| r1_4(int) = Constant[901] :
3927+
# 962| r1_5(glval<int>) = PointerAdd : r0_2, r1_4
3928+
# 962| r1_6(unknown[396]) = Constant[0] :
3929+
# 962| mu1_7(unknown[396]) = Store : r1_5, r1_6
3930+
#-----| Goto -> Block 2
3931+
3932+
# 963| Block 2
3933+
# 963| r2_0(glval<int>) = VariableAddress[#return] :
3934+
# 963| r2_1(glval<int[1000]>) = VariableAddress[a1] :
3935+
# 963| r2_2(int *) = Convert : r2_1
3936+
# 963| r2_3(int) = Constant[900] :
3937+
# 963| r2_4(int *) = PointerAdd[4] : r2_2, r2_3
3938+
# 963| r2_5(int) = Load : r2_4, mu0_1
3939+
# 963| m2_6(int) = Store : r2_0, r2_5
3940+
# 961| r2_7(glval<int>) = VariableAddress[#return] :
3941+
# 961| v2_8(void) = ReturnValue : r2_7, m2_6
3942+
# 961| v2_9(void) = UnmodeledUse : mu*
3943+
# 961| v2_10(void) = ExitFunction :
3944+
3945+
# 962| Block 3
3946+
# 962| r3_0(int) = Constant[2] :
3947+
# 962| r3_1(glval<int>) = PointerAdd : r0_2, r3_0
3948+
# 962| r3_2(int) = Constant[10002] :
3949+
# 962| mu3_3(int) = Store : r3_1, r3_2
3950+
# 962| r3_4(int) = Constant[3] :
3951+
# 962| r3_5(glval<int>) = PointerAdd : r0_2, r3_4
3952+
# 962| r3_6(unknown[3588]) = Constant[0] :
3953+
# 962| mu3_7(unknown[3588]) = Store : r3_5, r3_6
3954+
#-----| Goto -> Block 2

0 commit comments

Comments
 (0)