Add initial support for reading edge counts. This will be improved to enable
[oota-llvm.git] / lib / Analysis / ProfileInfoLoader.cpp
1 //===- ProfileInfoLoad.cpp - Load profile information from disk -----------===//
2 // 
3 //                      The LLVM Compiler Infrastructure
4 //
5 // This file was developed by the LLVM research group and is distributed under
6 // the University of Illinois Open Source License. See LICENSE.TXT for details.
7 // 
8 //===----------------------------------------------------------------------===//
9 //
10 // The ProfileInfoLoader class is used to load and represent profiling
11 // information read in from the dump file.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "llvm/Analysis/ProfileInfoLoader.h"
16 #include "llvm/Module.h"
17 #include "llvm/InstrTypes.h"
18 #include <cstdio>
19 using namespace llvm;
20
21 enum ProfilingType {
22   ArgumentInfo = 1,   // The command line argument block
23   FunctionInfo = 2,   // Function profiling information
24   BlockInfo    = 3,   // Block profiling information
25   EdgeInfo     = 4,   // Edge profiling information
26 };
27
28 // ByteSwap - Byteswap 'Var' if 'Really' is true.
29 //
30 static inline unsigned ByteSwap(unsigned Var, bool Really) {
31   if (!Really) return Var;
32   return ((Var & (255<< 0)) << 24) | 
33          ((Var & (255<< 8)) <<  8) | 
34          ((Var & (255<<16)) >>  8) | 
35          ((Var & (255<<24)) >> 24);
36 }
37
38 static void ReadProfilingBlock(const char *ToolName, FILE *F,
39                                bool ShouldByteSwap,
40                                std::vector<unsigned> &Data) {
41   // Read the number of entries...
42   unsigned NumEntries;
43   if (fread(&NumEntries, sizeof(unsigned), 1, F) != 1) {
44     std::cerr << ToolName << ": data packet truncated!\n";
45     perror(0);
46     exit(1);
47   }
48   NumEntries = ByteSwap(NumEntries, ShouldByteSwap);
49
50   // Read the counts...
51   std::vector<unsigned> TempSpace(NumEntries);
52
53   // Read in the block of data...
54   if (fread(&TempSpace[0], sizeof(unsigned)*NumEntries, 1, F) != 1) {
55     std::cerr << ToolName << ": data packet truncated!\n";
56     perror(0);
57     exit(1);
58   }
59
60   // Make sure we have enough space...
61   if (Data.size() < NumEntries)
62     Data.resize(NumEntries);
63   
64   // Accumulate the data we just read into the data.
65   if (!ShouldByteSwap) {
66     for (unsigned i = 0; i != NumEntries; ++i)
67       Data[i] += TempSpace[i];
68   } else {
69     for (unsigned i = 0; i != NumEntries; ++i)
70       Data[i] += ByteSwap(TempSpace[i], true);
71   }
72 }
73
74 // ProfileInfoLoader ctor - Read the specified profiling data file, exiting the
75 // program if the file is invalid or broken.
76 //
77 ProfileInfoLoader::ProfileInfoLoader(const char *ToolName,
78                                      const std::string &Filename,
79                                      Module &TheModule) : M(TheModule) {
80   FILE *F = fopen(Filename.c_str(), "r");
81   if (F == 0) {
82     std::cerr << ToolName << ": Error opening '" << Filename << "': ";
83     perror(0);
84     exit(1);
85   }
86
87   // Keep reading packets until we run out of them.
88   unsigned PacketType;
89   while (fread(&PacketType, sizeof(unsigned), 1, F) == 1) {
90     // If the low eight bits of the packet are zero, we must be dealing with an
91     // endianness mismatch.  Byteswap all words read from the profiling
92     // information.
93     bool ShouldByteSwap = (char)PacketType == 0;
94     PacketType = ByteSwap(PacketType, ShouldByteSwap);
95
96     switch (PacketType) {
97     case ArgumentInfo: {
98       unsigned ArgLength;
99       if (fread(&ArgLength, sizeof(unsigned), 1, F) != 1) {
100         std::cerr << ToolName << ": arguments packet truncated!\n";
101         perror(0);
102         exit(1);
103       }
104       ArgLength = ByteSwap(ArgLength, ShouldByteSwap);
105
106       // Read in the arguments...
107       std::vector<char> Chars(ArgLength+4);
108
109       if (ArgLength)
110         if (fread(&Chars[0], (ArgLength+3) & ~3, 1, F) != 1) {
111           std::cerr << ToolName << ": arguments packet truncated!\n";
112           perror(0);
113           exit(1);
114         }
115       CommandLines.push_back(std::string(&Chars[0], &Chars[ArgLength]));
116       break;
117     }
118       
119     case FunctionInfo:
120       ReadProfilingBlock(ToolName, F, ShouldByteSwap, FunctionCounts);
121       break;
122       
123     case BlockInfo:
124       ReadProfilingBlock(ToolName, F, ShouldByteSwap, BlockCounts);
125       break;
126
127     case EdgeInfo:
128       ReadProfilingBlock(ToolName, F, ShouldByteSwap, EdgeCounts);
129       break;
130
131     default:
132       std::cerr << ToolName << ": Unknown packet type #" << PacketType << "!\n";
133       exit(1);
134     }
135   }
136   
137   fclose(F);
138 }
139
140
141 // getFunctionCounts - This method is used by consumers of function counting
142 // information.  If we do not directly have function count information, we
143 // compute it from other, more refined, types of profile information.
144 //
145 void ProfileInfoLoader::getFunctionCounts(std::vector<std::pair<Function*,
146                                                       unsigned> > &Counts) {
147   if (FunctionCounts.empty()) {
148     // Synthesize function frequency information from the number of times their
149     // entry blocks were executed.
150     std::vector<std::pair<BasicBlock*, unsigned> > BlockCounts;
151     getBlockCounts(BlockCounts);
152
153     for (unsigned i = 0, e = BlockCounts.size(); i != e; ++i)
154       if (&BlockCounts[i].first->getParent()->front() == BlockCounts[i].first)
155         Counts.push_back(std::make_pair(BlockCounts[i].first->getParent(),
156                                         BlockCounts[i].second));
157     return;
158   }
159   
160   unsigned Counter = 0;
161   for (Module::iterator I = M.begin(), E = M.end();
162        I != E && Counter != FunctionCounts.size(); ++I)
163     if (!I->isExternal())
164       Counts.push_back(std::make_pair(I, FunctionCounts[Counter++]));
165 }
166
167 // getBlockCounts - This method is used by consumers of block counting
168 // information.  If we do not directly have block count information, we
169 // compute it from other, more refined, types of profile information.
170 //
171 void ProfileInfoLoader::getBlockCounts(std::vector<std::pair<BasicBlock*,
172                                                          unsigned> > &Counts) {
173   if (BlockCounts.empty()) {
174     std::cerr << "Block counts not available, and no synthesis "
175               << "is implemented yet!\n";
176     return;
177   }
178
179   unsigned Counter = 0;
180   for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F)
181     for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
182       Counts.push_back(std::make_pair(BB, BlockCounts[Counter++]));
183       if (Counter == BlockCounts.size())
184         return;
185     }
186 }
187
188 // getEdgeCounts - This method is used by consumers of edge counting
189 // information.  If we do not directly have edge count information, we compute
190 // it from other, more refined, types of profile information.
191 //
192 void ProfileInfoLoader::getEdgeCounts(std::vector<std::pair<Edge,
193                                                   unsigned> > &Counts) {
194   if (EdgeCounts.empty()) {
195     std::cerr << "Edge counts not available, and no synthesis "
196               << "is implemented yet!\n";
197     return;
198   }
199
200   unsigned Counter = 0;
201   for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F)
202     for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
203       for (unsigned i = 0, e = BB->getTerminator()->getNumSuccessors();
204            i != e; ++i) {
205         Counts.push_back(std::make_pair(Edge(BB, i), EdgeCounts[Counter++]));
206         if (Counter == EdgeCounts.size())
207           return;
208       }
209 }