1//===- SPIRVFinalizeShaderLinkage.cpp - Finalize shader linkage ----------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Shader-only analogue of DXILFinalizeLinkage: internalizes non-entry,
10// non-exported HLSL helper functions and erases the resulting dead ones.
11//
12//===----------------------------------------------------------------------===//
13
14#include "SPIRV.h"
15#include "SPIRVSubtarget.h"
16#include "SPIRVTargetMachine.h"
17#include "SPIRVUtils.h"
18#include "llvm/ADT/STLExtras.h"
19#include "llvm/IR/Function.h"
20#include "llvm/IR/GlobalValue.h"
21#include "llvm/IR/Module.h"
22#include "llvm/Pass.h"
23
24#define DEBUG_TYPE "spirv-finalize-shader-linkage"
25
26using namespace llvm;
27
28namespace {
29
30bool finalizeShaderLinkage(const SPIRVTargetMachine &TM, Module &M) {
31 // This pass only applies to shader targets because shaders don't have
32 // linkers.
33 if (!TM.getSubtargetImpl()->isShader())
34 return false;
35
36 bool Changed = false;
37
38 for (Function &F : M) {
39 if (F.isIntrinsic() || F.isDeclaration() || isEntryPoint(F))
40 continue;
41 if (F.hasExternalLinkage() && !F.hasHiddenVisibility())
42 continue;
43 if (!F.hasLocalLinkage()) {
44 F.setLinkage(GlobalValue::InternalLinkage);
45 Changed = true;
46 }
47 }
48
49 // Erase dead helpers, iterating to a fixpoint for helper-calls-helper chains.
50 bool LocalChange = true;
51 while (LocalChange) {
52 LocalChange = false;
53 for (Function &F : make_early_inc_range(Range&: M))
54 if (F.isDefTriviallyDead()) {
55 F.eraseFromParent();
56 LocalChange = Changed = true;
57 }
58 }
59 return Changed;
60}
61
62class SPIRVFinalizeShaderLinkageLegacy : public ModulePass {
63public:
64 static char ID;
65 SPIRVFinalizeShaderLinkageLegacy(const SPIRVTargetMachine &TM)
66 : ModulePass(ID), TM(TM) {}
67 StringRef getPassName() const override {
68 return "SPIRV Finalize Shader Linkage";
69 }
70 bool runOnModule(Module &M) override { return finalizeShaderLinkage(TM, M); }
71
72private:
73 const SPIRVTargetMachine &TM;
74};
75
76} // namespace
77
78PreservedAnalyses
79SPIRVFinalizeShaderLinkagePass::run(Module &M, ModuleAnalysisManager &AM) {
80 return finalizeShaderLinkage(TM, M) ? PreservedAnalyses::none()
81 : PreservedAnalyses::all();
82}
83
84char SPIRVFinalizeShaderLinkageLegacy::ID = 0;
85
86INITIALIZE_PASS(SPIRVFinalizeShaderLinkageLegacy,
87 "spirv-finalize-shader-linkage",
88 "Finalize SPIR-V shader linkage", false, false)
89
90ModulePass *
91llvm::createSPIRVFinalizeShaderLinkagePass(const SPIRVTargetMachine &TM) {
92 return new SPIRVFinalizeShaderLinkageLegacy(TM);
93}
94