https://github.com/fhahn updated https://github.com/llvm/llvm-project/pull/95004
>From c3b6943c236990c9f0ba363b4335b3c0e048ef2c Mon Sep 17 00:00:00 2001 From: Florian Hahn <f...@fhahn.com> Date: Mon, 10 Jun 2024 16:54:02 +0100 Subject: [PATCH 1/3] [clang] Add value_type attr, use it to add noalias when pass-by-value. This adds an attribute version of -fpass-by-value-is-noalias (added in a874d63344) Still needs proper docs. --- clang/include/clang/Basic/Attr.td | 10 +++++ clang/lib/CodeGen/CGCall.cpp | 7 ++-- clang/test/CodeGenCXX/value-type-attr.cpp | 40 +++++++++++++++++++ ...a-attribute-supported-attributes-list.test | 1 + 4 files changed, 55 insertions(+), 3 deletions(-) create mode 100644 clang/test/CodeGenCXX/value-type-attr.cpp diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 4d34346460561..4270f3ec5d6ab 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1972,6 +1972,16 @@ def TrivialABI : InheritableAttr { let SimpleHandler = 1; } +def ValueType : InheritableAttr { + // This attribute does not have a C [[]] spelling because it requires the + // CPlusPlus language option. + let Spellings = [Clang<"value_type", 0>]; + let Subjects = SubjectList<[CXXRecord]>; + let Documentation = [TrivialABIDocs]; + let LangOpts = [CPlusPlus]; + let SimpleHandler = 1; +} + def MaxFieldAlignment : InheritableAttr { // This attribute has no spellings as it is only ever created implicitly. let Spellings = []; diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 7aa77e55dbfcc..fb4154eef303d 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -2797,9 +2797,10 @@ void CodeGenModule::ConstructAttributeList(StringRef Name, Attrs.addByValAttr(getTypes().ConvertTypeForMem(ParamType)); auto *Decl = ParamType->getAsRecordDecl(); - if (CodeGenOpts.PassByValueIsNoAlias && Decl && - Decl->getArgPassingRestrictions() == - RecordArgPassingKind::CanPassInRegs) + if (Decl && ((CodeGenOpts.PassByValueIsNoAlias && + Decl->getArgPassingRestrictions() == + RecordArgPassingKind::CanPassInRegs) || + Decl->hasAttr<ValueTypeAttr>())) // When calling the function, the pointer passed in will be the only // reference to the underlying object. Mark it accordingly. Attrs.addAttribute(llvm::Attribute::NoAlias); diff --git a/clang/test/CodeGenCXX/value-type-attr.cpp b/clang/test/CodeGenCXX/value-type-attr.cpp new file mode 100644 index 0000000000000..46938dd7d271a --- /dev/null +++ b/clang/test/CodeGenCXX/value-type-attr.cpp @@ -0,0 +1,40 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 +// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fcxx-exceptions -fexceptions -emit-llvm -o - %s | FileCheck %s + +struct Small { + int *p; + Small(); + ~Small(); + Small(const Small &) noexcept; + Small &operator=(const Small &); +}; + + +struct __attribute__((value_type)) SmallVT { + int *p; + SmallVT(); + ~SmallVT(); + SmallVT(const SmallVT &) noexcept; + SmallVT &operator=(const SmallVT &); +}; + +struct Large { + int *p; + int a[128]; + Large(); + ~Large(); + Large(const Large &) noexcept; + Large &operator=(const Large &); +}; + +struct __attribute__((value_type)) LargeVT { + int *p; + int a[128]; + LargeVT(); + ~LargeVT(); + LargeVT(const LargeVT &) noexcept; + LargeVT &operator=(const LargeVT &); +}; + +void foo(Small a, SmallVT b, Large c, LargeVT d) {} +// CHECK: define void @_Z3foo5Small7SmallVT5Large7LargeVT(ptr noundef %a, ptr noalias noundef %b, ptr noundef %c, ptr noalias noundef %d) diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index 55f196625770a..2bc34802c5f5b 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -209,6 +209,7 @@ // CHECK-NEXT: UnsafeBufferUsage (SubjectMatchRule_function, SubjectMatchRule_field) // CHECK-NEXT: UseHandle (SubjectMatchRule_variable_is_parameter) // CHECK-NEXT: VTablePointerAuthentication (SubjectMatchRule_record) +// CHECK-NEXT: ValueType (SubjectMatchRule_record) // CHECK-NEXT: VecReturn (SubjectMatchRule_record) // CHECK-NEXT: VecTypeHint (SubjectMatchRule_function) // CHECK-NEXT: WarnUnused (SubjectMatchRule_record) >From 82e6bdb714db9ceeab06a4b61a3748ba5926bc88 Mon Sep 17 00:00:00 2001 From: Florian Hahn <f...@fhahn.com> Date: Fri, 14 Mar 2025 16:23:24 +0000 Subject: [PATCH 2/3] !fixup add attr docs. --- clang/include/clang/Basic/AttrDocs.td | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 34e7ff9612859..0fa733a1a2f94 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -9242,3 +9242,14 @@ Declares that a function potentially allocates heap memory, and prevents any pot of ``nonallocating`` by the compiler. }]; } + +def ValueTypeDocs : Documentation { + let Category = DocCatDecl; + let Content = [{ +The ``value_type`` attribute can be used to mark user-defined types as 'value +types'. When objects of value types are passed by-value to functions, the +argument must be the only value referencing the passed object. This allows the +optimizer to assume that no other pointers may alias the object when it is +passed indirectly to a function.. + }]; +} >From e0ff9c786da3b27ad6fa9112beb58684ad6457af Mon Sep 17 00:00:00 2001 From: Florian Hahn <f...@fhahn.com> Date: Fri, 14 Mar 2025 16:45:50 +0000 Subject: [PATCH 3/3] !fixup update wording --- clang/include/clang/Basic/AttrDocs.td | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 0fa733a1a2f94..4228bc1f7d888 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -9247,9 +9247,10 @@ def ValueTypeDocs : Documentation { let Category = DocCatDecl; let Content = [{ The ``value_type`` attribute can be used to mark user-defined types as 'value -types'. When objects of value types are passed by-value to functions, the -argument must be the only value referencing the passed object. This allows the -optimizer to assume that no other pointers may alias the object when it is -passed indirectly to a function.. +types'. When objects of value types are passed value to functions, the objects +are always considered to be formally copied into a new object. This means the +argument itself must be the only value referencing the passed object. This +allows the optimizer to assume that no other pointers may alias the object when +it is passed indirectly to a function.. }]; } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits