From: Nick Desaulniers Date: Fri, 18 Jun 2021 20:33:44 +0000 (-0700) Subject: [Clang][Codegen] Add GNU function attribute 'no_profile' and lower it to noprofile X-Git-Tag: llvmorg-14-init~3586 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=193e41c987127aad86d0380df83e67a85266f1f1;p=platform%2Fupstream%2Fllvm.git [Clang][Codegen] Add GNU function attribute 'no_profile' and lower it to noprofile noprofile IR attribute already exists to prevent profiling with PGO; emit that when a function uses the newly added no_profile function attribute. The Linux kernel would like to avoid compiler generated code in functions annotated with such attribute. We already respect this for libcalls to fentry() and mcount(). Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80223 Link: https://lore.kernel.org/lkml/CAKwvOdmPTi93n2L0_yQkrzLdmpxzrOR7zggSzonyaw2PGshApw@mail.gmail.com/ Reviewed By: MaskRay, void, phosek, aaron.ballman Differential Revision: https://reviews.llvm.org/D104475 --- diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 7146210..8829b4b 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1970,6 +1970,13 @@ def NoInstrumentFunction : InheritableAttr { let SimpleHandler = 1; } +def NoProfileFunction : InheritableAttr { + let Spellings = [Clang<"no_profile">]; + let Subjects = SubjectList<[Function]>; + let Documentation = [NoProfileDocs]; + let SimpleHandler = 1; +} + def NotTailCalled : InheritableAttr { let Spellings = [Clang<"not_tail_called">]; let Subjects = SubjectList<[Function]>; diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 6594e77..6173c8c 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -2559,6 +2559,17 @@ This attribute accepts a single parameter that must be one of the following: }]; } +def NoProfileDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +Use the ``no_profile`` attribute on a function declaration to denote that the +compiler should not instrument the function with profile-related +instrumentation, such as via the +``-fprofile-generate`` / ``-fprofile-instr-generate`` / +``-fcs-profile-generate`` / ``-fprofile-arcs`` flags. +}]; +} + def NoSanitizeDocs : Documentation { let Category = DocCatFunction; let Content = [{ diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 518305e..97288d0 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -893,6 +893,9 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, if (D && D->hasAttr()) Fn->addFnAttr("cfi-canonical-jump-table"); + if (D && D->hasAttr()) + Fn->addFnAttr(llvm::Attribute::NoProfile); + if (getLangOpts().OpenCL) { // Add metadata for a kernel function. if (const FunctionDecl *FD = dyn_cast_or_null(D)) diff --git a/clang/test/CodeGen/no_profile.c b/clang/test/CodeGen/no_profile.c new file mode 100644 index 0000000..5ac116b --- /dev/null +++ b/clang/test/CodeGen/no_profile.c @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -fprofile-instrument=llvm -disable-llvm-passes \ +// RUN: -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fprofile-instrument=csllvm -disable-llvm-passes \ +// RUN: -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fprofile-instrument=clang -disable-llvm-passes \ +// RUN: -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fprofile-arcs -disable-llvm-passes \ +// RUN: -emit-llvm -o - %s | FileCheck %s +int g(int); + +void __attribute__((no_profile)) no_instr() { +// CHECK: define {{.*}} void @no_instr() [[ATTR:#[0-9]+]] +} + +void instr(void) { +// CHECK: define {{.*}} void @instr() [[ATTR2:#[0-9]+]] +} +// CHECK: attributes [[ATTR]] = {{.*}} noprofile +// CHECK: attributes [[ATTR2]] = { +// CHECK-NOT: noprofile +// CHECK: } diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index 8256f12..290306b 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -99,6 +99,7 @@ // CHECK-NEXT: NoMerge (SubjectMatchRule_function) // CHECK-NEXT: NoMicroMips (SubjectMatchRule_function) // CHECK-NEXT: NoMips16 (SubjectMatchRule_function) +// CHECK-NEXT: NoProfileFunction (SubjectMatchRule_function) // CHECK-NEXT: NoSanitize (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_variable_is_global) // CHECK-NEXT: NoSanitizeSpecific (SubjectMatchRule_function, SubjectMatchRule_variable_is_global) // CHECK-NEXT: NoSpeculativeLoadHardening (SubjectMatchRule_function, SubjectMatchRule_objc_method) diff --git a/clang/test/Sema/no_profile-attribute.c b/clang/test/Sema/no_profile-attribute.c new file mode 100644 index 0000000..b3c073f1 --- /dev/null +++ b/clang/test/Sema/no_profile-attribute.c @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 %s -fsyntax-only -verify +__attribute__((no_profile)) +void no_profile0(void); +#if !__has_attribute(no_profile) +#error "Where did the no_profile function attribute go?" +#endif + +void no_profile1(__attribute__((no_profile)) int param); // expected-warning {{'no_profile' attribute only applies to functions}} +__attribute__((no_profile(""))) // expected-error {{'no_profile' attribute takes no arguments}} +void no_profile2(void); +void no_profile3(void) { + __attribute__((no_profile)); // expected-error {{'no_profile' attribute cannot be applied to a statement}} +}