LLVM 20.0.0git
AMDGPUUnifyMetadata.cpp
Go to the documentation of this file.
1//===- AMDGPUUnifyMetadata.cpp - Unify OpenCL metadata --------------------===//
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// \file
10// This pass that unifies multiple OpenCL metadata due to linking.
11//
12//===----------------------------------------------------------------------===//
13
14#include "AMDGPU.h"
15#include "llvm/IR/Constants.h"
16#include "llvm/IR/Module.h"
17#include "llvm/IR/PassManager.h"
18#include "llvm/Pass.h"
19
20using namespace llvm;
21
22namespace {
23
24 namespace kOCLMD {
25
26 const char SpirVer[] = "opencl.spir.version";
27 const char OCLVer[] = "opencl.ocl.version";
28 const char UsedExt[] = "opencl.used.extensions";
29 const char UsedOptCoreFeat[] = "opencl.used.optional.core.features";
30 const char CompilerOptions[] = "opencl.compiler.options";
31 const char LLVMIdent[] = "llvm.ident";
32
33 } // end namespace kOCLMD
34
35 /// Unify multiple OpenCL metadata due to linking.
36 class AMDGPUUnifyMetadata : public ModulePass {
37 public:
38 static char ID;
39
40 explicit AMDGPUUnifyMetadata() : ModulePass(ID) {}
41
42 private:
43 bool runOnModule(Module &M) override;
44 };
45
46 /// Unify version metadata.
47 /// \return true if changes are made.
48 /// Assume the named metadata has operands each of which is a pair of
49 /// integer constant, e.g.
50 /// !Name = {!n1, !n2}
51 /// !n1 = {i32 1, i32 2}
52 /// !n2 = {i32 2, i32 0}
53 /// Keep the largest version as the sole operand if PickFirst is false.
54 /// Otherwise pick it from the first value, representing kernel module.
55 bool unifyVersionMD(Module &M, StringRef Name, bool PickFirst) {
56 auto NamedMD = M.getNamedMetadata(Name);
57 if (!NamedMD || NamedMD->getNumOperands() <= 1)
58 return false;
59 MDNode *MaxMD = nullptr;
60 auto MaxVer = 0U;
61 for (auto *VersionMD : NamedMD->operands()) {
62 assert(VersionMD->getNumOperands() == 2);
63 auto CMajor = mdconst::extract<ConstantInt>(VersionMD->getOperand(0));
64 auto VersionMajor = CMajor->getZExtValue();
65 auto CMinor = mdconst::extract<ConstantInt>(VersionMD->getOperand(1));
66 auto VersionMinor = CMinor->getZExtValue();
67 auto Ver = (VersionMajor * 100) + (VersionMinor * 10);
68 if (Ver > MaxVer) {
69 MaxVer = Ver;
70 MaxMD = VersionMD;
71 }
72 if (PickFirst)
73 break;
74 }
75 NamedMD->eraseFromParent();
76 NamedMD = M.getOrInsertNamedMetadata(Name);
77 NamedMD->addOperand(MaxMD);
78 return true;
79 }
80
81 /// Unify version metadata.
82 /// \return true if changes are made.
83 /// Assume the named metadata has operands each of which is a list e.g.
84 /// !Name = {!n1, !n2}
85 /// !n1 = !{!"cl_khr_fp16", {!"cl_khr_fp64"}}
86 /// !n2 = !{!"cl_khr_image"}
87 /// Combine it into a single list with unique operands.
88 bool unifyExtensionMD(Module &M, StringRef Name) {
89 auto NamedMD = M.getNamedMetadata(Name);
90 if (!NamedMD || NamedMD->getNumOperands() == 1)
91 return false;
92
94 for (auto *MD : NamedMD->operands())
95 for (const auto &Op : MD->operands())
96 if (!llvm::is_contained(All, Op.get()))
97 All.push_back(Op.get());
98
99 NamedMD->eraseFromParent();
100 NamedMD = M.getOrInsertNamedMetadata(Name);
101 for (const auto &MD : All)
102 NamedMD->addOperand(MDNode::get(M.getContext(), MD));
103
104 return true;
105 }
106
107 bool unifyMetadataImpl(Module &M) {
108 const char *Vers[] = {kOCLMD::SpirVer, kOCLMD::OCLVer};
109 const char *Exts[] = {kOCLMD::UsedExt, kOCLMD::UsedOptCoreFeat,
110 kOCLMD::CompilerOptions, kOCLMD::LLVMIdent};
111
112 bool Changed = false;
113
114 for (auto &I : Vers)
115 Changed |= unifyVersionMD(M, I, true);
116
117 for (auto &I : Exts)
118 Changed |= unifyExtensionMD(M, I);
119
120 return Changed;
121 }
122
123 } // end anonymous namespace
124
125 char AMDGPUUnifyMetadata::ID = 0;
126
127 char &llvm::AMDGPUUnifyMetadataID = AMDGPUUnifyMetadata::ID;
128
129 INITIALIZE_PASS(AMDGPUUnifyMetadata, "amdgpu-unify-metadata",
130 "Unify multiple OpenCL metadata due to linking", false, false)
131
133 return new AMDGPUUnifyMetadata();
134 }
135
136 bool AMDGPUUnifyMetadata::runOnModule(Module &M) {
137 return unifyMetadataImpl(M);
138 }
139
142 return unifyMetadataImpl(M) ? PreservedAnalyses::none()
144 }
This file contains the declarations for the subclasses of Constant, which represent the different fla...
std::string Name
#define I(x, y, z)
Definition: MD5.cpp:58
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A container for analyses that lazily runs them and caches their results.
Definition: PassManager.h:253
This class represents an Operation in the Expression.
Metadata node.
Definition: Metadata.h:1069
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition: Metadata.h:1542
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition: Pass.h:251
virtual bool runOnModule(Module &M)=0
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
A set of analyses that are preserved following a run of a transformation pass.
Definition: Analysis.h:111
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition: Analysis.h:114
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: Analysis.h:117
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1210
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
constexpr uint32_t VersionMinor
HSA metadata minor version.
constexpr uint32_t VersionMajor
HSA metadata major version.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
ModulePass * createAMDGPUUnifyMetadataPass()
char & AMDGPUUnifyMetadataID
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition: STLExtras.h:1879
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)