From 76b292da6aaa41e23a809ffde7ead9b8aca148f9 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Mon, 25 Jul 2022 14:26:54 -0400 Subject: [PATCH] C++: initial GVN for function calls --- .../gvn/internal/ValueNumberingInternal.qll | 74 +++++++++++++++++++ .../GlobalValueNumbering/ast_ir_gvn.expected | 6 +- .../diff_ir_expr.expected | 23 +++++- .../GlobalValueNumbering/ir_gvn.expected | 43 +++++------ 4 files changed, 123 insertions(+), 23 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/internal/ValueNumberingInternal.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/internal/ValueNumberingInternal.qll index 2dc735f49df..ebb6b6c06a4 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/internal/ValueNumberingInternal.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/internal/ValueNumberingInternal.qll @@ -41,8 +41,75 @@ newtype TValueNumber = ) { loadTotalOverlapValueNumber(_, irFunc, type, memOperand, operand) } or + TCallValueNumber(TCallPartialValueNumber vn) { callValueNumber(_, _, vn) } or TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) } +newtype TCallPartialValueNumber = + TNilArgument() or + TArgument(TCallPartialValueNumber head, TValueNumber arg) { + exists(CallInstruction call, int index | + callArgValueNumber(call, index, arg) and + callPartialValueNumber(call, index, head) + ) + } + +predicate callValueNumber(CallInstruction call, int index, TCallPartialValueNumber vn) { + index = max(int n | callArgRank(call, n, _) | n) and + exists(TCallPartialValueNumber head, TValueNumber arg | + callPartialValueNumber(call, index, head) and + callArgValueNumber(call, index, arg) and + vn = TArgument(head, arg) + ) + or + not exists(int n | callArgRank(call, n, _)) and + index = -1 and + vn = TNilArgument() +} + +predicate callPartialValueNumber(CallInstruction call, int index, TCallPartialValueNumber head) { + index = 1 and head = TNilArgument() + or + exists(TCallPartialValueNumber prev, TValueNumber prevVN | + callPartialValueNumber(call, index - 1, prev) and + callArgValueNumber(call, index - 1, prevVN) and + head = TArgument(prev, prevVN) + ) +} + +/** + */ +predicate callArgValueNumber(CallInstruction call, int index, TValueNumber arg) { + exists(Instruction instr | + callArgRank(call, index, instr) and + arg = tvalueNumber(instr) + ) +} + +/** + * Holds if `arg` is the `index`th element in `call`'s extended argument list, including the `this` + * argument and side-effect reads. + */ +predicate callArgRank(CallInstruction call, int index, Instruction arg) { + arg = + rank[index](int argIndex, boolean isEffect, Instruction instr | + instr = call.getThisArgument() and + argIndex = -1 and + isEffect = false + or + instr = call.getPositionalArgument(argIndex) and + isEffect = false + or + exists(ReadSideEffectInstruction read | + read.getPrimaryInstruction() = call and + read.getSideEffectOperand().getDef() = instr and + read.getIndex() = argIndex and + isEffect = true + ) + | + instr order by argIndex, isEffect + ) +} + /** * A `CopyInstruction` whose source operand's value is congruent to the definition of that source * operand. @@ -93,6 +160,8 @@ private predicate numberableInstruction(Instruction instr) { instr instanceof CongruentCopyInstruction or instr instanceof LoadTotalOverlapInstruction + or + instr instanceof CallInstruction } private predicate filteredNumberableInstruction(Instruction instr) { @@ -309,6 +378,11 @@ private TValueNumber nonUniqueValueNumber(Instruction instr) { or // The value number of a copy is just the value number of its source value. result = tvalueNumber(instr.(CongruentCopyInstruction).getSourceValue()) + or + exists(TCallPartialValueNumber pvn | + callValueNumber(instr, _, pvn) and + result = TCallValueNumber(pvn) + ) ) ) } diff --git a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ast_ir_gvn.expected b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ast_ir_gvn.expected index b76e3ac2abc..0671cdf1db9 100644 --- a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ast_ir_gvn.expected +++ b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ast_ir_gvn.expected @@ -12,6 +12,7 @@ | test.cpp:29:7:29:8 | GVN | 29:c7-c8 31:c7-c8 | | test.cpp:29:7:29:13 | GVN | 29:c7-c13 31:c7-c13 | | test.cpp:29:12:29:13 | GVN | 29:c12-c13 31:c12-c13 | +| test.cpp:30:3:30:17 | GVN | 30:c3-c17 77:c20-c28 80:c9-c17 | | test.cpp:31:7:31:24 | GVN | 31:c7-c24 32:c7-c7 | | test.cpp:43:3:43:3 | GVN | 43:c3-c3 45:c3-c3 | | test.cpp:43:7:43:8 | GVN | 43:c7-c8 45:c7-c8 | @@ -28,7 +29,7 @@ | test.cpp:56:13:56:16 | GVN | 56:c13-c16 56:c31-c34 59:c9-c12 | | test.cpp:56:14:56:16 | GVN | 56:c14-c16 56:c32-c34 56:c47-c49 59:c10-c12 | | test.cpp:62:5:62:10 | GVN | 62:c5-c10 65:c10-c15 | -| test.cpp:77:20:77:28 | GVN | 77:c20-c28 79:c7-c7 | +| test.cpp:77:20:77:28 | GVN | 77:c20-c28 79:c7-c7 80:c9-c17 | | test.cpp:79:11:79:14 | GVN | 79:c11-c14 79:c24-c27 | | test.cpp:92:11:92:16 | GVN | 92:c11-c16 92:c15-c16 93:c10-c10 | | test.cpp:105:11:105:12 | GVN | 105:c11-c12 106:c33-c34 | @@ -44,9 +45,12 @@ | test.cpp:144:15:144:15 | GVN | 144:c15-c15 149:c15-c15 | | test.cpp:153:11:153:18 | GVN | 153:c11-c18 154:c11-c18 156:c3-c10 | | test.cpp:153:21:153:21 | GVN | 153:c21-c21 154:c21-c21 | +| test.cpp:166:11:166:16 | GVN | 166:c11-c16 167:c11-c16 173:c11-c16 | | test.cpp:166:18:166:20 | GVN | 166:c18-c20 167:c18-c20 171:c10-c12 173:c18-c20 | | test.cpp:166:18:166:20 | GVN | 166:c18-c20 167:c18-c20 173:c18-c20 | +| test.cpp:168:11:168:16 | GVN | 168:c11-c16 169:c11-c16 174:c11-c16 | | test.cpp:168:18:168:20 | GVN | 168:c18-c20 169:c18-c20 171:c15-c17 174:c18-c20 | | test.cpp:168:18:168:20 | GVN | 168:c18-c20 169:c18-c20 171:c15-c17 174:c18-c20 | +| test.cpp:176:3:176:5 | GVN | 176:c3-c5 178:c3-c5 | | test.cpp:176:7:176:7 | GVN | 176:c7-c7 178:c7-c7 | | test.cpp:176:10:176:10 | GVN | 176:c10-c10 178:c10-c10 | diff --git a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/diff_ir_expr.expected b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/diff_ir_expr.expected index d0d2259905e..d9232b53245 100644 --- a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/diff_ir_expr.expected +++ b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/diff_ir_expr.expected @@ -10,7 +10,8 @@ | test.cpp:21:16:21:16 | 2 | test.cpp:178:10:178:10 | 2 | AST only | | test.cpp:29:3:29:3 | x | test.cpp:31:3:31:3 | x | IR only | | test.cpp:29:3:29:24 | ... = ... | test.cpp:29:3:29:24 | ... = ... | AST only | -| test.cpp:30:3:30:17 | call to change_global02 | test.cpp:30:3:30:17 | call to change_global02 | AST only | +| test.cpp:30:3:30:17 | call to change_global02 | test.cpp:77:20:77:28 | call to getAValue | IR only | +| test.cpp:30:3:30:17 | call to change_global02 | test.cpp:80:9:80:17 | call to getAValue | IR only | | test.cpp:31:3:31:3 | x | test.cpp:29:3:29:3 | x | IR only | | test.cpp:31:3:31:24 | ... = ... | test.cpp:31:3:31:24 | ... = ... | AST only | | test.cpp:32:3:32:7 | ... = ... | test.cpp:32:3:32:7 | ... = ... | AST only | @@ -77,15 +78,21 @@ | test.cpp:59:17:59:20 | (int)... | test.cpp:59:17:59:20 | (int)... | AST only | | test.cpp:59:17:59:20 | (int)... | test.cpp:88:12:88:12 | 0 | AST only | | test.cpp:62:5:62:12 | ... ++ | test.cpp:62:5:62:12 | ... ++ | AST only | +| test.cpp:77:20:77:28 | call to getAValue | test.cpp:30:3:30:17 | call to change_global02 | IR only | | test.cpp:77:20:77:28 | call to getAValue | test.cpp:79:7:79:7 | v | IR only | +| test.cpp:77:20:77:28 | call to getAValue | test.cpp:80:9:80:17 | call to getAValue | IR only | | test.cpp:77:20:77:30 | (signed short)... | test.cpp:77:20:77:30 | (signed short)... | AST only | | test.cpp:77:20:77:30 | (signed short)... | test.cpp:79:7:79:7 | v | AST only | | test.cpp:79:7:79:7 | (int)... | test.cpp:79:7:79:7 | (int)... | AST only | | test.cpp:79:7:79:7 | v | test.cpp:77:20:77:28 | call to getAValue | IR only | | test.cpp:79:7:79:7 | v | test.cpp:77:20:77:30 | (signed short)... | AST only | +| test.cpp:79:7:79:7 | v | test.cpp:80:9:80:17 | call to getAValue | IR only | | test.cpp:79:11:79:20 | (int)... | test.cpp:79:11:79:20 | (int)... | AST only | | test.cpp:79:24:79:33 | (int)... | test.cpp:79:24:79:33 | (int)... | AST only | | test.cpp:80:5:80:19 | ... = ... | test.cpp:80:5:80:19 | ... = ... | AST only | +| test.cpp:80:9:80:17 | call to getAValue | test.cpp:30:3:30:17 | call to change_global02 | IR only | +| test.cpp:80:9:80:17 | call to getAValue | test.cpp:77:20:77:28 | call to getAValue | IR only | +| test.cpp:80:9:80:17 | call to getAValue | test.cpp:79:7:79:7 | v | IR only | | test.cpp:80:9:80:19 | (signed short)... | test.cpp:80:9:80:19 | (signed short)... | AST only | | test.cpp:88:3:88:20 | ... = ... | test.cpp:88:3:88:20 | ... = ... | AST only | | test.cpp:88:12:88:12 | 0 | test.cpp:44:9:44:9 | 0 | AST only | @@ -132,16 +139,24 @@ | test.cpp:147:7:147:7 | y | test.cpp:145:15:145:15 | y | AST only | | test.cpp:149:15:149:15 | x | test.cpp:144:15:144:15 | x | IR only | | test.cpp:156:3:156:17 | ... = ... | test.cpp:156:3:156:17 | ... = ... | AST only | +| test.cpp:166:11:166:16 | call to strlen | test.cpp:167:11:167:16 | call to strlen | IR only | +| test.cpp:166:11:166:16 | call to strlen | test.cpp:173:11:173:16 | call to strlen | IR only | | test.cpp:166:18:166:20 | (const char *)... | test.cpp:166:18:166:20 | (const char *)... | AST only | | test.cpp:166:18:166:20 | (const char *)... | test.cpp:167:18:167:20 | (const char *)... | AST only | | test.cpp:166:18:166:20 | (const char *)... | test.cpp:173:18:173:20 | (const char *)... | AST only | +| test.cpp:167:11:167:16 | call to strlen | test.cpp:166:11:166:16 | call to strlen | IR only | +| test.cpp:167:11:167:16 | call to strlen | test.cpp:173:11:173:16 | call to strlen | IR only | | test.cpp:167:18:167:20 | (const char *)... | test.cpp:166:18:166:20 | (const char *)... | AST only | | test.cpp:167:18:167:20 | (const char *)... | test.cpp:167:18:167:20 | (const char *)... | AST only | | test.cpp:167:18:167:20 | (const char *)... | test.cpp:173:18:173:20 | (const char *)... | AST only | +| test.cpp:168:11:168:16 | call to strlen | test.cpp:169:11:169:16 | call to strlen | IR only | +| test.cpp:168:11:168:16 | call to strlen | test.cpp:174:11:174:16 | call to strlen | IR only | | test.cpp:168:18:168:20 | (const char *)... | test.cpp:168:18:168:20 | (const char *)... | AST only | | test.cpp:168:18:168:20 | (const char *)... | test.cpp:169:18:169:20 | (const char *)... | AST only | | test.cpp:168:18:168:20 | (const char *)... | test.cpp:171:15:171:17 | (const char *)... | AST only | | test.cpp:168:18:168:20 | (const char *)... | test.cpp:174:18:174:20 | (const char *)... | AST only | +| test.cpp:169:11:169:16 | call to strlen | test.cpp:168:11:168:16 | call to strlen | IR only | +| test.cpp:169:11:169:16 | call to strlen | test.cpp:174:11:174:16 | call to strlen | IR only | | test.cpp:169:18:169:20 | (const char *)... | test.cpp:168:18:168:20 | (const char *)... | AST only | | test.cpp:169:18:169:20 | (const char *)... | test.cpp:169:18:169:20 | (const char *)... | AST only | | test.cpp:169:18:169:20 | (const char *)... | test.cpp:171:15:171:17 | (const char *)... | AST only | @@ -150,15 +165,21 @@ | test.cpp:171:15:171:17 | (const char *)... | test.cpp:169:18:169:20 | (const char *)... | AST only | | test.cpp:171:15:171:17 | (const char *)... | test.cpp:171:15:171:17 | (const char *)... | AST only | | test.cpp:171:15:171:17 | (const char *)... | test.cpp:174:18:174:20 | (const char *)... | AST only | +| test.cpp:173:11:173:16 | call to strlen | test.cpp:166:11:166:16 | call to strlen | IR only | +| test.cpp:173:11:173:16 | call to strlen | test.cpp:167:11:167:16 | call to strlen | IR only | | test.cpp:173:18:173:20 | (const char *)... | test.cpp:166:18:166:20 | (const char *)... | AST only | | test.cpp:173:18:173:20 | (const char *)... | test.cpp:167:18:167:20 | (const char *)... | AST only | | test.cpp:173:18:173:20 | (const char *)... | test.cpp:173:18:173:20 | (const char *)... | AST only | +| test.cpp:174:11:174:16 | call to strlen | test.cpp:168:11:168:16 | call to strlen | IR only | +| test.cpp:174:11:174:16 | call to strlen | test.cpp:169:11:169:16 | call to strlen | IR only | | test.cpp:174:18:174:20 | (const char *)... | test.cpp:168:18:168:20 | (const char *)... | AST only | | test.cpp:174:18:174:20 | (const char *)... | test.cpp:169:18:169:20 | (const char *)... | AST only | | test.cpp:174:18:174:20 | (const char *)... | test.cpp:171:15:171:17 | (const char *)... | AST only | | test.cpp:174:18:174:20 | (const char *)... | test.cpp:174:18:174:20 | (const char *)... | AST only | +| test.cpp:176:3:176:5 | call to add | test.cpp:178:3:178:5 | call to add | IR only | | test.cpp:176:7:176:7 | 1 | test.cpp:10:16:10:16 | 1 | AST only | | test.cpp:176:10:176:10 | 2 | test.cpp:21:16:21:16 | 2 | AST only | | test.cpp:177:7:177:7 | 3 | test.cpp:35:16:35:16 | 3 | AST only | +| test.cpp:178:3:178:5 | call to add | test.cpp:176:3:176:5 | call to add | IR only | | test.cpp:178:7:178:7 | 1 | test.cpp:10:16:10:16 | 1 | AST only | | test.cpp:178:10:178:10 | 2 | test.cpp:21:16:21:16 | 2 | AST only | diff --git a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected index 99aa3538253..bf1c05c4c43 100644 --- a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected +++ b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected @@ -237,6 +237,7 @@ test.cpp: # 30| r30_1(glval) = FunctionAddress[change_global02] : # 30| valnum = unique # 30| v30_2(void) = Call[change_global02] : func:r30_1 +# 30| valnum = r77_3, r80_2, v30_2 # 30| m30_3(unknown) = ^CallSideEffect : ~m25_4 # 30| valnum = unique # 30| m30_4(unknown) = Chi : total:m25_4, partial:m30_3 @@ -590,19 +591,19 @@ test.cpp: # 77| r77_2(glval) = FunctionAddress[getAValue] : # 77| valnum = unique # 77| r77_3(int) = Call[getAValue] : func:r77_2 -# 77| valnum = unique +# 77| valnum = r77_3, r80_2, v30_2 # 77| m77_4(unknown) = ^CallSideEffect : ~m75_4 # 77| valnum = unique # 77| m77_5(unknown) = Chi : total:m75_4, partial:m77_4 # 77| valnum = unique # 77| r77_6(signed short) = Convert : r77_3 -# 77| valnum = m77_7, r77_6, r79_2 +# 77| valnum = m77_7, m80_7, r77_6, r79_2, r80_5 # 77| m77_7(signed short) = Store[v] : &:r77_1, r77_6 -# 77| valnum = m77_7, r77_6, r79_2 +# 77| valnum = m77_7, m80_7, r77_6, r79_2, r80_5 # 79| r79_1(glval) = VariableAddress[v] : # 79| valnum = r77_1, r79_1, r80_6 # 79| r79_2(signed short) = Load[v] : &:r79_1, m77_7 -# 79| valnum = m77_7, r77_6, r79_2 +# 79| valnum = m77_7, m80_7, r77_6, r79_2, r80_5 # 79| r79_3(int) = Convert : r79_2 # 79| valnum = unique # 79| r79_4(glval) = VariableAddress[vals] : @@ -637,17 +638,17 @@ test.cpp: # 80| r80_1(glval) = FunctionAddress[getAValue] : # 80| valnum = unique # 80| r80_2(int) = Call[getAValue] : func:r80_1 -# 80| valnum = unique +# 80| valnum = r77_3, r80_2, v30_2 # 80| m80_3(unknown) = ^CallSideEffect : ~m77_5 # 80| valnum = unique # 80| m80_4(unknown) = Chi : total:m77_5, partial:m80_3 # 80| valnum = unique # 80| r80_5(signed short) = Convert : r80_2 -# 80| valnum = m80_7, r80_5 +# 80| valnum = m77_7, m80_7, r77_6, r79_2, r80_5 # 80| r80_6(glval) = VariableAddress[v] : # 80| valnum = r77_1, r79_1, r80_6 # 80| m80_7(signed short) = Store[v] : &:r80_6, r80_5 -# 80| valnum = m80_7, r80_5 +# 80| valnum = m77_7, m80_7, r77_6, r79_2, r80_5 #-----| Goto -> Block 2 # 82| Block 2 @@ -1182,10 +1183,10 @@ test.cpp: # 166| r166_5(char *) = Convert : r166_4 # 166| valnum = r166_5, r167_5, r173_5 # 166| r166_6(int) = Call[strlen] : func:r166_2, 0:r166_5 -# 166| valnum = m166_8, r166_6 +# 166| valnum = m166_8, m167_8, m173_8, r166_6, r167_6, r173_6 # 166| v166_7(void) = ^BufferReadSideEffect[0] : &:r166_5, ~m165_8 # 166| m166_8(int) = Store[a] : &:r166_1, r166_6 -# 166| valnum = m166_8, r166_6 +# 166| valnum = m166_8, m167_8, m173_8, r166_6, r167_6, r173_6 # 167| r167_1(glval) = VariableAddress[b] : # 167| valnum = unique # 167| r167_2(glval) = FunctionAddress[strlen] : @@ -1197,10 +1198,10 @@ test.cpp: # 167| r167_5(char *) = Convert : r167_4 # 167| valnum = r166_5, r167_5, r173_5 # 167| r167_6(int) = Call[strlen] : func:r167_2, 0:r167_5 -# 167| valnum = m167_8, r167_6 +# 167| valnum = m166_8, m167_8, m173_8, r166_6, r167_6, r173_6 # 167| v167_7(void) = ^BufferReadSideEffect[0] : &:r167_5, ~m165_8 # 167| m167_8(int) = Store[b] : &:r167_1, r167_6 -# 167| valnum = m167_8, r167_6 +# 167| valnum = m166_8, m167_8, m173_8, r166_6, r167_6, r173_6 # 168| r168_1(glval) = VariableAddress[c] : # 168| valnum = unique # 168| r168_2(glval) = FunctionAddress[strlen] : @@ -1212,10 +1213,10 @@ test.cpp: # 168| r168_5(char *) = Convert : r168_4 # 168| valnum = r168_5, r169_5, r171_6, r174_5 # 168| r168_6(int) = Call[strlen] : func:r168_2, 0:r168_5 -# 168| valnum = m168_8, r168_6 +# 168| valnum = m168_8, m169_8, m174_8, r168_6, r169_6, r174_6 # 168| v168_7(void) = ^BufferReadSideEffect[0] : &:r168_5, ~m165_12 # 168| m168_8(int) = Store[c] : &:r168_1, r168_6 -# 168| valnum = m168_8, r168_6 +# 168| valnum = m168_8, m169_8, m174_8, r168_6, r169_6, r174_6 # 169| r169_1(glval) = VariableAddress[d] : # 169| valnum = unique # 169| r169_2(glval) = FunctionAddress[strlen] : @@ -1227,10 +1228,10 @@ test.cpp: # 169| r169_5(char *) = Convert : r169_4 # 169| valnum = r168_5, r169_5, r171_6, r174_5 # 169| r169_6(int) = Call[strlen] : func:r169_2, 0:r169_5 -# 169| valnum = m169_8, r169_6 +# 169| valnum = m168_8, m169_8, m174_8, r168_6, r169_6, r174_6 # 169| v169_7(void) = ^BufferReadSideEffect[0] : &:r169_5, ~m165_12 # 169| m169_8(int) = Store[d] : &:r169_1, r169_6 -# 169| valnum = m169_8, r169_6 +# 169| valnum = m168_8, m169_8, m174_8, r168_6, r169_6, r174_6 # 171| r171_1(glval) = FunctionAddress[strcat] : # 171| valnum = unique # 171| r171_2(glval) = VariableAddress[dst] : @@ -1262,10 +1263,10 @@ test.cpp: # 173| r173_5(char *) = Convert : r173_4 # 173| valnum = r166_5, r167_5, r173_5 # 173| r173_6(int) = Call[strlen] : func:r173_2, 0:r173_5 -# 173| valnum = m173_8, r173_6 +# 173| valnum = m166_8, m167_8, m173_8, r166_6, r167_6, r173_6 # 173| v173_7(void) = ^BufferReadSideEffect[0] : &:r173_5, ~m171_11 # 173| m173_8(int) = Store[e] : &:r173_1, r173_6 -# 173| valnum = m173_8, r173_6 +# 173| valnum = m166_8, m167_8, m173_8, r166_6, r167_6, r173_6 # 174| r174_1(glval) = VariableAddress[f] : # 174| valnum = unique # 174| r174_2(glval) = FunctionAddress[strlen] : @@ -1277,10 +1278,10 @@ test.cpp: # 174| r174_5(char *) = Convert : r174_4 # 174| valnum = r168_5, r169_5, r171_6, r174_5 # 174| r174_6(int) = Call[strlen] : func:r174_2, 0:r174_5 -# 174| valnum = m174_8, r174_6 +# 174| valnum = m168_8, m169_8, m174_8, r168_6, r169_6, r174_6 # 174| v174_7(void) = ^BufferReadSideEffect[0] : &:r174_5, ~m165_12 # 174| m174_8(int) = Store[f] : &:r174_1, r174_6 -# 174| valnum = m174_8, r174_6 +# 174| valnum = m168_8, m169_8, m174_8, r168_6, r169_6, r174_6 # 176| r176_1(glval) = FunctionAddress[add] : # 176| valnum = unique # 176| r176_2(int) = Constant[1] : @@ -1288,7 +1289,7 @@ test.cpp: # 176| r176_3(int) = Constant[2] : # 176| valnum = r176_3, r178_3 # 176| r176_4(int) = Call[add] : func:r176_1, 0:r176_2, 1:r176_3 -# 176| valnum = unique +# 176| valnum = r176_4, r178_4 # 176| m176_5(unknown) = ^CallSideEffect : ~m165_4 # 176| valnum = unique # 176| m176_6(unknown) = Chi : total:m165_4, partial:m176_5 @@ -1312,7 +1313,7 @@ test.cpp: # 178| r178_3(int) = Constant[2] : # 178| valnum = r176_3, r178_3 # 178| r178_4(int) = Call[add] : func:r178_1, 0:r178_2, 1:r178_3 -# 178| valnum = unique +# 178| valnum = r176_4, r178_4 # 178| m178_5(unknown) = ^CallSideEffect : ~m177_6 # 178| valnum = unique # 178| m178_6(unknown) = Chi : total:m177_6, partial:m178_5