| //===- SPIRVFinalizeShaderLinkage.cpp - Finalize shader linkage ----------===// | |
| // | |
| // 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 | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // Shader-only analogue of DXILFinalizeLinkage: internalizes non-entry, | |
| // non-exported HLSL helper functions and erases the resulting dead ones. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "SPIRV.h" | |
| #include "SPIRVSubtarget.h" | |
| #include "SPIRVTargetMachine.h" | |
| #include "SPIRVUtils.h" | |
| #include "llvm/ADT/STLExtras.h" | |
| #include "llvm/IR/Function.h" | |
| #include "llvm/IR/GlobalValue.h" | |
| #include "llvm/IR/Module.h" | |
| #include "llvm/Pass.h" | |
| #define DEBUG_TYPE "spirv-finalize-shader-linkage" | |
| using namespace llvm; | |
| namespace { | |
| bool finalizeShaderLinkage(const SPIRVTargetMachine &TM, Module &M) { | |
| // This pass only applies to shader targets because shaders don't have | |
| // linkers. | |
| if (!TM.getSubtargetImpl()->isShader()) | |
| return false; | |
| bool Changed = false; | |
| for (Function &F : M) { | |
| if (F.isIntrinsic() || F.isDeclaration() || isEntryPoint(F)) | |
| continue; | |
| if (F.hasExternalLinkage() && !F.hasHiddenVisibility()) | |
| continue; | |
| if (!F.hasLocalLinkage()) { | |
| F.setLinkage(GlobalValue::InternalLinkage); | |
| Changed = true; | |
| } | |
| } | |
| // Erase dead helpers, iterating to a fixpoint for helper-calls-helper chains. | |
| bool LocalChange = true; | |
| while (LocalChange) { | |
| LocalChange = false; | |
| for (Function &F : make_early_inc_range(M)) | |
| if (F.isDefTriviallyDead()) { | |
| F.eraseFromParent(); | |
| LocalChange = Changed = true; | |
| } | |
| } | |
| return Changed; | |
| } | |
| class SPIRVFinalizeShaderLinkageLegacy : public ModulePass { | |
| public: | |
| static char ID; | |
| SPIRVFinalizeShaderLinkageLegacy(const SPIRVTargetMachine &TM) | |
| : ModulePass(ID), TM(TM) {} | |
| StringRef getPassName() const override { | |
| return "SPIRV Finalize Shader Linkage"; | |
| } | |
| bool runOnModule(Module &M) override { return finalizeShaderLinkage(TM, M); } | |
| private: | |
| const SPIRVTargetMachine &TM; | |
| }; | |
| } // namespace | |
| PreservedAnalyses | |
| SPIRVFinalizeShaderLinkagePass::run(Module &M, ModuleAnalysisManager &AM) { | |
| return finalizeShaderLinkage(TM, M) ? PreservedAnalyses::none() | |
| : PreservedAnalyses::all(); | |
| } | |
| char SPIRVFinalizeShaderLinkageLegacy::ID = 0; | |
| INITIALIZE_PASS(SPIRVFinalizeShaderLinkageLegacy, | |
| "spirv-finalize-shader-linkage", | |
| "Finalize SPIR-V shader linkage", false, false) | |
| ModulePass * | |
| llvm::createSPIRVFinalizeShaderLinkagePass(const SPIRVTargetMachine &TM) { | |
| return new SPIRVFinalizeShaderLinkageLegacy(TM); | |
| } |