[clang][IR] Add support for leaf attribute
This patch adds support for leaf attribute as an optimization hint
in Clang/LLVM.
Differential Revision: https://reviews.llvm.org/D90275
GitOrigin-RevId: 7c0e3a77bc43a9c4d05f68ffd4e84d0f75efbd91
diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td
index 79902c8..61eb86a 100644
--- a/include/clang/Basic/Attr.td
+++ b/include/clang/Basic/Attr.td
@@ -1448,6 +1448,13 @@
let Documentation = [LayoutVersionDocs];
}
+def Leaf : InheritableAttr {
+ let Spellings = [GCC<"leaf">];
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [LeafDocs];
+ let SimpleHandler = 1;
+}
+
def LifetimeBound : DeclOrTypeAttr {
let Spellings = [Clang<"lifetimebound", 0>];
let Subjects = SubjectList<[ParmVar, ImplicitObjectParameter], ErrorDiag>;
diff --git a/include/clang/Basic/AttrDocs.td b/include/clang/Basic/AttrDocs.td
index 28f35cf..e70596b 100644
--- a/include/clang/Basic/AttrDocs.td
+++ b/include/clang/Basic/AttrDocs.td
@@ -3976,6 +3976,22 @@
}];
}
+def LeafDocs : Documentation {
+ let Category = DocCatVariable;
+ let Content = [{
+
+The ``leaf`` attribute is used as a compiler hint to improve dataflow analysis
+in library functions. Functions marked with the ``leaf`` attribute are not allowed
+to jump back into the caller's translation unit, whether through invoking a
+callback function, an external function call, use of ``longjmp``, or other means.
+Therefore, they cannot use or modify any data that does not escape the caller function's
+compilation unit.
+
+For more information see
+`gcc documentation <https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html>`
+}];
+}
+
def NoStackProtectorDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index 5db34b6..73194be 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -1989,6 +1989,8 @@
FuncAttrs.addAttribute("no_caller_saved_registers");
if (TargetDecl->hasAttr<AnyX86NoCfCheckAttr>())
FuncAttrs.addAttribute(llvm::Attribute::NoCfCheck);
+ if (TargetDecl->hasAttr<LeafAttr>())
+ FuncAttrs.addAttribute(llvm::Attribute::NoCallback);
HasOptnone = TargetDecl->hasAttr<OptimizeNoneAttr>();
if (auto *AllocSize = TargetDecl->getAttr<AllocSizeAttr>()) {
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 1509485..395d0ef 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -7715,6 +7715,9 @@
case ParsedAttr::AT_AnyX86NoCfCheck:
handleNoCfCheckAttr(S, D, AL);
break;
+ case ParsedAttr::AT_Leaf:
+ handleSimpleAttribute<LeafAttr>(S, D, AL);
+ break;
case ParsedAttr::AT_NoThrow:
if (!AL.isUsedAsTypeAttr())
handleSimpleAttribute<NoThrowAttr>(S, D, AL);
diff --git a/test/CodeGen/attr-leaf.c b/test/CodeGen/attr-leaf.c
new file mode 100644
index 0000000..2b2bacf
--- /dev/null
+++ b/test/CodeGen/attr-leaf.c
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -Oz -o - %s | FileCheck %s
+
+// CHECK: define void @f() local_unnamed_addr [[ATTRS:#[0-9]+]] {
+void f() __attribute__((leaf));
+
+void f()
+{
+}
+
+// CHECK: attributes [[ATTRS]] = { {{.*}}nocallback{{.*}} }
diff --git a/test/Misc/pragma-attribute-supported-attributes-list.test b/test/Misc/pragma-attribute-supported-attributes-list.test
index 0ba6769..cb1e482 100644
--- a/test/Misc/pragma-attribute-supported-attributes-list.test
+++ b/test/Misc/pragma-attribute-supported-attributes-list.test
@@ -68,6 +68,7 @@
// CHECK-NEXT: InitPriority (SubjectMatchRule_variable)
// CHECK-NEXT: InternalLinkage (SubjectMatchRule_variable, SubjectMatchRule_function, SubjectMatchRule_record)
// CHECK-NEXT: LTOVisibilityPublic (SubjectMatchRule_record)
+// CHECK-NEXT: Leaf (SubjectMatchRule_function)
// CHECK-NEXT: LoaderUninitialized (SubjectMatchRule_variable_is_global)
// CHECK-NEXT: Lockable (SubjectMatchRule_record)
// CHECK-NEXT: MIGServerRoutine (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_block)
diff --git a/test/Sema/attr-leaf.c b/test/Sema/attr-leaf.c
new file mode 100644
index 0000000..a28ad79
--- /dev/null
+++ b/test/Sema/attr-leaf.c
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -verify -fsyntax-only %s
+
+void f1() __attribute__((leaf));
+
+void f2() __attribute__((leaf("abc"))); // expected-error {{'leaf' attribute takes no argument}}
+
+int var __attribute__ ((leaf())); // expected-warning {{'leaf' attribute only applies to functions}}
+
+// FIXME: Might diagnose a warning if leaf attribute is used in function definition
+// The leaf attribute has no effect on functions defined within the current compilation unit
+__attribute__((leaf)) void f3() {
+}