aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib
diff options
context:
space:
mode:
authorAntonio Frighetto <me@antoniofrighetto.com>2025-07-02 09:23:22 +0200
committerAntonio Frighetto <me@antoniofrighetto.com>2025-07-02 09:29:36 +0200
commitf1cc0b607b03548028db3ca57bb057b2599b1711 (patch)
treebb9c8f0c81f52d3cead1c23ba0a31fde611d697f /llvm/lib
parentd5608d6751315f2e34a0445ca7f5be44a1520463 (diff)
downloadllvm-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.cpp2
-rw-r--r--llvm/lib/Bitcode/Writer/BitcodeWriter.cpp2
-rw-r--r--llvm/lib/IR/Attributes.cpp3
-rw-r--r--llvm/lib/IR/Function.cpp6
-rw-r--r--llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp6
-rw-r--r--llvm/lib/Transforms/Utils/CodeExtractor.cpp1
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");
}