Skip to content

Commit e3a4701

Browse files
committed
[clang][CodeGen] Lower Likelihood attributes to @llvm.expect intrin instead of branch weights
08196e0 exposed LowerExpectIntrinsic's internal implementation detail in the form of LikelyBranchWeight/UnlikelyBranchWeight options to the outside. While this isn't incorrect from the results viewpoint, this is suboptimal from the layering viewpoint, and causes confusion - should transforms also use those weights, or should they use something else, D98898? So go back to status quo by making LikelyBranchWeight/UnlikelyBranchWeight internal again, and fixing all the code that used it directly, which currently is only clang codegen, thankfully, to emit proper @llvm.expect intrinsics instead.
1 parent 37d6be9 commit e3a4701

File tree

7 files changed

+524
-157
lines changed

7 files changed

+524
-157
lines changed

clang/lib/CodeGen/CGStmt.cpp

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -821,8 +821,11 @@ void CodeGenFunction::EmitWhileStmt(const WhileStmt &S,
821821
llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
822822
if (ConditionScope.requiresCleanups())
823823
ExitBlock = createBasicBlock("while.exit");
824-
llvm::MDNode *Weights = createProfileOrBranchWeightsForLoop(
825-
S.getCond(), getProfileCount(S.getBody()), S.getBody());
824+
llvm::MDNode *Weights =
825+
createProfileWeightsForLoop(S.getCond(), getProfileCount(S.getBody()));
826+
if (!Weights && CGM.getCodeGenOpts().OptimizationLevel)
827+
BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
828+
BoolCondVal, Stmt::getLikelihood(S.getBody()));
826829
Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock, Weights);
827830

828831
if (ExitBlock != LoopExit.getBlock()) {
@@ -1008,8 +1011,11 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S,
10081011
// C99 6.8.5p2/p4: The first substatement is executed if the expression
10091012
// compares unequal to 0. The condition must be a scalar type.
10101013
llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
1011-
llvm::MDNode *Weights = createProfileOrBranchWeightsForLoop(
1012-
S.getCond(), getProfileCount(S.getBody()), S.getBody());
1014+
llvm::MDNode *Weights =
1015+
createProfileWeightsForLoop(S.getCond(), getProfileCount(S.getBody()));
1016+
if (!Weights && CGM.getCodeGenOpts().OptimizationLevel)
1017+
BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1018+
BoolCondVal, Stmt::getLikelihood(S.getBody()));
10131019

10141020
if (llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal))
10151021
if (C->isOne())
@@ -1094,8 +1100,11 @@ CodeGenFunction::EmitCXXForRangeStmt(const CXXForRangeStmt &S,
10941100
// The body is executed if the expression, contextually converted
10951101
// to bool, is true.
10961102
llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
1097-
llvm::MDNode *Weights = createProfileOrBranchWeightsForLoop(
1098-
S.getCond(), getProfileCount(S.getBody()), S.getBody());
1103+
llvm::MDNode *Weights =
1104+
createProfileWeightsForLoop(S.getCond(), getProfileCount(S.getBody()));
1105+
if (!Weights && CGM.getCodeGenOpts().OptimizationLevel)
1106+
BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
1107+
BoolCondVal, Stmt::getLikelihood(S.getBody()));
10991108
Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
11001109

11011110
if (ExitBlock != LoopExit.getBlock()) {
@@ -1369,7 +1378,7 @@ void CodeGenFunction::EmitCaseStmtRange(const CaseStmt &S,
13691378
// this case.
13701379
(*SwitchWeights)[0] += ThisCount;
13711380
} else if (SwitchLikelihood)
1372-
Weights = createBranchWeights(LH);
1381+
Cond = emitCondLikelihoodViaExpectIntrinsic(Cond, LH);
13731382

13741383
Builder.CreateCondBr(Cond, CaseDest, FalseDest, Weights);
13751384

clang/lib/CodeGen/CodeGenFunction.cpp

Lines changed: 44 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1764,31 +1764,39 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
17641764
return;
17651765
}
17661766

1767-
// If the branch has a condition wrapped by __builtin_unpredictable,
1768-
// create metadata that specifies that the branch is unpredictable.
1769-
// Don't bother if not optimizing because that metadata would not be used.
1770-
llvm::MDNode *Unpredictable = nullptr;
1771-
auto *Call = dyn_cast<CallExpr>(Cond->IgnoreImpCasts());
1772-
if (Call && CGM.getCodeGenOpts().OptimizationLevel != 0) {
1773-
auto *FD = dyn_cast_or_null<FunctionDecl>(Call->getCalleeDecl());
1774-
if (FD && FD->getBuiltinID() == Builtin::BI__builtin_unpredictable) {
1775-
llvm::MDBuilder MDHelper(getLLVMContext());
1776-
Unpredictable = MDHelper.createUnpredictable();
1777-
}
1778-
}
1779-
1780-
llvm::MDNode *Weights = createBranchWeights(LH);
1781-
if (!Weights) {
1782-
uint64_t CurrentCount = std::max(getCurrentProfileCount(), TrueCount);
1783-
Weights = createProfileWeights(TrueCount, CurrentCount - TrueCount);
1784-
}
1785-
17861767
// Emit the code with the fully general case.
17871768
llvm::Value *CondV;
17881769
{
17891770
ApplyDebugLocation DL(*this, Cond);
17901771
CondV = EvaluateExprAsBool(Cond);
17911772
}
1773+
1774+
llvm::MDNode *Weights = nullptr;
1775+
llvm::MDNode *Unpredictable = nullptr;
1776+
1777+
// If optimizing, lower unpredictability/probability knowledge about cond.
1778+
if (CGM.getCodeGenOpts().OptimizationLevel != 0) {
1779+
// If the branch has a condition wrapped by __builtin_unpredictable,
1780+
// create metadata that specifies that the branch is unpredictable.
1781+
if (auto *Call = dyn_cast<CallExpr>(Cond->IgnoreImpCasts())) {
1782+
auto *FD = dyn_cast_or_null<FunctionDecl>(Call->getCalleeDecl());
1783+
if (FD && FD->getBuiltinID() == Builtin::BI__builtin_unpredictable) {
1784+
llvm::MDBuilder MDHelper(getLLVMContext());
1785+
Unpredictable = MDHelper.createUnpredictable();
1786+
}
1787+
}
1788+
1789+
// If there is a Likelihood knowledge for the cond, lower it.
1790+
llvm::Value *NewCondV = emitCondLikelihoodViaExpectIntrinsic(CondV, LH);
1791+
if (CondV != NewCondV)
1792+
CondV = NewCondV;
1793+
else {
1794+
// Otherwise, lower profile counts.
1795+
uint64_t CurrentCount = std::max(getCurrentProfileCount(), TrueCount);
1796+
Weights = createProfileWeights(TrueCount, CurrentCount - TrueCount);
1797+
}
1798+
}
1799+
17921800
Builder.CreateCondBr(CondV, TrueBlock, FalseBlock, Weights, Unpredictable);
17931801
}
17941802

@@ -2632,35 +2640,26 @@ llvm::DebugLoc CodeGenFunction::SourceLocToDebugLoc(SourceLocation Location) {
26322640
return llvm::DebugLoc();
26332641
}
26342642

2635-
static Optional<std::pair<uint32_t, uint32_t>>
2636-
getLikelihoodWeights(Stmt::Likelihood LH) {
2643+
llvm::Value *
2644+
CodeGenFunction::emitCondLikelihoodViaExpectIntrinsic(llvm::Value *Cond,
2645+
Stmt::Likelihood LH) {
26372646
switch (LH) {
2638-
case Stmt::LH_Unlikely:
2639-
return std::pair<uint32_t, uint32_t>(llvm::UnlikelyBranchWeight,
2640-
llvm::LikelyBranchWeight);
26412647
case Stmt::LH_None:
2642-
return None;
2648+
return Cond;
26432649
case Stmt::LH_Likely:
2644-
return std::pair<uint32_t, uint32_t>(llvm::LikelyBranchWeight,
2645-
llvm::UnlikelyBranchWeight);
2650+
case Stmt::LH_Unlikely:
2651+
// Don't generate llvm.expect on -O0 as the backend won't use it for
2652+
// anything.
2653+
if (CGM.getCodeGenOpts().OptimizationLevel == 0)
2654+
return Cond;
2655+
llvm::Type *CondTy = Cond->getType();
2656+
assert(CondTy->isIntegerTy(1) && "expecting condition to be a boolean");
2657+
llvm::Function *FnExpect =
2658+
CGM.getIntrinsic(llvm::Intrinsic::expect, CondTy);
2659+
llvm::Value *ExpectedValueOfCond =
2660+
llvm::ConstantInt::getBool(CondTy, LH == Stmt::LH_Likely);
2661+
return Builder.CreateCall(FnExpect, {Cond, ExpectedValueOfCond},
2662+
Cond->getName() + ".expval");
26462663
}
26472664
llvm_unreachable("Unknown Likelihood");
26482665
}
2649-
2650-
llvm::MDNode *CodeGenFunction::createBranchWeights(Stmt::Likelihood LH) const {
2651-
Optional<std::pair<uint32_t, uint32_t>> LHW = getLikelihoodWeights(LH);
2652-
if (!LHW)
2653-
return nullptr;
2654-
2655-
llvm::MDBuilder MDHelper(CGM.getLLVMContext());
2656-
return MDHelper.createBranchWeights(LHW->first, LHW->second);
2657-
}
2658-
2659-
llvm::MDNode *CodeGenFunction::createProfileOrBranchWeightsForLoop(
2660-
const Stmt *Cond, uint64_t LoopCount, const Stmt *Body) const {
2661-
llvm::MDNode *Weights = createProfileWeightsForLoop(Cond, LoopCount);
2662-
if (!Weights && CGM.getCodeGenOpts().OptimizationLevel)
2663-
Weights = createBranchWeights(Stmt::getLikelihood(Body));
2664-
2665-
return Weights;
2666-
}

clang/lib/CodeGen/CodeGenFunction.h

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1445,8 +1445,9 @@ class CodeGenFunction : public CodeGenTypeCache {
14451445
};
14461446
OpenMPCancelExitStack OMPCancelStack;
14471447

1448-
/// Calculate branch weights for the likelihood attribute
1449-
llvm::MDNode *createBranchWeights(Stmt::Likelihood LH) const;
1448+
/// Lower the Likelihood knowledge about the \p Cond via llvm.expect intrin.
1449+
llvm::Value *emitCondLikelihoodViaExpectIntrinsic(llvm::Value *Cond,
1450+
Stmt::Likelihood LH);
14501451

14511452
CodeGenPGO PGO;
14521453

@@ -1457,13 +1458,6 @@ class CodeGenFunction : public CodeGenTypeCache {
14571458
llvm::MDNode *createProfileWeightsForLoop(const Stmt *Cond,
14581459
uint64_t LoopCount) const;
14591460

1460-
/// Calculate the branch weight for PGO data or the likelihood attribute.
1461-
/// The function tries to get the weight of \ref createProfileWeightsForLoop.
1462-
/// If that fails it gets the weight of \ref createBranchWeights.
1463-
llvm::MDNode *createProfileOrBranchWeightsForLoop(const Stmt *Cond,
1464-
uint64_t LoopCount,
1465-
const Stmt *Body) const;
1466-
14671461
public:
14681462
/// Increment the profiler's counter for the given statement by \p StepV.
14691463
/// If \p StepV is null, the default increment is 1.

0 commit comments

Comments
 (0)