[llvm] [AutoUpgrade] Prevent deletion of call if uses still exist (PR #177606)

Kshitij Paranjape via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 30 01:00:55 PST 2026


https://github.com/kshitijvp updated https://github.com/llvm/llvm-project/pull/177606

>From 7a06e21a6f708344429f53166d3f3dadce251b5e Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Fri, 23 Jan 2026 21:16:56 +0530
Subject: [PATCH 1/3] [AutoUpgrade] Prevent deletion of call if uses still
 exist

The calls to the llvm.x86.sse2.pshuflw are being
deleted due to invalid vector type, even though
uses still exist. Adding checks to prevent deletion
of call when uses still exist or even if eraseFromParent()
is called ensuring it is called after replaceAllUsesWith().
---
 llvm/lib/IR/AutoUpgrade.cpp       |  7 ++++---
 llvm/test/Verifier/issue176674.ll | 13 +++++++++++++
 2 files changed, 17 insertions(+), 3 deletions(-)
 create mode 100644 llvm/test/Verifier/issue176674.ll

diff --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp
index 562114c355f9e..64d0b339009cb 100644
--- a/llvm/lib/IR/AutoUpgrade.cpp
+++ b/llvm/lib/IR/AutoUpgrade.cpp
@@ -4944,9 +4944,10 @@ void llvm::UpgradeIntrinsicCall(CallBase *CI, Function *NewFn) {
       llvm_unreachable("Unknown function for CallBase upgrade.");
     }
 
-    if (Rep)
+    if (Rep) {
       CI->replaceAllUsesWith(Rep);
-    CI->eraseFromParent();
+      CI->eraseFromParent();
+    }
     return;
   }
 
@@ -5668,7 +5669,7 @@ void llvm::UpgradeCallsToIntrinsic(Function *F) {
         UpgradeIntrinsicCall(CB, NewFn);
 
     // Remove old function, no longer used, from the module.
-    if (F != NewFn)
+    if (NewFn != nullptr && F != NewFn)
       F->eraseFromParent();
   }
 }
diff --git a/llvm/test/Verifier/issue176674.ll b/llvm/test/Verifier/issue176674.ll
new file mode 100644
index 0000000000000..349950b143fa2
--- /dev/null
+++ b/llvm/test/Verifier/issue176674.ll
@@ -0,0 +1,13 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt < %s -passes=verify -S | FileCheck %s
+define void @test(ptr %a) {
+; CHECK-LABEL: define void @test(
+; CHECK-SAME: ptr [[A:%.*]]) {
+; CHECK-NEXT:    [[V:%.*]] = call <4 x i32> @llvm.x86.sse2.pshuflw.128(<4 x i32> zeroinitializer, i8 0)
+; CHECK-NEXT:    store <4 x i32> [[V]], ptr [[A]], align 16
+; CHECK-NEXT:    ret void
+;
+  %v = call <4 x i32> @llvm.x86.sse2.pshuflw.128(<4 x i32> zeroinitializer, i8 0)
+  store <4 x i32> %v, ptr %a
+  ret void
+}

>From c138552e8ca609932ef09f7c2401437b632157ea Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Fri, 30 Jan 2026 14:18:33 +0530
Subject: [PATCH 2/3] Added case when no intrinsics match

Added case when provided intrinsics does
not match any of the standard llvm intrinsics.
Also when pshufl.w was called with invalid
intrinsic signature it caused assertion failure
idx < size. Handled this case by reportFatalUsageError.
---
 llvm/lib/IR/AutoUpgrade.cpp         | 53 ++++++++++++++++-------------
 llvm/test/Verifier/issue176674.ll   | 11 ++----
 llvm/test/Verifier/issue176674_1.ll |  8 +++++
 3 files changed, 40 insertions(+), 32 deletions(-)
 create mode 100644 llvm/test/Verifier/issue176674_1.ll

diff --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp
index 64d0b339009cb..4cdda02cc499c 100644
--- a/llvm/lib/IR/AutoUpgrade.cpp
+++ b/llvm/lib/IR/AutoUpgrade.cpp
@@ -3022,7 +3022,7 @@ static Value *upgradeX86IntrinsicCall(StringRef Name, CallBase *CI, Function *F,
     Intrinsic::ID IID;
     switch (VecWidth) {
     default:
-      llvm_unreachable("Unexpected intrinsic");
+      reportFatalUsageError("Unexpected intrinsic");
     case 128:
       IID = Intrinsic::x86_avx512_vpshufbitqmb_128;
       break;
@@ -3055,7 +3055,7 @@ static Value *upgradeX86IntrinsicCall(StringRef Name, CallBase *CI, Function *F,
     else if (VecWidth == 512 && EltWidth == 64)
       IID = Intrinsic::x86_avx512_fpclass_pd_512;
     else
-      llvm_unreachable("Unexpected intrinsic");
+      reportFatalUsageError("Unexpected intrinsic");
 
     Rep =
         Builder.CreateIntrinsic(IID, {CI->getOperand(0), CI->getArgOperand(1)});
@@ -3079,7 +3079,7 @@ static Value *upgradeX86IntrinsicCall(StringRef Name, CallBase *CI, Function *F,
     else if (VecWidth == 512 && EltWidth == 64)
       IID = Intrinsic::x86_avx512_mask_cmp_pd_512;
     else
-      llvm_unreachable("Unexpected intrinsic");
+      reportFatalUsageError("Unexpected intrinsic");
 
     Value *Mask = Constant::getAllOnesValue(CI->getType());
     if (VecWidth == 512)
@@ -3249,7 +3249,7 @@ static Value *upgradeX86IntrinsicCall(StringRef Name, CallBase *CI, Function *F,
              Name.ends_with("d") || Name.ends_with("q"))
       IsSigned = true;
     else
-      llvm_unreachable("Unknown suffix");
+      reportFatalUsageError("Unknown suffix");
 
     unsigned Imm;
     if (CI->arg_size() == 3) {
@@ -3622,6 +3622,9 @@ static Value *upgradeX86IntrinsicCall(StringRef Name, CallBase *CI, Function *F,
     Value *Op0 = CI->getArgOperand(0);
     unsigned Imm = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
     unsigned NumElts = cast<FixedVectorType>(CI->getType())->getNumElements();
+    
+    if (Name == "sse2.pshufl.w" && NumElts % 8 != 0)
+      reportFatalUsageError("Invalid Intrinsic Signature");
 
     SmallVector<int, 16> Idxs(NumElts);
     for (unsigned l = 0; l != NumElts; l += 8) {
@@ -3893,7 +3896,7 @@ static Value *upgradeX86IntrinsicCall(StringRef Name, CallBase *CI, Function *F,
       else if (Name[17] == '3' && Name[18] == '2') // avx512.mask.psllv32hi
         IID = Intrinsic::x86_avx512_psllv_w_512;
       else
-        llvm_unreachable("Unexpected size");
+        reportFatalUsageError("Unexpected size");
     } else if (Name.ends_with(".128")) {
       if (Size == 'd') // avx512.mask.psll.d.128, avx512.mask.psll.di.128
         IID = IsImmediate ? Intrinsic::x86_sse2_pslli_d
@@ -3905,7 +3908,7 @@ static Value *upgradeX86IntrinsicCall(StringRef Name, CallBase *CI, Function *F,
         IID = IsImmediate ? Intrinsic::x86_sse2_pslli_w
                           : Intrinsic::x86_sse2_psll_w;
       else
-        llvm_unreachable("Unexpected size");
+        reportFatalUsageError("Unexpected size");
     } else if (Name.ends_with(".256")) {
       if (Size == 'd') // avx512.mask.psll.d.256, avx512.mask.psll.di.256
         IID = IsImmediate ? Intrinsic::x86_avx2_pslli_d
@@ -3917,7 +3920,7 @@ static Value *upgradeX86IntrinsicCall(StringRef Name, CallBase *CI, Function *F,
         IID = IsImmediate ? Intrinsic::x86_avx2_pslli_w
                           : Intrinsic::x86_avx2_psll_w;
       else
-        llvm_unreachable("Unexpected size");
+        reportFatalUsageError("Unexpected size");
     } else {
       if (Size == 'd') // psll.di.512, pslli.d, psll.d, psllv.d.512
         IID = IsImmediate  ? Intrinsic::x86_avx512_pslli_d_512
@@ -3931,7 +3934,7 @@ static Value *upgradeX86IntrinsicCall(StringRef Name, CallBase *CI, Function *F,
         IID = IsImmediate ? Intrinsic::x86_avx512_pslli_w_512
                           : Intrinsic::x86_avx512_psll_w_512;
       else
-        llvm_unreachable("Unexpected size");
+        reportFatalUsageError("Unexpected size");
     }
 
     Rep = upgradeX86MaskedShift(Builder, *CI, IID);
@@ -3960,7 +3963,7 @@ static Value *upgradeX86IntrinsicCall(StringRef Name, CallBase *CI, Function *F,
       else if (Name[17] == '3' && Name[18] == '2') // avx512.mask.psrlv32hi
         IID = Intrinsic::x86_avx512_psrlv_w_512;
       else
-        llvm_unreachable("Unexpected size");
+        reportFatalUsageError("Unexpected size");
     } else if (Name.ends_with(".128")) {
       if (Size == 'd') // avx512.mask.psrl.d.128, avx512.mask.psrl.di.128
         IID = IsImmediate ? Intrinsic::x86_sse2_psrli_d
@@ -3972,7 +3975,7 @@ static Value *upgradeX86IntrinsicCall(StringRef Name, CallBase *CI, Function *F,
         IID = IsImmediate ? Intrinsic::x86_sse2_psrli_w
                           : Intrinsic::x86_sse2_psrl_w;
       else
-        llvm_unreachable("Unexpected size");
+        reportFatalUsageError("Unexpected size");
     } else if (Name.ends_with(".256")) {
       if (Size == 'd') // avx512.mask.psrl.d.256, avx512.mask.psrl.di.256
         IID = IsImmediate ? Intrinsic::x86_avx2_psrli_d
@@ -3984,7 +3987,7 @@ static Value *upgradeX86IntrinsicCall(StringRef Name, CallBase *CI, Function *F,
         IID = IsImmediate ? Intrinsic::x86_avx2_psrli_w
                           : Intrinsic::x86_avx2_psrl_w;
       else
-        llvm_unreachable("Unexpected size");
+        reportFatalUsageError("Unexpected size");
     } else {
       if (Size == 'd') // psrl.di.512, psrli.d, psrl.d, psrl.d.512
         IID = IsImmediate  ? Intrinsic::x86_avx512_psrli_d_512
@@ -3998,7 +4001,7 @@ static Value *upgradeX86IntrinsicCall(StringRef Name, CallBase *CI, Function *F,
         IID = IsImmediate ? Intrinsic::x86_avx512_psrli_w_512
                           : Intrinsic::x86_avx512_psrl_w_512;
       else
-        llvm_unreachable("Unexpected size");
+        reportFatalUsageError("Unexpected size");
     }
 
     Rep = upgradeX86MaskedShift(Builder, *CI, IID);
@@ -4023,7 +4026,7 @@ static Value *upgradeX86IntrinsicCall(StringRef Name, CallBase *CI, Function *F,
       else if (Name[17] == '3' && Name[18] == '2') // avx512.mask.psrav32hi
         IID = Intrinsic::x86_avx512_psrav_w_512;
       else
-        llvm_unreachable("Unexpected size");
+        reportFatalUsageError("Unexpected size");
     } else if (Name.ends_with(".128")) {
       if (Size == 'd') // avx512.mask.psra.d.128, avx512.mask.psra.di.128
         IID = IsImmediate ? Intrinsic::x86_sse2_psrai_d
@@ -4036,7 +4039,7 @@ static Value *upgradeX86IntrinsicCall(StringRef Name, CallBase *CI, Function *F,
         IID = IsImmediate ? Intrinsic::x86_sse2_psrai_w
                           : Intrinsic::x86_sse2_psra_w;
       else
-        llvm_unreachable("Unexpected size");
+        reportFatalUsageError("Unexpected size");
     } else if (Name.ends_with(".256")) {
       if (Size == 'd') // avx512.mask.psra.d.256, avx512.mask.psra.di.256
         IID = IsImmediate ? Intrinsic::x86_avx2_psrai_d
@@ -4049,7 +4052,7 @@ static Value *upgradeX86IntrinsicCall(StringRef Name, CallBase *CI, Function *F,
         IID = IsImmediate ? Intrinsic::x86_avx2_psrai_w
                           : Intrinsic::x86_avx2_psra_w;
       else
-        llvm_unreachable("Unexpected size");
+        reportFatalUsageError("Unexpected size");
     } else {
       if (Size == 'd') // psra.di.512, psrai.d, psra.d, psrav.d.512
         IID = IsImmediate  ? Intrinsic::x86_avx512_psrai_d_512
@@ -4063,7 +4066,7 @@ static Value *upgradeX86IntrinsicCall(StringRef Name, CallBase *CI, Function *F,
         IID = IsImmediate ? Intrinsic::x86_avx512_psrai_w_512
                           : Intrinsic::x86_avx512_psra_w_512;
       else
-        llvm_unreachable("Unexpected size");
+        reportFatalUsageError("Unexpected size");
     }
 
     Rep = upgradeX86MaskedShift(Builder, *CI, IID);
@@ -4232,7 +4235,7 @@ static Value *upgradeX86IntrinsicCall(StringRef Name, CallBase *CI, Function *F,
     else if (VecWidth == 256 && EltWidth == 64)
       IID = Intrinsic::x86_fma_vfmaddsub_pd_256;
     else
-      llvm_unreachable("Unexpected intrinsic");
+      reportFatalUsageError("Unexpected intrinsic");
 
     Value *Ops[] = {CI->getArgOperand(0), CI->getArgOperand(1),
                     CI->getArgOperand(2)};
@@ -4307,7 +4310,7 @@ static Value *upgradeX86IntrinsicCall(StringRef Name, CallBase *CI, Function *F,
     else if (VecWidth == 512 && EltWidth == 64)
       IID = Intrinsic::x86_avx512_pternlog_q_512;
     else
-      llvm_unreachable("Unexpected intrinsic");
+      reportFatalUsageError("Unexpected intrinsic");
 
     Value *Args[] = {CI->getArgOperand(0), CI->getArgOperand(1),
                      CI->getArgOperand(2), CI->getArgOperand(3)};
@@ -4334,7 +4337,7 @@ static Value *upgradeX86IntrinsicCall(StringRef Name, CallBase *CI, Function *F,
     else if (VecWidth == 512 && High)
       IID = Intrinsic::x86_avx512_vpmadd52h_uq_512;
     else
-      llvm_unreachable("Unexpected intrinsic");
+      reportFatalUsageError("Unexpected intrinsic");
 
     Value *Args[] = {CI->getArgOperand(0), CI->getArgOperand(1),
                      CI->getArgOperand(2)};
@@ -4369,7 +4372,7 @@ static Value *upgradeX86IntrinsicCall(StringRef Name, CallBase *CI, Function *F,
     else if (VecWidth == 512 && IsSaturating)
       IID = Intrinsic::x86_avx512_vpdpbusds_512;
     else
-      llvm_unreachable("Unexpected intrinsic");
+      reportFatalUsageError("Unexpected intrinsic");
 
     Value *Args[] = {CI->getArgOperand(0), CI->getArgOperand(1),
                      CI->getArgOperand(2)};
@@ -4393,7 +4396,7 @@ static Value *upgradeX86IntrinsicCall(StringRef Name, CallBase *CI, Function *F,
       else if (VecWidth == 512)
         NewArgType = VectorType::get(Builder.getInt8Ty(), 64, false);
       else
-        llvm_unreachable("Unexpected vector bit width");
+        reportFatalUsageError("Unexpected vector bit width");
 
       Args[1] = Builder.CreateBitCast(Args[1], NewArgType);
       Args[2] = Builder.CreateBitCast(Args[2], NewArgType);
@@ -4424,7 +4427,7 @@ static Value *upgradeX86IntrinsicCall(StringRef Name, CallBase *CI, Function *F,
     else if (VecWidth == 512 && IsSaturating)
       IID = Intrinsic::x86_avx512_vpdpwssds_512;
     else
-      llvm_unreachable("Unexpected intrinsic");
+      reportFatalUsageError("Unexpected intrinsic");
 
     Value *Args[] = {CI->getArgOperand(0), CI->getArgOperand(1),
                      CI->getArgOperand(2)};
@@ -4448,7 +4451,7 @@ static Value *upgradeX86IntrinsicCall(StringRef Name, CallBase *CI, Function *F,
       else if (VecWidth == 512)
         NewArgType = VectorType::get(Builder.getInt16Ty(), 32, false);
       else
-        llvm_unreachable("Unexpected vector bit width");
+        reportFatalUsageError("Unexpected vector bit width");
 
       Args[1] = Builder.CreateBitCast(Args[1], NewArgType);
       Args[2] = Builder.CreateBitCast(Args[2], NewArgType);
@@ -4471,7 +4474,7 @@ static Value *upgradeX86IntrinsicCall(StringRef Name, CallBase *CI, Function *F,
     else if (Name[0] == 's' && Name.back() == '4')
       IID = Intrinsic::x86_subborrow_64;
     else
-      llvm_unreachable("Unexpected intrinsic");
+      reportFatalUsageError("Unexpected intrinsic");
 
     // Make a call with 3 operands.
     Value *Args[] = {CI->getArgOperand(0), CI->getArgOperand(1),
@@ -4490,6 +4493,8 @@ static Value *upgradeX86IntrinsicCall(StringRef Name, CallBase *CI, Function *F,
              upgradeAVX512MaskToSelect(Name, Builder, *CI, Rep)) {
     // Rep will be updated by the call in the condition.
   }
+  else
+    reportFatalUsageError("Invalid Intrinsic Used");
 
   return Rep;
 }
diff --git a/llvm/test/Verifier/issue176674.ll b/llvm/test/Verifier/issue176674.ll
index 349950b143fa2..5873a596ee84a 100644
--- a/llvm/test/Verifier/issue176674.ll
+++ b/llvm/test/Verifier/issue176674.ll
@@ -1,12 +1,7 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
-; RUN: opt < %s -passes=verify -S | FileCheck %s
+; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
+; CHECK: LLVM ERROR: Invalid Intrinsic Used
+
 define void @test(ptr %a) {
-; CHECK-LABEL: define void @test(
-; CHECK-SAME: ptr [[A:%.*]]) {
-; CHECK-NEXT:    [[V:%.*]] = call <4 x i32> @llvm.x86.sse2.pshuflw.128(<4 x i32> zeroinitializer, i8 0)
-; CHECK-NEXT:    store <4 x i32> [[V]], ptr [[A]], align 16
-; CHECK-NEXT:    ret void
-;
   %v = call <4 x i32> @llvm.x86.sse2.pshuflw.128(<4 x i32> zeroinitializer, i8 0)
   store <4 x i32> %v, ptr %a
   ret void
diff --git a/llvm/test/Verifier/issue176674_1.ll b/llvm/test/Verifier/issue176674_1.ll
new file mode 100644
index 0000000000000..886c4b1b2f111
--- /dev/null
+++ b/llvm/test/Verifier/issue176674_1.ll
@@ -0,0 +1,8 @@
+; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
+; CHECK: LLVM ERROR: Invalid Intrinsic Signature
+
+define void @test(ptr %a) {
+  %v = call <4 x i32> @llvm.x86.sse2.pshufl.w(<4 x i32> zeroinitializer, i8 0)
+  store <4 x i32> %v, ptr %a
+  ret void
+}

>From c72b33867e423fff7c08ae77a94287faa231d019 Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Fri, 30 Jan 2026 14:30:38 +0530
Subject: [PATCH 3/3] Nitpick

---
 llvm/lib/IR/AutoUpgrade.cpp | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp
index 4cdda02cc499c..0145fd0dc9ad1 100644
--- a/llvm/lib/IR/AutoUpgrade.cpp
+++ b/llvm/lib/IR/AutoUpgrade.cpp
@@ -3622,7 +3622,7 @@ static Value *upgradeX86IntrinsicCall(StringRef Name, CallBase *CI, Function *F,
     Value *Op0 = CI->getArgOperand(0);
     unsigned Imm = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
     unsigned NumElts = cast<FixedVectorType>(CI->getType())->getNumElements();
-    
+
     if (Name == "sse2.pshufl.w" && NumElts % 8 != 0)
       reportFatalUsageError("Invalid Intrinsic Signature");
 
@@ -4492,8 +4492,7 @@ static Value *upgradeX86IntrinsicCall(StringRef Name, CallBase *CI, Function *F,
   } else if (Name.starts_with("avx512.mask.") &&
              upgradeAVX512MaskToSelect(Name, Builder, *CI, Rep)) {
     // Rep will be updated by the call in the condition.
-  }
-  else
+  } else
     reportFatalUsageError("Invalid Intrinsic Used");
 
   return Rep;
@@ -4951,8 +4950,8 @@ void llvm::UpgradeIntrinsicCall(CallBase *CI, Function *NewFn) {
 
     if (Rep) {
       CI->replaceAllUsesWith(Rep);
-      CI->eraseFromParent();
     }
+    CI->eraseFromParent();
     return;
   }
 
@@ -5674,7 +5673,7 @@ void llvm::UpgradeCallsToIntrinsic(Function *F) {
         UpgradeIntrinsicCall(CB, NewFn);
 
     // Remove old function, no longer used, from the module.
-    if (NewFn != nullptr && F != NewFn)
+    if (F != NewFn)
       F->eraseFromParent();
   }
 }



More information about the llvm-commits mailing list