Skip to content

Commit 779edbf

Browse files
committed
Go CFG: merge result-var 'result-init' node into 'result-zero-init'
A named result variable previously created two additional nodes: 'result-zero-init:i' computing the zero value, and 'result-init:i' writing that value into the result variable. The result-init node existed only to write the value already computed by result-zero-init. Make the result-zero-init instruction perform the write itself (InitResultInstruction is now keyed on result-zero-init with its own value as RHS) and drop the separate result-init node. All zero-value constant semantics stay on the same node, so GVN and constant analysis are unchanged; the only data-flow change is the SSA def relabeling (result-init -> result-zero-init) with no flow loss.
1 parent 585f021 commit 779edbf

4 files changed

Lines changed: 33 additions & 55 deletions

File tree

go/ql/lib/semmle/go/controlflow/ControlFlowGraphShared.qll

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -569,15 +569,9 @@ module GoCfg {
569569
tag = "param-init:" + i.toString()
570570
)
571571
or
572-
// Result variable init (on the function body)
573-
exists(int i, Go::FuncDef fd |
574-
n = fd.getBody() and
575-
exists(fd.getBody()) and
576-
exists(fd.getResultVar(i)) and
577-
tag = "result-init:" + i.toString()
578-
)
579-
or
580-
// Result variable zero init (on the function body)
572+
// Result variable zero init + init (on the function body). This single
573+
// node computes the zero value and writes it to the result variable (see
574+
// `IR::InitResultInstruction`).
581575
exists(int i, Go::FuncDef fd |
582576
n = fd.getBody() and
583577
exists(fd.getBody()) and
@@ -1731,7 +1725,7 @@ module GoCfg {
17311725
* Function definition prologue and epilogue:
17321726
* - Prologue: Before(body) → param-init:-1 → param-init:0 → ... when a
17331727
* receiver exists; otherwise it starts at param-init:0. Then
1734-
* result-zero-init:0 → result-init:0 → ... → first statement
1728+
* result-zero-init:0 → result-zero-init:1 → ... → first statement
17351729
* - Epilogue: return → result-read:0 → result-read:1 → ... → result-read:last
17361730
*
17371731
* The last result-read node goes to `NormalExit(fd)` via the shared
@@ -1812,15 +1806,11 @@ module GoCfg {
18121806
)
18131807
)
18141808
or
1815-
// result-zero-init:j → result-init:j (for each result variable)
1809+
// result-zero-init:j → next: result-zero-init:(j+1), or Before(body).
1810+
// The zero-init node also writes the result variable (see
1811+
// `IR::InitResultInstruction`), so there is no separate result-init node.
18161812
exists(int j | exists(fd.getResultVar(j)) |
18171813
n1.isAdditional(fd.getBody(), "result-zero-init:" + j.toString()) and
1818-
n2.isAdditional(fd.getBody(), "result-init:" + j.toString())
1819-
)
1820-
or
1821-
// result-init:j → next: result-zero-init:(j+1), or Before(body)
1822-
exists(int j | exists(fd.getResultVar(j)) |
1823-
n1.isAdditional(fd.getBody(), "result-init:" + j.toString()) and
18241814
(
18251815
// Next result var exists
18261816
exists(fd.getResultVar(j + 1)) and

go/ql/lib/semmle/go/controlflow/IR.qll

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,6 @@ module IR {
199199
or
200200
this instanceof InitParameterInstruction and result = "parameter initialization"
201201
or
202-
this instanceof InitResultInstruction and result = "result initialization"
203-
or
204202
this instanceof GetNextEntryInstruction and result = "next key-value pair"
205203
or
206204
this instanceof EvalImplicitTrueInstruction and result = "implicit true"
@@ -1038,22 +1036,24 @@ module IR {
10381036
override ControlFlow::Root getRoot() { result = parm.getFunction() }
10391037
}
10401038

1041-
/** An instruction initializing a result variable to its zero value. */
1039+
/**
1040+
* An instruction initializing a result variable to its zero value.
1041+
*
1042+
* This is the same node as the `EvalImplicitInitInstruction` that computes the
1043+
* zero value: the zero-value instruction performs the write of the result
1044+
* variable directly, rather than feeding a separate write node.
1045+
*/
10421046
class InitResultInstruction extends WriteInstruction {
10431047
ResultVariable res;
10441048
int idx;
10451049
FuncDef fd;
10461050

10471051
InitResultInstruction() {
1048-
this.isAdditional(fd.getBody(), "result-init:" + idx.toString()) and
1052+
this.isAdditional(fd.getBody(), "result-zero-init:" + idx.toString()) and
10491053
res = fd.getResultVar(idx)
10501054
}
10511055

1052-
override Instruction getRhs() {
1053-
result
1054-
.(EvalImplicitInitInstruction)
1055-
.isAdditional(fd.getBody(), "result-zero-init:" + idx.toString())
1056-
}
1056+
override Instruction getRhs() { result = this }
10571057

10581058
override ControlFlow::Root getRoot() { result = res.getFunction() }
10591059
}
@@ -1173,7 +1173,7 @@ module IR {
11731173
)
11741174
or
11751175
exists(FuncDef fd, int idx |
1176-
write.isAdditional(fd.getBody(), "result-init:" + idx.toString()) and
1176+
write.isAdditional(fd.getBody(), "result-zero-init:" + idx.toString()) and
11771177
lhs = fd.getResultVar(idx).getDeclaration()
11781178
)
11791179
} or

go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph/ControlFlowNode_getASuccessor.expected

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -245,12 +245,10 @@
245245
| epilogues.go:42:1:48:1 | function declaration | epilogues.go:42:1:48:1 | After function declaration |
246246
| epilogues.go:42:51:48:1 | block statement | epilogues.go:42:51:48:1 | param-init:0 block statement |
247247
| epilogues.go:42:51:48:1 | param-init:0 block statement | epilogues.go:42:51:48:1 | result-zero-init:0 block statement |
248-
| epilogues.go:42:51:48:1 | result-init:0 block statement | epilogues.go:42:51:48:1 | result-zero-init:1 block statement |
249-
| epilogues.go:42:51:48:1 | result-init:1 block statement | epilogues.go:43:2:46:2 | if statement |
250248
| epilogues.go:42:51:48:1 | result-read:0 block statement | epilogues.go:42:51:48:1 | result-read:1 block statement |
251249
| epilogues.go:42:51:48:1 | result-read:1 block statement | epilogues.go:42:1:48:1 | Normal Exit |
252-
| epilogues.go:42:51:48:1 | result-zero-init:0 block statement | epilogues.go:42:51:48:1 | result-init:0 block statement |
253-
| epilogues.go:42:51:48:1 | result-zero-init:1 block statement | epilogues.go:42:51:48:1 | result-init:1 block statement |
250+
| epilogues.go:42:51:48:1 | result-zero-init:0 block statement | epilogues.go:42:51:48:1 | result-zero-init:1 block statement |
251+
| epilogues.go:42:51:48:1 | result-zero-init:1 block statement | epilogues.go:43:2:46:2 | if statement |
254252
| epilogues.go:43:2:46:2 | After if statement | epilogues.go:47:2:47:14 | Before return statement |
255253
| epilogues.go:43:2:46:2 | if statement | epilogues.go:43:5:43:9 | Before ...<... |
256254
| epilogues.go:43:5:43:5 | After x | epilogues.go:43:9:43:9 | Before 0 |
@@ -293,9 +291,8 @@
293291
| epilogues.go:51:1:54:1 | function declaration | epilogues.go:51:1:54:1 | After function declaration |
294292
| epilogues.go:51:38:54:1 | block statement | epilogues.go:51:38:54:1 | param-init:0 block statement |
295293
| epilogues.go:51:38:54:1 | param-init:0 block statement | epilogues.go:51:38:54:1 | result-zero-init:0 block statement |
296-
| epilogues.go:51:38:54:1 | result-init:0 block statement | epilogues.go:52:2:52:10 | ... = ... |
297294
| epilogues.go:51:38:54:1 | result-read:0 block statement | epilogues.go:51:1:54:1 | Normal Exit |
298-
| epilogues.go:51:38:54:1 | result-zero-init:0 block statement | epilogues.go:51:38:54:1 | result-init:0 block statement |
295+
| epilogues.go:51:38:54:1 | result-zero-init:0 block statement | epilogues.go:52:2:52:10 | ... = ... |
299296
| epilogues.go:52:2:52:10 | ... = ... | epilogues.go:52:6:52:10 | Before ...+... |
300297
| epilogues.go:52:2:52:10 | After ... = ... | epilogues.go:53:2:53:7 | Before return statement |
301298
| epilogues.go:52:2:52:10 | assign:0 ... = ... | epilogues.go:52:2:52:10 | After ... = ... |
@@ -512,9 +509,8 @@
512509
| epilogues.go:87:1:98:1 | function declaration | epilogues.go:87:1:98:1 | After function declaration |
513510
| epilogues.go:87:42:98:1 | block statement | epilogues.go:87:42:98:1 | param-init:0 block statement |
514511
| epilogues.go:87:42:98:1 | param-init:0 block statement | epilogues.go:87:42:98:1 | result-zero-init:0 block statement |
515-
| epilogues.go:87:42:98:1 | result-init:0 block statement | epilogues.go:88:2:92:4 | Before defer statement |
516512
| epilogues.go:87:42:98:1 | result-read:0 block statement | epilogues.go:87:1:98:1 | Normal Exit |
517-
| epilogues.go:87:42:98:1 | result-zero-init:0 block statement | epilogues.go:87:42:98:1 | result-init:0 block statement |
513+
| epilogues.go:87:42:98:1 | result-zero-init:0 block statement | epilogues.go:88:2:92:4 | Before defer statement |
518514
| epilogues.go:88:2:92:4 | After defer statement | epilogues.go:93:2:95:2 | if statement |
519515
| epilogues.go:88:2:92:4 | Before defer statement | epilogues.go:88:8:92:4 | function call |
520516
| epilogues.go:88:2:92:4 | defer statement | epilogues.go:88:2:92:4 | After defer statement |
@@ -610,12 +606,10 @@
610606
| epilogues.go:102:1:110:1 | function declaration | epilogues.go:102:1:110:1 | After function declaration |
611607
| epilogues.go:102:50:110:1 | block statement | epilogues.go:102:50:110:1 | param-init:0 block statement |
612608
| epilogues.go:102:50:110:1 | param-init:0 block statement | epilogues.go:102:50:110:1 | result-zero-init:0 block statement |
613-
| epilogues.go:102:50:110:1 | result-init:0 block statement | epilogues.go:102:50:110:1 | result-zero-init:1 block statement |
614-
| epilogues.go:102:50:110:1 | result-init:1 block statement | epilogues.go:103:2:103:19 | Before defer statement |
615609
| epilogues.go:102:50:110:1 | result-read:0 block statement | epilogues.go:102:50:110:1 | result-read:1 block statement |
616610
| epilogues.go:102:50:110:1 | result-read:1 block statement | epilogues.go:102:1:110:1 | Normal Exit |
617-
| epilogues.go:102:50:110:1 | result-zero-init:0 block statement | epilogues.go:102:50:110:1 | result-init:0 block statement |
618-
| epilogues.go:102:50:110:1 | result-zero-init:1 block statement | epilogues.go:102:50:110:1 | result-init:1 block statement |
611+
| epilogues.go:102:50:110:1 | result-zero-init:0 block statement | epilogues.go:102:50:110:1 | result-zero-init:1 block statement |
612+
| epilogues.go:102:50:110:1 | result-zero-init:1 block statement | epilogues.go:103:2:103:19 | Before defer statement |
619613
| epilogues.go:103:2:103:19 | After defer statement | epilogues.go:104:2:106:2 | if statement |
620614
| epilogues.go:103:2:103:19 | Before defer statement | epilogues.go:103:8:103:19 | call to epiRecover |
621615
| epilogues.go:103:2:103:19 | defer statement | epilogues.go:103:2:103:19 | After defer statement |
@@ -1292,9 +1286,8 @@
12921286
| exprs.go:49:1:54:1 | function declaration | exprs.go:49:1:54:1 | After function declaration |
12931287
| exprs.go:49:30:54:1 | block statement | exprs.go:49:30:54:1 | param-init:0 block statement |
12941288
| exprs.go:49:30:54:1 | param-init:0 block statement | exprs.go:49:30:54:1 | result-zero-init:0 block statement |
1295-
| exprs.go:49:30:54:1 | result-init:0 block statement | exprs.go:50:2:52:2 | for statement |
12961289
| exprs.go:49:30:54:1 | result-read:0 block statement | exprs.go:49:1:54:1 | Normal Exit |
1297-
| exprs.go:49:30:54:1 | result-zero-init:0 block statement | exprs.go:49:30:54:1 | result-init:0 block statement |
1290+
| exprs.go:49:30:54:1 | result-zero-init:0 block statement | exprs.go:50:2:52:2 | for statement |
12981291
| exprs.go:50:2:52:2 | After for statement | exprs.go:53:2:53:7 | Before return statement |
12991292
| exprs.go:50:2:52:2 | [LoopHeader] for statement | exprs.go:50:27:50:29 | Before increment statement |
13001293
| exprs.go:50:2:52:2 | for statement | exprs.go:50:6:50:11 | ... := ... |
@@ -2143,9 +2136,8 @@
21432136
| main.go:47:1:50:1 | Normal Exit | main.go:47:1:50:1 | Exit |
21442137
| main.go:47:1:50:1 | function declaration | main.go:47:1:50:1 | After function declaration |
21452138
| main.go:47:25:50:1 | block statement | main.go:47:25:50:1 | result-zero-init:0 block statement |
2146-
| main.go:47:25:50:1 | result-init:0 block statement | main.go:48:2:48:12 | ... = ... |
21472139
| main.go:47:25:50:1 | result-read:0 block statement | main.go:47:1:50:1 | Normal Exit |
2148-
| main.go:47:25:50:1 | result-zero-init:0 block statement | main.go:47:25:50:1 | result-init:0 block statement |
2140+
| main.go:47:25:50:1 | result-zero-init:0 block statement | main.go:48:2:48:12 | ... = ... |
21492141
| main.go:48:2:48:12 | ... = ... | main.go:48:11:48:12 | Before 42 |
21502142
| main.go:48:2:48:12 | After ... = ... | main.go:49:2:49:7 | Before return statement |
21512143
| main.go:48:2:48:12 | assign:0 ... = ... | main.go:48:2:48:12 | After ... = ... |
@@ -2160,9 +2152,8 @@
21602152
| main.go:52:1:54:1 | Normal Exit | main.go:52:1:54:1 | Exit |
21612153
| main.go:52:1:54:1 | function declaration | main.go:52:1:54:1 | After function declaration |
21622154
| main.go:52:26:54:1 | block statement | main.go:52:26:54:1 | result-zero-init:0 block statement |
2163-
| main.go:52:26:54:1 | result-init:0 block statement | main.go:53:2:53:7 | Before return statement |
21642155
| main.go:52:26:54:1 | result-read:0 block statement | main.go:52:1:54:1 | Normal Exit |
2165-
| main.go:52:26:54:1 | result-zero-init:0 block statement | main.go:52:26:54:1 | result-init:0 block statement |
2156+
| main.go:52:26:54:1 | result-zero-init:0 block statement | main.go:53:2:53:7 | Before return statement |
21662157
| main.go:53:2:53:7 | Before return statement | main.go:53:2:53:7 | return statement |
21672158
| main.go:53:2:53:7 | return statement | main.go:52:26:54:1 | result-read:0 block statement |
21682159
| main.go:56:1:64:1 | After function declaration | main.go:66:1:90:1 | Before function declaration |
@@ -2172,9 +2163,8 @@
21722163
| main.go:56:1:64:1 | function declaration | main.go:56:1:64:1 | After function declaration |
21732164
| main.go:56:38:64:1 | block statement | main.go:56:38:64:1 | param-init:0 block statement |
21742165
| main.go:56:38:64:1 | param-init:0 block statement | main.go:56:38:64:1 | result-zero-init:0 block statement |
2175-
| main.go:56:38:64:1 | result-init:0 block statement | main.go:57:2:57:11 | ... = ... |
21762166
| main.go:56:38:64:1 | result-read:0 block statement | main.go:56:1:64:1 | Normal Exit |
2177-
| main.go:56:38:64:1 | result-zero-init:0 block statement | main.go:56:38:64:1 | result-init:0 block statement |
2167+
| main.go:56:38:64:1 | result-zero-init:0 block statement | main.go:57:2:57:11 | ... = ... |
21782168
| main.go:57:2:57:11 | ... = ... | main.go:57:11:57:11 | Before 0 |
21792169
| main.go:57:2:57:11 | After ... = ... | main.go:58:2:62:2 | if statement |
21802170
| main.go:57:2:57:11 | assign:0 ... = ... | main.go:57:2:57:11 | After ... = ... |
@@ -2377,12 +2367,10 @@
23772367
| main.go:92:1:96:1 | Normal Exit | main.go:92:1:96:1 | Exit |
23782368
| main.go:92:1:96:1 | function declaration | main.go:92:1:96:1 | After function declaration |
23792369
| main.go:92:36:96:1 | block statement | main.go:92:36:96:1 | result-zero-init:0 block statement |
2380-
| main.go:92:36:96:1 | result-init:0 block statement | main.go:92:36:96:1 | result-zero-init:1 block statement |
2381-
| main.go:92:36:96:1 | result-init:1 block statement | main.go:93:2:93:8 | ... := ... |
23822370
| main.go:92:36:96:1 | result-read:0 block statement | main.go:92:36:96:1 | result-read:1 block statement |
23832371
| main.go:92:36:96:1 | result-read:1 block statement | main.go:92:1:96:1 | Normal Exit |
2384-
| main.go:92:36:96:1 | result-zero-init:0 block statement | main.go:92:36:96:1 | result-init:0 block statement |
2385-
| main.go:92:36:96:1 | result-zero-init:1 block statement | main.go:92:36:96:1 | result-init:1 block statement |
2372+
| main.go:92:36:96:1 | result-zero-init:0 block statement | main.go:92:36:96:1 | result-zero-init:1 block statement |
2373+
| main.go:92:36:96:1 | result-zero-init:1 block statement | main.go:93:2:93:8 | ... := ... |
23862374
| main.go:93:2:93:8 | ... := ... | main.go:93:7:93:8 | Before 23 |
23872375
| main.go:93:2:93:8 | After ... := ... | main.go:94:2:94:15 | ... = ... |
23882376
| main.go:93:2:93:8 | assign:0 ... := ... | main.go:93:2:93:8 | After ... := ... |

go/ql/test/library-tests/semmle/go/dataflow/SSA/VarDefs.expected

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
| main.go:34:19:36:1 | param-init:0 block statement | main.go:34:11:34:11 | x | main.go:34:19:36:1 | param-init:0 block statement |
1111
| main.go:39:2:39:8 | assign:0 ... := ... | main.go:39:2:39:2 | x | main.go:39:7:39:8 | 23 |
1212
| main.go:40:2:40:10 | assign:0 ... := ... | main.go:40:2:40:4 | ptr | main.go:40:9:40:10 | &... |
13-
| main.go:47:25:50:1 | result-init:0 block statement | main.go:47:13:47:18 | result | main.go:47:25:50:1 | result-zero-init:0 block statement |
13+
| main.go:47:25:50:1 | result-zero-init:0 block statement | main.go:47:13:47:18 | result | main.go:47:25:50:1 | result-zero-init:0 block statement |
1414
| main.go:48:2:48:12 | assign:0 ... = ... | main.go:47:13:47:18 | result | main.go:48:11:48:12 | 42 |
15-
| main.go:52:26:54:1 | result-init:0 block statement | main.go:52:14:52:19 | result | main.go:52:26:54:1 | result-zero-init:0 block statement |
15+
| main.go:52:26:54:1 | result-zero-init:0 block statement | main.go:52:14:52:19 | result | main.go:52:26:54:1 | result-zero-init:0 block statement |
1616
| main.go:57:6:57:10 | assign:0 value declaration specifier | main.go:57:6:57:6 | x | main.go:57:6:57:10 | zero-init:0 value declaration specifier |
1717
| main.go:59:3:59:7 | assign:0 ... = ... | main.go:57:6:57:6 | x | main.go:59:7:59:7 | 2 |
1818
| main.go:63:2:63:7 | assign:0 ... := ... | main.go:63:2:63:2 | y | main.go:63:7:63:7 | 1 |
@@ -23,8 +23,8 @@
2323
| main.go:73:6:73:11 | assign:0 ... := ... | main.go:73:6:73:6 | i | main.go:73:11:73:11 | 0 |
2424
| main.go:73:16:73:18 | increment statement | main.go:73:6:73:6 | i | main.go:73:16:73:18 | incdec-rhs increment statement |
2525
| main.go:74:3:74:7 | assign:0 ... = ... | main.go:72:2:72:2 | z | main.go:74:7:74:7 | 2 |
26-
| main.go:82:36:86:1 | result-init:0 block statement | main.go:82:18:82:18 | a | main.go:82:36:86:1 | result-zero-init:0 block statement |
27-
| main.go:82:36:86:1 | result-init:1 block statement | main.go:82:25:82:25 | b | main.go:82:36:86:1 | result-zero-init:1 block statement |
26+
| main.go:82:36:86:1 | result-zero-init:0 block statement | main.go:82:18:82:18 | a | main.go:82:36:86:1 | result-zero-init:0 block statement |
27+
| main.go:82:36:86:1 | result-zero-init:1 block statement | main.go:82:25:82:25 | b | main.go:82:36:86:1 | result-zero-init:1 block statement |
2828
| main.go:83:2:83:8 | assign:0 ... := ... | main.go:83:2:83:2 | x | main.go:83:7:83:8 | 23 |
2929
| main.go:84:2:84:15 | assign:0 ... = ... | main.go:83:2:83:2 | x | main.go:84:9:84:12 | ...+... |
3030
| main.go:84:2:84:15 | assign:1 ... = ... | main.go:82:18:82:18 | a | main.go:84:15:84:15 | x |

0 commit comments

Comments
 (0)