[llvm] [SPIRV][SPIRVPrepareGlobals] Convert llvm.embedded.module from a 0-element array to a 1-element array (PR #166950)
Juan Manuel Martinez CaamaƱo via llvm-commits
llvm-commits at lists.llvm.org
Mon Nov 10 04:17:15 PST 2025
https://github.com/jmmartinez updated https://github.com/llvm/llvm-project/pull/166950
>From e43cefcf8641d0fbb6fd33948e1cd2f7748d95de Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?=
<jmartinezcaamao at gmail.com>
Date: Thu, 6 Nov 2025 15:48:22 +0100
Subject: [PATCH 1/3] [SPIRV][SPIRVPrepareGlobals] Add pass skeleton
Add a pass where we can do IR->IR preprocessing of global-variables.
---
llvm/lib/Target/SPIRV/CMakeLists.txt | 1 +
llvm/lib/Target/SPIRV/SPIRV.h | 2 +
llvm/lib/Target/SPIRV/SPIRVPrepareGlobals.cpp | 43 +++++++++++++++++++
llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp | 2 +
llvm/test/CodeGen/SPIRV/llc-pipeline.ll | 2 +
5 files changed, 50 insertions(+)
create mode 100644 llvm/lib/Target/SPIRV/SPIRVPrepareGlobals.cpp
diff --git a/llvm/lib/Target/SPIRV/CMakeLists.txt b/llvm/lib/Target/SPIRV/CMakeLists.txt
index eab7b213756b3..79b76165cd57a 100644
--- a/llvm/lib/Target/SPIRV/CMakeLists.txt
+++ b/llvm/lib/Target/SPIRV/CMakeLists.txt
@@ -41,6 +41,7 @@ add_llvm_target(SPIRVCodeGen
SPIRVPreLegalizerCombiner.cpp
SPIRVPostLegalizer.cpp
SPIRVPrepareFunctions.cpp
+ SPIRVPrepareGlobals.cpp
SPIRVRegisterBankInfo.cpp
SPIRVRegisterInfo.cpp
SPIRVRegularizer.cpp
diff --git a/llvm/lib/Target/SPIRV/SPIRV.h b/llvm/lib/Target/SPIRV/SPIRV.h
index efd49b930aa34..fa85ee781c249 100644
--- a/llvm/lib/Target/SPIRV/SPIRV.h
+++ b/llvm/lib/Target/SPIRV/SPIRV.h
@@ -31,6 +31,7 @@ FunctionPass *createSPIRVPreLegalizerCombiner();
FunctionPass *createSPIRVPreLegalizerPass();
FunctionPass *createSPIRVPostLegalizerPass();
ModulePass *createSPIRVEmitIntrinsicsPass(SPIRVTargetMachine *TM);
+ModulePass *createSPIRVPrepareGlobalsPass();
MachineFunctionPass *createSPIRVEmitNonSemanticDIPass(SPIRVTargetMachine *TM);
InstructionSelector *
createSPIRVInstructionSelector(const SPIRVTargetMachine &TM,
@@ -51,6 +52,7 @@ void initializeSPIRVLegalizePointerCastPass(PassRegistry &);
void initializeSPIRVRegularizerPass(PassRegistry &);
void initializeSPIRVMergeRegionExitTargetsPass(PassRegistry &);
void initializeSPIRVPrepareFunctionsPass(PassRegistry &);
+void initializeSPIRVPrepareGlobalsPass(PassRegistry &);
void initializeSPIRVStripConvergentIntrinsicsPass(PassRegistry &);
void initializeSPIRVLegalizeImplicitBindingPass(PassRegistry &);
} // namespace llvm
diff --git a/llvm/lib/Target/SPIRV/SPIRVPrepareGlobals.cpp b/llvm/lib/Target/SPIRV/SPIRVPrepareGlobals.cpp
new file mode 100644
index 0000000000000..46c8a6f2c3a54
--- /dev/null
+++ b/llvm/lib/Target/SPIRV/SPIRVPrepareGlobals.cpp
@@ -0,0 +1,43 @@
+//===-- SPIRVPrepareGlobals.cpp - Prepare IR SPIRV globals ------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// The pass transforms IR globals that cannot be trivially mapped to SPIRV
+// into something that is trival to lower.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SPIRV.h"
+
+using namespace llvm;
+
+namespace {
+
+struct SPIRVPrepareGlobals : public ModulePass {
+ static char ID;
+ SPIRVPrepareGlobals() : ModulePass(ID) {}
+
+ StringRef getPassName() const override {
+ return "SPIRV prepare global variables";
+ }
+
+ bool runOnModule(Module &M) override;
+};
+
+bool SPIRVPrepareGlobals::runOnModule(Module &M) { return false; }
+char SPIRVPrepareGlobals::ID = 0;
+
+} // namespace
+
+INITIALIZE_PASS(SPIRVPrepareGlobals, "prepare-globals",
+ "SPIRV prepare global variables", false, false)
+
+namespace llvm {
+ModulePass *createSPIRVPrepareGlobalsPass() {
+ return new SPIRVPrepareGlobals();
+}
+} // namespace llvm
diff --git a/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp b/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp
index 2951a4bc695e2..10bbca225b20a 100644
--- a/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp
@@ -59,6 +59,7 @@ extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSPIRVTarget() {
initializeSPIRVEmitIntrinsicsPass(PR);
initializeSPIRVEmitNonSemanticDIPass(PR);
initializeSPIRVPrepareFunctionsPass(PR);
+ initializeSPIRVPrepareGlobalsPass(PR);
initializeSPIRVStripConvergentIntrinsicsPass(PR);
}
@@ -172,6 +173,7 @@ void SPIRVPassConfig::addIRPasses() {
addPass(createSPIRVRegularizerPass());
addPass(createSPIRVPrepareFunctionsPass(TM));
+ addPass(createSPIRVPrepareGlobalsPass());
}
void SPIRVPassConfig::addISelPrepare() {
diff --git a/llvm/test/CodeGen/SPIRV/llc-pipeline.ll b/llvm/test/CodeGen/SPIRV/llc-pipeline.ll
index 3fff2a8a24a73..6db375445e4a3 100644
--- a/llvm/test/CodeGen/SPIRV/llc-pipeline.ll
+++ b/llvm/test/CodeGen/SPIRV/llc-pipeline.ll
@@ -31,6 +31,7 @@
; SPIRV-O0-NEXT: Expand reduction intrinsics
; SPIRV-O0-NEXT: SPIR-V Regularizer
; SPIRV-O0-NEXT: SPIRV prepare functions
+; SPIRV-O0-NEXT: SPIRV prepare global variables
; SPIRV-O0-NEXT: FunctionPass Manager
; SPIRV-O0-NEXT: Lower invoke and unwind, for unwindless code generators
; SPIRV-O0-NEXT: Remove unreachable blocks from the CFG
@@ -130,6 +131,7 @@
; SPIRV-Opt-NEXT: Expand reduction intrinsics
; SPIRV-Opt-NEXT: SPIR-V Regularizer
; SPIRV-Opt-NEXT: SPIRV prepare functions
+; SPIRV-Opt-NEXT: SPIRV prepare global variables
; SPIRV-Opt-NEXT: FunctionPass Manager
; SPIRV-Opt-NEXT: Dominator Tree Construction
; SPIRV-Opt-NEXT: Natural Loop Information
>From eb7f3404fa31441460e97833e12014508be9d936 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?=
<jmartinezcaamao at gmail.com>
Date: Fri, 7 Nov 2025 13:55:31 +0100
Subject: [PATCH 2/3] Pre-commit test: [SPIRV][SPIRVPrepareGlobals]
tryExtendLLVMBitcodeMarker
---
.../CodeGen/SPIRV/fembed-bitcode-marker.ll | 22 +++++++++++++
llvm/test/CodeGen/SPIRV/fembed-bitcode.ll | 32 +++++++++++++++++++
2 files changed, 54 insertions(+)
create mode 100644 llvm/test/CodeGen/SPIRV/fembed-bitcode-marker.ll
create mode 100644 llvm/test/CodeGen/SPIRV/fembed-bitcode.ll
diff --git a/llvm/test/CodeGen/SPIRV/fembed-bitcode-marker.ll b/llvm/test/CodeGen/SPIRV/fembed-bitcode-marker.ll
new file mode 100644
index 0000000000000..863736ef84d87
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/fembed-bitcode-marker.ll
@@ -0,0 +1,22 @@
+; RUN: not llc -verify-machineinstrs -mtriple=spirv-unknown-unknown %s -o -
+; RUN: not llc -verify-machineinstrs -mtriple=spirv64-amd-amdhsa %s -o -
+;
+; Verify that we lower the embedded bitcode
+
+ at llvm.embedded.module = private addrspace(1) constant [0 x i8] zeroinitializer, section ".llvmbc", align 1
+ at llvm.compiler.used = appending addrspace(1) global [1 x ptr addrspace(4)] [ptr addrspace(4) addrspacecast (ptr addrspace(1) @llvm.embedded.module to ptr addrspace(4))], section "llvm.metadata"
+
+; CHECK: OpName %[[#LLVM_EMBEDDED_MODULE:]] "llvm.embedded.module"
+; CHECK: OpDecorate %[[#LLVM_EMBEDDED_MODULE]] Constant
+; CHECK: %[[#UCHAR:]] = OpTypeInt 8 0
+; CHECK: %[[#UINT:]] = OpTypeInt 32 0
+; CHECK: %[[#ONE:]] = OpConstant %[[#UINT]] 1
+; CHECK: %[[#UCHAR_ARR_1:]] = OpTypeArray %[[#UCHAR]] %[[#ONE]]
+; CHECK: %[[#UCHAR_ARR_1_PTR:]] = OpTypePointer CrossWorkgroup %[[#UCHAR_ARR_1]]
+; CHECK: %[[#CONST_UCHAR_ARR_1:]] = OpConstantNull %[[#UCHAR_ARR_1]]
+; CHECK: %[[#LLVM_EMBEDDED_MODULE]] = OpVariable %[[#UCHAR_ARR_1_PTR]] CrossWorkgroup %[[#CONST_UCHAR_ARR_1]]
+
+define spir_kernel void @foo() {
+entry:
+ ret void
+}
diff --git a/llvm/test/CodeGen/SPIRV/fembed-bitcode.ll b/llvm/test/CodeGen/SPIRV/fembed-bitcode.ll
new file mode 100644
index 0000000000000..1e7106e0674c5
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/fembed-bitcode.ll
@@ -0,0 +1,32 @@
+; RUN: llc -verify-machineinstrs -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+; RUN: llc -verify-machineinstrs -mtriple=spirv64-amd-amdhsa %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -mtriple=spirv64-amd-amdhsa %s -o - -filetype=obj | spirv-val %}
+;
+; Verify that we can lower the embeded module and cmdline
+
+ at llvm.embedded.module = private addrspace(1) constant [4 x i8] c"BC\C0\DE", section ".llvmbc", align 1
+ at llvm.cmdline = private addrspace(1) constant [5 x i8] c"-cc1\00", section ".llvmcmd", align 1
+ at llvm.compiler.used = appending addrspace(1) global [2 x ptr addrspace(4)] [ptr addrspace(4) addrspacecast (ptr addrspace(1) @llvm.embedded.module to ptr addrspace(4)), ptr addrspace(4) addrspacecast (ptr addrspace(1) @llvm.cmdline to ptr addrspace(4))], section "llvm.metadata"
+
+; CHECK: OpName %[[#LLVM_EMBEDDED_MODULE:]] "llvm.embedded.module"
+; CHECK: OpName %[[#LLVM_CMDLINE:]] "llvm.cmdline"
+; CHECK: OpDecorate %[[#LLVM_EMBEDDED_MODULE]] Constant
+; CHECK: OpDecorate %[[#LLVM_CMDLINE]] Constant
+; CHECK: %[[#UCHAR:]] = OpTypeInt 8 0
+; CHECK: %[[#UINT:]] = OpTypeInt 32 0
+; CHECK: %[[#FIVE:]] = OpConstant %[[#UINT]] 5
+; CHECK: %[[#UCHAR_ARR_5:]] = OpTypeArray %[[#UCHAR]] %[[#FIVE]]
+; CHECK: %[[#FOUR:]] = OpConstant %[[#UINT]] 4
+; CHECK: %[[#UCHAR_ARR_4:]] = OpTypeArray %[[#UCHAR]] %[[#FOUR]]
+; CHECK: %[[#UCHAR_ARR_5_PTR:]] = OpTypePointer CrossWorkgroup %[[#UCHAR_ARR_5]]
+; CHECK: %[[#UCHAR_ARR_4_PTR:]] = OpTypePointer CrossWorkgroup %[[#UCHAR_ARR_4]]
+; CHECK: %[[#CONST_UCHAR_ARR_4:]] = OpConstantComposite %[[#UCHAR_ARR_4]]
+; CHECK: %[[#LLVM_EMBEDDED_MODULE]] = OpVariable %[[#UCHAR_ARR_4_PTR]] CrossWorkgroup %[[#CONST_UCHAR_ARR_4]]
+; CHECK: %[[#CONST_UCHAR_ARR_5:]] = OpConstantComposite %[[#UCHAR_ARR_5]]
+; CHECK: %[[#LLVM_CMDLINE]] = OpVariable %[[#UCHAR_ARR_5_PTR]] CrossWorkgroup %[[#CONST_UCHAR_ARR_5]]
+
+define spir_kernel void @foo() {
+entry:
+ ret void
+}
>From 5815524bd328eab02e806712ebbc8fdd087c2063 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?=
<jmartinezcaamao at gmail.com>
Date: Thu, 6 Nov 2025 17:14:10 +0100
Subject: [PATCH 3/3] [SPIRV][SPIRVPrepareGlobals] Convert llvm.embedded.module
from a 0-element array to a 1-element array
When compiling with -fembed-bitcode-marker, Clang inserts a placeholder
for the bitcode. This placeholder is a [0 x i8] array, which we cannot
represent in SPIRV.
For AMD flavoured SPIRV, we extend the llvm.embedded.module global to a
zeroinitialized 1-element array.
---
llvm/lib/Target/SPIRV/SPIRVPrepareGlobals.cpp | 27 ++++++++++++++++++-
.../CodeGen/SPIRV/fembed-bitcode-marker.ll | 4 ++-
2 files changed, 29 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Target/SPIRV/SPIRVPrepareGlobals.cpp b/llvm/lib/Target/SPIRV/SPIRVPrepareGlobals.cpp
index 46c8a6f2c3a54..c44c53129f1e0 100644
--- a/llvm/lib/Target/SPIRV/SPIRVPrepareGlobals.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVPrepareGlobals.cpp
@@ -13,6 +13,8 @@
#include "SPIRV.h"
+#include "llvm/IR/Module.h"
+
using namespace llvm;
namespace {
@@ -28,7 +30,30 @@ struct SPIRVPrepareGlobals : public ModulePass {
bool runOnModule(Module &M) override;
};
-bool SPIRVPrepareGlobals::runOnModule(Module &M) { return false; }
+bool tryExtendLLVMBitcodeMarker(GlobalVariable &Bitcode) {
+ assert(Bitcode.getName() == "llvm.embedded.module");
+
+ ArrayType *AT = cast<ArrayType>(Bitcode.getValueType());
+ if (AT->getNumElements() != 0)
+ return false;
+
+ ArrayType *AT1 = ArrayType::get(AT->getElementType(), 1);
+ Constant *OneEltInit = Constant::getNullValue(AT1);
+ Bitcode.replaceInitializer(OneEltInit);
+ return true;
+}
+
+bool SPIRVPrepareGlobals::runOnModule(Module &M) {
+ const bool IsAMD = M.getTargetTriple().getVendor() == Triple::AMD;
+ if (!IsAMD)
+ return false;
+
+ bool Changed = false;
+ if (GlobalVariable *Bitcode = M.getNamedGlobal("llvm.embedded.module"))
+ Changed |= tryExtendLLVMBitcodeMarker(*Bitcode);
+
+ return Changed;
+}
char SPIRVPrepareGlobals::ID = 0;
} // namespace
diff --git a/llvm/test/CodeGen/SPIRV/fembed-bitcode-marker.ll b/llvm/test/CodeGen/SPIRV/fembed-bitcode-marker.ll
index 863736ef84d87..72caa68b52930 100644
--- a/llvm/test/CodeGen/SPIRV/fembed-bitcode-marker.ll
+++ b/llvm/test/CodeGen/SPIRV/fembed-bitcode-marker.ll
@@ -1,5 +1,7 @@
+; Expanding the bitcode marker works only for AMD at the moment
; RUN: not llc -verify-machineinstrs -mtriple=spirv-unknown-unknown %s -o -
-; RUN: not llc -verify-machineinstrs -mtriple=spirv64-amd-amdhsa %s -o -
+; RUN: llc -verify-machineinstrs -mtriple=spirv64-amd-amdhsa %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -mtriple=spirv64-amd-amdhsa %s -o - -filetype=obj | spirv-val %}
;
; Verify that we lower the embedded bitcode
More information about the llvm-commits
mailing list