blob: 554d0f0e151d6de6191c6e0960451eea697291d7 [file] [edit]
//===- 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 "SPIRVFinalizeShaderLinkage.h"
#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 SPIRVFinalizeShaderLinkage::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);
}