blob: 1f6d9234c1ed9dcaff1794556770e90025a3f076 [file] [log] [blame]
Eugene Zelenkoc8fbf6f2017-08-10 00:46:15 +00001//===- AMDGPUUnifyMetadata.cpp - Unify OpenCL metadata --------------------===//
Stanislav Mekhanoshin50ea93a2016-12-08 19:46:04 +00002//
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
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000011// This pass that unifies multiple OpenCL metadata due to linking.
Stanislav Mekhanoshin50ea93a2016-12-08 19:46:04 +000012//
13//===----------------------------------------------------------------------===//
14
15#include "AMDGPU.h"
Eugene Zelenko734bb7b2017-01-20 17:52:16 +000016#include "llvm/ADT/SmallVector.h"
17#include "llvm/ADT/StringRef.h"
Stanislav Mekhanoshin50ea93a2016-12-08 19:46:04 +000018#include "llvm/IR/Constants.h"
Eugene Zelenkoc8fbf6f2017-08-10 00:46:15 +000019#include "llvm/IR/Metadata.h"
Stanislav Mekhanoshin50ea93a2016-12-08 19:46:04 +000020#include "llvm/IR/Module.h"
21#include "llvm/Pass.h"
Eugene Zelenko734bb7b2017-01-20 17:52:16 +000022#include <algorithm>
23#include <cassert>
Stanislav Mekhanoshin50ea93a2016-12-08 19:46:04 +000024
25using namespace llvm;
26
27namespace {
Eugene Zelenko734bb7b2017-01-20 17:52:16 +000028
Stanislav Mekhanoshin50ea93a2016-12-08 19:46:04 +000029 namespace kOCLMD {
Eugene Zelenko734bb7b2017-01-20 17:52:16 +000030
Stanislav Mekhanoshin50ea93a2016-12-08 19:46:04 +000031 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";
Eugene Zelenko734bb7b2017-01-20 17:52:16 +000037
38 } // end namespace kOCLMD
Stanislav Mekhanoshin50ea93a2016-12-08 19:46:04 +000039
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000040 /// Unify multiple OpenCL metadata due to linking.
Stanislav Mekhanoshinf6c1feb2017-01-27 16:38:10 +000041 class AMDGPUUnifyMetadata : public ModulePass {
Stanislav Mekhanoshin50ea93a2016-12-08 19:46:04 +000042 public:
43 static char ID;
Eugene Zelenkoc8fbf6f2017-08-10 00:46:15 +000044
45 explicit AMDGPUUnifyMetadata() : ModulePass(ID) {}
Stanislav Mekhanoshin50ea93a2016-12-08 19:46:04 +000046
47 private:
Eugene Zelenkoc8fbf6f2017-08-10 00:46:15 +000048 bool runOnModule(Module &M) override;
Stanislav Mekhanoshin50ea93a2016-12-08 19:46:04 +000049
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000050 /// Unify version metadata.
Stanislav Mekhanoshin50ea93a2016-12-08 19:46:04 +000051 /// \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
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000085 /// Unify version metadata.
Stanislav Mekhanoshin50ea93a2016-12-08 19:46:04 +000086 /// \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
97 SmallVector<Metadata *, 4> All;
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);
Konstantin Zhuravlyov980688c2016-12-19 16:54:24 +0000105 for (const auto &MD : All)
106 NamedMD->addOperand(MDNode::get(M.getContext(), MD));
107
Stanislav Mekhanoshin50ea93a2016-12-08 19:46:04 +0000108 return true;
109 }
110};
111
112} // end anonymous namespace
113
114char AMDGPUUnifyMetadata::ID = 0;
115
116char &llvm::AMDGPUUnifyMetadataID = AMDGPUUnifyMetadata::ID;
117
118INITIALIZE_PASS(AMDGPUUnifyMetadata, "amdgpu-unify-metadata",
119 "Unify multiple OpenCL metadata due to linking",
120 false, false)
121
Stanislav Mekhanoshinf6c1feb2017-01-27 16:38:10 +0000122ModulePass* llvm::createAMDGPUUnifyMetadataPass() {
Stanislav Mekhanoshin50ea93a2016-12-08 19:46:04 +0000123 return new AMDGPUUnifyMetadata();
124}
125
126bool 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
Konstantin Zhuravlyov980688c2016-12-19 16:54:24 +0000140 for (auto &I : Vers)
Stanislav Mekhanoshin50ea93a2016-12-08 19:46:04 +0000141 Changed |= unifyVersionMD(M, I, true);
142
Konstantin Zhuravlyov980688c2016-12-19 16:54:24 +0000143 for (auto &I : Exts)
Stanislav Mekhanoshin50ea93a2016-12-08 19:46:04 +0000144 Changed |= unifyExtensionMD(M, I);
145
146 return Changed;
147}