LLVM  14.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 
20 using namespace llvm;
21 
22 namespace {
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 
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 
141  ModuleAnalysisManager &AM) {
142  return unifyMetadataImpl(M) ? PreservedAnalyses::none()
144  }
llvm::PreservedAnalyses
A set of analyses that are preserved following a run of a transformation pass.
Definition: PassManager.h:155
llvm
This file implements support for optimizing divisions by a constant.
Definition: AllocatorList.h:23
M
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
Definition: README.txt:252
llvm::ModulePass
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition: Pass.h:238
Pass.h
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1168
llvm::AMDGPUUnifyMetadataID
char & AMDGPUUnifyMetadataID
Definition: AMDGPUUnifyMetadata.cpp:127
kOCLMD
Definition: AMDGPUUnifyMetadata.cpp:24
llvm::PreservedAnalyses::none
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition: PassManager.h:158
Module.h
llvm::createAMDGPUUnifyMetadataPass
ModulePass * createAMDGPUUnifyMetadataPass()
llvm::MDNode::get
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition: Metadata.h:1233
llvm::AMDGPU::HSAMD::V3::VersionMajor
constexpr uint32_t VersionMajor
HSA metadata major version.
Definition: AMDGPUMetadata.h:454
llvm::AMDGPUUnifyMetadataPass::run
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
Definition: AMDGPUUnifyMetadata.cpp:140
Constants.h
llvm::AMDGPU::HSAMD::V3::VersionMinor
constexpr uint32_t VersionMinor
HSA metadata minor version.
Definition: AMDGPUMetadata.h:456
I
#define I(x, y, z)
Definition: MD5.cpp:59
llvm::is_contained
bool is_contained(R &&Range, const E &Element)
Wrapper function around std::find to detect if an element exists in a container.
Definition: STLExtras.h:1616
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:67
llvm::MDNode
Metadata node.
Definition: Metadata.h:906
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
AMDGPU.h
llvm::MachO::All
@ All
Definition: InterfaceFile.h:73
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:52
llvm::AMDGPU::SendMsg::Op
Op
Definition: SIDefines.h:324
llvm::PreservedAnalyses::all
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: PassManager.h:161
PassManager.h
llvm::AnalysisManager
A container for analyses that lazily runs them and caches their results.
Definition: InstructionSimplify.h:44
INITIALIZE_PASS
INITIALIZE_PASS(AMDGPUUnifyMetadata, "amdgpu-unify-metadata", "Unify multiple OpenCL metadata due to linking", false, false) ModulePass *llvm
Definition: AMDGPUUnifyMetadata.cpp:129
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:37