1 //===- ProfileInfoLoad.cpp - Load profile information from disk -----------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // The ProfileInfoLoader class is used to load and represent profiling
11 // information read in from the dump file.
13 //===----------------------------------------------------------------------===//
15 #include "llvm/Analysis/ProfileInfoLoader.h"
16 #include "llvm/Analysis/ProfileInfoTypes.h"
17 #include "llvm/Module.h"
18 #include "llvm/InstrTypes.h"
19 #include "llvm/Support/Streams.h"
25 // ByteSwap - Byteswap 'Var' if 'Really' is true.
27 static inline unsigned ByteSwap(unsigned Var
, bool Really
) {
28 if (!Really
) return Var
;
29 return ((Var
& (255<< 0)) << 24) |
30 ((Var
& (255<< 8)) << 8) |
31 ((Var
& (255<<16)) >> 8) |
32 ((Var
& (255<<24)) >> 24);
35 static void ReadProfilingBlock(const char *ToolName
, FILE *F
,
37 std::vector
<unsigned> &Data
) {
38 // Read the number of entries...
40 if (fread(&NumEntries
, sizeof(unsigned), 1, F
) != 1) {
41 cerr
<< ToolName
<< ": data packet truncated!\n";
45 NumEntries
= ByteSwap(NumEntries
, ShouldByteSwap
);
48 std::vector
<unsigned> TempSpace(NumEntries
);
50 // Read in the block of data...
51 if (fread(&TempSpace
[0], sizeof(unsigned)*NumEntries
, 1, F
) != 1) {
52 cerr
<< ToolName
<< ": data packet truncated!\n";
57 // Make sure we have enough space...
58 if (Data
.size() < NumEntries
)
59 Data
.resize(NumEntries
);
61 // Accumulate the data we just read into the data.
62 if (!ShouldByteSwap
) {
63 for (unsigned i
= 0; i
!= NumEntries
; ++i
)
64 Data
[i
] += TempSpace
[i
];
66 for (unsigned i
= 0; i
!= NumEntries
; ++i
)
67 Data
[i
] += ByteSwap(TempSpace
[i
], true);
71 // ProfileInfoLoader ctor - Read the specified profiling data file, exiting the
72 // program if the file is invalid or broken.
74 ProfileInfoLoader::ProfileInfoLoader(const char *ToolName
,
75 const std::string
&Filename
,
76 Module
&TheModule
) : M(TheModule
) {
77 FILE *F
= fopen(Filename
.c_str(), "r");
79 cerr
<< ToolName
<< ": Error opening '" << Filename
<< "': ";
84 // Keep reading packets until we run out of them.
86 while (fread(&PacketType
, sizeof(unsigned), 1, F
) == 1) {
87 // If the low eight bits of the packet are zero, we must be dealing with an
88 // endianness mismatch. Byteswap all words read from the profiling
90 bool ShouldByteSwap
= (char)PacketType
== 0;
91 PacketType
= ByteSwap(PacketType
, ShouldByteSwap
);
96 if (fread(&ArgLength
, sizeof(unsigned), 1, F
) != 1) {
97 cerr
<< ToolName
<< ": arguments packet truncated!\n";
101 ArgLength
= ByteSwap(ArgLength
, ShouldByteSwap
);
103 // Read in the arguments...
104 std::vector
<char> Chars(ArgLength
+4);
107 if (fread(&Chars
[0], (ArgLength
+3) & ~3, 1, F
) != 1) {
108 cerr
<< ToolName
<< ": arguments packet truncated!\n";
112 CommandLines
.push_back(std::string(&Chars
[0], &Chars
[ArgLength
]));
117 ReadProfilingBlock(ToolName
, F
, ShouldByteSwap
, FunctionCounts
);
121 ReadProfilingBlock(ToolName
, F
, ShouldByteSwap
, BlockCounts
);
125 ReadProfilingBlock(ToolName
, F
, ShouldByteSwap
, EdgeCounts
);
129 ReadProfilingBlock(ToolName
, F
, ShouldByteSwap
, BBTrace
);
133 cerr
<< ToolName
<< ": Unknown packet type #" << PacketType
<< "!\n";
142 // getFunctionCounts - This method is used by consumers of function counting
143 // information. If we do not directly have function count information, we
144 // compute it from other, more refined, types of profile information.
146 void ProfileInfoLoader::getFunctionCounts(std::vector
<std::pair
<Function
*,
147 unsigned> > &Counts
) {
148 if (FunctionCounts
.empty()) {
149 if (hasAccurateBlockCounts()) {
150 // Synthesize function frequency information from the number of times
151 // their entry blocks were executed.
152 std::vector
<std::pair
<BasicBlock
*, unsigned> > BlockCounts
;
153 getBlockCounts(BlockCounts
);
155 for (unsigned i
= 0, e
= BlockCounts
.size(); i
!= e
; ++i
)
156 if (&BlockCounts
[i
].first
->getParent()->getEntryBlock() ==
157 BlockCounts
[i
].first
)
158 Counts
.push_back(std::make_pair(BlockCounts
[i
].first
->getParent(),
159 BlockCounts
[i
].second
));
161 cerr
<< "Function counts are not available!\n";
166 unsigned Counter
= 0;
167 for (Module::iterator I
= M
.begin(), E
= M
.end();
168 I
!= E
&& Counter
!= FunctionCounts
.size(); ++I
)
169 if (!I
->isDeclaration())
170 Counts
.push_back(std::make_pair(I
, FunctionCounts
[Counter
++]));
173 // getBlockCounts - This method is used by consumers of block counting
174 // information. If we do not directly have block count information, we
175 // compute it from other, more refined, types of profile information.
177 void ProfileInfoLoader::getBlockCounts(std::vector
<std::pair
<BasicBlock
*,
178 unsigned> > &Counts
) {
179 if (BlockCounts
.empty()) {
180 if (hasAccurateEdgeCounts()) {
181 // Synthesize block count information from edge frequency information.
182 // The block execution frequency is equal to the sum of the execution
183 // frequency of all outgoing edges from a block.
185 // If a block has no successors, this will not be correct, so we have to
186 // special case it. :(
187 std::vector
<std::pair
<Edge
, unsigned> > EdgeCounts
;
188 getEdgeCounts(EdgeCounts
);
190 std::map
<BasicBlock
*, unsigned> InEdgeFreqs
;
192 BasicBlock
*LastBlock
= 0;
193 TerminatorInst
*TI
= 0;
194 for (unsigned i
= 0, e
= EdgeCounts
.size(); i
!= e
; ++i
) {
195 if (EdgeCounts
[i
].first
.first
!= LastBlock
) {
196 LastBlock
= EdgeCounts
[i
].first
.first
;
197 TI
= LastBlock
->getTerminator();
198 Counts
.push_back(std::make_pair(LastBlock
, 0));
200 Counts
.back().second
+= EdgeCounts
[i
].second
;
201 unsigned SuccNum
= EdgeCounts
[i
].first
.second
;
202 if (SuccNum
>= TI
->getNumSuccessors()) {
203 static bool Warned
= false;
205 cerr
<< "WARNING: profile info doesn't seem to match"
206 << " the program!\n";
210 // If this successor has no successors of its own, we will never
211 // compute an execution count for that block. Remember the incoming
212 // edge frequencies to add later.
213 BasicBlock
*Succ
= TI
->getSuccessor(SuccNum
);
214 if (Succ
->getTerminator()->getNumSuccessors() == 0)
215 InEdgeFreqs
[Succ
] += EdgeCounts
[i
].second
;
219 // Now we have to accumulate information for those blocks without
220 // successors into our table.
221 for (std::map
<BasicBlock
*, unsigned>::iterator I
= InEdgeFreqs
.begin(),
222 E
= InEdgeFreqs
.end(); I
!= E
; ++I
) {
224 for (; i
!= Counts
.size() && Counts
[i
].first
!= I
->first
; ++i
)
226 if (i
== Counts
.size()) Counts
.push_back(std::make_pair(I
->first
, 0));
227 Counts
[i
].second
+= I
->second
;
231 cerr
<< "Block counts are not available!\n";
236 unsigned Counter
= 0;
237 for (Module::iterator F
= M
.begin(), E
= M
.end(); F
!= E
; ++F
)
238 for (Function::iterator BB
= F
->begin(), E
= F
->end(); BB
!= E
; ++BB
) {
239 Counts
.push_back(std::make_pair(BB
, BlockCounts
[Counter
++]));
240 if (Counter
== BlockCounts
.size())
245 // getEdgeCounts - This method is used by consumers of edge counting
246 // information. If we do not directly have edge count information, we compute
247 // it from other, more refined, types of profile information.
249 void ProfileInfoLoader::getEdgeCounts(std::vector
<std::pair
<Edge
,
250 unsigned> > &Counts
) {
251 if (EdgeCounts
.empty()) {
252 cerr
<< "Edge counts not available, and no synthesis "
253 << "is implemented yet!\n";
257 unsigned Counter
= 0;
258 for (Module::iterator F
= M
.begin(), E
= M
.end(); F
!= E
; ++F
)
259 for (Function::iterator BB
= F
->begin(), E
= F
->end(); BB
!= E
; ++BB
)
260 for (unsigned i
= 0, e
= BB
->getTerminator()->getNumSuccessors();
262 Counts
.push_back(std::make_pair(Edge(BB
, i
), EdgeCounts
[Counter
++]));
263 if (Counter
== EdgeCounts
.size())
268 // getBBTrace - This method is used by consumers of basic-block trace
271 void ProfileInfoLoader::getBBTrace(std::vector
<BasicBlock
*> &Trace
) {
272 if (BBTrace
.empty ()) {
273 cerr
<< "Basic block trace is not available!\n";
276 cerr
<< "Basic block trace loading is not implemented yet!\n";