aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CodeGenFunction.cpp
diff options
context:
space:
mode:
authorRoman Lebedev <lebedev.ri@gmail.com>2021-03-21 22:13:47 +0300
committerRoman Lebedev <lebedev.ri@gmail.com>2021-03-21 22:50:21 +0300
commite3a470162738871bba982416748ae5f5e3572947 (patch)
tree91128665e388d02ee455879014cee60923318fe0 /clang/lib/CodeGen/CodeGenFunction.cpp
parent37d6be90524ca1659521ab879aaae5e5501f1e97 (diff)
downloadllvm-e3a470162738871bba982416748ae5f5e3572947.zip
llvm-e3a470162738871bba982416748ae5f5e3572947.tar.gz
llvm-e3a470162738871bba982416748ae5f5e3572947.tar.bz2
[clang][CodeGen] Lower Likelihood attributes to @llvm.expect intrin instead of branch weights
08196e0b2e1f8aaa8a854585335c17ba479114df 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.
Diffstat (limited to 'clang/lib/CodeGen/CodeGenFunction.cpp')
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp89
1 files changed, 44 insertions, 45 deletions
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index a00ae74..1c53826 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -1764,31 +1764,39 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
return;
}
- // If the branch has a condition wrapped by __builtin_unpredictable,
- // create metadata that specifies that the branch is unpredictable.
- // Don't bother if not optimizing because that metadata would not be used.
- llvm::MDNode *Unpredictable = nullptr;
- auto *Call = dyn_cast<CallExpr>(Cond->IgnoreImpCasts());
- if (Call && CGM.getCodeGenOpts().OptimizationLevel != 0) {
- auto *FD = dyn_cast_or_null<FunctionDecl>(Call->getCalleeDecl());
- if (FD && FD->getBuiltinID() == Builtin::BI__builtin_unpredictable) {
- llvm::MDBuilder MDHelper(getLLVMContext());
- Unpredictable = MDHelper.createUnpredictable();
- }
- }
-
- llvm::MDNode *Weights = createBranchWeights(LH);
- if (!Weights) {
- uint64_t CurrentCount = std::max(getCurrentProfileCount(), TrueCount);
- Weights = createProfileWeights(TrueCount, CurrentCount - TrueCount);
- }
-
// Emit the code with the fully general case.
llvm::Value *CondV;
{
ApplyDebugLocation DL(*this, Cond);
CondV = EvaluateExprAsBool(Cond);
}
+
+ llvm::MDNode *Weights = nullptr;
+ llvm::MDNode *Unpredictable = nullptr;
+
+ // If optimizing, lower unpredictability/probability knowledge about cond.
+ if (CGM.getCodeGenOpts().OptimizationLevel != 0) {
+ // If the branch has a condition wrapped by __builtin_unpredictable,
+ // create metadata that specifies that the branch is unpredictable.
+ if (auto *Call = dyn_cast<CallExpr>(Cond->IgnoreImpCasts())) {
+ auto *FD = dyn_cast_or_null<FunctionDecl>(Call->getCalleeDecl());
+ if (FD && FD->getBuiltinID() == Builtin::BI__builtin_unpredictable) {
+ llvm::MDBuilder MDHelper(getLLVMContext());
+ Unpredictable = MDHelper.createUnpredictable();
+ }
+ }
+
+ // If there is a Likelihood knowledge for the cond, lower it.
+ llvm::Value *NewCondV = emitCondLikelihoodViaExpectIntrinsic(CondV, LH);
+ if (CondV != NewCondV)
+ CondV = NewCondV;
+ else {
+ // Otherwise, lower profile counts.
+ uint64_t CurrentCount = std::max(getCurrentProfileCount(), TrueCount);
+ Weights = createProfileWeights(TrueCount, CurrentCount - TrueCount);
+ }
+ }
+
Builder.CreateCondBr(CondV, TrueBlock, FalseBlock, Weights, Unpredictable);
}
@@ -2632,35 +2640,26 @@ llvm::DebugLoc CodeGenFunction::SourceLocToDebugLoc(SourceLocation Location) {
return llvm::DebugLoc();
}
-static Optional<std::pair<uint32_t, uint32_t>>
-getLikelihoodWeights(Stmt::Likelihood LH) {
+llvm::Value *
+CodeGenFunction::emitCondLikelihoodViaExpectIntrinsic(llvm::Value *Cond,
+ 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;
+ return Cond;
case Stmt::LH_Likely:
- return std::pair<uint32_t, uint32_t>(llvm::LikelyBranchWeight,
- llvm::UnlikelyBranchWeight);
+ case Stmt::LH_Unlikely:
+ // Don't generate llvm.expect on -O0 as the backend won't use it for
+ // anything.
+ if (CGM.getCodeGenOpts().OptimizationLevel == 0)
+ return Cond;
+ llvm::Type *CondTy = Cond->getType();
+ assert(CondTy->isIntegerTy(1) && "expecting condition to be a boolean");
+ llvm::Function *FnExpect =
+ CGM.getIntrinsic(llvm::Intrinsic::expect, CondTy);
+ llvm::Value *ExpectedValueOfCond =
+ llvm::ConstantInt::getBool(CondTy, LH == Stmt::LH_Likely);
+ return Builder.CreateCall(FnExpect, {Cond, ExpectedValueOfCond},
+ Cond->getName() + ".expval");
}
llvm_unreachable("Unknown Likelihood");
}
-
-llvm::MDNode *CodeGenFunction::createBranchWeights(Stmt::Likelihood LH) const {
- Optional<std::pair<uint32_t, uint32_t>> LHW = getLikelihoodWeights(LH);
- if (!LHW)
- return nullptr;
-
- llvm::MDBuilder MDHelper(CGM.getLLVMContext());
- return MDHelper.createBranchWeights(LHW->first, LHW->second);
-}
-
-llvm::MDNode *CodeGenFunction::createProfileOrBranchWeightsForLoop(
- const Stmt *Cond, uint64_t LoopCount, const Stmt *Body) const {
- llvm::MDNode *Weights = createProfileWeightsForLoop(Cond, LoopCount);
- if (!Weights && CGM.getCodeGenOpts().OptimizationLevel)
- Weights = createBranchWeights(Stmt::getLikelihood(Body));
-
- return Weights;
-}