blob: d4401a22a1adb850b2a799089ebc36c9b2a0a01b [file] [log] [blame]
Eugene Zelenkoc8fbf6f2017-08-10 00:46:15 +00001//===- AMDGPUUnifyMetadata.cpp - Unify OpenCL metadata --------------------===//
Stanislav Mekhanoshin50ea93a2016-12-08 19:46:04 +00002//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Stanislav Mekhanoshin50ea93a2016-12-08 19:46:04 +00006//
7//===----------------------------------------------------------------------===//
8//
9// \file
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000010// This pass that unifies multiple OpenCL metadata due to linking.
Stanislav Mekhanoshin50ea93a2016-12-08 19:46:04 +000011//
12//===----------------------------------------------------------------------===//
13
14#include "AMDGPU.h"
Eugene Zelenko734bb7b2017-01-20 17:52:16 +000015#include "llvm/ADT/SmallVector.h"
16#include "llvm/ADT/StringRef.h"
Stanislav Mekhanoshin50ea93a2016-12-08 19:46:04 +000017#include "llvm/IR/Constants.h"
Eugene Zelenkoc8fbf6f2017-08-10 00:46:15 +000018#include "llvm/IR/Metadata.h"
Stanislav Mekhanoshin50ea93a2016-12-08 19:46:04 +000019#include "llvm/IR/Module.h"
20#include "llvm/Pass.h"
Eugene Zelenko734bb7b2017-01-20 17:52:16 +000021#include <algorithm>
22#include <cassert>
Stanislav Mekhanoshin50ea93a2016-12-08 19:46:04 +000023
24using namespace llvm;
25
26namespace {
Eugene Zelenko734bb7b2017-01-20 17:52:16 +000027
Stanislav Mekhanoshin50ea93a2016-12-08 19:46:04 +000028 namespace kOCLMD {
Eugene Zelenko734bb7b2017-01-20 17:52:16 +000029
Stanislav Mekhanoshin50ea93a2016-12-08 19:46:04 +000030 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";
Eugene Zelenko734bb7b2017-01-20 17:52:16 +000036
37 } // end namespace kOCLMD
Stanislav Mekhanoshin50ea93a2016-12-08 19:46:04 +000038
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000039 /// Unify multiple OpenCL metadata due to linking.
Stanislav Mekhanoshinf6c1feb2017-01-27 16:38:10 +000040 class AMDGPUUnifyMetadata : public ModulePass {
Stanislav Mekhanoshin50ea93a2016-12-08 19:46:04 +000041 public:
42 static char ID;
Eugene Zelenkoc8fbf6f2017-08-10 00:46:15 +000043
44 explicit AMDGPUUnifyMetadata() : ModulePass(ID) {}
Stanislav Mekhanoshin50ea93a2016-12-08 19:46:04 +000045
46 private:
Eugene Zelenkoc8fbf6f2017-08-10 00:46:15 +000047 bool runOnModule(Module &M) override;
Stanislav Mekhanoshin50ea93a2016-12-08 19:46:04 +000048
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000049 /// Unify version metadata.
Stanislav Mekhanoshin50ea93a2016-12-08 19:46:04 +000050 /// \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
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000084 /// Unify version metadata.
Stanislav Mekhanoshin50ea93a2016-12-08 19:46:04 +000085 /// \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
96 SmallVector<Metadata *, 4> All;
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);
Konstantin Zhuravlyov980688c2016-12-19 16:54:24 +0000104 for (const auto &MD : All)
105 NamedMD->addOperand(MDNode::get(M.getContext(), MD));
106
Stanislav Mekhanoshin50ea93a2016-12-08 19:46:04 +0000107 return true;
108 }
109};
110
111} // end anonymous namespace
112
113char AMDGPUUnifyMetadata::ID = 0;
114
115char &llvm::AMDGPUUnifyMetadataID = AMDGPUUnifyMetadata::ID;
116
117INITIALIZE_PASS(AMDGPUUnifyMetadata, "amdgpu-unify-metadata",
118 "Unify multiple OpenCL metadata due to linking",
119 false, false)
120
Stanislav Mekhanoshinf6c1feb2017-01-27 16:38:10 +0000121ModulePass* llvm::createAMDGPUUnifyMetadataPass() {
Stanislav Mekhanoshin50ea93a2016-12-08 19:46:04 +0000122 return new AMDGPUUnifyMetadata();
123}
124
125bool 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
Konstantin Zhuravlyov980688c2016-12-19 16:54:24 +0000139 for (auto &I : Vers)
Stanislav Mekhanoshin50ea93a2016-12-08 19:46:04 +0000140 Changed |= unifyVersionMD(M, I, true);
141
Konstantin Zhuravlyov980688c2016-12-19 16:54:24 +0000142 for (auto &I : Exts)
Stanislav Mekhanoshin50ea93a2016-12-08 19:46:04 +0000143 Changed |= unifyExtensionMD(M, I);
144
145 return Changed;
146}