Skip to content

Commit 294f3ce

Browse files
authored
Reapply "[llvm][IR] Extend BranchWeightMetadata to track provenance o… (llvm#95281)
…f weights" llvm#95136 Reverts llvm#95060, and relands llvm#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.
1 parent 7b80384 commit 294f3ce

31 files changed

+179
-92
lines changed

clang/test/CodeGenCXX/attr-likelihood-if-vs-builtin-expect.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,5 +221,5 @@ void tu2(int &i) {
221221
}
222222
}
223223

224-
// CHECK: [[BW_LIKELY]] = !{!"branch_weights", i32 2000, i32 1}
225-
// CHECK: [[BW_UNLIKELY]] = !{!"branch_weights", i32 1, i32 2000}
224+
// CHECK: [[BW_LIKELY]] = !{!"branch_weights", !"expected", i32 2000, i32 1}
225+
// CHECK: [[BW_UNLIKELY]] = !{!"branch_weights", !"expected", i32 1, i32 2000}

llvm/docs/BranchWeightMetadata.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,14 @@ Supported Instructions
2828

2929
Metadata is only assigned to the conditional branches. There are two extra
3030
operands for the true and the false branch.
31+
We optionally track if the metadata was added by ``__builtin_expect`` or
32+
``__builtin_expect_with_probability`` with an optional field ``!"expected"``.
3133

3234
.. code-block:: none
3335
3436
!0 = !{
3537
!"branch_weights",
38+
[ !"expected", ]
3639
i32 <TRUE_BRANCH_WEIGHT>,
3740
i32 <FALSE_BRANCH_WEIGHT>
3841
}
@@ -47,6 +50,7 @@ is always case #0).
4750
4851
!0 = !{
4952
!"branch_weights",
53+
[ !"expected", ]
5054
i32 <DEFAULT_BRANCH_WEIGHT>
5155
[ , i32 <CASE_BRANCH_WEIGHT> ... ]
5256
}
@@ -60,6 +64,7 @@ Branch weights are assigned to every destination.
6064
6165
!0 = !{
6266
!"branch_weights",
67+
[ !"expected", ]
6368
i32 <LABEL_BRANCH_WEIGHT>
6469
[ , i32 <LABEL_BRANCH_WEIGHT> ... ]
6570
}
@@ -75,6 +80,7 @@ block and entry counts which may not be accurate with sampling.
7580
7681
!0 = !{
7782
!"branch_weights",
83+
[ !"expected", ]
7884
i32 <CALL_BRANCH_WEIGHT>
7985
}
8086
@@ -95,6 +101,7 @@ is used.
95101
96102
!0 = !{
97103
!"branch_weights",
104+
[ !"expected", ]
98105
i32 <INVOKE_NORMAL_WEIGHT>
99106
[ , i32 <INVOKE_UNWIND_WEIGHT> ]
100107
}

llvm/include/llvm/IR/MDBuilder.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,11 @@ class MDBuilder {
5959
//===------------------------------------------------------------------===//
6060

6161
/// Return metadata containing two branch weights.
62-
MDNode *createBranchWeights(uint32_t TrueWeight, uint32_t FalseWeight);
62+
/// @param TrueWeight the weight of the true branch
63+
/// @param FalseWeight the weight of the false branch
64+
/// @param Do these weights come from __builtin_expect*
65+
MDNode *createBranchWeights(uint32_t TrueWeight, uint32_t FalseWeight,
66+
bool IsExpected = false);
6367

6468
/// Return metadata containing two branch weights, with significant bias
6569
/// towards `true` destination.
@@ -70,7 +74,10 @@ class MDBuilder {
7074
MDNode *createUnlikelyBranchWeights();
7175

7276
/// Return metadata containing a number of branch weights.
73-
MDNode *createBranchWeights(ArrayRef<uint32_t> Weights);
77+
/// @param Weights the weights of all the branches
78+
/// @param Do these weights come from __builtin_expect*
79+
MDNode *createBranchWeights(ArrayRef<uint32_t> Weights,
80+
bool IsExpected = false);
7481

7582
/// Return metadata specifying that a branch or switch is unpredictable.
7683
MDNode *createUnpredictable();

llvm/include/llvm/IR/ProfDataUtils.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,17 @@ MDNode *getBranchWeightMDNode(const Instruction &I);
5555
/// Nullptr otherwise.
5656
MDNode *getValidBranchWeightMDNode(const Instruction &I);
5757

58+
/// Check if Branch Weight Metadata has an "expected" field from an llvm.expect*
59+
/// intrinsic
60+
bool hasBranchWeightOrigin(const Instruction &I);
61+
62+
/// Check if Branch Weight Metadata has an "expected" field from an llvm.expect*
63+
/// intrinsic
64+
bool hasBranchWeightOrigin(const MDNode *ProfileData);
65+
66+
/// Return the offset to the first branch weight data
67+
unsigned getBranchWeightOffset(const MDNode *ProfileData);
68+
5869
/// Extract branch weights from MD_prof metadata
5970
///
6071
/// \param ProfileData A pointer to an MDNode.
@@ -111,7 +122,11 @@ bool extractProfTotalWeight(const Instruction &I, uint64_t &TotalWeights);
111122

112123
/// Create a new `branch_weights` metadata node and add or overwrite
113124
/// a `prof` metadata reference to instruction `I`.
114-
void setBranchWeights(Instruction &I, ArrayRef<uint32_t> Weights);
125+
/// \param I the Instruction to set branch weights on.
126+
/// \param Weights an array of weights to set on instruction I.
127+
/// \param IsExpected were these weights added from an llvm.expect* intrinsic.
128+
void setBranchWeights(Instruction &I, ArrayRef<uint32_t> Weights,
129+
bool IsExpected);
115130

116131
/// Scaling the profile data attached to 'I' using the ratio of S/T.
117132
void scaleProfData(Instruction &I, uint64_t S, uint64_t T);

llvm/lib/Bitcode/Reader/BitcodeReader.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
#include "llvm/IR/Module.h"
5858
#include "llvm/IR/ModuleSummaryIndex.h"
5959
#include "llvm/IR/Operator.h"
60+
#include "llvm/IR/ProfDataUtils.h"
6061
#include "llvm/IR/Type.h"
6162
#include "llvm/IR/Value.h"
6263
#include "llvm/IR/Verifier.h"
@@ -6951,8 +6952,10 @@ Error BitcodeReader::materialize(GlobalValue *GV) {
69516952
else
69526953
continue; // ignore and continue.
69536954

6955+
unsigned Offset = getBranchWeightOffset(MD);
6956+
69546957
// If branch weight doesn't match, just strip branch weight.
6955-
if (MD->getNumOperands() != 1 + ExpectedNumOperands)
6958+
if (MD->getNumOperands() != Offset + ExpectedNumOperands)
69566959
I.setMetadata(LLVMContext::MD_prof, nullptr);
69576960
}
69586961
}

llvm/lib/CodeGen/CodeGenPrepare.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8866,7 +8866,8 @@ bool CodeGenPrepare::splitBranchCondition(Function &F, ModifyDT &ModifiedDT) {
88668866
scaleWeights(NewTrueWeight, NewFalseWeight);
88678867
Br1->setMetadata(LLVMContext::MD_prof,
88688868
MDBuilder(Br1->getContext())
8869-
.createBranchWeights(TrueWeight, FalseWeight));
8869+
.createBranchWeights(TrueWeight, FalseWeight,
8870+
hasBranchWeightOrigin(*Br1)));
88708871

88718872
NewTrueWeight = TrueWeight;
88728873
NewFalseWeight = 2 * FalseWeight;

llvm/lib/IR/Instruction.cpp

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1268,12 +1268,23 @@ Instruction *Instruction::cloneImpl() const {
12681268

12691269
void Instruction::swapProfMetadata() {
12701270
MDNode *ProfileData = getBranchWeightMDNode(*this);
1271-
if (!ProfileData || ProfileData->getNumOperands() != 3)
1271+
if (!ProfileData)
1272+
return;
1273+
unsigned FirstIdx = getBranchWeightOffset(ProfileData);
1274+
if (ProfileData->getNumOperands() != 2 + FirstIdx)
12721275
return;
12731276

1274-
// The first operand is the name. Fetch them backwards and build a new one.
1275-
Metadata *Ops[] = {ProfileData->getOperand(0), ProfileData->getOperand(2),
1276-
ProfileData->getOperand(1)};
1277+
unsigned SecondIdx = FirstIdx + 1;
1278+
SmallVector<Metadata *, 4> Ops;
1279+
// If there are more weights past the second, we can't swap them
1280+
if (ProfileData->getNumOperands() > SecondIdx + 1)
1281+
return;
1282+
for (unsigned Idx = 0; Idx < FirstIdx; ++Idx) {
1283+
Ops.push_back(ProfileData->getOperand(Idx));
1284+
}
1285+
// Switch the order of the weights
1286+
Ops.push_back(ProfileData->getOperand(SecondIdx));
1287+
Ops.push_back(ProfileData->getOperand(FirstIdx));
12771288
setMetadata(LLVMContext::MD_prof,
12781289
MDNode::get(ProfileData->getContext(), Ops));
12791290
}

llvm/lib/IR/Instructions.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5199,7 +5199,11 @@ void SwitchInstProfUpdateWrapper::init() {
51995199
if (!ProfileData)
52005200
return;
52015201

5202-
if (ProfileData->getNumOperands() != SI.getNumSuccessors() + 1) {
5202+
// FIXME: This check belongs in ProfDataUtils. Its almost equivalent to
5203+
// getValidBranchWeightMDNode(), but the need to use llvm_unreachable
5204+
// makes them slightly different.
5205+
if (ProfileData->getNumOperands() !=
5206+
SI.getNumSuccessors() + getBranchWeightOffset(ProfileData)) {
52035207
llvm_unreachable("number of prof branch_weights metadata operands does "
52045208
"not correspond to number of succesors");
52055209
}

llvm/lib/IR/MDBuilder.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ MDNode *MDBuilder::createFPMath(float Accuracy) {
3535
}
3636

3737
MDNode *MDBuilder::createBranchWeights(uint32_t TrueWeight,
38-
uint32_t FalseWeight) {
39-
return createBranchWeights({TrueWeight, FalseWeight});
38+
uint32_t FalseWeight, bool IsExpected) {
39+
return createBranchWeights({TrueWeight, FalseWeight}, IsExpected);
4040
}
4141

4242
MDNode *MDBuilder::createLikelyBranchWeights() {
@@ -49,15 +49,19 @@ MDNode *MDBuilder::createUnlikelyBranchWeights() {
4949
return createBranchWeights(1, (1U << 20) - 1);
5050
}
5151

52-
MDNode *MDBuilder::createBranchWeights(ArrayRef<uint32_t> Weights) {
52+
MDNode *MDBuilder::createBranchWeights(ArrayRef<uint32_t> Weights,
53+
bool IsExpected) {
5354
assert(Weights.size() >= 1 && "Need at least one branch weights!");
5455

55-
SmallVector<Metadata *, 4> Vals(Weights.size() + 1);
56+
unsigned int Offset = IsExpected ? 2 : 1;
57+
SmallVector<Metadata *, 4> Vals(Weights.size() + Offset);
5658
Vals[0] = createString("branch_weights");
59+
if (IsExpected)
60+
Vals[1] = createString("expected");
5761

5862
Type *Int32Ty = Type::getInt32Ty(Context);
5963
for (unsigned i = 0, e = Weights.size(); i != e; ++i)
60-
Vals[i + 1] = createConstant(ConstantInt::get(Int32Ty, Weights[i]));
64+
Vals[i + Offset] = createConstant(ConstantInt::get(Int32Ty, Weights[i]));
6165

6266
return MDNode::get(Context, Vals);
6367
}

llvm/lib/IR/Metadata.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1196,10 +1196,10 @@ MDNode *MDNode::mergeDirectCallProfMetadata(MDNode *A, MDNode *B,
11961196
StringRef AProfName = AMDS->getString();
11971197
StringRef BProfName = BMDS->getString();
11981198
if (AProfName == "branch_weights" && BProfName == "branch_weights") {
1199-
ConstantInt *AInstrWeight =
1200-
mdconst::dyn_extract<ConstantInt>(A->getOperand(1));
1201-
ConstantInt *BInstrWeight =
1202-
mdconst::dyn_extract<ConstantInt>(B->getOperand(1));
1199+
ConstantInt *AInstrWeight = mdconst::dyn_extract<ConstantInt>(
1200+
A->getOperand(getBranchWeightOffset(A)));
1201+
ConstantInt *BInstrWeight = mdconst::dyn_extract<ConstantInt>(
1202+
B->getOperand(getBranchWeightOffset(B)));
12031203
assert(AInstrWeight && BInstrWeight && "verified by LLVM verifier");
12041204
return MDNode::get(Ctx,
12051205
{MDHelper.createString("branch_weights"),

0 commit comments

Comments
 (0)