blob: 256009ef9ff50e32ba71f0011c87f01d9e10df8d [file] [log] [blame]
//===- bolt/Passes/StokeInfo.h ----------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Pass to get information for functions for the Stoke Optimization
// To use the Stoke optimization technique to optimize the HHVM.
// This Pass solves the two major problems to use the Stoke program without
// proting its code:
//
// 1. Stoke works on function level, but it is only limited to relative
// small functions which are loop-free, call-free, exception-free, etc.
//
// 2. Stoke requires much information being manually provided, such as the
// register usages and memory modification, etc.
//
// This Pass analyzes all functions and get the required information into
// .csv file. Next, we use python scripts to process the file, filter
// out functions for optimization and automatically generate configure files.
// Finally, these configure files are feed to the Stoke to do the job.
//
//===----------------------------------------------------------------------===//
#ifndef BOLT_PASSES_STOKEINFO_H
#define BOLT_PASSES_STOKEINFO_H
#include "bolt/Passes/BinaryPasses.h"
#include <fstream>
namespace llvm {
namespace bolt {
class DataflowInfoManager;
class RegAnalysis;
/// Structure to hold information needed by Stoke for a function
struct StokeFuncInfo {
std::string FuncName;
uint64_t Offset;
uint64_t Size;
uint64_t NumInstrs;
uint64_t NumBlocks;
bool IsLoopFree;
unsigned NumLoops;
unsigned MaxLoopDepth;
uint64_t HotSize;
uint64_t TotalSize;
uint64_t Score;
bool HasCall;
std::set<std::string> DefIn;
std::set<std::string> LiveOut;
bool HeapOut;
bool StackOut;
bool HasRipAddr;
bool Omitted;
StokeFuncInfo() { reset(); }
void reset() {
FuncName = "";
Offset = Size = NumInstrs = NumBlocks = 0;
NumLoops = MaxLoopDepth = 0;
HotSize = TotalSize = 0;
Score = 0;
IsLoopFree = HasCall = HeapOut = StackOut = HasRipAddr = Omitted = false;
DefIn.clear();
LiveOut.clear();
}
void printCsvHeader(std::ofstream &Outfile) {
if (Outfile.is_open())
Outfile << "FuncName,Offset,Size,NumInstrs,NumBlocks,"
<< "IsLoopFree,NumLoops,MaxLoopDepth,"
<< "HotSize,TotalSize,"
<< "Score,"
<< "HasCall,"
<< "DefIn,LiveOut,HeapOut,StackOut,"
<< "HasRipAddr,"
<< "Omitted\n";
}
void printData(std::ofstream &Outfile) {
if (Outfile.is_open()) {
Outfile << FuncName << "," << Offset << "," << Size << "," << NumInstrs
<< "," << NumBlocks << "," << IsLoopFree << "," << NumLoops << ","
<< MaxLoopDepth << "," << HotSize << "," << TotalSize << ","
<< Score << "," << HasCall << ",\"{ ";
for (std::string S : DefIn)
Outfile << "%" << S << " ";
Outfile << "}\",\"{ ";
for (std::string S : LiveOut)
Outfile << "%" << S << " ";
Outfile << "}\"," << HeapOut << "," << StackOut << "," << HasRipAddr
<< "," << Omitted << "\n";
}
}
};
class StokeInfo : public BinaryFunctionPass {
private:
// stoke --def_in option default value, for X86:
// rax, rcx, rdx, rsi, rdi, r8, r9, xmm0-xmm7
BitVector DefaultDefInMask;
// --live_out option default value: rax, rdx, xmm0, xmm1
BitVector DefaultLiveOutMask;
uint16_t NumRegs;
public:
StokeInfo(const cl::opt<bool> &PrintPass) : BinaryFunctionPass(PrintPass) {}
const char *getName() const override { return "stoke-get-stat"; }
void checkInstr(const BinaryFunction &BF, StokeFuncInfo &FuncInfo);
/// Get all required information for the stoke optimization
bool checkFunction(BinaryFunction &BF, DataflowInfoManager &DInfo,
RegAnalysis &RA, StokeFuncInfo &FuncInfo);
void runOnFunctions(BinaryContext &BC) override;
};
} // namespace bolt
} // namespace llvm
#endif