diff options
author | Roman Lebedev <lebedev.ri@gmail.com> | 2021-03-21 22:13:47 +0300 |
---|---|---|
committer | Roman Lebedev <lebedev.ri@gmail.com> | 2021-03-21 22:50:21 +0300 |
commit | e3a470162738871bba982416748ae5f5e3572947 (patch) | |
tree | 91128665e388d02ee455879014cee60923318fe0 /clang/lib/CodeGen/CodeGenFunction.cpp | |
parent | 37d6be90524ca1659521ab879aaae5e5501f1e97 (diff) | |
download | llvm-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.cpp | 89 |
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; -} |