[llvm-branch-commits] [llvm] aba17bb - [IR] Use alloc markers for operator delete variants (#138261)
Cullen Rhodes via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Jan 22 00:24:52 PST 2026
Author: Marc Auberer
Date: 2026-01-22T08:24:43Z
New Revision: aba17bb896b75b2a64753b937599b44eb76678a9
URL: https://github.com/llvm/llvm-project/commit/aba17bb896b75b2a64753b937599b44eb76678a9
DIFF: https://github.com/llvm/llvm-project/commit/aba17bb896b75b2a64753b937599b44eb76678a9.diff
LOG: [IR] Use alloc markers for operator delete variants (#138261)
Follow-up to https://github.com/llvm/llvm-project/pull/129914
This fixes the problem properly by using the data via the allocation
markers.
PS: Sorry for the long delay ;)
(cherry picked from commit 72d5925412522d01e48f8d6027e51c2dead11617)
Added:
Modified:
llvm/include/llvm/Analysis/MemorySSA.h
llvm/include/llvm/IR/Constants.h
llvm/include/llvm/IR/GlobalAlias.h
llvm/include/llvm/IR/GlobalIFunc.h
llvm/include/llvm/IR/GlobalVariable.h
llvm/include/llvm/IR/InstrTypes.h
llvm/include/llvm/IR/Instructions.h
llvm/include/llvm/IR/User.h
llvm/lib/IR/ConstantsContext.h
llvm/lib/IR/User.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/Analysis/MemorySSA.h b/llvm/include/llvm/Analysis/MemorySSA.h
index 07d39ab3e10a9..ab44bc09d9550 100644
--- a/llvm/include/llvm/Analysis/MemorySSA.h
+++ b/llvm/include/llvm/Analysis/MemorySSA.h
@@ -318,7 +318,7 @@ class MemoryUse final : public MemoryUseOrDef {
// allocate space for exactly one operand
void *operator new(size_t S) { return User::operator new(S, AllocMarker); }
- void operator delete(void *Ptr) { User::operator delete(Ptr); }
+ void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); }
static bool classof(const Value *MA) {
return MA->getValueID() == MemoryUseVal;
@@ -383,7 +383,7 @@ class MemoryDef final : public MemoryUseOrDef {
// allocate space for exactly two operands
void *operator new(size_t S) { return User::operator new(S, AllocMarker); }
- void operator delete(void *Ptr) { User::operator delete(Ptr); }
+ void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); }
static bool classof(const Value *MA) {
return MA->getValueID() == MemoryDefVal;
@@ -483,7 +483,7 @@ class MemoryPhi final : public MemoryAccess {
void *operator new(size_t S) { return User::operator new(S, AllocMarker); }
public:
- void operator delete(void *Ptr) { User::operator delete(Ptr); }
+ void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); }
/// Provide fast operand accessors
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess);
diff --git a/llvm/include/llvm/IR/Constants.h b/llvm/include/llvm/IR/Constants.h
index 3bb2fa28cced8..6bf990c69e19f 100644
--- a/llvm/include/llvm/IR/Constants.h
+++ b/llvm/include/llvm/IR/Constants.h
@@ -917,7 +917,7 @@ class BlockAddress final : public Constant {
Value *handleOperandChangeImpl(Value *From, Value *To);
public:
- void operator delete(void *Ptr) { User::operator delete(Ptr); }
+ void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); }
/// Return a BlockAddress for the specified function and basic block.
LLVM_ABI static BlockAddress *get(Function *F, BasicBlock *BB);
@@ -970,7 +970,7 @@ class DSOLocalEquivalent final : public Constant {
Value *handleOperandChangeImpl(Value *From, Value *To);
public:
- void operator delete(void *Ptr) { User::operator delete(Ptr); }
+ void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); }
/// Return a DSOLocalEquivalent for the specified global value.
LLVM_ABI static DSOLocalEquivalent *get(GlobalValue *GV);
diff --git a/llvm/include/llvm/IR/GlobalAlias.h b/llvm/include/llvm/IR/GlobalAlias.h
index 12b9f053abb17..c0a6c3d69374c 100644
--- a/llvm/include/llvm/IR/GlobalAlias.h
+++ b/llvm/include/llvm/IR/GlobalAlias.h
@@ -63,7 +63,7 @@ class GlobalAlias : public GlobalValue, public ilist_node<GlobalAlias> {
// allocate space for exactly one operand
void *operator new(size_t S) { return User::operator new(S, AllocMarker); }
- void operator delete(void *Ptr) { User::operator delete(Ptr); }
+ void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); }
/// Provide fast operand accessors
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant);
diff --git a/llvm/include/llvm/IR/GlobalIFunc.h b/llvm/include/llvm/IR/GlobalIFunc.h
index d93146aa016be..853b3fe250cc9 100644
--- a/llvm/include/llvm/IR/GlobalIFunc.h
+++ b/llvm/include/llvm/IR/GlobalIFunc.h
@@ -52,7 +52,7 @@ class GlobalIFunc final : public GlobalObject, public ilist_node<GlobalIFunc> {
// allocate space for exactly one operand
void *operator new(size_t S) { return User::operator new(S, AllocMarker); }
- void operator delete(void *Ptr) { User::operator delete(Ptr); }
+ void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); }
/// Provide fast operand accessors
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant);
diff --git a/llvm/include/llvm/IR/GlobalVariable.h b/llvm/include/llvm/IR/GlobalVariable.h
index d1d42cebc1352..8e6af8ae6e203 100644
--- a/llvm/include/llvm/IR/GlobalVariable.h
+++ b/llvm/include/llvm/IR/GlobalVariable.h
@@ -100,7 +100,7 @@ class GlobalVariable : public GlobalObject, public ilist_node<GlobalVariable> {
void *operator new(size_t s) { return User::operator new(s, AllocMarker); }
// delete space for exactly one operand as created in the corresponding new operator
- void operator delete(void *ptr) { User::operator delete(ptr); }
+ void operator delete(void *ptr) { User::operator delete(ptr, AllocMarker); }
/// Provide fast operand accessors
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
diff --git a/llvm/include/llvm/IR/InstrTypes.h b/llvm/include/llvm/IR/InstrTypes.h
index 9f56779a9b935..55cc26d1e9c8f 100644
--- a/llvm/include/llvm/IR/InstrTypes.h
+++ b/llvm/include/llvm/IR/InstrTypes.h
@@ -68,7 +68,7 @@ class UnaryInstruction : public Instruction {
public:
// allocate space for exactly one operand
void *operator new(size_t S) { return User::operator new(S, AllocMarker); }
- void operator delete(void *Ptr) { User::operator delete(Ptr); }
+ void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); }
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
@@ -185,7 +185,7 @@ class BinaryOperator : public Instruction {
public:
// allocate space for exactly two operands
void *operator new(size_t S) { return User::operator new(S, AllocMarker); }
- void operator delete(void *Ptr) { User::operator delete(Ptr); }
+ void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); }
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
@@ -734,7 +734,7 @@ class CmpInst : public Instruction {
public:
// allocate space for exactly two operands
void *operator new(size_t S) { return User::operator new(S, AllocMarker); }
- void operator delete(void *Ptr) { User::operator delete(Ptr); }
+ void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); }
/// Construct a compare instruction, given the opcode, the predicate and
/// the two operands. Optionally (if InstBefore is specified) insert the
diff --git a/llvm/include/llvm/IR/Instructions.h b/llvm/include/llvm/IR/Instructions.h
index dbcaa6459eea9..d4ea74c05ae62 100644
--- a/llvm/include/llvm/IR/Instructions.h
+++ b/llvm/include/llvm/IR/Instructions.h
@@ -325,7 +325,7 @@ class StoreInst : public Instruction {
// allocate space for exactly two operands
void *operator new(size_t S) { return User::operator new(S, AllocMarker); }
- void operator delete(void *Ptr) { User::operator delete(Ptr); }
+ void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); }
/// Return true if this is a store to a volatile memory location.
bool isVolatile() const { return getSubclassData<VolatileField>(); }
@@ -449,7 +449,7 @@ class FenceInst : public Instruction {
// allocate space for exactly zero operands
void *operator new(size_t S) { return User::operator new(S, AllocMarker); }
- void operator delete(void *Ptr) { User::operator delete(Ptr); }
+ void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); }
/// Returns the ordering constraint of this fence instruction.
AtomicOrdering getOrdering() const {
@@ -530,7 +530,7 @@ class AtomicCmpXchgInst : public Instruction {
// allocate space for exactly three operands
void *operator new(size_t S) { return User::operator new(S, AllocMarker); }
- void operator delete(void *Ptr) { User::operator delete(Ptr); }
+ void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); }
using VolatileField = BoolBitfieldElementT<0>;
using WeakField = BoolBitfieldElementT<VolatileField::NextBit>;
@@ -806,7 +806,7 @@ class AtomicRMWInst : public Instruction {
// allocate space for exactly two operands
void *operator new(size_t S) { return User::operator new(S, AllocMarker); }
- void operator delete(void *Ptr) { User::operator delete(Ptr); }
+ void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); }
using VolatileField = BoolBitfieldElementT<0>;
using AtomicOrderingField =
@@ -1958,7 +1958,9 @@ class ShuffleVectorInst : public Instruction {
InsertPosition InsertBefore = nullptr);
void *operator new(size_t S) { return User::operator new(S, AllocMarker); }
- void operator delete(void *Ptr) { return User::operator delete(Ptr); }
+ void operator delete(void *Ptr) {
+ return User::operator delete(Ptr, AllocMarker);
+ }
/// Swap the operands and adjust the mask to preserve the semantics
/// of the instruction.
@@ -2553,7 +2555,7 @@ class InsertValueInst : public Instruction {
public:
// allocate space for exactly two operands
void *operator new(size_t S) { return User::operator new(S, AllocMarker); }
- void operator delete(void *Ptr) { User::operator delete(Ptr); }
+ void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); }
static InsertValueInst *Create(Value *Agg, Value *Val,
ArrayRef<unsigned> Idxs,
@@ -2906,7 +2908,7 @@ class LandingPadInst : public Instruction {
LLVM_ABI LandingPadInst *cloneImpl() const;
public:
- void operator delete(void *Ptr) { User::operator delete(Ptr); }
+ void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); }
/// Constructors - NumReservedClauses is a hint for the number of incoming
/// clauses that this landingpad will have (use 0 if you really have no idea).
@@ -3233,7 +3235,7 @@ class SwitchInst : public Instruction {
}
public:
- void operator delete(void *Ptr) { User::operator delete(Ptr); }
+ void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); }
// -2
static const unsigned DefaultPseudoIndex = static_cast<unsigned>(~0L-1);
@@ -3623,7 +3625,7 @@ class IndirectBrInst : public Instruction {
LLVM_ABI IndirectBrInst *cloneImpl() const;
public:
- void operator delete(void *Ptr) { User::operator delete(Ptr); }
+ void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); }
/// Iterator type that casts an operand to a basic block.
///
@@ -4145,7 +4147,9 @@ class CatchSwitchInst : public Instruction {
LLVM_ABI CatchSwitchInst *cloneImpl() const;
public:
- void operator delete(void *Ptr) { return User::operator delete(Ptr); }
+ void operator delete(void *Ptr) {
+ return User::operator delete(Ptr, AllocMarker);
+ }
static CatchSwitchInst *Create(Value *ParentPad, BasicBlock *UnwindDest,
unsigned NumHandlers,
@@ -4532,7 +4536,7 @@ class UnreachableInst : public Instruction {
// allocate space for exactly zero operands
void *operator new(size_t S) { return User::operator new(S, AllocMarker); }
- void operator delete(void *Ptr) { User::operator delete(Ptr); }
+ void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); }
unsigned getNumSuccessors() const { return 0; }
diff --git a/llvm/include/llvm/IR/User.h b/llvm/include/llvm/IR/User.h
index da886a508a3e8..1d83cfef06c6a 100644
--- a/llvm/include/llvm/IR/User.h
+++ b/llvm/include/llvm/IR/User.h
@@ -128,6 +128,10 @@ class User : public Value {
// null.
assert((!AllocInfo.HasHungOffUses || !getOperandList()) &&
"Error in initializing hung off uses for User");
+
+ Use *Operands = reinterpret_cast<Use *>(this) - NumUserOperands;
+ for (unsigned I = 0; I < NumUserOperands; ++I)
+ new (&Operands[I]) Use(this);
}
/// Allocate the array of Uses, followed by a pointer
@@ -150,42 +154,12 @@ class User : public Value {
/// Free memory allocated for User and Use objects.
LLVM_ABI void operator delete(void *Usr);
/// Placement delete - required by std, called if the ctor throws.
- void operator delete(void *Usr, HungOffOperandsAllocMarker) {
- // Note: If a subclass manipulates the information which is required to
- // calculate the Usr memory pointer, e.g. NumUserOperands, the operator
- // delete of that subclass has to restore the changed information to the
- // original value, since the dtor of that class is not called if the ctor
- // fails.
- User::operator delete(Usr);
-
-#ifndef LLVM_ENABLE_EXCEPTIONS
- llvm_unreachable("Constructor throws?");
-#endif
- }
+ LLVM_ABI void operator delete(void *Usr, HungOffOperandsAllocMarker);
/// Placement delete - required by std, called if the ctor throws.
- void operator delete(void *Usr, IntrusiveOperandsAllocMarker) {
- // Note: If a subclass manipulates the information which is required to calculate the
- // Usr memory pointer, e.g. NumUserOperands, the operator delete of that subclass has
- // to restore the changed information to the original value, since the dtor of that class
- // is not called if the ctor fails.
- User::operator delete(Usr);
-
-#ifndef LLVM_ENABLE_EXCEPTIONS
- llvm_unreachable("Constructor throws?");
-#endif
- }
+ LLVM_ABI void operator delete(void *Usr,
+ IntrusiveOperandsAndDescriptorAllocMarker);
/// Placement delete - required by std, called if the ctor throws.
- void operator delete(void *Usr, IntrusiveOperandsAndDescriptorAllocMarker) {
- // Note: If a subclass manipulates the information which is required to calculate the
- // Usr memory pointer, e.g. NumUserOperands, the operator delete of that subclass has
- // to restore the changed information to the original value, since the dtor of that class
- // is not called if the ctor fails.
- User::operator delete(Usr);
-
-#ifndef LLVM_ENABLE_EXCEPTIONS
- llvm_unreachable("Constructor throws?");
-#endif
- }
+ LLVM_ABI void operator delete(void *Usr, IntrusiveOperandsAllocMarker Marker);
protected:
template <int Idx, typename U> static Use &OpFrom(const U *that) {
diff --git a/llvm/lib/IR/ConstantsContext.h b/llvm/lib/IR/ConstantsContext.h
index 2073e0d42d8e3..cc9bad431787c 100644
--- a/llvm/lib/IR/ConstantsContext.h
+++ b/llvm/lib/IR/ConstantsContext.h
@@ -54,7 +54,7 @@ class CastConstantExpr final : public ConstantExpr {
// allocate space for exactly one operand
void *operator new(size_t S) { return User::operator new(S, AllocMarker); }
- void operator delete(void *Ptr) { User::operator delete(Ptr); }
+ void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); }
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
@@ -82,7 +82,7 @@ class BinaryConstantExpr final : public ConstantExpr {
// allocate space for exactly two operands
void *operator new(size_t S) { return User::operator new(S, AllocMarker); }
- void operator delete(void *Ptr) { User::operator delete(Ptr); }
+ void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); }
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
@@ -111,7 +111,7 @@ class ExtractElementConstantExpr final : public ConstantExpr {
// allocate space for exactly two operands
void *operator new(size_t S) { return User::operator new(S, AllocMarker); }
- void operator delete(void *Ptr) { User::operator delete(Ptr); }
+ void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); }
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
@@ -140,7 +140,7 @@ class InsertElementConstantExpr final : public ConstantExpr {
// allocate space for exactly three operands
void *operator new(size_t S) { return User::operator new(S, AllocMarker); }
- void operator delete(void *Ptr) { User::operator delete(Ptr); }
+ void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); }
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
@@ -178,7 +178,9 @@ class ShuffleVectorConstantExpr final : public ConstantExpr {
Constant *ShuffleMaskForBitcode;
void *operator new(size_t S) { return User::operator new(S, AllocMarker); }
- void operator delete(void *Ptr) { return User::operator delete(Ptr); }
+ void operator delete(void *Ptr) {
+ return User::operator delete(Ptr, AllocMarker);
+ }
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
diff --git a/llvm/lib/IR/User.cpp b/llvm/lib/IR/User.cpp
index e97a07fe5e7a2..4acfba6766a5d 100644
--- a/llvm/lib/IR/User.cpp
+++ b/llvm/lib/IR/User.cpp
@@ -158,8 +158,6 @@ void *User::allocateFixedOperandUser(size_t Size, unsigned Us,
Obj->NumUserOperands = Us;
Obj->HasHungOffUses = false;
Obj->HasDescriptor = DescBytes != 0;
- for (unsigned I = 0; I < Us; ++I)
- new (&Operands[I]) Use(Obj);
if (DescBytes != 0) {
auto *DescInfo = reinterpret_cast<DescriptorInfo *>(Operands) - 1;
@@ -234,3 +232,26 @@ User::~User() {
}
void User::operator delete(void *Usr) { ::operator delete(((void **)Usr)[-1]); }
+
+void User::operator delete(void *Usr, HungOffOperandsAllocMarker) {
+ Use **HungOffOperandList = static_cast<Use **>(Usr) - 1;
+ ::operator delete(HungOffOperandList);
+}
+
+void User::operator delete(void *Usr,
+ IntrusiveOperandsAndDescriptorAllocMarker Marker) {
+ unsigned NumOps = Marker.NumOps;
+ Use *UseBegin = static_cast<Use *>(Usr) - NumOps;
+ auto *DI = reinterpret_cast<DescriptorInfo *>(UseBegin) - 1;
+ uint8_t *Storage = reinterpret_cast<uint8_t *>(DI) - DI->SizeInBytes;
+ ::operator delete(Storage);
+}
+
+void User::operator delete(void *Usr, IntrusiveOperandsAllocMarker Marker) {
+ unsigned NumOps = Marker.NumOps;
+ size_t LeadingSize = sizeof(Use) * NumOps;
+ // Handle the edge case where there are no operands and no descriptor.
+ LeadingSize = std::max(LeadingSize, sizeof(void *));
+ uint8_t *Storage = static_cast<uint8_t *>(Usr) - LeadingSize;
+ ::operator delete(Storage);
+}
More information about the llvm-branch-commits
mailing list