Files
clang-p2996/bolt/BinaryBasicBlock.cpp
Maksim Panchenko 2029458f34 [BOLT] Strip 'repz' prefix from 'repz retq'.
Summary:
Add pass to strip 'repz' prefix from 'repz retq' sequence. The prefix
is not used in Intel CPUs afaik. The pass is on by default.

(cherry picked from FBD4610329)
2017-02-23 18:09:10 -08:00

267 lines
7.8 KiB
C++

//===--- BinaryBasicBlock.cpp - Interface for assembly-level basic block --===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//===----------------------------------------------------------------------===//
#include "BinaryBasicBlock.h"
#include "BinaryContext.h"
#include "BinaryFunction.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCInst.h"
#include <limits>
#include <string>
#undef DEBUG_TYPE
#define DEBUG_TYPE "bolt"
namespace llvm {
namespace bolt {
bool operator<(const BinaryBasicBlock &LHS, const BinaryBasicBlock &RHS) {
return LHS.Index < RHS.Index;
}
void BinaryBasicBlock::adjustNumPseudos(const MCInst &Inst, int Sign) {
auto &BC = Function->getBinaryContext();
if (BC.MII->get(Inst.getOpcode()).isPseudo())
NumPseudos += Sign;
}
BinaryBasicBlock::iterator BinaryBasicBlock::getFirstNonPseudo() {
const auto &BC = Function->getBinaryContext();
for (auto II = Instructions.begin(), E = Instructions.end(); II != E; ++II) {
if (!BC.MII->get(II->getOpcode()).isPseudo())
return II;
}
return end();
}
BinaryBasicBlock::reverse_iterator BinaryBasicBlock::getLastNonPseudo() {
const auto &BC = Function->getBinaryContext();
for (auto RII = Instructions.rbegin(), E = Instructions.rend();
RII != E; ++RII) {
if (!BC.MII->get(RII->getOpcode()).isPseudo())
return RII;
}
return rend();
}
bool BinaryBasicBlock::validateSuccessorInvariants() {
const MCSymbol *TBB = nullptr;
const MCSymbol *FBB = nullptr;
MCInst *CondBranch = nullptr;
MCInst *UncondBranch = nullptr;
assert(getNumPseudos() == getNumPseudos());
if (analyzeBranch(TBB, FBB, CondBranch, UncondBranch)) {
switch (Successors.size()) {
case 0:
return !CondBranch && !UncondBranch;
case 1:
return !CondBranch;
case 2:
if (CondBranch) {
return (TBB == getConditionalSuccessor(true)->getLabel() &&
((!UncondBranch && !FBB) ||
(UncondBranch && FBB == getConditionalSuccessor(false)->getLabel())));
}
return true;
default:
return true;
}
}
return true;
}
BinaryBasicBlock *BinaryBasicBlock::getSuccessor(const MCSymbol *Label) const {
if (!Label && succ_size() == 1)
return *succ_begin();
for (BinaryBasicBlock *BB : successors()) {
if (BB->getLabel() == Label)
return BB;
}
return nullptr;
}
BinaryBasicBlock *BinaryBasicBlock::getLandingPad(const MCSymbol *Label) const {
for (BinaryBasicBlock *BB : landing_pads()) {
if (BB->getLabel() == Label)
return BB;
}
return nullptr;
}
void BinaryBasicBlock::addSuccessor(BinaryBasicBlock *Succ,
uint64_t Count,
uint64_t MispredictedCount) {
Successors.push_back(Succ);
BranchInfo.push_back({Count, MispredictedCount});
Succ->Predecessors.push_back(this);
}
void BinaryBasicBlock::replaceSuccessor(BinaryBasicBlock *Succ,
BinaryBasicBlock *NewSucc,
uint64_t Count,
uint64_t MispredictedCount) {
auto I = succ_begin();
auto BI = BranchInfo.begin();
for (; I != succ_end(); ++I) {
assert(BI != BranchInfo.end() && "missing BranchInfo entry");
if (*I == Succ)
break;
++BI;
}
assert(I != succ_end() && "no such successor!");
*I = NewSucc;
*BI = BinaryBranchInfo{Count, MispredictedCount};
}
void BinaryBasicBlock::removeSuccessor(BinaryBasicBlock *Succ) {
Succ->removePredecessor(this);
auto I = succ_begin();
auto BI = BranchInfo.begin();
for (; I != succ_end(); ++I) {
assert(BI != BranchInfo.end() && "missing BranchInfo entry");
if (*I == Succ)
break;
++BI;
}
assert(I != succ_end() && "no such successor!");
Successors.erase(I);
BranchInfo.erase(BI);
}
void BinaryBasicBlock::addPredecessor(BinaryBasicBlock *Pred) {
Predecessors.push_back(Pred);
}
void BinaryBasicBlock::removePredecessor(BinaryBasicBlock *Pred) {
auto I = std::find(pred_begin(), pred_end(), Pred);
assert(I != pred_end() && "Pred is not a predecessor of this block!");
Predecessors.erase(I);
}
void BinaryBasicBlock::addLandingPad(BinaryBasicBlock *LPBlock) {
if (std::find(LandingPads.begin(), LandingPads.end(), LPBlock) == LandingPads.end()) {
LandingPads.push_back(LPBlock);
}
LPBlock->Throwers.insert(this);
}
void BinaryBasicBlock::clearLandingPads() {
for (auto *LPBlock : LandingPads) {
auto count = LPBlock->Throwers.erase(this);
assert(count == 1 && "Possible duplicate entry in LandingPads");
}
LandingPads.clear();
}
bool BinaryBasicBlock::analyzeBranch(const MCSymbol *&TBB,
const MCSymbol *&FBB,
MCInst *&CondBranch,
MCInst *&UncondBranch) {
auto &MIA = Function->getBinaryContext().MIA;
return MIA->analyzeBranch(Instructions, TBB, FBB, CondBranch, UncondBranch);
}
bool BinaryBasicBlock::swapConditionalSuccessors() {
if (succ_size() != 2)
return false;
std::swap(Successors[0], Successors[1]);
std::swap(BranchInfo[0], BranchInfo[1]);
return true;
}
void BinaryBasicBlock::addBranchInstruction(const BinaryBasicBlock *Successor) {
assert(isSuccessor(Successor));
auto &BC = Function->getBinaryContext();
MCInst NewInst;
BC.MIA->createUncondBranch(NewInst, Successor->getLabel(), BC.Ctx.get());
Instructions.emplace_back(std::move(NewInst));
}
void BinaryBasicBlock::addTailCallInstruction(const MCSymbol *Target) {
auto &BC = Function->getBinaryContext();
MCInst NewInst;
BC.MIA->createTailCall(NewInst, Target, BC.Ctx.get());
Instructions.emplace_back(std::move(NewInst));
}
uint32_t BinaryBasicBlock::getNumPseudos() const {
#ifndef NDEBUG
auto &BC = Function->getBinaryContext();
uint32_t N = 0;
for (auto &Instr : Instructions) {
if (BC.MII->get(Instr.getOpcode()).isPseudo())
++N;
}
if (N != NumPseudos) {
errs() << "BOLT-ERROR: instructions for basic block " << getName()
<< " in function " << *Function << ": calculated pseudos "
<< N << ", set pseudos " << NumPseudos << ", size " << size()
<< '\n';
llvm_unreachable("pseudos mismatch");
}
#endif
return NumPseudos;
}
ErrorOr<std::pair<double, double>>
BinaryBasicBlock::getBranchStats(const BinaryBasicBlock *Succ) const {
if (Function->hasValidProfile()) {
uint64_t TotalCount = 0;
uint64_t TotalMispreds = 0;
for (const auto &BI : BranchInfo) {
if (BI.Count != COUNT_NO_PROFILE) {
TotalCount += BI.Count;
TotalMispreds += BI.MispredictedCount;
}
}
if (TotalCount > 0) {
auto Itr = std::find(Successors.begin(), Successors.end(), Succ);
assert(Itr != Successors.end());
const auto &BI = BranchInfo[Itr - Successors.begin()];
if (BI.Count && BI.Count != COUNT_NO_PROFILE) {
if (TotalMispreds == 0) TotalMispreds = 1;
return std::make_pair(double(BI.Count) / TotalCount,
double(BI.MispredictedCount) / TotalMispreds);
}
}
}
return make_error_code(llvm::errc::result_out_of_range);
}
void BinaryBasicBlock::dump() const {
auto &BC = Function->getBinaryContext();
if (Label) outs() << Label->getName() << ":\n";
BC.printInstructions(outs(), Instructions.begin(), Instructions.end(), Offset);
outs() << "preds:";
for (auto itr = pred_begin(); itr != pred_end(); ++itr) {
outs() << " " << (*itr)->getName();
}
outs() << "\nsuccs:";
for (auto itr = succ_begin(); itr != succ_end(); ++itr) {
outs() << " " << (*itr)->getName();
}
outs() << "\n";
}
} // namespace bolt
} // namespace llvm