LLVM  9.0.0svn
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/ADT/SmallVector.h"
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/IR/Constants.h"
18 #include "llvm/IR/Metadata.h"
19 #include "llvm/IR/Module.h"
20 #include "llvm/Pass.h"
21 #include <algorithm>
22 #include <cassert>
23 
24 using namespace llvm;
25 
26 namespace {
27 
28  namespace kOCLMD {
29 
30  const char SpirVer[] = "opencl.spir.version";
31  const char OCLVer[] = "opencl.ocl.version";
32  const char UsedExt[] = "opencl.used.extensions";
33  const char UsedOptCoreFeat[] = "opencl.used.optional.core.features";
34  const char CompilerOptions[] = "opencl.compiler.options";
35  const char LLVMIdent[] = "llvm.ident";
36 
37  } // end namespace kOCLMD
38 
39  /// Unify multiple OpenCL metadata due to linking.
40  class AMDGPUUnifyMetadata : public ModulePass {
41  public:
42  static char ID;
43 
44  explicit AMDGPUUnifyMetadata() : ModulePass(ID) {}
45 
46  private:
47  bool runOnModule(Module &M) override;
48 
49  /// Unify version metadata.
50  /// \return true if changes are made.
51  /// Assume the named metadata has operands each of which is a pair of
52  /// integer constant, e.g.
53  /// !Name = {!n1, !n2}
54  /// !n1 = {i32 1, i32 2}
55  /// !n2 = {i32 2, i32 0}
56  /// Keep the largest version as the sole operand if PickFirst is false.
57  /// Otherwise pick it from the first value, representing kernel module.
58  bool unifyVersionMD(Module &M, StringRef Name, bool PickFirst) {
59  auto NamedMD = M.getNamedMetadata(Name);
60  if (!NamedMD || NamedMD->getNumOperands() <= 1)
61  return false;
62  MDNode *MaxMD = nullptr;
63  auto MaxVer = 0U;
64  for (const auto &VersionMD : NamedMD->operands()) {
65  assert(VersionMD->getNumOperands() == 2);
66  auto CMajor = mdconst::extract<ConstantInt>(VersionMD->getOperand(0));
67  auto VersionMajor = CMajor->getZExtValue();
68  auto CMinor = mdconst::extract<ConstantInt>(VersionMD->getOperand(1));
69  auto VersionMinor = CMinor->getZExtValue();
70  auto Ver = (VersionMajor * 100) + (VersionMinor * 10);
71  if (Ver > MaxVer) {
72  MaxVer = Ver;
73  MaxMD = VersionMD;
74  }
75  if (PickFirst)
76  break;
77  }
78  NamedMD->eraseFromParent();
79  NamedMD = M.getOrInsertNamedMetadata(Name);
80  NamedMD->addOperand(MaxMD);
81  return true;
82  }
83 
84  /// Unify version metadata.
85  /// \return true if changes are made.
86  /// Assume the named metadata has operands each of which is a list e.g.
87  /// !Name = {!n1, !n2}
88  /// !n1 = !{!"cl_khr_fp16", {!"cl_khr_fp64"}}
89  /// !n2 = !{!"cl_khr_image"}
90  /// Combine it into a single list with unique operands.
91  bool unifyExtensionMD(Module &M, StringRef Name) {
92  auto NamedMD = M.getNamedMetadata(Name);
93  if (!NamedMD || NamedMD->getNumOperands() == 1)
94  return false;
95 
97  for (const auto &MD : NamedMD->operands())
98  for (const auto &Op : MD->operands())
99  if (std::find(All.begin(), All.end(), Op.get()) == All.end())
100  All.push_back(Op.get());
101 
102  NamedMD->eraseFromParent();
103  NamedMD = M.getOrInsertNamedMetadata(Name);
104  for (const auto &MD : All)
105  NamedMD->addOperand(MDNode::get(M.getContext(), MD));
106 
107  return true;
108  }
109 };
110 
111 } // end anonymous namespace
112 
113 char AMDGPUUnifyMetadata::ID = 0;
114 
116 
117 INITIALIZE_PASS(AMDGPUUnifyMetadata, "amdgpu-unify-metadata",
118  "Unify multiple OpenCL metadata due to linking",
119  false, false)
120 
122  return new AMDGPUUnifyMetadata();
123 }
124 
125 bool AMDGPUUnifyMetadata::runOnModule(Module &M) {
126  const char* Vers[] = {
127  kOCLMD::SpirVer,
128  kOCLMD::OCLVer
129  };
130  const char* Exts[] = {
131  kOCLMD::UsedExt,
132  kOCLMD::UsedOptCoreFeat,
133  kOCLMD::CompilerOptions,
134  kOCLMD::LLVMIdent
135  };
136 
137  bool Changed = false;
138 
139  for (auto &I : Vers)
140  Changed |= unifyVersionMD(M, I, true);
141 
142  for (auto &I : Exts)
143  Changed |= unifyExtensionMD(M, I);
144 
145  return Changed;
146 }
This class represents lattice values for constants.
Definition: AllocatorList.h:23
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:65
amdgpu Simplify well known AMD library false FunctionCallee Value const Twine & Name
void addOperand(MDNode *M)
Definition: Metadata.cpp:1086
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:259
Metadata node.
Definition: Metadata.h:863
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:250
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata *> MDs)
Definition: Metadata.h:1165
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:1213
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:837
Module.h This file contains the declarations for the Module class.
constexpr uint32_t VersionMinor
HSA metadata minor version.
ModulePass * createAMDGPUUnifyMetadataPass()
#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:224
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
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.