1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-24 11:42:57 +01:00

[NFC] SwitchInst: Introduce wrapper for prof branch_weights handling

This patch introduces a wrapper class that re-implements
several mutator methods of SwitchInst to handle changes
of prof branch_weights metadata along with remove/add
switch case methods.
Subsequent patches will use this wrapper to implement
prof branch_weights metadata handling for SwitchInst.

Reviewers: davidx, eraman, reames, chandlerc
Reviewed By: davidx
Differential Revision: https://reviews.llvm.org/D62122

llvm-svn: 361596
This commit is contained in:
Yevgeny Rouban 2019-05-24 04:34:23 +00:00
parent c14d3f2f48
commit 23cfa4edf1
2 changed files with 166 additions and 0 deletions

View File

@ -3435,6 +3435,52 @@ public:
}
};
/// A wrapper class to simplify modification of SwitchInst cases along with
/// their prof branch_weights metadata.
class SwitchInstProfUpdateWrapper {
SwitchInst &SI;
Optional<SmallVector<uint32_t, 8> > Weights;
bool Changed = false;
protected:
static MDNode *getProfBranchWeightsMD(const SwitchInst &SI);
MDNode *buildProfBranchWeightsMD();
Optional<SmallVector<uint32_t, 8> > getProfBranchWeights();
public:
using CaseWeightOpt = Optional<uint32_t>;
SwitchInst *operator->() { return &SI; }
SwitchInst &operator*() { return SI; }
operator SwitchInst *() { return &SI; }
SwitchInstProfUpdateWrapper(SwitchInst &SI)
: SI(SI), Weights(getProfBranchWeights()) {}
~SwitchInstProfUpdateWrapper() {
if (Changed)
SI.setMetadata(LLVMContext::MD_prof, buildProfBranchWeightsMD());
}
/// Delegate the call to the underlying SwitchInst::removeCase() and remove
/// correspondent branch weight.
SwitchInst::CaseIt removeCase(SwitchInst::CaseIt I);
/// Delegate the call to the underlying SwitchInst::addCase() and set the
/// specified branch weight for the added case.
void addCase(ConstantInt *OnVal, BasicBlock *Dest, CaseWeightOpt W);
/// Delegate the call to the underlying SwitchInst::eraseFromParent() and mark
/// this object to not touch the underlying SwitchInst in destructor.
SymbolTableList<Instruction>::iterator eraseFromParent();
void setSuccessorWeight(unsigned idx, CaseWeightOpt W);
CaseWeightOpt getSuccessorWeight(unsigned idx);
static CaseWeightOpt getSuccessorWeight(const SwitchInst &SI, unsigned idx);
};
template <>
struct OperandTraits<SwitchInst> : public HungoffOperandTraits<2> {
};

View File

@ -3870,6 +3870,126 @@ void SwitchInst::growOperands() {
growHungoffUses(ReservedSpace);
}
MDNode *
SwitchInstProfUpdateWrapper::getProfBranchWeightsMD(const SwitchInst &SI) {
if (MDNode *ProfileData = SI.getMetadata(LLVMContext::MD_prof))
if (auto *MDName = dyn_cast<MDString>(ProfileData->getOperand(0)))
if (MDName->getString() == "branch_weights")
return ProfileData;
return nullptr;
}
MDNode *SwitchInstProfUpdateWrapper::buildProfBranchWeightsMD() {
assert(Changed && "called only if metadata has changed");
if (!Weights)
return nullptr;
assert(SI.getNumSuccessors() == Weights->size() &&
"num of prof branch_weights must accord with num of successors");
bool AllZeroes =
all_of(Weights.getValue(), [](uint32_t W) { return W == 0; });
if (AllZeroes || Weights.getValue().size() < 2)
return nullptr;
return MDBuilder(SI.getParent()->getContext()).createBranchWeights(*Weights);
}
Optional<SmallVector<uint32_t, 8> >
SwitchInstProfUpdateWrapper::getProfBranchWeights() {
MDNode *ProfileData = getProfBranchWeightsMD(SI);
if (!ProfileData)
return None;
SmallVector<uint32_t, 8> Weights;
for (unsigned CI = 1, CE = SI.getNumSuccessors(); CI <= CE; ++CI) {
ConstantInt *C = mdconst::extract<ConstantInt>(ProfileData->getOperand(CI));
uint32_t CW = C->getValue().getZExtValue();
Weights.push_back(CW);
}
return Weights;
}
SwitchInst::CaseIt
SwitchInstProfUpdateWrapper::removeCase(SwitchInst::CaseIt I) {
if (Weights) {
assert(SI.getNumSuccessors() == Weights->size() &&
"num of prof branch_weights must accord with num of successors");
Changed = true;
// Copy the last case to the place of the removed one and shrink.
// This is tightly coupled with the way SwitchInst::removeCase() removes
// the cases in SwitchInst::removeCase(CaseIt).
Weights.getValue()[I->getCaseIndex() + 1] = Weights.getValue().back();
Weights.getValue().pop_back();
}
return SI.removeCase(I);
}
void SwitchInstProfUpdateWrapper::addCase(
ConstantInt *OnVal, BasicBlock *Dest,
SwitchInstProfUpdateWrapper::CaseWeightOpt W) {
SI.addCase(OnVal, Dest);
if (!Weights && W && *W) {
Changed = true;
Weights = SmallVector<uint32_t, 8>(SI.getNumSuccessors(), 0);
Weights.getValue()[SI.getNumSuccessors() - 1] = *W;
} else if (Weights) {
Changed = true;
Weights.getValue().push_back(W ? *W : 0);
}
if (Weights)
assert(SI.getNumSuccessors() == Weights->size() &&
"num of prof branch_weights must accord with num of successors");
}
SymbolTableList<Instruction>::iterator
SwitchInstProfUpdateWrapper::eraseFromParent() {
// Instruction is erased. Mark as unchanged to not touch it in the destructor.
Changed = false;
if (Weights)
Weights->resize(0);
return SI.eraseFromParent();
}
SwitchInstProfUpdateWrapper::CaseWeightOpt
SwitchInstProfUpdateWrapper::getSuccessorWeight(unsigned idx) {
if (!Weights)
return None;
return Weights.getValue()[idx];
}
void SwitchInstProfUpdateWrapper::setSuccessorWeight(
unsigned idx, SwitchInstProfUpdateWrapper::CaseWeightOpt W) {
if (!W)
return;
if (!Weights && *W)
Weights = SmallVector<uint32_t, 8>(SI.getNumSuccessors(), 0);
if (Weights) {
auto &OldW = Weights.getValue()[idx];
if (*W != OldW) {
Changed = true;
OldW = *W;
}
}
}
SwitchInstProfUpdateWrapper::CaseWeightOpt
SwitchInstProfUpdateWrapper::getSuccessorWeight(const SwitchInst &SI,
unsigned idx) {
if (MDNode *ProfileData = getProfBranchWeightsMD(SI))
return mdconst::extract<ConstantInt>(ProfileData->getOperand(idx + 1))
->getValue()
.getZExtValue();
return None;
}
//===----------------------------------------------------------------------===//
// IndirectBrInst Implementation
//===----------------------------------------------------------------------===//