Index: clang/include/clang/Basic/Attr.td =================================================================== --- clang/include/clang/Basic/Attr.td +++ clang/include/clang/Basic/Attr.td @@ -1284,6 +1284,16 @@ let Documentation = [FallthroughDocs]; } +def Likely : StmtAttr { + let Spellings = [CXX11<"", "likely", 201803>]; + let Documentation = [LikelihoodDocs]; +} + +def Unlikely : StmtAttr { + let Spellings = [CXX11<"", "unlikely", 201803>]; + let Documentation = [LikelihoodDocs]; +} + def NoMerge : StmtAttr { let Spellings = [Clang<"nomerge">]; let Documentation = [NoMergeDocs]; Index: clang/include/clang/Basic/AttrDocs.td =================================================================== --- clang/include/clang/Basic/AttrDocs.td +++ clang/include/clang/Basic/AttrDocs.td @@ -1683,6 +1683,46 @@ }]; } +def LikelihoodDocs : Documentation { + let Category = DocCatStmt; + let Heading = "likely and unlikely"; + let Content = [{ +The ``likely`` and ``unlikely`` attributes are used as compiler hints. When +the next executed statement depends on a condition this attribute can +annotate all possible statements with either ``likely`` or ``unlikely``. +Using ``likely`` will hint the statement is more likely to be executed. +Using ``unlikely`` will hint the statement is less likely to be executed. + +It's not allowed to annotate a statement with both ``likely`` and +``unlikely``. It's not recommended to annotate both branches of an ``if`` +statement with an attribute. + +These attributes have no effect when using PGO or optimization level 0. + +At the moment the attribute is only implemented for an ``if`` statement. + +Here is an example: + +.. code-block:: c++ + + // compile with -Wimplicit-fallthrough + if (b) [[likely]] { + // The compiler will optimize to execute the code here. + } else { + } + + if (b) [[unlikely]] { + } else { + // The compiler will optimize to execute the code here. + } + + if (b) { + } else [[likely]] { + // The compiler will optimize to execute the code here. + } + }]; +} + def ARMInterruptDocs : Documentation { let Category = DocCatFunction; let Heading = "interrupt (ARM)"; Index: clang/include/clang/Basic/DiagnosticGroups.td =================================================================== --- clang/include/clang/Basic/DiagnosticGroups.td +++ clang/include/clang/Basic/DiagnosticGroups.td @@ -656,8 +656,10 @@ def IndependentClassAttribute : DiagGroup<"IndependentClass-attribute">; def UnknownAttributes : DiagGroup<"unknown-attributes">; def IgnoredAttributes : DiagGroup<"ignored-attributes">; +def LikelihoodAttributeIf : DiagGroup<"likelihood-attribute-if">; def Attributes : DiagGroup<"attributes", [UnknownAttributes, - IgnoredAttributes]>; + IgnoredAttributes, + LikelihoodAttributeIf]>; def UnknownSanitizers : DiagGroup<"unknown-sanitizers">; def UnnamedTypeTemplateArgs : DiagGroup<"unnamed-type-template-args", [CXX98CompatUnnamedTypeTemplateArgs]>; @@ -889,6 +891,7 @@ Implicit, InfiniteRecursion, IntInBoolContext, + LikelihoodAttributeIf, MismatchedTags, MissingBraces, Move, Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2396,6 +2396,15 @@ // C++11 attributes def err_repeat_attribute : Error<"%0 attribute cannot be repeated">; +def err_attribute_compatibility : Error< + "incompatible attributes '%0' and '%1'">; +def note_attribute_compatibility_here : Note< + "attribute '%0' declarered here">; +def warn_attribute_likelihood_if_duplicated : Warning< + "attribute '%0' found in both true and false branch">, + InGroup, DefaultIgnore; +def note_attribute_likelihood_if_duplicated_here : Note< + "attribute '%0' in %select{true|false}1 branch declared here">; // C++11 final def err_final_function_overridden : Error< Index: clang/lib/CodeGen/CGStmt.cpp =================================================================== --- clang/lib/CodeGen/CGStmt.cpp +++ clang/lib/CodeGen/CGStmt.cpp @@ -27,6 +27,7 @@ #include "llvm/IR/Intrinsics.h" #include "llvm/IR/MDBuilder.h" #include "llvm/Support/SaveAndRestore.h" +#include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h" using namespace clang; using namespace CodeGen; @@ -652,6 +653,50 @@ EmitBranch(IndGotoBB); } +static std::pair getLikelihood(const Stmt *Stmt) { + auto R = std::make_pair(false, false); + auto *AS = dyn_cast(Stmt); + if (!AS) + return R; + + for (const auto *A : AS->getAttrs()) { + if (isa(A)) { + R.first = true; + return R; + } + if (isa(A)) { + R.second = true; + return R; + } + } + return R; +} + +static Optional> +getLikelihoodWeights(const Stmt *Then, const Stmt *Else) { + assert(Then && "IfStmt without a ThenStmt"); + + // The code doesn't protect against the same attribute on both branches. + // The frontend already issued a diagnostic. + std::pair LH = getLikelihood(Then); + if (LH.first) + return std::pair(llvm::LikelyBranchWeight, + llvm::UnlikelyBranchWeight); + if (LH.second) + return std::pair(llvm::UnlikelyBranchWeight, + llvm::LikelyBranchWeight); + if (Else) { + LH = LH = getLikelihood(Else); + if (LH.first) + return std::pair(llvm::UnlikelyBranchWeight, + llvm::LikelyBranchWeight); + if (LH.second) + return std::pair(llvm::LikelyBranchWeight, + llvm::UnlikelyBranchWeight); + } + return Optional>{}; +} + void CodeGenFunction::EmitIfStmt(const IfStmt &S) { // C99 6.8.4.1: The first substatement is executed if the expression compares // unequal to 0. The condition must be a scalar type. @@ -695,8 +740,21 @@ if (S.getElse()) ElseBlock = createBasicBlock("if.else"); - EmitBranchOnBoolExpr(S.getCond(), ThenBlock, ElseBlock, - getProfileCount(S.getThen())); + // Prefer the PGO based weights over the likelihood attribute. + // When the build isn't optimized the metadata isn't used, so don't generate + // it. + llvm::MDNode *Weights = nullptr; + uint64_t Count = getProfileCount(S.getThen()); + if (!Count && CGM.getCodeGenOpts().OptimizationLevel) { + Optional> LHW = + getLikelihoodWeights(S.getThen(), S.getElse()); + if (LHW) { + llvm::MDBuilder MDHelper(CGM.getLLVMContext()); + Weights = MDHelper.createBranchWeights(LHW->first, LHW->second); + } + } + + EmitBranchOnBoolExpr(S.getCond(), ThenBlock, ElseBlock, Count, Weights); // Emit the 'then' code. EmitBlock(ThenBlock); Index: clang/lib/CodeGen/CodeGenFunction.h =================================================================== --- clang/lib/CodeGen/CodeGenFunction.h +++ clang/lib/CodeGen/CodeGenFunction.h @@ -4360,7 +4360,8 @@ /// TrueCount should be the number of times we expect the condition to /// evaluate to true based on PGO data. void EmitBranchOnBoolExpr(const Expr *Cond, llvm::BasicBlock *TrueBlock, - llvm::BasicBlock *FalseBlock, uint64_t TrueCount); + llvm::BasicBlock *FalseBlock, uint64_t TrueCount, + llvm::MDNode *Weights = nullptr); /// Given an assignment `*LHS = RHS`, emit a test that checks if \p RHS is /// nonnull, if \p LHS is marked _Nonnull. Index: clang/lib/CodeGen/CodeGenFunction.cpp =================================================================== --- clang/lib/CodeGen/CodeGenFunction.cpp +++ clang/lib/CodeGen/CodeGenFunction.cpp @@ -1462,16 +1462,15 @@ return true; } - - /// 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. void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock, - uint64_t TrueCount) { + uint64_t TrueCount, + llvm::MDNode *Weights) { Cond = Cond->IgnoreParens(); if (const BinaryOperator *CondBOp = dyn_cast(Cond)) { @@ -1486,7 +1485,7 @@ // br(1 && X) -> br(X). incrementProfileCounter(CondBOp); return EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock, - TrueCount); + TrueCount, Weights); } // If we have "X && 1", simplify the code to use an uncond branch. @@ -1495,7 +1494,7 @@ ConstantBool) { // br(X && 1) -> br(X). return EmitBranchOnBoolExpr(CondBOp->getLHS(), TrueBlock, FalseBlock, - TrueCount); + TrueCount, Weights); } // Emit the LHS as a conditional. If the LHS conditional is false, we @@ -1508,7 +1507,8 @@ ConditionalEvaluation eval(*this); { ApplyDebugLocation DL(*this, Cond); - EmitBranchOnBoolExpr(CondBOp->getLHS(), LHSTrue, FalseBlock, RHSCount); + EmitBranchOnBoolExpr(CondBOp->getLHS(), LHSTrue, FalseBlock, RHSCount, + Weights); EmitBlock(LHSTrue); } @@ -1517,7 +1517,8 @@ // Any temporaries created here are conditional. eval.begin(*this); - EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock, TrueCount); + EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock, TrueCount, + Weights); eval.end(*this); return; @@ -1532,7 +1533,7 @@ // br(0 || X) -> br(X). incrementProfileCounter(CondBOp); return EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock, - TrueCount); + TrueCount, Weights); } // If we have "X || 0", simplify the code to use an uncond branch. @@ -1541,7 +1542,7 @@ !ConstantBool) { // br(X || 0) -> br(X). return EmitBranchOnBoolExpr(CondBOp->getLHS(), TrueBlock, FalseBlock, - TrueCount); + TrueCount, Weights); } // Emit the LHS as a conditional. If the LHS conditional is true, we @@ -1557,7 +1558,8 @@ ConditionalEvaluation eval(*this); { ApplyDebugLocation DL(*this, Cond); - EmitBranchOnBoolExpr(CondBOp->getLHS(), TrueBlock, LHSFalse, LHSCount); + EmitBranchOnBoolExpr(CondBOp->getLHS(), TrueBlock, LHSFalse, LHSCount, + Weights); EmitBlock(LHSFalse); } @@ -1566,7 +1568,8 @@ // Any temporaries created here are conditional. eval.begin(*this); - EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock, RHSCount); + EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock, RHSCount, + Weights); eval.end(*this); @@ -1581,7 +1584,7 @@ uint64_t FalseCount = getCurrentProfileCount() - TrueCount; // Negate the condition and swap the destination blocks. return EmitBranchOnBoolExpr(CondUOp->getSubExpr(), FalseBlock, TrueBlock, - FalseCount); + FalseCount, Weights); } } @@ -1592,7 +1595,7 @@ ConditionalEvaluation cond(*this); EmitBranchOnBoolExpr(CondOp->getCond(), LHSBlock, RHSBlock, - getProfileCount(CondOp)); + getProfileCount(CondOp), Weights); // When computing PGO branch weights, we only know the overall count for // the true block. This code is essentially doing tail duplication of the @@ -1612,14 +1615,14 @@ { ApplyDebugLocation DL(*this, Cond); EmitBranchOnBoolExpr(CondOp->getLHS(), TrueBlock, FalseBlock, - LHSScaledTrueCount); + LHSScaledTrueCount, Weights); } cond.end(*this); cond.begin(*this); EmitBlock(RHSBlock); EmitBranchOnBoolExpr(CondOp->getRHS(), TrueBlock, FalseBlock, - TrueCount - LHSScaledTrueCount); + TrueCount - LHSScaledTrueCount, Weights); cond.end(*this); return; @@ -1650,9 +1653,10 @@ // Create branch weights based on the number of times we get here and the // number of times the condition should be true. - uint64_t CurrentCount = std::max(getCurrentProfileCount(), TrueCount); - llvm::MDNode *Weights = - createProfileWeights(TrueCount, CurrentCount - TrueCount); + 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; Index: clang/lib/Parse/ParseDeclCXX.cpp =================================================================== --- clang/lib/Parse/ParseDeclCXX.cpp +++ clang/lib/Parse/ParseDeclCXX.cpp @@ -4018,6 +4018,8 @@ case ParsedAttr::AT_FallThrough: case ParsedAttr::AT_CXX11NoReturn: case ParsedAttr::AT_NoUniqueAddress: + case ParsedAttr::AT_Likely: + case ParsedAttr::AT_Unlikely: return true; case ParsedAttr::AT_WarnUnusedResult: return !ScopeName && AttrName->getName().equals("nodiscard"); Index: clang/lib/Sema/SemaStmt.cpp =================================================================== --- clang/lib/Sema/SemaStmt.cpp +++ clang/lib/Sema/SemaStmt.cpp @@ -574,6 +574,50 @@ }; } +static void CheckIfStmtLikelihood(Sema &S, SourceLocation IfLoc, Stmt *ThenStmt, + Stmt *ElseStmt) { + auto *Then = dyn_cast(ThenStmt); + auto *Else = dyn_cast(ElseStmt); + if (!Then || !Else) + return; + + // Warn when both the true and false branch of an if statement have the same + // likelihood attribute. It's not prohibited, but makes no sense. + const LikelyAttr *Likely = nullptr; + const UnlikelyAttr *Unlikely = nullptr; + for (const auto *A : Then->getAttrs()) { + if (auto *LA = dyn_cast(A)) + Likely = LA; + else if (auto *UA = dyn_cast(A)) + Unlikely = UA; + } + + for (const auto *A : Else->getAttrs()) { + if (isa(A) && Likely) { + S.Diag(IfLoc, diag::warn_attribute_likelihood_if_duplicated) + << A->getSpelling(); + S.Diag(Likely->getLocation(), + diag::note_attribute_likelihood_if_duplicated_here) + << Likely->getSpelling() << /*branch=*/0 << Likely->getRange(); + S.Diag(A->getLocation(), + diag::note_attribute_likelihood_if_duplicated_here) + << A->getSpelling() << /*branch=*/1 << A->getRange(); + return; + } + if (isa(A) && Unlikely) { + S.Diag(IfLoc, diag::warn_attribute_likelihood_if_duplicated) + << A->getSpelling(); + S.Diag(Unlikely->getLocation(), + diag::note_attribute_likelihood_if_duplicated_here) + << Unlikely->getSpelling() << /*branch=*/0 << Unlikely->getRange(); + S.Diag(A->getLocation(), + diag::note_attribute_likelihood_if_duplicated_here) + << A->getSpelling() << /*branch=*/1 << A->getRange(); + return; + } + } +} + StmtResult Sema::ActOnIfStmt(SourceLocation IfLoc, bool IsConstexpr, Stmt *InitStmt, ConditionResult Cond, @@ -596,6 +640,8 @@ if (!elseStmt) DiagnoseEmptyStmtBody(CondExpr->getEndLoc(), thenStmt, diag::warn_empty_if_body); + else + CheckIfStmtLikelihood(*this, IfLoc, thenStmt, elseStmt); return BuildIfStmt(IfLoc, IsConstexpr, InitStmt, Cond, thenStmt, ElseLoc, elseStmt); Index: clang/lib/Sema/SemaStmtAttr.cpp =================================================================== --- clang/lib/Sema/SemaStmtAttr.cpp +++ clang/lib/Sema/SemaStmtAttr.cpp @@ -210,6 +210,24 @@ return ::new (S.Context) NoMergeAttr(S.Context, A); } +static Attr *handleLikely(Sema &S, Stmt *St, const ParsedAttr &A, + SourceRange Range) { + + if (!S.getLangOpts().CPlusPlus20 && A.isCXX11Attribute() && !A.getScopeName()) + S.Diag(A.getLoc(), diag::ext_cxx20_attr) << A << Range; + + return ::new (S.Context) LikelyAttr(S.Context, A); +} + +static Attr *handleUnlikely(Sema &S, Stmt *St, const ParsedAttr &A, + SourceRange Range) { + + if (!S.getLangOpts().CPlusPlus20 && A.isCXX11Attribute() && !A.getScopeName()) + S.Diag(A.getLoc(), diag::ext_cxx20_attr) << A << Range; + + return ::new (S.Context) UnlikelyAttr(S.Context, A); +} + static void CheckForIncompatibleAttributes(Sema &S, const SmallVectorImpl &Attrs) { @@ -315,6 +333,34 @@ << CategoryState.NumericAttr->getDiagnosticName(Policy); } } + + // C++20 [dcl.attr.likelihood]p1 The attribute-token likely shall not appear + // in an attribute-specifier-seq that contains the attribute-token unlikely. + const LikelyAttr *Likely = nullptr; + const UnlikelyAttr *Unlikely = nullptr; + for (const auto *I : Attrs) { + if (const auto *Attr = dyn_cast(I)) { + if (Unlikely) { + S.Diag(Attr->getLocation(), diag::err_attribute_compatibility) + << Attr->getSpelling() << Unlikely->getSpelling() + << Attr->getRange(); + S.Diag(Unlikely->getLocation(), diag::note_attribute_compatibility_here) + << Unlikely->getSpelling() << Unlikely->getRange(); + + return; + } + Likely = Attr; + } else if (const auto *Attr = dyn_cast(I)) { + if (Likely) { + S.Diag(Attr->getLocation(), diag::err_attribute_compatibility) + << Attr->getSpelling() << Likely->getSpelling() << Attr->getRange(); + S.Diag(Likely->getLocation(), diag::note_attribute_compatibility_here) + << Likely->getSpelling() << Likely->getRange(); + return; + } + Unlikely = Attr; + } + } } static Attr *handleOpenCLUnrollHint(Sema &S, Stmt *St, const ParsedAttr &A, @@ -377,6 +423,10 @@ return handleSuppressAttr(S, St, A, Range); case ParsedAttr::AT_NoMerge: return handleNoMergeAttr(S, St, A, Range); + case ParsedAttr::AT_Likely: + return handleLikely(S, St, A, Range); + case ParsedAttr::AT_Unlikely: + return handleUnlikely(S, St, A, Range); default: // if we're here, then we parsed a known attribute, but didn't recognize // it as a statement attribute => it is declaration attribute Index: clang/test/CodeGenCXX/attr-likelihood-if-branch-weights.cpp =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/attr-likelihood-if-branch-weights.cpp @@ -0,0 +1,25 @@ +// RUN %clang_cc1 -O1 -emit-llvm %s -o - -triple=x86_64-linux-gnu | FileCheck -DLIKELY=2000 -DUNLIKELY=1 %s +// RUN: %clang_cc1 -O1 -emit-llvm %s -triple=x86_64-linux-gnu -mllvm -likely-branch-weight=99 -mllvm -unlikely-branch-weight=42 -o - | FileCheck -DLIKELY=99 -DUNLIKELY=42 %s + +extern bool b; +extern bool A(); +extern bool B(); + +bool f() { + // CHECK: br i1 %tobool.not, label %if.end, label %if.then, !prof !7 + if (b) [[likely]] { + return A(); + } + return B(); +} + +bool g() { + // CHECK: br i1 %tobool.not, label %if.end, label %if.then, !prof !8 + if (b) [[unlikely]] { + return A(); + } + return B(); +} + +// CHECK: !7 = !{!"branch_weights", i32 [[UNLIKELY]], i32 [[LIKELY]]} +// CHECK: !8 = !{!"branch_weights", i32 [[LIKELY]], i32 [[UNLIKELY]]} Index: clang/test/Misc/warning-wall.c =================================================================== --- clang/test/Misc/warning-wall.c +++ clang/test/Misc/warning-wall.c @@ -22,6 +22,7 @@ CHECK-NEXT: -Wimplicit-int CHECK-NEXT: -Winfinite-recursion CHECK-NEXT: -Wint-in-bool-context +CHECK-NEXT: -Wlikelihood-attribute-if CHECK-NEXT: -Wmismatched-tags CHECK-NEXT: -Wmissing-braces CHECK-NEXT: -Wmove Index: clang/test/Preprocessor/has_attribute.cpp =================================================================== --- clang/test/Preprocessor/has_attribute.cpp +++ clang/test/Preprocessor/has_attribute.cpp @@ -62,13 +62,13 @@ // FIXME(201806L) CHECK: ensures: 0 // FIXME(201806L) CHECK: expects: 0 // CHECK: fallthrough: 201603L -// FIXME(201803L) CHECK: likely: 0 +// CHECK: likely: 201803L // CHECK: maybe_unused: 201603L // ITANIUM: no_unique_address: 201803L // WINDOWS: no_unique_address: 0 // CHECK: nodiscard: 201907L // CHECK: noreturn: 200809L -// FIXME(201803L) CHECK: unlikely: 0 +// CHECK: unlikely: 201803L // Test for Microsoft __declspec attributes Index: clang/test/SemaCXX/attr-likelihood.cpp =================================================================== --- /dev/null +++ clang/test/SemaCXX/attr-likelihood.cpp @@ -0,0 +1,101 @@ +// RUN: %clang_cc1 %s -verify -Wlikelihood-attribute-if +// RUN: %clang_cc1 %s -verify -Wall +// RUN: %clang_cc1 %s -DPEDANTIC -pedantic -verify -Wlikelihood-attribute-if + +#if PEDANTIC +void g() +{ + if(true) + [[likely]] {} // expected-warning {{use of the 'likely' attribute is a C++20 extension}} + else + [[unlikely]] {} // expected-warning {{use of the 'unlikely' attribute is a C++20 extension}} +} +#else +void a() +{ + if(true) + [[likely]] // expected-note {{attribute 'likely' declarered here}} + [[unlikely]] // expected-error {{incompatible attributes 'unlikely' and 'likely'}} + ; +} + +void b() +{ + if(true) + [[unlikely]] // expected-note {{attribute 'unlikely' declarered here}} + [[likely]] // expected-error {{incompatible attributes 'likely' and 'unlikely'}} + ; +} + +void c() +{ + if(true) [[likely]] ; +} + +void d() +{ + if(true) [[unlikely]] ; +} + +void e() +{ + if(true) // expected-warning {{attribute 'likely' found in both true and false branch}} + [[likely]] {} // expected-note {{attribute 'likely' in true branch declared here}} + else + [[likely]] {} // expected-note {{attribute 'likely' in false branch declared here}} +} + +void f() +{ + if(true) // expected-warning {{attribute 'unlikely' found in both true and false branch}} + [[unlikely]] {} // expected-note {{attribute 'unlikely' in true branch declared here}} + else + [[unlikely]] {} // expected-note {{attribute 'unlikely' in false branch declared here}} +} + +void g() +{ + if(true) + [[likely]] {} + else + [[unlikely]] {} +} + +void h() +{ + if(true) + [[likely]] {} + else + {} +} + +void i() +{ + if(true) + [[unlikely]] {} + else + {} +} + +void j() +{ + if(true) {} + else + [[likely]] {} +} + +void k() +{ + if(true) {} + else + [[likely]] {} +} + +void l() +{ + if(true) + [[likely]] {} + else + [[unlikely]] if(false) [[likely]] {} +} +#endif Index: clang/www/cxx_status.html =================================================================== --- clang/www/cxx_status.html +++ clang/www/cxx_status.html @@ -987,7 +987,7 @@ [[likely]] and [[unlikely]] attributes P0479R5 - No + Clang 12 (partial) typename optional in more contexts Index: llvm/include/llvm/Transforms/Scalar/LowerExpectIntrinsic.h =================================================================== --- llvm/include/llvm/Transforms/Scalar/LowerExpectIntrinsic.h +++ llvm/include/llvm/Transforms/Scalar/LowerExpectIntrinsic.h @@ -17,6 +17,7 @@ #include "llvm/IR/Function.h" #include "llvm/IR/PassManager.h" +#include "llvm/Support/CommandLine.h" namespace llvm { @@ -31,6 +32,8 @@ PreservedAnalyses run(Function &F, FunctionAnalysisManager &); }; +extern cl::opt LikelyBranchWeight; +extern cl::opt UnlikelyBranchWeight; } #endif Index: llvm/lib/Transforms/Scalar/LowerExpectIntrinsic.cpp =================================================================== --- llvm/lib/Transforms/Scalar/LowerExpectIntrinsic.cpp +++ llvm/lib/Transforms/Scalar/LowerExpectIntrinsic.cpp @@ -24,7 +24,6 @@ #include "llvm/IR/Metadata.h" #include "llvm/InitializePasses.h" #include "llvm/Pass.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Utils/MisExpect.h" @@ -48,10 +47,10 @@ // 'select' instructions. It may be worthwhile to hoist these values to some // shared space, so they can be used directly by other passes. -static cl::opt LikelyBranchWeight( +cl::opt llvm::LikelyBranchWeight( "likely-branch-weight", cl::Hidden, cl::init(2000), cl::desc("Weight of the branch likely to be taken (default = 2000)")); -static cl::opt UnlikelyBranchWeight( +cl::opt llvm::UnlikelyBranchWeight( "unlikely-branch-weight", cl::Hidden, cl::init(1), cl::desc("Weight of the branch unlikely to be taken (default = 1)"));