[llvm] [SPIR-V] Preserve constexpr vectors as OpSpecConstantComposite (PR #215794)
Arseniy Obolenskiy via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 25 07:36:02 PDT 2026
https://github.com/aobolensk updated https://github.com/llvm/llvm-project/pull/215794
>From f4beea153861d4c4302f1e7cf5c198eb72a22bc5 Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Wed, 12 Aug 2026 14:58:37 +0200
Subject: [PATCH 1/2] [SPIR-V] Preserve constexpr vectors as
OpSpecConstantComposite
Let SPIRVEmitIntrinsics handle these the same as structs/arrays, instead of eagerly expanding them to runtime insertelement chains
---
llvm/lib/Target/SPIRV/SPIRVRegularizer.cpp | 45 ++-----------------
.../CodeGen/SPIRV/pointers/global-ptrtoint.ll | 20 ++++++++-
2 files changed, 23 insertions(+), 42 deletions(-)
diff --git a/llvm/lib/Target/SPIRV/SPIRVRegularizer.cpp b/llvm/lib/Target/SPIRV/SPIRVRegularizer.cpp
index d5e393470eae9..f8f549928d059 100644
--- a/llvm/lib/Target/SPIRV/SPIRVRegularizer.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVRegularizer.cpp
@@ -93,56 +93,19 @@ static void runLowerConstExpr(Function &F) {
};
WorkList.pop_front();
- auto LowerConstantVec = [&II, &LowerOp, &WorkList,
- &Ctx](ConstantVector *Vec,
- unsigned NumOfOp) -> Value * {
- if (llvm::all_of(Vec->operands(), [](Value *V) {
- return isa<ConstantExpr>(V) || isa<Function>(V);
- })) {
- // Expand a vector of constexprs and construct it back with
- // series of insertelement instructions.
- std::list<Value *> OpList;
- llvm::transform(Vec->operands(), std::back_inserter(OpList),
- [LowerOp](Value *V) { return LowerOp(V); });
- Value *Repl = nullptr;
- unsigned Idx = 0;
- auto *PhiII = dyn_cast<PHINode>(II);
- Instruction *InsPoint =
- PhiII ? &PhiII->getIncomingBlock(NumOfOp)->back() : II;
- std::list<Instruction *> ReplList;
- for (auto V : OpList) {
- if (auto *Inst = dyn_cast<Instruction>(V))
- ReplList.push_back(Inst);
- Repl = InsertElementInst::Create(
- (Repl ? Repl : PoisonValue::get(Vec->getType())), V,
- ConstantInt::get(Type::getInt32Ty(Ctx), Idx++), "",
- InsPoint->getIterator());
- }
- WorkList.splice(WorkList.begin(), ReplList);
- return Repl;
- }
- return nullptr;
- };
for (unsigned OI = 0, OE = II->getNumOperands(); OI != OE; ++OI) {
auto *Op = II->getOperand(OI);
- if (auto *Vec = dyn_cast<ConstantVector>(Op)) {
- Value *ReplInst = LowerConstantVec(Vec, OI);
- if (ReplInst)
- II->replaceUsesOfWith(Op, ReplInst);
- } else if (auto CE = dyn_cast<ConstantExpr>(Op)) {
+ if (auto CE = dyn_cast<ConstantExpr>(Op)) {
WorkList.push_front(cast<Instruction>(LowerOp(CE)));
} else if (auto MDAsVal = dyn_cast<MetadataAsValue>(Op)) {
auto ConstMD = dyn_cast<ConstantAsMetadata>(MDAsVal->getMetadata());
if (!ConstMD)
continue;
Constant *C = ConstMD->getValue();
- Value *ReplInst = nullptr;
- if (auto *Vec = dyn_cast<ConstantVector>(C))
- ReplInst = LowerConstantVec(Vec, OI);
- if (auto *CE = dyn_cast<ConstantExpr>(C))
- ReplInst = LowerOp(CE);
- if (!ReplInst)
+ auto *CE = dyn_cast<ConstantExpr>(C);
+ if (!CE)
continue;
+ Value *ReplInst = LowerOp(CE);
Metadata *RepMD = ValueAsMetadata::get(ReplInst);
Value *RepMDVal = MetadataAsValue::get(Ctx, RepMD);
II->setOperand(OI, RepMDVal);
diff --git a/llvm/test/CodeGen/SPIRV/pointers/global-ptrtoint.ll b/llvm/test/CodeGen/SPIRV/pointers/global-ptrtoint.ll
index aa6d714e2e767..0044d15b20576 100644
--- a/llvm/test/CodeGen/SPIRV/pointers/global-ptrtoint.ll
+++ b/llvm/test/CodeGen/SPIRV/pointers/global-ptrtoint.ll
@@ -16,13 +16,31 @@
; CHECK-DAG: %[[UseGlobalValue:.*]] = OpSpecConstantOp %[[TyI64]] Bitcast %[[PtrToInt]]
; CHECK-DAG: %[[ConstComposite:.*]] = OpSpecConstantComposite %[[TyStruct]] %[[Const128]] %[[UseGlobalValue]]
; CHECK-DAG: %[[TyPtrStruct:.*]] = OpTypePointer CrossWorkgroup %[[TyStruct]]
-; CHECK: OpVariable %[[TyPtrStruct]] CrossWorkgroup %[[ConstComposite]]
+; CHECK-DAG: OpVariable %[[TyPtrStruct]] CrossWorkgroup %[[ConstComposite]]
+
+; CHECK-DAG: OpName %[[VecGlobal1:.*]] "vec_global1"
+; CHECK-DAG: OpName %[[VecGlobal2:.*]] "vec_global2"
+; CHECK-DAG: %[[TyVec:.*]] = OpTypeVector %[[TyI64]] 2
+; CHECK-DAG: %[[PtrToInt1:.*]] = OpSpecConstantOp %[[TyI64]] ConvertPtrToU %[[VecGlobal1]]
+; CHECK-DAG: %[[PtrToInt2:.*]] = OpSpecConstantOp %[[TyI64]] ConvertPtrToU %[[VecGlobal2]]
+; CHECK-DAG: %[[VecElt1:.*]] = OpSpecConstantOp %[[TyI64]] Bitcast %[[PtrToInt1]]
+; CHECK-DAG: %[[VecElt2:.*]] = OpSpecConstantOp %[[TyI64]] Bitcast %[[PtrToInt2]]
+; CHECK-DAG: OpSpecConstantComposite %[[TyVec]] %[[VecElt1]] %[[VecElt2]]
; CHECK: OpFunction
@dev_global = addrspace(1) global [2 x i32] zeroinitializer
+ at vec_global1 = addrspace(1) global [2 x i32] zeroinitializer
+ at vec_global2 = addrspace(1) global [2 x i32] zeroinitializer
@__AsanDeviceGlobalMetadata = addrspace(1) global { i64, i64 } { i64 128, i64 ptrtoint (ptr addrspace(1) @dev_global to i64) }
define void @foo() {
entry:
ret void
}
+
+define <2 x i64> @bar() {
+entry:
+ ret <2 x i64> <i64 ptrtoint (ptr addrspace(1) @vec_global1 to i64), i64 ptrtoint (ptr addrspace(1) @vec_global2 to i64)>
+}
+
+; CHECK-NOT: OpCompositeInsert
>From 5d430aba7e9a59e1a4015a690797a35881bd7fb9 Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Tue, 25 Aug 2026 16:35:27 +0200
Subject: [PATCH 2/2] Add test
---
.../SPIRVRegularizer-constexpr-metadata.ll | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
create mode 100644 llvm/test/CodeGen/SPIRV/passes/SPIRVRegularizer-constexpr-metadata.ll
diff --git a/llvm/test/CodeGen/SPIRV/passes/SPIRVRegularizer-constexpr-metadata.ll b/llvm/test/CodeGen/SPIRV/passes/SPIRVRegularizer-constexpr-metadata.ll
new file mode 100644
index 0000000000000..0caa509b4fa6a
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/passes/SPIRVRegularizer-constexpr-metadata.ll
@@ -0,0 +1,16 @@
+; RUN: opt -S -passes=spirv-regularizer -mtriple=spirv64-unknown-unknown < %s | FileCheck %s
+
+; Verify that a ConstantExpr wrapped in metadata (a call operand) is lowered
+; to an instruction, matching the legacy pass behavior in runLowerConstExpr.
+
+ at g = addrspace(1) global i32 0
+
+declare void @llvm.use_md(metadata)
+
+define void @constexpr_in_metadata() {
+; CHECK-LABEL: define void @constexpr_in_metadata(
+; CHECK: [[V:%.*]] = ptrtoint ptr addrspace(1) @g to i64
+; CHECK: call void @llvm.use_md(metadata i64 [[V]])
+ call void @llvm.use_md(metadata i64 ptrtoint (ptr addrspace(1) @g to i64))
+ ret void
+}
More information about the llvm-commits
mailing list