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 _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
