llvm-project/llvm/lib/Analysis/DXILMetadataAnalysis.cpp
Nikita Popov 979c275097
[IR] Store Triple in Module (NFC) (#129868)
The module currently stores the target triple as a string. This means
that any code that wants to actually use the triple first has to
instantiate a Triple, which is somewhat expensive. The change in #121652
caused a moderate compile-time regression due to this. While it would be
easy enough to work around, I think that architecturally, it makes more
sense to store the parsed Triple in the module, so that it can always be
directly queried.

For this change, I've opted not to add any magic conversions between
std::string and Triple for backwards-compatibilty purses, and instead
write out needed Triple()s or str()s explicitly. This is because I think
a decent number of them should be changed to work on Triple as well, to
avoid unnecessary conversions back and forth.

The only interesting part in this patch is that the default triple is
Triple("") instead of Triple() to preserve existing behavior. The former
defaults to using the ELF object format instead of unknown object
format. We should fix that as well.
2025-03-06 10:27:47 +01:00

148 lines
5.4 KiB
C++

//=- DXILMetadataAnalysis.cpp - Representation of Module metadata -*- 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
//
//===----------------------------------------------------------------------===//
#include "llvm/Analysis/DXILMetadataAnalysis.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/InitializePasses.h"
#include "llvm/Support/ErrorHandling.h"
#define DEBUG_TYPE "dxil-metadata-analysis"
using namespace llvm;
using namespace dxil;
static ModuleMetadataInfo collectMetadataInfo(Module &M) {
ModuleMetadataInfo MMDAI;
const Triple &TT = M.getTargetTriple();
MMDAI.DXILVersion = TT.getDXILVersion();
MMDAI.ShaderModelVersion = TT.getOSVersion();
MMDAI.ShaderProfile = TT.getEnvironment();
NamedMDNode *ValidatorVerNode = M.getNamedMetadata("dx.valver");
if (ValidatorVerNode) {
auto *ValVerMD = cast<MDNode>(ValidatorVerNode->getOperand(0));
auto *MajorMD = mdconst::extract<ConstantInt>(ValVerMD->getOperand(0));
auto *MinorMD = mdconst::extract<ConstantInt>(ValVerMD->getOperand(1));
MMDAI.ValidatorVersion =
VersionTuple(MajorMD->getZExtValue(), MinorMD->getZExtValue());
}
// For all HLSL Shader functions
for (auto &F : M.functions()) {
if (!F.hasFnAttribute("hlsl.shader"))
continue;
EntryProperties EFP(&F);
// Get "hlsl.shader" attribute
Attribute EntryAttr = F.getFnAttribute("hlsl.shader");
assert(EntryAttr.isValid() &&
"Invalid value specified for HLSL function attribute hlsl.shader");
StringRef EntryProfile = EntryAttr.getValueAsString();
Triple T("", "", "", EntryProfile);
EFP.ShaderStage = T.getEnvironment();
// Get numthreads attribute value, if one exists
StringRef NumThreadsStr =
F.getFnAttribute("hlsl.numthreads").getValueAsString();
if (!NumThreadsStr.empty()) {
SmallVector<StringRef> NumThreadsVec;
NumThreadsStr.split(NumThreadsVec, ',');
assert(NumThreadsVec.size() == 3 && "Invalid numthreads specified");
// Read in the three component values of numthreads
[[maybe_unused]] bool Success =
llvm::to_integer(NumThreadsVec[0], EFP.NumThreadsX, 10);
assert(Success && "Failed to parse X component of numthreads");
Success = llvm::to_integer(NumThreadsVec[1], EFP.NumThreadsY, 10);
assert(Success && "Failed to parse Y component of numthreads");
Success = llvm::to_integer(NumThreadsVec[2], EFP.NumThreadsZ, 10);
assert(Success && "Failed to parse Z component of numthreads");
}
MMDAI.EntryPropertyVec.push_back(EFP);
}
return MMDAI;
}
void ModuleMetadataInfo::print(raw_ostream &OS) const {
OS << "Shader Model Version : " << ShaderModelVersion.getAsString() << "\n";
OS << "DXIL Version : " << DXILVersion.getAsString() << "\n";
OS << "Target Shader Stage : "
<< Triple::getEnvironmentTypeName(ShaderProfile) << "\n";
OS << "Validator Version : " << ValidatorVersion.getAsString() << "\n";
for (const auto &EP : EntryPropertyVec) {
OS << " " << EP.Entry->getName() << "\n";
OS << " Function Shader Stage : "
<< Triple::getEnvironmentTypeName(EP.ShaderStage) << "\n";
OS << " NumThreads: " << EP.NumThreadsX << "," << EP.NumThreadsY << ","
<< EP.NumThreadsZ << "\n";
}
}
//===----------------------------------------------------------------------===//
// DXILMetadataAnalysis and DXILMetadataAnalysisPrinterPass
// Provide an explicit template instantiation for the static ID.
AnalysisKey DXILMetadataAnalysis::Key;
llvm::dxil::ModuleMetadataInfo
DXILMetadataAnalysis::run(Module &M, ModuleAnalysisManager &AM) {
return collectMetadataInfo(M);
}
PreservedAnalyses
DXILMetadataAnalysisPrinterPass::run(Module &M, ModuleAnalysisManager &AM) {
llvm::dxil::ModuleMetadataInfo &Data = AM.getResult<DXILMetadataAnalysis>(M);
Data.print(OS);
return PreservedAnalyses::all();
}
//===----------------------------------------------------------------------===//
// DXILMetadataAnalysisWrapperPass
DXILMetadataAnalysisWrapperPass::DXILMetadataAnalysisWrapperPass()
: ModulePass(ID) {
initializeDXILMetadataAnalysisWrapperPassPass(
*PassRegistry::getPassRegistry());
}
DXILMetadataAnalysisWrapperPass::~DXILMetadataAnalysisWrapperPass() = default;
void DXILMetadataAnalysisWrapperPass::getAnalysisUsage(
AnalysisUsage &AU) const {
AU.setPreservesAll();
}
bool DXILMetadataAnalysisWrapperPass::runOnModule(Module &M) {
MetadataInfo.reset(new ModuleMetadataInfo(collectMetadataInfo(M)));
return false;
}
void DXILMetadataAnalysisWrapperPass::releaseMemory() { MetadataInfo.reset(); }
void DXILMetadataAnalysisWrapperPass::print(raw_ostream &OS,
const Module *) const {
if (!MetadataInfo) {
OS << "No module metadata info has been built!\n";
return;
}
MetadataInfo->print(dbgs());
}
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD
void DXILMetadataAnalysisWrapperPass::dump() const { print(dbgs(), nullptr); }
#endif
INITIALIZE_PASS(DXILMetadataAnalysisWrapperPass, "dxil-metadata-analysis",
"DXIL Module Metadata analysis", false, true)
char DXILMetadataAnalysisWrapperPass::ID = 0;