Author: Gulfem Savrun Yeniceri Date: 2020-12-14T14:48:17-08:00 New Revision: 7c0e3a77bc43a9c4d05f68ffd4e84d0f75efbd91
URL: https://github.com/llvm/llvm-project/commit/7c0e3a77bc43a9c4d05f68ffd4e84d0f75efbd91 DIFF: https://github.com/llvm/llvm-project/commit/7c0e3a77bc43a9c4d05f68ffd4e84d0f75efbd91.diff LOG: [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 Added: clang/test/CodeGen/attr-leaf.c clang/test/Sema/attr-leaf.c Modified: clang/include/clang/Basic/Attr.td clang/include/clang/Basic/AttrDocs.td clang/lib/CodeGen/CGCall.cpp clang/lib/Sema/SemaDeclAttr.cpp clang/test/Misc/pragma-attribute-supported-attributes-list.test llvm/include/llvm/Bitcode/LLVMBitCodes.h llvm/include/llvm/IR/Attributes.td llvm/lib/AsmParser/LLLexer.cpp llvm/lib/AsmParser/LLParser.cpp llvm/lib/AsmParser/LLToken.h llvm/lib/Bitcode/Reader/BitcodeReader.cpp llvm/lib/Bitcode/Writer/BitcodeWriter.cpp llvm/lib/IR/Attributes.cpp llvm/lib/IR/Verifier.cpp llvm/lib/Transforms/Utils/CodeExtractor.cpp llvm/test/Bitcode/attributes.ll Removed: ################################################################################ diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 79902c8f5b89..61eb86ac81a1 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1448,6 +1448,13 @@ def LayoutVersion : InheritableAttr, TargetSpecificAttr<TargetMicrosoftCXXABI> { 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/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 28f35cf2c0c7..e70596b5ac28 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -3976,6 +3976,22 @@ are used to instantiate the specialization. }]; } +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/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 5db34b693bf3..73194be922dd 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1989,6 +1989,8 @@ void CodeGenModule::ConstructAttributeList( 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/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 15094854300d..395d0ef57945 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -7715,6 +7715,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, 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/clang/test/CodeGen/attr-leaf.c b/clang/test/CodeGen/attr-leaf.c new file mode 100644 index 000000000000..2b2bacf5e725 --- /dev/null +++ b/clang/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/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index 0ba6769a1a8a..cb1e48217a81 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/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/clang/test/Sema/attr-leaf.c b/clang/test/Sema/attr-leaf.c new file mode 100644 index 000000000000..a28ad79ae791 --- /dev/null +++ b/clang/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() { +} diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h index 80fa4ac97d0d..a6d28024e2e5 100644 --- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -653,6 +653,7 @@ enum AttributeKindCodes { ATTR_KIND_NOUNDEF = 68, ATTR_KIND_BYREF = 69, ATTR_KIND_MUSTPROGRESS = 70, + ATTR_KIND_NO_CALLBACK = 71, }; enum ComdatSelectionKindCodes { diff --git a/llvm/include/llvm/IR/Attributes.td b/llvm/include/llvm/IR/Attributes.td index 762f4d69b795..30d297563cb1 100644 --- a/llvm/include/llvm/IR/Attributes.td +++ b/llvm/include/llvm/IR/Attributes.td @@ -103,6 +103,9 @@ def NoAlias : EnumAttr<"noalias">; /// Callee isn't recognized as a builtin. def NoBuiltin : EnumAttr<"nobuiltin">; +/// Function cannot enter into caller's translation unit. +def NoCallback : EnumAttr<"nocallback">; + /// Function creates no aliases of pointer. def NoCapture : EnumAttr<"nocapture">; diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp index baabd553fbdf..c50e824d6f18 100644 --- a/llvm/lib/AsmParser/LLLexer.cpp +++ b/llvm/lib/AsmParser/LLLexer.cpp @@ -653,6 +653,7 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(nest); KEYWORD(noalias); KEYWORD(nobuiltin); + KEYWORD(nocallback); KEYWORD(nocapture); KEYWORD(noduplicate); KEYWORD(nofree); diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 675151e6e147..0c2c10700d78 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -1353,6 +1353,9 @@ bool LLParser::parseFnAttributeValuePairs(AttrBuilder &B, break; case lltok::kw_naked: B.addAttribute(Attribute::Naked); break; case lltok::kw_nobuiltin: B.addAttribute(Attribute::NoBuiltin); break; + case lltok::kw_nocallback: + B.addAttribute(Attribute::NoCallback); + break; case lltok::kw_noduplicate: B.addAttribute(Attribute::NoDuplicate); break; case lltok::kw_nofree: B.addAttribute(Attribute::NoFree); break; case lltok::kw_noimplicitfloat: diff --git a/llvm/lib/AsmParser/LLToken.h b/llvm/lib/AsmParser/LLToken.h index 7dd0fdab2cbf..32e1165c7745 100644 --- a/llvm/lib/AsmParser/LLToken.h +++ b/llvm/lib/AsmParser/LLToken.h @@ -200,6 +200,7 @@ enum Kind { kw_noalias, kw_noundef, kw_nobuiltin, + kw_nocallback, kw_nocapture, kw_noduplicate, kw_nofree, diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 158f8d177d66..43e4fca007c6 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1433,6 +1433,8 @@ static Attribute::AttrKind getAttrFromCode(uint64_t Code) { return Attribute::NoAlias; case bitc::ATTR_KIND_NO_BUILTIN: return Attribute::NoBuiltin; + case bitc::ATTR_KIND_NO_CALLBACK: + return Attribute::NoCallback; case bitc::ATTR_KIND_NO_CAPTURE: return Attribute::NoCapture; case bitc::ATTR_KIND_NO_DUPLICATE: diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index 5c13738fad61..5b965186daa8 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -646,6 +646,8 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) { return bitc::ATTR_KIND_NO_ALIAS; case Attribute::NoBuiltin: return bitc::ATTR_KIND_NO_BUILTIN; + case Attribute::NoCallback: + return bitc::ATTR_KIND_NO_CALLBACK; case Attribute::NoCapture: return bitc::ATTR_KIND_NO_CAPTURE; case Attribute::NoDuplicate: diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp index 82350ad6d29b..fc0d68ebc729 100644 --- a/llvm/lib/IR/Attributes.cpp +++ b/llvm/lib/IR/Attributes.cpp @@ -371,6 +371,8 @@ std::string Attribute::getAsString(bool InAttrGrp) const { return "noalias"; if (hasAttribute(Attribute::NoBuiltin)) return "nobuiltin"; + if (hasAttribute(Attribute::NoCallback)) + return "nocallback"; if (hasAttribute(Attribute::NoCapture)) return "nocapture"; if (hasAttribute(Attribute::NoDuplicate)) diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index ac44a95d7da5..71bb94e77593 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -1597,6 +1597,7 @@ static bool isFuncOnlyAttr(Attribute::AttrKind Kind) { case Attribute::NoReturn: case Attribute::NoSync: case Attribute::WillReturn: + case Attribute::NoCallback: case Attribute::NoCfCheck: case Attribute::NoUnwind: case Attribute::NoInline: diff --git a/llvm/lib/Transforms/Utils/CodeExtractor.cpp b/llvm/lib/Transforms/Utils/CodeExtractor.cpp index 1d01e40843c5..91297b8dea19 100644 --- a/llvm/lib/Transforms/Utils/CodeExtractor.cpp +++ b/llvm/lib/Transforms/Utils/CodeExtractor.cpp @@ -946,6 +946,7 @@ Function *CodeExtractor::constructFunction(const ValueSet &inputs, case Attribute::NoRecurse: case Attribute::InlineHint: case Attribute::MinSize: + case Attribute::NoCallback: case Attribute::NoDuplicate: case Attribute::NoFree: case Attribute::NoImplicitFloat: diff --git a/llvm/test/Bitcode/attributes.ll b/llvm/test/Bitcode/attributes.ll index baafc70cf40b..36c9ff7ca391 100644 --- a/llvm/test/Bitcode/attributes.ll +++ b/llvm/test/Bitcode/attributes.ll @@ -404,6 +404,12 @@ define void @f68() mustprogress ret void } +; CHECK; define void @f69() #43 +define void @f70() nocallback +{ + ret void +} + ; CHECK: attributes #0 = { noreturn } ; CHECK: attributes #1 = { nounwind } ; CHECK: attributes #2 = { readnone } @@ -446,4 +452,5 @@ define void @f68() mustprogress ; CHECK: attributes #39 = { sanitize_memtag } ; CHECK: attributes #40 = { null_pointer_is_valid } ; CHECK: attributes #41 = { mustprogress } +; CHECK: attributes #42 = { nocallback } ; CHECK: attributes #[[NOBUILTIN]] = { nobuiltin } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits