Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(45)

Side by Side Diff: runtime/vm/block_scheduler.cc

Issue 18111006: Collect edge count profiling data and reorder basic blocks. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 #include "vm/block_scheduler.h"
6
7 #include "vm/allocation.h"
8 #include "vm/flow_graph.h"
9
10 namespace dart {
11
12 // Compute the edge count at the deopt id of a TargetEntry or Goto.
13 static intptr_t ComputeEdgeCount(const Code& unoptimized_code,
14 intptr_t deopt_id) {
srdjan 2013/08/14 00:28:24 This seems like quite slow way to extract edge cou
15 ASSERT(deopt_id != Isolate::kNoDeoptId);
16
17 // Intrinsified functions do not have edge counts, so give all edges equal
18 // weights.
srdjan 2013/08/14 00:28:24 Some intrinsified functions should have edge count
19 if (unoptimized_code.pointer_offsets_length() == 0) return 1;
20
21 uword pc = unoptimized_code.GetPcForDeoptId(deopt_id, PcDescriptors::kDeopt);
22 Array& array = Array::Handle();
23 // Pointer offsets are sorted in decreasing order. Find the first one
24 // after the deopt id's pc.
25 // TODO(kmillikin): Use a more reliable way to find the counter.
26 for (intptr_t j = unoptimized_code.pointer_offsets_length() - 1;
27 j >= 0;
28 --j) {
29 uword addr =
30 unoptimized_code.GetPointerOffsetAt(j) + unoptimized_code.EntryPoint();
31 if (addr > pc) {
32 array ^= *reinterpret_cast<RawObject**>(addr);
33 break;
34 }
35 }
36 ASSERT(!array.IsNull());
37 return Smi::Value(Smi::RawCast(array.At(0)));
38 }
39
40
41 // There is an edge from instruction->successor. Set its weight (edge count
42 // per function entry).
43 static void SetEdgeWeight(Instruction* instruction,
44 BlockEntryInstr* successor,
45 const Code& unoptimized_code,
46 intptr_t entry_count) {
47 intptr_t count = -1;
48 double weight = 0.0;
Florian Schneider 2013/08/12 11:30:09 style-nit: I would not hoist these two declaration
Kevin Millikin (Google) 2013/08/13 11:14:57 OK, done.
srdjan 2013/08/14 00:28:24 Could you please upload your changes.
49 TargetEntryInstr* target = successor->AsTargetEntry();
50 if (target != NULL) {
51 count = ComputeEdgeCount(unoptimized_code, target->deopt_id());
52 if ((count >= 0) && (entry_count != 0)) {
53 weight = static_cast<double>(count) / static_cast<double>(entry_count);
54 target->set_edge_weight(weight);
55 }
56 } else {
57 GotoInstr* jump = instruction->AsGoto();
58 if (jump != NULL) {
59 count = ComputeEdgeCount(unoptimized_code, jump->deopt_id());
60 if ((count >= 0) && (entry_count != 0)) {
61 weight = static_cast<double>(count) / static_cast<double>(entry_count);
62 jump->set_edge_weight(weight);
63 }
64 }
65 }
66 }
67
68
69 void BlockScheduler::AssignEdgeWeights() const {
70 const Code& unoptimized_code = Code::Handle(
71 flow_graph()->parsed_function().function().unoptimized_code());
72
73 intptr_t entry_count =
74 ComputeEdgeCount(unoptimized_code,
75 flow_graph()->graph_entry()->normal_entry()->deopt_id());
76 flow_graph()->graph_entry()->set_entry_count(entry_count);
77
78 for (BlockIterator it = flow_graph()->reverse_postorder_iterator();
79 !it.Done();
80 it.Advance()) {
81 BlockEntryInstr* block = it.Current();
82 Instruction* last = block->last_instruction();
83 for (intptr_t i = 0; i < last->SuccessorCount(); ++i) {
84 BlockEntryInstr* succ = last->SuccessorAt(i);
85 SetEdgeWeight(last, succ, unoptimized_code, entry_count);
86 }
87 }
88 }
89
90
91 // A weighted control-flow graph edge.
92 struct Edge {
93 Edge(BlockEntryInstr* source, BlockEntryInstr* target, double weight)
94 : source(source), target(target), weight(weight) { }
95
96 static int LowestWeightFirst(const Edge* a, const Edge* b);
97
98 BlockEntryInstr* source;
99 BlockEntryInstr* target;
100 double weight;
101 };
102
103
104 // A linked list node in a chain of blocks.
105 struct Link : public ZoneAllocated {
106 Link(BlockEntryInstr* block, Link* next) : block(block), next(next) { }
107
108 BlockEntryInstr* block;
109 Link* next;
110 };
111
112
113 // A chain of blocks with first and last pointers for fast concatenation and
114 // a length to support adding a shorter chain's links to a longer chain.
115 struct Chain : public ZoneAllocated {
116 explicit Chain(BlockEntryInstr* block)
117 : first(new Link(block, NULL)), last(first), length(1) { }
118
119 Link* first;
120 Link* last;
121 intptr_t length;
122 };
123
124
125 int Edge::LowestWeightFirst(const Edge* a, const Edge* b) {
126 return (a->weight < b->weight) ? -1 : (a->weight > b->weight);
127 }
128
129
130 // Combine two chains by adding the shorter chain's links to the longer
131 // chain.
132 static void Union(GrowableArray<Chain*>* chains,
133 Chain* source_chain,
134 Chain* target_chain) {
135 if (source_chain->length < target_chain->length) {
136 for (Link* link = source_chain->first; link != NULL; link = link->next) {
137 (*chains)[link->block->postorder_number()] = target_chain;
138 }
139 // Link the chains.
140 source_chain->last->next = target_chain->first;
141 // Update the state of the longer chain.
142 target_chain->first = source_chain->first;
143 target_chain->length += source_chain->length;
144 } else {
145 for (Link* link = target_chain->first; link != NULL; link = link->next) {
146 (*chains)[link->block->postorder_number()] = source_chain;
147 }
148 source_chain->last->next = target_chain->first;
149 source_chain->last = target_chain->last;
150 source_chain->length += target_chain->length;
151 }
152 }
153
154
155 void BlockScheduler::ReorderBlocks() const {
156 // Add every block to a chain of length 1 and compute a list of edges
157 // sorted by weight.
158 intptr_t block_count = flow_graph()->preorder().length();
159 GrowableArray<Edge> edges(2 * block_count);
160
161 // A map from a block's postorder number to the chain it is in. Used to
162 // implement a simple (ordered) union-find data structure. Chains are
163 // stored by pointer so that they are aliased (mutating one mutates all
164 // shared ones). Find(n) is simply chains[n].
165 GrowableArray<Chain*> chains(block_count);
166
167 for (BlockIterator it = flow_graph()->postorder_iterator();
168 !it.Done();
169 it.Advance()) {
170 BlockEntryInstr* block = it.Current();
171 chains.Add(new Chain(block));
172
173 Instruction* last = block->last_instruction();
174 for (intptr_t i = 0; i < last->SuccessorCount(); ++i) {
175 BlockEntryInstr* succ = last->SuccessorAt(i);
176 double weight = 0.0;
177 if (succ->IsTargetEntry()) {
178 weight = succ->AsTargetEntry()->edge_weight();
179 } else if (last->IsGoto()) {
180 weight = last->AsGoto()->edge_weight();
181 }
182 edges.Add(Edge(block, succ, weight));
183 }
184 }
185
186 // Handle each edge in turn. The edges are sorted by increasing weight.
187 edges.Sort(Edge::LowestWeightFirst);
188 while (!edges.is_empty()) {
189 Edge edge = edges.RemoveLast();
190 Chain* source_chain = chains[edge.source->postorder_number()];
191 Chain* target_chain = chains[edge.target->postorder_number()];
192
193 // If the source and target are already in the same chain or if the
194 // edge's source or target is not exposed at the appropriate end of a
195 // chain skip this edge.
196 if ((source_chain == target_chain) ||
197 (edge.source != source_chain->last->block) ||
198 (edge.target != target_chain->first->block)) {
199 continue;
200 }
201
202 Union(&chains, source_chain, target_chain);
203 }
204
205 // Build a new block order. Emit each chain when its first block occurs
206 // in the original reverse postorder ordering (which gives a topological
207 // sort of the blocks).
208 for (intptr_t i = block_count - 1; i >= 0; --i) {
209 if (chains[i]->first->block == flow_graph()->postorder()[i]) {
210 for (Link* link = chains[i]->first; link != NULL; link = link->next) {
211 flow_graph()->codegen_block_order(true)->Add(link->block);
212 }
213 }
214 }
215 }
216
217 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698