Reapply "[llvm][IR] Extend BranchWeightMetadata to track provenance o… (#95281)

…f weights" #95136

Reverts #95060, and relands #86609, with the unintended code generation
changes addressed.

This patch implements the changes to LLVM IR discussed in
https://discourse.llvm.org/t/rfc-update-branch-weights-metadata-to-allow-tracking-branch-weight-origins/75032

In this patch, we add an optional field to MD_prof meatdata nodes for
branch weights, which can be used to distinguish weights added from
llvm.expect* intrinsics from those added via other methods, e.g. from
profiles or inserted by the compiler.

One of the major motivations, is for use with MisExpect diagnostics,
which need to know if branch_weight metadata originates from an
llvm.expect intrinsic. Without that information, we end up checking
branch weights multiple times in the case if ThinLTO + SampleProfiling,
leading to some inaccuracy in how we report MisExpect related
diagnostics to users.

Since we change the format of MD_prof metadata in a fundamental way, we
need to update code handling branch weights in a number of places.

We also update the lang ref for branch weights to reflect the change.
This commit is contained in:
Paul Kirth 2024-06-12 12:52:28 -07:00 committed by GitHub
parent 7b8038426c
commit 294f3ce5dd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
31 changed files with 179 additions and 92 deletions

View File

@ -221,5 +221,5 @@ void tu2(int &i) {
}
}
// CHECK: [[BW_LIKELY]] = !{!"branch_weights", i32 2000, i32 1}
// CHECK: [[BW_UNLIKELY]] = !{!"branch_weights", i32 1, i32 2000}
// CHECK: [[BW_LIKELY]] = !{!"branch_weights", !"expected", i32 2000, i32 1}
// CHECK: [[BW_UNLIKELY]] = !{!"branch_weights", !"expected", i32 1, i32 2000}

View File

@ -28,11 +28,14 @@ Supported Instructions
Metadata is only assigned to the conditional branches. There are two extra
operands for the true and the false branch.
We optionally track if the metadata was added by ``__builtin_expect`` or
``__builtin_expect_with_probability`` with an optional field ``!"expected"``.
.. code-block:: none
!0 = !{
!"branch_weights",
[ !"expected", ]
i32 <TRUE_BRANCH_WEIGHT>,
i32 <FALSE_BRANCH_WEIGHT>
}
@ -47,6 +50,7 @@ is always case #0).
!0 = !{
!"branch_weights",
[ !"expected", ]
i32 <DEFAULT_BRANCH_WEIGHT>
[ , i32 <CASE_BRANCH_WEIGHT> ... ]
}
@ -60,6 +64,7 @@ Branch weights are assigned to every destination.
!0 = !{
!"branch_weights",
[ !"expected", ]
i32 <LABEL_BRANCH_WEIGHT>
[ , i32 <LABEL_BRANCH_WEIGHT> ... ]
}
@ -75,6 +80,7 @@ block and entry counts which may not be accurate with sampling.
!0 = !{
!"branch_weights",
[ !"expected", ]
i32 <CALL_BRANCH_WEIGHT>
}
@ -95,6 +101,7 @@ is used.
!0 = !{
!"branch_weights",
[ !"expected", ]
i32 <INVOKE_NORMAL_WEIGHT>
[ , i32 <INVOKE_UNWIND_WEIGHT> ]
}

View File

@ -59,7 +59,11 @@ public:
//===------------------------------------------------------------------===//
/// Return metadata containing two branch weights.
MDNode *createBranchWeights(uint32_t TrueWeight, uint32_t FalseWeight);
/// @param TrueWeight the weight of the true branch
/// @param FalseWeight the weight of the false branch
/// @param Do these weights come from __builtin_expect*
MDNode *createBranchWeights(uint32_t TrueWeight, uint32_t FalseWeight,
bool IsExpected = false);
/// Return metadata containing two branch weights, with significant bias
/// towards `true` destination.
@ -70,7 +74,10 @@ public:
MDNode *createUnlikelyBranchWeights();
/// Return metadata containing a number of branch weights.
MDNode *createBranchWeights(ArrayRef<uint32_t> Weights);
/// @param Weights the weights of all the branches
/// @param Do these weights come from __builtin_expect*
MDNode *createBranchWeights(ArrayRef<uint32_t> Weights,
bool IsExpected = false);
/// Return metadata specifying that a branch or switch is unpredictable.
MDNode *createUnpredictable();

View File

@ -55,6 +55,17 @@ MDNode *getBranchWeightMDNode(const Instruction &I);
/// Nullptr otherwise.
MDNode *getValidBranchWeightMDNode(const Instruction &I);
/// Check if Branch Weight Metadata has an "expected" field from an llvm.expect*
/// intrinsic
bool hasBranchWeightOrigin(const Instruction &I);
/// Check if Branch Weight Metadata has an "expected" field from an llvm.expect*
/// intrinsic
bool hasBranchWeightOrigin(const MDNode *ProfileData);
/// Return the offset to the first branch weight data
unsigned getBranchWeightOffset(const MDNode *ProfileData);
/// Extract branch weights from MD_prof metadata
///
/// \param ProfileData A pointer to an MDNode.
@ -111,7 +122,11 @@ bool extractProfTotalWeight(const Instruction &I, uint64_t &TotalWeights);
/// Create a new `branch_weights` metadata node and add or overwrite
/// a `prof` metadata reference to instruction `I`.
void setBranchWeights(Instruction &I, ArrayRef<uint32_t> Weights);
/// \param I the Instruction to set branch weights on.
/// \param Weights an array of weights to set on instruction I.
/// \param IsExpected were these weights added from an llvm.expect* intrinsic.
void setBranchWeights(Instruction &I, ArrayRef<uint32_t> Weights,
bool IsExpected);
/// Scaling the profile data attached to 'I' using the ratio of S/T.
void scaleProfData(Instruction &I, uint64_t S, uint64_t T);

View File

@ -57,6 +57,7 @@
#include "llvm/IR/Module.h"
#include "llvm/IR/ModuleSummaryIndex.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/ProfDataUtils.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Value.h"
#include "llvm/IR/Verifier.h"
@ -6951,8 +6952,10 @@ Error BitcodeReader::materialize(GlobalValue *GV) {
else
continue; // ignore and continue.
unsigned Offset = getBranchWeightOffset(MD);
// If branch weight doesn't match, just strip branch weight.
if (MD->getNumOperands() != 1 + ExpectedNumOperands)
if (MD->getNumOperands() != Offset + ExpectedNumOperands)
I.setMetadata(LLVMContext::MD_prof, nullptr);
}
}

View File

@ -8866,7 +8866,8 @@ bool CodeGenPrepare::splitBranchCondition(Function &F, ModifyDT &ModifiedDT) {
scaleWeights(NewTrueWeight, NewFalseWeight);
Br1->setMetadata(LLVMContext::MD_prof,
MDBuilder(Br1->getContext())
.createBranchWeights(TrueWeight, FalseWeight));
.createBranchWeights(TrueWeight, FalseWeight,
hasBranchWeightOrigin(*Br1)));
NewTrueWeight = TrueWeight;
NewFalseWeight = 2 * FalseWeight;

View File

@ -1268,12 +1268,23 @@ Instruction *Instruction::cloneImpl() const {
void Instruction::swapProfMetadata() {
MDNode *ProfileData = getBranchWeightMDNode(*this);
if (!ProfileData || ProfileData->getNumOperands() != 3)
if (!ProfileData)
return;
unsigned FirstIdx = getBranchWeightOffset(ProfileData);
if (ProfileData->getNumOperands() != 2 + FirstIdx)
return;
// The first operand is the name. Fetch them backwards and build a new one.
Metadata *Ops[] = {ProfileData->getOperand(0), ProfileData->getOperand(2),
ProfileData->getOperand(1)};
unsigned SecondIdx = FirstIdx + 1;
SmallVector<Metadata *, 4> Ops;
// If there are more weights past the second, we can't swap them
if (ProfileData->getNumOperands() > SecondIdx + 1)
return;
for (unsigned Idx = 0; Idx < FirstIdx; ++Idx) {
Ops.push_back(ProfileData->getOperand(Idx));
}
// Switch the order of the weights
Ops.push_back(ProfileData->getOperand(SecondIdx));
Ops.push_back(ProfileData->getOperand(FirstIdx));
setMetadata(LLVMContext::MD_prof,
MDNode::get(ProfileData->getContext(), Ops));
}

View File

@ -5199,7 +5199,11 @@ void SwitchInstProfUpdateWrapper::init() {
if (!ProfileData)
return;
if (ProfileData->getNumOperands() != SI.getNumSuccessors() + 1) {
// FIXME: This check belongs in ProfDataUtils. Its almost equivalent to
// getValidBranchWeightMDNode(), but the need to use llvm_unreachable
// makes them slightly different.
if (ProfileData->getNumOperands() !=
SI.getNumSuccessors() + getBranchWeightOffset(ProfileData)) {
llvm_unreachable("number of prof branch_weights metadata operands does "
"not correspond to number of succesors");
}

View File

@ -35,8 +35,8 @@ MDNode *MDBuilder::createFPMath(float Accuracy) {
}
MDNode *MDBuilder::createBranchWeights(uint32_t TrueWeight,
uint32_t FalseWeight) {
return createBranchWeights({TrueWeight, FalseWeight});
uint32_t FalseWeight, bool IsExpected) {
return createBranchWeights({TrueWeight, FalseWeight}, IsExpected);
}
MDNode *MDBuilder::createLikelyBranchWeights() {
@ -49,15 +49,19 @@ MDNode *MDBuilder::createUnlikelyBranchWeights() {
return createBranchWeights(1, (1U << 20) - 1);
}
MDNode *MDBuilder::createBranchWeights(ArrayRef<uint32_t> Weights) {
MDNode *MDBuilder::createBranchWeights(ArrayRef<uint32_t> Weights,
bool IsExpected) {
assert(Weights.size() >= 1 && "Need at least one branch weights!");
SmallVector<Metadata *, 4> Vals(Weights.size() + 1);
unsigned int Offset = IsExpected ? 2 : 1;
SmallVector<Metadata *, 4> Vals(Weights.size() + Offset);
Vals[0] = createString("branch_weights");
if (IsExpected)
Vals[1] = createString("expected");
Type *Int32Ty = Type::getInt32Ty(Context);
for (unsigned i = 0, e = Weights.size(); i != e; ++i)
Vals[i + 1] = createConstant(ConstantInt::get(Int32Ty, Weights[i]));
Vals[i + Offset] = createConstant(ConstantInt::get(Int32Ty, Weights[i]));
return MDNode::get(Context, Vals);
}

View File

@ -1196,10 +1196,10 @@ MDNode *MDNode::mergeDirectCallProfMetadata(MDNode *A, MDNode *B,
StringRef AProfName = AMDS->getString();
StringRef BProfName = BMDS->getString();
if (AProfName == "branch_weights" && BProfName == "branch_weights") {
ConstantInt *AInstrWeight =
mdconst::dyn_extract<ConstantInt>(A->getOperand(1));
ConstantInt *BInstrWeight =
mdconst::dyn_extract<ConstantInt>(B->getOperand(1));
ConstantInt *AInstrWeight = mdconst::dyn_extract<ConstantInt>(
A->getOperand(getBranchWeightOffset(A)));
ConstantInt *BInstrWeight = mdconst::dyn_extract<ConstantInt>(
B->getOperand(getBranchWeightOffset(B)));
assert(AInstrWeight && BInstrWeight && "verified by LLVM verifier");
return MDNode::get(Ctx,
{MDHelper.createString("branch_weights"),

View File

@ -19,6 +19,7 @@
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/ProfDataUtils.h"
#include "llvm/Support/BranchProbability.h"
#include "llvm/Support/CommandLine.h"
@ -40,9 +41,6 @@ namespace {
// We maintain some constants here to ensure that we access the branch weights
// correctly, and can change the behavior in the future if the layout changes
// The index at which the weights vector starts
constexpr unsigned WeightsIdx = 1;
// the minimum number of operands for MD_prof nodes with branch weights
constexpr unsigned MinBWOps = 3;
@ -75,6 +73,7 @@ static void extractFromBranchWeightMD(const MDNode *ProfileData,
assert(isBranchWeightMD(ProfileData) && "wrong metadata");
unsigned NOps = ProfileData->getNumOperands();
unsigned WeightsIdx = getBranchWeightOffset(ProfileData);
assert(WeightsIdx < NOps && "Weights Index must be less than NOps.");
Weights.resize(NOps - WeightsIdx);
@ -82,8 +81,8 @@ static void extractFromBranchWeightMD(const MDNode *ProfileData,
ConstantInt *Weight =
mdconst::dyn_extract<ConstantInt>(ProfileData->getOperand(Idx));
assert(Weight && "Malformed branch_weight in MD_prof node");
assert(Weight->getValue().getActiveBits() <= 32 &&
"Too many bits for uint32_t");
assert(Weight->getValue().getActiveBits() <= (sizeof(T) * 8) &&
"Too many bits for MD_prof branch_weight");
Weights[Idx - WeightsIdx] = Weight->getZExtValue();
}
}
@ -123,6 +122,26 @@ bool hasValidBranchWeightMD(const Instruction &I) {
return getValidBranchWeightMDNode(I);
}
bool hasBranchWeightOrigin(const Instruction &I) {
auto *ProfileData = I.getMetadata(LLVMContext::MD_prof);
return hasBranchWeightOrigin(ProfileData);
}
bool hasBranchWeightOrigin(const MDNode *ProfileData) {
if (!isBranchWeightMD(ProfileData))
return false;
auto *ProfDataName = dyn_cast<MDString>(ProfileData->getOperand(1));
// NOTE: if we ever have more types of branch weight provenance,
// we need to check the string value is "expected". For now, we
// supply a more generic API, and avoid the spurious comparisons.
assert(ProfDataName == nullptr || ProfDataName->getString() == "expected");
return ProfDataName != nullptr;
}
unsigned getBranchWeightOffset(const MDNode *ProfileData) {
return hasBranchWeightOrigin(ProfileData) ? 2 : 1;
}
MDNode *getBranchWeightMDNode(const Instruction &I) {
auto *ProfileData = I.getMetadata(LLVMContext::MD_prof);
if (!isBranchWeightMD(ProfileData))
@ -132,7 +151,9 @@ MDNode *getBranchWeightMDNode(const Instruction &I) {
MDNode *getValidBranchWeightMDNode(const Instruction &I) {
auto *ProfileData = getBranchWeightMDNode(I);
if (ProfileData && ProfileData->getNumOperands() == 1 + I.getNumSuccessors())
auto Offset = getBranchWeightOffset(ProfileData);
if (ProfileData &&
ProfileData->getNumOperands() == Offset + I.getNumSuccessors())
return ProfileData;
return nullptr;
}
@ -191,7 +212,8 @@ bool extractProfTotalWeight(const MDNode *ProfileData, uint64_t &TotalVal) {
return false;
if (ProfDataName->getString() == "branch_weights") {
for (unsigned Idx = 1; Idx < ProfileData->getNumOperands(); Idx++) {
unsigned Offset = getBranchWeightOffset(ProfileData);
for (unsigned Idx = Offset; Idx < ProfileData->getNumOperands(); ++Idx) {
auto *V = mdconst::dyn_extract<ConstantInt>(ProfileData->getOperand(Idx));
assert(V && "Malformed branch_weight in MD_prof node");
TotalVal += V->getValue().getZExtValue();
@ -212,9 +234,10 @@ bool extractProfTotalWeight(const Instruction &I, uint64_t &TotalVal) {
return extractProfTotalWeight(I.getMetadata(LLVMContext::MD_prof), TotalVal);
}
void setBranchWeights(Instruction &I, ArrayRef<uint32_t> Weights) {
void setBranchWeights(Instruction &I, ArrayRef<uint32_t> Weights,
bool IsExpected) {
MDBuilder MDB(I.getContext());
MDNode *BranchWeights = MDB.createBranchWeights(Weights);
MDNode *BranchWeights = MDB.createBranchWeights(Weights, IsExpected);
I.setMetadata(LLVMContext::MD_prof, BranchWeights);
}
@ -241,9 +264,11 @@ void scaleProfData(Instruction &I, uint64_t S, uint64_t T) {
if (ProfDataName->getString() == "branch_weights" &&
ProfileData->getNumOperands() > 0) {
// Using APInt::div may be expensive, but most cases should fit 64 bits.
APInt Val(128, mdconst::dyn_extract<ConstantInt>(ProfileData->getOperand(1))
->getValue()
.getZExtValue());
APInt Val(128,
mdconst::dyn_extract<ConstantInt>(
ProfileData->getOperand(getBranchWeightOffset(ProfileData)))
->getValue()
.getZExtValue());
Val *= APS;
Vals.push_back(MDB.createConstant(ConstantInt::get(
Type::getInt32Ty(C), Val.udiv(APT).getLimitedValue(UINT32_MAX))));

View File

@ -104,6 +104,7 @@
#include "llvm/IR/Module.h"
#include "llvm/IR/ModuleSlotTracker.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/ProfDataUtils.h"
#include "llvm/IR/Statepoint.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Use.h"
@ -4808,8 +4809,10 @@ void Verifier::visitProfMetadata(Instruction &I, MDNode *MD) {
// Check consistency of !prof branch_weights metadata.
if (ProfName == "branch_weights") {
unsigned int Offset = getBranchWeightOffset(MD);
if (isa<InvokeInst>(&I)) {
Check(MD->getNumOperands() == 2 || MD->getNumOperands() == 3,
Check(MD->getNumOperands() == (1 + Offset) ||
MD->getNumOperands() == (2 + Offset),
"Wrong number of InvokeInst branch_weights operands", MD);
} else {
unsigned ExpectedNumOperands = 0;
@ -4829,10 +4832,10 @@ void Verifier::visitProfMetadata(Instruction &I, MDNode *MD) {
CheckFailed("!prof branch_weights are not allowed for this instruction",
MD);
Check(MD->getNumOperands() == 1 + ExpectedNumOperands,
Check(MD->getNumOperands() == Offset + ExpectedNumOperands,
"Wrong number of operands", MD);
}
for (unsigned i = 1; i < MD->getNumOperands(); ++i) {
for (unsigned i = Offset; i < MD->getNumOperands(); ++i) {
auto &MDO = MD->getOperand(i);
Check(MDO, "second operand should not be null", MD);
Check(mdconst::dyn_extract<ConstantInt>(MDO),

View File

@ -1662,7 +1662,8 @@ void SampleProfileLoader::generateMDProfMetadata(Function &F) {
else if (OverwriteExistingWeights)
I.setMetadata(LLVMContext::MD_prof, nullptr);
} else if (!isa<IntrinsicInst>(&I)) {
setBranchWeights(I, {static_cast<uint32_t>(BlockWeights[BB])});
setBranchWeights(I, {static_cast<uint32_t>(BlockWeights[BB])},
/*IsExpected=*/false);
}
}
} else if (OverwriteExistingWeights || ProfileSampleBlockAccurate) {
@ -1673,7 +1674,7 @@ void SampleProfileLoader::generateMDProfMetadata(Function &F) {
if (cast<CallBase>(I).isIndirectCall()) {
I.setMetadata(LLVMContext::MD_prof, nullptr);
} else {
setBranchWeights(I, {uint32_t(0)});
setBranchWeights(I, {uint32_t(0)}, /*IsExpected=*/false);
}
}
}
@ -1756,7 +1757,7 @@ void SampleProfileLoader::generateMDProfMetadata(Function &F) {
if (MaxWeight > 0 &&
(!TI->extractProfTotalWeight(TempWeight) || OverwriteExistingWeights)) {
LLVM_DEBUG(dbgs() << "SUCCESS. Found non-zero weights.\n");
setBranchWeights(*TI, Weights);
setBranchWeights(*TI, Weights, /*IsExpected=*/false);
ORE->emit([&]() {
return OptimizationRemark(DEBUG_TYPE, "PopularDest", MaxDestInst)
<< "most popular destination for conditional branches at "

View File

@ -1878,7 +1878,7 @@ void CHR::fixupBranchesAndSelects(CHRScope *Scope,
static_cast<uint32_t>(CHRBranchBias.scale(1000)),
static_cast<uint32_t>(CHRBranchBias.getCompl().scale(1000)),
};
setBranchWeights(*MergedBR, Weights);
setBranchWeights(*MergedBR, Weights, /*IsExpected=*/false);
CHR_DEBUG(dbgs() << "CHR branch bias " << Weights[0] << ":" << Weights[1]
<< "\n");
}

View File

@ -259,7 +259,8 @@ CallBase &llvm::pgo::promoteIndirectCall(CallBase &CB, Function *DirectCallee,
promoteCallWithIfThenElse(CB, DirectCallee, BranchWeights);
if (AttachProfToDirectCall) {
setBranchWeights(NewInst, {static_cast<uint32_t>(Count)});
setBranchWeights(NewInst, {static_cast<uint32_t>(Count)},
/*IsExpected=*/false);
}
using namespace ore;

View File

@ -1474,7 +1474,8 @@ void PGOUseFunc::populateCoverage(IndexedInstrProfReader *PGOReader) {
for (auto *Succ : successors(&BB))
Weights.push_back((Coverage[Succ] || !Coverage[&BB]) ? 1 : 0);
if (Weights.size() >= 2)
llvm::setBranchWeights(*BB.getTerminator(), Weights);
llvm::setBranchWeights(*BB.getTerminator(), Weights,
/*IsExpected=*/false);
}
unsigned NumCorruptCoverage = 0;
@ -2260,7 +2261,7 @@ void llvm::setProfMetadata(Module *M, Instruction *TI,
misexpect::checkExpectAnnotations(*TI, Weights, /*IsFrontend=*/false);
setBranchWeights(*TI, Weights);
setBranchWeights(*TI, Weights, /*IsExpected=*/false);
if (EmitBranchProbability) {
std::string BrCondStr = getBranchCondString(TI);
if (BrCondStr.empty())

View File

@ -231,7 +231,7 @@ static void updatePredecessorProfileMetadata(PHINode *PN, BasicBlock *BB) {
Weights[0] = BP.getCompl().getNumerator();
Weights[1] = BP.getNumerator();
}
setBranchWeights(*PredBr, Weights);
setBranchWeights(*PredBr, Weights, hasBranchWeightOrigin(*PredBr));
}
}
@ -2618,7 +2618,7 @@ void JumpThreadingPass::updateBlockFreqAndEdgeWeight(BasicBlock *PredBB,
Weights.push_back(Prob.getNumerator());
auto TI = BB->getTerminator();
setBranchWeights(*TI, Weights);
setBranchWeights(*TI, Weights, hasBranchWeightOrigin(*TI));
}
}

View File

@ -102,7 +102,7 @@ static bool handleSwitchExpect(SwitchInst &SI) {
misexpect::checkExpectAnnotations(SI, Weights, /*IsFrontend=*/true);
SI.setCondition(ArgValue);
setBranchWeights(SI, Weights);
setBranchWeights(SI, Weights, /*IsExpected=*/true);
return true;
}
@ -262,11 +262,13 @@ static void handlePhiDef(CallInst *Expect) {
if (IsOpndComingFromSuccessor(BI->getSuccessor(1)))
BI->setMetadata(LLVMContext::MD_prof,
MDB.createBranchWeights(LikelyBranchWeightVal,
UnlikelyBranchWeightVal));
UnlikelyBranchWeightVal,
/*IsExpected=*/true));
else if (IsOpndComingFromSuccessor(BI->getSuccessor(0)))
BI->setMetadata(LLVMContext::MD_prof,
MDB.createBranchWeights(UnlikelyBranchWeightVal,
LikelyBranchWeightVal));
LikelyBranchWeightVal,
/*IsExpected=*/true));
}
}
@ -331,12 +333,12 @@ template <class BrSelInst> static bool handleBrSelExpect(BrSelInst &BSI) {
SmallVector<uint32_t, 4> ExpectedWeights;
if ((ExpectedValue->getZExtValue() == ValueComparedTo) ==
(Predicate == CmpInst::ICMP_EQ)) {
Node =
MDB.createBranchWeights(LikelyBranchWeightVal, UnlikelyBranchWeightVal);
Node = MDB.createBranchWeights(
LikelyBranchWeightVal, UnlikelyBranchWeightVal, /*IsExpected=*/true);
ExpectedWeights = {LikelyBranchWeightVal, UnlikelyBranchWeightVal};
} else {
Node =
MDB.createBranchWeights(UnlikelyBranchWeightVal, LikelyBranchWeightVal);
Node = MDB.createBranchWeights(UnlikelyBranchWeightVal,
LikelyBranchWeightVal, /*IsExpected=*/true);
ExpectedWeights = {UnlikelyBranchWeightVal, LikelyBranchWeightVal};
}

View File

@ -231,7 +231,7 @@ bool llvm::ConstantFoldTerminator(BasicBlock *BB, bool DeleteDeadConditions,
// Remove weight for this case.
std::swap(Weights[Idx + 1], Weights.back());
Weights.pop_back();
setBranchWeights(*SI, Weights);
setBranchWeights(*SI, Weights, hasBranchWeightOrigin(MD));
}
// Remove this entry.
BasicBlock *ParentBB = SI->getParent();

View File

@ -680,7 +680,7 @@ struct WeightInfo {
/// To avoid dealing with division rounding we can just multiple both part
/// of weights to E and use weight as (F - I * E, E).
static void updateBranchWeights(Instruction *Term, WeightInfo &Info) {
setBranchWeights(*Term, Info.Weights);
setBranchWeights(*Term, Info.Weights, /*IsExpected=*/false);
for (auto [Idx, SubWeight] : enumerate(Info.SubWeights))
if (SubWeight != 0)
// Don't set the probability of taking the edge from latch to loop header
@ -1073,7 +1073,7 @@ bool llvm::peelLoop(Loop *L, unsigned PeelCount, LoopInfo *LI,
}
for (const auto &[Term, Info] : Weights) {
setBranchWeights(*Term, Info.Weights);
setBranchWeights(*Term, Info.Weights, /*IsExpected=*/false);
}
// Update Metadata for count of peeled off iterations.

View File

@ -390,13 +390,13 @@ static void updateBranchWeights(BranchInst &PreHeaderBI, BranchInst &LoopBI,
SuccsSwapped ? LoopBackWeight : ExitWeight1,
SuccsSwapped ? ExitWeight1 : LoopBackWeight,
};
setBranchWeights(LoopBI, LoopBIWeights);
setBranchWeights(LoopBI, LoopBIWeights, /*IsExpected=*/false);
if (HasConditionalPreHeader) {
const uint32_t PreHeaderBIWeights[] = {
SuccsSwapped ? EnterWeight : ExitWeight0,
SuccsSwapped ? ExitWeight0 : EnterWeight,
};
setBranchWeights(PreHeaderBI, PreHeaderBIWeights);
setBranchWeights(PreHeaderBI, PreHeaderBIWeights, /*IsExpected=*/false);
}
}

View File

@ -861,26 +861,28 @@ static bool ValuesOverlap(std::vector<ValueEqualityComparisonCase> &C1,
// Set branch weights on SwitchInst. This sets the metadata if there is at
// least one non-zero weight.
static void setBranchWeights(SwitchInst *SI, ArrayRef<uint32_t> Weights) {
static void setBranchWeights(SwitchInst *SI, ArrayRef<uint32_t> Weights,
bool IsExpected) {
// Check that there is at least one non-zero weight. Otherwise, pass
// nullptr to setMetadata which will erase the existing metadata.
MDNode *N = nullptr;
if (llvm::any_of(Weights, [](uint32_t W) { return W != 0; }))
N = MDBuilder(SI->getParent()->getContext()).createBranchWeights(Weights);
N = MDBuilder(SI->getParent()->getContext())
.createBranchWeights(Weights, IsExpected);
SI->setMetadata(LLVMContext::MD_prof, N);
}
// Similar to the above, but for branch and select instructions that take
// exactly 2 weights.
static void setBranchWeights(Instruction *I, uint32_t TrueWeight,
uint32_t FalseWeight) {
uint32_t FalseWeight, bool IsExpected) {
assert(isa<BranchInst>(I) || isa<SelectInst>(I));
// Check that there is at least one non-zero weight. Otherwise, pass
// nullptr to setMetadata which will erase the existing metadata.
MDNode *N = nullptr;
if (TrueWeight || FalseWeight)
N = MDBuilder(I->getParent()->getContext())
.createBranchWeights(TrueWeight, FalseWeight);
.createBranchWeights(TrueWeight, FalseWeight, IsExpected);
I->setMetadata(LLVMContext::MD_prof, N);
}
@ -1338,7 +1340,7 @@ bool SimplifyCFGOpt::PerformValueComparisonIntoPredecessorFolding(
SmallVector<uint32_t, 8> MDWeights(Weights.begin(), Weights.end());
setBranchWeights(NewSI, MDWeights);
setBranchWeights(NewSI, MDWeights, /*IsExpected=*/false);
}
EraseTerminatorAndDCECond(PTI);
@ -3831,7 +3833,7 @@ static bool performBranchToCommonDestFolding(BranchInst *BI, BranchInst *PBI,
FitWeights(NewWeights);
SmallVector<uint32_t, 8> MDWeights(NewWeights.begin(), NewWeights.end());
setBranchWeights(PBI, MDWeights[0], MDWeights[1]);
setBranchWeights(PBI, MDWeights[0], MDWeights[1], /*IsExpected=*/false);
// TODO: If BB is reachable from all paths through PredBlock, then we
// could replace PBI's branch probabilities with BI's.
@ -4568,7 +4570,7 @@ static bool SimplifyCondBranchToCondBranch(BranchInst *PBI, BranchInst *BI,
// Halve the weights if any of them cannot fit in an uint32_t
FitWeights(NewWeights);
setBranchWeights(PBI, NewWeights[0], NewWeights[1]);
setBranchWeights(PBI, NewWeights[0], NewWeights[1], /*IsExpected=*/false);
}
// OtherDest may have phi nodes. If so, add an entry from PBI's
@ -4604,7 +4606,8 @@ static bool SimplifyCondBranchToCondBranch(BranchInst *PBI, BranchInst *BI,
FitWeights(NewWeights);
setBranchWeights(NV, NewWeights[0], NewWeights[1]);
setBranchWeights(NV, NewWeights[0], NewWeights[1],
/*IsExpected=*/false);
}
}
}
@ -4667,7 +4670,7 @@ bool SimplifyCFGOpt::SimplifyTerminatorOnSelect(Instruction *OldTerm,
// Create a conditional branch sharing the condition of the select.
BranchInst *NewBI = Builder.CreateCondBr(Cond, TrueBB, FalseBB);
if (TrueWeight != FalseWeight)
setBranchWeights(NewBI, TrueWeight, FalseWeight);
setBranchWeights(NewBI, TrueWeight, FalseWeight, /*IsExpected=*/false);
}
} else if (KeepEdge1 && (KeepEdge2 || TrueBB == FalseBB)) {
// Neither of the selected blocks were successors, so this
@ -5617,7 +5620,7 @@ bool SimplifyCFGOpt::TurnSwitchRangeIntoICmp(SwitchInst *SI,
TrueWeight /= 2;
FalseWeight /= 2;
}
setBranchWeights(NewBI, TrueWeight, FalseWeight);
setBranchWeights(NewBI, TrueWeight, FalseWeight, /*IsExpected=*/false);
}
}

View File

@ -2145,7 +2145,7 @@ public:
BranchInst &BI = *BranchInst::Create(Bypass, LoopVectorPreHeader, Cond);
if (AddBranchWeights)
setBranchWeights(BI, SCEVCheckBypassWeights);
setBranchWeights(BI, SCEVCheckBypassWeights, /*IsExpected=*/false);
ReplaceInstWithInst(SCEVCheckBlock->getTerminator(), &BI);
return SCEVCheckBlock;
}
@ -2173,7 +2173,7 @@ public:
BranchInst &BI =
*BranchInst::Create(Bypass, LoopVectorPreHeader, MemRuntimeCheckCond);
if (AddBranchWeights) {
setBranchWeights(BI, MemCheckBypassWeights);
setBranchWeights(BI, MemCheckBypassWeights, /*IsExpected=*/false);
}
ReplaceInstWithInst(MemCheckBlock->getTerminator(), &BI);
MemCheckBlock->getTerminator()->setDebugLoc(
@ -2888,7 +2888,7 @@ void InnerLoopVectorizer::emitIterationCountCheck(BasicBlock *Bypass) {
BranchInst &BI =
*BranchInst::Create(Bypass, LoopVectorPreHeader, CheckMinIters);
if (hasBranchWeightMD(*OrigLoop->getLoopLatch()->getTerminator()))
setBranchWeights(BI, MinItersBypassWeights);
setBranchWeights(BI, MinItersBypassWeights, /*IsExpected=*/false);
ReplaceInstWithInst(TCCheckBlock->getTerminator(), &BI);
LoopBypassBlocks.push_back(TCCheckBlock);
}
@ -3127,7 +3127,7 @@ BasicBlock *InnerLoopVectorizer::completeLoopSkeleton() {
unsigned TripCount = UF * VF.getKnownMinValue();
assert(TripCount > 0 && "trip count should not be zero");
const uint32_t Weights[] = {1, TripCount - 1};
setBranchWeights(BI, Weights);
setBranchWeights(BI, Weights, /*IsExpected=*/false);
}
}
@ -7668,7 +7668,7 @@ EpilogueVectorizerMainLoop::emitIterationCountCheck(BasicBlock *Bypass,
BranchInst &BI =
*BranchInst::Create(Bypass, LoopVectorPreHeader, CheckMinIters);
if (hasBranchWeightMD(*OrigLoop->getLoopLatch()->getTerminator()))
setBranchWeights(BI, MinItersBypassWeights);
setBranchWeights(BI, MinItersBypassWeights, /*IsExpected=*/false);
ReplaceInstWithInst(TCCheckBlock->getTerminator(), &BI);
return TCCheckBlock;
@ -7825,7 +7825,7 @@ EpilogueVectorizerEpilogueLoop::emitMinimumVectorEpilogueIterCountCheck(
unsigned EstimatedSkipCount = std::min(MainLoopStep, EpilogueLoopStep);
const uint32_t Weights[] = {EstimatedSkipCount,
MainLoopStep - EstimatedSkipCount};
setBranchWeights(BI, Weights);
setBranchWeights(BI, Weights, /*IsExpected=*/false);
}
ReplaceInstWithInst(Insert->getTerminator(), &BI);

View File

@ -284,7 +284,7 @@ define i32 @test10(i64 %t6) {
declare i1 @llvm.expect.i1(i1, i1) nounwind readnone
; CHECK: !0 = !{!"branch_weights", i32 2000, i32 1}
; CHECK: !1 = !{!"branch_weights", i32 1, i32 2000}
; CHECK: !2 = !{!"branch_weights", i32 1, i32 1, i32 2000}
; CHECK: !3 = !{!"branch_weights", i32 2000, i32 1, i32 1}
; CHECK: !0 = !{!"branch_weights", !"expected", i32 2000, i32 1}
; CHECK: !1 = !{!"branch_weights", !"expected", i32 1, i32 2000}
; CHECK: !2 = !{!"branch_weights", !"expected", i32 1, i32 1, i32 2000}
; CHECK: !3 = !{!"branch_weights", !"expected", i32 2000, i32 1, i32 1}

View File

@ -284,7 +284,7 @@ define i32 @test10(i64 %t6) {
declare i1 @llvm.expect.with.probability.i1(i1, i1, double) nounwind readnone
; CHECK: !0 = !{!"branch_weights", i32 1717986918, i32 429496731}
; CHECK: !1 = !{!"branch_weights", i32 429496731, i32 1717986918}
; CHECK: !2 = !{!"branch_weights", i32 214748366, i32 214748366, i32 1717986918}
; CHECK: !3 = !{!"branch_weights", i32 1717986918, i32 214748366, i32 214748366}
; CHECK: !0 = !{!"branch_weights", !"expected", i32 1717986918, i32 429496731}
; CHECK: !1 = !{!"branch_weights", !"expected", i32 429496731, i32 1717986918}
; CHECK: !2 = !{!"branch_weights", !"expected", i32 214748366, i32 214748366, i32 1717986918}
; CHECK: !3 = !{!"branch_weights", !"expected", i32 1717986918, i32 214748366, i32 214748366}

View File

@ -99,6 +99,5 @@ attributes #1 = { nounwind readnone }
!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{!"clang version 5.0.0 (trunk 304373)"}
; CHECK: [[LIKELY]] = !{!"branch_weights", i32 2000, i32 1}
; CHECK: [[UNLIKELY]] = !{!"branch_weights", i32 1, i32 2000}
; CHECK: [[LIKELY]] = !{!"branch_weights", !"expected", i32 2000, i32 1}
; CHECK: [[UNLIKELY]] = !{!"branch_weights", !"expected", i32 1, i32 2000}

View File

@ -352,5 +352,5 @@ declare i64 @llvm.expect.i64(i64, i64)
!llvm.ident = !{!0}
!0 = !{!"clang version 5.0.0 (trunk 302965)"}
; CHECK: [[WEIGHT]] = !{!"branch_weights", i32 2000, i32 1}
; CHECK: [[WEIGHT2]] = !{!"branch_weights", i32 1, i32 2000}
; CHECK: [[WEIGHT]] = !{!"branch_weights", !"expected", i32 2000, i32 1}
; CHECK: [[WEIGHT2]] = !{!"branch_weights", !"expected", i32 1, i32 2000}

View File

@ -99,5 +99,5 @@ declare i64 @llvm.expect.i64(i64, i64)
!0 = !{!"clang version 5.0.0 (trunk 302965)"}
; CHECK: [[WEIGHT]] = !{!"branch_weights", i32 2000, i32 1}
; CHECK: [[WEIGHT2]] = !{!"branch_weights", i32 1, i32 2000}
; CHECK: [[WEIGHT]] = !{!"branch_weights", !"expected", i32 2000, i32 1}
; CHECK: [[WEIGHT2]] = !{!"branch_weights", !"expected", i32 1, i32 2000}

View File

@ -53,4 +53,4 @@ declare i64 @llvm.expect.i64(i64, i64)
!0 = !{!"clang version 5.0.0 (trunk 302965)"}
; CHECK: [[WEIGHT]] = !{!"branch_weights", i32 1, i32 2000}
; CHECK: [[WEIGHT]] = !{!"branch_weights", !"expected", i32 1, i32 2000}

View File

@ -235,5 +235,5 @@ block5:
ret void
}
; CHECK: !0 = !{!"branch_weights", i32 2147483647, i32 1}
; CHECK: !1 = !{!"branch_weights", i32 1, i32 2147483647}
; CHECK: !0 = !{!"branch_weights", !"expected", i32 2147483647, i32 1}
; CHECK: !1 = !{!"branch_weights", !"expected", i32 1, i32 2147483647}

View File

@ -293,7 +293,7 @@ declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture)
; CHECK: [[META1]] = !{!"llvm.loop.isvectorized", i32 1}
; CHECK: [[META2]] = !{!"llvm.loop.unroll.runtime.disable"}
; CHECK: [[LOOP3]] = distinct !{[[LOOP3]], [[META2]], [[META1]]}
; CHECK: [[PROF4]] = !{!"branch_weights", i32 2000, i32 1}
; CHECK: [[PROF4]] = !{!"branch_weights", !"expected", i32 2000, i32 1}
; CHECK: [[LOOP5]] = distinct !{[[LOOP5]], [[META1]], [[META2]]}
; CHECK: [[LOOP6]] = distinct !{[[LOOP6]], [[META2]], [[META1]]}
;.