]> git.proxmox.com Git - rustc.git/blame - src/librustc_passes/mir_stats.rs
New upstream version 1.25.0+dfsg1
[rustc.git] / src / librustc_passes / mir_stats.rs
CommitLineData
476ff2be
SL
1// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11// The visitors in this module collect sizes and counts of the most important
12// pieces of MIR. The resulting numbers are good approximations but not
13// completely accurate (some things might be counted twice, others missed).
14
15use rustc_const_math::{ConstUsize};
476ff2be 16use rustc::mir::{AggregateKind, AssertMessage, BasicBlock, BasicBlockData};
abe05a73 17use rustc::mir::{Constant, Literal, Location, Local, LocalDecl};
ff7c6d11 18use rustc::mir::{Place, PlaceElem, PlaceProjection};
476ff2be
SL
19use rustc::mir::{Mir, Operand, ProjectionElem};
20use rustc::mir::{Rvalue, SourceInfo, Statement, StatementKind};
8bb4bdeb 21use rustc::mir::{Terminator, TerminatorKind, VisibilityScope, VisibilityScopeData};
476ff2be 22use rustc::mir::visit as mir_visit;
ea8adc8c 23use rustc::ty::{self, ClosureSubsts, TyCtxt};
476ff2be
SL
24use rustc::util::nodemap::{FxHashMap};
25
26struct NodeData {
27 count: usize,
28 size: usize,
29}
30
31struct StatCollector<'a, 'tcx: 'a> {
32 _tcx: TyCtxt<'a, 'tcx, 'tcx>,
33 data: FxHashMap<&'static str, NodeData>,
34}
35
476ff2be
SL
36impl<'a, 'tcx> StatCollector<'a, 'tcx> {
37
38 fn record_with_size(&mut self, label: &'static str, node_size: usize) {
39 let entry = self.data.entry(label).or_insert(NodeData {
40 count: 0,
41 size: 0,
42 });
43
44 entry.count += 1;
45 entry.size = node_size;
46 }
47
48 fn record<T>(&mut self, label: &'static str, node: &T) {
49 self.record_with_size(label, ::std::mem::size_of_val(node));
50 }
476ff2be
SL
51}
52
53impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> {
54 fn visit_mir(&mut self, mir: &Mir<'tcx>) {
55 self.record("Mir", mir);
56
57 // since the `super_mir` method does not traverse the MIR of
58 // promoted rvalues, (but we still want to gather statistics
59 // on the structures represented there) we manually traverse
60 // the promoted rvalues here.
61 for promoted_mir in &mir.promoted {
62 self.visit_mir(promoted_mir);
63 }
64
65 self.super_mir(mir);
66 }
67
68 fn visit_basic_block_data(&mut self,
69 block: BasicBlock,
70 data: &BasicBlockData<'tcx>) {
71 self.record("BasicBlockData", data);
72 self.super_basic_block_data(block, data);
73 }
74
75 fn visit_visibility_scope_data(&mut self,
76 scope_data: &VisibilityScopeData) {
77 self.record("VisibilityScopeData", scope_data);
78 self.super_visibility_scope_data(scope_data);
79 }
80
81 fn visit_statement(&mut self,
82 block: BasicBlock,
83 statement: &Statement<'tcx>,
84 location: Location) {
85 self.record("Statement", statement);
86 self.record(match statement.kind {
87 StatementKind::Assign(..) => "StatementKind::Assign",
041b39d2 88 StatementKind::EndRegion(..) => "StatementKind::EndRegion",
3b2f2976 89 StatementKind::Validate(..) => "StatementKind::Validate",
476ff2be
SL
90 StatementKind::SetDiscriminant { .. } => "StatementKind::SetDiscriminant",
91 StatementKind::StorageLive(..) => "StatementKind::StorageLive",
92 StatementKind::StorageDead(..) => "StatementKind::StorageDead",
8bb4bdeb 93 StatementKind::InlineAsm { .. } => "StatementKind::InlineAsm",
476ff2be
SL
94 StatementKind::Nop => "StatementKind::Nop",
95 }, &statement.kind);
96 self.super_statement(block, statement, location);
97 }
98
99 fn visit_terminator(&mut self,
100 block: BasicBlock,
101 terminator: &Terminator<'tcx>,
102 location: Location) {
103 self.record("Terminator", terminator);
104 self.super_terminator(block, terminator, location);
105 }
106
107 fn visit_terminator_kind(&mut self,
108 block: BasicBlock,
109 kind: &TerminatorKind<'tcx>,
110 location: Location) {
111 self.record("TerminatorKind", kind);
112 self.record(match *kind {
113 TerminatorKind::Goto { .. } => "TerminatorKind::Goto",
476ff2be
SL
114 TerminatorKind::SwitchInt { .. } => "TerminatorKind::SwitchInt",
115 TerminatorKind::Resume => "TerminatorKind::Resume",
ff7c6d11 116 TerminatorKind::Abort => "TerminatorKind::Abort",
476ff2be
SL
117 TerminatorKind::Return => "TerminatorKind::Return",
118 TerminatorKind::Unreachable => "TerminatorKind::Unreachable",
119 TerminatorKind::Drop { .. } => "TerminatorKind::Drop",
120 TerminatorKind::DropAndReplace { .. } => "TerminatorKind::DropAndReplace",
121 TerminatorKind::Call { .. } => "TerminatorKind::Call",
122 TerminatorKind::Assert { .. } => "TerminatorKind::Assert",
ea8adc8c
XL
123 TerminatorKind::GeneratorDrop => "TerminatorKind::GeneratorDrop",
124 TerminatorKind::Yield { .. } => "TerminatorKind::Yield",
abe05a73 125 TerminatorKind::FalseEdges { .. } => "TerminatorKind::FalseEdges",
2c00a5a8 126 TerminatorKind::FalseUnwind { .. } => "TerminatorKind::FalseUnwind",
476ff2be
SL
127 }, kind);
128 self.super_terminator_kind(block, kind, location);
129 }
130
131 fn visit_assert_message(&mut self,
132 msg: &AssertMessage<'tcx>,
133 location: Location) {
134 self.record("AssertMessage", msg);
135 self.record(match *msg {
136 AssertMessage::BoundsCheck { .. } => "AssertMessage::BoundsCheck",
137 AssertMessage::Math(..) => "AssertMessage::Math",
ea8adc8c
XL
138 AssertMessage::GeneratorResumedAfterReturn => {
139 "AssertMessage::GeneratorResumedAfterReturn"
140 }
141 AssertMessage::GeneratorResumedAfterPanic => {
142 "AssertMessage::GeneratorResumedAfterPanic"
143 }
476ff2be
SL
144 }, msg);
145 self.super_assert_message(msg, location);
146 }
147
148 fn visit_rvalue(&mut self,
149 rvalue: &Rvalue<'tcx>,
150 location: Location) {
151 self.record("Rvalue", rvalue);
152 let rvalue_kind = match *rvalue {
153 Rvalue::Use(..) => "Rvalue::Use",
154 Rvalue::Repeat(..) => "Rvalue::Repeat",
155 Rvalue::Ref(..) => "Rvalue::Ref",
156 Rvalue::Len(..) => "Rvalue::Len",
157 Rvalue::Cast(..) => "Rvalue::Cast",
158 Rvalue::BinaryOp(..) => "Rvalue::BinaryOp",
159 Rvalue::CheckedBinaryOp(..) => "Rvalue::CheckedBinaryOp",
160 Rvalue::UnaryOp(..) => "Rvalue::UnaryOp",
8bb4bdeb 161 Rvalue::Discriminant(..) => "Rvalue::Discriminant",
7cac9316 162 Rvalue::NullaryOp(..) => "Rvalue::NullaryOp",
476ff2be
SL
163 Rvalue::Aggregate(ref kind, ref _operands) => {
164 // AggregateKind is not distinguished by visit API, so
165 // record it. (`super_rvalue` handles `_operands`.)
cc61c64b 166 self.record(match **kind {
8bb4bdeb 167 AggregateKind::Array(_) => "AggregateKind::Array",
476ff2be
SL
168 AggregateKind::Tuple => "AggregateKind::Tuple",
169 AggregateKind::Adt(..) => "AggregateKind::Adt",
170 AggregateKind::Closure(..) => "AggregateKind::Closure",
ea8adc8c 171 AggregateKind::Generator(..) => "AggregateKind::Generator",
476ff2be
SL
172 }, kind);
173
174 "Rvalue::Aggregate"
175 }
476ff2be
SL
176 };
177 self.record(rvalue_kind, rvalue);
178 self.super_rvalue(rvalue, location);
179 }
180
181 fn visit_operand(&mut self,
182 operand: &Operand<'tcx>,
183 location: Location) {
184 self.record("Operand", operand);
185 self.record(match *operand {
ff7c6d11
XL
186 Operand::Copy(..) => "Operand::Copy",
187 Operand::Move(..) => "Operand::Move",
476ff2be
SL
188 Operand::Constant(..) => "Operand::Constant",
189 }, operand);
190 self.super_operand(operand, location);
191 }
192
ff7c6d11
XL
193 fn visit_place(&mut self,
194 place: &Place<'tcx>,
195 context: mir_visit::PlaceContext<'tcx>,
476ff2be 196 location: Location) {
ff7c6d11
XL
197 self.record("Place", place);
198 self.record(match *place {
199 Place::Local(..) => "Place::Local",
200 Place::Static(..) => "Place::Static",
201 Place::Projection(..) => "Place::Projection",
202 }, place);
203 self.super_place(place, context, location);
476ff2be
SL
204 }
205
206 fn visit_projection(&mut self,
ff7c6d11
XL
207 place: &PlaceProjection<'tcx>,
208 context: mir_visit::PlaceContext<'tcx>,
476ff2be 209 location: Location) {
ff7c6d11
XL
210 self.record("PlaceProjection", place);
211 self.super_projection(place, context, location);
476ff2be
SL
212 }
213
214 fn visit_projection_elem(&mut self,
ff7c6d11
XL
215 place: &PlaceElem<'tcx>,
216 context: mir_visit::PlaceContext<'tcx>,
476ff2be 217 location: Location) {
ff7c6d11
XL
218 self.record("PlaceElem", place);
219 self.record(match *place {
220 ProjectionElem::Deref => "PlaceElem::Deref",
221 ProjectionElem::Subslice { .. } => "PlaceElem::Subslice",
222 ProjectionElem::Field(..) => "PlaceElem::Field",
223 ProjectionElem::Index(..) => "PlaceElem::Index",
224 ProjectionElem::ConstantIndex { .. } => "PlaceElem::ConstantIndex",
225 ProjectionElem::Downcast(..) => "PlaceElem::Downcast",
226 }, place);
227 self.super_projection_elem(place, context, location);
476ff2be
SL
228 }
229
230 fn visit_constant(&mut self,
231 constant: &Constant<'tcx>,
232 location: Location) {
233 self.record("Constant", constant);
234 self.super_constant(constant, location);
235 }
236
237 fn visit_literal(&mut self,
238 literal: &Literal<'tcx>,
239 location: Location) {
240 self.record("Literal", literal);
241 self.record(match *literal {
476ff2be
SL
242 Literal::Value { .. } => "Literal::Value",
243 Literal::Promoted { .. } => "Literal::Promoted",
244 }, literal);
245 self.super_literal(literal, location);
246 }
247
248 fn visit_source_info(&mut self,
249 source_info: &SourceInfo) {
250 self.record("SourceInfo", source_info);
251 self.super_source_info(source_info);
252 }
253
254 fn visit_closure_substs(&mut self,
3b2f2976
XL
255 substs: &ClosureSubsts<'tcx>,
256 _: Location) {
476ff2be
SL
257 self.record("ClosureSubsts", substs);
258 self.super_closure_substs(substs);
259 }
260
ea8adc8c
XL
261 fn visit_const(&mut self,
262 constant: &&'tcx ty::Const<'tcx>,
263 _: Location) {
264 self.record("Const", constant);
265 self.super_const(constant);
476ff2be
SL
266 }
267
268 fn visit_const_usize(&mut self,
269 const_usize: &ConstUsize,
270 _: Location) {
271 self.record("ConstUsize", const_usize);
272 self.super_const_usize(const_usize);
273 }
274
476ff2be 275 fn visit_local_decl(&mut self,
abe05a73 276 local: Local,
476ff2be
SL
277 local_decl: &LocalDecl<'tcx>) {
278 self.record("LocalDecl", local_decl);
abe05a73 279 self.super_local_decl(local, local_decl);
476ff2be
SL
280 }
281
282 fn visit_visibility_scope(&mut self,
283 scope: &VisibilityScope) {
284 self.record("VisiblityScope", scope);
285 self.super_visibility_scope(scope);
286 }
287}