[clang] [llvm] [HLSL][SPIR-V] Implement vk::push_constant (PR #166793)
Steven Perron via llvm-commits
llvm-commits at lists.llvm.org
Wed Dec 10 07:58:44 PST 2025
================
@@ -0,0 +1,108 @@
+//===- SPIRVPushConstantAccess.cpp - Translate CBuffer Loads ---------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass changes the types of all the globals in the PushConstant
+// address space into a target extension type, and makes all references
+// to this global go though a custom SPIR-V intrinsic.
+//
+// This allows the backend to properly lower the push constant struct type
+// to a fully laid out type, and generate the proper OpAccessChain.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SPIRVPushConstantAccess.h"
+#include "SPIRV.h"
+#include "SPIRVSubtarget.h"
+#include "SPIRVTargetMachine.h"
+#include "SPIRVUtils.h"
+#include "llvm/Frontend/HLSL/CBuffer.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/IntrinsicsSPIRV.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/ReplaceConstant.h"
+
+#define DEBUG_TYPE "spirv-pushconstant-access"
+using namespace llvm;
+
+static bool replacePushConstantAccesses(Module &M, SPIRVGlobalRegistry *GR) {
+ SmallVector<GlobalVariable *> PushConstants;
+ for (GlobalVariable &GV : M.globals()) {
+ if (GV.getAddressSpace() ==
+ storageClassToAddressSpace(SPIRV::StorageClass::PushConstant))
+ PushConstants.push_back(&GV);
+ }
+
+ for (GlobalVariable *GV : PushConstants) {
+ Type *PCType = llvm::TargetExtType::get(
+ M.getContext(), "spirv.PushConstant", {GV->getValueType()});
+ GlobalVariable *NewGV = new GlobalVariable(
+ M, PCType, GV->isConstant(), GV->getLinkage(),
+ /* initializer= */ nullptr, GV->getName(),
+ /* InsertBefore= */ GV, GV->getThreadLocalMode(), GV->getAddressSpace(),
+ GV->isExternallyInitialized());
+
+ SmallVector<User *, 4> Users(GV->user_begin(), GV->user_end());
+ for (llvm::User *U : Users) {
+ Instruction *I = dyn_cast<Instruction>(U);
+ if (!I)
+ continue;
----------------
s-perron wrote:
What are the non instruction uses, and why is it okay to leave them as is? Looking at the tests, I don't see any case where this happens.
https://github.com/llvm/llvm-project/pull/166793
More information about the llvm-commits
mailing list