[llvm] [SPIRV] Support -fembed-bitcode=marker for non-shader modules (PR #162082)

Juan Manuel Martinez CaamaƱo via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 7 01:32:32 PDT 2025


https://github.com/jmmartinez updated https://github.com/llvm/llvm-project/pull/162082

>From 2cb721d203110602dbe178a784af79d75f337287 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?= <juamarti at amd.com>
Date: Mon, 6 Oct 2025 14:20:17 +0200
Subject: [PATCH 1/4] Pre-Commit tests: [SPIRV] Support -fembed-bitcode=marker
 for non-shader modules

---
 .../SPIRV/fembed-bitcode-marker-shader.ll     | 21 ++++++++++++++++
 .../CodeGen/SPIRV/fembed-bitcode-marker.ll    | 11 ++++++++
 llvm/test/CodeGen/SPIRV/fembed-bitcode.ll     | 25 +++++++++++++++++++
 3 files changed, 57 insertions(+)
 create mode 100644 llvm/test/CodeGen/SPIRV/fembed-bitcode-marker-shader.ll
 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-shader.ll b/llvm/test/CodeGen/SPIRV/fembed-bitcode-marker-shader.ll
new file mode 100644
index 0000000000000..20ac543486766
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/fembed-bitcode-marker-shader.ll
@@ -0,0 +1,21 @@
+; RUN: llc -verify-machineinstrs -mtriple=spirv-vulkan-unknown %s -o - | FileCheck %s
+
+ at llvm.embedded.module = private constant [0 x i8] zeroinitializer, section ".llvmbc", align 1
+ at llvm.cmdline = private constant [5 x i8] c"-cc1\00", section ".llvmcmd", align 1
+ at llvm.compiler.used = appending global [2 x ptr] [ptr @llvm.embedded.module, ptr @llvm.cmdline], section "llvm.metadata"
+
+; CHECK-DAG: OpName [[FOO:%[0-9]+]] "foo"
+; CHECK-DAG: OpName [[MODULE:%[0-9]+]] "llvm.embedded.module"
+; CHECK-DAG: [[INT8:%[0-9]+]] = OpTypeInt 8 0
+; CHECK-DAG: [[RUNTIME_ARRAY_INT8x1:%[0-9]+]] = OpTypeRuntimeArray [[INT8]]
+; CHECK-DAG: [[POINTER:%[0-9]+]] = OpTypePointer Function [[RUNTIME_ARRAY_INT8x1]]
+; CHECK-DAG: [[EMBEDDED_MODULE_INIT:%[0-9]+]] = OpConstantNull [[RUNTIME_ARRAY_INT8x1]]
+; CHECK: [[FOO]] = OpFunction {{.*}} None {{.*}} 
+; CHECK-DAG: {{%[0-9]+}} = OpVariable [[POINTER]] Function [[EMBEDDED_MODULE_INIT]]
+
+define void @foo() #1 {
+entry:
+  ret void
+}
+
+attributes #1 = { "hlsl.numthreads"="4,8,16" "hlsl.shader"="compute" }
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..6bc9beec1e9e3
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/fembed-bitcode-marker.ll
@@ -0,0 +1,11 @@
+; XFAIL: *
+; RUN: llc -verify-machineinstrs -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
+
+ at llvm.embedded.module = private constant [0 x i8] zeroinitializer, section ".llvmbc", align 1
+ at llvm.cmdline = private constant [5 x i8] c"-cc1\00", section ".llvmcmd", align 1
+ at llvm.compiler.used = appending global [2 x ptr] [ptr @llvm.embedded.module, ptr @llvm.cmdline], section "llvm.metadata"
+
+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..0044e09aceaab
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/fembed-bitcode.ll
@@ -0,0 +1,25 @@
+; RUN: llc -verify-machineinstrs -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
+
+ at llvm.embedded.module = private constant [4 x i8] c"BC\C0\DE", section ".llvmbc", align 1
+ at llvm.cmdline = private constant [5 x i8] c"-cc1\00", section ".llvmcmd", align 1
+ at llvm.compiler.used = appending global [2 x ptr] [ptr @llvm.embedded.module, ptr @llvm.cmdline], section "llvm.metadata"
+
+; CHECK-DAG: OpName [[FOO:%[0-9]+]] "foo"
+; CHECK-DAG: OpName [[MODULE:%[0-9]+]] "llvm.embedded.module"
+; CHECK-DAG: [[INT8:%[0-9]+]] = OpTypeInt 8 0
+; CHECK-DAG: [[INT32:%[0-9]+]] = OpTypeInt 32 0
+; CHECK-DAG: [[CONST_4_32:%[0-9]+]] = OpConstant [[INT32]] 4
+; CHECK-DAG: [[ARRAY_INT8x4:%[0-9]+]] = OpTypeArray [[INT8]] [[CONST_4_32]]
+; CHECK-DAG: [[POINTER:%[0-9]+]] = OpTypePointer Function [[ARRAY_INT8x4]]
+; CHECK-DAG: [[CONST_B_8:%[0-9]+]] = OpConstant [[INT8]] 66
+; CHECK-DAG: [[CONST_C_8:%[0-9]+]] = OpConstant [[INT8]] 67
+; CHECK-DAG: [[CONST_0xC0_8:%[0-9]+]] = OpConstant [[INT8]] 192
+; CHECK-DAG: [[CONST_0xDE_8:%[0-9]+]] = OpConstant [[INT8]] 222
+; CHECK-DAG: [[EMBEDDED_MODULE_INIT:%[0-9]+]] = OpConstantComposite [[ARRAY_INT8x4]] [[CONST_B_8]] [[CONST_C_8]] [[CONST_0xC0_8]] [[CONST_0xDE_8]]
+; CHECK: [[FOO]] = OpFunction {{.*}} None {{.*}} 
+; CHECK-DAG: {{%[0-9]+}} = OpVariable [[POINTER]] Function [[EMBEDDED_MODULE_INIT]]
+
+define spir_kernel void @foo() {
+entry:
+  ret void
+}

>From 806bb398c21045ed3f27bb328f89392e05efb0ab Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?= <juamarti at amd.com>
Date: Tue, 7 Oct 2025 10:14:27 +0200
Subject: [PATCH 2/4] [Review] Add spirv-val call to tests

---
 llvm/test/CodeGen/SPIRV/fembed-bitcode-marker-shader.ll | 1 +
 llvm/test/CodeGen/SPIRV/fembed-bitcode-marker.ll        | 1 +
 llvm/test/CodeGen/SPIRV/fembed-bitcode.ll               | 1 +
 3 files changed, 3 insertions(+)

diff --git a/llvm/test/CodeGen/SPIRV/fembed-bitcode-marker-shader.ll b/llvm/test/CodeGen/SPIRV/fembed-bitcode-marker-shader.ll
index 20ac543486766..811a4be7726af 100644
--- a/llvm/test/CodeGen/SPIRV/fembed-bitcode-marker-shader.ll
+++ b/llvm/test/CodeGen/SPIRV/fembed-bitcode-marker-shader.ll
@@ -1,4 +1,5 @@
 ; RUN: llc -verify-machineinstrs -mtriple=spirv-vulkan-unknown %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
 
 @llvm.embedded.module = private constant [0 x i8] zeroinitializer, section ".llvmbc", align 1
 @llvm.cmdline = private constant [5 x i8] c"-cc1\00", section ".llvmcmd", align 1
diff --git a/llvm/test/CodeGen/SPIRV/fembed-bitcode-marker.ll b/llvm/test/CodeGen/SPIRV/fembed-bitcode-marker.ll
index 6bc9beec1e9e3..b727e5dd84545 100644
--- a/llvm/test/CodeGen/SPIRV/fembed-bitcode-marker.ll
+++ b/llvm/test/CodeGen/SPIRV/fembed-bitcode-marker.ll
@@ -1,5 +1,6 @@
 ; XFAIL: *
 ; 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 %}
 
 @llvm.embedded.module = private constant [0 x i8] zeroinitializer, section ".llvmbc", align 1
 @llvm.cmdline = private constant [5 x i8] c"-cc1\00", section ".llvmcmd", align 1
diff --git a/llvm/test/CodeGen/SPIRV/fembed-bitcode.ll b/llvm/test/CodeGen/SPIRV/fembed-bitcode.ll
index 0044e09aceaab..fa6ef86288d7c 100644
--- a/llvm/test/CodeGen/SPIRV/fembed-bitcode.ll
+++ b/llvm/test/CodeGen/SPIRV/fembed-bitcode.ll
@@ -1,4 +1,5 @@
 ; 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 %}
 
 @llvm.embedded.module = private constant [4 x i8] c"BC\C0\DE", section ".llvmbc", align 1
 @llvm.cmdline = private constant [5 x i8] c"-cc1\00", section ".llvmcmd", align 1

>From 7e22ddd11fbd9cfb8fd0f0da01b6e33ad1496cfd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?= <juamarti at amd.com>
Date: Mon, 6 Oct 2025 13:48:36 +0200
Subject: [PATCH 3/4] [SPIRV] Support -fembed-bitcode=marker for non-shader
 modules

-fembed-bitcode=marker gets lowered as a [0 x i8] zeroinitialized global
variable. This is interpreted as a runtime-array and is not supported in
non-shaders.

To work around this, we replace the [0 x i8] by a zeroinitialized
single-element array.
---
 llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 36 +++++++++++++++++++
 .../CodeGen/SPIRV/fembed-bitcode-marker.ll    | 12 ++++++-
 2 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index e16c8f0fc302e..08dce614504f1 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -236,6 +236,8 @@ class SPIRVEmitIntrinsics
 
   Instruction *buildLogicalAccessChainFromGEP(GetElementPtrInst &GEP);
 
+  bool promoteEmbddedBitcodeMarker(Module &M) const;
+
 public:
   static char ID;
   SPIRVEmitIntrinsics(SPIRVTargetMachine *TM = nullptr)
@@ -3005,9 +3007,43 @@ void SPIRVEmitIntrinsics::parseFunDeclarations(Module &M) {
   }
 }
 
+bool SPIRVEmitIntrinsics::promoteEmbddedBitcodeMarker(Module &M) const {
+  const SPIRVSubtarget *STI = TM->getSubtargetImpl();
+  if (STI->isShader())
+    return false;
+
+  GlobalVariable *EmbeddedBitcode = M.getNamedGlobal("llvm.embedded.module");
+  if (!EmbeddedBitcode)
+    return false;
+
+  ArrayType *AT = cast<ArrayType>(EmbeddedBitcode->getValueType());
+  if (AT->getNumElements() != 0)
+    return false;
+
+  // When compiling with -fembed-bitcode=marker, LLVM generates a [0 x i8]
+  // zeroinitialized global variable containing the bitcode. This results in an
+  // assert outside of shaders. As a workaround, we replace this global with a
+  // zeroinitialized [1 x i8].
+  ArrayType *AT1 = ArrayType::get(AT->getElementType(), 1);
+  Constant *ZeroInit = Constant::getNullValue(AT1);
+  GlobalVariable *NewEmbeddedBitcode = new GlobalVariable(
+      AT1, EmbeddedBitcode->isConstant(), EmbeddedBitcode->getLinkage(),
+      ZeroInit, "", EmbeddedBitcode->getThreadLocalMode(),
+      EmbeddedBitcode->getAddressSpace(),
+      EmbeddedBitcode->isExternallyInitialized());
+  NewEmbeddedBitcode->setSection(NewEmbeddedBitcode->getSection());
+  NewEmbeddedBitcode->takeName(EmbeddedBitcode);
+
+  M.insertGlobalVariable(NewEmbeddedBitcode);
+  EmbeddedBitcode->replaceAllUsesWith(NewEmbeddedBitcode);
+  EmbeddedBitcode->eraseFromParent();
+  return true;
+}
+
 bool SPIRVEmitIntrinsics::runOnModule(Module &M) {
   bool Changed = false;
 
+  Changed |= promoteEmbddedBitcodeMarker(M);
   parseFunDeclarations(M);
   insertConstantsForFPFastMathDefault(M);
 
diff --git a/llvm/test/CodeGen/SPIRV/fembed-bitcode-marker.ll b/llvm/test/CodeGen/SPIRV/fembed-bitcode-marker.ll
index b727e5dd84545..1b0c13f36fc56 100644
--- a/llvm/test/CodeGen/SPIRV/fembed-bitcode-marker.ll
+++ b/llvm/test/CodeGen/SPIRV/fembed-bitcode-marker.ll
@@ -1,4 +1,3 @@
-; XFAIL: *
 ; 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 %}
 
@@ -6,6 +5,17 @@
 @llvm.cmdline = private constant [5 x i8] c"-cc1\00", section ".llvmcmd", align 1
 @llvm.compiler.used = appending global [2 x ptr] [ptr @llvm.embedded.module, ptr @llvm.cmdline], section "llvm.metadata"
 
+; CHECK-DAG: OpName [[FOO:%[0-9]+]] "foo"
+; CHECK-DAG: OpName [[MODULE:%[0-9]+]] "llvm.embedded.module"
+; CHECK-DAG: [[INT8:%[0-9]+]] = OpTypeInt 8 0
+; CHECK-DAG: [[INT32:%[0-9]+]] = OpTypeInt 32 0
+; CHECK-DAG: [[CONST_1_32:%[0-9]+]] = OpConstant [[INT32]] 1
+; CHECK-DAG: [[ARRAY_INT8x1:%[0-9]+]] = OpTypeArray [[INT8]] [[CONST_1_32]]
+; CHECK-DAG: [[POINTER:%[0-9]+]] = OpTypePointer Function [[ARRAY_INT8x1]]
+; CHECK-DAG: [[EMBEDDED_MODULE_INIT:%[0-9]+]] = OpConstantNull [[ARRAY_INT8x1]]
+; CHECK: [[FOO]] = OpFunction {{.*}} None {{.*}}
+; CHECK-DAG: {{%[0-9]+}} = OpVariable [[POINTER]] Function [[EMBEDDED_MODULE_INIT]]
+
 define spir_kernel void @foo() {
 entry:
   ret void

>From 5c2271caae04cd5b55ee797fe590156ad6b6f041 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?= <juamarti at amd.com>
Date: Tue, 7 Oct 2025 10:04:46 +0200
Subject: [PATCH 4/4] [Review] Fix names

---
 llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index 08dce614504f1..647502155f4e2 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -236,7 +236,7 @@ class SPIRVEmitIntrinsics
 
   Instruction *buildLogicalAccessChainFromGEP(GetElementPtrInst &GEP);
 
-  bool promoteEmbddedBitcodeMarker(Module &M) const;
+  bool promoteEmbeddedBitcodeMarkear(Module &M) const;
 
 public:
   static char ID;
@@ -3007,7 +3007,7 @@ void SPIRVEmitIntrinsics::parseFunDeclarations(Module &M) {
   }
 }
 
-bool SPIRVEmitIntrinsics::promoteEmbddedBitcodeMarker(Module &M) const {
+bool SPIRVEmitIntrinsics::promoteEmbeddedBitcodeMarkear(Module &M) const {
   const SPIRVSubtarget *STI = TM->getSubtargetImpl();
   if (STI->isShader())
     return false;
@@ -3016,18 +3016,18 @@ bool SPIRVEmitIntrinsics::promoteEmbddedBitcodeMarker(Module &M) const {
   if (!EmbeddedBitcode)
     return false;
 
-  ArrayType *AT = cast<ArrayType>(EmbeddedBitcode->getValueType());
-  if (AT->getNumElements() != 0)
+  ArrayType *ArrTy = cast<ArrayType>(EmbeddedBitcode->getValueType());
+  if (ArrTy->getNumElements() != 0)
     return false;
 
   // When compiling with -fembed-bitcode=marker, LLVM generates a [0 x i8]
   // zeroinitialized global variable containing the bitcode. This results in an
   // assert outside of shaders. As a workaround, we replace this global with a
   // zeroinitialized [1 x i8].
-  ArrayType *AT1 = ArrayType::get(AT->getElementType(), 1);
-  Constant *ZeroInit = Constant::getNullValue(AT1);
+  ArrayType *ArrTyOneElt = ArrayType::get(ArrTy->getElementType(), 1);
+  Constant *ZeroInit = Constant::getNullValue(ArrTyOneElt);
   GlobalVariable *NewEmbeddedBitcode = new GlobalVariable(
-      AT1, EmbeddedBitcode->isConstant(), EmbeddedBitcode->getLinkage(),
+      ArrTyOneElt, EmbeddedBitcode->isConstant(), EmbeddedBitcode->getLinkage(),
       ZeroInit, "", EmbeddedBitcode->getThreadLocalMode(),
       EmbeddedBitcode->getAddressSpace(),
       EmbeddedBitcode->isExternallyInitialized());
@@ -3043,7 +3043,7 @@ bool SPIRVEmitIntrinsics::promoteEmbddedBitcodeMarker(Module &M) const {
 bool SPIRVEmitIntrinsics::runOnModule(Module &M) {
   bool Changed = false;
 
-  Changed |= promoteEmbddedBitcodeMarker(M);
+  Changed |= promoteEmbeddedBitcodeMarkear(M);
   parseFunDeclarations(M);
   insertConstantsForFPFastMathDefault(M);
 



More information about the llvm-commits mailing list