2015-10-09 17:21:14 -07:00
|
|
|
//===--- 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.
|
|
|
|
|
//
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
//
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
2015-10-14 15:35:14 -07:00
|
|
|
#include "BinaryBasicBlock.h"
|
2016-07-23 08:01:53 -07:00
|
|
|
#include "BinaryContext.h"
|
2016-08-29 21:11:22 -07:00
|
|
|
#include "BinaryFunction.h"
|
2015-10-09 17:21:14 -07:00
|
|
|
#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
|
2016-02-05 14:42:04 -08:00
|
|
|
#define DEBUG_TYPE "bolt"
|
2015-10-09 17:21:14 -07:00
|
|
|
|
|
|
|
|
namespace llvm {
|
2016-02-05 14:42:04 -08:00
|
|
|
namespace bolt {
|
2015-10-09 17:21:14 -07:00
|
|
|
|
2017-05-08 22:51:36 -07:00
|
|
|
constexpr uint32_t BinaryBasicBlock::INVALID_OFFSET;
|
|
|
|
|
|
2015-10-09 17:21:14 -07:00
|
|
|
bool operator<(const BinaryBasicBlock &LHS, const BinaryBasicBlock &RHS) {
|
2016-09-07 18:59:23 -07:00
|
|
|
return LHS.Index < RHS.Index;
|
2015-10-09 17:21:14 -07:00
|
|
|
}
|
2016-06-09 11:36:55 -07:00
|
|
|
|
Indirect call promotion optimization.
Summary:
Perform indirect call promotion optimization in BOLT.
The code scans the instructions during CFG creation for all
indirect calls. Right now indirect tail calls are not handled
since the functions are marked not simple. The offsets of the
indirect calls are stored for later use by the ICP pass.
The indirect call promotion pass visits each indirect call and
examines the BranchData for each. If the most frequent targets
from that callsite exceed the specified threshold (default 90%),
the call is promoted. Otherwise, it is ignored. By default,
only one target is considered at each callsite.
When an candiate callsite is processed, we modify the callsite
to test for the most common call targets before calling through
the original generic call mechanism.
The CFG and layout are modified by ICP.
A few new command line options have been added:
-indirect-call-promotion
-indirect-call-promotion-threshold=<percentage>
-indirect-call-promotion-topn=<int>
The threshold is the minimum frequency of a call target needed
before ICP is triggered.
The topn option controls the number of targets to consider for
each callsite, e.g. ICP is triggered if topn=2 and the total
requency of the top two call targets exceeds the threshold.
Example of ICP:
C++ code:
int B_count = 0;
int C_count = 0;
struct A { virtual void foo() = 0; }
struct B : public A { virtual void foo() { ++B_count; }; };
struct C : public A { virtual void foo() { ++C_count; }; };
A* a = ...
a->foo();
...
original:
400863: 49 8b 07 mov (%r15),%rax
400866: 4c 89 ff mov %r15,%rdi
400869: ff 10 callq *(%rax)
40086b: 41 83 e6 01 and $0x1,%r14d
40086f: 4d 89 e6 mov %r12,%r14
400872: 4c 0f 44 f5 cmove %rbp,%r14
400876: 4c 89 f7 mov %r14,%rdi
...
after ICP:
40085e: 49 8b 07 mov (%r15),%rax
400861: 4c 89 ff mov %r15,%rdi
400864: 49 ba e0 0b 40 00 00 movabs $0x400be0,%r10
40086b: 00 00 00
40086e: 4c 3b 10 cmp (%rax),%r10
400871: 75 29 jne 40089c <main+0x9c>
400873: 41 ff d2 callq *%r10
400876: 41 83 e6 01 and $0x1,%r14d
40087a: 4d 89 e6 mov %r12,%r14
40087d: 4c 0f 44 f5 cmove %rbp,%r14
400881: 4c 89 f7 mov %r14,%rdi
...
40089c: ff 10 callq *(%rax)
40089e: eb d6 jmp 400876 <main+0x76>
(cherry picked from FBD3612218)
2016-09-07 18:59:23 -07:00
|
|
|
void BinaryBasicBlock::adjustNumPseudos(const MCInst &Inst, int Sign) {
|
|
|
|
|
auto &BC = Function->getBinaryContext();
|
|
|
|
|
if (BC.MII->get(Inst.getOpcode()).isPseudo())
|
|
|
|
|
NumPseudos += Sign;
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-23 18:09:10 -08:00
|
|
|
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;
|
2016-09-08 14:52:26 -07:00
|
|
|
}
|
2017-02-23 18:09:10 -08:00
|
|
|
return end();
|
2016-09-08 14:52:26 -07:00
|
|
|
}
|
|
|
|
|
|
2017-02-23 18:09:10 -08:00
|
|
|
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;
|
2016-09-02 18:09:07 -07:00
|
|
|
}
|
2017-02-23 18:09:10 -08:00
|
|
|
return rend();
|
2016-09-02 18:09:07 -07:00
|
|
|
}
|
|
|
|
|
|
Indirect call promotion optimization.
Summary:
Perform indirect call promotion optimization in BOLT.
The code scans the instructions during CFG creation for all
indirect calls. Right now indirect tail calls are not handled
since the functions are marked not simple. The offsets of the
indirect calls are stored for later use by the ICP pass.
The indirect call promotion pass visits each indirect call and
examines the BranchData for each. If the most frequent targets
from that callsite exceed the specified threshold (default 90%),
the call is promoted. Otherwise, it is ignored. By default,
only one target is considered at each callsite.
When an candiate callsite is processed, we modify the callsite
to test for the most common call targets before calling through
the original generic call mechanism.
The CFG and layout are modified by ICP.
A few new command line options have been added:
-indirect-call-promotion
-indirect-call-promotion-threshold=<percentage>
-indirect-call-promotion-topn=<int>
The threshold is the minimum frequency of a call target needed
before ICP is triggered.
The topn option controls the number of targets to consider for
each callsite, e.g. ICP is triggered if topn=2 and the total
requency of the top two call targets exceeds the threshold.
Example of ICP:
C++ code:
int B_count = 0;
int C_count = 0;
struct A { virtual void foo() = 0; }
struct B : public A { virtual void foo() { ++B_count; }; };
struct C : public A { virtual void foo() { ++C_count; }; };
A* a = ...
a->foo();
...
original:
400863: 49 8b 07 mov (%r15),%rax
400866: 4c 89 ff mov %r15,%rdi
400869: ff 10 callq *(%rax)
40086b: 41 83 e6 01 and $0x1,%r14d
40086f: 4d 89 e6 mov %r12,%r14
400872: 4c 0f 44 f5 cmove %rbp,%r14
400876: 4c 89 f7 mov %r14,%rdi
...
after ICP:
40085e: 49 8b 07 mov (%r15),%rax
400861: 4c 89 ff mov %r15,%rdi
400864: 49 ba e0 0b 40 00 00 movabs $0x400be0,%r10
40086b: 00 00 00
40086e: 4c 3b 10 cmp (%rax),%r10
400871: 75 29 jne 40089c <main+0x9c>
400873: 41 ff d2 callq *%r10
400876: 41 83 e6 01 and $0x1,%r14d
40087a: 4d 89 e6 mov %r12,%r14
40087d: 4c 0f 44 f5 cmove %rbp,%r14
400881: 4c 89 f7 mov %r14,%rdi
...
40089c: ff 10 callq *(%rax)
40089e: eb d6 jmp 400876 <main+0x76>
(cherry picked from FBD3612218)
2016-09-07 18:59:23 -07:00
|
|
|
bool BinaryBasicBlock::validateSuccessorInvariants() {
|
2017-03-08 19:58:33 -08:00
|
|
|
const auto *Inst = getLastNonPseudoInstr();
|
|
|
|
|
const auto *JT = Inst ? Function->getJumpTable(*Inst) : nullptr;
|
|
|
|
|
auto &BC = Function->getBinaryContext();
|
|
|
|
|
bool Valid = true;
|
Indirect call promotion optimization.
Summary:
Perform indirect call promotion optimization in BOLT.
The code scans the instructions during CFG creation for all
indirect calls. Right now indirect tail calls are not handled
since the functions are marked not simple. The offsets of the
indirect calls are stored for later use by the ICP pass.
The indirect call promotion pass visits each indirect call and
examines the BranchData for each. If the most frequent targets
from that callsite exceed the specified threshold (default 90%),
the call is promoted. Otherwise, it is ignored. By default,
only one target is considered at each callsite.
When an candiate callsite is processed, we modify the callsite
to test for the most common call targets before calling through
the original generic call mechanism.
The CFG and layout are modified by ICP.
A few new command line options have been added:
-indirect-call-promotion
-indirect-call-promotion-threshold=<percentage>
-indirect-call-promotion-topn=<int>
The threshold is the minimum frequency of a call target needed
before ICP is triggered.
The topn option controls the number of targets to consider for
each callsite, e.g. ICP is triggered if topn=2 and the total
requency of the top two call targets exceeds the threshold.
Example of ICP:
C++ code:
int B_count = 0;
int C_count = 0;
struct A { virtual void foo() = 0; }
struct B : public A { virtual void foo() { ++B_count; }; };
struct C : public A { virtual void foo() { ++C_count; }; };
A* a = ...
a->foo();
...
original:
400863: 49 8b 07 mov (%r15),%rax
400866: 4c 89 ff mov %r15,%rdi
400869: ff 10 callq *(%rax)
40086b: 41 83 e6 01 and $0x1,%r14d
40086f: 4d 89 e6 mov %r12,%r14
400872: 4c 0f 44 f5 cmove %rbp,%r14
400876: 4c 89 f7 mov %r14,%rdi
...
after ICP:
40085e: 49 8b 07 mov (%r15),%rax
400861: 4c 89 ff mov %r15,%rdi
400864: 49 ba e0 0b 40 00 00 movabs $0x400be0,%r10
40086b: 00 00 00
40086e: 4c 3b 10 cmp (%rax),%r10
400871: 75 29 jne 40089c <main+0x9c>
400873: 41 ff d2 callq *%r10
400876: 41 83 e6 01 and $0x1,%r14d
40087a: 4d 89 e6 mov %r12,%r14
40087d: 4c 0f 44 f5 cmove %rbp,%r14
400881: 4c 89 f7 mov %r14,%rdi
...
40089c: ff 10 callq *(%rax)
40089e: eb d6 jmp 400876 <main+0x76>
(cherry picked from FBD3612218)
2016-09-07 18:59:23 -07:00
|
|
|
|
2017-03-08 19:58:33 -08:00
|
|
|
if (JT) {
|
|
|
|
|
// Note: for now we assume that successors do not reference labels from
|
|
|
|
|
// any overlapping jump tables. We only look at the entries for the jump
|
|
|
|
|
// table that is referenced at the last instruction.
|
2018-03-09 09:45:13 -08:00
|
|
|
const auto Range = JT->getEntriesForAddress(BC.MIB->getJumpTable(*Inst));
|
2017-03-08 19:58:33 -08:00
|
|
|
const std::vector<const MCSymbol *> Entries(&JT->Entries[Range.first],
|
|
|
|
|
&JT->Entries[Range.second]);
|
|
|
|
|
std::set<const MCSymbol *> UniqueSyms(Entries.begin(), Entries.end());
|
|
|
|
|
for (auto *Succ : Successors) {
|
|
|
|
|
auto Itr = UniqueSyms.find(Succ->getLabel());
|
|
|
|
|
if (Itr != UniqueSyms.end()) {
|
|
|
|
|
UniqueSyms.erase(Itr);
|
|
|
|
|
} else {
|
|
|
|
|
// Work on the assumption that jump table blocks don't
|
|
|
|
|
// have a conditional successor.
|
|
|
|
|
Valid = false;
|
2017-11-14 20:05:11 -08:00
|
|
|
errs() << "BOLT-WARNING: Jump table successor "
|
|
|
|
|
<< Succ->getName()
|
|
|
|
|
<< " not contained in the jump table.\n";
|
2017-03-08 19:58:33 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// If there are any leftover entries in the jump table, they
|
|
|
|
|
// must be one of the function end labels.
|
2017-11-14 20:05:11 -08:00
|
|
|
if (Valid) {
|
|
|
|
|
for (auto *Sym : UniqueSyms) {
|
|
|
|
|
Valid &= (Sym == Function->getFunctionEndLabel() ||
|
|
|
|
|
Sym == Function->getFunctionColdEndLabel());
|
|
|
|
|
if (!Valid) {
|
|
|
|
|
errs() << "BOLT-WARNING: Jump table contains illegal entry: "
|
|
|
|
|
<< Sym->getName() << "\n";
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-03-08 19:58:33 -08:00
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
const MCSymbol *TBB = nullptr;
|
|
|
|
|
const MCSymbol *FBB = nullptr;
|
|
|
|
|
MCInst *CondBranch = nullptr;
|
|
|
|
|
MCInst *UncondBranch = nullptr;
|
Indirect call promotion optimization.
Summary:
Perform indirect call promotion optimization in BOLT.
The code scans the instructions during CFG creation for all
indirect calls. Right now indirect tail calls are not handled
since the functions are marked not simple. The offsets of the
indirect calls are stored for later use by the ICP pass.
The indirect call promotion pass visits each indirect call and
examines the BranchData for each. If the most frequent targets
from that callsite exceed the specified threshold (default 90%),
the call is promoted. Otherwise, it is ignored. By default,
only one target is considered at each callsite.
When an candiate callsite is processed, we modify the callsite
to test for the most common call targets before calling through
the original generic call mechanism.
The CFG and layout are modified by ICP.
A few new command line options have been added:
-indirect-call-promotion
-indirect-call-promotion-threshold=<percentage>
-indirect-call-promotion-topn=<int>
The threshold is the minimum frequency of a call target needed
before ICP is triggered.
The topn option controls the number of targets to consider for
each callsite, e.g. ICP is triggered if topn=2 and the total
requency of the top two call targets exceeds the threshold.
Example of ICP:
C++ code:
int B_count = 0;
int C_count = 0;
struct A { virtual void foo() = 0; }
struct B : public A { virtual void foo() { ++B_count; }; };
struct C : public A { virtual void foo() { ++C_count; }; };
A* a = ...
a->foo();
...
original:
400863: 49 8b 07 mov (%r15),%rax
400866: 4c 89 ff mov %r15,%rdi
400869: ff 10 callq *(%rax)
40086b: 41 83 e6 01 and $0x1,%r14d
40086f: 4d 89 e6 mov %r12,%r14
400872: 4c 0f 44 f5 cmove %rbp,%r14
400876: 4c 89 f7 mov %r14,%rdi
...
after ICP:
40085e: 49 8b 07 mov (%r15),%rax
400861: 4c 89 ff mov %r15,%rdi
400864: 49 ba e0 0b 40 00 00 movabs $0x400be0,%r10
40086b: 00 00 00
40086e: 4c 3b 10 cmp (%rax),%r10
400871: 75 29 jne 40089c <main+0x9c>
400873: 41 ff d2 callq *%r10
400876: 41 83 e6 01 and $0x1,%r14d
40087a: 4d 89 e6 mov %r12,%r14
40087d: 4c 0f 44 f5 cmove %rbp,%r14
400881: 4c 89 f7 mov %r14,%rdi
...
40089c: ff 10 callq *(%rax)
40089e: eb d6 jmp 400876 <main+0x76>
(cherry picked from FBD3612218)
2016-09-07 18:59:23 -07:00
|
|
|
|
2017-03-08 19:58:33 -08:00
|
|
|
if (analyzeBranch(TBB, FBB, CondBranch, UncondBranch)) {
|
|
|
|
|
switch (Successors.size()) {
|
|
|
|
|
case 0:
|
|
|
|
|
Valid = !CondBranch && !UncondBranch;
|
|
|
|
|
break;
|
2017-11-28 09:57:21 -08:00
|
|
|
case 1: {
|
|
|
|
|
const bool HasCondBlock = CondBranch &&
|
2018-03-09 09:45:13 -08:00
|
|
|
Function->getBasicBlockForLabel(BC.MIB->getTargetSymbol(*CondBranch));
|
2017-11-28 09:57:21 -08:00
|
|
|
Valid = !CondBranch || !HasCondBlock;
|
2017-03-08 19:58:33 -08:00
|
|
|
break;
|
2017-11-28 09:57:21 -08:00
|
|
|
}
|
2017-03-08 19:58:33 -08:00
|
|
|
case 2:
|
|
|
|
|
Valid =
|
2017-11-06 21:04:28 -08:00
|
|
|
(CondBranch &&
|
2017-03-08 19:58:33 -08:00
|
|
|
(TBB == getConditionalSuccessor(true)->getLabel() &&
|
|
|
|
|
((!UncondBranch && !FBB) ||
|
|
|
|
|
(UncondBranch &&
|
|
|
|
|
FBB == getConditionalSuccessor(false)->getLabel()))));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!Valid) {
|
|
|
|
|
errs() << "BOLT-WARNING: CFG invalid in " << *getFunction() << " @ "
|
|
|
|
|
<< getName() << "\n";
|
|
|
|
|
if (JT) {
|
|
|
|
|
errs() << "Jump Table instruction addr = 0x"
|
2018-03-09 09:45:13 -08:00
|
|
|
<< Twine::utohexstr(BC.MIB->getJumpTable(*Inst)) << "\n";
|
2017-03-08 19:58:33 -08:00
|
|
|
JT->print(errs());
|
Indirect call promotion optimization.
Summary:
Perform indirect call promotion optimization in BOLT.
The code scans the instructions during CFG creation for all
indirect calls. Right now indirect tail calls are not handled
since the functions are marked not simple. The offsets of the
indirect calls are stored for later use by the ICP pass.
The indirect call promotion pass visits each indirect call and
examines the BranchData for each. If the most frequent targets
from that callsite exceed the specified threshold (default 90%),
the call is promoted. Otherwise, it is ignored. By default,
only one target is considered at each callsite.
When an candiate callsite is processed, we modify the callsite
to test for the most common call targets before calling through
the original generic call mechanism.
The CFG and layout are modified by ICP.
A few new command line options have been added:
-indirect-call-promotion
-indirect-call-promotion-threshold=<percentage>
-indirect-call-promotion-topn=<int>
The threshold is the minimum frequency of a call target needed
before ICP is triggered.
The topn option controls the number of targets to consider for
each callsite, e.g. ICP is triggered if topn=2 and the total
requency of the top two call targets exceeds the threshold.
Example of ICP:
C++ code:
int B_count = 0;
int C_count = 0;
struct A { virtual void foo() = 0; }
struct B : public A { virtual void foo() { ++B_count; }; };
struct C : public A { virtual void foo() { ++C_count; }; };
A* a = ...
a->foo();
...
original:
400863: 49 8b 07 mov (%r15),%rax
400866: 4c 89 ff mov %r15,%rdi
400869: ff 10 callq *(%rax)
40086b: 41 83 e6 01 and $0x1,%r14d
40086f: 4d 89 e6 mov %r12,%r14
400872: 4c 0f 44 f5 cmove %rbp,%r14
400876: 4c 89 f7 mov %r14,%rdi
...
after ICP:
40085e: 49 8b 07 mov (%r15),%rax
400861: 4c 89 ff mov %r15,%rdi
400864: 49 ba e0 0b 40 00 00 movabs $0x400be0,%r10
40086b: 00 00 00
40086e: 4c 3b 10 cmp (%rax),%r10
400871: 75 29 jne 40089c <main+0x9c>
400873: 41 ff d2 callq *%r10
400876: 41 83 e6 01 and $0x1,%r14d
40087a: 4d 89 e6 mov %r12,%r14
40087d: 4c 0f 44 f5 cmove %rbp,%r14
400881: 4c 89 f7 mov %r14,%rdi
...
40089c: ff 10 callq *(%rax)
40089e: eb d6 jmp 400876 <main+0x76>
(cherry picked from FBD3612218)
2016-09-07 18:59:23 -07:00
|
|
|
}
|
2017-11-28 09:57:21 -08:00
|
|
|
getFunction()->dump();
|
Indirect call promotion optimization.
Summary:
Perform indirect call promotion optimization in BOLT.
The code scans the instructions during CFG creation for all
indirect calls. Right now indirect tail calls are not handled
since the functions are marked not simple. The offsets of the
indirect calls are stored for later use by the ICP pass.
The indirect call promotion pass visits each indirect call and
examines the BranchData for each. If the most frequent targets
from that callsite exceed the specified threshold (default 90%),
the call is promoted. Otherwise, it is ignored. By default,
only one target is considered at each callsite.
When an candiate callsite is processed, we modify the callsite
to test for the most common call targets before calling through
the original generic call mechanism.
The CFG and layout are modified by ICP.
A few new command line options have been added:
-indirect-call-promotion
-indirect-call-promotion-threshold=<percentage>
-indirect-call-promotion-topn=<int>
The threshold is the minimum frequency of a call target needed
before ICP is triggered.
The topn option controls the number of targets to consider for
each callsite, e.g. ICP is triggered if topn=2 and the total
requency of the top two call targets exceeds the threshold.
Example of ICP:
C++ code:
int B_count = 0;
int C_count = 0;
struct A { virtual void foo() = 0; }
struct B : public A { virtual void foo() { ++B_count; }; };
struct C : public A { virtual void foo() { ++C_count; }; };
A* a = ...
a->foo();
...
original:
400863: 49 8b 07 mov (%r15),%rax
400866: 4c 89 ff mov %r15,%rdi
400869: ff 10 callq *(%rax)
40086b: 41 83 e6 01 and $0x1,%r14d
40086f: 4d 89 e6 mov %r12,%r14
400872: 4c 0f 44 f5 cmove %rbp,%r14
400876: 4c 89 f7 mov %r14,%rdi
...
after ICP:
40085e: 49 8b 07 mov (%r15),%rax
400861: 4c 89 ff mov %r15,%rdi
400864: 49 ba e0 0b 40 00 00 movabs $0x400be0,%r10
40086b: 00 00 00
40086e: 4c 3b 10 cmp (%rax),%r10
400871: 75 29 jne 40089c <main+0x9c>
400873: 41 ff d2 callq *%r10
400876: 41 83 e6 01 and $0x1,%r14d
40087a: 4d 89 e6 mov %r12,%r14
40087d: 4c 0f 44 f5 cmove %rbp,%r14
400881: 4c 89 f7 mov %r14,%rdi
...
40089c: ff 10 callq *(%rax)
40089e: eb d6 jmp 400876 <main+0x76>
(cherry picked from FBD3612218)
2016-09-07 18:59:23 -07:00
|
|
|
}
|
2017-03-08 19:58:33 -08:00
|
|
|
return Valid;
|
Indirect call promotion optimization.
Summary:
Perform indirect call promotion optimization in BOLT.
The code scans the instructions during CFG creation for all
indirect calls. Right now indirect tail calls are not handled
since the functions are marked not simple. The offsets of the
indirect calls are stored for later use by the ICP pass.
The indirect call promotion pass visits each indirect call and
examines the BranchData for each. If the most frequent targets
from that callsite exceed the specified threshold (default 90%),
the call is promoted. Otherwise, it is ignored. By default,
only one target is considered at each callsite.
When an candiate callsite is processed, we modify the callsite
to test for the most common call targets before calling through
the original generic call mechanism.
The CFG and layout are modified by ICP.
A few new command line options have been added:
-indirect-call-promotion
-indirect-call-promotion-threshold=<percentage>
-indirect-call-promotion-topn=<int>
The threshold is the minimum frequency of a call target needed
before ICP is triggered.
The topn option controls the number of targets to consider for
each callsite, e.g. ICP is triggered if topn=2 and the total
requency of the top two call targets exceeds the threshold.
Example of ICP:
C++ code:
int B_count = 0;
int C_count = 0;
struct A { virtual void foo() = 0; }
struct B : public A { virtual void foo() { ++B_count; }; };
struct C : public A { virtual void foo() { ++C_count; }; };
A* a = ...
a->foo();
...
original:
400863: 49 8b 07 mov (%r15),%rax
400866: 4c 89 ff mov %r15,%rdi
400869: ff 10 callq *(%rax)
40086b: 41 83 e6 01 and $0x1,%r14d
40086f: 4d 89 e6 mov %r12,%r14
400872: 4c 0f 44 f5 cmove %rbp,%r14
400876: 4c 89 f7 mov %r14,%rdi
...
after ICP:
40085e: 49 8b 07 mov (%r15),%rax
400861: 4c 89 ff mov %r15,%rdi
400864: 49 ba e0 0b 40 00 00 movabs $0x400be0,%r10
40086b: 00 00 00
40086e: 4c 3b 10 cmp (%rax),%r10
400871: 75 29 jne 40089c <main+0x9c>
400873: 41 ff d2 callq *%r10
400876: 41 83 e6 01 and $0x1,%r14d
40087a: 4d 89 e6 mov %r12,%r14
40087d: 4c 0f 44 f5 cmove %rbp,%r14
400881: 4c 89 f7 mov %r14,%rdi
...
40089c: ff 10 callq *(%rax)
40089e: eb d6 jmp 400876 <main+0x76>
(cherry picked from FBD3612218)
2016-09-07 18:59:23 -07:00
|
|
|
}
|
2017-02-24 21:59:33 -08:00
|
|
|
|
2016-06-09 11:36:55 -07:00
|
|
|
BinaryBasicBlock *BinaryBasicBlock::getSuccessor(const MCSymbol *Label) const {
|
2016-08-29 21:11:22 -07:00
|
|
|
if (!Label && succ_size() == 1)
|
|
|
|
|
return *succ_begin();
|
|
|
|
|
|
2016-06-09 11:36:55 -07:00
|
|
|
for (BinaryBasicBlock *BB : successors()) {
|
|
|
|
|
if (BB->getLabel() == Label)
|
|
|
|
|
return BB;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-31 11:45:37 -07:00
|
|
|
BinaryBasicBlock *
|
|
|
|
|
BinaryBasicBlock::getSuccessor(const MCSymbol *Label,
|
|
|
|
|
BinaryBranchInfo &BI) const {
|
|
|
|
|
auto BIIter = branch_info_begin();
|
|
|
|
|
for (BinaryBasicBlock *BB : successors()) {
|
|
|
|
|
if (BB->getLabel() == Label) {
|
|
|
|
|
BI = *BIIter;
|
|
|
|
|
return BB;
|
|
|
|
|
}
|
|
|
|
|
++BIIter;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-09 11:36:55 -07:00
|
|
|
BinaryBasicBlock *BinaryBasicBlock::getLandingPad(const MCSymbol *Label) const {
|
|
|
|
|
for (BinaryBasicBlock *BB : landing_pads()) {
|
|
|
|
|
if (BB->getLabel() == Label)
|
|
|
|
|
return BB;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
2015-10-09 17:21:14 -07:00
|
|
|
|
2017-02-24 21:59:33 -08:00
|
|
|
int32_t BinaryBasicBlock::getCFIStateAtInstr(const MCInst *Instr) const {
|
2017-05-01 16:52:54 -07:00
|
|
|
assert(
|
|
|
|
|
getFunction()->getState() >= BinaryFunction::State::CFG &&
|
|
|
|
|
"can only calculate CFI state when function is in or past the CFG state");
|
2017-02-24 21:59:33 -08:00
|
|
|
|
|
|
|
|
const auto &FDEProgram = getFunction()->getFDEProgram();
|
|
|
|
|
|
|
|
|
|
// Find the last CFI preceding Instr in this basic block.
|
|
|
|
|
const MCInst *LastCFI = nullptr;
|
|
|
|
|
bool InstrSeen = (Instr == nullptr);
|
|
|
|
|
for (auto RII = Instructions.rbegin(), E = Instructions.rend();
|
|
|
|
|
RII != E; ++RII) {
|
|
|
|
|
if (!InstrSeen) {
|
|
|
|
|
InstrSeen = (&*RII == Instr);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2018-03-09 09:45:13 -08:00
|
|
|
if (Function->getBinaryContext().MIB->isCFI(*RII)) {
|
2017-02-24 21:59:33 -08:00
|
|
|
LastCFI = &*RII;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert(InstrSeen && "instruction expected in basic block");
|
|
|
|
|
|
|
|
|
|
// CFI state is the same as at basic block entry point.
|
|
|
|
|
if (!LastCFI)
|
|
|
|
|
return getCFIState();
|
|
|
|
|
|
|
|
|
|
// Fold all RememberState/RestoreState sequences, such as for:
|
|
|
|
|
//
|
|
|
|
|
// [ CFI #(K-1) ]
|
|
|
|
|
// RememberState (#K)
|
|
|
|
|
// ....
|
|
|
|
|
// RestoreState
|
|
|
|
|
// RememberState
|
|
|
|
|
// ....
|
|
|
|
|
// RestoreState
|
|
|
|
|
// [ GNU_args_size ]
|
|
|
|
|
// RememberState
|
|
|
|
|
// ....
|
|
|
|
|
// RestoreState <- LastCFI
|
|
|
|
|
//
|
|
|
|
|
// we return K - the most efficient state to (re-)generate.
|
|
|
|
|
int64_t State = LastCFI->getOperand(0).getImm();
|
|
|
|
|
while (State >= 0 &&
|
|
|
|
|
FDEProgram[State].getOperation() == MCCFIInstruction::OpRestoreState) {
|
|
|
|
|
int32_t Depth = 1;
|
|
|
|
|
--State;
|
|
|
|
|
assert(State >= 0 && "first CFI cannot be RestoreState");
|
|
|
|
|
while (Depth && State >= 0) {
|
|
|
|
|
const auto &CFIInstr = FDEProgram[State];
|
|
|
|
|
if (CFIInstr.getOperation() == MCCFIInstruction::OpRestoreState) {
|
|
|
|
|
++Depth;
|
|
|
|
|
} else if (CFIInstr.getOperation() == MCCFIInstruction::OpRememberState) {
|
|
|
|
|
--Depth;
|
|
|
|
|
}
|
|
|
|
|
--State;
|
|
|
|
|
}
|
|
|
|
|
assert(Depth == 0 && "unbalanced RememberState/RestoreState stack");
|
|
|
|
|
|
|
|
|
|
// Skip any GNU_args_size.
|
|
|
|
|
while (State >= 0 &&
|
|
|
|
|
FDEProgram[State].getOperation() == MCCFIInstruction::OpGnuArgsSize){
|
|
|
|
|
--State;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert((State + 1 >= 0) && "miscalculated CFI state");
|
|
|
|
|
return State + 1;
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-09 17:21:14 -07:00
|
|
|
void BinaryBasicBlock::addSuccessor(BinaryBasicBlock *Succ,
|
|
|
|
|
uint64_t Count,
|
|
|
|
|
uint64_t MispredictedCount) {
|
|
|
|
|
Successors.push_back(Succ);
|
2015-10-12 12:30:47 -07:00
|
|
|
BranchInfo.push_back({Count, MispredictedCount});
|
2015-10-09 17:21:14 -07:00
|
|
|
Succ->Predecessors.push_back(this);
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-02 18:09:07 -07:00
|
|
|
void BinaryBasicBlock::replaceSuccessor(BinaryBasicBlock *Succ,
|
|
|
|
|
BinaryBasicBlock *NewSucc,
|
|
|
|
|
uint64_t Count,
|
|
|
|
|
uint64_t MispredictedCount) {
|
2017-03-20 22:44:25 -07:00
|
|
|
Succ->removePredecessor(this);
|
2016-09-02 18:09:07 -07:00
|
|
|
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};
|
2017-03-20 22:44:25 -07:00
|
|
|
NewSucc->addPredecessor(this);
|
2016-09-02 18:09:07 -07:00
|
|
|
}
|
|
|
|
|
|
2018-03-30 17:44:14 -07:00
|
|
|
void BinaryBasicBlock::removeAllSuccessors() {
|
|
|
|
|
for (auto *SuccessorBB : successors()) {
|
|
|
|
|
SuccessorBB->removePredecessor(this);
|
|
|
|
|
}
|
|
|
|
|
Successors.clear();
|
|
|
|
|
BranchInfo.clear();
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-09 17:21:14 -07:00
|
|
|
void BinaryBasicBlock::removeSuccessor(BinaryBasicBlock *Succ) {
|
|
|
|
|
Succ->removePredecessor(this);
|
2015-10-12 12:30:47 -07:00
|
|
|
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;
|
|
|
|
|
}
|
2015-10-09 17:21:14 -07:00
|
|
|
assert(I != succ_end() && "no such successor!");
|
|
|
|
|
|
|
|
|
|
Successors.erase(I);
|
2015-10-12 12:30:47 -07:00
|
|
|
BranchInfo.erase(BI);
|
2015-10-09 17:21:14 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BinaryBasicBlock::addPredecessor(BinaryBasicBlock *Pred) {
|
|
|
|
|
Predecessors.push_back(Pred);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BinaryBasicBlock::removePredecessor(BinaryBasicBlock *Pred) {
|
2018-03-30 17:44:14 -07:00
|
|
|
// Note: the predecessor could be listed multiple times.
|
|
|
|
|
bool Erased{false};
|
|
|
|
|
for (auto PredI = Predecessors.begin(); PredI != Predecessors.end(); ) {
|
|
|
|
|
if (*PredI == Pred) {
|
|
|
|
|
Erased = true;
|
|
|
|
|
PredI = Predecessors.erase(PredI);
|
|
|
|
|
} else {
|
|
|
|
|
++PredI;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
assert(Erased && "Pred is not a predecessor of this block!");
|
2015-10-09 17:21:14 -07:00
|
|
|
}
|
|
|
|
|
|
2017-03-20 22:44:25 -07:00
|
|
|
void BinaryBasicBlock::removeDuplicateConditionalSuccessor(MCInst *CondBranch) {
|
2017-04-05 13:00:20 -07:00
|
|
|
assert(succ_size() == 2 && Successors[0] == Successors[1] &&
|
|
|
|
|
"conditional successors expected");
|
2017-03-20 22:44:25 -07:00
|
|
|
|
|
|
|
|
auto *Succ = Successors[0];
|
|
|
|
|
const auto CondBI = BranchInfo[0];
|
|
|
|
|
const auto UncondBI = BranchInfo[1];
|
|
|
|
|
|
2019-01-31 11:23:02 -08:00
|
|
|
eraseInstruction(findInstruction(CondBranch));
|
2017-03-20 22:44:25 -07:00
|
|
|
|
|
|
|
|
Successors.clear();
|
|
|
|
|
BranchInfo.clear();
|
|
|
|
|
|
|
|
|
|
Successors.push_back(Succ);
|
|
|
|
|
|
2017-04-05 13:00:20 -07:00
|
|
|
uint64_t Count = COUNT_NO_PROFILE;
|
|
|
|
|
if (CondBI.Count != COUNT_NO_PROFILE && UncondBI.Count != COUNT_NO_PROFILE)
|
|
|
|
|
Count = CondBI.Count + UncondBI.Count;
|
|
|
|
|
BranchInfo.push_back({Count, 0});
|
2017-03-20 22:44:25 -07:00
|
|
|
}
|
|
|
|
|
|
2019-01-31 11:23:02 -08:00
|
|
|
void BinaryBasicBlock::adjustExecutionCount(double Ratio) {
|
|
|
|
|
auto adjustedCount = [&](uint64_t Count) -> uint64_t {
|
|
|
|
|
auto NewCount = Count * Ratio;
|
|
|
|
|
if (!NewCount && Count && (Ratio > 0.0))
|
|
|
|
|
NewCount = 1;
|
|
|
|
|
return NewCount;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
setExecutionCount(adjustedCount(getKnownExecutionCount()));
|
|
|
|
|
for (auto &BI : branch_info()) {
|
|
|
|
|
if (BI.Count != COUNT_NO_PROFILE)
|
|
|
|
|
BI.Count = adjustedCount(BI.Count);
|
|
|
|
|
if (BI.MispredictedCount != COUNT_INFERRED)
|
|
|
|
|
BI.MispredictedCount = adjustedCount(BI.MispredictedCount);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-13 17:12:00 -07:00
|
|
|
bool BinaryBasicBlock::analyzeBranch(const MCSymbol *&TBB,
|
2016-05-02 12:47:18 -07:00
|
|
|
const MCSymbol *&FBB,
|
|
|
|
|
MCInst *&CondBranch,
|
|
|
|
|
MCInst *&UncondBranch) {
|
2018-03-09 09:45:13 -08:00
|
|
|
auto &MIB = Function->getBinaryContext().MIB;
|
|
|
|
|
return MIB->analyzeBranch(Instructions.begin(),
|
2017-11-04 19:22:05 -07:00
|
|
|
Instructions.end(),
|
|
|
|
|
TBB,
|
|
|
|
|
FBB,
|
|
|
|
|
CondBranch,
|
|
|
|
|
UncondBranch);
|
2016-05-02 12:47:18 -07:00
|
|
|
}
|
2018-04-13 15:46:19 -07:00
|
|
|
|
|
|
|
|
bool BinaryBasicBlock::isMacroOpFusionPair(const_iterator I) const {
|
|
|
|
|
auto &MIB = Function->getBinaryContext().MIB;
|
|
|
|
|
ArrayRef<MCInst> Insts = Instructions;
|
|
|
|
|
return MIB->isMacroOpFusionPair(Insts.slice(I - begin()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BinaryBasicBlock::const_iterator
|
|
|
|
|
BinaryBasicBlock::getMacroOpFusionPair() const {
|
|
|
|
|
if (!Function->getBinaryContext().isX86())
|
|
|
|
|
return end();
|
|
|
|
|
|
2018-08-03 16:36:06 -07:00
|
|
|
if (getNumNonPseudos() < 2 || succ_size() != 2)
|
2018-04-13 15:46:19 -07:00
|
|
|
return end();
|
|
|
|
|
|
|
|
|
|
auto RI = getLastNonPseudo();
|
|
|
|
|
assert(RI != rend() && "cannot have an empty block with 2 successors");
|
|
|
|
|
|
|
|
|
|
auto &BC = Function->getBinaryContext();
|
|
|
|
|
|
|
|
|
|
// Skip instruction if it's an unconditional branch following
|
|
|
|
|
// a conditional one.
|
|
|
|
|
if (BC.MIB->isUnconditionalBranch(*RI))
|
|
|
|
|
++RI;
|
|
|
|
|
|
|
|
|
|
if (!BC.MIB->isConditionalBranch(*RI))
|
|
|
|
|
return end();
|
|
|
|
|
|
|
|
|
|
// Start checking with instruction preceding the conditional branch.
|
|
|
|
|
++RI;
|
|
|
|
|
if (RI == rend())
|
|
|
|
|
return end();
|
|
|
|
|
|
|
|
|
|
auto II = std::prev(RI.base()); // convert to a forward iterator
|
|
|
|
|
if (isMacroOpFusionPair(II))
|
|
|
|
|
return II;
|
|
|
|
|
|
|
|
|
|
return end();
|
|
|
|
|
}
|
2016-05-02 12:47:18 -07:00
|
|
|
|
2017-05-01 16:52:54 -07:00
|
|
|
MCInst *BinaryBasicBlock::getTerminatorBefore(MCInst *Pos) {
|
|
|
|
|
auto &BC = Function->getBinaryContext();
|
|
|
|
|
auto Itr = rbegin();
|
|
|
|
|
bool Check = Pos ? false : true;
|
|
|
|
|
MCInst *FirstTerminator{nullptr};
|
|
|
|
|
while (Itr != rend()) {
|
|
|
|
|
if (!Check) {
|
|
|
|
|
if (&*Itr == Pos)
|
|
|
|
|
Check = true;
|
|
|
|
|
++Itr;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2018-03-09 09:45:13 -08:00
|
|
|
if (BC.MIB->isTerminator(*Itr))
|
2017-05-01 16:52:54 -07:00
|
|
|
FirstTerminator = &*Itr;
|
|
|
|
|
++Itr;
|
|
|
|
|
}
|
|
|
|
|
return FirstTerminator;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool BinaryBasicBlock::hasTerminatorAfter(MCInst *Pos) {
|
|
|
|
|
auto &BC = Function->getBinaryContext();
|
|
|
|
|
auto Itr = rbegin();
|
|
|
|
|
while (Itr != rend()) {
|
|
|
|
|
if (&*Itr == Pos)
|
|
|
|
|
return false;
|
2018-03-09 09:45:13 -08:00
|
|
|
if (BC.MIB->isTerminator(*Itr))
|
2017-05-01 16:52:54 -07:00
|
|
|
return true;
|
|
|
|
|
++Itr;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-29 21:11:22 -07:00
|
|
|
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) {
|
2016-09-02 18:09:07 -07:00
|
|
|
assert(isSuccessor(Successor));
|
2016-08-29 21:11:22 -07:00
|
|
|
auto &BC = Function->getBinaryContext();
|
|
|
|
|
MCInst NewInst;
|
2018-03-09 09:45:13 -08:00
|
|
|
BC.MIB->createUncondBranch(NewInst, Successor->getLabel(), BC.Ctx.get());
|
2016-08-29 21:11:22 -07:00
|
|
|
Instructions.emplace_back(std::move(NewInst));
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-02 18:09:07 -07:00
|
|
|
void BinaryBasicBlock::addTailCallInstruction(const MCSymbol *Target) {
|
|
|
|
|
auto &BC = Function->getBinaryContext();
|
|
|
|
|
MCInst NewInst;
|
2018-03-09 09:45:13 -08:00
|
|
|
BC.MIB->createTailCall(NewInst, Target, BC.Ctx.get());
|
2016-09-02 18:09:07 -07:00
|
|
|
Instructions.emplace_back(std::move(NewInst));
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-02 10:59:33 -07:00
|
|
|
uint32_t BinaryBasicBlock::getNumCalls() const {
|
|
|
|
|
uint32_t N{0};
|
|
|
|
|
auto &BC = Function->getBinaryContext();
|
|
|
|
|
for (auto &Instr : Instructions) {
|
2018-03-09 09:45:13 -08:00
|
|
|
if (BC.MIB->isCall(Instr))
|
2017-08-02 10:59:33 -07:00
|
|
|
++N;
|
|
|
|
|
}
|
|
|
|
|
return N;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-29 21:11:22 -07:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-22 18:08:20 -07:00
|
|
|
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) {
|
2016-12-21 17:13:56 -08:00
|
|
|
if (BI.Count != COUNT_NO_PROFILE) {
|
2016-09-22 18:08:20 -07:00
|
|
|
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()];
|
2016-12-21 17:13:56 -08:00
|
|
|
if (BI.Count && BI.Count != COUNT_NO_PROFILE) {
|
2016-09-22 18:08:20 -07:00
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-07 18:59:23 -07:00
|
|
|
void BinaryBasicBlock::dump() const {
|
|
|
|
|
auto &BC = Function->getBinaryContext();
|
2016-09-02 14:15:29 -07:00
|
|
|
if (Label) outs() << Label->getName() << ":\n";
|
2017-05-08 22:51:36 -07:00
|
|
|
BC.printInstructions(outs(), Instructions.begin(), Instructions.end(),
|
|
|
|
|
getOffset());
|
2016-09-02 14:15:29 -07:00
|
|
|
outs() << "preds:";
|
2016-07-23 08:01:53 -07:00
|
|
|
for (auto itr = pred_begin(); itr != pred_end(); ++itr) {
|
2016-09-02 14:15:29 -07:00
|
|
|
outs() << " " << (*itr)->getName();
|
2016-07-23 08:01:53 -07:00
|
|
|
}
|
2016-09-02 14:15:29 -07:00
|
|
|
outs() << "\nsuccs:";
|
2016-07-23 08:01:53 -07:00
|
|
|
for (auto itr = succ_begin(); itr != succ_end(); ++itr) {
|
2016-09-02 14:15:29 -07:00
|
|
|
outs() << " " << (*itr)->getName();
|
2016-07-23 08:01:53 -07:00
|
|
|
}
|
2016-09-02 14:15:29 -07:00
|
|
|
outs() << "\n";
|
2016-07-23 08:01:53 -07:00
|
|
|
}
|
|
|
|
|
|
2017-06-07 20:25:30 -07:00
|
|
|
uint64_t BinaryBasicBlock::estimateSize() const {
|
|
|
|
|
return Function->getBinaryContext().computeCodeSize(begin(), end());
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-28 09:57:21 -08:00
|
|
|
BinaryBasicBlock::BinaryBranchInfo &
|
|
|
|
|
BinaryBasicBlock::getBranchInfo(const BinaryBasicBlock &Succ) {
|
|
|
|
|
auto BI = branch_info_begin();
|
|
|
|
|
for (auto BB : successors()) {
|
|
|
|
|
if (&Succ == BB)
|
|
|
|
|
return *BI;
|
|
|
|
|
++BI;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
llvm_unreachable("Invalid successor");
|
|
|
|
|
return *BI;
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-30 13:21:50 -07:00
|
|
|
BinaryBasicBlock::BinaryBranchInfo &
|
|
|
|
|
BinaryBasicBlock::getBranchInfo(const MCSymbol *Label) {
|
|
|
|
|
auto BI = branch_info_begin();
|
|
|
|
|
for (auto BB : successors()) {
|
|
|
|
|
if (BB->getLabel() == Label)
|
|
|
|
|
return *BI;
|
|
|
|
|
++BI;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
llvm_unreachable("Invalid successor");
|
|
|
|
|
return *BI;
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-31 11:23:02 -08:00
|
|
|
BinaryBasicBlock *BinaryBasicBlock::splitAt(iterator II) {
|
|
|
|
|
assert(II != end() && "expected iterator pointing to instruction");
|
|
|
|
|
|
|
|
|
|
auto *NewBlock = getFunction()->addBasicBlock(0);
|
|
|
|
|
|
|
|
|
|
// Adjust successors/predecessors and propagate the execution count.
|
|
|
|
|
moveAllSuccessorsTo(NewBlock);
|
|
|
|
|
addSuccessor(NewBlock, getExecutionCount(), 0);
|
|
|
|
|
|
|
|
|
|
// Set correct CFI state for the new block.
|
|
|
|
|
NewBlock->setCFIState(getCFIStateAtInstr(&*II));
|
|
|
|
|
|
|
|
|
|
// Move instructions over.
|
|
|
|
|
adjustNumPseudos(II, end(), -1);
|
|
|
|
|
NewBlock->addInstructions(II, end());
|
|
|
|
|
Instructions.erase(II, end());
|
|
|
|
|
|
|
|
|
|
return NewBlock;
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-05 14:42:04 -08:00
|
|
|
} // namespace bolt
|
2015-10-09 17:21:14 -07:00
|
|
|
} // namespace llvm
|