Skip to content

Commit c27605e

Browse files
rakudramaCommit Queue
authored andcommitted
[dart2js] SSA cleanup
This change essentially converts the complex `SsaOptimizerTask.optimize` method with local functions into a `SsaOptimizerWorkItem` object. - The work item now owns the ranges rather than the global task (which was a kind of leak, although inconsequential). - Moved some optimization phase constructor calls into methods to reduce repeated code. - Factor out code that updates the properties of an invocation. Change-Id: I204acd0a68fd8bc4e64e707ff16f1b743125ff29 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/448421 Reviewed-by: Nate Biggs <[email protected]> Commit-Queue: Stephen Adams <[email protected]>
1 parent 90e1704 commit c27605e

File tree

3 files changed

+127
-145
lines changed

3 files changed

+127
-145
lines changed

pkg/compiler/lib/src/ssa/nodes.dart

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2117,6 +2117,10 @@ class HInvokeClosure extends HInvokeDynamic {
21172117
}
21182118
@override
21192119
R accept<R>(HVisitor<R> visitor) => visitor.visitInvokeClosure(this);
2120+
2121+
@override
2122+
String toString() =>
2123+
'invoke closure: selector=$selector, mask=$receiverType, element=$element';
21202124
}
21212125

21222126
class HInvokeDynamicMethod extends HInvokeDynamic {
@@ -2208,8 +2212,7 @@ class HInvokeDynamicSetter extends HInvokeDynamicField {
22082212
MemberEntity? element,
22092213
List<HInstruction> inputs,
22102214
bool isIntercepted,
2211-
// TODO(johnniwinther): The result type for a setter should be the empty
2212-
// type.
2215+
// TODO(johnniwinther): The result type for a setter should be 'void'.
22132216
AbstractValue resultType,
22142217
SourceInformation? sourceInformation,
22152218
) : super(

pkg/compiler/lib/src/ssa/optimize.dart

Lines changed: 118 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,6 @@ abstract class OptimizationPhase {
6060
class SsaOptimizerTask extends CompilerTask {
6161
final CompilerOptions _options;
6262

63-
Map<HInstruction, Range> ranges = {};
64-
6563
final Map<MemberEntity, OptimizationTestLog> loggersForTesting = {};
6664

6765
SsaOptimizerTask(super.measurer, this._options);
@@ -78,90 +76,112 @@ class SsaOptimizerTask extends CompilerTask {
7876
CodegenRegistry registry,
7977
SsaMetrics metrics,
8078
) {
81-
void runPhase(OptimizationPhase phase) {
82-
measureSubtask(phase.name, () => phase.visitGraph(graph));
83-
codegen.tracer.traceGraph(phase.name, graph);
84-
assert(graph.isValid(), 'Graph not valid after ${phase.name}');
85-
assert(
86-
phase.validPostcondition(graph),
87-
'Graph does not satisfy phase postcondition after ${phase.name}',
88-
);
89-
}
79+
final workItem = SsaOptimizerWorkItem(
80+
this,
81+
member,
82+
graph,
83+
codegen,
84+
closedWorld,
85+
globalInferenceResults,
86+
registry,
87+
metrics,
88+
);
89+
workItem.optimize();
90+
}
91+
}
9092

91-
SsaCodeMotion codeMotion;
92-
SsaLoadElimination loadElimination;
93+
class SsaOptimizerWorkItem {
94+
final SsaOptimizerTask task;
95+
96+
final MemberEntity member;
97+
final HGraph graph;
98+
final CodegenInputs codegen;
99+
final JClosedWorld closedWorld;
100+
final GlobalTypeInferenceResults globalInferenceResults;
101+
final CodegenRegistry registry;
102+
final SsaMetrics metrics;
103+
104+
late final OptimizationTestLog? log = retainDataForTesting
105+
? task.loggersForTesting[member] = OptimizationTestLog(
106+
closedWorld.dartTypes,
107+
)
108+
: null;
109+
110+
late final TypeRecipeDomain typeRecipeDomain = TypeRecipeDomainImpl(
111+
closedWorld.dartTypes,
112+
);
93113

94-
TypeRecipeDomain typeRecipeDomain = TypeRecipeDomainImpl(
95-
closedWorld.dartTypes,
114+
Map<HInstruction, Range> ranges = {};
115+
116+
SsaOptimizerWorkItem(
117+
this.task,
118+
this.member,
119+
this.graph,
120+
this.codegen,
121+
this.closedWorld,
122+
this.globalInferenceResults,
123+
this.registry,
124+
this.metrics,
125+
);
126+
127+
void runPhase(OptimizationPhase phase) {
128+
task.measureSubtask(phase.name, () => phase.visitGraph(graph));
129+
codegen.tracer.traceGraph(phase.name, graph);
130+
assert(graph.isValid(), 'Graph not valid after ${phase.name}');
131+
assert(
132+
phase.validPostcondition(graph),
133+
'Graph does not satisfy phase postcondition after ${phase.name}',
96134
);
135+
}
97136

98-
OptimizationTestLog? log;
99-
if (retainDataForTesting) {
100-
log = loggersForTesting[member] = OptimizationTestLog(
101-
closedWorld.dartTypes,
102-
);
103-
}
137+
SsaInstructionSimplifier simplifierPhase({
138+
bool beforeTypePropagation = false,
139+
}) {
140+
return SsaInstructionSimplifier(
141+
globalInferenceResults,
142+
task._options,
143+
closedWorld,
144+
typeRecipeDomain,
145+
registry,
146+
log,
147+
metrics,
148+
beforeTypePropagation: beforeTypePropagation,
149+
);
150+
}
104151

105-
measure(() {
152+
SsaTypePropagator typePropagatorPhase() {
153+
return SsaTypePropagator(
154+
globalInferenceResults,
155+
closedWorld.commonElements,
156+
closedWorld,
157+
log,
158+
);
159+
}
160+
161+
void optimize() {
162+
SsaCodeMotion codeMotion;
163+
SsaLoadElimination loadElimination;
164+
165+
task.measure(() {
106166
List<OptimizationPhase> phases = [
107167
// Run trivial instruction simplification first to optimize some
108168
// patterns useful for type conversion.
109-
SsaInstructionSimplifier(
110-
globalInferenceResults,
111-
_options,
112-
closedWorld,
113-
typeRecipeDomain,
114-
registry,
115-
log,
116-
metrics,
117-
beforeTypePropagation: true,
118-
),
169+
simplifierPhase(beforeTypePropagation: true),
119170
SsaTypeConversionInserter(closedWorld),
120171
SsaRedundantPhiEliminator(),
121172
SsaDeadPhiEliminator(),
122-
SsaTypePropagator(
123-
globalInferenceResults,
124-
closedWorld.commonElements,
125-
closedWorld,
126-
log,
127-
),
173+
typePropagatorPhase(),
128174
// After type propagation, more instructions can be simplified.
129-
SsaInstructionSimplifier(
130-
globalInferenceResults,
131-
_options,
132-
closedWorld,
133-
typeRecipeDomain,
134-
registry,
135-
log,
136-
metrics,
137-
),
138-
SsaInstructionSimplifier(
139-
globalInferenceResults,
140-
_options,
141-
closedWorld,
142-
typeRecipeDomain,
143-
registry,
144-
log,
145-
metrics,
146-
),
147-
SsaTypePropagator(
148-
globalInferenceResults,
149-
closedWorld.commonElements,
150-
closedWorld,
151-
log,
152-
),
175+
simplifierPhase(),
176+
simplifierPhase(),
177+
typePropagatorPhase(),
153178
// Run a dead code eliminator before LICM because dead
154179
// interceptors are often in the way of LICM'able instructions.
155180
SsaDeadCodeEliminator(closedWorld, this),
156181
SsaGlobalValueNumberer(closedWorld.abstractValueDomain),
157182
// After GVN, some instructions might need their type to be
158183
// updated because they now have different inputs.
159-
SsaTypePropagator(
160-
globalInferenceResults,
161-
closedWorld.commonElements,
162-
closedWorld,
163-
log,
164-
),
184+
typePropagatorPhase(),
165185
codeMotion = SsaCodeMotion(closedWorld.abstractValueDomain),
166186
loadElimination = SsaLoadElimination(closedWorld),
167187
SsaRedundantPhiEliminator(),
@@ -171,29 +191,16 @@ class SsaOptimizerTask extends CompilerTask {
171191
// controlled by a test on the value, so redo 'conversion insertion' to
172192
// learn from the refined type.
173193
SsaTypeConversionInserter(closedWorld),
174-
SsaTypePropagator(
175-
globalInferenceResults,
176-
closedWorld.commonElements,
177-
closedWorld,
178-
log,
179-
),
194+
typePropagatorPhase(),
180195
SsaValueRangeAnalyzer(closedWorld, this, codegen.tracer),
181196
// Previous optimizations may have generated new
182197
// opportunities for instruction simplification.
183-
SsaInstructionSimplifier(
184-
globalInferenceResults,
185-
_options,
186-
closedWorld,
187-
typeRecipeDomain,
188-
registry,
189-
log,
190-
metrics,
191-
),
198+
simplifierPhase(),
192199
];
193200
phases.forEach(runPhase);
194201

195-
// Simplifying interceptors is just an optimization, it is required for
196-
// implementation correctness because the code generator assumes it is
202+
// Simplifying interceptors is not just an optimization, it is required
203+
// for implementation correctness because the code generator assumes it is
197204
// always performed to compute the intercepted classes sets.
198205
runPhase(SsaSimplifyInterceptors(closedWorld, member.enclosingClass));
199206

@@ -204,46 +211,20 @@ class SsaOptimizerTask extends CompilerTask {
204211
dce.newGvnCandidates ||
205212
loadElimination.newGvnCandidates) {
206213
phases = [
207-
SsaTypePropagator(
208-
globalInferenceResults,
209-
closedWorld.commonElements,
210-
closedWorld,
211-
log,
212-
),
214+
typePropagatorPhase(),
213215
SsaGlobalValueNumberer(closedWorld.abstractValueDomain),
214216
SsaCodeMotion(closedWorld.abstractValueDomain),
215217
SsaValueRangeAnalyzer(closedWorld, this, codegen.tracer),
216-
SsaInstructionSimplifier(
217-
globalInferenceResults,
218-
_options,
219-
closedWorld,
220-
typeRecipeDomain,
221-
registry,
222-
log,
223-
metrics,
224-
),
218+
simplifierPhase(),
225219
SsaSimplifyInterceptors(closedWorld, member.enclosingClass),
226220
SsaDeadCodeEliminator(closedWorld, this),
227221
];
228222
} else {
229223
phases = [
230-
SsaTypePropagator(
231-
globalInferenceResults,
232-
closedWorld.commonElements,
233-
closedWorld,
234-
log,
235-
),
224+
typePropagatorPhase(),
236225
// Run the simplifier to remove unneeded type checks inserted by
237226
// type propagation.
238-
SsaInstructionSimplifier(
239-
globalInferenceResults,
240-
_options,
241-
closedWorld,
242-
typeRecipeDomain,
243-
registry,
244-
log,
245-
metrics,
246-
),
227+
simplifierPhase(),
247228
];
248229
}
249230
phases.forEach(runPhase);
@@ -1028,6 +1009,8 @@ class SsaInstructionSimplifier extends HBaseVisitor<HInstruction>
10281009
resultMask,
10291010
const <DartType>[],
10301011
);
1012+
_updateInvocationAttributes(tagInstruction, commonElements.setArrayType);
1013+
10311014
// 'Linear typing' trick: [tagInstruction] is the only use of the
10321015
// [splitInstruction], so it becomes the sole alias.
10331016
// TODO(sra): Build this knowledge into alias analysis.
@@ -1073,15 +1056,7 @@ class SsaInstructionSimplifier extends HBaseVisitor<HInstruction>
10731056
node.element = method;
10741057
}
10751058

1076-
node.sideEffects.restrictTo(
1077-
_globalInferenceResults.inferredData.getSideEffectsOfElement(element),
1078-
);
1079-
if (_closedWorld.annotationsData.allowCSE(element)) {
1080-
node.allowCSE = true;
1081-
}
1082-
if (_closedWorld.annotationsData.allowDCE(element)) {
1083-
node.allowDCE = true;
1084-
}
1059+
_updateInvocationAttributes(node, method);
10851060

10861061
return node;
10871062
}
@@ -2091,15 +2066,7 @@ class SsaInstructionSimplifier extends HBaseVisitor<HInstruction>
20912066
if (_nativeData.isNativeMember(member)) {
20922067
return tryInlineNativeGetter(node, member) ?? node;
20932068
}
2094-
node.sideEffects.restrictTo(
2095-
_globalInferenceResults.inferredData.getSideEffectsOfElement(member),
2096-
);
2097-
if (_closedWorld.annotationsData.allowCSE(member)) {
2098-
node.allowCSE = true;
2099-
}
2100-
if (_closedWorld.annotationsData.allowDCE(member)) {
2101-
node.allowDCE = true;
2102-
}
2069+
_updateInvocationAttributes(node, member);
21032070
}
21042071
}
21052072

@@ -2113,6 +2080,18 @@ class SsaInstructionSimplifier extends HBaseVisitor<HInstruction>
21132080
return node;
21142081
}
21152082

2083+
void _updateInvocationAttributes(HInvoke node, FunctionEntity member) {
2084+
node.sideEffects.restrictTo(
2085+
_globalInferenceResults.inferredData.getSideEffectsOfElement(member),
2086+
);
2087+
if (_closedWorld.annotationsData.allowCSE(member)) {
2088+
node.allowCSE = true;
2089+
}
2090+
if (_closedWorld.annotationsData.allowDCE(member)) {
2091+
node.allowDCE = true;
2092+
}
2093+
}
2094+
21162095
HFieldGet _directFieldGet(
21172096
HInstruction receiver,
21182097
FieldEntity field,
@@ -3197,13 +3176,13 @@ class SsaDeadCodeEliminator extends HGraphVisitor implements OptimizationPhase {
31973176
final String name = "SsaDeadCodeEliminator";
31983177

31993178
final JClosedWorld closedWorld;
3200-
final SsaOptimizerTask optimizer;
3179+
final SsaOptimizerWorkItem workItem;
32013180
late final HGraph _graph;
32023181
Map<HInstruction, bool> trivialDeadStoreReceivers = Maplet();
32033182
bool eliminatedSideEffects = false;
32043183
bool newGvnCandidates = false;
32053184

3206-
SsaDeadCodeEliminator(this.closedWorld, this.optimizer);
3185+
SsaDeadCodeEliminator(this.closedWorld, this.workItem);
32073186

32083187
AbstractValueDomain get _abstractValueDomain =>
32093188
closedWorld.abstractValueDomain;
@@ -3261,7 +3240,7 @@ class SsaDeadCodeEliminator extends HGraphVisitor implements OptimizationPhase {
32613240
}
32623241

32633242
void _computeLiveness() {
3264-
var analyzer = SsaLiveBlockAnalyzer(_graph, closedWorld, optimizer);
3243+
var analyzer = SsaLiveBlockAnalyzer(_graph, closedWorld, workItem);
32653244
analyzer.analyze();
32663245
for (HBasicBlock block in _graph.blocks) {
32673246
block.isLive = analyzer.isLiveBlock(block);
@@ -3511,15 +3490,15 @@ class SsaLiveBlockAnalyzer extends HBaseVisitor<void> {
35113490
final HGraph graph;
35123491
final Set<HBasicBlock> live = {};
35133492
final List<HBasicBlock> worklist = [];
3514-
final SsaOptimizerTask optimizer;
3493+
final SsaOptimizerWorkItem workItem;
35153494
final JClosedWorld closedWorld;
35163495

3517-
SsaLiveBlockAnalyzer(this.graph, this.closedWorld, this.optimizer);
3496+
SsaLiveBlockAnalyzer(this.graph, this.closedWorld, this.workItem);
35183497

35193498
AbstractValueDomain get _abstractValueDomain =>
35203499
closedWorld.abstractValueDomain;
35213500

3522-
Map<HInstruction, Range> get ranges => optimizer.ranges;
3501+
Map<HInstruction, Range> get ranges => workItem.ranges;
35233502

35243503
bool isLiveBlock(HBasicBlock block) => live.contains(block);
35253504

0 commit comments

Comments
 (0)