Index: clang/lib/CodeGen/CGStmt.cpp =================================================================== --- clang/lib/CodeGen/CGStmt.cpp +++ clang/lib/CodeGen/CGStmt.cpp @@ -672,17 +672,8 @@ LikelihoodAttributeFinder(const Stmt *S) { Visit(S); } void VisitAttributedStmt(const AttributedStmt *S) { - for (const auto *A : S->getAttrs()) { - if (isa(A)) { - Result = Likely; - return; - } - if (isa(A)) { - Result = Unlikely; - return; - } - } - Visit(S->getSubStmt()); + if (!ProcessLikelihoodAttribute(S->getAttrs())) + Visit(S->getSubStmt()); } void VisitCompoundStmt(const CompoundStmt *CS) { @@ -692,8 +683,28 @@ return; } } + void VisitGotoStmt(const GotoStmt *GS) { + // Decl::getAttrs requires Decl::hasAttrs() == true. + const LabelDecl *LD = GS->getLabel(); + if (LD->hasAttrs()) + ProcessLikelihoodAttribute(LD->getAttrs()); + } void VisitStmt(const Stmt *) {} + + bool ProcessLikelihoodAttribute(const ArrayRef &Attrs) { + for (const auto *A : Attrs) { + if (isa(A)) { + Result = Likely; + return true; + } + if (isa(A)) { + Result = Unlikely; + return true; + } + } + return false; + } }; } // end anonymous namespace Index: clang/lib/Sema/SemaDeclAttr.cpp =================================================================== --- clang/lib/Sema/SemaDeclAttr.cpp +++ clang/lib/Sema/SemaDeclAttr.cpp @@ -6410,6 +6410,29 @@ D->addAttr(::new (S.Context) DeprecatedAttr(S.Context, AL, Str, Replacement)); } +static bool validateLikelihoodAttr(Sema &S, Decl *D, const ParsedAttr &A) { + if (!isa(D)) { + S.Diag(A.getRange().getBegin(), diag::err_stmt_attribute_invalid_on_decl) + << A << D->getBeginLoc(); + return false; + } + + if (!S.getLangOpts().CPlusPlus20 && A.isCXX11Attribute() && !A.getScopeName()) + S.Diag(A.getLoc(), diag::ext_cxx20_attr) << A << A.getRange(); + + return true; +} + +static void handleLikelyAttr(Sema &S, Decl *D, const ParsedAttr &A) { + if (validateLikelihoodAttr(S, D, A)) + D->addAttr(::new (S.Context) LikelyAttr(S.Context, A)); +} + +static void handleUnlikelyAttr(Sema &S, Decl *D, const ParsedAttr &A) { + if (validateLikelihoodAttr(S, D, A)) + D->addAttr(::new (S.Context) UnlikelyAttr(S.Context, A)); +} + static bool isGlobalVar(const Decl *D) { if (const auto *S = dyn_cast(D)) return S->hasGlobalStorage(); @@ -6943,6 +6966,12 @@ case ParsedAttr::AT_Deprecated: handleDeprecatedAttr(S, D, AL); break; + case ParsedAttr::AT_Likely: + handleLikelyAttr(S, D, AL); + break; + case ParsedAttr::AT_Unlikely: + handleUnlikelyAttr(S, D, AL); + break; case ParsedAttr::AT_Destructor: if (S.Context.getTargetInfo().getTriple().isOSAIX()) llvm::report_fatal_error("'destructor' attribute is not yet supported on AIX"); Index: clang/test/CodeGenCXX/attr-likelihood-if-branch-weights.cpp =================================================================== --- clang/test/CodeGenCXX/attr-likelihood-if-branch-weights.cpp +++ clang/test/CodeGenCXX/attr-likelihood-if-branch-weights.cpp @@ -125,7 +125,45 @@ // Make sure the branches aren't optimized away. b = true; } + + // CHECK: br {{.*}} !prof !8 + if (b) { + goto uend; + } else { + // Make sure the branches aren't optimized away. + b = true; + } + + // CHECK: br {{.*}} !prof !7 + if (b) { + goto lend; + } else { + // Make sure the branches aren't optimized away. + b = true; + } + + // CHECK: br {{.*}} !prof !8 + if (b) { + goto ugcc; + } else { + // Make sure the branches aren't optimized away. + b = true; + } + + // CHECK: br {{.*}} !prof !7 + if (b) { + goto lgcc; + } else { + // Make sure the branches aren't optimized away. + b = true; + } end:; +[[unlikely]] uend:; +[[likely]] lend:; +// GCC attributes are handled in a special way, make sure the likelihood +// attributes aren't ignored. +[[unlikely]] ugcc: __attribute__((unused));; +[[likely]] lgcc: __attribute__((unused));; } void ReturnStmt() { Index: clang/test/Sema/attr-likelihood.c =================================================================== --- clang/test/Sema/attr-likelihood.c +++ clang/test/Sema/attr-likelihood.c @@ -43,8 +43,7 @@ if (x) goto lbl; - // FIXME: allow the attribute on the label - [[clang::unlikely]] lbl : // expected-error {{'unlikely' attribute cannot be applied to a declaration}} + [[clang::unlikely]] lbl : [[clang::likely]] x = x + 1; [[clang::likely]]++ x; Index: clang/test/SemaCXX/attr-likelihood.cpp =================================================================== --- clang/test/SemaCXX/attr-likelihood.cpp +++ clang/test/SemaCXX/attr-likelihood.cpp @@ -115,8 +115,7 @@ if (x) goto lbl; - // FIXME: allow the attribute on the label - [[unlikely]] lbl : // expected-error {{'unlikely' attribute cannot be applied to a declaration}} + [[likely]] lbl : [[likely]] x = x + 1; [[likely]]++ x;