LLVM  4.0.0
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 // \brief This pass that unifies multiple OpenCL metadata due to linking.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "AMDGPU.h"
16 #include "llvm/IR/Constants.h"
17 #include "llvm/IR/Module.h"
18 #include "llvm/Pass.h"
19 
20 using namespace llvm;
21 
22 namespace {
23  namespace kOCLMD {
24  const char SpirVer[] = "opencl.spir.version";
25  const char OCLVer[] = "opencl.ocl.version";
26  const char UsedExt[] = "opencl.used.extensions";
27  const char UsedOptCoreFeat[] = "opencl.used.optional.core.features";
28  const char CompilerOptions[] = "opencl.compiler.options";
29  const char LLVMIdent[] = "llvm.ident";
30  }
31 
32  /// \brief Unify multiple OpenCL metadata due to linking.
33  class AMDGPUUnifyMetadata : public FunctionPass {
34  public:
35  static char ID;
36  explicit AMDGPUUnifyMetadata() : FunctionPass(ID) {};
37 
38  private:
39  // This should really be a module pass but we have to run it as early
40  // as possible, so given function passes are executed first and
41  // TargetMachine::addEarlyAsPossiblePasses() expects only function passes
42  // it has to be a function pass.
43  virtual bool runOnModule(Module &M);
44 
45  // \todo: Convert to a module pass.
46  virtual bool runOnFunction(Function &F);
47 
48  /// \brief Unify version metadata.
49  /// \return true if changes are made.
50  /// Assume the named metadata has operands each of which is a pair of
51  /// integer constant, e.g.
52  /// !Name = {!n1, !n2}
53  /// !n1 = {i32 1, i32 2}
54  /// !n2 = {i32 2, i32 0}
55  /// Keep the largest version as the sole operand if PickFirst is false.
56  /// Otherwise pick it from the first value, representing kernel module.
57  bool unifyVersionMD(Module &M, StringRef Name, bool PickFirst) {
58  auto NamedMD = M.getNamedMetadata(Name);
59  if (!NamedMD || NamedMD->getNumOperands() <= 1)
60  return false;
61  MDNode *MaxMD = nullptr;
62  auto MaxVer = 0U;
63  for (const auto &VersionMD : NamedMD->operands()) {
64  assert(VersionMD->getNumOperands() == 2);
65  auto CMajor = mdconst::extract<ConstantInt>(VersionMD->getOperand(0));
66  auto VersionMajor = CMajor->getZExtValue();
67  auto CMinor = mdconst::extract<ConstantInt>(VersionMD->getOperand(1));
68  auto VersionMinor = CMinor->getZExtValue();
69  auto Ver = (VersionMajor * 100) + (VersionMinor * 10);
70  if (Ver > MaxVer) {
71  MaxVer = Ver;
72  MaxMD = VersionMD;
73  }
74  if (PickFirst)
75  break;
76  }
77  NamedMD->eraseFromParent();
78  NamedMD = M.getOrInsertNamedMetadata(Name);
79  NamedMD->addOperand(MaxMD);
80  return true;
81  }
82 
83  /// \brief Unify version metadata.
84  /// \return true if changes are made.
85  /// Assume the named metadata has operands each of which is a list e.g.
86  /// !Name = {!n1, !n2}
87  /// !n1 = !{!"cl_khr_fp16", {!"cl_khr_fp64"}}
88  /// !n2 = !{!"cl_khr_image"}
89  /// Combine it into a single list with unique operands.
90  bool unifyExtensionMD(Module &M, StringRef Name) {
91  auto NamedMD = M.getNamedMetadata(Name);
92  if (!NamedMD || NamedMD->getNumOperands() == 1)
93  return false;
94 
96  for (const auto &MD : NamedMD->operands())
97  for (const auto &Op : MD->operands())
98  if (std::find(All.begin(), All.end(), Op.get()) == All.end())
99  All.push_back(Op.get());
100 
101  NamedMD->eraseFromParent();
102  NamedMD = M.getOrInsertNamedMetadata(Name);
103  for (const auto &MD : All)
104  NamedMD->addOperand(MDNode::get(M.getContext(), MD));
105 
106  return true;
107  }
108 };
109 
110 } // end anonymous namespace
111 
112 char AMDGPUUnifyMetadata::ID = 0;
113 
115 
116 INITIALIZE_PASS(AMDGPUUnifyMetadata, "amdgpu-unify-metadata",
117  "Unify multiple OpenCL metadata due to linking",
118  false, false)
119 
121  return new AMDGPUUnifyMetadata();
122 }
123 
124 bool AMDGPUUnifyMetadata::runOnModule(Module &M) {
125  const char* Vers[] = {
126  kOCLMD::SpirVer,
127  kOCLMD::OCLVer
128  };
129  const char* Exts[] = {
130  kOCLMD::UsedExt,
131  kOCLMD::UsedOptCoreFeat,
132  kOCLMD::CompilerOptions,
133  kOCLMD::LLVMIdent
134  };
135 
136  bool Changed = false;
137 
138  for (auto &I : Vers)
139  Changed |= unifyVersionMD(M, I, true);
140 
141  for (auto &I : Exts)
142  Changed |= unifyExtensionMD(M, I);
143 
144  return Changed;
145 }
146 
147 bool AMDGPUUnifyMetadata::runOnFunction(Function &F) {
148  return runOnModule(*F.getParent());
149 }
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:52
void addOperand(MDNode *M)
Definition: Metadata.cpp:1048
NamedMDNode * getOrInsertNamedMetadata(StringRef Name)
Return the named MDNode in the module with the specified name.
Definition: Module.cpp:274
Metadata node.
Definition: Metadata.h:830
char & AMDGPUUnifyMetadataID
#define F(x, y, z)
Definition: MD5.cpp:51
INITIALIZE_PASS(AMDGPUUnifyMetadata,"amdgpu-unify-metadata","Unify multiple OpenCL metadata due to linking", false, false) FunctionPass *llvm
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
Definition: SmallVector.h:115
This file contains the declarations for the subclasses of Constant, which represent the different fla...
FunctionPass * createAMDGPUUnifyMetadataPass()
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:298
auto find(R &&Range, const T &Val) -> decltype(std::begin(Range))
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:757
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:843
Module.h This file contains the declarations for the Module class.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition: Metadata.h:1132
NamedMDNode * getNamedMetadata(const Twine &Name) const
Return the first NamedMDNode in the module with the specified name.
Definition: Module.cpp:265
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
Definition: SmallVector.h:119
#define I(x, y, z)
Definition: MD5.cpp:54
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:537
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:47
LLVMContext & getContext() const
Get the global data context.
Definition: Module.h:222