Home | History | Annotate | Download | only in Analysis
      1 //===- ProfileDataLoader.cpp - Load profile information from disk ---------===//
      2 //
      3 //                      The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // The ProfileDataLoader class is used to load raw profiling data from the dump
     11 // file.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "llvm/Analysis/ProfileDataLoader.h"
     16 #include "llvm/ADT/ArrayRef.h"
     17 #include "llvm/ADT/OwningPtr.h"
     18 #include "llvm/Analysis/ProfileDataTypes.h"
     19 #include "llvm/IR/InstrTypes.h"
     20 #include "llvm/IR/Module.h"
     21 #include "llvm/Support/raw_ostream.h"
     22 #include "llvm/Support/system_error.h"
     23 #include <cstdio>
     24 #include <cstdlib>
     25 using namespace llvm;
     26 
     27 raw_ostream &llvm::operator<<(raw_ostream &O, std::pair<const BasicBlock *,
     28                                                         const BasicBlock *> E) {
     29   O << "(";
     30 
     31   if (E.first)
     32     O << E.first->getName();
     33   else
     34     O << "0";
     35 
     36   O << ",";
     37 
     38   if (E.second)
     39     O << E.second->getName();
     40   else
     41     O << "0";
     42 
     43   return O << ")";
     44 }
     45 
     46 /// AddCounts - Add 'A' and 'B', accounting for the fact that the value of one
     47 /// (or both) may not be defined.
     48 static unsigned AddCounts(unsigned A, unsigned B) {
     49   // If either value is undefined, use the other.
     50   // Undefined + undefined = undefined.
     51   if (A == ProfileDataLoader::Uncounted) return B;
     52   if (B == ProfileDataLoader::Uncounted) return A;
     53 
     54   return A + B;
     55 }
     56 
     57 /// ReadProfilingData - Load 'NumEntries' items of type 'T' from file 'F'
     58 template <typename T>
     59 static void ReadProfilingData(const char *ToolName, FILE *F,
     60                               T *Data, size_t NumEntries) {
     61   // Read in the block of data...
     62   if (fread(Data, sizeof(T), NumEntries, F) != NumEntries)
     63     report_fatal_error(Twine(ToolName) + ": Profiling data truncated");
     64 }
     65 
     66 /// ReadProfilingNumEntries - Read how many entries are in this profiling data
     67 /// packet.
     68 static unsigned ReadProfilingNumEntries(const char *ToolName, FILE *F,
     69                                         bool ShouldByteSwap) {
     70   unsigned Entry;
     71   ReadProfilingData<unsigned>(ToolName, F, &Entry, 1);
     72   return ShouldByteSwap ? ByteSwap_32(Entry) : Entry;
     73 }
     74 
     75 /// ReadProfilingBlock - Read the number of entries in the next profiling data
     76 /// packet and then accumulate the entries into 'Data'.
     77 static void ReadProfilingBlock(const char *ToolName, FILE *F,
     78                                bool ShouldByteSwap,
     79                                SmallVectorImpl<unsigned> &Data) {
     80   // Read the number of entries...
     81   unsigned NumEntries = ReadProfilingNumEntries(ToolName, F, ShouldByteSwap);
     82 
     83   // Read in the data.
     84   SmallVector<unsigned, 8> TempSpace(NumEntries);
     85   ReadProfilingData<unsigned>(ToolName, F, TempSpace.data(), NumEntries);
     86 
     87   // Make sure we have enough space ...
     88   if (Data.size() < NumEntries)
     89     Data.resize(NumEntries, ProfileDataLoader::Uncounted);
     90 
     91   // Accumulate the data we just read into the existing data.
     92   for (unsigned i = 0; i < NumEntries; ++i) {
     93     unsigned Entry = ShouldByteSwap ? ByteSwap_32(TempSpace[i]) : TempSpace[i];
     94     Data[i] = AddCounts(Entry, Data[i]);
     95   }
     96 }
     97 
     98 /// ReadProfilingArgBlock - Read the command line arguments that the progam was
     99 /// run with when the current profiling data packet(s) were generated.
    100 static void ReadProfilingArgBlock(const char *ToolName, FILE *F,
    101                                   bool ShouldByteSwap,
    102                                   SmallVectorImpl<std::string> &CommandLines) {
    103   // Read the number of bytes ...
    104   unsigned ArgLength = ReadProfilingNumEntries(ToolName, F, ShouldByteSwap);
    105 
    106   // Read in the arguments (if there are any to read).  Round up the length to
    107   // the nearest 4-byte multiple.
    108   SmallVector<char, 8> Args(ArgLength+4);
    109   if (ArgLength)
    110     ReadProfilingData<char>(ToolName, F, Args.data(), (ArgLength+3) & ~3);
    111 
    112   // Store the arguments.
    113   CommandLines.push_back(std::string(&Args[0], &Args[ArgLength]));
    114 }
    115 
    116 const unsigned ProfileDataLoader::Uncounted = ~0U;
    117 
    118 /// ProfileDataLoader ctor - Read the specified profiling data file, reporting
    119 /// a fatal error if the file is invalid or broken.
    120 ProfileDataLoader::ProfileDataLoader(const char *ToolName,
    121                                      const std::string &Filename)
    122   : Filename(Filename) {
    123   FILE *F = fopen(Filename.c_str(), "rb");
    124   if (F == 0)
    125     report_fatal_error(Twine(ToolName) + ": Error opening '" +
    126                        Filename + "': ");
    127 
    128   // Keep reading packets until we run out of them.
    129   unsigned PacketType;
    130   while (fread(&PacketType, sizeof(unsigned), 1, F) == 1) {
    131     // If the low eight bits of the packet are zero, we must be dealing with an
    132     // endianness mismatch.  Byteswap all words read from the profiling
    133     // information.  This can happen when the compiler host and target have
    134     // different endianness.
    135     bool ShouldByteSwap = (char)PacketType == 0;
    136     PacketType = ShouldByteSwap ? ByteSwap_32(PacketType) : PacketType;
    137 
    138     switch (PacketType) {
    139       case ArgumentInfo:
    140         ReadProfilingArgBlock(ToolName, F, ShouldByteSwap, CommandLines);
    141         break;
    142 
    143       case EdgeInfo:
    144         ReadProfilingBlock(ToolName, F, ShouldByteSwap, EdgeCounts);
    145         break;
    146 
    147       default:
    148         report_fatal_error(std::string(ToolName)
    149                            + ": Unknown profiling packet type");
    150         break;
    151     }
    152   }
    153 
    154   fclose(F);
    155 }
    156