From 0b691dd46ca245eb8c0d0f89d15f175562646486 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Mon, 25 Jul 2022 14:24:41 -0400 Subject: [PATCH 01/19] C++: function tests for GVN --- .../GlobalValueNumbering/ast_gvn.expected | 7 + .../GlobalValueNumbering/ast_ir_gvn.expected | 6 + .../diff_ir_expr.expected | 35 ++++ .../GlobalValueNumbering/ir_gvn.expected | 178 ++++++++++++++++++ .../GlobalValueNumbering/test.cpp | 20 ++ 5 files changed, 246 insertions(+) diff --git a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ast_gvn.expected b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ast_gvn.expected index d5d46ee0b72d..96fb15a2f22c 100644 --- a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ast_gvn.expected +++ b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ast_gvn.expected @@ -2,6 +2,7 @@ | test.cpp:5:7:5:8 | p0 | 5:c7-c8 6:c7-c8 | | test.cpp:5:7:5:13 | ... + ... | 5:c7-c13 6:c7-c13 7:c7-c7 | | test.cpp:5:12:5:13 | p1 | 5:c12-c13 6:c12-c13 | +| test.cpp:10:16:10:16 | 1 | 10:c16-c16 176:c7-c7 178:c7-c7 | | test.cpp:16:3:16:3 | x | 16:c3-c3 17:c3-c3 | | test.cpp:16:7:16:8 | p0 | 16:c7-c8 17:c7-c8 | | test.cpp:16:7:16:13 | ... + ... | 16:c7-c13 17:c7-c13 | @@ -38,3 +39,9 @@ | test.cpp:145:15:145:15 | y | 145:c15-c15 147:c7-c7 | | test.cpp:153:11:153:18 | global_a | 153:c11-c18 154:c11-c18 156:c3-c10 | | test.cpp:153:21:153:21 | x | 153:c21-c21 154:c21-c21 | +| test.cpp:166:18:166:20 | (const char *)... | 166:c18-c20 167:c18-c20 173:c18-c20 | +| test.cpp:166:18:166:20 | dst | 166:c18-c20 167:c18-c20 171:c10-c12 173:c18-c20 | +| test.cpp:168:18:168:20 | (const char *)... | 168:c18-c20 169:c18-c20 171:c15-c17 174:c18-c20 | +| test.cpp:168:18:168:20 | src | 168:c18-c20 169:c18-c20 171:c15-c17 174:c18-c20 | +| test.cpp:176:10:176:10 | 2 | 176:c10-c10 178:c10-c10 21:c16-c16 | +| test.cpp:177:7:177:7 | 3 | 177:c7-c7 35:c16-c16 | 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 2e8aecd11a6b..b76e3ac2abcb 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 @@ -44,3 +44,9 @@ | 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: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: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: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 b838a13d5af3..d0d2259905e5 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 @@ -1,15 +1,20 @@ | test.cpp:5:3:5:13 | ... = ... | test.cpp:5:3:5:13 | ... = ... | AST only | | test.cpp:6:3:6:13 | ... = ... | test.cpp:6:3:6:13 | ... = ... | AST only | | test.cpp:7:3:7:7 | ... = ... | test.cpp:7:3:7:7 | ... = ... | AST only | +| test.cpp:10:16:10:16 | 1 | test.cpp:176:7:176:7 | 1 | AST only | +| test.cpp:10:16:10:16 | 1 | test.cpp:178:7:178:7 | 1 | AST only | | test.cpp:16:3:16:24 | ... = ... | test.cpp:16:3:16:24 | ... = ... | AST only | | test.cpp:17:3:17:24 | ... = ... | test.cpp:17:3:17:24 | ... = ... | AST only | | test.cpp:18:3:18:7 | ... = ... | test.cpp:18:3:18:7 | ... = ... | AST only | +| test.cpp:21:16:21:16 | 2 | test.cpp:176:10:176:10 | 2 | AST only | +| 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: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 | +| test.cpp:35:16:35:16 | 3 | test.cpp:177:7:177:7 | 3 | AST only | | test.cpp:43:3:43:3 | x | test.cpp:45:3:45:3 | x | IR only | | test.cpp:43:3:43:24 | ... = ... | test.cpp:43:3:43:24 | ... = ... | AST only | | test.cpp:43:7:43:24 | ... + ... | test.cpp:45:7:45:24 | ... + ... | IR only | @@ -127,3 +132,33 @@ | 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: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: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: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: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 | +| test.cpp:169:18:169:20 | (const char *)... | test.cpp:174:18:174:20 | (const char *)... | AST only | +| test.cpp:171:15:171:17 | (const char *)... | test.cpp:168:18:168:20 | (const char *)... | AST only | +| 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: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: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: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: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 88e365023a11..99aa3538253e 100644 --- a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected +++ b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected @@ -1145,3 +1145,181 @@ test.cpp: # 152| v152_7(void) = ReturnVoid : # 152| v152_8(void) = AliasedUse : ~m156_7 # 152| v152_9(void) = ExitFunction : + +# 165| void test_func_value_numbering(char*, char*) +# 165| Block 0 +# 165| v165_1(void) = EnterFunction : +# 165| m165_2(unknown) = AliasedDefinition : +# 165| valnum = unique +# 165| m165_3(unknown) = InitializeNonLocal : +# 165| valnum = unique +# 165| m165_4(unknown) = Chi : total:m165_2, partial:m165_3 +# 165| valnum = unique +# 165| r165_5(glval) = VariableAddress[dst] : +# 165| valnum = r165_5, r166_3, r167_3, r171_2, r173_3 +# 165| m165_6(char *) = InitializeParameter[dst] : &:r165_5 +# 165| valnum = m165_6, r165_7, r166_4, r167_4, r171_3, r173_4 +# 165| r165_7(char *) = Load[dst] : &:r165_5, m165_6 +# 165| valnum = m165_6, r165_7, r166_4, r167_4, r171_3, r173_4 +# 165| m165_8(unknown) = InitializeIndirection[dst] : &:r165_7 +# 165| valnum = unique +# 165| r165_9(glval) = VariableAddress[src] : +# 165| valnum = r165_9, r168_3, r169_3, r171_4, r174_3 +# 165| m165_10(char *) = InitializeParameter[src] : &:r165_9 +# 165| valnum = m165_10, r165_11, r168_4, r169_4, r171_5, r174_4 +# 165| r165_11(char *) = Load[src] : &:r165_9, m165_10 +# 165| valnum = m165_10, r165_11, r168_4, r169_4, r171_5, r174_4 +# 165| m165_12(unknown) = InitializeIndirection[src] : &:r165_11 +# 165| valnum = unique +# 166| r166_1(glval) = VariableAddress[a] : +# 166| valnum = unique +# 166| r166_2(glval) = FunctionAddress[strlen] : +# 166| valnum = unique +# 166| r166_3(glval) = VariableAddress[dst] : +# 166| valnum = r165_5, r166_3, r167_3, r171_2, r173_3 +# 166| r166_4(char *) = Load[dst] : &:r166_3, m165_6 +# 166| valnum = m165_6, r165_7, r166_4, r167_4, r171_3, r173_4 +# 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| 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 +# 167| r167_1(glval) = VariableAddress[b] : +# 167| valnum = unique +# 167| r167_2(glval) = FunctionAddress[strlen] : +# 167| valnum = unique +# 167| r167_3(glval) = VariableAddress[dst] : +# 167| valnum = r165_5, r166_3, r167_3, r171_2, r173_3 +# 167| r167_4(char *) = Load[dst] : &:r167_3, m165_6 +# 167| valnum = m165_6, r165_7, r166_4, r167_4, r171_3, r173_4 +# 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| 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 +# 168| r168_1(glval) = VariableAddress[c] : +# 168| valnum = unique +# 168| r168_2(glval) = FunctionAddress[strlen] : +# 168| valnum = unique +# 168| r168_3(glval) = VariableAddress[src] : +# 168| valnum = r165_9, r168_3, r169_3, r171_4, r174_3 +# 168| r168_4(char *) = Load[src] : &:r168_3, m165_10 +# 168| valnum = m165_10, r165_11, r168_4, r169_4, r171_5, r174_4 +# 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| 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 +# 169| r169_1(glval) = VariableAddress[d] : +# 169| valnum = unique +# 169| r169_2(glval) = FunctionAddress[strlen] : +# 169| valnum = unique +# 169| r169_3(glval) = VariableAddress[src] : +# 169| valnum = r165_9, r168_3, r169_3, r171_4, r174_3 +# 169| r169_4(char *) = Load[src] : &:r169_3, m165_10 +# 169| valnum = m165_10, r165_11, r168_4, r169_4, r171_5, r174_4 +# 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| 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 +# 171| r171_1(glval) = FunctionAddress[strcat] : +# 171| valnum = unique +# 171| r171_2(glval) = VariableAddress[dst] : +# 171| valnum = r165_5, r166_3, r167_3, r171_2, r173_3 +# 171| r171_3(char *) = Load[dst] : &:r171_2, m165_6 +# 171| valnum = m165_6, r165_7, r166_4, r167_4, r171_3, r173_4 +# 171| r171_4(glval) = VariableAddress[src] : +# 171| valnum = r165_9, r168_3, r169_3, r171_4, r174_3 +# 171| r171_5(char *) = Load[src] : &:r171_4, m165_10 +# 171| valnum = m165_10, r165_11, r168_4, r169_4, r171_5, r174_4 +# 171| r171_6(char *) = Convert : r171_5 +# 171| valnum = r168_5, r169_5, r171_6, r174_5 +# 171| r171_7(char *) = Call[strcat] : func:r171_1, 0:r171_3, 1:r171_6 +# 171| valnum = unique +# 171| v171_8(void) = ^BufferReadSideEffect[0] : &:r171_3, ~m165_8 +# 171| v171_9(void) = ^BufferReadSideEffect[1] : &:r171_6, ~m165_12 +# 171| m171_10(unknown) = ^BufferMayWriteSideEffect[0] : &:r171_3 +# 171| valnum = unique +# 171| m171_11(unknown) = Chi : total:m165_8, partial:m171_10 +# 171| valnum = unique +# 173| r173_1(glval) = VariableAddress[e] : +# 173| valnum = unique +# 173| r173_2(glval) = FunctionAddress[strlen] : +# 173| valnum = unique +# 173| r173_3(glval) = VariableAddress[dst] : +# 173| valnum = r165_5, r166_3, r167_3, r171_2, r173_3 +# 173| r173_4(char *) = Load[dst] : &:r173_3, m165_6 +# 173| valnum = m165_6, r165_7, r166_4, r167_4, r171_3, r173_4 +# 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| 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 +# 174| r174_1(glval) = VariableAddress[f] : +# 174| valnum = unique +# 174| r174_2(glval) = FunctionAddress[strlen] : +# 174| valnum = unique +# 174| r174_3(glval) = VariableAddress[src] : +# 174| valnum = r165_9, r168_3, r169_3, r171_4, r174_3 +# 174| r174_4(char *) = Load[src] : &:r174_3, m165_10 +# 174| valnum = m165_10, r165_11, r168_4, r169_4, r171_5, r174_4 +# 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| 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 +# 176| r176_1(glval) = FunctionAddress[add] : +# 176| valnum = unique +# 176| r176_2(int) = Constant[1] : +# 176| valnum = r176_2, r178_2 +# 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| m176_5(unknown) = ^CallSideEffect : ~m165_4 +# 176| valnum = unique +# 176| m176_6(unknown) = Chi : total:m165_4, partial:m176_5 +# 176| valnum = unique +# 177| r177_1(glval) = FunctionAddress[add] : +# 177| valnum = unique +# 177| r177_2(int) = Constant[3] : +# 177| valnum = unique +# 177| r177_3(int) = Constant[4] : +# 177| valnum = unique +# 177| r177_4(int) = Call[add] : func:r177_1, 0:r177_2, 1:r177_3 +# 177| valnum = unique +# 177| m177_5(unknown) = ^CallSideEffect : ~m176_6 +# 177| valnum = unique +# 177| m177_6(unknown) = Chi : total:m176_6, partial:m177_5 +# 177| valnum = unique +# 178| r178_1(glval) = FunctionAddress[add] : +# 178| valnum = unique +# 178| r178_2(int) = Constant[1] : +# 178| valnum = r176_2, r178_2 +# 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| m178_5(unknown) = ^CallSideEffect : ~m177_6 +# 178| valnum = unique +# 178| m178_6(unknown) = Chi : total:m177_6, partial:m178_5 +# 178| valnum = unique +# 179| v179_1(void) = NoOp : +# 165| v165_13(void) = ReturnIndirection[dst] : &:r165_7, m171_11 +# 165| v165_14(void) = ReturnIndirection[src] : &:r165_11, m165_12 +# 165| v165_15(void) = ReturnVoid : +# 165| v165_16(void) = AliasedUse : ~m178_6 +# 165| v165_17(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/test.cpp b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/test.cpp index dfef91006e38..c3624f7bf206 100644 --- a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/test.cpp +++ b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/test.cpp @@ -156,4 +156,24 @@ void test_read_global_different(int n) { global_a->y = n; int d = global_a->x; +} + +int strlen(const char *str); +char *strcat(char *dst, const char *src); +int add(int a, int b); + +void test_func_value_numbering(char *dst, char *src) { + int a = strlen(dst); + int b = strlen(dst); // same as previous line + int c = strlen(src); + int d = strlen(src); // same as previous line + + strcat(dst, src); + + int e = strlen(dst); // different from a and b + int f = strlen(src); // same as c and d + + add(1, 2); + add(3, 4); + add(1, 2); // same as two lines earlier } \ No newline at end of file From 76b292da6aaa41e23a809ffde7ead9b8aca148f9 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Mon, 25 Jul 2022 14:26:54 -0400 Subject: [PATCH 02/19] 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 2dc735f49dfb..ebb6b6c06a47 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 b76e3ac2abcb..0671cdf1db90 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 d0d2259905e5..d9232b532454 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 99aa3538253e..bf1c05c4c434 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 From cc8e65f811067519c84fbf8ab969e3d52ce42771 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Mon, 25 Jul 2022 14:55:20 -0400 Subject: [PATCH 03/19] C++: include aliased memory in function call GVNs --- .../implementation/aliased_ssa/Instruction.qll | 18 ++++++++++++++++++ .../gvn/internal/ValueNumberingInternal.qll | 14 ++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll index 8e863ddf6352..3679b9e9bce4 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll @@ -1712,6 +1712,15 @@ class SideEffectInstruction extends Instruction { */ class CallSideEffectInstruction extends SideEffectInstruction { CallSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallSideEffect } + + /** Gets the operand for the value that will be read by this instruction */ + final SideEffectOperand getSideEffectOperand() { + result = this.getAnOperand() + } + + final Instruction getSideEffect() { + result = this.getAnOperand().getDef() + } } /** @@ -1723,6 +1732,15 @@ class CallSideEffectInstruction extends SideEffectInstruction { */ class CallReadSideEffectInstruction extends SideEffectInstruction { CallReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallReadSideEffect } + + /** Gets the operand for the value that will be read by this instruction */ + final SideEffectOperand getSideEffectOperand() { + result = this.getAnOperand() + } + + final Instruction getSideEffect() { + result = this.getAnOperand().getDef() + } } /** 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 ebb6b6c06a47..02de941eea57 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 @@ -92,6 +92,20 @@ predicate callArgValueNumber(CallInstruction call, int index, TValueNumber arg) predicate callArgRank(CallInstruction call, int index, Instruction arg) { arg = rank[index](int argIndex, boolean isEffect, Instruction instr | + exists(CallSideEffectInstruction cse | + cse.getPrimaryInstruction() = call and + cse.getSideEffectOperand().getAnyDef() = instr and + argIndex = -2 and + isEffect = false + ) + or + exists(CallReadSideEffectInstruction cse | + cse.getPrimaryInstruction() = call and + cse.getSideEffectOperand().getAnyDef() = instr and + argIndex = -2 and + isEffect = false + ) + or instr = call.getThisArgument() and argIndex = -1 and isEffect = false From 4ae218729a7bf3ac4ec50915b969f6256607f8e7 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Mon, 25 Jul 2022 15:21:39 -0400 Subject: [PATCH 04/19] C++/C#: Sync identical files --- .../cpp/ir/implementation/raw/Instruction.qll | 18 ++++ .../gvn/internal/ValueNumberingInternal.qll | 88 +++++++++++++++++++ .../unaliased_ssa/Instruction.qll | 18 ++++ .../gvn/internal/ValueNumberingInternal.qll | 88 +++++++++++++++++++ .../ir/implementation/raw/Instruction.qll | 18 ++++ .../gvn/internal/ValueNumberingInternal.qll | 88 +++++++++++++++++++ .../unaliased_ssa/Instruction.qll | 18 ++++ .../gvn/internal/ValueNumberingInternal.qll | 88 +++++++++++++++++++ 8 files changed, 424 insertions(+) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll index 8e863ddf6352..3679b9e9bce4 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll @@ -1712,6 +1712,15 @@ class SideEffectInstruction extends Instruction { */ class CallSideEffectInstruction extends SideEffectInstruction { CallSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallSideEffect } + + /** Gets the operand for the value that will be read by this instruction */ + final SideEffectOperand getSideEffectOperand() { + result = this.getAnOperand() + } + + final Instruction getSideEffect() { + result = this.getAnOperand().getDef() + } } /** @@ -1723,6 +1732,15 @@ class CallSideEffectInstruction extends SideEffectInstruction { */ class CallReadSideEffectInstruction extends SideEffectInstruction { CallReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallReadSideEffect } + + /** Gets the operand for the value that will be read by this instruction */ + final SideEffectOperand getSideEffectOperand() { + result = this.getAnOperand() + } + + final Instruction getSideEffect() { + result = this.getAnOperand().getDef() + } } /** diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll index 2dc735f49dfb..02de941eea57 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll @@ -41,8 +41,89 @@ 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 | + exists(CallSideEffectInstruction cse | + cse.getPrimaryInstruction() = call and + cse.getSideEffectOperand().getAnyDef() = instr and + argIndex = -2 and + isEffect = false + ) + or + exists(CallReadSideEffectInstruction cse | + cse.getPrimaryInstruction() = call and + cse.getSideEffectOperand().getAnyDef() = instr and + argIndex = -2 and + isEffect = false + ) + or + 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 +174,8 @@ private predicate numberableInstruction(Instruction instr) { instr instanceof CongruentCopyInstruction or instr instanceof LoadTotalOverlapInstruction + or + instr instanceof CallInstruction } private predicate filteredNumberableInstruction(Instruction instr) { @@ -309,6 +392,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/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll index 8e863ddf6352..3679b9e9bce4 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll @@ -1712,6 +1712,15 @@ class SideEffectInstruction extends Instruction { */ class CallSideEffectInstruction extends SideEffectInstruction { CallSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallSideEffect } + + /** Gets the operand for the value that will be read by this instruction */ + final SideEffectOperand getSideEffectOperand() { + result = this.getAnOperand() + } + + final Instruction getSideEffect() { + result = this.getAnOperand().getDef() + } } /** @@ -1723,6 +1732,15 @@ class CallSideEffectInstruction extends SideEffectInstruction { */ class CallReadSideEffectInstruction extends SideEffectInstruction { CallReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallReadSideEffect } + + /** Gets the operand for the value that will be read by this instruction */ + final SideEffectOperand getSideEffectOperand() { + result = this.getAnOperand() + } + + final Instruction getSideEffect() { + result = this.getAnOperand().getDef() + } } /** diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll index 2dc735f49dfb..02de941eea57 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll @@ -41,8 +41,89 @@ 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 | + exists(CallSideEffectInstruction cse | + cse.getPrimaryInstruction() = call and + cse.getSideEffectOperand().getAnyDef() = instr and + argIndex = -2 and + isEffect = false + ) + or + exists(CallReadSideEffectInstruction cse | + cse.getPrimaryInstruction() = call and + cse.getSideEffectOperand().getAnyDef() = instr and + argIndex = -2 and + isEffect = false + ) + or + 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 +174,8 @@ private predicate numberableInstruction(Instruction instr) { instr instanceof CongruentCopyInstruction or instr instanceof LoadTotalOverlapInstruction + or + instr instanceof CallInstruction } private predicate filteredNumberableInstruction(Instruction instr) { @@ -309,6 +392,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/csharp/ql/src/experimental/ir/implementation/raw/Instruction.qll b/csharp/ql/src/experimental/ir/implementation/raw/Instruction.qll index 8e863ddf6352..3679b9e9bce4 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/Instruction.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/Instruction.qll @@ -1712,6 +1712,15 @@ class SideEffectInstruction extends Instruction { */ class CallSideEffectInstruction extends SideEffectInstruction { CallSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallSideEffect } + + /** Gets the operand for the value that will be read by this instruction */ + final SideEffectOperand getSideEffectOperand() { + result = this.getAnOperand() + } + + final Instruction getSideEffect() { + result = this.getAnOperand().getDef() + } } /** @@ -1723,6 +1732,15 @@ class CallSideEffectInstruction extends SideEffectInstruction { */ class CallReadSideEffectInstruction extends SideEffectInstruction { CallReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallReadSideEffect } + + /** Gets the operand for the value that will be read by this instruction */ + final SideEffectOperand getSideEffectOperand() { + result = this.getAnOperand() + } + + final Instruction getSideEffect() { + result = this.getAnOperand().getDef() + } } /** diff --git a/csharp/ql/src/experimental/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll b/csharp/ql/src/experimental/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll index 2dc735f49dfb..02de941eea57 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll @@ -41,8 +41,89 @@ 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 | + exists(CallSideEffectInstruction cse | + cse.getPrimaryInstruction() = call and + cse.getSideEffectOperand().getAnyDef() = instr and + argIndex = -2 and + isEffect = false + ) + or + exists(CallReadSideEffectInstruction cse | + cse.getPrimaryInstruction() = call and + cse.getSideEffectOperand().getAnyDef() = instr and + argIndex = -2 and + isEffect = false + ) + or + 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 +174,8 @@ private predicate numberableInstruction(Instruction instr) { instr instanceof CongruentCopyInstruction or instr instanceof LoadTotalOverlapInstruction + or + instr instanceof CallInstruction } private predicate filteredNumberableInstruction(Instruction instr) { @@ -309,6 +392,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/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Instruction.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Instruction.qll index 8e863ddf6352..3679b9e9bce4 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Instruction.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Instruction.qll @@ -1712,6 +1712,15 @@ class SideEffectInstruction extends Instruction { */ class CallSideEffectInstruction extends SideEffectInstruction { CallSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallSideEffect } + + /** Gets the operand for the value that will be read by this instruction */ + final SideEffectOperand getSideEffectOperand() { + result = this.getAnOperand() + } + + final Instruction getSideEffect() { + result = this.getAnOperand().getDef() + } } /** @@ -1723,6 +1732,15 @@ class CallSideEffectInstruction extends SideEffectInstruction { */ class CallReadSideEffectInstruction extends SideEffectInstruction { CallReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallReadSideEffect } + + /** Gets the operand for the value that will be read by this instruction */ + final SideEffectOperand getSideEffectOperand() { + result = this.getAnOperand() + } + + final Instruction getSideEffect() { + result = this.getAnOperand().getDef() + } } /** diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll index 2dc735f49dfb..02de941eea57 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll @@ -41,8 +41,89 @@ 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 | + exists(CallSideEffectInstruction cse | + cse.getPrimaryInstruction() = call and + cse.getSideEffectOperand().getAnyDef() = instr and + argIndex = -2 and + isEffect = false + ) + or + exists(CallReadSideEffectInstruction cse | + cse.getPrimaryInstruction() = call and + cse.getSideEffectOperand().getAnyDef() = instr and + argIndex = -2 and + isEffect = false + ) + or + 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 +174,8 @@ private predicate numberableInstruction(Instruction instr) { instr instanceof CongruentCopyInstruction or instr instanceof LoadTotalOverlapInstruction + or + instr instanceof CallInstruction } private predicate filteredNumberableInstruction(Instruction instr) { @@ -309,6 +392,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) + ) ) ) } From d324969d685ef4110d6076dc11c06eaedfe50c19 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Fri, 29 Jul 2022 10:38:13 -0400 Subject: [PATCH 05/19] C++: remove some side-effect instructions This leverages the existing alias analysis to identify functions which have no reads or writes of the AllAliasedMemory virtual variable, and therefore have no global side effects. A recursion over the call graph identifies functions which have no indirect global side effects, and calls to those functions have their global side effect instructions removed. --- .../aliased_ssa/internal/SSAConstruction.qll | 18 +- .../implementation/internal/TInstruction.qll | 1 + .../internal/TInstructionInternal.qll | 1 + .../ir/ir/operand_locations.expected | 657 +++++++----------- .../ir/ssa/aliased_ssa_ir.expected | 78 +-- .../ir/ssa/aliased_ssa_ir_unsound.expected | 78 +-- 6 files changed, 325 insertions(+), 508 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll index 303a96830114..d5e2c1595ac4 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll @@ -11,8 +11,11 @@ private import NewIR private class OldBlock = Reachability::ReachableBlock; -private class OldInstruction = Reachability::ReachableInstruction; +private class OldInstruction extends Reachability::ReachableInstruction { + OldInstruction() { not Elim::removeableSideEffect(this)} +} +private import SideEffectElimination as Elim import Cached cached @@ -58,7 +61,9 @@ private module Cached { cached predicate hasInstruction(TStageInstruction instr) { - instr instanceof TRawInstruction and instr instanceof OldInstruction + instr instanceof TRawInstruction and + instr instanceof OldInstruction and + not Elim::removeableSideEffect(instr) or instr = phiInstruction(_, _) or @@ -382,7 +387,14 @@ private module Cached { ( if Reachability::isInfeasibleInstructionSuccessor(oldInstruction, kind) then result = unreachedInstruction(instruction.getEnclosingIRFunction()) - else result = getNewInstruction(oldInstruction.getSuccessor(kind)) + else + if Elim::removeableSideEffect(oldInstruction.getSuccessor(kind)) + then + // the only removed nodes are side-effect writes, but those may have Chi nodes + // skip to the following instruction in the old IR, which won't be removed + // if we start skipping specific side effects, this may no longer hold + result = getNewInstruction(oldInstruction.getSuccessor(kind).getSuccessor(kind)) + else result = getNewInstruction(oldInstruction.getSuccessor(kind)) ) ) or diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/TInstruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/TInstruction.qll index 5a7099d9fa2e..b41b4818bdb6 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/TInstruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/TInstruction.qll @@ -34,6 +34,7 @@ newtype TInstruction = AliasedSSA::SSA::hasPhiInstruction(blockStartInstr, memoryLocation) } or TAliasedSsaChiInstruction(TRawInstruction primaryInstruction) { + not Elim::removeableSideEffect(primaryInstruction) and AliasedSSA::SSA::hasChiInstruction(primaryInstruction) } or TAliasedSsaUnreachedInstruction(IRFunctionBase irFunc) { diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/TInstructionInternal.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/TInstructionInternal.qll index 2c9ac1c4b80f..be5a401c07ba 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/TInstructionInternal.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/TInstructionInternal.qll @@ -2,3 +2,4 @@ import semmle.code.cpp.ir.internal.IRCppLanguage as Language import semmle.code.cpp.ir.implementation.raw.internal.IRConstruction as IRConstruction import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.SSAConstruction as UnaliasedSsa import semmle.code.cpp.ir.implementation.aliased_ssa.internal.SSAConstruction as AliasedSSA +import semmle.code.cpp.ir.implementation.aliased_ssa.internal.SideEffectElimination as Elim diff --git a/cpp/ql/test/library-tests/ir/ir/operand_locations.expected b/cpp/ql/test/library-tests/ir/ir/operand_locations.expected index 3510d24b7c75..449908bf1c49 100644 --- a/cpp/ql/test/library-tests/ir/ir/operand_locations.expected +++ b/cpp/ql/test/library-tests/ir/ir/operand_locations.expected @@ -25,7 +25,7 @@ | bad_asts.cpp:10:22:10:22 | Right | r10_9 | | bad_asts.cpp:14:8:14:28 | ChiPartial | partial:m14_3 | | bad_asts.cpp:14:8:14:28 | ChiTotal | total:m14_2 | -| bad_asts.cpp:14:8:14:28 | SideEffect | ~m16_6 | +| bad_asts.cpp:14:8:14:28 | SideEffect | m14_3 | | bad_asts.cpp:15:7:15:7 | Address | &:r15_1 | | bad_asts.cpp:15:7:15:7 | Unary | r15_1 | | bad_asts.cpp:15:10:15:12 | Address | &:r15_3 | @@ -33,13 +33,10 @@ | bad_asts.cpp:16:5:16:5 | Address | &:r16_1 | | bad_asts.cpp:16:5:16:5 | Address | &:r16_1 | | bad_asts.cpp:16:5:16:5 | Arg(this) | this:r16_1 | -| bad_asts.cpp:16:5:16:5 | ChiPartial | partial:m16_8 | +| bad_asts.cpp:16:5:16:5 | ChiPartial | partial:m16_6 | | bad_asts.cpp:16:5:16:5 | ChiTotal | total:m15_5 | | bad_asts.cpp:16:5:16:5 | SideEffect | ~m15_5 | | bad_asts.cpp:16:7:16:23 | CallTarget | func:r16_2 | -| bad_asts.cpp:16:7:16:23 | ChiPartial | partial:m16_5 | -| bad_asts.cpp:16:7:16:23 | ChiTotal | total:m14_4 | -| bad_asts.cpp:16:7:16:23 | SideEffect | ~m14_4 | | bad_asts.cpp:16:25:16:25 | Arg(0) | 0:r16_3 | | bad_asts.cpp:19:10:19:10 | Address | &:r19_5 | | bad_asts.cpp:19:10:19:10 | Address | &:r19_5 | @@ -761,7 +758,7 @@ | file://:0:0:0:0 | Load | m763_6 | | file://:0:0:0:0 | Load | m1466_4 | | file://:0:0:0:0 | Load | m1466_4 | -| file://:0:0:0:0 | Load | m1685_9 | +| file://:0:0:0:0 | Load | m1685_7 | | file://:0:0:0:0 | Load | m1714_7 | | file://:0:0:0:0 | Load | ~m1444_6 | | file://:0:0:0:0 | Load | ~m1712_10 | @@ -2958,24 +2955,21 @@ | ir.cpp:652:10:652:20 | ChiPartial | partial:m652_3 | | ir.cpp:652:10:652:20 | ChiTotal | total:m652_2 | | ir.cpp:652:10:652:20 | Load | m652_6 | -| ir.cpp:652:10:652:20 | SideEffect | m655_10 | -| ir.cpp:652:10:652:20 | SideEffect | ~m655_7 | +| ir.cpp:652:10:652:20 | SideEffect | m652_3 | +| ir.cpp:652:10:652:20 | SideEffect | m655_8 | | ir.cpp:653:9:653:12 | Address | &:r653_1 | | ir.cpp:653:9:653:12 | Address | &:r653_2 | | ir.cpp:653:9:653:12 | Address | &:r653_2 | | ir.cpp:653:9:653:12 | Arg(this) | this:r653_2 | -| ir.cpp:653:9:653:12 | ChiPartial | partial:m653_9 | +| ir.cpp:653:9:653:12 | ChiPartial | partial:m653_7 | | ir.cpp:653:9:653:12 | ChiTotal | total:m652_8 | | ir.cpp:653:9:653:12 | Load | m652_6 | | ir.cpp:653:9:653:12 | SideEffect | ~m652_8 | | ir.cpp:653:15:653:36 | CallTarget | func:r653_3 | -| ir.cpp:653:15:653:36 | ChiPartial | partial:m653_6 | -| ir.cpp:653:15:653:36 | ChiTotal | total:m652_4 | -| ir.cpp:653:15:653:36 | SideEffect | ~m652_4 | | ir.cpp:653:38:653:38 | Arg(0) | 0:r653_4 | -| ir.cpp:654:9:654:15 | ChiPartial | partial:m654_10 | -| ir.cpp:654:9:654:15 | ChiTotal | total:m653_10 | -| ir.cpp:654:9:654:15 | SideEffect | ~m653_10 | +| ir.cpp:654:9:654:15 | ChiPartial | partial:m654_8 | +| ir.cpp:654:9:654:15 | ChiTotal | total:m653_8 | +| ir.cpp:654:9:654:15 | SideEffect | ~m653_8 | | ir.cpp:654:10:654:14 | Address | &:r654_3 | | ir.cpp:654:10:654:14 | Address | &:r654_3 | | ir.cpp:654:10:654:14 | Arg(this) | this:r654_3 | @@ -2983,22 +2977,16 @@ | ir.cpp:654:11:654:14 | Load | m652_6 | | ir.cpp:654:11:654:14 | Unary | r654_2 | | ir.cpp:654:17:654:38 | CallTarget | func:r654_4 | -| ir.cpp:654:17:654:38 | ChiPartial | partial:m654_7 | -| ir.cpp:654:17:654:38 | ChiTotal | total:m653_7 | -| ir.cpp:654:17:654:38 | SideEffect | ~m653_7 | | ir.cpp:654:40:654:40 | Arg(0) | 0:r654_5 | | ir.cpp:655:9:655:30 | Address | &:r655_1 | | ir.cpp:655:9:655:30 | Address | &:r655_2 | | ir.cpp:655:9:655:30 | Address | &:r655_2 | | ir.cpp:655:9:655:30 | Arg(this) | this:r655_2 | | ir.cpp:655:9:655:30 | CallTarget | func:r655_3 | -| ir.cpp:655:9:655:30 | ChiPartial | partial:m655_6 | -| ir.cpp:655:9:655:30 | ChiPartial | partial:m655_9 | -| ir.cpp:655:9:655:30 | ChiTotal | total:m654_8 | -| ir.cpp:655:9:655:30 | ChiTotal | total:m654_11 | +| ir.cpp:655:9:655:30 | ChiPartial | partial:m655_7 | +| ir.cpp:655:9:655:30 | ChiTotal | total:m654_9 | | ir.cpp:655:9:655:30 | Load | m652_6 | -| ir.cpp:655:9:655:30 | SideEffect | ~m654_8 | -| ir.cpp:655:9:655:30 | SideEffect | ~m654_11 | +| ir.cpp:655:9:655:30 | SideEffect | ~m654_9 | | ir.cpp:655:32:655:32 | Arg(0) | 0:r655_4 | | ir.cpp:658:5:658:5 | Address | &:r658_5 | | ir.cpp:658:5:658:5 | Address | &:r658_5 | @@ -3160,15 +3148,12 @@ | ir.cpp:708:5:708:11 | Address | &:r708_9 | | ir.cpp:708:5:708:11 | ChiPartial | partial:m708_3 | | ir.cpp:708:5:708:11 | ChiTotal | total:m708_2 | -| ir.cpp:708:5:708:11 | Load | m709_10 | -| ir.cpp:708:5:708:11 | SideEffect | ~m709_9 | +| ir.cpp:708:5:708:11 | Load | m709_8 | +| ir.cpp:708:5:708:11 | SideEffect | m708_3 | | ir.cpp:708:17:708:17 | Address | &:r708_5 | | ir.cpp:708:24:708:24 | Address | &:r708_7 | | ir.cpp:709:3:709:19 | Address | &:r709_1 | | ir.cpp:709:10:709:12 | CallTarget | func:r709_2 | -| ir.cpp:709:10:709:12 | ChiPartial | partial:m709_8 | -| ir.cpp:709:10:709:12 | ChiTotal | total:m708_4 | -| ir.cpp:709:10:709:12 | SideEffect | ~m708_4 | | ir.cpp:709:10:709:12 | StoreValue | r709_7 | | ir.cpp:709:14:709:14 | Address | &:r709_3 | | ir.cpp:709:14:709:14 | Arg(0) | 0:r709_4 | @@ -3197,21 +3182,18 @@ | ir.cpp:720:8:720:29 | Address | &:r720_5 | | ir.cpp:720:8:720:29 | ChiPartial | partial:m720_3 | | ir.cpp:720:8:720:29 | ChiTotal | total:m720_2 | -| ir.cpp:720:8:720:29 | Load | m721_12 | -| ir.cpp:720:8:720:29 | SideEffect | ~m721_10 | +| ir.cpp:720:8:720:29 | Load | m721_10 | +| ir.cpp:720:8:720:29 | SideEffect | ~m721_8 | | ir.cpp:721:3:721:54 | Address | &:r721_1 | | ir.cpp:721:10:721:39 | CallTarget | func:r721_2 | -| ir.cpp:721:10:721:39 | ChiPartial | partial:m721_6 | -| ir.cpp:721:10:721:39 | ChiTotal | total:m720_4 | -| ir.cpp:721:10:721:39 | SideEffect | ~m720_4 | | ir.cpp:721:10:721:39 | Unary | r721_5 | -| ir.cpp:721:10:721:53 | StoreValue | r721_11 | +| ir.cpp:721:10:721:53 | StoreValue | r721_9 | | ir.cpp:721:41:721:47 | Address | &:r721_3 | | ir.cpp:721:41:721:47 | Address | &:r721_3 | | ir.cpp:721:41:721:47 | Arg(0) | 0:r721_3 | -| ir.cpp:721:41:721:47 | ChiPartial | partial:m721_9 | -| ir.cpp:721:41:721:47 | ChiTotal | total:m721_7 | -| ir.cpp:721:41:721:47 | SideEffect | ~m721_7 | +| ir.cpp:721:41:721:47 | ChiPartial | partial:m721_7 | +| ir.cpp:721:41:721:47 | ChiTotal | total:m720_4 | +| ir.cpp:721:41:721:47 | SideEffect | ~m720_4 | | ir.cpp:721:50:721:52 | Arg(1) | 1:r721_4 | | ir.cpp:724:6:724:13 | ChiPartial | partial:m724_3 | | ir.cpp:724:6:724:13 | ChiTotal | total:m724_2 | @@ -4080,43 +4062,34 @@ | ir.cpp:846:8:846:8 | ChiPartial | partial:m846_3 | | ir.cpp:846:8:846:8 | ChiPartial | partial:m846_12 | | ir.cpp:846:8:846:8 | ChiPartial | partial:m846_12 | -| ir.cpp:846:8:846:8 | ChiPartial | partial:m846_14 | | ir.cpp:846:8:846:8 | ChiTotal | total:m846_2 | | ir.cpp:846:8:846:8 | ChiTotal | total:m846_2 | | ir.cpp:846:8:846:8 | ChiTotal | total:m846_4 | -| ir.cpp:846:8:846:8 | ChiTotal | total:m846_4 | | ir.cpp:846:8:846:8 | ChiTotal | total:m846_8 | | ir.cpp:846:8:846:8 | Load | m846_6 | | ir.cpp:846:8:846:8 | Load | m846_6 | +| ir.cpp:846:8:846:8 | SideEffect | m846_3 | | ir.cpp:846:8:846:8 | SideEffect | m846_8 | -| ir.cpp:846:8:846:8 | SideEffect | m846_15 | -| ir.cpp:846:8:846:8 | SideEffect | ~m846_4 | +| ir.cpp:846:8:846:8 | SideEffect | m846_13 | | ir.cpp:846:8:846:8 | SideEffect | ~m846_4 | | ir.cpp:846:8:846:8 | SideEffect | ~m846_13 | -| ir.cpp:846:8:846:8 | SideEffect | ~m846_13 | | ir.cpp:846:8:846:8 | Unary | m846_6 | | ir.cpp:846:8:846:8 | Unary | m846_6 | | ir.cpp:849:6:849:16 | ChiPartial | partial:m849_3 | | ir.cpp:849:6:849:16 | ChiTotal | total:m849_2 | -| ir.cpp:849:6:849:16 | SideEffect | ~m851_6 | +| ir.cpp:849:6:849:16 | SideEffect | m849_3 | | ir.cpp:850:19:850:19 | Address | &:r850_1 | | ir.cpp:850:19:850:19 | Address | &:r850_1 | | ir.cpp:850:19:850:19 | Arg(this) | this:r850_1 | | ir.cpp:850:19:850:19 | CallTarget | func:r850_3 | | ir.cpp:850:19:850:19 | ChiPartial | partial:m850_5 | -| ir.cpp:850:19:850:19 | ChiPartial | partial:m850_7 | -| ir.cpp:850:19:850:19 | ChiTotal | total:m849_4 | | ir.cpp:850:19:850:19 | ChiTotal | total:m850_2 | -| ir.cpp:850:19:850:19 | SideEffect | ~m849_4 | | ir.cpp:851:22:851:22 | Address | &:r851_1 | | ir.cpp:851:22:851:22 | Address | &:r851_1 | | ir.cpp:851:22:851:22 | Arg(this) | this:r851_1 | | ir.cpp:851:22:851:22 | CallTarget | func:r851_3 | | ir.cpp:851:22:851:22 | ChiPartial | partial:m851_5 | -| ir.cpp:851:22:851:22 | ChiPartial | partial:m851_7 | -| ir.cpp:851:22:851:22 | ChiTotal | total:m850_6 | | ir.cpp:851:22:851:22 | ChiTotal | total:m851_2 | -| ir.cpp:851:22:851:22 | SideEffect | ~m850_6 | | ir.cpp:853:20:853:21 | Address | &:r853_1 | | ir.cpp:853:25:853:26 | StoreValue | r853_3 | | ir.cpp:853:26:853:26 | Unary | r853_2 | @@ -4284,7 +4257,7 @@ | ir.cpp:896:6:896:16 | ChiPartial | partial:m896_3 | | ir.cpp:896:6:896:16 | ChiTotal | total:m896_2 | | ir.cpp:896:6:896:16 | Load | m896_8 | -| ir.cpp:896:6:896:16 | SideEffect | ~m905_8 | +| ir.cpp:896:6:896:16 | SideEffect | m896_3 | | ir.cpp:896:22:896:22 | Address | &:r896_5 | | ir.cpp:897:21:897:24 | Address | &:r897_1 | | ir.cpp:899:3:899:29 | StoreValue | r899_2 | @@ -4324,16 +4297,13 @@ | ir.cpp:904:20:904:23 | Unary | r904_1 | | ir.cpp:904:20:904:23 | Unary | r904_2 | | ir.cpp:905:3:905:13 | CallTarget | func:r905_1 | -| ir.cpp:905:3:905:13 | ChiPartial | partial:m905_7 | -| ir.cpp:905:3:905:13 | ChiTotal | total:m896_4 | -| ir.cpp:905:3:905:13 | SideEffect | ~m896_4 | | ir.cpp:905:15:905:15 | Address | &:r905_2 | | ir.cpp:905:15:905:15 | Arg(0) | 0:r905_3 | | ir.cpp:905:15:905:15 | Load | m896_6 | | ir.cpp:905:18:905:22 | Address | &:r905_5 | | ir.cpp:905:18:905:22 | Address | &:r905_5 | | ir.cpp:905:18:905:22 | Arg(1) | 1:r905_5 | -| ir.cpp:905:18:905:22 | ChiPartial | partial:m905_10 | +| ir.cpp:905:18:905:22 | ChiPartial | partial:m905_8 | | ir.cpp:905:18:905:22 | ChiTotal | total:m901_6 | | ir.cpp:905:18:905:22 | SideEffect | ~m901_6 | | ir.cpp:905:18:905:22 | Unary | r905_4 | @@ -5882,7 +5852,7 @@ | ir.cpp:1270:51:1270:55 | Address | &:r1270_9 | | ir.cpp:1270:51:1270:55 | Address | &:r1270_9 | | ir.cpp:1270:51:1270:55 | Load | m1270_8 | -| ir.cpp:1270:51:1270:55 | SideEffect | m1281_12 | +| ir.cpp:1270:51:1270:55 | SideEffect | m1281_10 | | ir.cpp:1271:7:1271:7 | Address | &:r1271_1 | | ir.cpp:1271:7:1271:7 | Address | &:r1271_1 | | ir.cpp:1271:7:1271:7 | Arg(this) | this:r1271_1 | @@ -5893,24 +5863,15 @@ | ir.cpp:1271:7:1271:7 | ChiTotal | total:m1271_2 | | ir.cpp:1271:7:1271:7 | SideEffect | ~m1270_4 | | ir.cpp:1272:7:1272:26 | CallTarget | func:r1272_2 | -| ir.cpp:1272:7:1272:26 | ChiPartial | partial:m1272_5 | -| ir.cpp:1272:7:1272:26 | ChiTotal | total:m1271_6 | -| ir.cpp:1272:7:1272:26 | SideEffect | ~m1271_6 | | ir.cpp:1272:28:1272:29 | Arg(0) | 0:r1272_3 | | ir.cpp:1273:5:1273:27 | CallTarget | func:r1273_1 | -| ir.cpp:1273:5:1273:27 | ChiPartial | partial:m1273_4 | -| ir.cpp:1273:5:1273:27 | ChiTotal | total:m1272_6 | -| ir.cpp:1273:5:1273:27 | SideEffect | ~m1272_6 | | ir.cpp:1273:29:1273:30 | Arg(0) | 0:r1273_2 | | ir.cpp:1275:7:1275:7 | Address | &:r1275_1 | | ir.cpp:1276:7:1276:19 | CallTarget | func:r1276_2 | -| ir.cpp:1276:7:1276:19 | ChiPartial | partial:m1276_8 | -| ir.cpp:1276:7:1276:19 | ChiTotal | total:m1273_5 | -| ir.cpp:1276:7:1276:19 | SideEffect | ~m1273_5 | | ir.cpp:1276:21:1276:22 | Address | &:r1276_4 | | ir.cpp:1276:21:1276:22 | Address | &:r1276_4 | | ir.cpp:1276:21:1276:22 | Arg(0) | 0:r1276_4 | -| ir.cpp:1276:21:1276:22 | ChiPartial | partial:m1276_11 | +| ir.cpp:1276:21:1276:22 | ChiPartial | partial:m1276_9 | | ir.cpp:1276:21:1276:22 | ChiTotal | total:m1275_2 | | ir.cpp:1276:21:1276:22 | SideEffect | ~m1275_2 | | ir.cpp:1276:22:1276:22 | Unary | r1276_3 | @@ -5918,29 +5879,23 @@ | ir.cpp:1276:25:1276:31 | Arg(1) | 1:r1276_6 | | ir.cpp:1276:25:1276:31 | Load | m1270_6 | | ir.cpp:1277:5:1277:20 | CallTarget | func:r1277_1 | -| ir.cpp:1277:5:1277:20 | ChiPartial | partial:m1277_7 | -| ir.cpp:1277:5:1277:20 | ChiTotal | total:m1276_9 | -| ir.cpp:1277:5:1277:20 | SideEffect | ~m1276_9 | | ir.cpp:1277:22:1277:23 | Address | &:r1277_3 | | ir.cpp:1277:22:1277:23 | Address | &:r1277_3 | | ir.cpp:1277:22:1277:23 | Arg(0) | 0:r1277_3 | -| ir.cpp:1277:22:1277:23 | ChiPartial | partial:m1277_10 | -| ir.cpp:1277:22:1277:23 | ChiTotal | total:m1276_12 | -| ir.cpp:1277:22:1277:23 | SideEffect | ~m1276_12 | +| ir.cpp:1277:22:1277:23 | ChiPartial | partial:m1277_8 | +| ir.cpp:1277:22:1277:23 | ChiTotal | total:m1276_10 | +| ir.cpp:1277:22:1277:23 | SideEffect | ~m1276_10 | | ir.cpp:1277:23:1277:23 | Unary | r1277_2 | | ir.cpp:1277:26:1277:32 | Address | &:r1277_4 | | ir.cpp:1277:26:1277:32 | Arg(1) | 1:r1277_5 | | ir.cpp:1277:26:1277:32 | Load | m1270_6 | | ir.cpp:1279:7:1279:7 | Unary | r1279_1 | | ir.cpp:1279:11:1279:23 | CallTarget | func:r1279_3 | -| ir.cpp:1279:11:1279:23 | ChiPartial | partial:m1279_11 | -| ir.cpp:1279:11:1279:23 | ChiTotal | total:m1277_8 | -| ir.cpp:1279:11:1279:23 | SideEffect | ~m1277_8 | | ir.cpp:1279:25:1279:29 | Address | &:r1279_4 | | ir.cpp:1279:25:1279:29 | Address | &:r1279_5 | | ir.cpp:1279:25:1279:29 | Address | &:r1279_5 | | ir.cpp:1279:25:1279:29 | Arg(0) | 0:r1279_5 | -| ir.cpp:1279:25:1279:29 | ChiPartial | partial:m1279_14 | +| ir.cpp:1279:25:1279:29 | ChiPartial | partial:m1279_12 | | ir.cpp:1279:25:1279:29 | ChiTotal | total:m1270_10 | | ir.cpp:1279:25:1279:29 | Load | m1270_8 | | ir.cpp:1279:25:1279:29 | SideEffect | ~m1270_10 | @@ -5953,36 +5908,30 @@ | ir.cpp:1280:7:1280:11 | Load | m1270_8 | | ir.cpp:1280:7:1280:11 | Unary | r1280_2 | | ir.cpp:1280:14:1280:26 | CallTarget | func:r1280_4 | -| ir.cpp:1280:14:1280:26 | ChiPartial | partial:m1280_9 | -| ir.cpp:1280:14:1280:26 | ChiTotal | total:m1279_12 | -| ir.cpp:1280:14:1280:26 | SideEffect | ~m1279_12 | | ir.cpp:1280:28:1280:29 | Address | &:r1280_6 | | ir.cpp:1280:28:1280:29 | Address | &:r1280_6 | | ir.cpp:1280:28:1280:29 | Arg(0) | 0:r1280_6 | -| ir.cpp:1280:28:1280:29 | ChiPartial | partial:m1280_12 | -| ir.cpp:1280:28:1280:29 | ChiTotal | total:m1277_11 | -| ir.cpp:1280:28:1280:29 | SideEffect | ~m1277_11 | +| ir.cpp:1280:28:1280:29 | ChiPartial | partial:m1280_10 | +| ir.cpp:1280:28:1280:29 | ChiTotal | total:m1277_9 | +| ir.cpp:1280:28:1280:29 | SideEffect | ~m1277_9 | | ir.cpp:1280:29:1280:29 | Unary | r1280_5 | | ir.cpp:1280:32:1280:33 | Arg(1) | 1:r1280_7 | | ir.cpp:1281:5:1281:9 | Address | &:r1281_1 | | ir.cpp:1281:5:1281:9 | Load | m1270_8 | | ir.cpp:1281:12:1281:24 | CallTarget | func:r1281_3 | -| ir.cpp:1281:12:1281:24 | ChiPartial | partial:m1281_8 | -| ir.cpp:1281:12:1281:24 | ChiTotal | total:m1280_10 | -| ir.cpp:1281:12:1281:24 | SideEffect | ~m1280_10 | | ir.cpp:1281:26:1281:30 | Address | &:r1281_4 | | ir.cpp:1281:26:1281:30 | Address | &:r1281_5 | | ir.cpp:1281:26:1281:30 | Address | &:r1281_5 | | ir.cpp:1281:26:1281:30 | Arg(0) | 0:r1281_5 | -| ir.cpp:1281:26:1281:30 | ChiPartial | partial:m1281_11 | -| ir.cpp:1281:26:1281:30 | ChiTotal | total:m1279_15 | +| ir.cpp:1281:26:1281:30 | ChiPartial | partial:m1281_9 | +| ir.cpp:1281:26:1281:30 | ChiTotal | total:m1279_13 | | ir.cpp:1281:26:1281:30 | Load | m1270_8 | -| ir.cpp:1281:26:1281:30 | SideEffect | ~m1279_15 | +| ir.cpp:1281:26:1281:30 | SideEffect | ~m1279_13 | | ir.cpp:1281:33:1281:34 | Arg(1) | 1:r1281_6 | | ir.cpp:1283:7:1283:31 | CallTarget | func:r1283_2 | | ir.cpp:1283:7:1283:31 | ChiPartial | partial:m1283_4 | -| ir.cpp:1283:7:1283:31 | ChiTotal | total:m1281_9 | -| ir.cpp:1283:7:1283:31 | SideEffect | ~m1281_9 | +| ir.cpp:1283:7:1283:31 | ChiTotal | total:m1271_6 | +| ir.cpp:1283:7:1283:31 | SideEffect | ~m1271_6 | | ir.cpp:1284:5:1284:32 | CallTarget | func:r1284_1 | | ir.cpp:1284:5:1284:32 | ChiPartial | partial:m1284_3 | | ir.cpp:1284:5:1284:32 | ChiTotal | total:m1283_5 | @@ -6011,13 +5960,10 @@ | ir.cpp:1291:16:1291:16 | StoreValue | r1291_3 | | ir.cpp:1295:6:1295:15 | ChiPartial | partial:m1295_3 | | ir.cpp:1295:6:1295:15 | ChiTotal | total:m1295_2 | -| ir.cpp:1295:6:1295:15 | SideEffect | ~m1296_8 | +| ir.cpp:1295:6:1295:15 | SideEffect | m1295_3 | | ir.cpp:1295:21:1295:21 | Address | &:r1295_5 | | ir.cpp:1295:28:1295:28 | Address | &:r1295_7 | | ir.cpp:1296:12:1296:21 | CallTarget | func:r1296_1 | -| ir.cpp:1296:12:1296:21 | ChiPartial | partial:m1296_7 | -| ir.cpp:1296:12:1296:21 | ChiTotal | total:m1295_4 | -| ir.cpp:1296:12:1296:21 | SideEffect | ~m1295_4 | | ir.cpp:1296:23:1296:23 | Address | &:r1296_2 | | ir.cpp:1296:23:1296:23 | Arg(0) | 0:r1296_3 | | ir.cpp:1296:23:1296:23 | Load | m1295_6 | @@ -6399,7 +6345,7 @@ | ir.cpp:1376:5:1376:30 | Load | m1376_6 | | ir.cpp:1379:6:1379:30 | ChiPartial | partial:m1379_3 | | ir.cpp:1379:6:1379:30 | ChiTotal | total:m1379_2 | -| ir.cpp:1379:6:1379:30 | SideEffect | ~m1388_5 | +| ir.cpp:1379:6:1379:30 | SideEffect | ~m1386_10 | | ir.cpp:1380:21:1380:21 | Address | &:r1380_1 | | ir.cpp:1380:25:1380:52 | CallTarget | func:r1380_2 | | ir.cpp:1380:25:1380:52 | ChiPartial | partial:m1380_4 | @@ -6466,13 +6412,10 @@ | ir.cpp:1386:36:1386:41 | ChiTotal | total:m1386_5 | | ir.cpp:1386:36:1386:41 | SideEffect | ~m1386_5 | | ir.cpp:1388:5:1388:37 | CallTarget | func:r1388_2 | -| ir.cpp:1388:5:1388:37 | ChiPartial | partial:m1388_4 | -| ir.cpp:1388:5:1388:37 | ChiTotal | total:m1386_10 | -| ir.cpp:1388:5:1388:37 | SideEffect | ~m1386_10 | | ir.cpp:1388:5:1388:37 | StoreValue | r1388_3 | | ir.cpp:1388:5:1388:39 | Address | &:r1388_1 | | ir.cpp:1388:5:1388:39 | Address | &:r1388_1 | -| ir.cpp:1388:5:1388:39 | Load | m1388_6 | +| ir.cpp:1388:5:1388:39 | Load | m1388_4 | | ir.cpp:1391:6:1391:31 | ChiPartial | partial:m1391_3 | | ir.cpp:1391:6:1391:31 | ChiTotal | total:m1391_2 | | ir.cpp:1391:6:1391:31 | SideEffect | ~m1401_6 | @@ -6587,7 +6530,7 @@ | ir.cpp:1401:45:1401:45 | StoreValue | r1401_9 | | ir.cpp:1404:6:1404:20 | ChiPartial | partial:m1404_3 | | ir.cpp:1404:6:1404:20 | ChiTotal | total:m1404_2 | -| ir.cpp:1404:6:1404:20 | SideEffect | ~m1413_4 | +| ir.cpp:1404:6:1404:20 | SideEffect | ~m1411_5 | | ir.cpp:1405:11:1405:11 | Address | &:r1405_1 | | ir.cpp:1405:15:1405:32 | CallTarget | func:r1405_2 | | ir.cpp:1405:15:1405:32 | ChiPartial | partial:m1405_4 | @@ -6632,9 +6575,6 @@ | ir.cpp:1411:34:1411:34 | Load | ~m1411_7 | | ir.cpp:1411:34:1411:34 | StoreValue | r1411_9 | | ir.cpp:1413:5:1413:27 | CallTarget | func:r1413_1 | -| ir.cpp:1413:5:1413:27 | ChiPartial | partial:m1413_3 | -| ir.cpp:1413:5:1413:27 | ChiTotal | total:m1411_5 | -| ir.cpp:1413:5:1413:27 | SideEffect | ~m1411_5 | | ir.cpp:1421:6:1421:29 | ChiPartial | partial:m1421_3 | | ir.cpp:1421:6:1421:29 | ChiTotal | total:m1421_2 | | ir.cpp:1421:6:1421:29 | SideEffect | ~m1426_5 | @@ -6966,10 +6906,7 @@ | ir.cpp:1500:39:1500:39 | Arg(this) | this:r1500_1 | | ir.cpp:1500:39:1500:39 | CallTarget | func:r1500_3 | | ir.cpp:1500:39:1500:39 | ChiPartial | partial:m1500_5 | -| ir.cpp:1500:39:1500:39 | ChiPartial | partial:m1500_7 | -| ir.cpp:1500:39:1500:39 | ChiTotal | total:m1499_4 | | ir.cpp:1500:39:1500:39 | ChiTotal | total:m1500_2 | -| ir.cpp:1500:39:1500:39 | SideEffect | ~m1499_4 | | ir.cpp:1503:14:1503:14 | Address | &:r1503_1 | | ir.cpp:1503:15:1503:15 | Address | &:r1503_5 | | ir.cpp:1503:18:1503:18 | Address | &:r1503_9 | @@ -6980,7 +6917,7 @@ | ir.cpp:1503:34:1503:34 | Address | &:r1503_31 | | ir.cpp:1503:41:1503:41 | Address | &:r1503_37 | | ir.cpp:1503:46:1503:46 | Address | &:r1503_2 | -| ir.cpp:1503:46:1503:46 | Load | m1500_8 | +| ir.cpp:1503:46:1503:46 | Load | m1500_6 | | ir.cpp:1503:46:1503:46 | StoreValue | r1503_3 | | ir.cpp:1503:47:1503:47 | Address | &:r1503_19 | | ir.cpp:1503:47:1503:47 | Address | &:r1503_33 | @@ -7025,7 +6962,7 @@ | ir.cpp:1507:9:1507:9 | Address | &:r1507_3 | | ir.cpp:1507:9:1507:9 | Load | m1503_22 | | ir.cpp:1507:9:1507:13 | ChiPartial | partial:m1507_4 | -| ir.cpp:1507:9:1507:13 | ChiTotal | total:m1500_6 | +| ir.cpp:1507:9:1507:13 | ChiTotal | total:m1499_4 | | ir.cpp:1507:13:1507:13 | StoreValue | r1507_1 | | ir.cpp:1508:9:1508:10 | Address | &:r1508_5 | | ir.cpp:1508:9:1508:14 | ChiPartial | partial:m1508_6 | @@ -7054,7 +6991,7 @@ | ir.cpp:1511:17:1511:17 | StoreValue | r1511_4 | | ir.cpp:1515:14:1515:35 | Address | &:r1515_1 | | ir.cpp:1515:39:1515:39 | Address | &:r1515_2 | -| ir.cpp:1515:39:1515:39 | Load | m1500_8 | +| ir.cpp:1515:39:1515:39 | Load | m1500_6 | | ir.cpp:1515:39:1515:39 | StoreValue | r1515_3 | | ir.cpp:1516:15:1516:15 | Address | &:r1516_1 | | ir.cpp:1516:19:1516:40 | Unary | r1516_2 | @@ -7239,176 +7176,155 @@ | ir.cpp:1580:34:1580:34 | Arg(this) | this:r1580_1 | | ir.cpp:1580:34:1580:34 | CallTarget | func:r1580_3 | | ir.cpp:1580:34:1580:34 | ChiPartial | partial:m1580_5 | -| ir.cpp:1580:34:1580:34 | ChiPartial | partial:m1580_7 | -| ir.cpp:1580:34:1580:34 | ChiTotal | total:m1579_4 | | ir.cpp:1580:34:1580:34 | ChiTotal | total:m1580_2 | -| ir.cpp:1580:34:1580:34 | SideEffect | ~m1579_4 | | ir.cpp:1583:14:1583:14 | Address | &:r1583_1 | | ir.cpp:1583:14:1583:14 | Address | &:r1583_6 | | ir.cpp:1583:14:1583:14 | Address | &:r1583_6 | -| ir.cpp:1583:14:1583:14 | Address | &:r1583_18 | -| ir.cpp:1583:14:1583:14 | Address | &:r1583_18 | -| ir.cpp:1583:14:1583:14 | Address | &:r1583_30 | -| ir.cpp:1583:14:1583:14 | Address | &:r1583_30 | +| ir.cpp:1583:14:1583:14 | Address | &:r1583_16 | +| ir.cpp:1583:14:1583:14 | Address | &:r1583_16 | +| ir.cpp:1583:14:1583:14 | Address | &:r1583_26 | +| ir.cpp:1583:14:1583:14 | Address | &:r1583_26 | | ir.cpp:1583:14:1583:14 | Arg(this) | this:r1583_6 | -| ir.cpp:1583:14:1583:14 | Arg(this) | this:r1583_18 | -| ir.cpp:1583:14:1583:14 | Arg(this) | this:r1583_30 | +| ir.cpp:1583:14:1583:14 | Arg(this) | this:r1583_16 | +| ir.cpp:1583:14:1583:14 | Arg(this) | this:r1583_26 | | ir.cpp:1583:14:1583:14 | CallTarget | func:r1583_7 | -| ir.cpp:1583:14:1583:14 | CallTarget | func:r1583_19 | -| ir.cpp:1583:14:1583:14 | CallTarget | func:r1583_31 | -| ir.cpp:1583:14:1583:14 | ChiPartial | partial:m1583_9 | -| ir.cpp:1583:14:1583:14 | ChiPartial | partial:m1583_12 | -| ir.cpp:1583:14:1583:14 | ChiPartial | partial:m1583_21 | -| ir.cpp:1583:14:1583:14 | ChiPartial | partial:m1583_24 | -| ir.cpp:1583:14:1583:14 | ChiPartial | partial:m1583_33 | -| ir.cpp:1583:14:1583:14 | ChiPartial | partial:m1583_36 | -| ir.cpp:1583:14:1583:14 | ChiTotal | total:m1580_6 | +| ir.cpp:1583:14:1583:14 | CallTarget | func:r1583_17 | +| ir.cpp:1583:14:1583:14 | CallTarget | func:r1583_27 | +| ir.cpp:1583:14:1583:14 | ChiPartial | partial:m1583_10 | +| ir.cpp:1583:14:1583:14 | ChiPartial | partial:m1583_20 | +| ir.cpp:1583:14:1583:14 | ChiPartial | partial:m1583_30 | | ir.cpp:1583:14:1583:14 | ChiTotal | total:m1583_4 | -| ir.cpp:1583:14:1583:14 | ChiTotal | total:m1583_10 | -| ir.cpp:1583:14:1583:14 | ChiTotal | total:m1583_13 | -| ir.cpp:1583:14:1583:14 | ChiTotal | total:m1583_22 | -| ir.cpp:1583:14:1583:14 | ChiTotal | total:m1583_25 | +| ir.cpp:1583:14:1583:14 | ChiTotal | total:m1583_11 | +| ir.cpp:1583:14:1583:14 | ChiTotal | total:m1583_21 | | ir.cpp:1583:14:1583:14 | SideEffect | m1583_4 | -| ir.cpp:1583:14:1583:14 | SideEffect | m1583_13 | -| ir.cpp:1583:14:1583:14 | SideEffect | m1583_25 | -| ir.cpp:1583:14:1583:14 | SideEffect | ~m1580_6 | -| ir.cpp:1583:14:1583:14 | SideEffect | ~m1583_10 | -| ir.cpp:1583:14:1583:14 | SideEffect | ~m1583_22 | +| ir.cpp:1583:14:1583:14 | SideEffect | m1583_11 | +| ir.cpp:1583:14:1583:14 | SideEffect | m1583_21 | | ir.cpp:1583:14:1583:14 | Unary | r1583_8 | -| ir.cpp:1583:14:1583:14 | Unary | r1583_20 | -| ir.cpp:1583:14:1583:14 | Unary | r1583_32 | -| ir.cpp:1583:14:1583:27 | StoreValue | r1583_15 | -| ir.cpp:1583:14:1583:27 | StoreValue | r1583_27 | -| ir.cpp:1583:14:1583:27 | StoreValue | r1583_39 | -| ir.cpp:1583:14:1583:27 | Unary | r1583_14 | -| ir.cpp:1583:14:1583:27 | Unary | r1583_26 | -| ir.cpp:1583:14:1583:27 | Unary | r1583_38 | +| ir.cpp:1583:14:1583:14 | Unary | r1583_18 | +| ir.cpp:1583:14:1583:14 | Unary | r1583_28 | +| ir.cpp:1583:14:1583:27 | StoreValue | r1583_13 | +| ir.cpp:1583:14:1583:27 | StoreValue | r1583_23 | +| ir.cpp:1583:14:1583:27 | StoreValue | r1583_33 | +| ir.cpp:1583:14:1583:27 | Unary | r1583_12 | +| ir.cpp:1583:14:1583:27 | Unary | r1583_22 | +| ir.cpp:1583:14:1583:27 | Unary | r1583_32 | | ir.cpp:1583:15:1583:15 | Address | &:r1583_5 | -| ir.cpp:1583:18:1583:18 | Address | &:r1583_17 | -| ir.cpp:1583:21:1583:21 | Address | &:r1583_29 | +| ir.cpp:1583:18:1583:18 | Address | &:r1583_15 | +| ir.cpp:1583:21:1583:21 | Address | &:r1583_25 | | ir.cpp:1583:26:1583:26 | Address | &:r1583_2 | -| ir.cpp:1583:26:1583:26 | Load | m1580_8 | +| ir.cpp:1583:26:1583:26 | Load | m1580_6 | | ir.cpp:1583:26:1583:26 | StoreValue | r1583_3 | | ir.cpp:1584:9:1584:9 | Address | &:r1584_2 | | ir.cpp:1584:9:1584:9 | Address | &:r1584_4 | -| ir.cpp:1584:9:1584:9 | Load | m1583_28 | +| ir.cpp:1584:9:1584:9 | Load | m1583_24 | | ir.cpp:1584:9:1584:9 | Unary | r1584_3 | | ir.cpp:1584:9:1584:15 | ChiPartial | partial:m1584_5 | -| ir.cpp:1584:9:1584:15 | ChiTotal | total:m1583_37 | +| ir.cpp:1584:9:1584:15 | ChiTotal | total:m1583_31 | | ir.cpp:1584:13:1584:15 | StoreValue | r1584_1 | | ir.cpp:1585:17:1585:18 | Address | &:r1585_1 | | ir.cpp:1585:22:1585:22 | Address | &:r1585_2 | -| ir.cpp:1585:22:1585:22 | Load | m1583_28 | +| ir.cpp:1585:22:1585:22 | Load | m1583_24 | | ir.cpp:1585:22:1585:22 | StoreValue | r1585_5 | | ir.cpp:1585:22:1585:22 | Unary | r1585_3 | | ir.cpp:1585:22:1585:22 | Unary | r1585_4 | | ir.cpp:1586:13:1586:13 | Address | &:r1586_1 | | ir.cpp:1586:17:1586:17 | Address | &:r1586_2 | | ir.cpp:1586:17:1586:17 | Address | &:r1586_3 | -| ir.cpp:1586:17:1586:17 | Load | m1583_16 | -| ir.cpp:1586:17:1586:17 | Load | ~m1583_37 | +| ir.cpp:1586:17:1586:17 | Load | m1583_14 | +| ir.cpp:1586:17:1586:17 | Load | ~m1583_31 | | ir.cpp:1586:17:1586:17 | StoreValue | r1586_4 | | ir.cpp:1587:9:1587:9 | Address | &:r1587_2 | | ir.cpp:1587:9:1587:9 | Address | &:r1587_4 | -| ir.cpp:1587:9:1587:9 | Load | m1583_40 | +| ir.cpp:1587:9:1587:9 | Load | m1583_34 | | ir.cpp:1587:9:1587:9 | Unary | r1587_3 | | ir.cpp:1587:9:1587:13 | ChiPartial | partial:m1587_5 | -| ir.cpp:1587:9:1587:13 | ChiTotal | total:m1583_34 | +| ir.cpp:1587:9:1587:13 | ChiTotal | total:m1579_4 | | ir.cpp:1587:13:1587:13 | StoreValue | r1587_1 | | ir.cpp:1588:14:1588:15 | Address | &:r1588_1 | | ir.cpp:1588:19:1588:19 | Address | &:r1588_2 | -| ir.cpp:1588:19:1588:19 | Load | m1583_40 | +| ir.cpp:1588:19:1588:19 | Load | m1583_34 | | ir.cpp:1588:19:1588:19 | StoreValue | r1588_5 | | ir.cpp:1588:19:1588:19 | Unary | r1588_3 | | ir.cpp:1588:19:1588:19 | Unary | r1588_4 | | ir.cpp:1589:13:1589:13 | Address | &:r1589_1 | | ir.cpp:1589:17:1589:17 | Address | &:r1589_2 | | ir.cpp:1589:17:1589:17 | Address | &:r1589_3 | -| ir.cpp:1589:17:1589:17 | Load | m1583_40 | +| ir.cpp:1589:17:1589:17 | Load | m1583_34 | | ir.cpp:1589:17:1589:17 | Load | ~m1587_6 | | ir.cpp:1589:17:1589:17 | StoreValue | r1589_4 | | ir.cpp:1593:14:1593:35 | Address | &:r1593_1 | | ir.cpp:1593:39:1593:39 | Address | &:r1593_2 | -| ir.cpp:1593:39:1593:39 | Load | m1580_8 | +| ir.cpp:1593:39:1593:39 | Load | m1580_6 | | ir.cpp:1593:39:1593:39 | StoreValue | r1593_3 | | ir.cpp:1594:15:1594:15 | Address | &:r1594_1 | | ir.cpp:1594:19:1594:40 | Address | &:r1594_2 | | ir.cpp:1594:19:1594:40 | Address | &:r1594_2 | | ir.cpp:1594:19:1594:40 | Arg(this) | this:r1594_2 | -| ir.cpp:1594:19:1594:40 | ChiPartial | partial:m1594_8 | +| ir.cpp:1594:19:1594:40 | ChiPartial | partial:m1594_6 | | ir.cpp:1594:19:1594:40 | ChiTotal | total:m1593_4 | | ir.cpp:1594:19:1594:40 | SideEffect | m1593_4 | | ir.cpp:1594:42:1594:47 | CallTarget | func:r1594_3 | -| ir.cpp:1594:42:1594:47 | ChiPartial | partial:m1594_5 | -| ir.cpp:1594:42:1594:47 | ChiTotal | total:m1587_6 | -| ir.cpp:1594:42:1594:47 | SideEffect | ~m1587_6 | | ir.cpp:1594:42:1594:47 | Unary | r1594_4 | -| ir.cpp:1594:42:1594:50 | StoreValue | r1594_11 | -| ir.cpp:1594:42:1594:50 | Unary | r1594_10 | +| ir.cpp:1594:42:1594:50 | StoreValue | r1594_9 | +| ir.cpp:1594:42:1594:50 | Unary | r1594_8 | | ir.cpp:1595:15:1595:15 | Address | &:r1595_1 | | ir.cpp:1595:19:1595:40 | Address | &:r1595_2 | | ir.cpp:1595:19:1595:40 | Address | &:r1595_2 | | ir.cpp:1595:19:1595:40 | Arg(this) | this:r1595_2 | -| ir.cpp:1595:19:1595:40 | ChiPartial | partial:m1595_8 | -| ir.cpp:1595:19:1595:40 | ChiTotal | total:m1594_9 | -| ir.cpp:1595:19:1595:40 | SideEffect | m1594_9 | +| ir.cpp:1595:19:1595:40 | ChiPartial | partial:m1595_6 | +| ir.cpp:1595:19:1595:40 | ChiTotal | total:m1594_7 | +| ir.cpp:1595:19:1595:40 | SideEffect | m1594_7 | | ir.cpp:1595:42:1595:47 | CallTarget | func:r1595_3 | -| ir.cpp:1595:42:1595:47 | ChiPartial | partial:m1595_5 | -| ir.cpp:1595:42:1595:47 | ChiTotal | total:m1594_6 | -| ir.cpp:1595:42:1595:47 | SideEffect | ~m1594_6 | | ir.cpp:1595:42:1595:47 | Unary | r1595_4 | -| ir.cpp:1595:42:1595:50 | StoreValue | r1595_11 | -| ir.cpp:1595:42:1595:50 | Unary | r1595_10 | +| ir.cpp:1595:42:1595:50 | StoreValue | r1595_9 | +| ir.cpp:1595:42:1595:50 | Unary | r1595_8 | | ir.cpp:1596:15:1596:15 | Address | &:r1596_1 | | ir.cpp:1596:19:1596:40 | Address | &:r1596_2 | | ir.cpp:1596:19:1596:40 | Address | &:r1596_2 | | ir.cpp:1596:19:1596:40 | Arg(this) | this:r1596_2 | -| ir.cpp:1596:19:1596:40 | ChiPartial | partial:m1596_8 | -| ir.cpp:1596:19:1596:40 | ChiTotal | total:m1595_9 | -| ir.cpp:1596:19:1596:40 | SideEffect | m1595_9 | +| ir.cpp:1596:19:1596:40 | ChiPartial | partial:m1596_6 | +| ir.cpp:1596:19:1596:40 | ChiTotal | total:m1595_7 | +| ir.cpp:1596:19:1596:40 | SideEffect | m1595_7 | | ir.cpp:1596:42:1596:47 | CallTarget | func:r1596_3 | -| ir.cpp:1596:42:1596:47 | ChiPartial | partial:m1596_5 | -| ir.cpp:1596:42:1596:47 | ChiTotal | total:m1595_6 | -| ir.cpp:1596:42:1596:47 | SideEffect | ~m1595_6 | | ir.cpp:1596:42:1596:47 | Unary | r1596_4 | -| ir.cpp:1596:42:1596:50 | StoreValue | r1596_11 | -| ir.cpp:1596:42:1596:50 | Unary | r1596_10 | +| ir.cpp:1596:42:1596:50 | StoreValue | r1596_9 | +| ir.cpp:1596:42:1596:50 | Unary | r1596_8 | | ir.cpp:1597:9:1597:9 | Address | &:r1597_2 | | ir.cpp:1597:9:1597:9 | Address | &:r1597_4 | -| ir.cpp:1597:9:1597:9 | Load | m1595_12 | +| ir.cpp:1597:9:1597:9 | Load | m1595_10 | | ir.cpp:1597:9:1597:9 | Unary | r1597_3 | | ir.cpp:1597:9:1597:15 | ChiPartial | partial:m1597_5 | -| ir.cpp:1597:9:1597:15 | ChiTotal | total:m1596_9 | +| ir.cpp:1597:9:1597:15 | ChiTotal | total:m1596_7 | | ir.cpp:1597:13:1597:15 | StoreValue | r1597_1 | | ir.cpp:1598:17:1598:18 | Address | &:r1598_1 | | ir.cpp:1598:22:1598:22 | Address | &:r1598_2 | -| ir.cpp:1598:22:1598:22 | Load | m1595_12 | +| ir.cpp:1598:22:1598:22 | Load | m1595_10 | | ir.cpp:1598:22:1598:22 | StoreValue | r1598_5 | | ir.cpp:1598:22:1598:22 | Unary | r1598_3 | | ir.cpp:1598:22:1598:22 | Unary | r1598_4 | | ir.cpp:1599:13:1599:13 | Address | &:r1599_1 | | ir.cpp:1599:17:1599:17 | Address | &:r1599_2 | | ir.cpp:1599:17:1599:17 | Address | &:r1599_3 | -| ir.cpp:1599:17:1599:17 | Load | m1594_12 | -| ir.cpp:1599:17:1599:17 | Load | ~m1596_9 | +| ir.cpp:1599:17:1599:17 | Load | m1594_10 | +| ir.cpp:1599:17:1599:17 | Load | ~m1596_7 | | ir.cpp:1599:17:1599:17 | StoreValue | r1599_4 | | ir.cpp:1600:9:1600:9 | Address | &:r1600_2 | | ir.cpp:1600:9:1600:9 | Address | &:r1600_4 | -| ir.cpp:1600:9:1600:9 | Load | m1596_12 | +| ir.cpp:1600:9:1600:9 | Load | m1596_10 | | ir.cpp:1600:9:1600:9 | Unary | r1600_3 | | ir.cpp:1600:9:1600:13 | ChiPartial | partial:m1600_5 | -| ir.cpp:1600:9:1600:13 | ChiTotal | total:m1596_6 | +| ir.cpp:1600:9:1600:13 | ChiTotal | total:m1587_6 | | ir.cpp:1600:13:1600:13 | StoreValue | r1600_1 | | ir.cpp:1601:14:1601:15 | Address | &:r1601_1 | | ir.cpp:1601:19:1601:19 | Address | &:r1601_2 | -| ir.cpp:1601:19:1601:19 | Load | m1596_12 | +| ir.cpp:1601:19:1601:19 | Load | m1596_10 | | ir.cpp:1601:19:1601:19 | StoreValue | r1601_5 | | ir.cpp:1601:19:1601:19 | Unary | r1601_3 | | ir.cpp:1601:19:1601:19 | Unary | r1601_4 | | ir.cpp:1602:13:1602:13 | Address | &:r1602_1 | | ir.cpp:1602:17:1602:17 | Address | &:r1602_2 | | ir.cpp:1602:17:1602:17 | Address | &:r1602_3 | -| ir.cpp:1602:17:1602:17 | Load | m1596_12 | +| ir.cpp:1602:17:1602:17 | Load | m1596_10 | | ir.cpp:1602:17:1602:17 | Load | ~m1600_6 | | ir.cpp:1602:17:1602:17 | StoreValue | r1602_4 | | ir.cpp:1606:8:1606:8 | Address | &:r1606_5 | @@ -7482,99 +7398,87 @@ | ir.cpp:1646:36:1646:36 | Arg(this) | this:r1646_1 | | ir.cpp:1646:36:1646:36 | CallTarget | func:r1646_3 | | ir.cpp:1646:36:1646:36 | ChiPartial | partial:m1646_5 | -| ir.cpp:1646:36:1646:36 | ChiPartial | partial:m1646_7 | -| ir.cpp:1646:36:1646:36 | ChiTotal | total:m1645_4 | | ir.cpp:1646:36:1646:36 | ChiTotal | total:m1646_2 | -| ir.cpp:1646:36:1646:36 | SideEffect | ~m1645_4 | | ir.cpp:1649:16:1649:16 | Address | &:r1649_1 | | ir.cpp:1649:16:1649:16 | Address | &:r1649_7 | -| ir.cpp:1649:16:1649:16 | Address | &:r1649_21 | -| ir.cpp:1649:16:1649:16 | Address | &:r1649_35 | +| ir.cpp:1649:16:1649:16 | Address | &:r1649_19 | +| ir.cpp:1649:16:1649:16 | Address | &:r1649_31 | | ir.cpp:1649:16:1649:16 | CallTarget | func:r1649_10 | -| ir.cpp:1649:16:1649:16 | CallTarget | func:r1649_24 | -| ir.cpp:1649:16:1649:16 | CallTarget | func:r1649_38 | -| ir.cpp:1649:16:1649:16 | ChiPartial | partial:m1649_12 | -| ir.cpp:1649:16:1649:16 | ChiPartial | partial:m1649_26 | -| ir.cpp:1649:16:1649:16 | ChiPartial | partial:m1649_40 | -| ir.cpp:1649:16:1649:16 | ChiTotal | total:m1646_6 | -| ir.cpp:1649:16:1649:16 | ChiTotal | total:m1649_13 | -| ir.cpp:1649:16:1649:16 | ChiTotal | total:m1649_27 | +| ir.cpp:1649:16:1649:16 | CallTarget | func:r1649_22 | +| ir.cpp:1649:16:1649:16 | CallTarget | func:r1649_34 | | ir.cpp:1649:16:1649:16 | Load | m1649_4 | | ir.cpp:1649:16:1649:16 | Load | m1649_4 | | ir.cpp:1649:16:1649:16 | Load | m1649_4 | -| ir.cpp:1649:16:1649:16 | SideEffect | ~m1646_6 | -| ir.cpp:1649:16:1649:16 | SideEffect | ~m1649_13 | -| ir.cpp:1649:16:1649:16 | SideEffect | ~m1649_27 | | ir.cpp:1649:16:1649:16 | StoreValue | r1649_11 | | ir.cpp:1649:16:1649:16 | Unary | r1649_8 | -| ir.cpp:1649:16:1649:16 | Unary | r1649_22 | -| ir.cpp:1649:16:1649:16 | Unary | r1649_25 | -| ir.cpp:1649:16:1649:16 | Unary | r1649_36 | -| ir.cpp:1649:16:1649:16 | Unary | r1649_39 | +| ir.cpp:1649:16:1649:16 | Unary | r1649_20 | +| ir.cpp:1649:16:1649:16 | Unary | r1649_23 | +| ir.cpp:1649:16:1649:16 | Unary | r1649_32 | +| ir.cpp:1649:16:1649:16 | Unary | r1649_35 | | ir.cpp:1649:16:1649:30 | Address | &:r1649_6 | -| ir.cpp:1649:16:1649:30 | StoreValue | r1649_18 | -| ir.cpp:1649:16:1649:30 | StoreValue | r1649_32 | -| ir.cpp:1649:16:1649:30 | StoreValue | r1649_46 | +| ir.cpp:1649:16:1649:30 | StoreValue | r1649_16 | +| ir.cpp:1649:16:1649:30 | StoreValue | r1649_28 | +| ir.cpp:1649:16:1649:30 | StoreValue | r1649_40 | | ir.cpp:1649:16:1649:30 | Unary | r1649_6 | -| ir.cpp:1649:16:1649:30 | Unary | r1649_31 | -| ir.cpp:1649:16:1649:30 | Unary | r1649_45 | +| ir.cpp:1649:16:1649:30 | Unary | r1649_27 | +| ir.cpp:1649:16:1649:30 | Unary | r1649_39 | | ir.cpp:1649:17:1649:17 | Address | &:r1649_5 | -| ir.cpp:1649:20:1649:20 | Address | &:r1649_20 | -| ir.cpp:1649:23:1649:23 | Address | &:r1649_34 | +| ir.cpp:1649:20:1649:20 | Address | &:r1649_18 | +| ir.cpp:1649:23:1649:23 | Address | &:r1649_30 | | ir.cpp:1649:29:1649:29 | StoreValue | r1649_3 | | ir.cpp:1649:29:1649:29 | Unary | r1649_2 | | ir.cpp:1649:30:1649:30 | Address | &:r1649_9 | | ir.cpp:1649:30:1649:30 | Address | &:r1649_9 | -| ir.cpp:1649:30:1649:30 | Address | &:r1649_23 | -| ir.cpp:1649:30:1649:30 | Address | &:r1649_23 | -| ir.cpp:1649:30:1649:30 | Address | &:r1649_37 | -| ir.cpp:1649:30:1649:30 | Address | &:r1649_37 | +| ir.cpp:1649:30:1649:30 | Address | &:r1649_21 | +| ir.cpp:1649:30:1649:30 | Address | &:r1649_21 | +| ir.cpp:1649:30:1649:30 | Address | &:r1649_33 | +| ir.cpp:1649:30:1649:30 | Address | &:r1649_33 | | ir.cpp:1649:30:1649:30 | Arg(this) | this:r1649_9 | -| ir.cpp:1649:30:1649:30 | Arg(this) | this:r1649_23 | -| ir.cpp:1649:30:1649:30 | Arg(this) | this:r1649_37 | -| ir.cpp:1649:30:1649:30 | ChiPartial | partial:m1649_15 | -| ir.cpp:1649:30:1649:30 | ChiPartial | partial:m1649_29 | -| ir.cpp:1649:30:1649:30 | ChiPartial | partial:m1649_43 | -| ir.cpp:1649:30:1649:30 | ChiTotal | total:m1646_8 | -| ir.cpp:1649:30:1649:30 | ChiTotal | total:m1649_16 | -| ir.cpp:1649:30:1649:30 | ChiTotal | total:m1649_30 | -| ir.cpp:1649:30:1649:30 | SideEffect | m1646_8 | -| ir.cpp:1649:30:1649:30 | SideEffect | m1649_16 | -| ir.cpp:1649:30:1649:30 | SideEffect | m1649_30 | +| ir.cpp:1649:30:1649:30 | Arg(this) | this:r1649_21 | +| ir.cpp:1649:30:1649:30 | Arg(this) | this:r1649_33 | +| ir.cpp:1649:30:1649:30 | ChiPartial | partial:m1649_13 | +| ir.cpp:1649:30:1649:30 | ChiPartial | partial:m1649_25 | +| ir.cpp:1649:30:1649:30 | ChiPartial | partial:m1649_37 | +| ir.cpp:1649:30:1649:30 | ChiTotal | total:m1646_6 | +| ir.cpp:1649:30:1649:30 | ChiTotal | total:m1649_14 | +| ir.cpp:1649:30:1649:30 | ChiTotal | total:m1649_26 | +| ir.cpp:1649:30:1649:30 | SideEffect | m1646_6 | +| ir.cpp:1649:30:1649:30 | SideEffect | m1649_14 | +| ir.cpp:1649:30:1649:30 | SideEffect | m1649_26 | | ir.cpp:1650:9:1650:9 | Address | &:r1650_2 | | ir.cpp:1650:9:1650:9 | Address | &:r1650_4 | -| ir.cpp:1650:9:1650:9 | Load | m1649_19 | +| ir.cpp:1650:9:1650:9 | Load | m1649_17 | | ir.cpp:1650:9:1650:9 | Unary | r1650_3 | | ir.cpp:1650:13:1650:13 | StoreValue | r1650_1 | | ir.cpp:1651:14:1651:15 | Address | &:r1651_1 | | ir.cpp:1651:19:1651:19 | Address | &:r1651_2 | -| ir.cpp:1651:19:1651:19 | Load | m1649_19 | +| ir.cpp:1651:19:1651:19 | Load | m1649_17 | | ir.cpp:1651:19:1651:19 | StoreValue | r1651_5 | | ir.cpp:1651:19:1651:19 | Unary | r1651_3 | | ir.cpp:1651:19:1651:19 | Unary | r1651_4 | | ir.cpp:1652:13:1652:13 | Address | &:r1652_1 | | ir.cpp:1652:17:1652:17 | Address | &:r1652_2 | | ir.cpp:1652:17:1652:17 | Address | &:r1652_3 | -| ir.cpp:1652:17:1652:17 | Load | m1649_19 | +| ir.cpp:1652:17:1652:17 | Load | m1649_17 | | ir.cpp:1652:17:1652:17 | Load | m1650_5 | | ir.cpp:1652:17:1652:17 | StoreValue | r1652_4 | | ir.cpp:1653:9:1653:9 | Address | &:r1653_2 | | ir.cpp:1653:9:1653:9 | Address | &:r1653_4 | -| ir.cpp:1653:9:1653:9 | Load | m1649_33 | +| ir.cpp:1653:9:1653:9 | Load | m1649_29 | | ir.cpp:1653:9:1653:9 | Unary | r1653_3 | | ir.cpp:1653:9:1653:13 | ChiPartial | partial:m1653_5 | -| ir.cpp:1653:9:1653:13 | ChiTotal | total:m1649_41 | +| ir.cpp:1653:9:1653:13 | ChiTotal | total:m1645_4 | | ir.cpp:1653:13:1653:13 | StoreValue | r1653_1 | | ir.cpp:1654:14:1654:15 | Address | &:r1654_1 | | ir.cpp:1654:19:1654:19 | Address | &:r1654_2 | -| ir.cpp:1654:19:1654:19 | Load | m1649_33 | +| ir.cpp:1654:19:1654:19 | Load | m1649_29 | | ir.cpp:1654:19:1654:19 | StoreValue | r1654_5 | | ir.cpp:1654:19:1654:19 | Unary | r1654_3 | | ir.cpp:1654:19:1654:19 | Unary | r1654_4 | | ir.cpp:1655:13:1655:13 | Address | &:r1655_1 | | ir.cpp:1655:17:1655:17 | Address | &:r1655_2 | | ir.cpp:1655:17:1655:17 | Address | &:r1655_3 | -| ir.cpp:1655:17:1655:17 | Load | m1649_33 | +| ir.cpp:1655:17:1655:17 | Load | m1649_29 | | ir.cpp:1655:17:1655:17 | Load | ~m1653_6 | | ir.cpp:1655:17:1655:17 | StoreValue | r1655_4 | | ir.cpp:1659:16:1659:37 | Address | &:r1659_1 | @@ -7585,87 +7489,78 @@ | ir.cpp:1660:20:1660:41 | Address | &:r1660_5 | | ir.cpp:1660:20:1660:41 | Address | &:r1660_5 | | ir.cpp:1660:20:1660:41 | Arg(this) | this:r1660_5 | -| ir.cpp:1660:20:1660:41 | ChiPartial | partial:m1660_11 | -| ir.cpp:1660:20:1660:41 | ChiTotal | total:m1649_44 | +| ir.cpp:1660:20:1660:41 | ChiPartial | partial:m1660_9 | +| ir.cpp:1660:20:1660:41 | ChiTotal | total:m1649_38 | | ir.cpp:1660:20:1660:41 | Load | m1659_4 | -| ir.cpp:1660:20:1660:41 | SideEffect | m1649_44 | +| ir.cpp:1660:20:1660:41 | SideEffect | m1649_38 | | ir.cpp:1660:20:1660:41 | Unary | r1660_4 | | ir.cpp:1660:20:1660:50 | Address | &:r1660_2 | -| ir.cpp:1660:20:1660:50 | StoreValue | r1660_14 | +| ir.cpp:1660:20:1660:50 | StoreValue | r1660_12 | | ir.cpp:1660:20:1660:50 | Unary | r1660_2 | | ir.cpp:1660:43:1660:48 | CallTarget | func:r1660_6 | -| ir.cpp:1660:43:1660:48 | ChiPartial | partial:m1660_8 | -| ir.cpp:1660:43:1660:48 | ChiTotal | total:m1653_6 | -| ir.cpp:1660:43:1660:48 | SideEffect | ~m1653_6 | | ir.cpp:1660:43:1660:48 | StoreValue | r1660_7 | | ir.cpp:1661:15:1661:15 | Address | &:r1661_1 | | ir.cpp:1661:19:1661:40 | Address | &:r1661_2 | | ir.cpp:1661:19:1661:40 | Address | &:r1661_4 | | ir.cpp:1661:19:1661:40 | Address | &:r1661_4 | | ir.cpp:1661:19:1661:40 | Arg(this) | this:r1661_4 | -| ir.cpp:1661:19:1661:40 | ChiPartial | partial:m1661_10 | -| ir.cpp:1661:19:1661:40 | ChiTotal | total:m1660_12 | +| ir.cpp:1661:19:1661:40 | ChiPartial | partial:m1661_8 | +| ir.cpp:1661:19:1661:40 | ChiTotal | total:m1660_10 | | ir.cpp:1661:19:1661:40 | Load | m1659_4 | -| ir.cpp:1661:19:1661:40 | SideEffect | m1660_12 | +| ir.cpp:1661:19:1661:40 | SideEffect | m1660_10 | | ir.cpp:1661:19:1661:40 | Unary | r1661_3 | | ir.cpp:1661:42:1661:47 | CallTarget | func:r1661_5 | -| ir.cpp:1661:42:1661:47 | ChiPartial | partial:m1661_7 | -| ir.cpp:1661:42:1661:47 | ChiTotal | total:m1660_9 | -| ir.cpp:1661:42:1661:47 | SideEffect | ~m1660_9 | | ir.cpp:1661:42:1661:47 | Unary | r1661_6 | -| ir.cpp:1661:42:1661:50 | StoreValue | r1661_13 | -| ir.cpp:1661:42:1661:50 | Unary | r1661_12 | +| ir.cpp:1661:42:1661:50 | StoreValue | r1661_11 | +| ir.cpp:1661:42:1661:50 | Unary | r1661_10 | | ir.cpp:1662:16:1662:17 | Address | &:r1662_1 | | ir.cpp:1662:21:1662:42 | Address | &:r1662_2 | | ir.cpp:1662:21:1662:42 | Address | &:r1662_4 | | ir.cpp:1662:21:1662:42 | Address | &:r1662_4 | | ir.cpp:1662:21:1662:42 | Arg(this) | this:r1662_4 | -| ir.cpp:1662:21:1662:42 | ChiPartial | partial:m1662_10 | -| ir.cpp:1662:21:1662:42 | ChiTotal | total:m1661_11 | +| ir.cpp:1662:21:1662:42 | ChiPartial | partial:m1662_8 | +| ir.cpp:1662:21:1662:42 | ChiTotal | total:m1661_9 | | ir.cpp:1662:21:1662:42 | Load | m1659_4 | -| ir.cpp:1662:21:1662:42 | SideEffect | m1661_11 | +| ir.cpp:1662:21:1662:42 | SideEffect | m1661_9 | | ir.cpp:1662:21:1662:42 | Unary | r1662_3 | | ir.cpp:1662:44:1662:49 | CallTarget | func:r1662_5 | -| ir.cpp:1662:44:1662:49 | ChiPartial | partial:m1662_7 | -| ir.cpp:1662:44:1662:49 | ChiTotal | total:m1661_8 | -| ir.cpp:1662:44:1662:49 | SideEffect | ~m1661_8 | | ir.cpp:1662:44:1662:49 | Unary | r1662_6 | -| ir.cpp:1662:44:1662:52 | StoreValue | r1662_13 | -| ir.cpp:1662:44:1662:52 | Unary | r1662_12 | +| ir.cpp:1662:44:1662:52 | StoreValue | r1662_11 | +| ir.cpp:1662:44:1662:52 | Unary | r1662_10 | | ir.cpp:1663:9:1663:9 | Address | &:r1663_2 | | ir.cpp:1663:9:1663:9 | Address | &:r1663_4 | -| ir.cpp:1663:9:1663:9 | Load | m1660_15 | +| ir.cpp:1663:9:1663:9 | Load | m1660_13 | | ir.cpp:1663:9:1663:9 | Unary | r1663_3 | | ir.cpp:1663:13:1663:13 | StoreValue | r1663_1 | | ir.cpp:1664:14:1664:15 | Address | &:r1664_1 | | ir.cpp:1664:19:1664:19 | Address | &:r1664_2 | -| ir.cpp:1664:19:1664:19 | Load | m1660_15 | +| ir.cpp:1664:19:1664:19 | Load | m1660_13 | | ir.cpp:1664:19:1664:19 | StoreValue | r1664_5 | | ir.cpp:1664:19:1664:19 | Unary | r1664_3 | | ir.cpp:1664:19:1664:19 | Unary | r1664_4 | | ir.cpp:1665:13:1665:13 | Address | &:r1665_1 | | ir.cpp:1665:17:1665:17 | Address | &:r1665_2 | | ir.cpp:1665:17:1665:17 | Address | &:r1665_3 | -| ir.cpp:1665:17:1665:17 | Load | m1660_15 | +| ir.cpp:1665:17:1665:17 | Load | m1660_13 | | ir.cpp:1665:17:1665:17 | Load | m1663_5 | | ir.cpp:1665:17:1665:17 | StoreValue | r1665_4 | | ir.cpp:1666:9:1666:9 | Address | &:r1666_2 | | ir.cpp:1666:9:1666:9 | Address | &:r1666_4 | -| ir.cpp:1666:9:1666:9 | Load | m1661_14 | +| ir.cpp:1666:9:1666:9 | Load | m1661_12 | | ir.cpp:1666:9:1666:9 | Unary | r1666_3 | | ir.cpp:1666:9:1666:13 | ChiPartial | partial:m1666_5 | -| ir.cpp:1666:9:1666:13 | ChiTotal | total:m1662_8 | +| ir.cpp:1666:9:1666:13 | ChiTotal | total:m1653_6 | | ir.cpp:1666:13:1666:13 | StoreValue | r1666_1 | | ir.cpp:1667:14:1667:15 | Address | &:r1667_1 | | ir.cpp:1667:19:1667:19 | Address | &:r1667_2 | -| ir.cpp:1667:19:1667:19 | Load | m1661_14 | +| ir.cpp:1667:19:1667:19 | Load | m1661_12 | | ir.cpp:1667:19:1667:19 | StoreValue | r1667_5 | | ir.cpp:1667:19:1667:19 | Unary | r1667_3 | | ir.cpp:1667:19:1667:19 | Unary | r1667_4 | | ir.cpp:1668:13:1668:13 | Address | &:r1668_1 | | ir.cpp:1668:17:1668:17 | Address | &:r1668_2 | | ir.cpp:1668:17:1668:17 | Address | &:r1668_3 | -| ir.cpp:1668:17:1668:17 | Load | m1661_14 | +| ir.cpp:1668:17:1668:17 | Load | m1661_12 | | ir.cpp:1668:17:1668:17 | Load | ~m1666_6 | | ir.cpp:1668:17:1668:17 | StoreValue | r1668_4 | | ir.cpp:1672:6:1672:42 | ChiPartial | partial:m1672_3 | @@ -7701,7 +7596,7 @@ | ir.cpp:1680:5:1680:23 | SideEffect | m1680_8 | | ir.cpp:1683:6:1683:20 | ChiPartial | partial:m1683_3 | | ir.cpp:1683:6:1683:20 | ChiTotal | total:m1683_2 | -| ir.cpp:1683:6:1683:20 | SideEffect | ~m1686_6 | +| ir.cpp:1683:6:1683:20 | SideEffect | m1683_3 | | ir.cpp:1683:26:1683:26 | Address | &:r1683_5 | | ir.cpp:1683:34:1683:34 | Address | &:r1683_7 | | ir.cpp:1683:34:1683:34 | Address | &:r1683_7 | @@ -7721,22 +7616,16 @@ | ir.cpp:1685:24:1685:44 | Arg(this) | this:r1685_2 | | ir.cpp:1685:24:1685:44 | CallTarget | func:r1685_4 | | ir.cpp:1685:24:1685:44 | ChiPartial | partial:m1685_6 | -| ir.cpp:1685:24:1685:44 | ChiPartial | partial:m1685_8 | -| ir.cpp:1685:24:1685:44 | ChiTotal | total:m1683_4 | | ir.cpp:1685:24:1685:44 | ChiTotal | total:m1685_3 | -| ir.cpp:1685:24:1685:44 | SideEffect | ~m1683_4 | -| ir.cpp:1685:24:1685:44 | StoreValue | r1685_11 | +| ir.cpp:1685:24:1685:44 | StoreValue | r1685_9 | | ir.cpp:1685:24:1685:44 | Unary | r1685_2 | -| ir.cpp:1685:24:1685:44 | Unary | r1685_10 | +| ir.cpp:1685:24:1685:44 | Unary | r1685_8 | | ir.cpp:1686:10:1686:13 | Address | &:r1686_1 | | ir.cpp:1686:10:1686:13 | Address | &:r1686_1 | | ir.cpp:1686:10:1686:13 | Arg(this) | this:r1686_1 | | ir.cpp:1686:16:1686:37 | CallTarget | func:r1686_3 | | ir.cpp:1686:16:1686:37 | ChiPartial | partial:m1686_5 | -| ir.cpp:1686:16:1686:37 | ChiPartial | partial:m1686_7 | -| ir.cpp:1686:16:1686:37 | ChiTotal | total:m1685_7 | | ir.cpp:1686:16:1686:37 | ChiTotal | total:m1686_2 | -| ir.cpp:1686:16:1686:37 | SideEffect | ~m1685_7 | | ir.cpp:1688:10:1688:21 | Address | &:r1688_1 | | ir.cpp:1688:24:1690:5 | Address | &:r1688_2 | | ir.cpp:1688:24:1690:5 | Address | &:r1688_2 | @@ -7750,8 +7639,8 @@ | ir.cpp:1688:24:1690:5 | Address | &:r1688_20 | | ir.cpp:1688:24:1690:5 | ChiPartial | partial:m1688_10 | | ir.cpp:1688:24:1690:5 | ChiTotal | total:m0_3 | -| ir.cpp:1688:24:1690:5 | Load | m1685_12 | -| ir.cpp:1688:24:1690:5 | Load | m1686_8 | +| ir.cpp:1688:24:1690:5 | Load | m1685_10 | +| ir.cpp:1688:24:1690:5 | Load | m1686_6 | | ir.cpp:1688:24:1690:5 | Load | m1690_6 | | ir.cpp:1688:24:1690:5 | StoreValue | r1688_9 | | ir.cpp:1688:24:1690:5 | StoreValue | r1688_23 | @@ -7891,16 +7780,13 @@ | ir.cpp:1702:34:1702:34 | ChiPartial | partial:m1702_3 | | ir.cpp:1702:34:1702:34 | ChiTotal | total:m1702_2 | | ir.cpp:1702:34:1702:34 | Load | m1702_6 | +| ir.cpp:1702:34:1702:34 | SideEffect | m1702_3 | | ir.cpp:1702:34:1702:34 | SideEffect | m1702_8 | -| ir.cpp:1702:34:1702:34 | SideEffect | ~m1703_8 | | ir.cpp:1703:13:1703:13 | Address | &:r1703_1 | | ir.cpp:1703:13:1703:13 | Address | &:r1703_4 | | ir.cpp:1703:13:1703:13 | Arg(this) | this:r1703_4 | | ir.cpp:1703:13:1703:13 | CallTarget | func:r1703_5 | -| ir.cpp:1703:13:1703:13 | ChiPartial | partial:m1703_7 | -| ir.cpp:1703:13:1703:13 | ChiTotal | total:m1702_4 | | ir.cpp:1703:13:1703:13 | Load | m1702_6 | -| ir.cpp:1703:13:1703:13 | SideEffect | ~m1702_4 | | ir.cpp:1703:13:1703:13 | SideEffect | ~m1702_8 | | ir.cpp:1703:13:1703:13 | Unary | r1703_2 | | ir.cpp:1703:13:1703:13 | Unary | r1703_3 | @@ -7924,16 +7810,13 @@ | ir.cpp:1705:38:1705:38 | ChiPartial | partial:m1705_3 | | ir.cpp:1705:38:1705:38 | ChiTotal | total:m1705_2 | | ir.cpp:1705:38:1705:38 | Load | m1705_6 | +| ir.cpp:1705:38:1705:38 | SideEffect | m1705_3 | | ir.cpp:1705:38:1705:38 | SideEffect | m1705_8 | -| ir.cpp:1705:38:1705:38 | SideEffect | ~m1706_8 | | ir.cpp:1706:17:1706:17 | Address | &:r1706_1 | | ir.cpp:1706:17:1706:17 | Address | &:r1706_4 | | ir.cpp:1706:17:1706:17 | Arg(this) | this:r1706_4 | | ir.cpp:1706:17:1706:17 | CallTarget | func:r1706_5 | -| ir.cpp:1706:17:1706:17 | ChiPartial | partial:m1706_7 | -| ir.cpp:1706:17:1706:17 | ChiTotal | total:m1705_4 | | ir.cpp:1706:17:1706:17 | Load | m1705_6 | -| ir.cpp:1706:17:1706:17 | SideEffect | ~m1705_4 | | ir.cpp:1706:17:1706:17 | SideEffect | ~m1705_8 | | ir.cpp:1706:17:1706:17 | Unary | r1706_2 | | ir.cpp:1706:17:1706:17 | Unary | r1706_3 | @@ -8086,17 +7969,14 @@ | ir.cpp:1736:7:1736:7 | Arg(this) | this:r1736_9 | | ir.cpp:1736:7:1736:7 | CallTarget | func:r1736_10 | | ir.cpp:1736:7:1736:7 | ChiPartial | partial:m1736_3 | -| ir.cpp:1736:7:1736:7 | ChiPartial | partial:m1736_17 | -| ir.cpp:1736:7:1736:7 | ChiPartial | partial:m1736_20 | +| ir.cpp:1736:7:1736:7 | ChiPartial | partial:m1736_18 | | ir.cpp:1736:7:1736:7 | ChiTotal | total:m1736_2 | -| ir.cpp:1736:7:1736:7 | ChiTotal | total:m1736_4 | | ir.cpp:1736:7:1736:7 | ChiTotal | total:m1736_8 | | ir.cpp:1736:7:1736:7 | Load | m0_2 | | ir.cpp:1736:7:1736:7 | Load | m1736_6 | -| ir.cpp:1736:7:1736:7 | SideEffect | m1736_21 | +| ir.cpp:1736:7:1736:7 | SideEffect | m1736_3 | +| ir.cpp:1736:7:1736:7 | SideEffect | m1736_19 | | ir.cpp:1736:7:1736:7 | SideEffect | ~m0_4 | -| ir.cpp:1736:7:1736:7 | SideEffect | ~m1736_4 | -| ir.cpp:1736:7:1736:7 | SideEffect | ~m1736_18 | | ir.cpp:1736:7:1736:7 | Unary | m1736_6 | | ir.cpp:1736:7:1736:7 | Unary | r1736_12 | | ir.cpp:1736:7:1736:7 | Unary | r1736_13 | @@ -8108,26 +7988,20 @@ | ir.cpp:1740:5:1740:38 | ChiPartial | partial:m1740_3 | | ir.cpp:1740:5:1740:38 | ChiTotal | total:m1740_2 | | ir.cpp:1740:5:1740:38 | Load | m1740_6 | -| ir.cpp:1740:5:1740:38 | SideEffect | m1740_22 | -| ir.cpp:1740:5:1740:38 | SideEffect | ~m1740_20 | +| ir.cpp:1740:5:1740:38 | SideEffect | m1740_3 | +| ir.cpp:1740:5:1740:38 | SideEffect | m1740_18 | | ir.cpp:1740:5:1740:38 | Unary | m1740_6 | | ir.cpp:1740:5:1740:38 | Unary | m1740_6 | | ir.cpp:1740:42:1740:42 | Address | &:r1740_9 | -| ir.cpp:1740:42:1740:42 | Address | &:r1740_16 | +| ir.cpp:1740:42:1740:42 | Address | &:r1740_14 | | ir.cpp:1740:42:1740:42 | Arg(this) | this:r1740_9 | -| ir.cpp:1740:42:1740:42 | Arg(this) | this:r1740_16 | +| ir.cpp:1740:42:1740:42 | Arg(this) | this:r1740_14 | | ir.cpp:1740:42:1740:42 | CallTarget | func:r1740_10 | -| ir.cpp:1740:42:1740:42 | CallTarget | func:r1740_17 | +| ir.cpp:1740:42:1740:42 | CallTarget | func:r1740_15 | | ir.cpp:1740:42:1740:42 | ChiPartial | partial:m1740_12 | -| ir.cpp:1740:42:1740:42 | ChiPartial | partial:m1740_14 | -| ir.cpp:1740:42:1740:42 | ChiPartial | partial:m1740_19 | -| ir.cpp:1740:42:1740:42 | ChiPartial | partial:m1740_21 | -| ir.cpp:1740:42:1740:42 | ChiTotal | total:m1740_4 | +| ir.cpp:1740:42:1740:42 | ChiPartial | partial:m1740_17 | | ir.cpp:1740:42:1740:42 | ChiTotal | total:m1740_8 | | ir.cpp:1740:42:1740:42 | ChiTotal | total:m1740_13 | -| ir.cpp:1740:42:1740:42 | ChiTotal | total:m1740_15 | -| ir.cpp:1740:42:1740:42 | SideEffect | ~m1740_4 | -| ir.cpp:1740:42:1740:42 | SideEffect | ~m1740_13 | | ir.cpp:1743:7:1743:7 | Address | &:r1743_5 | | ir.cpp:1743:7:1743:7 | Address | &:r1743_5 | | ir.cpp:1743:7:1743:7 | Address | &:r1743_7 | @@ -8139,17 +8013,14 @@ | ir.cpp:1743:7:1743:7 | Arg(this) | this:r1743_9 | | ir.cpp:1743:7:1743:7 | CallTarget | func:r1743_10 | | ir.cpp:1743:7:1743:7 | ChiPartial | partial:m1743_3 | -| ir.cpp:1743:7:1743:7 | ChiPartial | partial:m1743_17 | -| ir.cpp:1743:7:1743:7 | ChiPartial | partial:m1743_20 | +| ir.cpp:1743:7:1743:7 | ChiPartial | partial:m1743_18 | | ir.cpp:1743:7:1743:7 | ChiTotal | total:m1743_2 | | ir.cpp:1743:7:1743:7 | ChiTotal | total:m1743_4 | -| ir.cpp:1743:7:1743:7 | ChiTotal | total:m1743_18 | | ir.cpp:1743:7:1743:7 | Load | m0_2 | | ir.cpp:1743:7:1743:7 | Load | m1743_6 | | ir.cpp:1743:7:1743:7 | SideEffect | m1743_8 | | ir.cpp:1743:7:1743:7 | SideEffect | ~m0_4 | -| ir.cpp:1743:7:1743:7 | SideEffect | ~m1743_4 | -| ir.cpp:1743:7:1743:7 | SideEffect | ~m1743_21 | +| ir.cpp:1743:7:1743:7 | SideEffect | ~m1743_19 | | ir.cpp:1743:7:1743:7 | Unary | m1743_6 | | ir.cpp:1743:7:1743:7 | Unary | r1743_12 | | ir.cpp:1743:7:1743:7 | Unary | r1743_13 | @@ -8162,25 +8033,19 @@ | ir.cpp:1747:5:1747:35 | ChiTotal | total:m1747_2 | | ir.cpp:1747:5:1747:35 | Load | m1747_6 | | ir.cpp:1747:5:1747:35 | SideEffect | m1747_8 | -| ir.cpp:1747:5:1747:35 | SideEffect | ~m1747_22 | +| ir.cpp:1747:5:1747:35 | SideEffect | ~m1747_18 | | ir.cpp:1747:5:1747:35 | Unary | m1747_6 | | ir.cpp:1747:5:1747:35 | Unary | m1747_6 | | ir.cpp:1747:39:1747:39 | Address | &:r1747_9 | -| ir.cpp:1747:39:1747:39 | Address | &:r1747_16 | +| ir.cpp:1747:39:1747:39 | Address | &:r1747_14 | | ir.cpp:1747:39:1747:39 | Arg(this) | this:r1747_9 | -| ir.cpp:1747:39:1747:39 | Arg(this) | this:r1747_16 | +| ir.cpp:1747:39:1747:39 | Arg(this) | this:r1747_14 | | ir.cpp:1747:39:1747:39 | CallTarget | func:r1747_10 | -| ir.cpp:1747:39:1747:39 | CallTarget | func:r1747_17 | +| ir.cpp:1747:39:1747:39 | CallTarget | func:r1747_15 | | ir.cpp:1747:39:1747:39 | ChiPartial | partial:m1747_12 | -| ir.cpp:1747:39:1747:39 | ChiPartial | partial:m1747_14 | -| ir.cpp:1747:39:1747:39 | ChiPartial | partial:m1747_19 | -| ir.cpp:1747:39:1747:39 | ChiPartial | partial:m1747_21 | +| ir.cpp:1747:39:1747:39 | ChiPartial | partial:m1747_17 | | ir.cpp:1747:39:1747:39 | ChiTotal | total:m1747_4 | | ir.cpp:1747:39:1747:39 | ChiTotal | total:m1747_13 | -| ir.cpp:1747:39:1747:39 | ChiTotal | total:m1747_15 | -| ir.cpp:1747:39:1747:39 | ChiTotal | total:m1747_20 | -| ir.cpp:1747:39:1747:39 | SideEffect | ~m1747_4 | -| ir.cpp:1747:39:1747:39 | SideEffect | ~m1747_15 | | ir.cpp:1750:5:1750:34 | ChiPartial | partial:m1750_3 | | ir.cpp:1750:5:1750:34 | ChiTotal | total:m1750_2 | | ir.cpp:1751:51:1751:51 | Address | &:r1751_1 | @@ -8195,11 +8060,8 @@ | ir.cpp:1753:40:1753:41 | Address | &:r1753_1 | | ir.cpp:1753:40:1753:41 | Arg(this) | this:r1753_1 | | ir.cpp:1753:44:1753:45 | CallTarget | func:r1753_3 | -| ir.cpp:1753:44:1753:45 | ChiPartial | partial:m1753_9 | -| ir.cpp:1753:44:1753:45 | ChiPartial | partial:m1753_12 | -| ir.cpp:1753:44:1753:45 | ChiTotal | total:m1750_4 | +| ir.cpp:1753:44:1753:45 | ChiPartial | partial:m1753_10 | | ir.cpp:1753:44:1753:45 | ChiTotal | total:m1753_2 | -| ir.cpp:1753:44:1753:45 | SideEffect | ~m1750_4 | | ir.cpp:1753:45:1753:45 | Address | &:r1753_4 | | ir.cpp:1753:45:1753:45 | Address | &:r1753_7 | | ir.cpp:1753:45:1753:45 | Arg(0) | 0:r1753_7 | @@ -8211,11 +8073,8 @@ | ir.cpp:1754:37:1754:38 | Address | &:r1754_1 | | ir.cpp:1754:37:1754:38 | Arg(this) | this:r1754_1 | | ir.cpp:1754:41:1754:42 | CallTarget | func:r1754_3 | -| ir.cpp:1754:41:1754:42 | ChiPartial | partial:m1754_9 | -| ir.cpp:1754:41:1754:42 | ChiPartial | partial:m1754_12 | -| ir.cpp:1754:41:1754:42 | ChiTotal | total:m1753_10 | +| ir.cpp:1754:41:1754:42 | ChiPartial | partial:m1754_10 | | ir.cpp:1754:41:1754:42 | ChiTotal | total:m1754_2 | -| ir.cpp:1754:41:1754:42 | SideEffect | ~m1753_10 | | ir.cpp:1754:42:1754:42 | Address | &:r1754_4 | | ir.cpp:1754:42:1754:42 | Address | &:r1754_7 | | ir.cpp:1754:42:1754:42 | Arg(0) | 0:r1754_7 | @@ -8524,7 +8383,7 @@ | perf-regression.cpp:9:5:9:8 | ChiPartial | partial:m9_3 | | perf-regression.cpp:9:5:9:8 | ChiTotal | total:m9_2 | | perf-regression.cpp:9:5:9:8 | Load | m12_3 | -| perf-regression.cpp:9:5:9:8 | SideEffect | ~m10_12 | +| perf-regression.cpp:9:5:9:8 | SideEffect | ~m10_6 | | perf-regression.cpp:10:8:10:10 | Address | &:r10_1 | | perf-regression.cpp:10:14:10:20 | Address | &:r10_4 | | perf-regression.cpp:10:14:10:20 | Address | &:r10_8 | @@ -8534,12 +8393,9 @@ | perf-regression.cpp:10:14:10:20 | CallTarget | func:r10_9 | | perf-regression.cpp:10:14:10:20 | ChiPartial | partial:m10_5 | | perf-regression.cpp:10:14:10:20 | ChiPartial | partial:m10_11 | -| perf-regression.cpp:10:14:10:20 | ChiPartial | partial:m10_13 | | perf-regression.cpp:10:14:10:20 | ChiTotal | total:m9_4 | -| perf-regression.cpp:10:14:10:20 | ChiTotal | total:m10_6 | | perf-regression.cpp:10:14:10:20 | ChiTotal | total:m10_7 | | perf-regression.cpp:10:14:10:20 | SideEffect | ~m9_4 | -| perf-regression.cpp:10:14:10:20 | SideEffect | ~m10_6 | | perf-regression.cpp:10:14:10:20 | StoreValue | r10_8 | | perf-regression.cpp:10:14:10:20 | Unary | r10_4 | | perf-regression.cpp:12:3:12:11 | Address | &:r12_1 | @@ -8560,13 +8416,10 @@ | smart_ptr.cpp:11:24:11:24 | Arg(0) | 0:r11_5 | | smart_ptr.cpp:11:24:11:24 | Load | m10_6 | | smart_ptr.cpp:11:24:11:25 | CallTarget | func:r11_3 | -| smart_ptr.cpp:11:24:11:25 | ChiPartial | partial:m11_7 | -| smart_ptr.cpp:11:24:11:25 | ChiTotal | total:m10_4 | -| smart_ptr.cpp:11:24:11:25 | SideEffect | ~m10_4 | | smart_ptr.cpp:12:5:12:18 | CallTarget | func:r12_1 | | smart_ptr.cpp:12:5:12:18 | ChiPartial | partial:m12_11 | -| smart_ptr.cpp:12:5:12:18 | ChiTotal | total:m11_8 | -| smart_ptr.cpp:12:5:12:18 | SideEffect | ~m11_8 | +| smart_ptr.cpp:12:5:12:18 | ChiTotal | total:m10_4 | +| smart_ptr.cpp:12:5:12:18 | SideEffect | ~m10_4 | | smart_ptr.cpp:12:20:12:23 | Address | &:r12_6 | | smart_ptr.cpp:12:20:12:23 | CallTarget | func:r12_3 | | smart_ptr.cpp:12:20:12:27 | Address | &:r12_2 | @@ -8578,19 +8431,19 @@ | smart_ptr.cpp:12:20:12:27 | ChiTotal | total:m10_8 | | smart_ptr.cpp:12:20:12:27 | Load | m12_8 | | smart_ptr.cpp:12:20:12:27 | SideEffect | ~m10_8 | -| smart_ptr.cpp:12:20:12:28 | Load | m11_9 | +| smart_ptr.cpp:12:20:12:28 | Load | m11_7 | | smart_ptr.cpp:12:20:12:28 | StoreValue | r12_7 | | smart_ptr.cpp:12:25:12:26 | Arg(0) | 0:r12_5 | | smart_ptr.cpp:12:25:12:26 | Unary | r12_4 | | smart_ptr.cpp:17:6:17:24 | ChiPartial | partial:m17_3 | | smart_ptr.cpp:17:6:17:24 | ChiTotal | total:m17_2 | -| smart_ptr.cpp:17:6:17:24 | SideEffect | ~m19_16 | +| smart_ptr.cpp:17:6:17:24 | SideEffect | ~m19_14 | | smart_ptr.cpp:17:33:17:33 | Address | &:r17_5 | | smart_ptr.cpp:17:33:17:33 | Address | &:r17_5 | | smart_ptr.cpp:17:33:17:33 | Address | &:r17_7 | | smart_ptr.cpp:17:33:17:33 | Address | &:r17_7 | | smart_ptr.cpp:17:33:17:33 | Load | m17_6 | -| smart_ptr.cpp:17:33:17:33 | SideEffect | m19_19 | +| smart_ptr.cpp:17:33:17:33 | SideEffect | m19_17 | | smart_ptr.cpp:18:23:18:24 | Address | &:r18_1 | | smart_ptr.cpp:18:23:18:24 | Address | &:r18_1 | | smart_ptr.cpp:18:23:18:24 | Arg(this) | this:r18_1 | @@ -8602,149 +8455,131 @@ | smart_ptr.cpp:18:26:18:27 | ChiTotal | total:m17_4 | | smart_ptr.cpp:18:26:18:27 | SideEffect | ~m17_4 | | smart_ptr.cpp:19:5:19:18 | CallTarget | func:r19_1 | -| smart_ptr.cpp:19:5:19:18 | ChiPartial | partial:m19_15 | -| smart_ptr.cpp:19:5:19:18 | ChiTotal | total:m19_10 | -| smart_ptr.cpp:19:5:19:18 | SideEffect | ~m19_10 | +| smart_ptr.cpp:19:5:19:18 | ChiPartial | partial:m19_13 | +| smart_ptr.cpp:19:5:19:18 | ChiTotal | total:m18_8 | +| smart_ptr.cpp:19:5:19:18 | SideEffect | ~m18_8 | | smart_ptr.cpp:19:20:19:21 | Address | &:r19_2 | | smart_ptr.cpp:19:20:19:21 | Address | &:r19_2 | | smart_ptr.cpp:19:20:19:21 | Address | &:r19_2 | | smart_ptr.cpp:19:20:19:21 | Address | &:r19_7 | -| smart_ptr.cpp:19:20:19:21 | Address | &:r19_13 | -| smart_ptr.cpp:19:20:19:21 | Address | &:r19_13 | +| smart_ptr.cpp:19:20:19:21 | Address | &:r19_11 | +| smart_ptr.cpp:19:20:19:21 | Address | &:r19_11 | | smart_ptr.cpp:19:20:19:21 | Arg(0) | 0:r19_7 | -| smart_ptr.cpp:19:20:19:21 | Arg(0) | 0:r19_13 | +| smart_ptr.cpp:19:20:19:21 | Arg(0) | 0:r19_11 | | smart_ptr.cpp:19:20:19:21 | Arg(this) | this:r19_2 | | smart_ptr.cpp:19:20:19:21 | CallTarget | func:r19_4 | -| smart_ptr.cpp:19:20:19:21 | ChiPartial | partial:m19_9 | -| smart_ptr.cpp:19:20:19:21 | ChiPartial | partial:m19_18 | +| smart_ptr.cpp:19:20:19:21 | ChiPartial | partial:m19_16 | | smart_ptr.cpp:19:20:19:21 | ChiTotal | total:m17_8 | -| smart_ptr.cpp:19:20:19:21 | ChiTotal | total:m18_8 | -| smart_ptr.cpp:19:20:19:21 | Load | m19_12 | +| smart_ptr.cpp:19:20:19:21 | Load | m19_10 | | smart_ptr.cpp:19:20:19:21 | SideEffect | m18_9 | | smart_ptr.cpp:19:20:19:21 | SideEffect | ~m17_8 | -| smart_ptr.cpp:19:20:19:21 | SideEffect | ~m18_8 | | smart_ptr.cpp:19:20:19:21 | Unary | r19_5 | | smart_ptr.cpp:19:20:19:21 | Unary | r19_6 | | smart_ptr.cpp:28:6:28:27 | ChiPartial | partial:m28_3 | | smart_ptr.cpp:28:6:28:27 | ChiTotal | total:m28_2 | -| smart_ptr.cpp:28:6:28:27 | SideEffect | ~m47_16 | +| smart_ptr.cpp:28:6:28:27 | SideEffect | ~m47_14 | | smart_ptr.cpp:29:27:29:38 | Address | &:r29_1 | | smart_ptr.cpp:31:5:31:24 | CallTarget | func:r31_1 | -| smart_ptr.cpp:31:5:31:24 | ChiPartial | partial:m31_15 | -| smart_ptr.cpp:31:5:31:24 | ChiTotal | total:m31_10 | -| smart_ptr.cpp:31:5:31:24 | SideEffect | ~m31_10 | +| smart_ptr.cpp:31:5:31:24 | ChiPartial | partial:m31_13 | +| smart_ptr.cpp:31:5:31:24 | ChiTotal | total:m28_4 | +| smart_ptr.cpp:31:5:31:24 | SideEffect | ~m28_4 | | smart_ptr.cpp:31:26:31:37 | Address | &:r31_2 | | smart_ptr.cpp:31:26:31:37 | Address | &:r31_2 | | smart_ptr.cpp:31:26:31:37 | Address | &:r31_2 | | smart_ptr.cpp:31:26:31:37 | Address | &:r31_7 | -| smart_ptr.cpp:31:26:31:37 | Address | &:r31_13 | +| smart_ptr.cpp:31:26:31:37 | Address | &:r31_11 | | smart_ptr.cpp:31:26:31:37 | Arg(0) | 0:r31_7 | -| smart_ptr.cpp:31:26:31:37 | Arg(0) | 0:r31_13 | +| smart_ptr.cpp:31:26:31:37 | Arg(0) | 0:r31_11 | | smart_ptr.cpp:31:26:31:37 | Arg(this) | this:r31_2 | | smart_ptr.cpp:31:26:31:37 | CallTarget | func:r31_4 | -| smart_ptr.cpp:31:26:31:37 | ChiPartial | partial:m31_9 | -| smart_ptr.cpp:31:26:31:37 | ChiTotal | total:m28_4 | -| smart_ptr.cpp:31:26:31:37 | Load | m31_12 | +| smart_ptr.cpp:31:26:31:37 | Load | m31_10 | | smart_ptr.cpp:31:26:31:37 | SideEffect | m29_2 | -| smart_ptr.cpp:31:26:31:37 | SideEffect | ~m28_4 | -| smart_ptr.cpp:31:26:31:37 | SideEffect | ~m31_16 | +| smart_ptr.cpp:31:26:31:37 | SideEffect | ~m31_14 | | smart_ptr.cpp:31:26:31:37 | Unary | r31_5 | | smart_ptr.cpp:31:26:31:37 | Unary | r31_6 | | smart_ptr.cpp:33:28:33:47 | Address | &:r33_1 | | smart_ptr.cpp:35:5:35:28 | CallTarget | func:r35_1 | -| smart_ptr.cpp:35:5:35:28 | ChiPartial | partial:m35_15 | -| smart_ptr.cpp:35:5:35:28 | ChiTotal | total:m35_10 | -| smart_ptr.cpp:35:5:35:28 | SideEffect | ~m35_10 | +| smart_ptr.cpp:35:5:35:28 | ChiPartial | partial:m35_13 | +| smart_ptr.cpp:35:5:35:28 | ChiTotal | total:m31_14 | +| smart_ptr.cpp:35:5:35:28 | SideEffect | ~m31_14 | | smart_ptr.cpp:35:30:35:49 | Address | &:r35_2 | | smart_ptr.cpp:35:30:35:49 | Address | &:r35_2 | | smart_ptr.cpp:35:30:35:49 | Address | &:r35_2 | | smart_ptr.cpp:35:30:35:49 | Address | &:r35_7 | -| smart_ptr.cpp:35:30:35:49 | Address | &:r35_13 | -| smart_ptr.cpp:35:30:35:49 | Address | &:r35_13 | +| smart_ptr.cpp:35:30:35:49 | Address | &:r35_11 | +| smart_ptr.cpp:35:30:35:49 | Address | &:r35_11 | | smart_ptr.cpp:35:30:35:49 | Arg(0) | 0:r35_7 | -| smart_ptr.cpp:35:30:35:49 | Arg(0) | 0:r35_13 | +| smart_ptr.cpp:35:30:35:49 | Arg(0) | 0:r35_11 | | smart_ptr.cpp:35:30:35:49 | Arg(this) | this:r35_2 | | smart_ptr.cpp:35:30:35:49 | CallTarget | func:r35_4 | -| smart_ptr.cpp:35:30:35:49 | ChiPartial | partial:m35_9 | -| smart_ptr.cpp:35:30:35:49 | ChiPartial | partial:m35_18 | -| smart_ptr.cpp:35:30:35:49 | ChiTotal | total:m31_16 | -| smart_ptr.cpp:35:30:35:49 | ChiTotal | total:m35_16 | -| smart_ptr.cpp:35:30:35:49 | Load | m35_12 | +| smart_ptr.cpp:35:30:35:49 | ChiPartial | partial:m35_16 | +| smart_ptr.cpp:35:30:35:49 | ChiTotal | total:m35_14 | +| smart_ptr.cpp:35:30:35:49 | Load | m35_10 | | smart_ptr.cpp:35:30:35:49 | SideEffect | m33_2 | -| smart_ptr.cpp:35:30:35:49 | SideEffect | ~m31_16 | -| smart_ptr.cpp:35:30:35:49 | SideEffect | ~m35_16 | +| smart_ptr.cpp:35:30:35:49 | SideEffect | ~m35_14 | | smart_ptr.cpp:35:30:35:49 | Unary | r35_5 | | smart_ptr.cpp:35:30:35:49 | Unary | r35_6 | | smart_ptr.cpp:37:39:37:53 | Address | &:r37_1 | | smart_ptr.cpp:39:5:39:35 | CallTarget | func:r39_1 | -| smart_ptr.cpp:39:5:39:35 | ChiPartial | partial:m39_15 | -| smart_ptr.cpp:39:5:39:35 | ChiTotal | total:m39_10 | -| smart_ptr.cpp:39:5:39:35 | SideEffect | ~m39_10 | +| smart_ptr.cpp:39:5:39:35 | ChiPartial | partial:m39_13 | +| smart_ptr.cpp:39:5:39:35 | ChiTotal | total:m35_17 | +| smart_ptr.cpp:39:5:39:35 | SideEffect | ~m35_17 | | smart_ptr.cpp:39:37:39:51 | Address | &:r39_2 | | smart_ptr.cpp:39:37:39:51 | Address | &:r39_2 | | smart_ptr.cpp:39:37:39:51 | Address | &:r39_2 | | smart_ptr.cpp:39:37:39:51 | Address | &:r39_7 | -| smart_ptr.cpp:39:37:39:51 | Address | &:r39_13 | -| smart_ptr.cpp:39:37:39:51 | Address | &:r39_13 | +| smart_ptr.cpp:39:37:39:51 | Address | &:r39_11 | +| smart_ptr.cpp:39:37:39:51 | Address | &:r39_11 | | smart_ptr.cpp:39:37:39:51 | Arg(0) | 0:r39_7 | -| smart_ptr.cpp:39:37:39:51 | Arg(0) | 0:r39_13 | +| smart_ptr.cpp:39:37:39:51 | Arg(0) | 0:r39_11 | | smart_ptr.cpp:39:37:39:51 | Arg(this) | this:r39_2 | | smart_ptr.cpp:39:37:39:51 | CallTarget | func:r39_4 | -| smart_ptr.cpp:39:37:39:51 | ChiPartial | partial:m39_9 | -| smart_ptr.cpp:39:37:39:51 | ChiPartial | partial:m39_18 | -| smart_ptr.cpp:39:37:39:51 | ChiTotal | total:m35_19 | -| smart_ptr.cpp:39:37:39:51 | ChiTotal | total:m39_16 | -| smart_ptr.cpp:39:37:39:51 | Load | m39_12 | +| smart_ptr.cpp:39:37:39:51 | ChiPartial | partial:m39_16 | +| smart_ptr.cpp:39:37:39:51 | ChiTotal | total:m39_14 | +| smart_ptr.cpp:39:37:39:51 | Load | m39_10 | | smart_ptr.cpp:39:37:39:51 | SideEffect | m37_2 | -| smart_ptr.cpp:39:37:39:51 | SideEffect | ~m35_19 | -| smart_ptr.cpp:39:37:39:51 | SideEffect | ~m39_16 | +| smart_ptr.cpp:39:37:39:51 | SideEffect | ~m39_14 | | smart_ptr.cpp:39:37:39:51 | Unary | r39_5 | | smart_ptr.cpp:39:37:39:51 | Unary | r39_6 | | smart_ptr.cpp:41:39:41:53 | Address | &:r41_1 | | smart_ptr.cpp:43:5:43:35 | CallTarget | func:r43_1 | -| smart_ptr.cpp:43:5:43:35 | ChiPartial | partial:m43_15 | -| smart_ptr.cpp:43:5:43:35 | ChiTotal | total:m43_10 | -| smart_ptr.cpp:43:5:43:35 | SideEffect | ~m43_10 | +| smart_ptr.cpp:43:5:43:35 | ChiPartial | partial:m43_13 | +| smart_ptr.cpp:43:5:43:35 | ChiTotal | total:m39_17 | +| smart_ptr.cpp:43:5:43:35 | SideEffect | ~m39_17 | | smart_ptr.cpp:43:37:43:51 | Address | &:r43_2 | | smart_ptr.cpp:43:37:43:51 | Address | &:r43_2 | | smart_ptr.cpp:43:37:43:51 | Address | &:r43_2 | | smart_ptr.cpp:43:37:43:51 | Address | &:r43_7 | -| smart_ptr.cpp:43:37:43:51 | Address | &:r43_13 | -| smart_ptr.cpp:43:37:43:51 | Address | &:r43_13 | +| smart_ptr.cpp:43:37:43:51 | Address | &:r43_11 | +| smart_ptr.cpp:43:37:43:51 | Address | &:r43_11 | | smart_ptr.cpp:43:37:43:51 | Arg(0) | 0:r43_7 | -| smart_ptr.cpp:43:37:43:51 | Arg(0) | 0:r43_13 | +| smart_ptr.cpp:43:37:43:51 | Arg(0) | 0:r43_11 | | smart_ptr.cpp:43:37:43:51 | Arg(this) | this:r43_2 | | smart_ptr.cpp:43:37:43:51 | CallTarget | func:r43_4 | -| smart_ptr.cpp:43:37:43:51 | ChiPartial | partial:m43_9 | -| smart_ptr.cpp:43:37:43:51 | ChiPartial | partial:m43_18 | -| smart_ptr.cpp:43:37:43:51 | ChiTotal | total:m39_19 | -| smart_ptr.cpp:43:37:43:51 | ChiTotal | total:m43_16 | -| smart_ptr.cpp:43:37:43:51 | Load | m43_12 | +| smart_ptr.cpp:43:37:43:51 | ChiPartial | partial:m43_16 | +| smart_ptr.cpp:43:37:43:51 | ChiTotal | total:m43_14 | +| smart_ptr.cpp:43:37:43:51 | Load | m43_10 | | smart_ptr.cpp:43:37:43:51 | SideEffect | m41_2 | -| smart_ptr.cpp:43:37:43:51 | SideEffect | ~m39_19 | -| smart_ptr.cpp:43:37:43:51 | SideEffect | ~m43_16 | +| smart_ptr.cpp:43:37:43:51 | SideEffect | ~m43_14 | | smart_ptr.cpp:43:37:43:51 | Unary | r43_5 | | smart_ptr.cpp:43:37:43:51 | Unary | r43_6 | | smart_ptr.cpp:45:45:45:65 | Address | &:r45_1 | | smart_ptr.cpp:47:5:47:41 | CallTarget | func:r47_1 | -| smart_ptr.cpp:47:5:47:41 | ChiPartial | partial:m47_15 | -| smart_ptr.cpp:47:5:47:41 | ChiTotal | total:m47_10 | -| smart_ptr.cpp:47:5:47:41 | SideEffect | ~m47_10 | +| smart_ptr.cpp:47:5:47:41 | ChiPartial | partial:m47_13 | +| smart_ptr.cpp:47:5:47:41 | ChiTotal | total:m43_17 | +| smart_ptr.cpp:47:5:47:41 | SideEffect | ~m43_17 | | smart_ptr.cpp:47:43:47:63 | Address | &:r47_2 | | smart_ptr.cpp:47:43:47:63 | Address | &:r47_2 | | smart_ptr.cpp:47:43:47:63 | Address | &:r47_2 | | smart_ptr.cpp:47:43:47:63 | Address | &:r47_7 | -| smart_ptr.cpp:47:43:47:63 | Address | &:r47_13 | +| smart_ptr.cpp:47:43:47:63 | Address | &:r47_11 | | smart_ptr.cpp:47:43:47:63 | Arg(0) | 0:r47_7 | -| smart_ptr.cpp:47:43:47:63 | Arg(0) | 0:r47_13 | +| smart_ptr.cpp:47:43:47:63 | Arg(0) | 0:r47_11 | | smart_ptr.cpp:47:43:47:63 | Arg(this) | this:r47_2 | | smart_ptr.cpp:47:43:47:63 | CallTarget | func:r47_4 | -| smart_ptr.cpp:47:43:47:63 | ChiPartial | partial:m47_9 | -| smart_ptr.cpp:47:43:47:63 | ChiTotal | total:m43_19 | -| smart_ptr.cpp:47:43:47:63 | Load | m47_12 | +| smart_ptr.cpp:47:43:47:63 | Load | m47_10 | | smart_ptr.cpp:47:43:47:63 | SideEffect | m45_2 | -| smart_ptr.cpp:47:43:47:63 | SideEffect | ~m43_19 | -| smart_ptr.cpp:47:43:47:63 | SideEffect | ~m47_16 | +| smart_ptr.cpp:47:43:47:63 | SideEffect | ~m47_14 | | smart_ptr.cpp:47:43:47:63 | Unary | r47_5 | | smart_ptr.cpp:47:43:47:63 | Unary | r47_6 | | struct_init.cpp:9:13:9:25 | Left | r9_3 | diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected index 147c10b7c7f7..bcb0b282640f 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected @@ -1050,46 +1050,36 @@ ssa.cpp: # 240| r240_3(glval) = FunctionAddress[Constructible] : # 240| r240_4(int) = Constant[1] : # 240| v240_5(void) = Call[Constructible] : func:r240_3, this:r240_1, 0:r240_4 -# 240| m240_6(unknown) = ^CallSideEffect : ~m239_4 -# 240| m240_7(unknown) = Chi : total:m239_4, partial:m240_6 -# 240| m240_8(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r240_1 -# 240| m240_9(Constructible) = Chi : total:m240_2, partial:m240_8 +# 240| m240_6(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r240_1 +# 240| m240_7(Constructible) = Chi : total:m240_2, partial:m240_6 # 241| r241_1(glval) = VariableAddress[c] : # 241| r241_2(glval) = FunctionAddress[g] : # 241| v241_3(void) = Call[g] : func:r241_2, this:r241_1 -# 241| m241_4(unknown) = ^CallSideEffect : ~m240_7 -# 241| m241_5(unknown) = Chi : total:m240_7, partial:m241_4 -# 241| v241_6(void) = ^IndirectReadSideEffect[-1] : &:r241_1, m240_9 -# 241| m241_7(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r241_1 -# 241| m241_8(Constructible) = Chi : total:m240_9, partial:m241_7 +# 241| v241_4(void) = ^IndirectReadSideEffect[-1] : &:r241_1, m240_7 +# 241| m241_5(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r241_1 +# 241| m241_6(Constructible) = Chi : total:m240_7, partial:m241_5 # 242| r242_1(glval) = VariableAddress[c] : # 242| r242_2(glval) = FunctionAddress[g] : # 242| v242_3(void) = Call[g] : func:r242_2, this:r242_1 -# 242| m242_4(unknown) = ^CallSideEffect : ~m241_5 -# 242| m242_5(unknown) = Chi : total:m241_5, partial:m242_4 -# 242| v242_6(void) = ^IndirectReadSideEffect[-1] : &:r242_1, m241_8 -# 242| m242_7(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r242_1 -# 242| m242_8(Constructible) = Chi : total:m241_8, partial:m242_7 +# 242| v242_4(void) = ^IndirectReadSideEffect[-1] : &:r242_1, m241_6 +# 242| m242_5(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r242_1 +# 242| m242_6(Constructible) = Chi : total:m241_6, partial:m242_5 # 243| r243_1(glval) = VariableAddress[c2] : # 243| m243_2(Constructible) = Uninitialized[c2] : &:r243_1 # 243| r243_3(glval) = FunctionAddress[Constructible] : # 243| r243_4(int) = Constant[2] : # 243| v243_5(void) = Call[Constructible] : func:r243_3, this:r243_1, 0:r243_4 -# 243| m243_6(unknown) = ^CallSideEffect : ~m242_5 -# 243| m243_7(unknown) = Chi : total:m242_5, partial:m243_6 -# 243| m243_8(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r243_1 -# 243| m243_9(Constructible) = Chi : total:m243_2, partial:m243_8 +# 243| m243_6(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r243_1 +# 243| m243_7(Constructible) = Chi : total:m243_2, partial:m243_6 # 244| r244_1(glval) = VariableAddress[c2] : # 244| r244_2(glval) = FunctionAddress[g] : # 244| v244_3(void) = Call[g] : func:r244_2, this:r244_1 -# 244| m244_4(unknown) = ^CallSideEffect : ~m243_7 -# 244| m244_5(unknown) = Chi : total:m243_7, partial:m244_4 -# 244| v244_6(void) = ^IndirectReadSideEffect[-1] : &:r244_1, m243_9 -# 244| m244_7(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r244_1 -# 244| m244_8(Constructible) = Chi : total:m243_9, partial:m244_7 +# 244| v244_4(void) = ^IndirectReadSideEffect[-1] : &:r244_1, m243_7 +# 244| m244_5(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r244_1 +# 244| m244_6(Constructible) = Chi : total:m243_7, partial:m244_5 # 245| v245_1(void) = NoOp : # 239| v239_5(void) = ReturnVoid : -# 239| v239_6(void) = AliasedUse : ~m244_5 +# 239| v239_6(void) = AliasedUse : m239_3 # 239| v239_7(void) = ExitFunction : # 247| char* VoidStarIndirectParameters(char*, int) @@ -1391,43 +1381,37 @@ ssa.cpp: # 294| r294_18(glval) = VariableAddress[x] : # 294| r294_19(int) = Load[x] : &:r294_18, m291_6 # 294| v294_20(void) = Call[A] : func:r294_17, this:r294_16, 0:r294_19 -# 294| m294_21(unknown) = ^CallSideEffect : ~m294_14 -# 294| m294_22(unknown) = Chi : total:m294_14, partial:m294_21 -# 294| m294_23(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_16 -# 294| m294_24(unknown) = Chi : total:m294_15, partial:m294_23 -# 294| v294_25(void) = Call[A] : func:r294_9, this:r294_8, 0:r294_16 -# 294| m294_26(unknown) = ^CallSideEffect : ~m294_22 -# 294| m294_27(unknown) = Chi : total:m294_22, partial:m294_26 -# 294| v294_28(void) = ^BufferReadSideEffect[0] : &:r294_16, ~m294_24 -# 294| m294_29(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_8 -# 294| m294_30(unknown) = Chi : total:m294_7, partial:m294_29 -# 294| m294_31(unknown) = ^BufferMayWriteSideEffect[0] : &:r294_16 -# 294| m294_32(unknown) = Chi : total:m294_24, partial:m294_31 -# 294| r294_33(glval) = FieldAddress[i] : r294_8 -# 294| r294_34(int) = Load[?] : &:r294_33, ~m294_30 -# 294| m294_35(int) = Store[j] : &:r294_1, r294_34 +# 294| m294_21(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_16 +# 294| m294_22(unknown) = Chi : total:m294_15, partial:m294_21 +# 294| v294_23(void) = Call[A] : func:r294_9, this:r294_8, 0:r294_16 +# 294| v294_24(void) = ^BufferReadSideEffect[0] : &:r294_16, ~m294_22 +# 294| m294_25(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_8 +# 294| m294_26(unknown) = Chi : total:m294_7, partial:m294_25 +# 294| m294_27(unknown) = ^BufferMayWriteSideEffect[0] : &:r294_16 +# 294| m294_28(unknown) = Chi : total:m294_22, partial:m294_27 +# 294| r294_29(glval) = FieldAddress[i] : r294_8 +# 294| r294_30(int) = Load[?] : &:r294_29, ~m294_26 +# 294| m294_31(int) = Store[j] : &:r294_1, r294_30 # 295| r295_1(glval) = VariableAddress[a] : # 295| r295_2(glval) = FunctionAddress[operator new] : # 295| r295_3(unsigned long) = Constant[4] : # 295| r295_4(void *) = Call[operator new] : func:r295_2, 0:r295_3 -# 295| m295_5(unknown) = ^CallSideEffect : ~m294_27 -# 295| m295_6(unknown) = Chi : total:m294_27, partial:m295_5 +# 295| m295_5(unknown) = ^CallSideEffect : ~m294_14 +# 295| m295_6(unknown) = Chi : total:m294_14, partial:m295_5 # 295| m295_7(unknown) = ^InitializeDynamicAllocation : &:r295_4 # 295| r295_8(A *) = Convert : r295_4 # 295| r295_9(glval) = FunctionAddress[A] : # 295| v295_10(void) = Call[A] : func:r295_9, this:r295_8 -# 295| m295_11(unknown) = ^CallSideEffect : ~m295_6 -# 295| m295_12(unknown) = Chi : total:m295_6, partial:m295_11 -# 295| m295_13(A) = ^IndirectMayWriteSideEffect[-1] : &:r295_8 -# 295| m295_14(unknown) = Chi : total:m295_7, partial:m295_13 -# 295| m295_15(A *) = Store[a] : &:r295_1, r295_8 +# 295| m295_11(A) = ^IndirectMayWriteSideEffect[-1] : &:r295_8 +# 295| m295_12(unknown) = Chi : total:m295_7, partial:m295_11 +# 295| m295_13(A *) = Store[a] : &:r295_1, r295_8 # 296| r296_1(glval) = VariableAddress[#return] : # 296| r296_2(glval) = VariableAddress[p] : # 296| r296_3(Point *) = Load[p] : &:r296_2, m292_9 # 296| m296_4(Point *) = Store[#return] : &:r296_1, r296_3 # 291| r291_7(glval) = VariableAddress[#return] : # 291| v291_8(void) = ReturnValue : &:r291_7, m296_4 -# 291| v291_9(void) = AliasedUse : ~m295_12 +# 291| v291_9(void) = AliasedUse : ~m295_6 # 291| v291_10(void) = ExitFunction : # 301| int main(int, char**) diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected index 396b7532d68d..e6669b18ae5b 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected @@ -1045,46 +1045,36 @@ ssa.cpp: # 240| r240_3(glval) = FunctionAddress[Constructible] : # 240| r240_4(int) = Constant[1] : # 240| v240_5(void) = Call[Constructible] : func:r240_3, this:r240_1, 0:r240_4 -# 240| m240_6(unknown) = ^CallSideEffect : ~m239_4 -# 240| m240_7(unknown) = Chi : total:m239_4, partial:m240_6 -# 240| m240_8(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r240_1 -# 240| m240_9(Constructible) = Chi : total:m240_2, partial:m240_8 +# 240| m240_6(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r240_1 +# 240| m240_7(Constructible) = Chi : total:m240_2, partial:m240_6 # 241| r241_1(glval) = VariableAddress[c] : # 241| r241_2(glval) = FunctionAddress[g] : # 241| v241_3(void) = Call[g] : func:r241_2, this:r241_1 -# 241| m241_4(unknown) = ^CallSideEffect : ~m240_7 -# 241| m241_5(unknown) = Chi : total:m240_7, partial:m241_4 -# 241| v241_6(void) = ^IndirectReadSideEffect[-1] : &:r241_1, m240_9 -# 241| m241_7(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r241_1 -# 241| m241_8(Constructible) = Chi : total:m240_9, partial:m241_7 +# 241| v241_4(void) = ^IndirectReadSideEffect[-1] : &:r241_1, m240_7 +# 241| m241_5(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r241_1 +# 241| m241_6(Constructible) = Chi : total:m240_7, partial:m241_5 # 242| r242_1(glval) = VariableAddress[c] : # 242| r242_2(glval) = FunctionAddress[g] : # 242| v242_3(void) = Call[g] : func:r242_2, this:r242_1 -# 242| m242_4(unknown) = ^CallSideEffect : ~m241_5 -# 242| m242_5(unknown) = Chi : total:m241_5, partial:m242_4 -# 242| v242_6(void) = ^IndirectReadSideEffect[-1] : &:r242_1, m241_8 -# 242| m242_7(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r242_1 -# 242| m242_8(Constructible) = Chi : total:m241_8, partial:m242_7 +# 242| v242_4(void) = ^IndirectReadSideEffect[-1] : &:r242_1, m241_6 +# 242| m242_5(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r242_1 +# 242| m242_6(Constructible) = Chi : total:m241_6, partial:m242_5 # 243| r243_1(glval) = VariableAddress[c2] : # 243| m243_2(Constructible) = Uninitialized[c2] : &:r243_1 # 243| r243_3(glval) = FunctionAddress[Constructible] : # 243| r243_4(int) = Constant[2] : # 243| v243_5(void) = Call[Constructible] : func:r243_3, this:r243_1, 0:r243_4 -# 243| m243_6(unknown) = ^CallSideEffect : ~m242_5 -# 243| m243_7(unknown) = Chi : total:m242_5, partial:m243_6 -# 243| m243_8(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r243_1 -# 243| m243_9(Constructible) = Chi : total:m243_2, partial:m243_8 +# 243| m243_6(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r243_1 +# 243| m243_7(Constructible) = Chi : total:m243_2, partial:m243_6 # 244| r244_1(glval) = VariableAddress[c2] : # 244| r244_2(glval) = FunctionAddress[g] : # 244| v244_3(void) = Call[g] : func:r244_2, this:r244_1 -# 244| m244_4(unknown) = ^CallSideEffect : ~m243_7 -# 244| m244_5(unknown) = Chi : total:m243_7, partial:m244_4 -# 244| v244_6(void) = ^IndirectReadSideEffect[-1] : &:r244_1, m243_9 -# 244| m244_7(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r244_1 -# 244| m244_8(Constructible) = Chi : total:m243_9, partial:m244_7 +# 244| v244_4(void) = ^IndirectReadSideEffect[-1] : &:r244_1, m243_7 +# 244| m244_5(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r244_1 +# 244| m244_6(Constructible) = Chi : total:m243_7, partial:m244_5 # 245| v245_1(void) = NoOp : # 239| v239_5(void) = ReturnVoid : -# 239| v239_6(void) = AliasedUse : ~m244_5 +# 239| v239_6(void) = AliasedUse : m239_3 # 239| v239_7(void) = ExitFunction : # 247| char* VoidStarIndirectParameters(char*, int) @@ -1385,43 +1375,37 @@ ssa.cpp: # 294| r294_18(glval) = VariableAddress[x] : # 294| r294_19(int) = Load[x] : &:r294_18, m291_6 # 294| v294_20(void) = Call[A] : func:r294_17, this:r294_16, 0:r294_19 -# 294| m294_21(unknown) = ^CallSideEffect : ~m294_14 -# 294| m294_22(unknown) = Chi : total:m294_14, partial:m294_21 -# 294| m294_23(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_16 -# 294| m294_24(unknown) = Chi : total:m294_15, partial:m294_23 -# 294| v294_25(void) = Call[A] : func:r294_9, this:r294_8, 0:r294_16 -# 294| m294_26(unknown) = ^CallSideEffect : ~m294_22 -# 294| m294_27(unknown) = Chi : total:m294_22, partial:m294_26 -# 294| v294_28(void) = ^BufferReadSideEffect[0] : &:r294_16, ~m294_24 -# 294| m294_29(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_8 -# 294| m294_30(unknown) = Chi : total:m294_7, partial:m294_29 -# 294| m294_31(unknown) = ^BufferMayWriteSideEffect[0] : &:r294_16 -# 294| m294_32(unknown) = Chi : total:m294_24, partial:m294_31 -# 294| r294_33(glval) = FieldAddress[i] : r294_8 -# 294| r294_34(int) = Load[?] : &:r294_33, ~m294_30 -# 294| m294_35(int) = Store[j] : &:r294_1, r294_34 +# 294| m294_21(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_16 +# 294| m294_22(unknown) = Chi : total:m294_15, partial:m294_21 +# 294| v294_23(void) = Call[A] : func:r294_9, this:r294_8, 0:r294_16 +# 294| v294_24(void) = ^BufferReadSideEffect[0] : &:r294_16, ~m294_22 +# 294| m294_25(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_8 +# 294| m294_26(unknown) = Chi : total:m294_7, partial:m294_25 +# 294| m294_27(unknown) = ^BufferMayWriteSideEffect[0] : &:r294_16 +# 294| m294_28(unknown) = Chi : total:m294_22, partial:m294_27 +# 294| r294_29(glval) = FieldAddress[i] : r294_8 +# 294| r294_30(int) = Load[?] : &:r294_29, ~m294_26 +# 294| m294_31(int) = Store[j] : &:r294_1, r294_30 # 295| r295_1(glval) = VariableAddress[a] : # 295| r295_2(glval) = FunctionAddress[operator new] : # 295| r295_3(unsigned long) = Constant[4] : # 295| r295_4(void *) = Call[operator new] : func:r295_2, 0:r295_3 -# 295| m295_5(unknown) = ^CallSideEffect : ~m294_27 -# 295| m295_6(unknown) = Chi : total:m294_27, partial:m295_5 +# 295| m295_5(unknown) = ^CallSideEffect : ~m294_14 +# 295| m295_6(unknown) = Chi : total:m294_14, partial:m295_5 # 295| m295_7(unknown) = ^InitializeDynamicAllocation : &:r295_4 # 295| r295_8(A *) = Convert : r295_4 # 295| r295_9(glval) = FunctionAddress[A] : # 295| v295_10(void) = Call[A] : func:r295_9, this:r295_8 -# 295| m295_11(unknown) = ^CallSideEffect : ~m295_6 -# 295| m295_12(unknown) = Chi : total:m295_6, partial:m295_11 -# 295| m295_13(A) = ^IndirectMayWriteSideEffect[-1] : &:r295_8 -# 295| m295_14(unknown) = Chi : total:m295_7, partial:m295_13 -# 295| m295_15(A *) = Store[a] : &:r295_1, r295_8 +# 295| m295_11(A) = ^IndirectMayWriteSideEffect[-1] : &:r295_8 +# 295| m295_12(unknown) = Chi : total:m295_7, partial:m295_11 +# 295| m295_13(A *) = Store[a] : &:r295_1, r295_8 # 296| r296_1(glval) = VariableAddress[#return] : # 296| r296_2(glval) = VariableAddress[p] : # 296| r296_3(Point *) = Load[p] : &:r296_2, m292_9 # 296| m296_4(Point *) = Store[#return] : &:r296_1, r296_3 # 291| r291_7(glval) = VariableAddress[#return] : # 291| v291_8(void) = ReturnValue : &:r291_7, m296_4 -# 291| v291_9(void) = AliasedUse : ~m295_12 +# 291| v291_9(void) = AliasedUse : ~m295_6 # 291| v291_10(void) = ExitFunction : # 301| int main(int, char**) From c09c38c9a8535c5606045b0dfe5f31831db531a5 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Fri, 29 Jul 2022 12:08:52 -0400 Subject: [PATCH 06/19] C++/C#: sync for IR side effect removal --- .../aliased_ssa/internal/SSAConstruction.qll | 11 ++--------- .../internal/SSAConstructionInternal.qll | 11 +++++++++++ .../ir/implementation/internal/TInstruction.qll | 2 +- .../unaliased_ssa/internal/SSAConstruction.qll | 17 +++++++++++------ .../internal/SSAConstructionInternal.qll | 6 ++++++ .../implementation/internal/AliasedSSAStub.qll | 2 ++ .../ir/implementation/internal/TInstruction.qll | 1 + .../unaliased_ssa/internal/SSAConstruction.qll | 17 +++++++++++------ .../internal/SSAConstructionInternal.qll | 6 ++++++ 9 files changed, 51 insertions(+), 22 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll index d5e2c1595ac4..c1329b9b8f77 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll @@ -9,13 +9,6 @@ private import SSAInstructions private import SSAOperands private import NewIR -private class OldBlock = Reachability::ReachableBlock; - -private class OldInstruction extends Reachability::ReachableInstruction { - OldInstruction() { not Elim::removeableSideEffect(this)} -} - -private import SideEffectElimination as Elim import Cached cached @@ -63,7 +56,7 @@ private module Cached { predicate hasInstruction(TStageInstruction instr) { instr instanceof TRawInstruction and instr instanceof OldInstruction and - not Elim::removeableSideEffect(instr) + not removedInstruction(instr) or instr = phiInstruction(_, _) or @@ -388,7 +381,7 @@ private module Cached { if Reachability::isInfeasibleInstructionSuccessor(oldInstruction, kind) then result = unreachedInstruction(instruction.getEnclosingIRFunction()) else - if Elim::removeableSideEffect(oldInstruction.getSuccessor(kind)) + if removedInstruction(oldInstruction.getSuccessor(kind)) then // the only removed nodes are side-effect writes, but those may have Chi nodes // skip to the following instruction in the old IR, which won't be removed diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstructionInternal.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstructionInternal.qll index 74919a578701..2d5dccc773a7 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstructionInternal.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstructionInternal.qll @@ -6,3 +6,14 @@ import semmle.code.cpp.ir.implementation.internal.TInstruction::AliasedSsaInstru import semmle.code.cpp.ir.internal.IRCppLanguage as Language import AliasedSSA as Alias import semmle.code.cpp.ir.implementation.internal.TOperand::AliasedSsaOperands as SSAOperands +private import SideEffectElimination as Elim + +predicate removedInstruction(Reachability::ReachableInstruction instr) { + Elim::removeableSideEffect(instr) +} + +class OldBlock = Reachability::ReachableBlock; + +class OldInstruction extends Reachability::ReachableInstruction { + OldInstruction() { not Elim::removeableSideEffect(this) } +} diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/TInstruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/TInstruction.qll index b41b4818bdb6..6dd4bc0c1d32 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/TInstruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/TInstruction.qll @@ -34,7 +34,7 @@ newtype TInstruction = AliasedSSA::SSA::hasPhiInstruction(blockStartInstr, memoryLocation) } or TAliasedSsaChiInstruction(TRawInstruction primaryInstruction) { - not Elim::removeableSideEffect(primaryInstruction) and + not AliasedSSA::removedInstruction(primaryInstruction) and AliasedSSA::SSA::hasChiInstruction(primaryInstruction) } or TAliasedSsaUnreachedInstruction(IRFunctionBase irFunc) { diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll index 303a96830114..c1329b9b8f77 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll @@ -9,10 +9,6 @@ private import SSAInstructions private import SSAOperands private import NewIR -private class OldBlock = Reachability::ReachableBlock; - -private class OldInstruction = Reachability::ReachableInstruction; - import Cached cached @@ -58,7 +54,9 @@ private module Cached { cached predicate hasInstruction(TStageInstruction instr) { - instr instanceof TRawInstruction and instr instanceof OldInstruction + instr instanceof TRawInstruction and + instr instanceof OldInstruction and + not removedInstruction(instr) or instr = phiInstruction(_, _) or @@ -382,7 +380,14 @@ private module Cached { ( if Reachability::isInfeasibleInstructionSuccessor(oldInstruction, kind) then result = unreachedInstruction(instruction.getEnclosingIRFunction()) - else result = getNewInstruction(oldInstruction.getSuccessor(kind)) + else + if removedInstruction(oldInstruction.getSuccessor(kind)) + then + // the only removed nodes are side-effect writes, but those may have Chi nodes + // skip to the following instruction in the old IR, which won't be removed + // if we start skipping specific side effects, this may no longer hold + result = getNewInstruction(oldInstruction.getSuccessor(kind).getSuccessor(kind)) + else result = getNewInstruction(oldInstruction.getSuccessor(kind)) ) ) or diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstructionInternal.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstructionInternal.qll index 8f64bff29f26..e0c4f4946238 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstructionInternal.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstructionInternal.qll @@ -7,3 +7,9 @@ import semmle.code.cpp.ir.implementation.internal.TInstruction::UnaliasedSsaInst import semmle.code.cpp.ir.internal.IRCppLanguage as Language import SimpleSSA as Alias import semmle.code.cpp.ir.implementation.internal.TOperand::UnaliasedSsaOperands as SSAOperands + +predicate removedInstruction(Reachability::ReachableInstruction instr) { none() } + +class OldBlock = Reachability::ReachableBlock; + +class OldInstruction = Reachability::ReachableInstruction; \ No newline at end of file diff --git a/csharp/ql/src/experimental/ir/implementation/internal/AliasedSSAStub.qll b/csharp/ql/src/experimental/ir/implementation/internal/AliasedSSAStub.qll index 0fedd38bfbd2..b650cbd138f8 100644 --- a/csharp/ql/src/experimental/ir/implementation/internal/AliasedSSAStub.qll +++ b/csharp/ql/src/experimental/ir/implementation/internal/AliasedSSAStub.qll @@ -17,3 +17,5 @@ module SSA { predicate hasUnreachedInstruction(IRFunctionBase irFunc) { none() } } + +predicate removedInstruction(TRawInstruction instr) { none() } diff --git a/csharp/ql/src/experimental/ir/implementation/internal/TInstruction.qll b/csharp/ql/src/experimental/ir/implementation/internal/TInstruction.qll index 5a7099d9fa2e..6dd4bc0c1d32 100644 --- a/csharp/ql/src/experimental/ir/implementation/internal/TInstruction.qll +++ b/csharp/ql/src/experimental/ir/implementation/internal/TInstruction.qll @@ -34,6 +34,7 @@ newtype TInstruction = AliasedSSA::SSA::hasPhiInstruction(blockStartInstr, memoryLocation) } or TAliasedSsaChiInstruction(TRawInstruction primaryInstruction) { + not AliasedSSA::removedInstruction(primaryInstruction) and AliasedSSA::SSA::hasChiInstruction(primaryInstruction) } or TAliasedSsaUnreachedInstruction(IRFunctionBase irFunc) { diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll index 303a96830114..c1329b9b8f77 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll @@ -9,10 +9,6 @@ private import SSAInstructions private import SSAOperands private import NewIR -private class OldBlock = Reachability::ReachableBlock; - -private class OldInstruction = Reachability::ReachableInstruction; - import Cached cached @@ -58,7 +54,9 @@ private module Cached { cached predicate hasInstruction(TStageInstruction instr) { - instr instanceof TRawInstruction and instr instanceof OldInstruction + instr instanceof TRawInstruction and + instr instanceof OldInstruction and + not removedInstruction(instr) or instr = phiInstruction(_, _) or @@ -382,7 +380,14 @@ private module Cached { ( if Reachability::isInfeasibleInstructionSuccessor(oldInstruction, kind) then result = unreachedInstruction(instruction.getEnclosingIRFunction()) - else result = getNewInstruction(oldInstruction.getSuccessor(kind)) + else + if removedInstruction(oldInstruction.getSuccessor(kind)) + then + // the only removed nodes are side-effect writes, but those may have Chi nodes + // skip to the following instruction in the old IR, which won't be removed + // if we start skipping specific side effects, this may no longer hold + result = getNewInstruction(oldInstruction.getSuccessor(kind).getSuccessor(kind)) + else result = getNewInstruction(oldInstruction.getSuccessor(kind)) ) ) or diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SSAConstructionInternal.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SSAConstructionInternal.qll index 005ea53b0188..771037c5795b 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SSAConstructionInternal.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SSAConstructionInternal.qll @@ -7,3 +7,9 @@ import experimental.ir.implementation.internal.TInstruction::UnaliasedSsaInstruc import experimental.ir.internal.IRCSharpLanguage as Language import SimpleSSA as Alias import experimental.ir.implementation.internal.TOperand::UnaliasedSsaOperands as SSAOperands + +predicate removedInstruction(Reachability::ReachableInstruction instr) { none() } + +class OldBlock = Reachability::ReachableBlock; + +class OldInstruction = Reachability::ReachableInstruction; \ No newline at end of file From 844aabe3d697337d7424d2bb5837b3bfb243d010 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Fri, 29 Jul 2022 14:51:09 -0400 Subject: [PATCH 07/19] C++/C#: fix join order in GVN --- .../gvn/internal/ValueNumberingInternal.qll | 10 +++++----- .../raw/gvn/internal/ValueNumberingInternal.qll | 10 +++++----- .../gvn/internal/ValueNumberingInternal.qll | 10 +++++----- .../raw/gvn/internal/ValueNumberingInternal.qll | 10 +++++----- .../gvn/internal/ValueNumberingInternal.qll | 10 +++++----- 5 files changed, 25 insertions(+), 25 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 02de941eea57..eeb7adf9a169 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 @@ -56,8 +56,8 @@ newtype TCallPartialValueNumber = 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 + callPartialValueNumber(call, index, pragma[only_bind_out](head)) and + callArgValueNumber(call, index, pragma[only_bind_into](arg)) and vn = TArgument(head, arg) ) or @@ -67,11 +67,11 @@ predicate callValueNumber(CallInstruction call, int index, TCallPartialValueNumb } predicate callPartialValueNumber(CallInstruction call, int index, TCallPartialValueNumber head) { - index = 1 and head = TNilArgument() + index = 1 and head = TNilArgument() and exists(call) or exists(TCallPartialValueNumber prev, TValueNumber prevVN | - callPartialValueNumber(call, index - 1, prev) and - callArgValueNumber(call, index - 1, prevVN) and + callPartialValueNumber(call, index - 1, pragma[only_bind_out](prev)) and + callArgValueNumber(call, index - 1, pragma[only_bind_into](prevVN)) and head = TArgument(prev, prevVN) ) } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll index 02de941eea57..eeb7adf9a169 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll @@ -56,8 +56,8 @@ newtype TCallPartialValueNumber = 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 + callPartialValueNumber(call, index, pragma[only_bind_out](head)) and + callArgValueNumber(call, index, pragma[only_bind_into](arg)) and vn = TArgument(head, arg) ) or @@ -67,11 +67,11 @@ predicate callValueNumber(CallInstruction call, int index, TCallPartialValueNumb } predicate callPartialValueNumber(CallInstruction call, int index, TCallPartialValueNumber head) { - index = 1 and head = TNilArgument() + index = 1 and head = TNilArgument() and exists(call) or exists(TCallPartialValueNumber prev, TValueNumber prevVN | - callPartialValueNumber(call, index - 1, prev) and - callArgValueNumber(call, index - 1, prevVN) and + callPartialValueNumber(call, index - 1, pragma[only_bind_out](prev)) and + callArgValueNumber(call, index - 1, pragma[only_bind_into](prevVN)) and head = TArgument(prev, prevVN) ) } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll index 02de941eea57..eeb7adf9a169 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll @@ -56,8 +56,8 @@ newtype TCallPartialValueNumber = 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 + callPartialValueNumber(call, index, pragma[only_bind_out](head)) and + callArgValueNumber(call, index, pragma[only_bind_into](arg)) and vn = TArgument(head, arg) ) or @@ -67,11 +67,11 @@ predicate callValueNumber(CallInstruction call, int index, TCallPartialValueNumb } predicate callPartialValueNumber(CallInstruction call, int index, TCallPartialValueNumber head) { - index = 1 and head = TNilArgument() + index = 1 and head = TNilArgument() and exists(call) or exists(TCallPartialValueNumber prev, TValueNumber prevVN | - callPartialValueNumber(call, index - 1, prev) and - callArgValueNumber(call, index - 1, prevVN) and + callPartialValueNumber(call, index - 1, pragma[only_bind_out](prev)) and + callArgValueNumber(call, index - 1, pragma[only_bind_into](prevVN)) and head = TArgument(prev, prevVN) ) } diff --git a/csharp/ql/src/experimental/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll b/csharp/ql/src/experimental/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll index 02de941eea57..eeb7adf9a169 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll @@ -56,8 +56,8 @@ newtype TCallPartialValueNumber = 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 + callPartialValueNumber(call, index, pragma[only_bind_out](head)) and + callArgValueNumber(call, index, pragma[only_bind_into](arg)) and vn = TArgument(head, arg) ) or @@ -67,11 +67,11 @@ predicate callValueNumber(CallInstruction call, int index, TCallPartialValueNumb } predicate callPartialValueNumber(CallInstruction call, int index, TCallPartialValueNumber head) { - index = 1 and head = TNilArgument() + index = 1 and head = TNilArgument() and exists(call) or exists(TCallPartialValueNumber prev, TValueNumber prevVN | - callPartialValueNumber(call, index - 1, prev) and - callArgValueNumber(call, index - 1, prevVN) and + callPartialValueNumber(call, index - 1, pragma[only_bind_out](prev)) and + callArgValueNumber(call, index - 1, pragma[only_bind_into](prevVN)) and head = TArgument(prev, prevVN) ) } diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll index 02de941eea57..eeb7adf9a169 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll @@ -56,8 +56,8 @@ newtype TCallPartialValueNumber = 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 + callPartialValueNumber(call, index, pragma[only_bind_out](head)) and + callArgValueNumber(call, index, pragma[only_bind_into](arg)) and vn = TArgument(head, arg) ) or @@ -67,11 +67,11 @@ predicate callValueNumber(CallInstruction call, int index, TCallPartialValueNumb } predicate callPartialValueNumber(CallInstruction call, int index, TCallPartialValueNumber head) { - index = 1 and head = TNilArgument() + index = 1 and head = TNilArgument() and exists(call) or exists(TCallPartialValueNumber prev, TValueNumber prevVN | - callPartialValueNumber(call, index - 1, prev) and - callArgValueNumber(call, index - 1, prevVN) and + callPartialValueNumber(call, index - 1, pragma[only_bind_out](prev)) and + callArgValueNumber(call, index - 1, pragma[only_bind_into](prevVN)) and head = TArgument(prev, prevVN) ) } From e0cfbb53dc74a1d283bd39fef13f8731c9dac326 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Mon, 1 Aug 2022 09:52:46 -0400 Subject: [PATCH 08/19] C++: add missing SideEffectElimination.qll --- .../internal/SideEffectElimination.qll | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SideEffectElimination.qll diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SideEffectElimination.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SideEffectElimination.qll new file mode 100644 index 000000000000..b5aa5134b471 --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SideEffectElimination.qll @@ -0,0 +1,42 @@ +import cpp as CPP +import semmle.code.cpp.ir.implementation.unaliased_ssa.IR as Unaliased +import AliasAnalysis as Alias +import AliasConfiguration as Conf +import semmle.code.cpp.models.interfaces.SideEffect as SideEffect + +private predicate noLocalSideEffectWrite(CPP::Function func) { + forall(Unaliased::AddressOperand addr | addr.getUse().getEnclosingFunction() = func | + not ( + Alias::getAddressOperandAllocation(addr) instanceof Conf::VariableAllocation and + Alias::getAddressOperandAllocation(addr).(Conf::VariableAllocation).alwaysEscapes() + ) + ) +} + +language[monotonicAggregates] +private predicate noTransitiveSideEffectWrite(CPP::Function func) { + exists(Unaliased::IRFunction irFunc | irFunc.getFunction() = func) and + noLocalSideEffectWrite(func) and + forall(Unaliased::CallInstruction call | call.getEnclosingFunction() = func | + exists(call.getStaticCallTarget()) + ) and + forall(Unaliased::CallInstruction call, CPP::Function callee | + call.getStaticCallTarget() = callee and + call.getEnclosingFunction() = func + | + noTransitiveSideEffectWrite(callee) + or + callee.(SideEffect::SideEffectFunction).hasOnlySpecificWriteSideEffects() + ) +} + +predicate removeableSideEffect(Unaliased::SideEffectInstruction instr) { + ( + instr instanceof Unaliased::CallSideEffectInstruction or + instr instanceof Unaliased::CallReadSideEffectInstruction + ) and + noTransitiveSideEffectWrite(instr + .getPrimaryInstruction() + .(Unaliased::CallInstruction) + .getStaticCallTarget()) +} From 83af49c72f2028ccff0ea23db3513e0d81c7cbba Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Mon, 1 Aug 2022 12:57:41 -0400 Subject: [PATCH 09/19] C++: respond to PR comments --- .../gvn/internal/ValueNumberingInternal.qll | 22 +++--- .../GlobalValueNumbering/ast_ir_gvn.expected | 6 +- .../diff_ir_expr.expected | 15 +--- .../GlobalValueNumbering/ir_gvn.expected | 78 ++++++++++++------- .../GlobalValueNumbering/test.cpp | 2 +- 5 files changed, 67 insertions(+), 56 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 eeb7adf9a169..4fb9bc42e827 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 @@ -44,7 +44,7 @@ newtype TValueNumber = TCallValueNumber(TCallPartialValueNumber vn) { callValueNumber(_, _, vn) } or TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) } -newtype TCallPartialValueNumber = +private newtype TCallPartialValueNumber = TNilArgument() or TArgument(TCallPartialValueNumber head, TValueNumber arg) { exists(CallInstruction call, int index | @@ -53,7 +53,7 @@ newtype TCallPartialValueNumber = ) } -predicate callValueNumber(CallInstruction call, int index, TCallPartialValueNumber vn) { +private 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, pragma[only_bind_out](head)) and @@ -61,16 +61,17 @@ predicate callValueNumber(CallInstruction call, int index, TCallPartialValueNumb vn = TArgument(head, arg) ) or + not call.getResultIRType() instanceof IRVoidType and 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() and exists(call) +private predicate callPartialValueNumber(CallInstruction call, int index, TCallPartialValueNumber head) { + index = 1 and head = TNilArgument() and not call.getResultIRType() instanceof IRVoidType or exists(TCallPartialValueNumber prev, TValueNumber prevVN | - callPartialValueNumber(call, index - 1, pragma[only_bind_out](prev)) and + callPartialValueNumber(call, index - 1, pragma[only_bind_out](prev)) and callArgValueNumber(call, index - 1, pragma[only_bind_into](prevVN)) and head = TArgument(prev, prevVN) ) @@ -78,7 +79,8 @@ predicate callPartialValueNumber(CallInstruction call, int index, TCallPartialVa /** */ -predicate callArgValueNumber(CallInstruction call, int index, TValueNumber arg) { +private predicate callArgValueNumber(CallInstruction call, int index, TValueNumber arg) { + not call.getResultIRType() instanceof IRVoidType and exists(Instruction instr | callArgRank(call, index, instr) and arg = tvalueNumber(instr) @@ -89,21 +91,21 @@ predicate callArgValueNumber(CallInstruction call, int index, TValueNumber arg) * 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) { +private predicate callArgRank(CallInstruction call, int index, Instruction arg) { arg = rank[index](int argIndex, boolean isEffect, Instruction instr | exists(CallSideEffectInstruction cse | cse.getPrimaryInstruction() = call and cse.getSideEffectOperand().getAnyDef() = instr and argIndex = -2 and - isEffect = false + isEffect = true ) or exists(CallReadSideEffectInstruction cse | cse.getPrimaryInstruction() = call and cse.getSideEffectOperand().getAnyDef() = instr and argIndex = -2 and - isEffect = false + isEffect = true ) or instr = call.getThisArgument() and @@ -115,7 +117,7 @@ predicate callArgRank(CallInstruction call, int index, Instruction arg) { or exists(ReadSideEffectInstruction read | read.getPrimaryInstruction() = call and - read.getSideEffectOperand().getDef() = instr and + read.getSideEffectOperand().getAnyDef() = instr and read.getIndex() = argIndex and isEffect = true ) 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 0671cdf1db90..2c9bfea9b850 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,7 +12,6 @@ | 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 | @@ -29,7 +28,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 80:c9-c17 | +| test.cpp:77:20:77:28 | GVN | 77:c20-c28 79:c7-c7 | | 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 | @@ -45,12 +44,11 @@ | 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:11:166:16 | GVN | 166:c11-c16 167: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 d9232b532454..127e1781f839 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,8 +10,7 @@ | 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: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:30:3:30:17 | call to change_global02 | test.cpp:30:3:30:17 | call to change_global02 | AST 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 | @@ -78,21 +77,15 @@ | 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 | @@ -140,12 +133,10 @@ | 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 | @@ -165,8 +156,6 @@ | 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 | @@ -176,10 +165,8 @@ | 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 bf1c05c4c434..c6f106b236fe 100644 --- a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected +++ b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected @@ -237,7 +237,6 @@ 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 @@ -591,19 +590,19 @@ test.cpp: # 77| r77_2(glval) = FunctionAddress[getAValue] : # 77| valnum = unique # 77| r77_3(int) = Call[getAValue] : func:r77_2 -# 77| valnum = r77_3, r80_2, v30_2 +# 77| valnum = unique # 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, m80_7, r77_6, r79_2, r80_5 +# 77| valnum = m77_7, r77_6, r79_2 # 77| m77_7(signed short) = Store[v] : &:r77_1, r77_6 -# 77| valnum = m77_7, m80_7, r77_6, r79_2, r80_5 +# 77| valnum = m77_7, r77_6, r79_2 # 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, m80_7, r77_6, r79_2, r80_5 +# 79| valnum = m77_7, r77_6, r79_2 # 79| r79_3(int) = Convert : r79_2 # 79| valnum = unique # 79| r79_4(glval) = VariableAddress[vals] : @@ -638,17 +637,17 @@ test.cpp: # 80| r80_1(glval) = FunctionAddress[getAValue] : # 80| valnum = unique # 80| r80_2(int) = Call[getAValue] : func:r80_1 -# 80| valnum = r77_3, r80_2, v30_2 +# 80| valnum = unique # 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 = m77_7, m80_7, r77_6, r79_2, r80_5 +# 80| valnum = m80_7, 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 = m77_7, m80_7, r77_6, r79_2, r80_5 +# 80| valnum = m80_7, r80_5 #-----| Goto -> Block 2 # 82| Block 2 @@ -1147,6 +1146,43 @@ test.cpp: # 152| v152_8(void) = AliasedUse : ~m156_7 # 152| v152_9(void) = ExitFunction : +# 163| int add(int, int) +# 163| Block 0 +# 163| v163_1(void) = EnterFunction : +# 163| m163_2(unknown) = AliasedDefinition : +# 163| valnum = unique +# 163| m163_3(unknown) = InitializeNonLocal : +# 163| valnum = unique +# 163| m163_4(unknown) = Chi : total:m163_2, partial:m163_3 +# 163| valnum = unique +# 163| r163_5(glval) = VariableAddress[a] : +# 163| valnum = r163_10, r163_5 +# 163| m163_6(int) = InitializeParameter[a] : &:r163_5 +# 163| valnum = m163_6, r163_11 +# 163| r163_7(glval) = VariableAddress[b] : +# 163| valnum = r163_12, r163_7 +# 163| m163_8(int) = InitializeParameter[b] : &:r163_7 +# 163| valnum = m163_8, r163_13 +# 163| r163_9(glval) = VariableAddress[#return] : +# 163| valnum = r163_16, r163_9 +# 163| r163_10(glval) = VariableAddress[a] : +# 163| valnum = r163_10, r163_5 +# 163| r163_11(int) = Load[a] : &:r163_10, m163_6 +# 163| valnum = m163_6, r163_11 +# 163| r163_12(glval) = VariableAddress[b] : +# 163| valnum = r163_12, r163_7 +# 163| r163_13(int) = Load[b] : &:r163_12, m163_8 +# 163| valnum = m163_8, r163_13 +# 163| r163_14(int) = Add : r163_11, r163_13 +# 163| valnum = m163_15, r163_14 +# 163| m163_15(int) = Store[#return] : &:r163_9, r163_14 +# 163| valnum = m163_15, r163_14 +# 163| r163_16(glval) = VariableAddress[#return] : +# 163| valnum = r163_16, r163_9 +# 163| v163_17(void) = ReturnValue : &:r163_16, m163_15 +# 163| v163_18(void) = AliasedUse : m163_3 +# 163| v163_19(void) = ExitFunction : + # 165| void test_func_value_numbering(char*, char*) # 165| Block 0 # 165| v165_1(void) = EnterFunction : @@ -1183,10 +1219,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, m167_8, m173_8, r166_6, r167_6, r173_6 +# 166| valnum = m166_8, m167_8, r166_6, r167_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, m167_8, m173_8, r166_6, r167_6, r173_6 +# 166| valnum = m166_8, m167_8, r166_6, r167_6 # 167| r167_1(glval) = VariableAddress[b] : # 167| valnum = unique # 167| r167_2(glval) = FunctionAddress[strlen] : @@ -1198,10 +1234,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 = m166_8, m167_8, m173_8, r166_6, r167_6, r173_6 +# 167| valnum = m166_8, m167_8, r166_6, r167_6 # 167| v167_7(void) = ^BufferReadSideEffect[0] : &:r167_5, ~m165_8 # 167| m167_8(int) = Store[b] : &:r167_1, r167_6 -# 167| valnum = m166_8, m167_8, m173_8, r166_6, r167_6, r173_6 +# 167| valnum = m166_8, m167_8, r166_6, r167_6 # 168| r168_1(glval) = VariableAddress[c] : # 168| valnum = unique # 168| r168_2(glval) = FunctionAddress[strlen] : @@ -1263,10 +1299,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 = m166_8, m167_8, m173_8, r166_6, r167_6, r173_6 +# 173| valnum = m173_8, r173_6 # 173| v173_7(void) = ^BufferReadSideEffect[0] : &:r173_5, ~m171_11 # 173| m173_8(int) = Store[e] : &:r173_1, r173_6 -# 173| valnum = m166_8, m167_8, m173_8, r166_6, r167_6, r173_6 +# 173| valnum = m173_8, r173_6 # 174| r174_1(glval) = VariableAddress[f] : # 174| valnum = unique # 174| r174_2(glval) = FunctionAddress[strlen] : @@ -1290,10 +1326,6 @@ test.cpp: # 176| valnum = r176_3, r178_3 # 176| r176_4(int) = Call[add] : func:r176_1, 0:r176_2, 1:r176_3 # 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 -# 176| valnum = unique # 177| r177_1(glval) = FunctionAddress[add] : # 177| valnum = unique # 177| r177_2(int) = Constant[3] : @@ -1302,10 +1334,6 @@ test.cpp: # 177| valnum = unique # 177| r177_4(int) = Call[add] : func:r177_1, 0:r177_2, 1:r177_3 # 177| valnum = unique -# 177| m177_5(unknown) = ^CallSideEffect : ~m176_6 -# 177| valnum = unique -# 177| m177_6(unknown) = Chi : total:m176_6, partial:m177_5 -# 177| valnum = unique # 178| r178_1(glval) = FunctionAddress[add] : # 178| valnum = unique # 178| r178_2(int) = Constant[1] : @@ -1314,13 +1342,9 @@ test.cpp: # 178| valnum = r176_3, r178_3 # 178| r178_4(int) = Call[add] : func:r178_1, 0:r178_2, 1:r178_3 # 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 -# 178| valnum = unique # 179| v179_1(void) = NoOp : # 165| v165_13(void) = ReturnIndirection[dst] : &:r165_7, m171_11 # 165| v165_14(void) = ReturnIndirection[src] : &:r165_11, m165_12 # 165| v165_15(void) = ReturnVoid : -# 165| v165_16(void) = AliasedUse : ~m178_6 +# 165| v165_16(void) = AliasedUse : m165_3 # 165| v165_17(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/test.cpp b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/test.cpp index c3624f7bf206..7ac0b4233bef 100644 --- a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/test.cpp +++ b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/test.cpp @@ -160,7 +160,7 @@ void test_read_global_different(int n) { int strlen(const char *str); char *strcat(char *dst, const char *src); -int add(int a, int b); +int add(int a, int b) { return a+b; } void test_func_value_numbering(char *dst, char *src) { int a = strlen(dst); From 5c11062d21fa066e9346bb69158d04e10d9aa415 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Mon, 1 Aug 2022 13:26:04 -0400 Subject: [PATCH 10/19] C++/C#: sync GVN files --- .../gvn/internal/ValueNumberingInternal.qll | 22 ++++++++++--------- .../gvn/internal/ValueNumberingInternal.qll | 22 ++++++++++--------- .../gvn/internal/ValueNumberingInternal.qll | 22 ++++++++++--------- .../gvn/internal/ValueNumberingInternal.qll | 22 ++++++++++--------- 4 files changed, 48 insertions(+), 40 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll index eeb7adf9a169..4fb9bc42e827 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll @@ -44,7 +44,7 @@ newtype TValueNumber = TCallValueNumber(TCallPartialValueNumber vn) { callValueNumber(_, _, vn) } or TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) } -newtype TCallPartialValueNumber = +private newtype TCallPartialValueNumber = TNilArgument() or TArgument(TCallPartialValueNumber head, TValueNumber arg) { exists(CallInstruction call, int index | @@ -53,7 +53,7 @@ newtype TCallPartialValueNumber = ) } -predicate callValueNumber(CallInstruction call, int index, TCallPartialValueNumber vn) { +private 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, pragma[only_bind_out](head)) and @@ -61,16 +61,17 @@ predicate callValueNumber(CallInstruction call, int index, TCallPartialValueNumb vn = TArgument(head, arg) ) or + not call.getResultIRType() instanceof IRVoidType and 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() and exists(call) +private predicate callPartialValueNumber(CallInstruction call, int index, TCallPartialValueNumber head) { + index = 1 and head = TNilArgument() and not call.getResultIRType() instanceof IRVoidType or exists(TCallPartialValueNumber prev, TValueNumber prevVN | - callPartialValueNumber(call, index - 1, pragma[only_bind_out](prev)) and + callPartialValueNumber(call, index - 1, pragma[only_bind_out](prev)) and callArgValueNumber(call, index - 1, pragma[only_bind_into](prevVN)) and head = TArgument(prev, prevVN) ) @@ -78,7 +79,8 @@ predicate callPartialValueNumber(CallInstruction call, int index, TCallPartialVa /** */ -predicate callArgValueNumber(CallInstruction call, int index, TValueNumber arg) { +private predicate callArgValueNumber(CallInstruction call, int index, TValueNumber arg) { + not call.getResultIRType() instanceof IRVoidType and exists(Instruction instr | callArgRank(call, index, instr) and arg = tvalueNumber(instr) @@ -89,21 +91,21 @@ predicate callArgValueNumber(CallInstruction call, int index, TValueNumber arg) * 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) { +private predicate callArgRank(CallInstruction call, int index, Instruction arg) { arg = rank[index](int argIndex, boolean isEffect, Instruction instr | exists(CallSideEffectInstruction cse | cse.getPrimaryInstruction() = call and cse.getSideEffectOperand().getAnyDef() = instr and argIndex = -2 and - isEffect = false + isEffect = true ) or exists(CallReadSideEffectInstruction cse | cse.getPrimaryInstruction() = call and cse.getSideEffectOperand().getAnyDef() = instr and argIndex = -2 and - isEffect = false + isEffect = true ) or instr = call.getThisArgument() and @@ -115,7 +117,7 @@ predicate callArgRank(CallInstruction call, int index, Instruction arg) { or exists(ReadSideEffectInstruction read | read.getPrimaryInstruction() = call and - read.getSideEffectOperand().getDef() = instr and + read.getSideEffectOperand().getAnyDef() = instr and read.getIndex() = argIndex and isEffect = true ) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll index eeb7adf9a169..4fb9bc42e827 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll @@ -44,7 +44,7 @@ newtype TValueNumber = TCallValueNumber(TCallPartialValueNumber vn) { callValueNumber(_, _, vn) } or TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) } -newtype TCallPartialValueNumber = +private newtype TCallPartialValueNumber = TNilArgument() or TArgument(TCallPartialValueNumber head, TValueNumber arg) { exists(CallInstruction call, int index | @@ -53,7 +53,7 @@ newtype TCallPartialValueNumber = ) } -predicate callValueNumber(CallInstruction call, int index, TCallPartialValueNumber vn) { +private 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, pragma[only_bind_out](head)) and @@ -61,16 +61,17 @@ predicate callValueNumber(CallInstruction call, int index, TCallPartialValueNumb vn = TArgument(head, arg) ) or + not call.getResultIRType() instanceof IRVoidType and 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() and exists(call) +private predicate callPartialValueNumber(CallInstruction call, int index, TCallPartialValueNumber head) { + index = 1 and head = TNilArgument() and not call.getResultIRType() instanceof IRVoidType or exists(TCallPartialValueNumber prev, TValueNumber prevVN | - callPartialValueNumber(call, index - 1, pragma[only_bind_out](prev)) and + callPartialValueNumber(call, index - 1, pragma[only_bind_out](prev)) and callArgValueNumber(call, index - 1, pragma[only_bind_into](prevVN)) and head = TArgument(prev, prevVN) ) @@ -78,7 +79,8 @@ predicate callPartialValueNumber(CallInstruction call, int index, TCallPartialVa /** */ -predicate callArgValueNumber(CallInstruction call, int index, TValueNumber arg) { +private predicate callArgValueNumber(CallInstruction call, int index, TValueNumber arg) { + not call.getResultIRType() instanceof IRVoidType and exists(Instruction instr | callArgRank(call, index, instr) and arg = tvalueNumber(instr) @@ -89,21 +91,21 @@ predicate callArgValueNumber(CallInstruction call, int index, TValueNumber arg) * 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) { +private predicate callArgRank(CallInstruction call, int index, Instruction arg) { arg = rank[index](int argIndex, boolean isEffect, Instruction instr | exists(CallSideEffectInstruction cse | cse.getPrimaryInstruction() = call and cse.getSideEffectOperand().getAnyDef() = instr and argIndex = -2 and - isEffect = false + isEffect = true ) or exists(CallReadSideEffectInstruction cse | cse.getPrimaryInstruction() = call and cse.getSideEffectOperand().getAnyDef() = instr and argIndex = -2 and - isEffect = false + isEffect = true ) or instr = call.getThisArgument() and @@ -115,7 +117,7 @@ predicate callArgRank(CallInstruction call, int index, Instruction arg) { or exists(ReadSideEffectInstruction read | read.getPrimaryInstruction() = call and - read.getSideEffectOperand().getDef() = instr and + read.getSideEffectOperand().getAnyDef() = instr and read.getIndex() = argIndex and isEffect = true ) diff --git a/csharp/ql/src/experimental/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll b/csharp/ql/src/experimental/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll index eeb7adf9a169..4fb9bc42e827 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll @@ -44,7 +44,7 @@ newtype TValueNumber = TCallValueNumber(TCallPartialValueNumber vn) { callValueNumber(_, _, vn) } or TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) } -newtype TCallPartialValueNumber = +private newtype TCallPartialValueNumber = TNilArgument() or TArgument(TCallPartialValueNumber head, TValueNumber arg) { exists(CallInstruction call, int index | @@ -53,7 +53,7 @@ newtype TCallPartialValueNumber = ) } -predicate callValueNumber(CallInstruction call, int index, TCallPartialValueNumber vn) { +private 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, pragma[only_bind_out](head)) and @@ -61,16 +61,17 @@ predicate callValueNumber(CallInstruction call, int index, TCallPartialValueNumb vn = TArgument(head, arg) ) or + not call.getResultIRType() instanceof IRVoidType and 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() and exists(call) +private predicate callPartialValueNumber(CallInstruction call, int index, TCallPartialValueNumber head) { + index = 1 and head = TNilArgument() and not call.getResultIRType() instanceof IRVoidType or exists(TCallPartialValueNumber prev, TValueNumber prevVN | - callPartialValueNumber(call, index - 1, pragma[only_bind_out](prev)) and + callPartialValueNumber(call, index - 1, pragma[only_bind_out](prev)) and callArgValueNumber(call, index - 1, pragma[only_bind_into](prevVN)) and head = TArgument(prev, prevVN) ) @@ -78,7 +79,8 @@ predicate callPartialValueNumber(CallInstruction call, int index, TCallPartialVa /** */ -predicate callArgValueNumber(CallInstruction call, int index, TValueNumber arg) { +private predicate callArgValueNumber(CallInstruction call, int index, TValueNumber arg) { + not call.getResultIRType() instanceof IRVoidType and exists(Instruction instr | callArgRank(call, index, instr) and arg = tvalueNumber(instr) @@ -89,21 +91,21 @@ predicate callArgValueNumber(CallInstruction call, int index, TValueNumber arg) * 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) { +private predicate callArgRank(CallInstruction call, int index, Instruction arg) { arg = rank[index](int argIndex, boolean isEffect, Instruction instr | exists(CallSideEffectInstruction cse | cse.getPrimaryInstruction() = call and cse.getSideEffectOperand().getAnyDef() = instr and argIndex = -2 and - isEffect = false + isEffect = true ) or exists(CallReadSideEffectInstruction cse | cse.getPrimaryInstruction() = call and cse.getSideEffectOperand().getAnyDef() = instr and argIndex = -2 and - isEffect = false + isEffect = true ) or instr = call.getThisArgument() and @@ -115,7 +117,7 @@ predicate callArgRank(CallInstruction call, int index, Instruction arg) { or exists(ReadSideEffectInstruction read | read.getPrimaryInstruction() = call and - read.getSideEffectOperand().getDef() = instr and + read.getSideEffectOperand().getAnyDef() = instr and read.getIndex() = argIndex and isEffect = true ) diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll index eeb7adf9a169..4fb9bc42e827 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll @@ -44,7 +44,7 @@ newtype TValueNumber = TCallValueNumber(TCallPartialValueNumber vn) { callValueNumber(_, _, vn) } or TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) } -newtype TCallPartialValueNumber = +private newtype TCallPartialValueNumber = TNilArgument() or TArgument(TCallPartialValueNumber head, TValueNumber arg) { exists(CallInstruction call, int index | @@ -53,7 +53,7 @@ newtype TCallPartialValueNumber = ) } -predicate callValueNumber(CallInstruction call, int index, TCallPartialValueNumber vn) { +private 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, pragma[only_bind_out](head)) and @@ -61,16 +61,17 @@ predicate callValueNumber(CallInstruction call, int index, TCallPartialValueNumb vn = TArgument(head, arg) ) or + not call.getResultIRType() instanceof IRVoidType and 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() and exists(call) +private predicate callPartialValueNumber(CallInstruction call, int index, TCallPartialValueNumber head) { + index = 1 and head = TNilArgument() and not call.getResultIRType() instanceof IRVoidType or exists(TCallPartialValueNumber prev, TValueNumber prevVN | - callPartialValueNumber(call, index - 1, pragma[only_bind_out](prev)) and + callPartialValueNumber(call, index - 1, pragma[only_bind_out](prev)) and callArgValueNumber(call, index - 1, pragma[only_bind_into](prevVN)) and head = TArgument(prev, prevVN) ) @@ -78,7 +79,8 @@ predicate callPartialValueNumber(CallInstruction call, int index, TCallPartialVa /** */ -predicate callArgValueNumber(CallInstruction call, int index, TValueNumber arg) { +private predicate callArgValueNumber(CallInstruction call, int index, TValueNumber arg) { + not call.getResultIRType() instanceof IRVoidType and exists(Instruction instr | callArgRank(call, index, instr) and arg = tvalueNumber(instr) @@ -89,21 +91,21 @@ predicate callArgValueNumber(CallInstruction call, int index, TValueNumber arg) * 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) { +private predicate callArgRank(CallInstruction call, int index, Instruction arg) { arg = rank[index](int argIndex, boolean isEffect, Instruction instr | exists(CallSideEffectInstruction cse | cse.getPrimaryInstruction() = call and cse.getSideEffectOperand().getAnyDef() = instr and argIndex = -2 and - isEffect = false + isEffect = true ) or exists(CallReadSideEffectInstruction cse | cse.getPrimaryInstruction() = call and cse.getSideEffectOperand().getAnyDef() = instr and argIndex = -2 and - isEffect = false + isEffect = true ) or instr = call.getThisArgument() and @@ -115,7 +117,7 @@ predicate callArgRank(CallInstruction call, int index, Instruction arg) { or exists(ReadSideEffectInstruction read | read.getPrimaryInstruction() = call and - read.getSideEffectOperand().getDef() = instr and + read.getSideEffectOperand().getAnyDef() = instr and read.getIndex() = argIndex and isEffect = true ) From 7c4d3800b63aa445889ae75e72f54cd87de791f1 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Mon, 1 Aug 2022 13:32:12 -0400 Subject: [PATCH 11/19] C++: change note for function call GVNs --- cpp/ql/lib/change-notes/2022-08-01-gvn-functions.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 cpp/ql/lib/change-notes/2022-08-01-gvn-functions.md diff --git a/cpp/ql/lib/change-notes/2022-08-01-gvn-functions.md b/cpp/ql/lib/change-notes/2022-08-01-gvn-functions.md new file mode 100644 index 000000000000..22e5a49d4292 --- /dev/null +++ b/cpp/ql/lib/change-notes/2022-08-01-gvn-functions.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Multiple function calls made in the same function may now receive the same global value number when the analysis can show they produce the same results. \ No newline at end of file From dc105b404bbf9e38503fcce66e5e4433a1dcc39d Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Thu, 25 Aug 2022 15:45:50 +0100 Subject: [PATCH 12/19] C++: Only GVN side-effect-free functions. This improves the performance dramatically. --- .../gvn/internal/ValueNumberingImports.qll | 1 + .../gvn/internal/ValueNumberingInternal.qll | 55 +++++++++---------- .../gvn/internal/ValueNumberingImports.qll | 1 + .../gvn/internal/ValueNumberingInternal.qll | 55 +++++++++---------- .../gvn/internal/ValueNumberingImports.qll | 1 + .../gvn/internal/ValueNumberingInternal.qll | 55 +++++++++---------- .../GlobalValueNumbering/ir_gvn.expected | 4 +- 7 files changed, 86 insertions(+), 86 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/internal/ValueNumberingImports.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/internal/ValueNumberingImports.qll index 8482a5e4b143..6e59b1f3dfbc 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/internal/ValueNumberingImports.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/internal/ValueNumberingImports.qll @@ -1,3 +1,4 @@ import semmle.code.cpp.ir.implementation.aliased_ssa.IR import semmle.code.cpp.ir.internal.Overlap import semmle.code.cpp.ir.internal.IRCppLanguage as Language +import semmle.code.cpp.models.interfaces.SideEffect as SideEffect 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 4fb9bc42e827..d8862dcaa07f 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 @@ -44,16 +44,30 @@ newtype TValueNumber = TCallValueNumber(TCallPartialValueNumber vn) { callValueNumber(_, _, vn) } or TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) } +private class NumberableCallInstruction extends CallInstruction { + NumberableCallInstruction() { + not this.getResultIRType() instanceof IRVoidType and + exists(SideEffect::SideEffectFunction sideEffectFunc | + sideEffectFunc = this.getStaticCallTarget() + | + sideEffectFunc.hasOnlySpecificReadSideEffects() and + sideEffectFunc.hasOnlySpecificWriteSideEffects() + ) + } +} + private newtype TCallPartialValueNumber = TNilArgument() or TArgument(TCallPartialValueNumber head, TValueNumber arg) { - exists(CallInstruction call, int index | + exists(NumberableCallInstruction call, int index | callArgValueNumber(call, index, arg) and callPartialValueNumber(call, index, head) ) } -private predicate callValueNumber(CallInstruction call, int index, TCallPartialValueNumber vn) { +private predicate callValueNumber( + NumberableCallInstruction call, int index, TCallPartialValueNumber vn +) { index = max(int n | callArgRank(call, n, _) | n) and exists(TCallPartialValueNumber head, TValueNumber arg | callPartialValueNumber(call, index, pragma[only_bind_out](head)) and @@ -61,14 +75,15 @@ private predicate callValueNumber(CallInstruction call, int index, TCallPartialV vn = TArgument(head, arg) ) or - not call.getResultIRType() instanceof IRVoidType and not exists(int n | callArgRank(call, n, _)) and index = -1 and vn = TNilArgument() } -private predicate callPartialValueNumber(CallInstruction call, int index, TCallPartialValueNumber head) { - index = 1 and head = TNilArgument() and not call.getResultIRType() instanceof IRVoidType +private predicate callPartialValueNumber( + NumberableCallInstruction call, int index, TCallPartialValueNumber head +) { + index = 1 and head = TNilArgument() or exists(TCallPartialValueNumber prev, TValueNumber prevVN | callPartialValueNumber(call, index - 1, pragma[only_bind_out](prev)) and @@ -79,8 +94,7 @@ private predicate callPartialValueNumber(CallInstruction call, int index, TCallP /** */ -private predicate callArgValueNumber(CallInstruction call, int index, TValueNumber arg) { - not call.getResultIRType() instanceof IRVoidType and +private predicate callArgValueNumber(NumberableCallInstruction call, int index, TValueNumber arg) { exists(Instruction instr | callArgRank(call, index, instr) and arg = tvalueNumber(instr) @@ -91,28 +105,13 @@ private predicate callArgValueNumber(CallInstruction call, int index, TValueNumb * Holds if `arg` is the `index`th element in `call`'s extended argument list, including the `this` * argument and side-effect reads. */ -private predicate callArgRank(CallInstruction call, int index, Instruction arg) { +private predicate callArgRank(NumberableCallInstruction call, int index, Instruction arg) { arg = rank[index](int argIndex, boolean isEffect, Instruction instr | - exists(CallSideEffectInstruction cse | - cse.getPrimaryInstruction() = call and - cse.getSideEffectOperand().getAnyDef() = instr and - argIndex = -2 and - isEffect = true - ) - or - exists(CallReadSideEffectInstruction cse | - cse.getPrimaryInstruction() = call and - cse.getSideEffectOperand().getAnyDef() = instr and - argIndex = -2 and - isEffect = true - ) - or - instr = call.getThisArgument() and - argIndex = -1 and - isEffect = false - or - instr = call.getPositionalArgument(argIndex) and + // There is no need to include the call's read and write side effects on + // all-aliased-memory as `NumberableCallInstruction`s do not read or write + // to all-aliased-memory. + instr = call.getArgument(argIndex) and isEffect = false or exists(ReadSideEffectInstruction read | @@ -177,7 +176,7 @@ private predicate numberableInstruction(Instruction instr) { or instr instanceof LoadTotalOverlapInstruction or - instr instanceof CallInstruction + instr instanceof NumberableCallInstruction } private predicate filteredNumberableInstruction(Instruction instr) { diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingImports.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingImports.qll index 8482a5e4b143..6e59b1f3dfbc 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingImports.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingImports.qll @@ -1,3 +1,4 @@ import semmle.code.cpp.ir.implementation.aliased_ssa.IR import semmle.code.cpp.ir.internal.Overlap import semmle.code.cpp.ir.internal.IRCppLanguage as Language +import semmle.code.cpp.models.interfaces.SideEffect as SideEffect diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll index 4fb9bc42e827..d8862dcaa07f 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll @@ -44,16 +44,30 @@ newtype TValueNumber = TCallValueNumber(TCallPartialValueNumber vn) { callValueNumber(_, _, vn) } or TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) } +private class NumberableCallInstruction extends CallInstruction { + NumberableCallInstruction() { + not this.getResultIRType() instanceof IRVoidType and + exists(SideEffect::SideEffectFunction sideEffectFunc | + sideEffectFunc = this.getStaticCallTarget() + | + sideEffectFunc.hasOnlySpecificReadSideEffects() and + sideEffectFunc.hasOnlySpecificWriteSideEffects() + ) + } +} + private newtype TCallPartialValueNumber = TNilArgument() or TArgument(TCallPartialValueNumber head, TValueNumber arg) { - exists(CallInstruction call, int index | + exists(NumberableCallInstruction call, int index | callArgValueNumber(call, index, arg) and callPartialValueNumber(call, index, head) ) } -private predicate callValueNumber(CallInstruction call, int index, TCallPartialValueNumber vn) { +private predicate callValueNumber( + NumberableCallInstruction call, int index, TCallPartialValueNumber vn +) { index = max(int n | callArgRank(call, n, _) | n) and exists(TCallPartialValueNumber head, TValueNumber arg | callPartialValueNumber(call, index, pragma[only_bind_out](head)) and @@ -61,14 +75,15 @@ private predicate callValueNumber(CallInstruction call, int index, TCallPartialV vn = TArgument(head, arg) ) or - not call.getResultIRType() instanceof IRVoidType and not exists(int n | callArgRank(call, n, _)) and index = -1 and vn = TNilArgument() } -private predicate callPartialValueNumber(CallInstruction call, int index, TCallPartialValueNumber head) { - index = 1 and head = TNilArgument() and not call.getResultIRType() instanceof IRVoidType +private predicate callPartialValueNumber( + NumberableCallInstruction call, int index, TCallPartialValueNumber head +) { + index = 1 and head = TNilArgument() or exists(TCallPartialValueNumber prev, TValueNumber prevVN | callPartialValueNumber(call, index - 1, pragma[only_bind_out](prev)) and @@ -79,8 +94,7 @@ private predicate callPartialValueNumber(CallInstruction call, int index, TCallP /** */ -private predicate callArgValueNumber(CallInstruction call, int index, TValueNumber arg) { - not call.getResultIRType() instanceof IRVoidType and +private predicate callArgValueNumber(NumberableCallInstruction call, int index, TValueNumber arg) { exists(Instruction instr | callArgRank(call, index, instr) and arg = tvalueNumber(instr) @@ -91,28 +105,13 @@ private predicate callArgValueNumber(CallInstruction call, int index, TValueNumb * Holds if `arg` is the `index`th element in `call`'s extended argument list, including the `this` * argument and side-effect reads. */ -private predicate callArgRank(CallInstruction call, int index, Instruction arg) { +private predicate callArgRank(NumberableCallInstruction call, int index, Instruction arg) { arg = rank[index](int argIndex, boolean isEffect, Instruction instr | - exists(CallSideEffectInstruction cse | - cse.getPrimaryInstruction() = call and - cse.getSideEffectOperand().getAnyDef() = instr and - argIndex = -2 and - isEffect = true - ) - or - exists(CallReadSideEffectInstruction cse | - cse.getPrimaryInstruction() = call and - cse.getSideEffectOperand().getAnyDef() = instr and - argIndex = -2 and - isEffect = true - ) - or - instr = call.getThisArgument() and - argIndex = -1 and - isEffect = false - or - instr = call.getPositionalArgument(argIndex) and + // There is no need to include the call's read and write side effects on + // all-aliased-memory as `NumberableCallInstruction`s do not read or write + // to all-aliased-memory. + instr = call.getArgument(argIndex) and isEffect = false or exists(ReadSideEffectInstruction read | @@ -177,7 +176,7 @@ private predicate numberableInstruction(Instruction instr) { or instr instanceof LoadTotalOverlapInstruction or - instr instanceof CallInstruction + instr instanceof NumberableCallInstruction } private predicate filteredNumberableInstruction(Instruction instr) { diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingImports.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingImports.qll index 8482a5e4b143..6e59b1f3dfbc 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingImports.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingImports.qll @@ -1,3 +1,4 @@ import semmle.code.cpp.ir.implementation.aliased_ssa.IR import semmle.code.cpp.ir.internal.Overlap import semmle.code.cpp.ir.internal.IRCppLanguage as Language +import semmle.code.cpp.models.interfaces.SideEffect as SideEffect diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll index 4fb9bc42e827..d8862dcaa07f 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll @@ -44,16 +44,30 @@ newtype TValueNumber = TCallValueNumber(TCallPartialValueNumber vn) { callValueNumber(_, _, vn) } or TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) } +private class NumberableCallInstruction extends CallInstruction { + NumberableCallInstruction() { + not this.getResultIRType() instanceof IRVoidType and + exists(SideEffect::SideEffectFunction sideEffectFunc | + sideEffectFunc = this.getStaticCallTarget() + | + sideEffectFunc.hasOnlySpecificReadSideEffects() and + sideEffectFunc.hasOnlySpecificWriteSideEffects() + ) + } +} + private newtype TCallPartialValueNumber = TNilArgument() or TArgument(TCallPartialValueNumber head, TValueNumber arg) { - exists(CallInstruction call, int index | + exists(NumberableCallInstruction call, int index | callArgValueNumber(call, index, arg) and callPartialValueNumber(call, index, head) ) } -private predicate callValueNumber(CallInstruction call, int index, TCallPartialValueNumber vn) { +private predicate callValueNumber( + NumberableCallInstruction call, int index, TCallPartialValueNumber vn +) { index = max(int n | callArgRank(call, n, _) | n) and exists(TCallPartialValueNumber head, TValueNumber arg | callPartialValueNumber(call, index, pragma[only_bind_out](head)) and @@ -61,14 +75,15 @@ private predicate callValueNumber(CallInstruction call, int index, TCallPartialV vn = TArgument(head, arg) ) or - not call.getResultIRType() instanceof IRVoidType and not exists(int n | callArgRank(call, n, _)) and index = -1 and vn = TNilArgument() } -private predicate callPartialValueNumber(CallInstruction call, int index, TCallPartialValueNumber head) { - index = 1 and head = TNilArgument() and not call.getResultIRType() instanceof IRVoidType +private predicate callPartialValueNumber( + NumberableCallInstruction call, int index, TCallPartialValueNumber head +) { + index = 1 and head = TNilArgument() or exists(TCallPartialValueNumber prev, TValueNumber prevVN | callPartialValueNumber(call, index - 1, pragma[only_bind_out](prev)) and @@ -79,8 +94,7 @@ private predicate callPartialValueNumber(CallInstruction call, int index, TCallP /** */ -private predicate callArgValueNumber(CallInstruction call, int index, TValueNumber arg) { - not call.getResultIRType() instanceof IRVoidType and +private predicate callArgValueNumber(NumberableCallInstruction call, int index, TValueNumber arg) { exists(Instruction instr | callArgRank(call, index, instr) and arg = tvalueNumber(instr) @@ -91,28 +105,13 @@ private predicate callArgValueNumber(CallInstruction call, int index, TValueNumb * Holds if `arg` is the `index`th element in `call`'s extended argument list, including the `this` * argument and side-effect reads. */ -private predicate callArgRank(CallInstruction call, int index, Instruction arg) { +private predicate callArgRank(NumberableCallInstruction call, int index, Instruction arg) { arg = rank[index](int argIndex, boolean isEffect, Instruction instr | - exists(CallSideEffectInstruction cse | - cse.getPrimaryInstruction() = call and - cse.getSideEffectOperand().getAnyDef() = instr and - argIndex = -2 and - isEffect = true - ) - or - exists(CallReadSideEffectInstruction cse | - cse.getPrimaryInstruction() = call and - cse.getSideEffectOperand().getAnyDef() = instr and - argIndex = -2 and - isEffect = true - ) - or - instr = call.getThisArgument() and - argIndex = -1 and - isEffect = false - or - instr = call.getPositionalArgument(argIndex) and + // There is no need to include the call's read and write side effects on + // all-aliased-memory as `NumberableCallInstruction`s do not read or write + // to all-aliased-memory. + instr = call.getArgument(argIndex) and isEffect = false or exists(ReadSideEffectInstruction read | @@ -177,7 +176,7 @@ private predicate numberableInstruction(Instruction instr) { or instr instanceof LoadTotalOverlapInstruction or - instr instanceof CallInstruction + instr instanceof NumberableCallInstruction } private predicate filteredNumberableInstruction(Instruction instr) { 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 c6f106b236fe..7fcdce18f57f 100644 --- a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected +++ b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected @@ -1325,7 +1325,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 = r176_4, r178_4 +# 176| valnum = unique # 177| r177_1(glval) = FunctionAddress[add] : # 177| valnum = unique # 177| r177_2(int) = Constant[3] : @@ -1341,7 +1341,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 = r176_4, r178_4 +# 178| valnum = unique # 179| v179_1(void) = NoOp : # 165| v165_13(void) = ReturnIndirection[dst] : &:r165_7, m171_11 # 165| v165_14(void) = ReturnIndirection[src] : &:r165_11, m165_12 From 86bb9c38ce341173db10f87fae7984ad2b869bed Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Thu, 25 Aug 2022 15:47:07 +0100 Subject: [PATCH 13/19] C#: Sync identical files. --- .../gvn/internal/ValueNumberingImports.qll | 1 + .../gvn/internal/ValueNumberingInternal.qll | 55 +++++++++---------- .../gvn/internal/ValueNumberingImports.qll | 1 + .../gvn/internal/ValueNumberingInternal.qll | 55 +++++++++---------- .../experimental/ir/interfaces/SideEffect.qll | 24 ++++++++ 5 files changed, 80 insertions(+), 56 deletions(-) create mode 100644 csharp/ql/src/experimental/ir/interfaces/SideEffect.qll diff --git a/csharp/ql/src/experimental/ir/implementation/raw/gvn/internal/ValueNumberingImports.qll b/csharp/ql/src/experimental/ir/implementation/raw/gvn/internal/ValueNumberingImports.qll index 34bd754692d6..6ea20d2b4df2 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/gvn/internal/ValueNumberingImports.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/gvn/internal/ValueNumberingImports.qll @@ -1,3 +1,4 @@ import experimental.ir.internal.Overlap import experimental.ir.internal.IRCSharpLanguage as Language import experimental.ir.implementation.unaliased_ssa.IR +import experimental.ir.interfaces.SideEffect as SideEffect diff --git a/csharp/ql/src/experimental/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll b/csharp/ql/src/experimental/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll index 4fb9bc42e827..d8862dcaa07f 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll @@ -44,16 +44,30 @@ newtype TValueNumber = TCallValueNumber(TCallPartialValueNumber vn) { callValueNumber(_, _, vn) } or TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) } +private class NumberableCallInstruction extends CallInstruction { + NumberableCallInstruction() { + not this.getResultIRType() instanceof IRVoidType and + exists(SideEffect::SideEffectFunction sideEffectFunc | + sideEffectFunc = this.getStaticCallTarget() + | + sideEffectFunc.hasOnlySpecificReadSideEffects() and + sideEffectFunc.hasOnlySpecificWriteSideEffects() + ) + } +} + private newtype TCallPartialValueNumber = TNilArgument() or TArgument(TCallPartialValueNumber head, TValueNumber arg) { - exists(CallInstruction call, int index | + exists(NumberableCallInstruction call, int index | callArgValueNumber(call, index, arg) and callPartialValueNumber(call, index, head) ) } -private predicate callValueNumber(CallInstruction call, int index, TCallPartialValueNumber vn) { +private predicate callValueNumber( + NumberableCallInstruction call, int index, TCallPartialValueNumber vn +) { index = max(int n | callArgRank(call, n, _) | n) and exists(TCallPartialValueNumber head, TValueNumber arg | callPartialValueNumber(call, index, pragma[only_bind_out](head)) and @@ -61,14 +75,15 @@ private predicate callValueNumber(CallInstruction call, int index, TCallPartialV vn = TArgument(head, arg) ) or - not call.getResultIRType() instanceof IRVoidType and not exists(int n | callArgRank(call, n, _)) and index = -1 and vn = TNilArgument() } -private predicate callPartialValueNumber(CallInstruction call, int index, TCallPartialValueNumber head) { - index = 1 and head = TNilArgument() and not call.getResultIRType() instanceof IRVoidType +private predicate callPartialValueNumber( + NumberableCallInstruction call, int index, TCallPartialValueNumber head +) { + index = 1 and head = TNilArgument() or exists(TCallPartialValueNumber prev, TValueNumber prevVN | callPartialValueNumber(call, index - 1, pragma[only_bind_out](prev)) and @@ -79,8 +94,7 @@ private predicate callPartialValueNumber(CallInstruction call, int index, TCallP /** */ -private predicate callArgValueNumber(CallInstruction call, int index, TValueNumber arg) { - not call.getResultIRType() instanceof IRVoidType and +private predicate callArgValueNumber(NumberableCallInstruction call, int index, TValueNumber arg) { exists(Instruction instr | callArgRank(call, index, instr) and arg = tvalueNumber(instr) @@ -91,28 +105,13 @@ private predicate callArgValueNumber(CallInstruction call, int index, TValueNumb * Holds if `arg` is the `index`th element in `call`'s extended argument list, including the `this` * argument and side-effect reads. */ -private predicate callArgRank(CallInstruction call, int index, Instruction arg) { +private predicate callArgRank(NumberableCallInstruction call, int index, Instruction arg) { arg = rank[index](int argIndex, boolean isEffect, Instruction instr | - exists(CallSideEffectInstruction cse | - cse.getPrimaryInstruction() = call and - cse.getSideEffectOperand().getAnyDef() = instr and - argIndex = -2 and - isEffect = true - ) - or - exists(CallReadSideEffectInstruction cse | - cse.getPrimaryInstruction() = call and - cse.getSideEffectOperand().getAnyDef() = instr and - argIndex = -2 and - isEffect = true - ) - or - instr = call.getThisArgument() and - argIndex = -1 and - isEffect = false - or - instr = call.getPositionalArgument(argIndex) and + // There is no need to include the call's read and write side effects on + // all-aliased-memory as `NumberableCallInstruction`s do not read or write + // to all-aliased-memory. + instr = call.getArgument(argIndex) and isEffect = false or exists(ReadSideEffectInstruction read | @@ -177,7 +176,7 @@ private predicate numberableInstruction(Instruction instr) { or instr instanceof LoadTotalOverlapInstruction or - instr instanceof CallInstruction + instr instanceof NumberableCallInstruction } private predicate filteredNumberableInstruction(Instruction instr) { diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingImports.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingImports.qll index 34bd754692d6..6ea20d2b4df2 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingImports.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingImports.qll @@ -1,3 +1,4 @@ import experimental.ir.internal.Overlap import experimental.ir.internal.IRCSharpLanguage as Language import experimental.ir.implementation.unaliased_ssa.IR +import experimental.ir.interfaces.SideEffect as SideEffect diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll index 4fb9bc42e827..d8862dcaa07f 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll @@ -44,16 +44,30 @@ newtype TValueNumber = TCallValueNumber(TCallPartialValueNumber vn) { callValueNumber(_, _, vn) } or TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) } +private class NumberableCallInstruction extends CallInstruction { + NumberableCallInstruction() { + not this.getResultIRType() instanceof IRVoidType and + exists(SideEffect::SideEffectFunction sideEffectFunc | + sideEffectFunc = this.getStaticCallTarget() + | + sideEffectFunc.hasOnlySpecificReadSideEffects() and + sideEffectFunc.hasOnlySpecificWriteSideEffects() + ) + } +} + private newtype TCallPartialValueNumber = TNilArgument() or TArgument(TCallPartialValueNumber head, TValueNumber arg) { - exists(CallInstruction call, int index | + exists(NumberableCallInstruction call, int index | callArgValueNumber(call, index, arg) and callPartialValueNumber(call, index, head) ) } -private predicate callValueNumber(CallInstruction call, int index, TCallPartialValueNumber vn) { +private predicate callValueNumber( + NumberableCallInstruction call, int index, TCallPartialValueNumber vn +) { index = max(int n | callArgRank(call, n, _) | n) and exists(TCallPartialValueNumber head, TValueNumber arg | callPartialValueNumber(call, index, pragma[only_bind_out](head)) and @@ -61,14 +75,15 @@ private predicate callValueNumber(CallInstruction call, int index, TCallPartialV vn = TArgument(head, arg) ) or - not call.getResultIRType() instanceof IRVoidType and not exists(int n | callArgRank(call, n, _)) and index = -1 and vn = TNilArgument() } -private predicate callPartialValueNumber(CallInstruction call, int index, TCallPartialValueNumber head) { - index = 1 and head = TNilArgument() and not call.getResultIRType() instanceof IRVoidType +private predicate callPartialValueNumber( + NumberableCallInstruction call, int index, TCallPartialValueNumber head +) { + index = 1 and head = TNilArgument() or exists(TCallPartialValueNumber prev, TValueNumber prevVN | callPartialValueNumber(call, index - 1, pragma[only_bind_out](prev)) and @@ -79,8 +94,7 @@ private predicate callPartialValueNumber(CallInstruction call, int index, TCallP /** */ -private predicate callArgValueNumber(CallInstruction call, int index, TValueNumber arg) { - not call.getResultIRType() instanceof IRVoidType and +private predicate callArgValueNumber(NumberableCallInstruction call, int index, TValueNumber arg) { exists(Instruction instr | callArgRank(call, index, instr) and arg = tvalueNumber(instr) @@ -91,28 +105,13 @@ private predicate callArgValueNumber(CallInstruction call, int index, TValueNumb * Holds if `arg` is the `index`th element in `call`'s extended argument list, including the `this` * argument and side-effect reads. */ -private predicate callArgRank(CallInstruction call, int index, Instruction arg) { +private predicate callArgRank(NumberableCallInstruction call, int index, Instruction arg) { arg = rank[index](int argIndex, boolean isEffect, Instruction instr | - exists(CallSideEffectInstruction cse | - cse.getPrimaryInstruction() = call and - cse.getSideEffectOperand().getAnyDef() = instr and - argIndex = -2 and - isEffect = true - ) - or - exists(CallReadSideEffectInstruction cse | - cse.getPrimaryInstruction() = call and - cse.getSideEffectOperand().getAnyDef() = instr and - argIndex = -2 and - isEffect = true - ) - or - instr = call.getThisArgument() and - argIndex = -1 and - isEffect = false - or - instr = call.getPositionalArgument(argIndex) and + // There is no need to include the call's read and write side effects on + // all-aliased-memory as `NumberableCallInstruction`s do not read or write + // to all-aliased-memory. + instr = call.getArgument(argIndex) and isEffect = false or exists(ReadSideEffectInstruction read | @@ -177,7 +176,7 @@ private predicate numberableInstruction(Instruction instr) { or instr instanceof LoadTotalOverlapInstruction or - instr instanceof CallInstruction + instr instanceof NumberableCallInstruction } private predicate filteredNumberableInstruction(Instruction instr) { diff --git a/csharp/ql/src/experimental/ir/interfaces/SideEffect.qll b/csharp/ql/src/experimental/ir/interfaces/SideEffect.qll new file mode 100644 index 000000000000..555955d22e76 --- /dev/null +++ b/csharp/ql/src/experimental/ir/interfaces/SideEffect.qll @@ -0,0 +1,24 @@ +private import csharp as CSharp + +/** + * Models the side effects of a library function. + */ +abstract class SideEffectFunction extends CSharp::Callable { + /** + * Holds if the function never reads from memory that was defined before entry to the function. + * This memory could be from global variables, or from other memory that was reachable from a + * pointer that was passed into the function. Input side-effects, and reads from memory that + * cannot be visible to the caller (for example a buffer inside an I/O library) are not modeled + * here. + */ + abstract predicate hasOnlySpecificReadSideEffects(); + + /** + * Holds if the function never writes to memory that remains allocated after the function + * returns. This memory could be from global variables, or from other memory that was reachable + * from a pointer that was passed into the function. Output side-effects, and writes to memory + * that cannot be visible to the caller (for example a buffer inside an I/O library) are not + * modeled here. + */ + abstract predicate hasOnlySpecificWriteSideEffects(); +} From 9f17bd0d89e5625bdedb4b066b07f0eb295298ed Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Thu, 25 Aug 2022 15:51:10 +0100 Subject: [PATCH 14/19] C++: Accept test changes. --- .../syntax-zoo/dataflow-ir-consistency.expected | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected b/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected index 044257ed9522..d7eab0ce9187 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected @@ -149,9 +149,6 @@ uniqueNodeLocation | conditional_destructors.cpp:29:6:29:7 | EnterFunction | Node should have one location but has 2. | | conditional_destructors.cpp:29:6:29:7 | ExitFunction | Node should have one location but has 2. | | conditional_destructors.cpp:29:6:29:7 | InitializeNonLocal | Node should have one location but has 2. | -| conditional_destructors.cpp:29:6:29:7 | Phi | Node should have one location but has 2. | -| conditional_destructors.cpp:29:6:29:7 | Phi | Node should have one location but has 2. | -| conditional_destructors.cpp:29:6:29:7 | Phi | Node should have one location but has 2. | | conditional_destructors.cpp:29:6:29:7 | ReturnVoid | Node should have one location but has 2. | | conditional_destructors.cpp:29:6:29:7 | SideEffect | Node should have one location but has 2. | | conditional_destructors.cpp:38:6:38:7 | AliasedDefinition | Node should have one location but has 2. | @@ -162,9 +159,6 @@ uniqueNodeLocation | conditional_destructors.cpp:38:6:38:7 | EnterFunction | Node should have one location but has 2. | | conditional_destructors.cpp:38:6:38:7 | ExitFunction | Node should have one location but has 2. | | conditional_destructors.cpp:38:6:38:7 | InitializeNonLocal | Node should have one location but has 2. | -| conditional_destructors.cpp:38:6:38:7 | Phi | Node should have one location but has 2. | -| conditional_destructors.cpp:38:6:38:7 | Phi | Node should have one location but has 2. | -| conditional_destructors.cpp:38:6:38:7 | Phi | Node should have one location but has 2. | | conditional_destructors.cpp:38:6:38:7 | ReturnVoid | Node should have one location but has 2. | | conditional_destructors.cpp:38:6:38:7 | SideEffect | Node should have one location but has 2. | | conditional_destructors.cpp:38:6:38:7 | Unreached | Node should have one location but has 2. | @@ -561,9 +555,6 @@ uniqueNodeLocation | forstmt.cpp:1:6:1:7 | EnterFunction | Node should have one location but has 2. | | forstmt.cpp:1:6:1:7 | ExitFunction | Node should have one location but has 2. | | forstmt.cpp:1:6:1:7 | InitializeNonLocal | Node should have one location but has 2. | -| forstmt.cpp:1:6:1:7 | Phi | Node should have one location but has 2. | -| forstmt.cpp:1:6:1:7 | Phi | Node should have one location but has 2. | -| forstmt.cpp:1:6:1:7 | Phi | Node should have one location but has 2. | | forstmt.cpp:1:6:1:7 | ReturnVoid | Node should have one location but has 2. | | forstmt.cpp:1:6:1:7 | SideEffect | Node should have one location but has 2. | | forstmt.cpp:8:6:8:7 | AliasedDefinition | Node should have one location but has 2. | @@ -574,9 +565,6 @@ uniqueNodeLocation | forstmt.cpp:8:6:8:7 | EnterFunction | Node should have one location but has 2. | | forstmt.cpp:8:6:8:7 | ExitFunction | Node should have one location but has 2. | | forstmt.cpp:8:6:8:7 | InitializeNonLocal | Node should have one location but has 2. | -| forstmt.cpp:8:6:8:7 | Phi | Node should have one location but has 2. | -| forstmt.cpp:8:6:8:7 | Phi | Node should have one location but has 2. | -| forstmt.cpp:8:6:8:7 | Phi | Node should have one location but has 2. | | forstmt.cpp:8:6:8:7 | ReturnVoid | Node should have one location but has 2. | | forstmt.cpp:8:6:8:7 | SideEffect | Node should have one location but has 2. | | forstmt.cpp:8:6:8:7 | Unreached | Node should have one location but has 2. | From e13ae70eeb0ce559799f93dc7d9aa7da109bef06 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Fri, 26 Aug 2022 09:06:38 +0100 Subject: [PATCH 15/19] C++: Autoformat. --- .../implementation/aliased_ssa/Instruction.qll | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll index 3679b9e9bce4..264cc7d9bf63 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll @@ -1714,13 +1714,9 @@ class CallSideEffectInstruction extends SideEffectInstruction { CallSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallSideEffect } /** Gets the operand for the value that will be read by this instruction */ - final SideEffectOperand getSideEffectOperand() { - result = this.getAnOperand() - } + final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() } - final Instruction getSideEffect() { - result = this.getAnOperand().getDef() - } + final Instruction getSideEffect() { result = this.getAnOperand().getDef() } } /** @@ -1732,15 +1728,11 @@ class CallSideEffectInstruction extends SideEffectInstruction { */ class CallReadSideEffectInstruction extends SideEffectInstruction { CallReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallReadSideEffect } - + /** Gets the operand for the value that will be read by this instruction */ - final SideEffectOperand getSideEffectOperand() { - result = this.getAnOperand() - } + final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() } - final Instruction getSideEffect() { - result = this.getAnOperand().getDef() - } + final Instruction getSideEffect() { result = this.getAnOperand().getDef() } } /** From 5b51fcbd3d0b8226f0007151753b2ccfd7a6cc5f Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Fri, 26 Aug 2022 09:07:08 +0100 Subject: [PATCH 16/19] C++: Suppress Code Scanning warning. --- .../aliased_ssa/gvn/internal/ValueNumberingInternal.qll | 1 + 1 file changed, 1 insertion(+) 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 d8862dcaa07f..fce87447110c 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 @@ -83,6 +83,7 @@ private predicate callValueNumber( private predicate callPartialValueNumber( NumberableCallInstruction call, int index, TCallPartialValueNumber head ) { + exists(call) and index = 1 and head = TNilArgument() or exists(TCallPartialValueNumber prev, TValueNumber prevVN | From 99b21b3d799174852b8e6b0b6c0e0eac6274fc65 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Fri, 26 Aug 2022 09:07:24 +0100 Subject: [PATCH 17/19] C++: Accept test changes. --- .../ir/ir/operand_locations.expected | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/cpp/ql/test/library-tests/ir/ir/operand_locations.expected b/cpp/ql/test/library-tests/ir/ir/operand_locations.expected index 410a1bed5006..ec373aa5dd15 100644 --- a/cpp/ql/test/library-tests/ir/ir/operand_locations.expected +++ b/cpp/ql/test/library-tests/ir/ir/operand_locations.expected @@ -8430,20 +8430,17 @@ | ir.cpp:1839:12:1839:12 | Address | &:r1839_7 | | ir.cpp:1839:12:1839:12 | Address | &:r1839_9 | | ir.cpp:1839:12:1839:12 | Address | &:r1839_12 | -| ir.cpp:1839:12:1839:12 | Address | &:r1839_20 | +| ir.cpp:1839:12:1839:12 | Address | &:r1839_18 | | ir.cpp:1839:12:1839:12 | Arg(this) | this:r0_5 | | ir.cpp:1839:12:1839:12 | CallTarget | func:r1839_11 | | ir.cpp:1839:12:1839:12 | ChiPartial | partial:m1839_3 | -| ir.cpp:1839:12:1839:12 | ChiPartial | partial:m1839_17 | | ir.cpp:1839:12:1839:12 | ChiTotal | total:m1839_2 | -| ir.cpp:1839:12:1839:12 | ChiTotal | total:m1839_4 | | ir.cpp:1839:12:1839:12 | Load | m0_2 | | ir.cpp:1839:12:1839:12 | Load | m0_21 | | ir.cpp:1839:12:1839:12 | Load | m1839_6 | | ir.cpp:1839:12:1839:12 | Load | m1839_6 | | ir.cpp:1839:12:1839:12 | SideEffect | m0_12 | -| ir.cpp:1839:12:1839:12 | SideEffect | ~m1839_4 | -| ir.cpp:1839:12:1839:12 | SideEffect | ~m1839_18 | +| ir.cpp:1839:12:1839:12 | SideEffect | m1839_3 | | ir.cpp:1839:12:1839:12 | Unary | r1839_10 | | ir.cpp:1839:12:1839:12 | Unary | r1839_13 | | ir.cpp:1839:12:1839:12 | Unary | r1839_14 | @@ -8451,7 +8448,7 @@ | ir.cpp:1839:12:1839:12 | Unary | r1839_16 | | ir.cpp:1843:10:1843:12 | ChiPartial | partial:m1843_3 | | ir.cpp:1843:10:1843:12 | ChiTotal | total:m1843_2 | -| ir.cpp:1843:10:1843:12 | SideEffect | ~m1845_18 | +| ir.cpp:1843:10:1843:12 | SideEffect | ~m1845_14 | | ir.cpp:1844:11:1844:11 | Address | &:r1844_1 | | ir.cpp:1844:11:1844:11 | Address | &:r1844_1 | | ir.cpp:1844:11:1844:11 | Arg(this) | this:r1844_1 | @@ -8470,13 +8467,10 @@ | ir.cpp:1845:9:1845:9 | Address | &:r1845_1 | | ir.cpp:1845:9:1845:9 | Address | &:r1845_1 | | ir.cpp:1845:9:1845:9 | Arg(this) | this:r1845_1 | -| ir.cpp:1845:9:1845:9 | ChiPartial | partial:m1845_21 | +| ir.cpp:1845:9:1845:9 | ChiPartial | partial:m1845_19 | | ir.cpp:1845:9:1845:9 | ChiTotal | total:m1844_10 | | ir.cpp:1845:9:1845:9 | SideEffect | m1844_10 | | ir.cpp:1845:11:1845:11 | CallTarget | func:r1845_2 | -| ir.cpp:1845:11:1845:11 | ChiPartial | partial:m1845_17 | -| ir.cpp:1845:11:1845:11 | ChiTotal | total:m1845_14 | -| ir.cpp:1845:11:1845:11 | SideEffect | ~m1845_14 | | ir.cpp:1845:11:1845:11 | Unary | r1845_16 | | ir.cpp:1845:13:1845:13 | Address | &:r1845_3 | | ir.cpp:1845:13:1845:13 | Address | &:r1845_3 | @@ -8491,7 +8485,7 @@ | ir.cpp:1845:13:1845:13 | ChiPartial | partial:m1845_8 | | ir.cpp:1845:13:1845:13 | ChiPartial | partial:m1845_11 | | ir.cpp:1845:13:1845:13 | ChiPartial | partial:m1845_13 | -| ir.cpp:1845:13:1845:13 | ChiPartial | partial:m1845_23 | +| ir.cpp:1845:13:1845:13 | ChiPartial | partial:m1845_21 | | ir.cpp:1845:13:1845:13 | ChiTotal | total:m1844_12 | | ir.cpp:1845:13:1845:13 | ChiTotal | total:m1845_4 | | ir.cpp:1845:13:1845:13 | ChiTotal | total:m1845_9 | From ba1005f875aaa0b5e2ad7b1c070f1d43b6b8d60b Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Fri, 26 Aug 2022 09:07:38 +0100 Subject: [PATCH 18/19] C#: Fix Code Scanning alert. --- csharp/ql/src/experimental/ir/interfaces/SideEffect.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csharp/ql/src/experimental/ir/interfaces/SideEffect.qll b/csharp/ql/src/experimental/ir/interfaces/SideEffect.qll index 555955d22e76..8e3f37d2aa60 100644 --- a/csharp/ql/src/experimental/ir/interfaces/SideEffect.qll +++ b/csharp/ql/src/experimental/ir/interfaces/SideEffect.qll @@ -1,7 +1,7 @@ private import csharp as CSharp /** - * Models the side effects of a library function. + * A class that models the side effects of a library function. */ abstract class SideEffectFunction extends CSharp::Callable { /** From 9ddacf55a56ccb155966fd4651382054029dd373 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Fri, 26 Aug 2022 09:07:53 +0100 Subject: [PATCH 19/19] C++/C#: Sync identical files. --- .../gvn/internal/ValueNumberingInternal.qll | 3 ++- .../cpp/ir/implementation/raw/Instruction.qll | 18 +++++------------- .../gvn/internal/ValueNumberingInternal.qll | 4 +++- .../unaliased_ssa/Instruction.qll | 18 +++++------------- .../gvn/internal/ValueNumberingInternal.qll | 4 +++- .../ir/implementation/raw/Instruction.qll | 18 +++++------------- .../gvn/internal/ValueNumberingInternal.qll | 4 +++- .../unaliased_ssa/Instruction.qll | 18 +++++------------- .../gvn/internal/ValueNumberingInternal.qll | 4 +++- 9 files changed, 34 insertions(+), 57 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 fce87447110c..b764d804bc57 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 @@ -84,7 +84,8 @@ private predicate callPartialValueNumber( NumberableCallInstruction call, int index, TCallPartialValueNumber head ) { exists(call) and - index = 1 and head = TNilArgument() + index = 1 and + head = TNilArgument() or exists(TCallPartialValueNumber prev, TValueNumber prevVN | callPartialValueNumber(call, index - 1, pragma[only_bind_out](prev)) and diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll index 3679b9e9bce4..264cc7d9bf63 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll @@ -1714,13 +1714,9 @@ class CallSideEffectInstruction extends SideEffectInstruction { CallSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallSideEffect } /** Gets the operand for the value that will be read by this instruction */ - final SideEffectOperand getSideEffectOperand() { - result = this.getAnOperand() - } + final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() } - final Instruction getSideEffect() { - result = this.getAnOperand().getDef() - } + final Instruction getSideEffect() { result = this.getAnOperand().getDef() } } /** @@ -1732,15 +1728,11 @@ class CallSideEffectInstruction extends SideEffectInstruction { */ class CallReadSideEffectInstruction extends SideEffectInstruction { CallReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallReadSideEffect } - + /** Gets the operand for the value that will be read by this instruction */ - final SideEffectOperand getSideEffectOperand() { - result = this.getAnOperand() - } + final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() } - final Instruction getSideEffect() { - result = this.getAnOperand().getDef() - } + final Instruction getSideEffect() { result = this.getAnOperand().getDef() } } /** diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll index d8862dcaa07f..b764d804bc57 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll @@ -83,7 +83,9 @@ private predicate callValueNumber( private predicate callPartialValueNumber( NumberableCallInstruction call, int index, TCallPartialValueNumber head ) { - index = 1 and head = TNilArgument() + exists(call) and + index = 1 and + head = TNilArgument() or exists(TCallPartialValueNumber prev, TValueNumber prevVN | callPartialValueNumber(call, index - 1, pragma[only_bind_out](prev)) and diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll index 3679b9e9bce4..264cc7d9bf63 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll @@ -1714,13 +1714,9 @@ class CallSideEffectInstruction extends SideEffectInstruction { CallSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallSideEffect } /** Gets the operand for the value that will be read by this instruction */ - final SideEffectOperand getSideEffectOperand() { - result = this.getAnOperand() - } + final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() } - final Instruction getSideEffect() { - result = this.getAnOperand().getDef() - } + final Instruction getSideEffect() { result = this.getAnOperand().getDef() } } /** @@ -1732,15 +1728,11 @@ class CallSideEffectInstruction extends SideEffectInstruction { */ class CallReadSideEffectInstruction extends SideEffectInstruction { CallReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallReadSideEffect } - + /** Gets the operand for the value that will be read by this instruction */ - final SideEffectOperand getSideEffectOperand() { - result = this.getAnOperand() - } + final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() } - final Instruction getSideEffect() { - result = this.getAnOperand().getDef() - } + final Instruction getSideEffect() { result = this.getAnOperand().getDef() } } /** diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll index d8862dcaa07f..b764d804bc57 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll @@ -83,7 +83,9 @@ private predicate callValueNumber( private predicate callPartialValueNumber( NumberableCallInstruction call, int index, TCallPartialValueNumber head ) { - index = 1 and head = TNilArgument() + exists(call) and + index = 1 and + head = TNilArgument() or exists(TCallPartialValueNumber prev, TValueNumber prevVN | callPartialValueNumber(call, index - 1, pragma[only_bind_out](prev)) and diff --git a/csharp/ql/src/experimental/ir/implementation/raw/Instruction.qll b/csharp/ql/src/experimental/ir/implementation/raw/Instruction.qll index 3679b9e9bce4..264cc7d9bf63 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/Instruction.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/Instruction.qll @@ -1714,13 +1714,9 @@ class CallSideEffectInstruction extends SideEffectInstruction { CallSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallSideEffect } /** Gets the operand for the value that will be read by this instruction */ - final SideEffectOperand getSideEffectOperand() { - result = this.getAnOperand() - } + final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() } - final Instruction getSideEffect() { - result = this.getAnOperand().getDef() - } + final Instruction getSideEffect() { result = this.getAnOperand().getDef() } } /** @@ -1732,15 +1728,11 @@ class CallSideEffectInstruction extends SideEffectInstruction { */ class CallReadSideEffectInstruction extends SideEffectInstruction { CallReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallReadSideEffect } - + /** Gets the operand for the value that will be read by this instruction */ - final SideEffectOperand getSideEffectOperand() { - result = this.getAnOperand() - } + final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() } - final Instruction getSideEffect() { - result = this.getAnOperand().getDef() - } + final Instruction getSideEffect() { result = this.getAnOperand().getDef() } } /** diff --git a/csharp/ql/src/experimental/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll b/csharp/ql/src/experimental/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll index d8862dcaa07f..b764d804bc57 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll @@ -83,7 +83,9 @@ private predicate callValueNumber( private predicate callPartialValueNumber( NumberableCallInstruction call, int index, TCallPartialValueNumber head ) { - index = 1 and head = TNilArgument() + exists(call) and + index = 1 and + head = TNilArgument() or exists(TCallPartialValueNumber prev, TValueNumber prevVN | callPartialValueNumber(call, index - 1, pragma[only_bind_out](prev)) and diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Instruction.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Instruction.qll index 3679b9e9bce4..264cc7d9bf63 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Instruction.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Instruction.qll @@ -1714,13 +1714,9 @@ class CallSideEffectInstruction extends SideEffectInstruction { CallSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallSideEffect } /** Gets the operand for the value that will be read by this instruction */ - final SideEffectOperand getSideEffectOperand() { - result = this.getAnOperand() - } + final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() } - final Instruction getSideEffect() { - result = this.getAnOperand().getDef() - } + final Instruction getSideEffect() { result = this.getAnOperand().getDef() } } /** @@ -1732,15 +1728,11 @@ class CallSideEffectInstruction extends SideEffectInstruction { */ class CallReadSideEffectInstruction extends SideEffectInstruction { CallReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallReadSideEffect } - + /** Gets the operand for the value that will be read by this instruction */ - final SideEffectOperand getSideEffectOperand() { - result = this.getAnOperand() - } + final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() } - final Instruction getSideEffect() { - result = this.getAnOperand().getDef() - } + final Instruction getSideEffect() { result = this.getAnOperand().getDef() } } /** diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll index d8862dcaa07f..b764d804bc57 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll @@ -83,7 +83,9 @@ private predicate callValueNumber( private predicate callPartialValueNumber( NumberableCallInstruction call, int index, TCallPartialValueNumber head ) { - index = 1 and head = TNilArgument() + exists(call) and + index = 1 and + head = TNilArgument() or exists(TCallPartialValueNumber prev, TValueNumber prevVN | callPartialValueNumber(call, index - 1, pragma[only_bind_out](prev)) and