https://github.com/boomanaiden154 updated 
https://github.com/llvm/llvm-project/pull/173694

>From c3f13e4a2c161945048236c241e9a840ac0c3e4e Mon Sep 17 00:00:00 2001
From: Aiden Grossman <[email protected]>
Date: Sat, 27 Dec 2025 01:58:55 +0000
Subject: [PATCH 1/5] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20ch?=
 =?UTF-8?q?anges=20to=20main=20this=20commit=20is=20based=20on?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.7

[skip ci]
---
 clang/lib/CodeGen/CGCall.cpp                  |   2 +-
 llvm/docs/LangRef.rst                         |  12 +++-
 llvm/include/llvm/AsmParser/LLParser.h        |   4 +-
 llvm/include/llvm/IR/Argument.h               |   6 +-
 llvm/include/llvm/IR/Attributes.h             |  47 ++++++++++++++++
 llvm/include/llvm/IR/Attributes.td            |   2 +-
 llvm/include/llvm/IR/Function.h               |   6 ++
 llvm/lib/AsmParser/LLParser.cpp               |  53 ++++++++++++------
 llvm/lib/Bitcode/Reader/BitcodeReader.cpp     |   5 ++
 llvm/lib/IR/AttributeImpl.h                   |   1 +
 llvm/lib/IR/Attributes.cpp                    |  35 ++++++++++++
 llvm/lib/IR/Function.cpp                      |   7 +--
 .../Scalar/DeadStoreElimination.cpp           |   4 +-
 llvm/test/Bitcode/attributes.ll               |   5 ++
 llvm/test/Bitcode/dead-on-return-upgrade.ll   |   7 +++
 .../test/Bitcode/dead-on-return-upgrade.ll.bc | Bin 0 -> 1612 bytes
 llvm/test/Verifier/dead-on-return.ll          |   6 ++
 17 files changed, 173 insertions(+), 29 deletions(-)
 create mode 100644 llvm/test/Bitcode/dead-on-return-upgrade.ll
 create mode 100644 llvm/test/Bitcode/dead-on-return-upgrade.ll.bc

diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 4a9025b6e0b0f..69d28feeb34b4 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(llvm::DeadOnReturnInfo());
         }
       }
 
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 5fa3a4ebb2472..b31c6bb555f36 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -1842,11 +1842,15 @@ Currently, only the following parameter attributes are 
defined:
 
     This attribute cannot be applied to return values.
 
-``dead_on_return``
+``dead_on_return`` or ``dead_on_return(<n>)``
     This attribute indicates that the memory pointed to by the argument is dead
     upon function return, both upon normal return and if the calls unwinds, 
meaning
     that the caller will not depend on its contents. Stores that would be 
observable
-    either on the return path or on the unwind path may be elided.
+    either on the return path or on the unwind path may be elided. The number 
of
+    bytes known to be dead can optionally be provided in parentheses. It is 
legal
+    for the number of bytes to be less than the size of the pointee type. If a 
number
+    of bytes is not specified, all memory rechable through the pointer is 
marked as
+    dead on return.
 
     Specifically, the behavior is as-if any memory written through the pointer
     during the execution of the function is overwritten with a poison value
@@ -1855,7 +1859,9 @@ Currently, only the following parameter attributes are 
defined:
 
     This attribute does not imply aliasing properties. For pointer arguments 
that
     do not alias other memory locations, ``noalias`` attribute may be used in
-    conjunction. Conversely, this attribute always implies ``dead_on_unwind``.
+    conjunction. Conversely, this attribute always implies ``dead_on_unwind``. 
If
+    a number of bytes is specified, then only those bytes are implied to be
+    ``dead_on_unwind``.
 
     This attribute cannot be applied to return values.
 
diff --git a/llvm/include/llvm/AsmParser/LLParser.h 
b/llvm/include/llvm/AsmParser/LLParser.h
index 9eb31d7e0a451..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 parseOptionalDerefAttrBytes(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 6ffc0f8fd5155..0ce28c6e825c1 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 bool hasDeadOnReturnAttr() 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 DeadOnReturnInfo getDeadOnReturnInfo() 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 e734466ce20e0..b89832bc14b08 100644
--- a/llvm/include/llvm/IR/Attributes.h
+++ b/llvm/include/llvm/IR/Attributes.h
@@ -60,6 +60,40 @@ enum class AllocFnKind : uint64_t {
   LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ Aligned)
 };
 
+class DeadOnReturnInfo {
+public:
+  DeadOnReturnInfo() : DeadBytes(std::nullopt) {}
+  DeadOnReturnInfo(uint64_t DeadOnReturnBytes) : DeadBytes(DeadOnReturnBytes) 
{}
+
+  uint64_t getNumberOfDeadBytes() {
+    assert(DeadBytes.has_value() &&
+           "This attribute does not specify a byte count. Did you forget to "
+           "check if the attribute covers all reachable memory?");
+    return DeadBytes.value();
+  }
+
+  bool coversAllReachableMemory() { return !DeadBytes.has_value(); }
+
+  static DeadOnReturnInfo createFromintValue(uint64_t Data) {
+    if (Data == std::numeric_limits<uint64_t>::max())
+      return DeadOnReturnInfo();
+    return DeadOnReturnInfo(Data);
+  }
+
+  uint64_t toIntValue() const {
+    if (DeadBytes.has_value())
+      return DeadBytes.value();
+    return std::numeric_limits<uint64_t>::max();
+  }
+
+  bool isZeroSized() const {
+    return DeadBytes.has_value() && DeadBytes.value() == 0;
+  }
+
+private:
+  std::optional<uint64_t> DeadBytes;
+};
+
 
//===----------------------------------------------------------------------===//
 /// \class
 /// Functions, function parameters, and return types can have attributes
@@ -276,6 +310,11 @@ class Attribute {
   /// dereferenceable attribute.
   LLVM_ABI uint64_t getDereferenceableBytes() 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 DeadOnReturnInfo getDeadOnReturnInfo() const;
+
   /// Returns the number of dereferenceable_or_null bytes from the
   /// dereferenceable_or_null attribute.
   LLVM_ABI uint64_t getDereferenceableOrNullBytes() const;
@@ -445,6 +484,7 @@ class AttributeSet {
   LLVM_ABI MaybeAlign getAlignment() const;
   LLVM_ABI MaybeAlign getStackAlignment() const;
   LLVM_ABI uint64_t getDereferenceableBytes() const;
+  LLVM_ABI DeadOnReturnInfo getDeadOnReturnInfo() const;
   LLVM_ABI uint64_t getDereferenceableOrNullBytes() const;
   LLVM_ABI Type *getByValType() const;
   LLVM_ABI Type *getStructRetType() const;
@@ -964,6 +1004,9 @@ class AttributeList {
   /// the return value.
   LLVM_ABI uint64_t getRetDereferenceableOrNullBytes() const;
 
+  /// Get the number of dead_on_return bytes (or zero if unknown) of an arg.
+  LLVM_ABI DeadOnReturnInfo getDeadOnReturnInfo(unsigned Index) const;
+
   /// Get the number of dereferenceable_or_null bytes (or zero if unknown) of 
an
   /// arg.
   LLVM_ABI uint64_t getParamDereferenceableOrNullBytes(unsigned ArgNo) const;
@@ -1242,6 +1285,10 @@ class AttrBuilder {
   /// internally in Attribute.
   LLVM_ABI AttrBuilder &addDereferenceableAttr(uint64_t Bytes);
 
+  /// This turns the number of dead_on_return bytes into the form used
+  /// internally in Attribute.
+  LLVM_ABI AttrBuilder &addDeadOnReturnAttr(DeadOnReturnInfo Info);
+
   /// This turns the number of dereferenceable_or_null bytes into the
   /// form used internally in Attribute.
   LLVM_ABI AttrBuilder &addDereferenceableOrNullAttr(uint64_t Bytes);
diff --git a/llvm/include/llvm/IR/Attributes.td 
b/llvm/include/llvm/IR/Attributes.td
index c086a39616249..e4db0e6984780 100644
--- a/llvm/include/llvm/IR/Attributes.td
+++ b/llvm/include/llvm/IR/Attributes.td
@@ -204,7 +204,7 @@ def NoFree : EnumAttr<"nofree", IntersectAnd, [FnAttr, 
ParamAttr]>;
 def DeadOnUnwind : EnumAttr<"dead_on_unwind", IntersectAnd, [ParamAttr]>;
 
 /// Argument is dead upon function return.
-def DeadOnReturn : EnumAttr<"dead_on_return", IntersectAnd, [ParamAttr]>;
+def DeadOnReturn : IntAttr<"dead_on_return", IntersectMin, [ParamAttr]>;
 
 /// Disable implicit floating point insts.
 def NoImplicitFloat : EnumAttr<"noimplicitfloat", IntersectPreserve, [FnAttr]>;
diff --git a/llvm/include/llvm/IR/Function.h b/llvm/include/llvm/IR/Function.h
index d3497716ca844..fd94b4fd98b4e 100644
--- a/llvm/include/llvm/IR/Function.h
+++ b/llvm/include/llvm/IR/Function.h
@@ -523,6 +523,12 @@ class LLVM_ABI Function : public GlobalObject, public 
ilist_node<Function> {
     return AttributeSets.getParamDereferenceableBytes(ArgNo);
   }
 
+  /// Extract the number of dead_on_return bytes for a parameter.
+  /// @param ArgNo Index of an argument, with 0 being the first function arg.
+  DeadOnReturnInfo getDeadOnReturnInfo(unsigned ArgNo) const {
+    return AttributeSets.getDeadOnReturnInfo(ArgNo);
+  }
+
   /// Extract the number of dereferenceable_or_null bytes for a
   /// parameter.
   /// @param ArgNo AttributeList ArgNo, referring to an argument.
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index a09ab4fc7828c..54ec602935ed1 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -20,6 +20,7 @@
 #include "llvm/AsmParser/SlotMapping.h"
 #include "llvm/BinaryFormat/Dwarf.h"
 #include "llvm/IR/Argument.h"
+#include "llvm/IR/Attributes.h"
 #include "llvm/IR/AutoUpgrade.h"
 #include "llvm/IR/BasicBlock.h"
 #include "llvm/IR/CallingConv.h"
@@ -1606,17 +1607,30 @@ bool LLParser::parseEnumAttribute(Attribute::AttrKind 
Attr, AttrBuilder &B,
     return false;
   }
   case Attribute::Dereferenceable: {
-    uint64_t Bytes;
-    if (parseOptionalDerefAttrBytes(lltok::kw_dereferenceable, 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: {
+    std::optional<uint64_t> Bytes;
+    if (parseOptionalAttrBytes(lltok::kw_dead_on_return, Bytes))
+      return true;
+    if (Bytes.has_value()) {
+      B.addDeadOnReturnAttr(DeadOnReturnInfo(Bytes.value()));
+    } else {
+      B.addDeadOnReturnAttr(DeadOnReturnInfo());
+    }
     return false;
   }
   case Attribute::DereferenceableOrNull: {
-    uint64_t Bytes;
-    if (parseOptionalDerefAttrBytes(lltok::kw_dereferenceable_or_null, 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: {
@@ -2468,31 +2482,38 @@ bool LLParser::parseOptionalCodeModel(CodeModel::Model 
&model) {
   return false;
 }
 
-/// parseOptionalDerefAttrBytes
+/// parseOptionalAttrBytes
 ///   ::= /* empty */
 ///   ::= AttrKind '(' 4 ')'
 ///
-/// where AttrKind is either 'dereferenceable' or 'dereferenceable_or_null'.
-bool LLParser::parseOptionalDerefAttrBytes(lltok::Kind AttrKind,
-                                           uint64_t &Bytes) {
+/// where AttrKind is either 'dereferenceable', 'dereferenceable_or_null', or
+/// 'dead_on_return'
+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_dereferenceable_or_null ||
+          AttrKind == lltok::kw_dead_on_return) &&
          "contract!");
 
   Bytes = 0;
   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/Bitcode/Reader/BitcodeReader.cpp 
b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index 9dd993f0dc173..9a4a951d71a08 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -80,6 +80,7 @@
 #include <cstddef>
 #include <cstdint>
 #include <deque>
+#include <limits>
 #include <map>
 #include <memory>
 #include <optional>
@@ -2384,6 +2385,8 @@ Error BitcodeReader::parseAttributeGroupBlock() {
             B.addInAllocaAttr(nullptr);
           else if (Kind == Attribute::UWTable)
             B.addUWTableAttr(UWTableKind::Default);
+          else if (Kind == Attribute::DeadOnReturn)
+            B.addDeadOnReturnAttr(DeadOnReturnInfo());
           else if (Attribute::isEnumAttrKind(Kind))
             B.addAttribute(Kind);
           else
@@ -2402,6 +2405,8 @@ Error BitcodeReader::parseAttributeGroupBlock() {
             B.addDereferenceableAttr(Record[++i]);
           else if (Kind == Attribute::DereferenceableOrNull)
             B.addDereferenceableOrNullAttr(Record[++i]);
+          else if (Kind == Attribute::DeadOnReturn)
+            B.addDeadOnReturnAttr(DeadOnReturnInfo(Record[++i]));
           else if (Kind == Attribute::AllocSize)
             B.addAllocSizeAttrFromRawRepr(Record[++i]);
           else if (Kind == Attribute::VScaleRange)
diff --git a/llvm/lib/IR/AttributeImpl.h b/llvm/lib/IR/AttributeImpl.h
index 707c8205ee1f9..91ba0ab8bc969 100644
--- a/llvm/lib/IR/AttributeImpl.h
+++ b/llvm/lib/IR/AttributeImpl.h
@@ -332,6 +332,7 @@ class AttributeSetNode final
   MaybeAlign getAlignment() const;
   MaybeAlign getStackAlignment() const;
   uint64_t getDereferenceableBytes() const;
+  DeadOnReturnInfo getDeadOnReturnInfo() 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 fe6d3e5edeb09..5dc7d79beca3f 100644
--- a/llvm/lib/IR/Attributes.cpp
+++ b/llvm/lib/IR/Attributes.cpp
@@ -451,6 +451,13 @@ uint64_t Attribute::getDereferenceableBytes() const {
   return pImpl->getValueAsInt();
 }
 
+DeadOnReturnInfo Attribute::getDeadOnReturnInfo() const {
+  assert(hasAttribute(Attribute::DeadOnReturn) &&
+         "Trying to get dead_on_return bytes from"
+         "a parameter without such an attribute!");
+  return DeadOnReturnInfo::createFromintValue(pImpl->getValueAsInt());
+}
+
 uint64_t Attribute::getDereferenceableOrNullBytes() const {
   assert(hasAttribute(Attribute::DereferenceableOrNull) &&
          "Trying to get dereferenceable bytes from "
@@ -574,6 +581,13 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
   if (hasAttribute(Attribute::DereferenceableOrNull))
     return AttrWithBytesToString("dereferenceable_or_null");
 
+  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;
     std::optional<unsigned> NumElems;
@@ -1162,6 +1176,10 @@ uint64_t AttributeSet::getDereferenceableBytes() const {
   return SetNode ? SetNode->getDereferenceableBytes() : 0;
 }
 
+DeadOnReturnInfo AttributeSet::getDeadOnReturnInfo() const {
+  return SetNode ? SetNode->getDeadOnReturnInfo() : DeadOnReturnInfo(0);
+}
+
 uint64_t AttributeSet::getDereferenceableOrNullBytes() const {
   return SetNode ? SetNode->getDereferenceableOrNullBytes() : 0;
 }
@@ -1366,6 +1384,12 @@ uint64_t AttributeSetNode::getDereferenceableBytes() 
const {
   return 0;
 }
 
+DeadOnReturnInfo AttributeSetNode::getDeadOnReturnInfo() const {
+  if (auto A = findEnumAttribute(Attribute::DeadOnReturn))
+    return A->getDeadOnReturnInfo();
+  return 0;
+}
+
 uint64_t AttributeSetNode::getDereferenceableOrNullBytes() const {
   if (auto A = findEnumAttribute(Attribute::DereferenceableOrNull))
     return A->getDereferenceableOrNullBytes();
@@ -1983,6 +2007,10 @@ uint64_t 
AttributeList::getRetDereferenceableOrNullBytes() const {
   return getRetAttrs().getDereferenceableOrNullBytes();
 }
 
+DeadOnReturnInfo AttributeList::getDeadOnReturnInfo(unsigned Index) const {
+  return getParamAttrs(Index).getDeadOnReturnInfo();
+}
+
 uint64_t
 AttributeList::getParamDereferenceableOrNullBytes(unsigned Index) const {
   return getParamAttrs(Index).getDereferenceableOrNullBytes();
@@ -2205,6 +2233,13 @@ AttrBuilder 
&AttrBuilder::addDereferenceableAttr(uint64_t Bytes) {
   return addRawIntAttr(Attribute::Dereferenceable, Bytes);
 }
 
+AttrBuilder &AttrBuilder::addDeadOnReturnAttr(DeadOnReturnInfo Info) {
+  if (Info.isZeroSized())
+    return *this;
+
+  return addRawIntAttr(Attribute::DeadOnReturn, Info.toIntValue());
+}
+
 AttrBuilder &AttrBuilder::addDereferenceableOrNullAttr(uint64_t Bytes) {
   if (Bytes == 0)
     return *this;
diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp
index 31a294447152e..467bd80d818fe 100644
--- a/llvm/lib/IR/Function.cpp
+++ b/llvm/lib/IR/Function.cpp
@@ -130,10 +130,9 @@ bool Argument::hasByValAttr() const {
   return hasAttribute(Attribute::ByVal);
 }
 
-bool Argument::hasDeadOnReturnAttr() const {
-  if (!getType()->isPointerTy())
-    return false;
-  return hasAttribute(Attribute::DeadOnReturn);
+DeadOnReturnInfo Argument::getDeadOnReturnInfo() const {
+  assert(getType()->isPointerTy() && "Only pointers have dead_on_return 
bytes");
+  return getParent()->getDeadOnReturnInfo(getArgNo());
 }
 
 bool Argument::hasByRefAttr() const {
diff --git a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp 
b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
index 4ac1321860f66..87393cd595e97 100644
--- a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
@@ -1017,7 +1017,9 @@ struct DSEState {
     // 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() || AI.hasDeadOnReturnAttr())
+      if (AI.hasPassPointeeByValueCopyAttr() ||
+          (AI.getType()->isPointerTy() &&
+           AI.getDeadOnReturnInfo().coversAllReachableMemory()))
         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 107a98aebeeb8..4f234d7a40079 100644
--- a/llvm/test/Bitcode/attributes.ll
+++ b/llvm/test/Bitcode/attributes.ll
@@ -582,6 +582,11 @@ 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
+}
+
 ; CHECK: attributes #0 = { noreturn }
 ; CHECK: attributes #1 = { nounwind }
 ; CHECK: attributes #2 = { memory(none) }
diff --git a/llvm/test/Bitcode/dead-on-return-upgrade.ll 
b/llvm/test/Bitcode/dead-on-return-upgrade.ll
new file mode 100644
index 0000000000000..ddf70f453091e
--- /dev/null
+++ b/llvm/test/Bitcode/dead-on-return-upgrade.ll
@@ -0,0 +1,7 @@
+; RUN: llvm-dis -o - %s.bc | FileCheck %s
+
+; 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/Bitcode/dead-on-return-upgrade.ll.bc 
b/llvm/test/Bitcode/dead-on-return-upgrade.ll.bc
new file mode 100644
index 
0000000000000000000000000000000000000000..a2432d5a39b5b0a28b2e4872340e1e704fde370a
GIT binary patch
literal 1612
zcmXX`Z%h+s7=Oz_uR?vVGE@q8-Bp<BjM1}zv|O7&&uNV=D{LQF;sS-X;-*+i`Rn3Z
z%e*@Kp)>u^B`$-^EbbdFd|(SMw8vP79YeD$Bofk&g0P?vWsAxDu;*Zx^m+T<pXYs^
z-=D`OOfJ@xAXI=5YEyHSZ@>TJH<$h$d#5~Ac|u_<KzcPo7ZnH<<>^r#ymJ74WU%7%
zhE)D(rN(H!r5IAbQJ~W5@^7{U)Nke4ZWY;F8e@q`ReGk-Xbjs&U3%eqIR6xFv{iPc
zRC_AltiK-7oKYBEL#kUeTOov(kydNV*B&w)iZ-5OE55J4uGUKAgS}c~BvMIgjctd`
zspy`HRB;$Hb*>YqQknz8$vkZty1^o}ORmY2ulde)?H5fGglJdNVK3ZuP?#>T84s#d
zWeS6h)1byuv|WFBm_@VD&uQ4hf?m6ZP?`QL{$l_A-Jd*s(EY>BUv*82uMnz-hdbA%
zqPRT&vm_ui)rKC!y((3Jp32gm5`{G^n1-Z?EkF+Rlil$y^$Mb%YVcM7SE+5fWP+I;
zp*>u|_G_W?G+|8%)(Bxu_ecC*@`{Qau!~+VIp`&N`$aD+YSVl0dK70ls*|IZHu0td
zS81l0MLj*QXOd2xhr7W~g!nnZJVsb1LY5(dPj8m=wvtym$l4Ck2QeUeqoTK!>@|?R
zFAE@TUqEb8iCv|lFD?$mgNL7O;%6EB_at8Dh_=)Sog1Ok+i}53&*<r?AT#4s{t*?-
zDZw1yj^mOkCYZtmACr#4p|7s-zZ3kZr2hGW=xr8#-jKh8>~9tQrJ{dW)Xu(3Jww!U
z2hK(DQazPr@j7(D8kmKIF4>@aq^B2xx`hm#%QAl{be_^i)2L8)JH)3QmH#)=D)#l0
z{qe@LTTx0zK=+|;#!0X0nZ*QiRiTp$)-#(<<$IroOlgT96|4ZrtE43-@L||Wk)H~o
zQ?U=~QIUfN(iab&Thie5Nxba9FSv@tqXu0ryMI2*EJ6WxEk7Evj)lsHBvV8%rzOjH
z!km(zM@!m1)}<n$sxAPqS=2tB#_O%r(~NSHrItBrnWg@5;7$!*;xKGqWRz<eoO9rp
zT*aU3PC6N6=Ck|P^~{Q%nbI@B;Hv(05BnuQAy~%=b1Y;|H%|cj(Ci@8X&3vvqV~ZP
zyune~3|_0J)`sB}NkMeqC83v=I7mfC*gpqU28SBV83~}X0#oVwsbOYjgvm7M78A6m
zvYo?OnO_Q$EOUZB)Kf}!+r^e)@#6q|doQN2L?la0GR+BfAg44Srnc+%+MGHlbvD5?
z1xq|<&vST#r8Y9k4F|O)r^3q_<qAt>=b+iI>qEUA<bX=lHkFM_Jm~O_U`hjqggF|r
zqzMav8I#l}cTa<KK~W?0)u8UV0(hLhrvwE;9^j&?_;{)44UmI($pHgUmKbX=jS~EX
zWO|inosjBcAs&4TKCK1M6&3mnpk;Ef*&7G^<krn|(zO+OdSv%%gKRaZeMckvs+U^v
z69-6-%E<zxo;dK<XdoybB0HmB1Xg8TG<$DLrZEM7CuEIDc^`qv=!Go3z|uLV99M(7
zq?4W-p;J3#Iui<N3jhE-0=Ou=18Tu<CV+4rj3NQ0JSYhKog(<d2H^h@WOF7?;APMV
z@YzabA%g$rlrN&xQx<PbVtK?o)F7mUl}uaig!tQFG{QO@vViHLl02iFhMoCbp~~Aw
zt9ItrK8;2G6m_u(5wIGu=D-kIlSlOS^#RQ7a`;zF#O}*C{O)dli_7hFwOsCO@wxpy
zzRnhBkN<Ly_q@;PavP0DxFg*83x3w!?yfQ$Yiese)yJxgwe4<`(OKQ*YIE0cX0!RY
b`&hNfU0v&HKkC2aJt}8Ca`EE!i3t4%@9aHT

literal 0
HcmV?d00001

diff --git a/llvm/test/Verifier/dead-on-return.ll 
b/llvm/test/Verifier/dead-on-return.ll
index eb1d67fa319c2..e2c29d2c980ae 100644
--- a/llvm/test/Verifier/dead-on-return.ll
+++ b/llvm/test/Verifier/dead-on-return.ll
@@ -5,3 +5,9 @@
 define void @arg_not_pointer(i32 dead_on_return %arg) {
   ret void
 }
+
+; CHECK: Attribute 'dead_on_return(4)' applied to incompatible type!
+; CHECK-NEXT: ptr @arg_not_pointer2
+define void @arg_not_pointer2(i32 dead_on_return(4) %arg) {
+  ret void
+}

>From ba9d3c13c2efe720833d62f1c6cbc150eb399ceb Mon Sep 17 00:00:00 2001
From: Aiden Grossman <[email protected]>
Date: Sat, 27 Dec 2025 02:05:36 +0000
Subject: [PATCH 2/5] formatting

Created using spr 1.3.7
---
 llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp 
b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
index 25d473b5beb72..78734beac4bbe 100644
--- a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
@@ -1214,7 +1214,8 @@ struct DSEState {
     return OW_None;
   }
 
-  bool isInvisibleToCallerAfterRet(const Value *V, const Value *Ptr, const 
LocationSize StoreSize) {
+  bool isInvisibleToCallerAfterRet(const Value *V, const Value *Ptr,
+                                   const LocationSize StoreSize) {
     if (isa<AllocaInst>(V))
       return true;
 
@@ -1774,7 +1775,8 @@ struct DSEState {
           BasicBlock *MaybeKillingBlock = UseInst->getParent();
           if (PostOrderNumbers.find(MaybeKillingBlock)->second <
               PostOrderNumbers.find(MaybeDeadAccess->getBlock())->second) {
-            if (!isInvisibleToCallerAfterRet(KillingUndObj, KillingLoc.Ptr, 
KillingLoc.Size)) {
+            if (!isInvisibleToCallerAfterRet(KillingUndObj, KillingLoc.Ptr,
+                                             KillingLoc.Size)) {
               LLVM_DEBUG(dbgs()
                          << "    ... found killing def " << *UseInst << "\n");
               KillingDefs.insert(UseInst);
@@ -1792,7 +1794,8 @@ struct DSEState {
     // For accesses to locations visible after the function returns, make sure
     // that the location is dead (=overwritten) along all paths from
     // MaybeDeadAccess to the exit.
-    if (!isInvisibleToCallerAfterRet(KillingUndObj, KillingLoc.Ptr, 
KillingLoc.Size)) {
+    if (!isInvisibleToCallerAfterRet(KillingUndObj, KillingLoc.Ptr,
+                                     KillingLoc.Size)) {
       SmallPtrSet<BasicBlock *, 16> KillingBlocks;
       for (Instruction *KD : KillingDefs)
         KillingBlocks.insert(KD->getParent());

>From 3b55b98f88ded624e1f09c000b25e9c0d41adb3d Mon Sep 17 00:00:00 2001
From: Aiden Grossman <[email protected]>
Date: Sun, 11 Jan 2026 07:52:23 +0000
Subject: [PATCH 3/5] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20ch?=
 =?UTF-8?q?anges=20introduced=20through=20rebase?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.7

[skip ci]
---
 llvm/docs/LangRef.rst                  | 11 +++++------
 llvm/include/llvm/AsmParser/LLParser.h |  2 +-
 llvm/include/llvm/IR/Attributes.h      |  4 ++--
 llvm/lib/AsmParser/LLParser.cpp        |  3 ++-
 4 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 0c2b973e0ec97..a5eb79be1a508 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -1846,10 +1846,10 @@ Currently, only the following parameter attributes are 
defined:
     This attribute indicates that the memory pointed to by the argument is dead
     upon function return, both upon normal return and if the calls unwinds, 
meaning
     that the caller will not depend on its contents. Stores that would be 
observable
-    either on the return path or on the unwind path may be elided. The number 
of
-    bytes known to be dead can optionally be provided in parentheses. It is 
legal
+    either on the return path or on the unwind path may be elided. A number of
+    bytes known to be dead may optionally be provided in parentheses. It is 
legal
     for the number of bytes to be less than the size of the pointee type. If a 
number
-    of bytes is not specified, all memory rechable through the pointer is 
marked as
+    of bytes is not specified, all memory reachable through the pointer is 
marked as
     dead on return.
 
     Specifically, the behavior is as-if any memory written through the pointer
@@ -1859,9 +1859,8 @@ Currently, only the following parameter attributes are 
defined:
 
     This attribute does not imply aliasing properties. For pointer arguments 
that
     do not alias other memory locations, ``noalias`` attribute may be used in
-    conjunction. Conversely, this attribute always implies ``dead_on_unwind``. 
If
-    a number of bytes is specified, then only those bytes are implied to be
-    ``dead_on_unwind``.
+    conjunction. Conversely, this attribute always implies ``dead_on_unwind``. 
When
+    a byte count is specified, ``dead_on_unwind`` is implied only for that 
range.
 
     This attribute cannot be applied to return values.
 
diff --git a/llvm/include/llvm/AsmParser/LLParser.h 
b/llvm/include/llvm/AsmParser/LLParser.h
index b792155206f05..185847f258cda 100644
--- a/llvm/include/llvm/AsmParser/LLParser.h
+++ b/llvm/include/llvm/AsmParser/LLParser.h
@@ -321,7 +321,7 @@ namespace llvm {
     bool parseOptionalCodeModel(CodeModel::Model &model);
     bool parseOptionalAttrBytes(lltok::Kind AttrKind,
                                 std::optional<uint64_t> &Bytes,
-                                bool ErrorNoBytes = false);
+                                bool ErrorNoBytes = true);
     bool parseOptionalUWTableKind(UWTableKind &Kind);
     bool parseAllocKind(AllocFnKind &Kind);
     std::optional<MemoryEffects> parseMemoryAttr();
diff --git a/llvm/include/llvm/IR/Attributes.h 
b/llvm/include/llvm/IR/Attributes.h
index b89832bc14b08..fe673705cf335 100644
--- a/llvm/include/llvm/IR/Attributes.h
+++ b/llvm/include/llvm/IR/Attributes.h
@@ -65,14 +65,14 @@ class DeadOnReturnInfo {
   DeadOnReturnInfo() : DeadBytes(std::nullopt) {}
   DeadOnReturnInfo(uint64_t DeadOnReturnBytes) : DeadBytes(DeadOnReturnBytes) 
{}
 
-  uint64_t getNumberOfDeadBytes() {
+  uint64_t getNumberOfDeadBytes() const {
     assert(DeadBytes.has_value() &&
            "This attribute does not specify a byte count. Did you forget to "
            "check if the attribute covers all reachable memory?");
     return DeadBytes.value();
   }
 
-  bool coversAllReachableMemory() { return !DeadBytes.has_value(); }
+  bool coversAllReachableMemory() const { return !DeadBytes.has_value(); }
 
   static DeadOnReturnInfo createFromintValue(uint64_t Data) {
     if (Data == std::numeric_limits<uint64_t>::max())
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 4187bf1992b0f..66f128ed3a1f1 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -1616,7 +1616,8 @@ bool LLParser::parseEnumAttribute(Attribute::AttrKind 
Attr, AttrBuilder &B,
   }
   case Attribute::DeadOnReturn: {
     std::optional<uint64_t> Bytes;
-    if (parseOptionalAttrBytes(lltok::kw_dead_on_return, Bytes))
+    if (parseOptionalAttrBytes(lltok::kw_dead_on_return, Bytes,
+                               /*ErrorNoBytes=*/false))
       return true;
     if (Bytes.has_value()) {
       B.addDeadOnReturnAttr(DeadOnReturnInfo(Bytes.value()));

>From 805d7b8f4c1bb9d394a6d0760bc7de2a274fda30 Mon Sep 17 00:00:00 2001
From: Aiden Grossman <[email protected]>
Date: Wed, 14 Jan 2026 17:22:23 +0000
Subject: [PATCH 4/5] feedback

Created using spr 1.3.7
---
 .../Scalar/DeadStoreElimination.cpp           | 27 ++++++++++------
 .../Transforms/DeadStoreElimination/simple.ll | 31 +++++++++++++++++--
 2 files changed, 46 insertions(+), 12 deletions(-)

diff --git a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp 
b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
index 78734beac4bbe..20436b92412f9 100644
--- a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
@@ -1018,16 +1018,19 @@ struct DSEState {
     // 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() ||
-          (AI.getType()->isPointerTy() &&
-           AI.getDeadOnReturnInfo().coversAllReachableMemory()))
+      if (AI.hasPassPointeeByValueCopyAttr()) {
         InvisibleToCallerAfterRet.insert({&AI, true});
-      if (AI.getType()->isPointerTy() &&
-          !AI.getDeadOnReturnInfo().coversAllReachableMemory()) {
-        if (uint64_t DeadOnReturnBytes =
-                AI.getDeadOnReturnInfo().getNumberOfDeadBytes())
-          InvisibleToCallerAfterRetBounded.insert({&AI, DeadOnReturnBytes});
+        continue;
       }
+
+      if (!AI.getType()->isPointerTy())
+        continue;
+
+      const DeadOnReturnInfo &Info = AI.getDeadOnReturnInfo();
+      if (Info.coversAllReachableMemory())
+        InvisibleToCallerAfterRet.insert({&AI, true});
+      else if (uint64_t DeadBytes = Info.getNumberOfDeadBytes())
+        InvisibleToCallerAfterRetBounded.insert({&AI, DeadBytes});
     }
 
     // Collect whether there is any irreducible control flow in the function.
@@ -1225,8 +1228,11 @@ struct DSEState {
       const Value *BaseValue =
           GetPointerBaseWithConstantOffset(Ptr, ValueOffset, DL);
       assert(BaseValue == V);
-      if (ValueOffset + StoreSize.toRaw() <
-          InvisibleToCallerAfterRetBounded[BaseValue])
+      // This store is only invisible after return if we are in bounds of the
+      // range marked dead.
+      if (ValueOffset + StoreSize.getValue() <=
+              InvisibleToCallerAfterRetBounded[BaseValue] &&
+          ValueOffset >= 0)
         return true;
     }
     if (I.second && isInvisibleToCallerOnUnwind(V) && isNoAliasCall(V))
@@ -1899,6 +1905,7 @@ struct DSEState {
               if (CapturedBeforeReturn.erase(UO))
                 ShouldIterateEndOfFunctionDSE = true;
               InvisibleToCallerAfterRet.erase(UO);
+              InvisibleToCallerAfterRetBounded.erase(UO);
             }
           }
         }
diff --git a/llvm/test/Transforms/DeadStoreElimination/simple.ll 
b/llvm/test/Transforms/DeadStoreElimination/simple.ll
index 7619842ea18cf..855cae3f70259 100644
--- a/llvm/test/Transforms/DeadStoreElimination/simple.ll
+++ b/llvm/test/Transforms/DeadStoreElimination/simple.ll
@@ -901,6 +901,18 @@ define void @test_dead_on_return_oob(ptr dead_on_return(4) 
%p) {
   ret void
 }
 
+define void @test_dead_on_return_zero_offset(ptr dead_on_return(8) %p) {
+; CHECK-LABEL: @test_dead_on_return_zero_offset(
+; CHECK-NEXT:    [[LOCAL_VAR:%.*]] = alloca ptr, align 8
+; CHECK-NEXT:    call void @opaque(ptr [[LOCAL_VAR]])
+; CHECK-NEXT:    ret void
+;
+  %local.var = alloca ptr
+  call void @opaque(ptr %local.var)
+  store ptr %local.var, ptr %p
+  ret void
+}
+
 define void @test_dead_on_return_inbounds(ptr dead_on_return(16) %p) {
 ; CHECK-LABEL: @test_dead_on_return_inbounds(
 ; CHECK-NEXT:    [[LOCAL_VAR:%.*]] = alloca ptr, align 8
@@ -914,8 +926,8 @@ define void @test_dead_on_return_inbounds(ptr 
dead_on_return(16) %p) {
   ret void
 }
 
-define void @test_on_return_overlapping_oob(ptr dead_on_return(8) %p) {
-; CHECK-LABEL: @test_on_return_overlapping_oob(
+define void @test_dead_on_return_overlapping_oob(ptr dead_on_return(8) %p) {
+; CHECK-LABEL: @test_dead_on_return_overlapping_oob(
 ; CHECK-NEXT:    [[LOCAL_VAR:%.*]] = alloca ptr, align 8
 ; CHECK-NEXT:    call void @opaque(ptr [[LOCAL_VAR]])
 ; CHECK-NEXT:    [[P1:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 4
@@ -929,5 +941,20 @@ define void @test_on_return_overlapping_oob(ptr 
dead_on_return(8) %p) {
   ret void
 }
 
+define void @test_dead_on_return_negative_oob(ptr dead_on_return(8) %p) {
+; CHECK-LABEL: @test_dead_on_return_negative_oob(
+; CHECK-NEXT:    [[LOCAL_VAR:%.*]] = alloca ptr, align 8
+; CHECK-NEXT:    call void @opaque(ptr [[LOCAL_VAR]])
+; CHECK-NEXT:    [[P1:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 -4
+; CHECK-NEXT:    store ptr [[LOCAL_VAR]], ptr [[P1]], align 8
+; CHECK-NEXT:    ret void
+;
+  %local.var = alloca ptr
+  call void @opaque(ptr %local.var)
+  %p1 = getelementptr inbounds i8, ptr %p, i64 -4
+  store ptr %local.var, ptr %p1
+  ret void
+}
+
 declare void @opaque(ptr)
 declare void @maythrow() memory(none)

>From f7ac1841ce7dacff0fdc64d9a99ef228ce0d9145 Mon Sep 17 00:00:00 2001
From: Aiden Grossman <[email protected]>
Date: Thu, 15 Jan 2026 01:57:11 +0000
Subject: [PATCH 5/5] feedback

Created using spr 1.3.7
---
 .../lib/Transforms/Scalar/DeadStoreElimination.cpp |  4 ++--
 .../test/Transforms/DeadStoreElimination/simple.ll | 14 ++++++++++++++
 2 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp 
b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
index 20436b92412f9..4a313230c2003 100644
--- a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
@@ -1222,8 +1222,7 @@ struct DSEState {
     if (isa<AllocaInst>(V))
       return true;
 
-    auto I = InvisibleToCallerAfterRet.insert({V, false});
-    if (I.second && InvisibleToCallerAfterRetBounded.contains(V)) {
+    if (InvisibleToCallerAfterRetBounded.contains(V)) {
       int64_t ValueOffset;
       const Value *BaseValue =
           GetPointerBaseWithConstantOffset(Ptr, ValueOffset, DL);
@@ -1235,6 +1234,7 @@ struct DSEState {
           ValueOffset >= 0)
         return true;
     }
+    auto I = InvisibleToCallerAfterRet.insert({V, false});
     if (I.second && isInvisibleToCallerOnUnwind(V) && isNoAliasCall(V))
       I.first->second = capturesNothing(PointerMayBeCaptured(
           V, /*ReturnCaptures=*/true, CaptureComponents::Provenance));
diff --git a/llvm/test/Transforms/DeadStoreElimination/simple.ll 
b/llvm/test/Transforms/DeadStoreElimination/simple.ll
index 855cae3f70259..cf3d9ad4bd316 100644
--- a/llvm/test/Transforms/DeadStoreElimination/simple.ll
+++ b/llvm/test/Transforms/DeadStoreElimination/simple.ll
@@ -956,5 +956,19 @@ define void @test_dead_on_return_negative_oob(ptr 
dead_on_return(8) %p) {
   ret void
 }
 
+define void @test_dead_on_return_two_stores(ptr dead_on_return(16) %p) {
+; CHECK-LABEL: @test_dead_on_return_two_stores(
+; CHECK-NEXT:    [[LOCAL_VAR:%.*]] = alloca ptr, align 8
+; CHECK-NEXT:    call void @opaque(ptr [[LOCAL_VAR]])
+; CHECK-NEXT:    ret void
+;
+  %local.var = alloca ptr
+  call void @opaque(ptr %local.var)
+  store ptr %local.var, ptr %p
+  %p1 = getelementptr inbounds i8, ptr %p, i64 8
+  store ptr %local.var, ptr %p1
+  ret void
+}
+
 declare void @opaque(ptr)
 declare void @maythrow() memory(none)

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to