[llvm-branch-commits] update (PR #173294)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Dec 22 10:37:12 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Aiden Grossman (boomanaiden154)
<details>
<summary>Changes</summary>
---
Full diff: https://github.com/llvm/llvm-project/pull/173294.diff
13 Files Affected:
- (modified) clang/lib/CodeGen/CGCall.cpp (+1-1)
- (modified) llvm/include/llvm/AsmParser/LLParser.h (+3-1)
- (modified) llvm/include/llvm/IR/Argument.h (+4-2)
- (modified) llvm/include/llvm/IR/Attributes.h (+7-6)
- (modified) llvm/include/llvm/IR/Function.h (+1-1)
- (modified) llvm/lib/AsmParser/LLParser.cpp (+19-11)
- (modified) llvm/lib/IR/AttributeImpl.h (+1-1)
- (modified) llvm/lib/IR/Attributes.cpp (+21-9)
- (modified) llvm/lib/IR/Function.cpp (+1-1)
- (modified) llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp (+2-1)
- (modified) llvm/test/Bitcode/attributes.ll (+7-2)
- (modified) llvm/test/Bitcode/dead-on-return-upgrade.ll (+1-1)
- (modified) llvm/test/Transforms/DeadStoreElimination/simple.ll (+3-3)
``````````diff
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 4a9025b6e0b0f..6a04f16677131 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -2884,7 +2884,7 @@ void CodeGenModule::ConstructAttributeList(StringRef Name,
// (e.g., Obj-C ARC-managed structs, MSVC callee-destroyed objects).
if (!ParamType.isDestructedType() || !ParamType->isRecordType() ||
ParamType->castAsRecordDecl()->isParamDestroyedInCallee())
- Attrs.addAttribute(llvm::Attribute::DeadOnReturn);
+ Attrs.addDeadOnReturnAttr(std::nullopt);
}
}
diff --git a/llvm/include/llvm/AsmParser/LLParser.h b/llvm/include/llvm/AsmParser/LLParser.h
index f94d7c7644427..b792155206f05 100644
--- a/llvm/include/llvm/AsmParser/LLParser.h
+++ b/llvm/include/llvm/AsmParser/LLParser.h
@@ -319,7 +319,9 @@ namespace llvm {
bool parseOptionalAlignment(MaybeAlign &Alignment,
bool AllowParens = false);
bool parseOptionalCodeModel(CodeModel::Model &model);
- bool parseOptionalAttrBytes(lltok::Kind AttrKind, uint64_t &Bytes);
+ bool parseOptionalAttrBytes(lltok::Kind AttrKind,
+ std::optional<uint64_t> &Bytes,
+ bool ErrorNoBytes = false);
bool parseOptionalUWTableKind(UWTableKind &Kind);
bool parseAllocKind(AllocFnKind &Kind);
std::optional<MemoryEffects> parseMemoryAttr();
diff --git a/llvm/include/llvm/IR/Argument.h b/llvm/include/llvm/IR/Argument.h
index df380919629fe..d70459aa80639 100644
--- a/llvm/include/llvm/IR/Argument.h
+++ b/llvm/include/llvm/IR/Argument.h
@@ -78,8 +78,10 @@ class Argument final : public Value {
/// Return true if this argument has the byval attribute.
LLVM_ABI bool hasByValAttr() const;
- /// Return true if this argument has the dead_on_return attribute.
- LLVM_ABI uint64_t getDeadOnReturnBytes() const;
+ /// Return the number of bytes marked dead by the dead_on_return attribute.
+ /// If no count was specified (implying all memory reachable through the
+ /// pointer is marked dead on return), std::nullopt is returned.
+ LLVM_ABI std::optional<uint64_t> getDeadOnReturnBytes() const;
/// Return true if this argument has the byref attribute.
LLVM_ABI bool hasByRefAttr() const;
diff --git a/llvm/include/llvm/IR/Attributes.h b/llvm/include/llvm/IR/Attributes.h
index 241c5060ec6cf..6366f98cc91ad 100644
--- a/llvm/include/llvm/IR/Attributes.h
+++ b/llvm/include/llvm/IR/Attributes.h
@@ -276,9 +276,10 @@ class Attribute {
/// dereferenceable attribute.
LLVM_ABI uint64_t getDereferenceableBytes() const;
- /// Returns the number of dead_on_return bytes from the
- /// dead_on_return attribute.
- LLVM_ABI uint64_t getDeadOnReturnBytes() const;
+ /// Returns the number of dead_on_return bytes from the dead_on_return
+ /// attribute, or std::nullopt if all memory reachable through the pointer is
+ /// marked dead on return.
+ LLVM_ABI std::optional<uint64_t> getDeadOnReturnBytes() const;
/// Returns the number of dereferenceable_or_null bytes from the
/// dereferenceable_or_null attribute.
@@ -449,7 +450,7 @@ class AttributeSet {
LLVM_ABI MaybeAlign getAlignment() const;
LLVM_ABI MaybeAlign getStackAlignment() const;
LLVM_ABI uint64_t getDereferenceableBytes() const;
- LLVM_ABI uint64_t getDeadOnReturnBytes() const;
+ LLVM_ABI std::optional<uint64_t> getDeadOnReturnBytes() const;
LLVM_ABI uint64_t getDereferenceableOrNullBytes() const;
LLVM_ABI Type *getByValType() const;
LLVM_ABI Type *getStructRetType() const;
@@ -970,7 +971,7 @@ class AttributeList {
LLVM_ABI uint64_t getRetDereferenceableOrNullBytes() const;
/// Get the number of dead_on_return bytes (or zero if unknown) of an arg.
- LLVM_ABI uint64_t getDeadOnReturnBytes(unsigned Index) const;
+ LLVM_ABI std::optional<uint64_t> getDeadOnReturnBytes(unsigned Index) const;
/// Get the number of dereferenceable_or_null bytes (or zero if unknown) of an
/// arg.
@@ -1252,7 +1253,7 @@ class AttrBuilder {
/// This turns the number of dead_on_return bytes into the form used
/// internally in Attribute.
- LLVM_ABI AttrBuilder &addDeadOnReturnAttr(uint64_t Bytes);
+ LLVM_ABI AttrBuilder &addDeadOnReturnAttr(std::optional<uint64_t> Bytes);
/// This turns the number of dereferenceable_or_null bytes into the
/// form used internally in Attribute.
diff --git a/llvm/include/llvm/IR/Function.h b/llvm/include/llvm/IR/Function.h
index 48b1604bdea32..ba4eff5b7d546 100644
--- a/llvm/include/llvm/IR/Function.h
+++ b/llvm/include/llvm/IR/Function.h
@@ -525,7 +525,7 @@ class LLVM_ABI Function : public GlobalObject, public ilist_node<Function> {
/// Extract the number of dead_on_return bytes for a parameter.
/// @param ArgNo Index of an argument, with 0 being the first function arg.
- uint64_t getDeadOnReturnBytes(unsigned ArgNo) const {
+ std::optional<uint64_t> getDeadOnReturnBytes(unsigned ArgNo) const {
return AttributeSets.getDeadOnReturnBytes(ArgNo);
}
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 148e0dad8e5c3..a6a9f0629bc25 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -1606,24 +1606,26 @@ bool LLParser::parseEnumAttribute(Attribute::AttrKind Attr, AttrBuilder &B,
return false;
}
case Attribute::Dereferenceable: {
- uint64_t Bytes;
+ std::optional<uint64_t> Bytes;
if (parseOptionalAttrBytes(lltok::kw_dereferenceable, Bytes))
return true;
- B.addDereferenceableAttr(Bytes);
+ assert(Bytes.has_value());
+ B.addDereferenceableAttr(Bytes.value());
return false;
}
case Attribute::DeadOnReturn: {
- uint64_t Bytes;
+ std::optional<uint64_t> Bytes;
if (parseOptionalAttrBytes(lltok::kw_dead_on_return, Bytes))
return true;
B.addDeadOnReturnAttr(Bytes);
return false;
}
case Attribute::DereferenceableOrNull: {
- uint64_t Bytes;
+ std::optional<uint64_t> Bytes;
if (parseOptionalAttrBytes(lltok::kw_dereferenceable_or_null, Bytes))
return true;
- B.addDereferenceableOrNullAttr(Bytes);
+ assert(Bytes.has_value());
+ B.addDereferenceableOrNullAttr(Bytes.value());
return false;
}
case Attribute::UWTable: {
@@ -2481,7 +2483,9 @@ bool LLParser::parseOptionalCodeModel(CodeModel::Model &model) {
///
/// where AttrKind is either 'dereferenceable', 'dereferenceable_or_null', or
/// 'dead_on_return'
-bool LLParser::parseOptionalAttrBytes(lltok::Kind AttrKind, uint64_t &Bytes) {
+bool LLParser::parseOptionalAttrBytes(lltok::Kind AttrKind,
+ std::optional<uint64_t> &Bytes,
+ bool ErrorNoBytes) {
assert((AttrKind == lltok::kw_dereferenceable ||
AttrKind == lltok::kw_dereferenceable_or_null ||
AttrKind == lltok::kw_dead_on_return) &&
@@ -2491,16 +2495,20 @@ bool LLParser::parseOptionalAttrBytes(lltok::Kind AttrKind, uint64_t &Bytes) {
if (!EatIfPresent(AttrKind))
return false;
LocTy ParenLoc = Lex.getLoc();
- if (!EatIfPresent(lltok::lparen))
- return error(ParenLoc, "expected '('");
+ if (!EatIfPresent(lltok::lparen)) {
+ if (ErrorNoBytes)
+ return error(ParenLoc, "expected '('");
+ Bytes = std::nullopt;
+ return false;
+ }
LocTy DerefLoc = Lex.getLoc();
- if (parseUInt64(Bytes))
+ if (parseUInt64(Bytes.value()))
return true;
ParenLoc = Lex.getLoc();
if (!EatIfPresent(lltok::rparen))
return error(ParenLoc, "expected ')'");
- if (!Bytes)
- return error(DerefLoc, "dereferenceable bytes must be non-zero");
+ if (!Bytes.value())
+ return error(DerefLoc, "byte count specified must be non-zero");
return false;
}
diff --git a/llvm/lib/IR/AttributeImpl.h b/llvm/lib/IR/AttributeImpl.h
index da216458d0b19..b23e8166dc757 100644
--- a/llvm/lib/IR/AttributeImpl.h
+++ b/llvm/lib/IR/AttributeImpl.h
@@ -332,7 +332,7 @@ class AttributeSetNode final
MaybeAlign getAlignment() const;
MaybeAlign getStackAlignment() const;
uint64_t getDereferenceableBytes() const;
- uint64_t getDeadOnReturnBytes() const;
+ std::optional<uint64_t> getDeadOnReturnBytes() const;
uint64_t getDereferenceableOrNullBytes() const;
std::optional<std::pair<unsigned, std::optional<unsigned>>> getAllocSizeArgs()
const;
diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp
index 87d30672de956..7fc1773726192 100644
--- a/llvm/lib/IR/Attributes.cpp
+++ b/llvm/lib/IR/Attributes.cpp
@@ -451,11 +451,14 @@ uint64_t Attribute::getDereferenceableBytes() const {
return pImpl->getValueAsInt();
}
-uint64_t Attribute::getDeadOnReturnBytes() const {
+std::optional<uint64_t> Attribute::getDeadOnReturnBytes() const {
assert(hasAttribute(Attribute::DeadOnReturn) &&
"Trying to get dead_on_return bytes from"
"from a parameter without such an attribute!");
- return pImpl->getValueAsInt();
+ uint64_t DeadBytes = pImpl->getValueAsInt();
+ if (DeadBytes == std::numeric_limits<uint64_t>::max())
+ return std::nullopt;
+ return DeadBytes;
}
uint64_t Attribute::getDereferenceableOrNullBytes() const {
@@ -581,8 +584,12 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
if (hasAttribute(Attribute::DereferenceableOrNull))
return AttrWithBytesToString("dereferenceable_or_null");
- if (hasAttribute(Attribute::DeadOnReturn))
+ if (hasAttribute(Attribute::DeadOnReturn)) {
+ uint64_t DeadBytes = getValueAsInt();
+ if (DeadBytes == std::numeric_limits<uint64_t>::max())
+ return "dead_on_return";
return AttrWithBytesToString("dead_on_return");
+ }
if (hasAttribute(Attribute::AllocSize)) {
unsigned ElemSize;
@@ -1172,7 +1179,7 @@ uint64_t AttributeSet::getDereferenceableBytes() const {
return SetNode ? SetNode->getDereferenceableBytes() : 0;
}
-uint64_t AttributeSet::getDeadOnReturnBytes() const {
+std::optional<uint64_t> AttributeSet::getDeadOnReturnBytes() const {
return SetNode ? SetNode->getDeadOnReturnBytes() : 0;
}
@@ -1380,7 +1387,7 @@ uint64_t AttributeSetNode::getDereferenceableBytes() const {
return 0;
}
-uint64_t AttributeSetNode::getDeadOnReturnBytes() const {
+std::optional<uint64_t> AttributeSetNode::getDeadOnReturnBytes() const {
if (auto A = findEnumAttribute(Attribute::DeadOnReturn))
return A->getDeadOnReturnBytes();
return 0;
@@ -2003,7 +2010,8 @@ uint64_t AttributeList::getRetDereferenceableOrNullBytes() const {
return getRetAttrs().getDereferenceableOrNullBytes();
}
-uint64_t AttributeList::getDeadOnReturnBytes(unsigned Index) const {
+std::optional<uint64_t>
+AttributeList::getDeadOnReturnBytes(unsigned Index) const {
return getParamAttrs(Index).getDeadOnReturnBytes();
}
@@ -2229,11 +2237,15 @@ AttrBuilder &AttrBuilder::addDereferenceableAttr(uint64_t Bytes) {
return addRawIntAttr(Attribute::Dereferenceable, Bytes);
}
-AttrBuilder &AttrBuilder::addDeadOnReturnAttr(uint64_t Bytes) {
- if (Bytes == 0)
+AttrBuilder &AttrBuilder::addDeadOnReturnAttr(std::optional<uint64_t> Bytes) {
+ if (!Bytes.has_value())
+ return addRawIntAttr(Attribute::DeadOnReturn,
+ std::numeric_limits<uint64_t>::max());
+
+ if (Bytes.value() == 0)
return *this;
- return addRawIntAttr(Attribute::DeadOnReturn, Bytes);
+ return addRawIntAttr(Attribute::DeadOnReturn, Bytes.value());
}
AttrBuilder &AttrBuilder::addDereferenceableOrNullAttr(uint64_t Bytes) {
diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp
index d4e80762919c8..78578ac223e66 100644
--- a/llvm/lib/IR/Function.cpp
+++ b/llvm/lib/IR/Function.cpp
@@ -130,7 +130,7 @@ bool Argument::hasByValAttr() const {
return hasAttribute(Attribute::ByVal);
}
-uint64_t Argument::getDeadOnReturnBytes() const {
+std::optional<uint64_t> Argument::getDeadOnReturnBytes() const {
assert(getType()->isPointerTy() && "Only pointers have dead_on_return bytes");
return getParent()->getDeadOnReturnBytes(getArgNo());
}
diff --git a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
index 16ab2d5f63dd5..51a27993af270 100644
--- a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
@@ -1018,7 +1018,8 @@ struct DSEState {
// stores to them are dead at the end of the function.
for (Argument &AI : F.args())
if (AI.hasPassPointeeByValueCopyAttr() ||
- (AI.getType()->isPointerTy() && AI.getDeadOnReturnBytes() > 0))
+ (AI.getType()->isPointerTy() &&
+ !AI.getDeadOnReturnBytes().has_value()))
InvisibleToCallerAfterRet.insert({&AI, true});
// Collect whether there is any irreducible control flow in the function.
diff --git a/llvm/test/Bitcode/attributes.ll b/llvm/test/Bitcode/attributes.ll
index e908d95215c7d..4f234d7a40079 100644
--- a/llvm/test/Bitcode/attributes.ll
+++ b/llvm/test/Bitcode/attributes.ll
@@ -577,8 +577,13 @@ define void @captures(ptr captures(address) %p) {
ret void
}
-; CHECK: define void @dead_on_return(ptr dead_on_return(4) %p)
-define void @dead_on_return(ptr dead_on_return(4) %p) {
+; CHECK: define void @dead_on_return(ptr dead_on_return %p)
+define void @dead_on_return(ptr dead_on_return %p) {
+ ret void
+}
+
+; CHECK: define void @dead_on_return_sized(ptr dead_on_return(4) %p)
+define void @dead_on_return_sized(ptr dead_on_return(4) %p) {
ret void
}
diff --git a/llvm/test/Bitcode/dead-on-return-upgrade.ll b/llvm/test/Bitcode/dead-on-return-upgrade.ll
index d3fa2b8f91108..ddf70f453091e 100644
--- a/llvm/test/Bitcode/dead-on-return-upgrade.ll
+++ b/llvm/test/Bitcode/dead-on-return-upgrade.ll
@@ -1,6 +1,6 @@
; RUN: llvm-dis -o - %s.bc | FileCheck %s
-; CHECK: define void @test_dead_on_return_autoupgrade(ptr dead_on_return(18446744073709551615) %p) {
+; CHECK: define void @test_dead_on_return_autoupgrade(ptr dead_on_return %p) {
define void @test_dead_on_return_autoupgrade(ptr dead_on_return %p) {
ret void
diff --git a/llvm/test/Transforms/DeadStoreElimination/simple.ll b/llvm/test/Transforms/DeadStoreElimination/simple.ll
index c9f43c6a574bc..9d28395a4ccd0 100644
--- a/llvm/test/Transforms/DeadStoreElimination/simple.ll
+++ b/llvm/test/Transforms/DeadStoreElimination/simple.ll
@@ -856,7 +856,7 @@ bb:
ret void
}
-define void @test_dead_on_return(ptr dead_on_return(4) %p) {
+define void @test_dead_on_return(ptr dead_on_return %p) {
; CHECK-LABEL: @test_dead_on_return(
; CHECK-NEXT: ret void
;
@@ -864,7 +864,7 @@ define void @test_dead_on_return(ptr dead_on_return(4) %p) {
ret void
}
-define void @test_dead_on_return_maythrow(ptr dead_on_return(4) %p) {
+define void @test_dead_on_return_maythrow(ptr dead_on_return %p) {
; CHECK-LABEL: @test_dead_on_return_maythrow(
; CHECK-NEXT: call void @maythrow()
; CHECK-NEXT: ret void
@@ -874,7 +874,7 @@ define void @test_dead_on_return_maythrow(ptr dead_on_return(4) %p) {
ret void
}
-define ptr @test_dead_on_return_ptr_returned(ptr dead_on_return(64) %p) {
+define ptr @test_dead_on_return_ptr_returned(ptr dead_on_return %p) {
; CHECK-LABEL: @test_dead_on_return_ptr_returned(
; CHECK-NEXT: [[LOCAL_VAR:%.*]] = alloca ptr, align 8
; CHECK-NEXT: call void @opaque(ptr [[LOCAL_VAR]])
``````````
</details>
https://github.com/llvm/llvm-project/pull/173294
More information about the llvm-branch-commits
mailing list