diff options
author | Antonio Frighetto <me@antoniofrighetto.com> | 2025-07-02 09:23:22 +0200 |
---|---|---|
committer | Antonio Frighetto <me@antoniofrighetto.com> | 2025-07-02 09:29:36 +0200 |
commit | f1cc0b607b03548028db3ca57bb057b2599b1711 (patch) | |
tree | bb9c8f0c81f52d3cead1c23ba0a31fde611d697f /llvm/lib | |
parent | d5608d6751315f2e34a0445ca7f5be44a1520463 (diff) | |
download | llvm-f1cc0b607b03548028db3ca57bb057b2599b1711.zip llvm-f1cc0b607b03548028db3ca57bb057b2599b1711.tar.gz llvm-f1cc0b607b03548028db3ca57bb057b2599b1711.tar.bz2 |
[IR] Introduce `dead_on_return` attribute
Add `dead_on_return` attribute, which is meant to be taken advantage
by the frontend, and states that the memory pointed to by the argument
is dead upon function return. As with `byval`, it is supposed to be
used for passing aggregates by value. The difference lies in the ABI:
`byval` implies that the pointer is explicitly passed as argument to
the callee (during codegen the copy is emitted as per byval contract),
whereas a `dead_on_return`-marked argument implies that the copy
already exists in the IR, is located at a specific stack offset within
the caller, and this memory will not be read further by the caller upon
callee return – or otherwise poison, if read before being written.
RFC: https://discourse.llvm.org/t/rfc-add-dead-on-return-attribute/86871.
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/IR/Attributes.cpp | 3 | ||||
-rw-r--r-- | llvm/lib/IR/Function.cpp | 6 | ||||
-rw-r--r-- | llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp | 6 | ||||
-rw-r--r-- | llvm/lib/Transforms/Utils/CodeExtractor.cpp | 1 |
6 files changed, 16 insertions, 4 deletions
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index c6549e7..de7bf9b 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -2244,6 +2244,8 @@ static Attribute::AttrKind getAttrFromCode(uint64_t Code) { return Attribute::NoExt; case bitc::ATTR_KIND_CAPTURES: return Attribute::Captures; + case bitc::ATTR_KIND_DEAD_ON_RETURN: + return Attribute::DeadOnReturn; } } diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index 2a2dd08..da00eec 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -938,6 +938,8 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) { return bitc::ATTR_KIND_NO_EXT; case Attribute::Captures: return bitc::ATTR_KIND_CAPTURES; + case Attribute::DeadOnReturn: + return bitc::ATTR_KIND_DEAD_ON_RETURN; case Attribute::EndAttrKinds: llvm_unreachable("Can not encode end-attribute kinds marker."); case Attribute::None: diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp index bfb32ff..d1fbcb9 100644 --- a/llvm/lib/IR/Attributes.cpp +++ b/llvm/lib/IR/Attributes.cpp @@ -2424,7 +2424,8 @@ AttributeMask AttributeFuncs::typeIncompatible(Type *Ty, AttributeSet AS, .addAttribute(Attribute::Writable) .addAttribute(Attribute::DeadOnUnwind) .addAttribute(Attribute::Initializes) - .addAttribute(Attribute::Captures); + .addAttribute(Attribute::Captures) + .addAttribute(Attribute::DeadOnReturn); if (ASK & ASK_UNSAFE_TO_DROP) Incompatible.addAttribute(Attribute::Nest) .addAttribute(Attribute::SwiftError) diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp index 3e7fcbb..7a03663 100644 --- a/llvm/lib/IR/Function.cpp +++ b/llvm/lib/IR/Function.cpp @@ -130,6 +130,12 @@ bool Argument::hasByValAttr() const { return hasAttribute(Attribute::ByVal); } +bool Argument::hasDeadOnReturnAttr() const { + if (!getType()->isPointerTy()) + return false; + return hasAttribute(Attribute::DeadOnReturn); +} + bool Argument::hasByRefAttr() const { if (!getType()->isPointerTy()) return false; diff --git a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp index 4a2eb92..85dd9a1 100644 --- a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp +++ b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp @@ -1017,10 +1017,10 @@ struct DSEState { } } - // Treat byval or inalloca arguments the same as Allocas, stores to them are - // dead at the end of the function. + // Treat byval, inalloca or dead on return arguments the same as Allocas, + // stores to them are dead at the end of the function. for (Argument &AI : F.args()) - if (AI.hasPassPointeeByValueCopyAttr()) + if (AI.hasPassPointeeByValueCopyAttr() || AI.hasDeadOnReturnAttr()) InvisibleToCallerAfterRet.insert({&AI, true}); // Collect whether there is any irreducible control flow in the function. diff --git a/llvm/lib/Transforms/Utils/CodeExtractor.cpp b/llvm/lib/Transforms/Utils/CodeExtractor.cpp index 242cf6d..e28a1b4 100644 --- a/llvm/lib/Transforms/Utils/CodeExtractor.cpp +++ b/llvm/lib/Transforms/Utils/CodeExtractor.cpp @@ -1020,6 +1020,7 @@ Function *CodeExtractor::constructFunctionDeclaration( case Attribute::EndAttrKinds: case Attribute::EmptyKey: case Attribute::TombstoneKey: + case Attribute::DeadOnReturn: llvm_unreachable("Not a function attribute"); } |