Mordante created this revision.
Mordante added reviewers: rsmith, rjmccall, aaron.ballman.
Mordante added a project: clang.
Herald added a subscriber: cfe-commits.
Mordante requested review of this revision.

Allows the likelihood attributes on label, which are not part of a case 
statement. When a `goto` is used it accepts the attribute placed on the target 
label.

Depends on D85091 <https://reviews.llvm.org/D85091>.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D86559

Files:
  clang/lib/CodeGen/CGStmt.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/test/CodeGenCXX/attr-likelihood-if-branch-weights.cpp
  clang/test/Sema/attr-likelihood.c
  clang/test/SemaCXX/attr-likelihood.cpp

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;
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/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/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<LabelDecl>(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<VarDecl>(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/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<LikelyAttr>(A)) {
-        Result = Likely;
-        return;
-      }
-      if (isa<UnlikelyAttr>(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<const clang::Attr *> &Attrs) {
+    for (const auto *A : Attrs) {
+      if (isa<LikelyAttr>(A)) {
+        Result = Likely;
+        return true;
+      }
+      if (isa<UnlikelyAttr>(A)) {
+        Result = Unlikely;
+        return true;
+      }
+    }
+    return false;
+  }
 };
 } // end anonymous namespace
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to