[llvm] [SPIRV] Fix assertion violation caused by unexpected ConstantExpr. (PR #170524)

Manuel Carrasco via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 3 10:01:16 PST 2025


https://github.com/mgcarrasco created https://github.com/llvm/llvm-project/pull/170524

`SPIRVEmitIntrinsics::simplifyZeroLengthArrayGepInst` asserted that it always expected a `GetElementPtrInst` from `IRBuilder::CreateGEP` (which returns a `Value`).  `IRBuilder` can fold and return a `ConstantExpr` instead, thus violating the assertion. The patch fixes this by using `GetElementPtrInst::Create` to always return a `GetElementPtrInst`.

This LLVM defect was identified via the AMD Fuzzing project.

>From eaa43cc08035cbc0db5f92c5e4367b252b1ada6a Mon Sep 17 00:00:00 2001
From: Manuel Carrasco <Manuel.Carrasco at amd.com>
Date: Wed, 3 Dec 2025 11:47:44 -0600
Subject: [PATCH] [SPIRV] Fix assertion violation caused by unexpected
 ConstantExpr.

---
 llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp |  7 ++-----
 llvm/test/CodeGen/SPIRV/const-array-gep.ll    | 19 +++++++++++++++++++
 2 files changed, 21 insertions(+), 5 deletions(-)
 create mode 100644 llvm/test/CodeGen/SPIRV/const-array-gep.ll

diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index eea49bfdaf04b..736020406ce96 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -2816,13 +2816,10 @@ SPIRVEmitIntrinsics::simplifyZeroLengthArrayGepInst(GetElementPtrInst *GEP) {
   ArrayType *ArrTy = dyn_cast<ArrayType>(SrcTy);
   if (ArrTy && ArrTy->getNumElements() == 0 &&
       PatternMatch::match(Indices[0], PatternMatch::m_Zero())) {
-    IRBuilder<> Builder(GEP);
     Indices.erase(Indices.begin());
     SrcTy = ArrTy->getElementType();
-    Value *NewGEP = Builder.CreateGEP(SrcTy, GEP->getPointerOperand(), Indices,
-                                      "", GEP->getNoWrapFlags());
-    assert(llvm::isa<GetElementPtrInst>(NewGEP) && "NewGEP should be a GEP");
-    return cast<GetElementPtrInst>(NewGEP);
+    return GetElementPtrInst::Create(SrcTy, GEP->getPointerOperand(), Indices,
+                                     GEP->getNoWrapFlags(), "", GEP);
   }
   return nullptr;
 }
diff --git a/llvm/test/CodeGen/SPIRV/const-array-gep.ll b/llvm/test/CodeGen/SPIRV/const-array-gep.ll
new file mode 100644
index 0000000000000..c1dfe18aee6e6
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/const-array-gep.ll
@@ -0,0 +1,19 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -O0 -mtriple=spirv64-unknown-unknown < %s | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown < %s -filetype=obj | spirv-val %}
+
+define spir_kernel void @_Z6kernelPi() addrspace(4) {
+; CHECK-LABEL: _Z6kernelPi
+; CHECK:       %12 = OpFunction %3 None %4 ; -- Begin function _Z6kernelPi
+; CHECK-NEXT:    %2 = OpLabel
+; CHECK-NEXT:    %13 = OpBitcast %6 %11
+; CHECK-NEXT:    %14 = OpInBoundsPtrAccessChain %6 %13 %10
+; CHECK-NEXT:    %15 = OpConvertPtrToU %5 %14
+; CHECK-NEXT:    %16 = OpBitcast %6 %11
+; CHECK-NEXT:    OpStore %16 %15 Aligned 4
+; CHECK-NEXT:    OpReturn
+; CHECK-NEXT:    OpFunctionEnd
+entry:
+  store i32 ptrtoint (ptr addrspace(4) getelementptr inbounds ([0 x i32], ptr addrspace(4) null, i64 0, i64 1) to i32), ptr addrspace(4) null, align 4
+  ret void
+}



More information about the llvm-commits mailing list