[llvm-branch-commits] [llvm] release/23.x: [IR] Set Number of Hungoff Uses after allocation (#213304) (PR #214940)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sat Aug 8 01:00:15 PDT 2026


https://github.com/llvmbot created https://github.com/llvm/llvm-project/pull/214940

Backport e416b09711039b65a37b6c83977fb04c2c0889ea

Requested by: @marcauberer

>From ae1d5af176c9305de6ab6c1dba3578a2113f1212 Mon Sep 17 00:00:00 2001
From: Marc Auberer <marc.auberer at chillibits.com>
Date: Sat, 8 Aug 2026 09:49:34 +0200
Subject: [PATCH] [IR] Set Number of Hungoff Uses after allocation (#213304)

If allocation of the Use[] in allocHungoffUses fails (e.g. due to OOM),
it may happen that the destructor of User is called with NumUserOperands
> 0. Then `Use::zap` tries to destruct Uses that were not constructed in
the first place.

Example scenario for SwitchInst:
`SwitchInst::init()` is called, which means the constructor of the
parent class User went through successfully, which means the destructor
of User will be called eventually. If now `SwitchInst::init()` calls
first `setNumHungOffUseOperands(2)` and then `allocHungoffUses()` and
the allocation there fails, `~User()` is called and tries to destruct 2
Uses, which can lead to problems.

This patch consequently ensures that first the allocation happens and
then NumUserOperands is set accordingly, so that this problem is
prevented.

(cherry picked from commit e416b09711039b65a37b6c83977fb04c2c0889ea)
---
 llvm/lib/IR/Instructions.cpp | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp
index 77d6981007b37..993bf82b9e3e6 100644
--- a/llvm/lib/IR/Instructions.cpp
+++ b/llvm/lib/IR/Instructions.cpp
@@ -132,8 +132,8 @@ const char *SelectInst::areInvalidOperands(Value *Op0, Value *Op1, Value *Op2) {
 PHINode::PHINode(const PHINode &PN)
     : Instruction(PN.getType(), Instruction::PHI, AllocMarker),
       ReservedSpace(PN.getNumOperands()) {
-  NumUserOperands = PN.getNumOperands();
   allocHungoffUses(PN.getNumOperands());
+  setNumHungOffUseOperands(PN.getNumOperands());
   std::copy(PN.op_begin(), PN.op_end(), op_begin());
   copyIncomingBlocks(make_range(PN.block_begin(), PN.block_end()));
   FMF = PN.FMF;
@@ -252,8 +252,8 @@ LandingPadInst::LandingPadInst(Type *RetTy, unsigned NumReservedValues,
 LandingPadInst::LandingPadInst(const LandingPadInst &LP)
     : Instruction(LP.getType(), Instruction::LandingPad, AllocMarker),
       ReservedSpace(LP.getNumOperands()) {
-  NumUserOperands = LP.getNumOperands();
   allocHungoffUses(LP.getNumOperands());
+  setNumHungOffUseOperands(LP.getNumOperands());
   Use *OL = getOperandList();
   const Use *InOL = LP.getOperandList();
   for (unsigned I = 0, E = ReservedSpace; I != E; ++I)
@@ -270,8 +270,8 @@ LandingPadInst *LandingPadInst::Create(Type *RetTy, unsigned NumReservedClauses,
 
 void LandingPadInst::init(unsigned NumReservedValues, const Twine &NameStr) {
   ReservedSpace = NumReservedValues;
-  setNumHungOffUseOperands(0);
   allocHungoffUses(ReservedSpace);
+  setNumHungOffUseOperands(0);
   setName(NameStr);
   setCleanup(false);
 }
@@ -1128,8 +1128,8 @@ void CatchSwitchInst::init(Value *ParentPad, BasicBlock *UnwindDest,
   assert(ParentPad && NumReservedValues);
 
   ReservedSpace = NumReservedValues;
-  setNumHungOffUseOperands(UnwindDest ? 2 : 1);
   allocHungoffUses(ReservedSpace);
+  setNumHungOffUseOperands(UnwindDest ? 2 : 1);
 
   Op<0>() = ParentPad;
   if (UnwindDest) {
@@ -4119,8 +4119,8 @@ CmpPredicate CmpPredicate::getSwapped(const CmpInst *Cmp) {
 void SwitchInst::init(Value *Value, BasicBlock *Default, unsigned NumReserved) {
   assert(Value && Default && NumReserved);
   ReservedSpace = NumReserved;
-  setNumHungOffUseOperands(2);
   allocHungoffUses(ReservedSpace);
+  setNumHungOffUseOperands(2);
 
   Op<0>() = Value;
   Op<1>() = Default;
@@ -4314,9 +4314,9 @@ SwitchInstProfUpdateWrapper::getSuccessorWeight(const SwitchInst &SI,
 void IndirectBrInst::init(Value *Address, unsigned NumDests) {
   assert(Address && Address->getType()->isPointerTy() &&
          "Address of indirectbr must be a pointer");
-  ReservedSpace = 1+NumDests;
-  setNumHungOffUseOperands(1);
+  ReservedSpace = 1 + NumDests;
   allocHungoffUses(ReservedSpace);
+  setNumHungOffUseOperands(1);
 
   Op<0>() = Address;
 }
@@ -4343,8 +4343,8 @@ IndirectBrInst::IndirectBrInst(Value *Address, unsigned NumCases,
 IndirectBrInst::IndirectBrInst(const IndirectBrInst &IBI)
     : Instruction(Type::getVoidTy(IBI.getContext()), Instruction::IndirectBr,
                   AllocMarker) {
-  NumUserOperands = IBI.NumUserOperands;
   allocHungoffUses(IBI.getNumOperands());
+  setNumHungOffUseOperands(IBI.NumUserOperands);
   Use *OL = getOperandList();
   const Use *InOL = IBI.getOperandList();
   for (unsigned i = 0, E = IBI.getNumOperands(); i != E; ++i)



More information about the llvm-branch-commits mailing list