LLVM  8.0.1
AMDGPUUnifyMetadata.cpp
Go to the documentation of this file.
1 //===- AMDGPUUnifyMetadata.cpp - Unify OpenCL metadata --------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // \file
11 // This pass that unifies multiple OpenCL metadata due to linking.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "AMDGPU.h"
16 #include "llvm/ADT/SmallVector.h"
17 #include "llvm/ADT/StringRef.h"
18 #include "llvm/IR/Constants.h"
19 #include "llvm/IR/Metadata.h"
20 #include "llvm/IR/Module.h"
21 #include "llvm/Pass.h"
22 #include <algorithm>
23 #include <cassert>
24 
25 using namespace llvm;
26 
27 namespace {
28 
29  namespace kOCLMD {
30 
31  const char SpirVer[] = "opencl.spir.version";
32  const char OCLVer[] = "opencl.ocl.version";
33  const char UsedExt[] = "opencl.used.extensions";
34  const char UsedOptCoreFeat[] = "opencl.used.optional.core.features";
35  const char CompilerOptions[] = "opencl.compiler.options";
36  const char LLVMIdent[] = "llvm.ident";
37 
38  } // end namespace kOCLMD
39 
40  /// Unify multiple OpenCL metadata due to linking.
41  class AMDGPUUnifyMetadata : public ModulePass {
42  public:
43  static char ID;
44 
45  explicit AMDGPUUnifyMetadata() : ModulePass(ID) {}
46 
47  private:
48  bool runOnModule(Module &M) override;
49 
50  /// Unify version metadata.
51  /// \return true if changes are made.
52  /// Assume the named metadata has operands each of which is a pair of
53  /// integer constant, e.g.
54  /// !Name = {!n1, !n2}
55  /// !n1 = {i32 1, i32 2}
56  /// !n2 = {i32 2, i32 0}
57  /// Keep the largest version as the sole operand if PickFirst is false.
58  /// Otherwise pick it from the first value, representing kernel module.
59  bool unifyVersionMD(Module &M, StringRef Name, bool PickFirst) {
60  auto NamedMD = M.getNamedMetadata(Name);
61  if (!NamedMD || NamedMD->getNumOperands() <= 1)
62  return false;
63  MDNode *MaxMD = nullptr;
64  auto MaxVer = 0U;
65  for (const auto &VersionMD : NamedMD->operands()) {
66  assert(VersionMD->getNumOperands() == 2);
67  auto CMajor = mdconst::extract<ConstantInt>(VersionMD->getOperand(0));
68  auto VersionMajor = CMajor->getZExtValue();
69  auto CMinor = mdconst::extract<ConstantInt>(VersionMD->getOperand(1));
70  auto VersionMinor = CMinor->getZExtValue();
71  auto Ver = (VersionMajor * 100) + (VersionMinor * 10);
72  if (Ver > MaxVer) {
73  MaxVer = Ver;
74  MaxMD = VersionMD;
75  }
76  if (PickFirst)
77  break;
78  }
79  NamedMD->eraseFromParent();
80  NamedMD = M.getOrInsertNamedMetadata(Name);
81  NamedMD->addOperand(MaxMD);
82  return true;
83  }
84 
85  /// Unify version metadata.
86  /// \return true if changes are made.
87  /// Assume the named metadata has operands each of which is a list e.g.
88  /// !Name = {!n1, !n2}
89  /// !n1 = !{!"cl_khr_fp16", {!"cl_khr_fp64"}}
90  /// !n2 = !{!"cl_khr_image"}
91  /// Combine it into a single list with unique operands.
92  bool unifyExtensionMD(Module &M, StringRef Name) {
93  auto NamedMD = M.getNamedMetadata(Name);
94  if (!NamedMD || NamedMD->getNumOperands() == 1)
95  return false;
96 
98  for (const auto &MD : NamedMD->operands())
99  for (const auto &Op : MD->operands())
100  if (std::find(All.begin(), All.end(), Op.get()) == All.end())
101  All.push_back(Op.get());
102 
103  NamedMD->eraseFromParent();
104  NamedMD = M.getOrInsertNamedMetadata(Name);
105  for (const auto &MD : All)
106  NamedMD->addOperand(MDNode::get(M.getContext(), MD));
107 
108  return true;
109  }
110 };
111 
112 } // end anonymous namespace
113 
114 char AMDGPUUnifyMetadata::ID = 0;
115 
117 
118 INITIALIZE_PASS(AMDGPUUnifyMetadata, "amdgpu-unify-metadata",
119  "Unify multiple OpenCL metadata due to linking",
120  false, false)
121 
123  return new AMDGPUUnifyMetadata();
124 }
125 
126 bool AMDGPUUnifyMetadata::runOnModule(Module &M) {
127  const char* Vers[] = {
128  kOCLMD::SpirVer,
129  kOCLMD::OCLVer
130  };
131  const char* Exts[] = {
132  kOCLMD::UsedExt,
133  kOCLMD::UsedOptCoreFeat,
134  kOCLMD::CompilerOptions,
135  kOCLMD::LLVMIdent
136  };
137 
138  bool Changed = false;
139 
140  for (auto &I : Vers)
141  Changed |= unifyVersionMD(M, I, true);
142 
143  for (auto &I : Exts)
144  Changed |= unifyExtensionMD(M, I);
145 
146  return Changed;
147 }
This class represents lattice values for constants.
Definition: AllocatorList.h:24
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:65
void addOperand(MDNode *M)
Definition: Metadata.cpp:1087
This file contains the declarations for metadata subclasses.
NamedMDNode * getOrInsertNamedMetadata(StringRef Name)
Return the named MDNode in the module with the specified name.
Definition: Module.cpp:261
Metadata node.
Definition: Metadata.h:864
amdgpu Simplify well known AMD library false Value Value const Twine & Name
LLVMContext & getContext() const
Get the global data context.
Definition: Module.h:244
char & AMDGPUUnifyMetadataID
NamedMDNode * getNamedMetadata(const Twine &Name) const
Return the first NamedMDNode in the module with the specified name.
Definition: Module.cpp:252
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata *> MDs)
Definition: Metadata.h:1166
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
Definition: SmallVector.h:129
This file contains the declarations for the subclasses of Constant, which represent the different fla...
auto find(R &&Range, const T &Val) -> decltype(adl_begin(Range))
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:1207
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:847
Module.h This file contains the declarations for the Module class.
constexpr uint32_t VersionMinor
HSA metadata minor version.
ModulePass * createAMDGPUUnifyMetadataPass()
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
Definition: SmallVector.h:133
#define I(x, y, z)
Definition: MD5.cpp:58
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition: Pass.h:225
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
INITIALIZE_PASS(AMDGPUUnifyMetadata, "amdgpu-unify-metadata", "Unify multiple OpenCL metadata due to linking", false, false) ModulePass *llvm
constexpr uint32_t VersionMajor
HSA metadata major version.