1 //===- AMDGPUUnifyMetadata.cpp - Unify OpenCL metadata --------------------===//
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
7 //===----------------------------------------------------------------------===//
10 // This pass that unifies multiple OpenCL metadata due to linking.
12 //===----------------------------------------------------------------------===//
15 #include "llvm/IR/Constants.h"
16 #include "llvm/IR/Module.h"
17 #include "llvm/IR/PassManager.h"
18 #include "llvm/Pass.h"
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";
33 } // end namespace kOCLMD
35 /// Unify multiple OpenCL metadata due to linking.
36 class AMDGPUUnifyMetadata
: public ModulePass
{
40 explicit AMDGPUUnifyMetadata() : ModulePass(ID
) {}
43 bool runOnModule(Module
&M
) override
;
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)
59 MDNode
*MaxMD
= nullptr;
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);
75 NamedMD
->eraseFromParent();
76 NamedMD
= M
.getOrInsertNamedMetadata(Name
);
77 NamedMD
->addOperand(MaxMD
);
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)
93 SmallVector
<Metadata
*, 4> All
;
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());
99 NamedMD
->eraseFromParent();
100 NamedMD
= M
.getOrInsertNamedMetadata(Name
);
101 for (const auto &MD
: All
)
102 NamedMD
->addOperand(MDNode::get(M
.getContext(), MD
));
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
};
112 bool Changed
= false;
115 Changed
|= unifyVersionMD(M
, I
, true);
118 Changed
|= unifyExtensionMD(M
, I
);
123 } // end anonymous namespace
125 char AMDGPUUnifyMetadata::ID
= 0;
127 char &llvm::AMDGPUUnifyMetadataID
= AMDGPUUnifyMetadata::ID
;
129 INITIALIZE_PASS(AMDGPUUnifyMetadata
, "amdgpu-unify-metadata",
130 "Unify multiple OpenCL metadata due to linking", false, false)
132 ModulePass
*llvm::createAMDGPUUnifyMetadataPass() {
133 return new AMDGPUUnifyMetadata();
136 bool AMDGPUUnifyMetadata::runOnModule(Module
&M
) {
137 return unifyMetadataImpl(M
);
140 PreservedAnalyses
AMDGPUUnifyMetadataPass::run(Module
&M
,
141 ModuleAnalysisManager
&AM
) {
142 return unifyMetadataImpl(M
) ? PreservedAnalyses::none()
143 : PreservedAnalyses::all();