From 639ac4c16b07f8316a7b32f9010365ea0b250f1c Mon Sep 17 00:00:00 2001 From: Steven Perron Date: Tue, 3 Dec 2024 12:42:40 -0500 Subject: [PATCH 1/6] [SPIRV] Expand RWBuffer load and store from HLSL The code pattern that clang will generate for HLSL has changed from the original plan. This allows the SPIR-V backend to generate code for the current code generation. It looks for patterns of the form: ``` %1 = @llvm.spv.resource.handlefrombinding %2 = @llvm.spv.resource.getpointer(%1, index) load/store %2 ``` These three llvm-ir instruction are treated as a single unit that will 1. Generate or find the global variable identified by the call to `resource.handlefrombinding`. 2. Generate an OpLoad of the variable to get the handle to the image. 3. Generate an OpImageRead or OpImageWrite using that handle with the given index. This will generate the OpLoad in the same BB as the read/write. Note: Now that `resource.handlefrombinding` is not processed on its own, many existing tests had to be removed. We do not have intrinsics that are able to use handles to sampled images, input attachments, etc., so we cannot generate the load of the handle. These tests are removed for now, and will be added when those resource types are fully implemented. --- llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp index 702206b8e0dc5..02b3ac9803deb 100644 --- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp @@ -731,6 +731,14 @@ Type *SPIRVEmitIntrinsics::deduceElementTypeHelper( if (Ty) break; } + } else if (auto *II = dyn_cast(I)) { + if (II->getIntrinsicID() == Intrinsic::spv_resource_getpointer) { + auto *ImageType = cast(II->getOperand(0)->getType()); + assert(ImageType->getTargetExtName() == "spirv.Image"); + Ty = ImageType->getTypeParameter(0); + // TODO: Need to look at the use to see if it needs to be a vector of the + // type. + } } else if (auto *CI = dyn_cast(I)) { static StringMap ResTypeByArg = { {"to_global", 0}, From 3c4b8af078517f66178367b9dd2bfd2c68e28c7d Mon Sep 17 00:00:00 2001 From: Steven Perron Date: Mon, 13 Jan 2025 14:51:29 -0500 Subject: [PATCH 2/6] Move type deduction for getpointer into `CallInst` case. --- llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp index 02b3ac9803deb..b59aa797ca3ea 100644 --- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp @@ -731,14 +731,6 @@ Type *SPIRVEmitIntrinsics::deduceElementTypeHelper( if (Ty) break; } - } else if (auto *II = dyn_cast(I)) { - if (II->getIntrinsicID() == Intrinsic::spv_resource_getpointer) { - auto *ImageType = cast(II->getOperand(0)->getType()); - assert(ImageType->getTargetExtName() == "spirv.Image"); - Ty = ImageType->getTypeParameter(0); - // TODO: Need to look at the use to see if it needs to be a vector of the - // type. - } } else if (auto *CI = dyn_cast(I)) { static StringMap ResTypeByArg = { {"to_global", 0}, @@ -749,7 +741,8 @@ Type *SPIRVEmitIntrinsics::deduceElementTypeHelper( {"__spirv_GenericCastToPtr_ToPrivate", 0}, {"__spirv_GenericCastToPtrExplicit_ToGlobal", 0}, {"__spirv_GenericCastToPtrExplicit_ToLocal", 0}, - {"__spirv_GenericCastToPtrExplicit_ToPrivate", 0}}; + {"__spirv_GenericCastToPtrExplicit_ToPrivate", 0}, + {"llvm.spv.resource.getpointer", 0}}; // TODO: maybe improve performance by caching demangled names auto *II = dyn_cast(I); From adb1306a9ec6db00ece44850ad78e5f830ff52be Mon Sep 17 00:00:00 2001 From: Steven Perron Date: Tue, 14 Jan 2025 09:50:17 -0500 Subject: [PATCH 3/6] Remove unused table entry. --- llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp index b59aa797ca3ea..702206b8e0dc5 100644 --- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp @@ -741,8 +741,7 @@ Type *SPIRVEmitIntrinsics::deduceElementTypeHelper( {"__spirv_GenericCastToPtr_ToPrivate", 0}, {"__spirv_GenericCastToPtrExplicit_ToGlobal", 0}, {"__spirv_GenericCastToPtrExplicit_ToLocal", 0}, - {"__spirv_GenericCastToPtrExplicit_ToPrivate", 0}, - {"llvm.spv.resource.getpointer", 0}}; + {"__spirv_GenericCastToPtrExplicit_ToPrivate", 0}}; // TODO: maybe improve performance by caching demangled names auto *II = dyn_cast(I); From 466738cd9a896d14e96766005405f20e08cdae2a Mon Sep 17 00:00:00 2001 From: Steven Perron Date: Thu, 16 Jan 2025 11:32:16 -0500 Subject: [PATCH 4/6] Move DXILFinalizeLinkage out of backend to clang. --- clang/lib/CodeGen/BackendUtil.cpp | 6 ++++++ clang/lib/CodeGen/CMakeLists.txt | 1 + .../Transforms/HLSL}/DXILFinalizeLinkage.h | 0 llvm/lib/Target/DirectX/CMakeLists.txt | 1 - .../Target/DirectX/DirectXTargetMachine.cpp | 2 -- llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp | 2 ++ llvm/lib/Transforms/CMakeLists.txt | 1 + llvm/lib/Transforms/HLSL/CMakeLists.txt | 18 +++++++++++++++++ .../HLSL}/DXILFinalizeLinkage.cpp | 20 ++----------------- 9 files changed, 30 insertions(+), 21 deletions(-) rename llvm/{lib/Target/DirectX => include/llvm/Transforms/HLSL}/DXILFinalizeLinkage.h (100%) create mode 100644 llvm/lib/Transforms/HLSL/CMakeLists.txt rename llvm/lib/{Target/DirectX => Transforms/HLSL}/DXILFinalizeLinkage.cpp (72%) diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 3951ad01497cc..b43689f3c0f13 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -57,6 +57,7 @@ #include "llvm/TargetParser/SubtargetFeature.h" #include "llvm/TargetParser/Triple.h" #include "llvm/Transforms/HipStdPar/HipStdPar.h" +#include "llvm/Transforms/HLSL/DXILFinalizeLinkage.h" #include "llvm/Transforms/IPO/EmbedBitcodePass.h" #include "llvm/Transforms/IPO/LowerTypeTests.h" #include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h" @@ -1164,6 +1165,11 @@ void EmitAssemblyHelper::RunOptimizationPipeline( LangOpts.HIPStdParInterposeAlloc) MPM.addPass(HipStdParAllocationInterpositionPass()); + if (LangOpts.HLSL) { + // HLSL legalization passes + MPM.addPass(DXILFinalizeLinkage()); + } + // Now that we have all of the passes ready, run them. { PrettyStackTraceString CrashInfo("Optimizer"); diff --git a/clang/lib/CodeGen/CMakeLists.txt b/clang/lib/CodeGen/CMakeLists.txt index 868ec847b9634..1c7929219fcfc 100644 --- a/clang/lib/CodeGen/CMakeLists.txt +++ b/clang/lib/CodeGen/CMakeLists.txt @@ -14,6 +14,7 @@ set(LLVM_LINK_COMPONENTS FrontendOpenMP FrontendOffloading HIPStdPar + HLSL IPO IRPrinter IRReader diff --git a/llvm/lib/Target/DirectX/DXILFinalizeLinkage.h b/llvm/include/llvm/Transforms/HLSL/DXILFinalizeLinkage.h similarity index 100% rename from llvm/lib/Target/DirectX/DXILFinalizeLinkage.h rename to llvm/include/llvm/Transforms/HLSL/DXILFinalizeLinkage.h diff --git a/llvm/lib/Target/DirectX/CMakeLists.txt b/llvm/lib/Target/DirectX/CMakeLists.txt index 26315db891b57..b7d2034fbdadb 100644 --- a/llvm/lib/Target/DirectX/CMakeLists.txt +++ b/llvm/lib/Target/DirectX/CMakeLists.txt @@ -21,7 +21,6 @@ add_llvm_target(DirectXCodeGen DirectXTargetTransformInfo.cpp DXContainerGlobals.cpp DXILDataScalarization.cpp - DXILFinalizeLinkage.cpp DXILFlattenArrays.cpp DXILIntrinsicExpansion.cpp DXILOpBuilder.cpp diff --git a/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp b/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp index ecb1bf775f857..c969abb43f858 100644 --- a/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp +++ b/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp @@ -61,7 +61,6 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeDirectXTarget() { initializeDXILTranslateMetadataLegacyPass(*PR); initializeDXILResourceMDWrapperPass(*PR); initializeShaderFlagsAnalysisWrapperPass(*PR); - initializeDXILFinalizeLinkageLegacyPass(*PR); } class DXILTargetObjectFile : public TargetLoweringObjectFile { @@ -91,7 +90,6 @@ class DirectXPassConfig : public TargetPassConfig { FunctionPass *createTargetRegisterAllocator(bool) override { return nullptr; } void addCodeGenPrepare() override { - addPass(createDXILFinalizeLinkageLegacyPass()); addPass(createDXILIntrinsicExpansionLegacyPass()); addPass(createDXILDataScalarizationLegacyPass()); addPass(createDXILFlattenArraysLegacyPass()); diff --git a/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp b/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp index 098c7a6fba50e..026384a6e71c8 100644 --- a/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "SPIRVTargetMachine.h" +#include "../DirectX/DirectX.h" #include "SPIRV.h" #include "SPIRVCallLowering.h" #include "SPIRVGlobalRegistry.h" @@ -224,6 +225,7 @@ void SPIRVPassConfig::addPreLegalizeMachineIR() { // Use the default legalizer. bool SPIRVPassConfig::addLegalizeMachineIR() { + addPass(new Legalizer()); addPass(createSPIRVPostLegalizerPass()); return false; diff --git a/llvm/lib/Transforms/CMakeLists.txt b/llvm/lib/Transforms/CMakeLists.txt index 7046f2f4b1d2c..e3c13a19f6de1 100644 --- a/llvm/lib/Transforms/CMakeLists.txt +++ b/llvm/lib/Transforms/CMakeLists.txt @@ -9,3 +9,4 @@ add_subdirectory(ObjCARC) add_subdirectory(Coroutines) add_subdirectory(CFGuard) add_subdirectory(HipStdPar) +add_subdirectory(HLSL) diff --git a/llvm/lib/Transforms/HLSL/CMakeLists.txt b/llvm/lib/Transforms/HLSL/CMakeLists.txt new file mode 100644 index 0000000000000..886a1737ab495 --- /dev/null +++ b/llvm/lib/Transforms/HLSL/CMakeLists.txt @@ -0,0 +1,18 @@ +add_llvm_component_library(LLVMHlsl + DXILFinalizeLinkage.cpp + + ADDITIONAL_HEADER_DIRS + ${LLVM_MAIN_INCLUDE_DIR}/llvm/Transforms/HLSL + + DEPENDS + intrinsics_gen + LLVMAnalysis + + COMPONENT_NAME + HLSL + + LINK_COMPONENTS + Analysis + Core + Support + TransformUtils) diff --git a/llvm/lib/Target/DirectX/DXILFinalizeLinkage.cpp b/llvm/lib/Transforms/HLSL/DXILFinalizeLinkage.cpp similarity index 72% rename from llvm/lib/Target/DirectX/DXILFinalizeLinkage.cpp rename to llvm/lib/Transforms/HLSL/DXILFinalizeLinkage.cpp index 91ac758150fb4..2ac24f6a26b37 100644 --- a/llvm/lib/Target/DirectX/DXILFinalizeLinkage.cpp +++ b/llvm/lib/Transforms/HLSL/DXILFinalizeLinkage.cpp @@ -6,8 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "DXILFinalizeLinkage.h" -#include "DirectX.h" +#include "llvm/Transforms/HLSL/DXILFinalizeLinkage.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalValue.h" #include "llvm/IR/Metadata.h" @@ -44,19 +43,4 @@ PreservedAnalyses DXILFinalizeLinkage::run(Module &M, if (finalizeLinkage(M)) return PreservedAnalyses::none(); return PreservedAnalyses::all(); -} - -bool DXILFinalizeLinkageLegacy::runOnModule(Module &M) { - return finalizeLinkage(M); -} - -char DXILFinalizeLinkageLegacy::ID = 0; - -INITIALIZE_PASS_BEGIN(DXILFinalizeLinkageLegacy, DEBUG_TYPE, - "DXIL Finalize Linkage", false, false) -INITIALIZE_PASS_END(DXILFinalizeLinkageLegacy, DEBUG_TYPE, - "DXIL Finalize Linkage", false, false) - -ModulePass *llvm::createDXILFinalizeLinkageLegacyPass() { - return new DXILFinalizeLinkageLegacy(); -} +} \ No newline at end of file From 7f971fa1e89956441e73949a786d262bff8ddabe Mon Sep 17 00:00:00 2001 From: Steven Perron Date: Thu, 16 Jan 2025 11:48:38 -0500 Subject: [PATCH 5/6] Modify FinalizeLinkage to chagen global variables. --- llvm/lib/Transforms/HLSL/DXILFinalizeLinkage.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Transforms/HLSL/DXILFinalizeLinkage.cpp b/llvm/lib/Transforms/HLSL/DXILFinalizeLinkage.cpp index 2ac24f6a26b37..c0dc4a6aa79c5 100644 --- a/llvm/lib/Transforms/HLSL/DXILFinalizeLinkage.cpp +++ b/llvm/lib/Transforms/HLSL/DXILFinalizeLinkage.cpp @@ -9,7 +9,6 @@ #include "llvm/Transforms/HLSL/DXILFinalizeLinkage.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalValue.h" -#include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" #define DEBUG_TYPE "dxil-finalize-linkage" @@ -19,6 +18,12 @@ using namespace llvm; static bool finalizeLinkage(Module &M) { SmallPtrSet Funcs; + for(auto &Var : M.globals()) { + if (Var.getLinkage() == GlobalValue::ExternalLinkage) { + Var.setLinkage(GlobalValue::InternalLinkage); + } + } + // Collect non-entry and non-exported functions to set to internal linkage. for (Function &EF : M.functions()) { if (EF.isIntrinsic()) From 64265ebd451b09a0703d360aa8dbe822382eda60 Mon Sep 17 00:00:00 2001 From: Steven Perron Date: Thu, 16 Jan 2025 14:06:41 -0500 Subject: [PATCH 6/6] Add global opt pass to remove dead store to global. --- clang/lib/CodeGen/BackendUtil.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index b43689f3c0f13..23445ebc369fe 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -83,6 +83,7 @@ #include "llvm/Transforms/ObjCARC.h" #include "llvm/Transforms/Scalar/EarlyCSE.h" #include "llvm/Transforms/Scalar/GVN.h" +#include "llvm/Transforms/IPO/GlobalOpt.h" #include "llvm/Transforms/Scalar/JumpThreading.h" #include "llvm/Transforms/Utils/Debugify.h" #include "llvm/Transforms/Utils/ModuleUtils.h" @@ -1168,6 +1169,7 @@ void EmitAssemblyHelper::RunOptimizationPipeline( if (LangOpts.HLSL) { // HLSL legalization passes MPM.addPass(DXILFinalizeLinkage()); + MPM.addPass(GlobalOptPass()); } // Now that we have all of the passes ready, run them.