aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CodeGenFunction.cpp
diff options
context:
space:
mode:
authorMark de Wever <koraq@xs4all.nl>2020-10-04 14:21:00 +0200
committerMark de Wever <koraq@xs4all.nl>2020-10-04 14:24:27 +0200
commit1113fbf44c2250621548e278d2a1e11ab2b2d63d (patch)
treecdc7bd0c400d2aaaf321d43cb1a1d0b304b0ce83 /clang/lib/CodeGen/CodeGenFunction.cpp
parent7ce4dfb4dd2ca431f17b62ef563cc3b2737c677e (diff)
downloadllvm-1113fbf44c2250621548e278d2a1e11ab2b2d63d.zip
llvm-1113fbf44c2250621548e278d2a1e11ab2b2d63d.tar.gz
llvm-1113fbf44c2250621548e278d2a1e11ab2b2d63d.tar.bz2
[CodeGen] Improve likelihood branch weights
Bruno De Fraine discovered some issues with D85091. The branch weights generated for `logical not` and `ternary conditional` were wrong. The `logical and` and `logical or` differed from the code generated of `__builtin_predict`. Adjusted the generated code for the likelihood to match `__builtin_predict`. The patch is based on Bruno's suggestions. Differential Revision: https://reviews.llvm.org/D88363
Diffstat (limited to 'clang/lib/CodeGen/CodeGenFunction.cpp')
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp62
1 files changed, 46 insertions, 16 deletions
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 47ef5c8..363b418 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -42,6 +42,7 @@
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Operator.h"
#include "llvm/Support/CRC.h"
+#include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h"
#include "llvm/Transforms/Utils/PromoteMemToReg.h"
using namespace clang;
using namespace CodeGen;
@@ -1477,15 +1478,30 @@ bool CodeGenFunction::ConstantFoldsToSimpleInteger(const Expr *Cond,
return true;
}
+static Optional<std::pair<uint32_t, uint32_t>>
+getLikelihoodWeights(Stmt::Likelihood LH) {
+ switch (LH) {
+ case Stmt::LH_Unlikely:
+ return std::pair<uint32_t, uint32_t>(llvm::UnlikelyBranchWeight,
+ llvm::LikelyBranchWeight);
+ case Stmt::LH_None:
+ return None;
+ case Stmt::LH_Likely:
+ return std::pair<uint32_t, uint32_t>(llvm::LikelyBranchWeight,
+ llvm::UnlikelyBranchWeight);
+ }
+ llvm_unreachable("Unknown Likelihood");
+}
+
/// EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g. for an if
/// statement) to the specified blocks. Based on the condition, this might try
/// to simplify the codegen of the conditional based on the branch.
-/// \param Weights The weights determined by the likelihood attributes.
+/// \param LH The value of the likelihood attribute on the True branch.
void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
llvm::BasicBlock *TrueBlock,
llvm::BasicBlock *FalseBlock,
uint64_t TrueCount,
- llvm::MDNode *Weights) {
+ Stmt::Likelihood LH) {
Cond = Cond->IgnoreParens();
if (const BinaryOperator *CondBOp = dyn_cast<BinaryOperator>(Cond)) {
@@ -1500,7 +1516,7 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
// br(1 && X) -> br(X).
incrementProfileCounter(CondBOp);
return EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock,
- TrueCount, Weights);
+ TrueCount, LH);
}
// If we have "X && 1", simplify the code to use an uncond branch.
@@ -1509,7 +1525,7 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
ConstantBool) {
// br(X && 1) -> br(X).
return EmitBranchOnBoolExpr(CondBOp->getLHS(), TrueBlock, FalseBlock,
- TrueCount, Weights);
+ TrueCount, LH);
}
// Emit the LHS as a conditional. If the LHS conditional is false, we
@@ -1522,8 +1538,11 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
ConditionalEvaluation eval(*this);
{
ApplyDebugLocation DL(*this, Cond);
+ // Propagate the likelihood attribute like __builtin_expect
+ // __builtin_expect(X && Y, 1) -> X and Y are likely
+ // __builtin_expect(X && Y, 0) -> only Y is unlikely
EmitBranchOnBoolExpr(CondBOp->getLHS(), LHSTrue, FalseBlock, RHSCount,
- Weights);
+ LH == Stmt::LH_Unlikely ? Stmt::LH_None : LH);
EmitBlock(LHSTrue);
}
@@ -1533,7 +1552,7 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
// Any temporaries created here are conditional.
eval.begin(*this);
EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock, TrueCount,
- Weights);
+ LH);
eval.end(*this);
return;
@@ -1548,7 +1567,7 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
// br(0 || X) -> br(X).
incrementProfileCounter(CondBOp);
return EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock,
- TrueCount, Weights);
+ TrueCount, LH);
}
// If we have "X || 0", simplify the code to use an uncond branch.
@@ -1557,7 +1576,7 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
!ConstantBool) {
// br(X || 0) -> br(X).
return EmitBranchOnBoolExpr(CondBOp->getLHS(), TrueBlock, FalseBlock,
- TrueCount, Weights);
+ TrueCount, LH);
}
// Emit the LHS as a conditional. If the LHS conditional is true, we
@@ -1572,9 +1591,12 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
ConditionalEvaluation eval(*this);
{
+ // Propagate the likelihood attribute like __builtin_expect
+ // __builtin_expect(X || Y, 1) -> only Y is likely
+ // __builtin_expect(X || Y, 0) -> both X and Y are unlikely
ApplyDebugLocation DL(*this, Cond);
EmitBranchOnBoolExpr(CondBOp->getLHS(), TrueBlock, LHSFalse, LHSCount,
- Weights);
+ LH == Stmt::LH_Likely ? Stmt::LH_None : LH);
EmitBlock(LHSFalse);
}
@@ -1584,7 +1606,7 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
// Any temporaries created here are conditional.
eval.begin(*this);
EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock, RHSCount,
- Weights);
+ LH);
eval.end(*this);
@@ -1597,9 +1619,11 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
if (CondUOp->getOpcode() == UO_LNot) {
// Negate the count.
uint64_t FalseCount = getCurrentProfileCount() - TrueCount;
+ // The values of the enum are chosen to make this negation possible.
+ LH = static_cast<Stmt::Likelihood>(-LH);
// Negate the condition and swap the destination blocks.
return EmitBranchOnBoolExpr(CondUOp->getSubExpr(), FalseBlock, TrueBlock,
- FalseCount, Weights);
+ FalseCount, LH);
}
}
@@ -1608,9 +1632,11 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
llvm::BasicBlock *LHSBlock = createBasicBlock("cond.true");
llvm::BasicBlock *RHSBlock = createBasicBlock("cond.false");
+ // The ConditionalOperator itself has no likelihood information for its
+ // true and false branches. This matches the behavior of __builtin_expect.
ConditionalEvaluation cond(*this);
EmitBranchOnBoolExpr(CondOp->getCond(), LHSBlock, RHSBlock,
- getProfileCount(CondOp), Weights);
+ getProfileCount(CondOp), Stmt::LH_None);
// When computing PGO branch weights, we only know the overall count for
// the true block. This code is essentially doing tail duplication of the
@@ -1630,14 +1656,14 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
{
ApplyDebugLocation DL(*this, Cond);
EmitBranchOnBoolExpr(CondOp->getLHS(), TrueBlock, FalseBlock,
- LHSScaledTrueCount, Weights);
+ LHSScaledTrueCount, LH);
}
cond.end(*this);
cond.begin(*this);
EmitBlock(RHSBlock);
EmitBranchOnBoolExpr(CondOp->getRHS(), TrueBlock, FalseBlock,
- TrueCount - LHSScaledTrueCount, Weights);
+ TrueCount - LHSScaledTrueCount, LH);
cond.end(*this);
return;
@@ -1666,8 +1692,12 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
}
}
- // Create branch weights based on the number of times we get here and the
- // number of times the condition should be true.
+ llvm::MDNode *Weights = nullptr;
+ Optional<std::pair<uint32_t, uint32_t>> LHW = getLikelihoodWeights(LH);
+ if (LHW) {
+ llvm::MDBuilder MDHelper(CGM.getLLVMContext());
+ Weights = MDHelper.createBranchWeights(LHW->first, LHW->second);
+ }
if (!Weights) {
uint64_t CurrentCount = std::max(getCurrentProfileCount(), TrueCount);
Weights = createProfileWeights(TrueCount, CurrentCount - TrueCount);