[hir] Perform alias analysis for aggregate rvalues
Maintain and use abstract memory to peform more refined aliasing of member expressions.
Sathya Gunasekaran committed
Dec 1, 2022 at 19:03 UTC
7bdd0f03cb529f673a632e2a774b6a9de4fec5e4
2 files changed
+85
-26
compiler/forget/src/HIR/BuildAliasSets.ts
+59
@@ -37,6 +37,65 @@ class AbstractState {
37
if (value.kind !== "Primitive") {
38
this.aliases.union([lvalue.place.identifier, alias.identifier]);
39
}
40
+ return;
41
+ }
42
+
43
+ // Complex alias:
44
+ // lvalue = alias.memberPath;
45
+ if (alias.memberPath.length > 1) {
46
+ // TODO(gsn): Handle nested member paths
47
+ return;
48
+ }
49
+
50
+ let object = this.#values.get(alias.identifier);
51
+
52
+ // Don't know what this, let's default to an Object conservatively.
53
+ if (object === undefined) {
54
+ object = { kind: "Object", values: new Map() };
55
+ }
56
+
57
+ // We're doing a member lookup on a non object.
58
+ //
59
+ // alias = 1;
60
+ // lvalue = alias.memberPath;
61
+ if (object.kind !== "Object") {
62
+ // Conservatively type the value as object.
63
+ //
64
+ // NOTE(gsn): Should this be an AbstractUnknown rather than an
65
+ // AbstractObject?
66
+ this.#values.set(lvalue.place.identifier, {
67
+ kind: "Object",
68
+ values: new Map(),
69
+ });
70
+ this.aliases.union([lvalue.place.identifier, alias.identifier]);
71
+ return;
72
+ }
73
+
74
+ let value = object.values.get(alias.memberPath[0]);
75
+
76
+ // We don't have a value for this member path.
77
+ //
78
+ // alias = {};
79
+ // lvalue = alias.memberPath;
80
+ if (value === undefined) {
81
+ // Conservatively type the value as object.
82
+ this.#values.set(lvalue.place.identifier, {
83
+ kind: "Object",
84
+ values: new Map(),
85
+ });
86
+ this.aliases.union([lvalue.place.identifier, alias.identifier]);
87
+ return;
88
+ }
89
+
90
+ // We have a value for this memberPath!
91
+ //
92
+ // alias.memberPath = value;
93
+ // lvalue = alias.memberPath;
94
+ this.#values.set(lvalue.place.identifier, value);
95
+
96
+ // No need to alias Primitives.
97
+ if (value.kind !== "Primitive") {
98
+ this.aliases.union([lvalue.place.identifier, alias.identifier]);
99
}
100
}
101
compiler/forget/src/__tests__/fixtures/hir/component.expect.md
+26
-26
@@ -37,7 +37,7 @@ function Component(props) {
37
bb0:
38
[1] Const mutate items$27_@0 = read props$26.items
39
[2] Const mutate maxItems$28_@1 = read props$26.maxItems
40
- [3] Const mutate renderedItems$29_@2[3:22] = Array []
40
+ [3] Const mutate renderedItems$29_@2[3:26] = Array []
41
[4] Const mutate seen$30_@3[0:19] = New mutate Set$6_@3()
42
[5] Const mutate $31_@4 = 0
43
[6] Const mutate max$32_@5[0:7] = Call mutate Math$8_@5.max(read $31_@4, read maxItems$28_@1)
@@ -71,23 +71,23 @@ bb4:
71
[19] Const mutate $43_@7 = "div"
72
[20] Const mutate $44_@8 = JSX <read $43_@7>{read item$10_@3}</read $43_@7>
73
[21] Call mutate renderedItems$29_@2.push(read $44_@8)
74
- [22] Const mutate $49_@9 = Binary read renderedItems$29_@2.length >= read max$32_@5
75
- [23] If (read $49_@9) then:bb2 else:bb10
74
+ [22] Const mutate $49_@2[3:26] = Binary read renderedItems$29_@2.length >= read max$32_@5
75
+ [23] If (read $49_@2) then:bb2 else:bb10
76
bb10:
77
predecessor blocks: bb4
78
[24] Goto(Continue) bb1
79
bb2:
80
predecessor blocks: bb4 bb1
81
- [25] Const mutate count$52_@10 = read renderedItems$29_@2.length
82
- [26] Const mutate $53_@11 = "div"
83
- [27] Const mutate $54_@12 = "\n "
84
- [28] Const mutate $55_@13 = "h1"
85
- [29] Const mutate $56_@14 = " Items"
86
- [30] Const mutate $57_@15 = JSX <read $55_@13>{freeze count$52_@10}{read $56_@14}</read $55_@13>
87
- [31] Const mutate $58_@16 = "\n "
88
- [32] Const mutate $59_@17 = "\n "
89
- [33] Const mutate $60_@18 = JSX <read $53_@11>{read $54_@12}{read $57_@15}{read $58_@16}{freeze renderedItems$29_@2}{read $59_@17}</read $53_@11>
90
- [34] Return read $60_@18
81
+ [25] Const mutate count$52_@2[3:26] = read renderedItems$29_@2.length
82
+ [26] Const mutate $53_@9 = "div"
83
+ [27] Const mutate $54_@10 = "\n "
84
+ [28] Const mutate $55_@11 = "h1"
85
+ [29] Const mutate $56_@12 = " Items"
86
+ [30] Const mutate $57_@13 = JSX <read $55_@11>{freeze count$52_@2}{read $56_@12}</read $55_@11>
87
+ [31] Const mutate $58_@14 = "\n "
88
+ [32] Const mutate $59_@15 = "\n "
89
+ [33] Const mutate $60_@16 = JSX <read $53_@9>{read $54_@10}{read $57_@13}{read $58_@14}{freeze renderedItems$29_@2}{read $59_@15}</read $53_@9>
90
+ [34] Return read $60_@16
91
scope0 [1:2]:
92
- read props$26.items
93
scope1 [2:3]:
@@ -103,7 +103,7 @@ flowchart TB
103
bb0_instrs["
104
[1] Const mutate items$27_@0 = read props$26.items
105
[2] Const mutate maxItems$28_@1 = read props$26.maxItems
106
- [3] Const mutate renderedItems$29_@2[3:22] = Array []
106
+ [3] Const mutate renderedItems$29_@2[3:26] = Array []
107
[4] Const mutate seen$30_@3[0:19] = New mutate Set$6_@3()
108
[5] Const mutate $31_@4 = 0
109
[6] Const mutate max$32_@5[0:7] = Call mutate Math$8_@5.max(read $31_@4, read maxItems$28_@1)
@@ -144,26 +144,26 @@ flowchart TB
144
[19] Const mutate $43_@7 = 'div'
145
[20] Const mutate $44_@8 = JSX <read $43_@7>{read item$10_@3}</read $43_@7>
146
[21] Call mutate renderedItems$29_@2.push(read $44_@8)
147
- [22] Const mutate $49_@9 = Binary read renderedItems$29_@2.length >= read max$32_@5
147
+ [22] Const mutate $49_@2[3:26] = Binary read renderedItems$29_@2.length >= read max$32_@5
148
"]
149
- bb4_instrs --> bb4_terminal(["If (read $49_@9)"])
149
+ bb4_instrs --> bb4_terminal(["If (read $49_@2)"])
150
end
151
subgraph bb10
152
bb10_terminal(["Goto"])
153
end
154
subgraph bb2
155
bb2_instrs["
156
- [25] Const mutate count$52_@10 = read renderedItems$29_@2.length
157
- [26] Const mutate $53_@11 = 'div'
158
- [27] Const mutate $54_@12 = '\n '
159
- [28] Const mutate $55_@13 = 'h1'
160
- [29] Const mutate $56_@14 = ' Items'
161
- [30] Const mutate $57_@15 = JSX <read $55_@13>{freeze count$52_@10}{read $56_@14}</read $55_@13>
162
- [31] Const mutate $58_@16 = '\n '
163
- [32] Const mutate $59_@17 = '\n '
164
- [33] Const mutate $60_@18 = JSX <read $53_@11>{read $54_@12}{read $57_@15}{read $58_@16}{freeze renderedItems$29_@2}{read $59_@17}</read $53_@11>
156
+ [25] Const mutate count$52_@2[3:26] = read renderedItems$29_@2.length
157
+ [26] Const mutate $53_@9 = 'div'
158
+ [27] Const mutate $54_@10 = '\n '
159
+ [28] Const mutate $55_@11 = 'h1'
160
+ [29] Const mutate $56_@12 = ' Items'
161
+ [30] Const mutate $57_@13 = JSX <read $55_@11>{freeze count$52_@2}{read $56_@12}</read $55_@11>
162
+ [31] Const mutate $58_@14 = '\n '
163
+ [32] Const mutate $59_@15 = '\n '
164
+ [33] Const mutate $60_@16 = JSX <read $53_@9>{read $54_@10}{read $57_@13}{read $58_@14}{freeze renderedItems$29_@2}{read $59_@15}</read $53_@9>
165
"]
166
- bb2_instrs --> bb2_terminal(["Return read $60_@18"])
166
+ bb2_instrs --> bb2_terminal(["Return read $60_@16"])
167
end
168
169
%% Jumps