blob: 78de9c16c7ae6098947a2c09caa71243769fc4ac [file] [log] [blame]
Chris Lattnere4367792003-10-28 20:13:07 +00001//===- ProfileInfo.cpp - Represents profile information -------------------===//
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 ProfileInfo class is used to represent profiling information read in from
11// the dump file.
12//
13//===----------------------------------------------------------------------===//
14
15#include "ProfileInfo.h"
Chris Lattner7a78d812003-10-28 21:08:18 +000016#include "llvm/Module.h"
Chris Lattnere4367792003-10-28 20:13:07 +000017#include <iostream>
18#include <sys/types.h>
19#include <sys/stat.h>
20#include <fcntl.h>
21#include <stdio.h>
22
23enum ProfilingType {
Chris Lattner7a78d812003-10-28 21:08:18 +000024 ArgumentInfo = 1, // The command line argument block
25 FunctionInfo = 2, // Function profiling information
26 BlockInfo = 3, // Block profiling information
Chris Lattnere4367792003-10-28 20:13:07 +000027};
28
29// ByteSwap - Byteswap 'Var' if 'Really' is true.
30//
31static inline unsigned ByteSwap(unsigned Var, bool Really) {
32 if (!Really) return Var;
33 return ((Var & (255<< 0)) << 24) |
34 ((Var & (255<< 8)) << 8) |
35 ((Var & (255<<16)) >> 8) |
36 ((Var & (255<<24)) >> 24);
37}
38
39static void ReadProfilingBlock(const char *ToolName, FILE *F,
40 bool ShouldByteSwap,
41 std::vector<unsigned> &Data) {
42 // Read the number of entries...
43 unsigned NumEntries;
44 if (fread(&NumEntries, sizeof(unsigned), 1, F) != 1) {
45 std::cerr << ToolName << ": data packet truncated!\n";
46 perror(0);
47 exit(1);
48 }
49 NumEntries = ByteSwap(NumEntries, ShouldByteSwap);
50
51 // Read the counts...
52 std::vector<unsigned> TempSpace(NumEntries);
53
54 // Read in the block of data...
55 if (fread(&TempSpace[0], sizeof(unsigned)*NumEntries, 1, F) != 1) {
56 std::cerr << ToolName << ": data packet truncated!\n";
57 perror(0);
58 exit(1);
59 }
60
61 // Make sure we have enough space...
62 if (Data.size() < NumEntries)
63 Data.resize(NumEntries);
64
65 // Accumulate the data we just read into the data.
66 if (!ShouldByteSwap) {
67 for (unsigned i = 0; i != NumEntries; ++i)
68 Data[i] += TempSpace[i];
69 } else {
70 for (unsigned i = 0; i != NumEntries; ++i)
71 Data[i] += ByteSwap(TempSpace[i], true);
72 }
73}
74
75// ProfileInfo ctor - Read the specified profiling data file, exiting the
76// program if the file is invalid or broken.
77//
Chris Lattner7a78d812003-10-28 21:08:18 +000078ProfileInfo::ProfileInfo(const char *ToolName, const std::string &Filename,
79 Module &TheModule) : M(TheModule) {
Chris Lattnere4367792003-10-28 20:13:07 +000080 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) {
Chris Lattner7a78d812003-10-28 21:08:18 +000097 case ArgumentInfo: {
Chris Lattnere4367792003-10-28 20:13:07 +000098 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
Chris Lattner7a78d812003-10-28 21:08:18 +0000119 case FunctionInfo:
Chris Lattnere4367792003-10-28 20:13:07 +0000120 ReadProfilingBlock(ToolName, F, ShouldByteSwap, FunctionCounts);
121 break;
122
Chris Lattner7a78d812003-10-28 21:08:18 +0000123 case BlockInfo:
Chris Lattnere4367792003-10-28 20:13:07 +0000124 ReadProfilingBlock(ToolName, F, ShouldByteSwap, BlockCounts);
125 break;
126
127 default:
128 std::cerr << ToolName << ": Unknown packet type #" << PacketType << "!\n";
129 exit(1);
130 }
131 }
132
133 fclose(F);
134}
Chris Lattner7a78d812003-10-28 21:08:18 +0000135
136
137// getFunctionCounts - This method is used by consumers of function counting
138// information. If we do not directly have function count information, we
139// compute it from other, more refined, types of profile information.
140//
141void ProfileInfo::getFunctionCounts(std::vector<std::pair<Function*,
142 unsigned> > &Counts) {
143 if (FunctionCounts.empty()) {
Chris Lattner750ba3d2003-10-29 21:47:44 +0000144 // Synthesize function frequency information from the number of times their
145 // entry blocks were executed.
146 std::vector<std::pair<BasicBlock*, unsigned> > BlockCounts;
147 getBlockCounts(BlockCounts);
148
149 for (unsigned i = 0, e = BlockCounts.size(); i != e; ++i)
150 if (&BlockCounts[i].first->getParent()->front() == BlockCounts[i].first)
151 Counts.push_back(std::make_pair(BlockCounts[i].first->getParent(),
152 BlockCounts[i].second));
Chris Lattner7a78d812003-10-28 21:08:18 +0000153 return;
154 }
155
156 unsigned Counter = 0;
157 for (Module::iterator I = M.begin(), E = M.end();
Chris Lattner33f1ca72003-10-28 21:25:23 +0000158 I != E && Counter != FunctionCounts.size(); ++I)
Chris Lattner7a78d812003-10-28 21:08:18 +0000159 if (!I->isExternal())
Chris Lattner33f1ca72003-10-28 21:25:23 +0000160 Counts.push_back(std::make_pair(I, FunctionCounts[Counter++]));
161}
162
163// getBlockCounts - This method is used by consumers of block counting
164// information. If we do not directly have block count information, we
165// compute it from other, more refined, types of profile information.
166//
167void ProfileInfo::getBlockCounts(std::vector<std::pair<BasicBlock*,
168 unsigned> > &Counts) {
169 if (BlockCounts.empty()) {
170 std::cerr << "Block counts not available, and no synthesis "
171 << "is implemented yet!\n";
172 return;
173 }
174
175 unsigned Counter = 0;
176 for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F)
177 for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
178 Counts.push_back(std::make_pair(BB, BlockCounts[Counter++]));
179 if (Counter == BlockCounts.size())
180 return;
181 }
Chris Lattner7a78d812003-10-28 21:08:18 +0000182}