10b57cec5SDimitry Andric //===- AMDGPUUnifyMetadata.cpp - Unify OpenCL metadata --------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // \file 100b57cec5SDimitry Andric // This pass that unifies multiple OpenCL metadata due to linking. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #include "AMDGPU.h" 150b57cec5SDimitry Andric #include "llvm/IR/Constants.h" 160b57cec5SDimitry Andric #include "llvm/IR/Module.h" 17e8d8bef9SDimitry Andric #include "llvm/IR/PassManager.h" 180b57cec5SDimitry Andric #include "llvm/Pass.h" 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric using namespace llvm; 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric namespace { 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric namespace kOCLMD { 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric const char SpirVer[] = "opencl.spir.version"; 270b57cec5SDimitry Andric const char OCLVer[] = "opencl.ocl.version"; 280b57cec5SDimitry Andric const char UsedExt[] = "opencl.used.extensions"; 290b57cec5SDimitry Andric const char UsedOptCoreFeat[] = "opencl.used.optional.core.features"; 300b57cec5SDimitry Andric const char CompilerOptions[] = "opencl.compiler.options"; 310b57cec5SDimitry Andric const char LLVMIdent[] = "llvm.ident"; 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric } // end namespace kOCLMD 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric /// Unify multiple OpenCL metadata due to linking. 360b57cec5SDimitry Andric class AMDGPUUnifyMetadata : public ModulePass { 370b57cec5SDimitry Andric public: 380b57cec5SDimitry Andric static char ID; 390b57cec5SDimitry Andric AMDGPUUnifyMetadata()400b57cec5SDimitry Andric explicit AMDGPUUnifyMetadata() : ModulePass(ID) {} 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric private: 430b57cec5SDimitry Andric bool runOnModule(Module &M) override; 44e8d8bef9SDimitry Andric }; 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric /// Unify version metadata. 470b57cec5SDimitry Andric /// \return true if changes are made. 480b57cec5SDimitry Andric /// Assume the named metadata has operands each of which is a pair of 490b57cec5SDimitry Andric /// integer constant, e.g. 500b57cec5SDimitry Andric /// !Name = {!n1, !n2} 510b57cec5SDimitry Andric /// !n1 = {i32 1, i32 2} 520b57cec5SDimitry Andric /// !n2 = {i32 2, i32 0} 530b57cec5SDimitry Andric /// Keep the largest version as the sole operand if PickFirst is false. 540b57cec5SDimitry Andric /// Otherwise pick it from the first value, representing kernel module. unifyVersionMD(Module & M,StringRef Name,bool PickFirst)550b57cec5SDimitry Andric bool unifyVersionMD(Module &M, StringRef Name, bool PickFirst) { 560b57cec5SDimitry Andric auto NamedMD = M.getNamedMetadata(Name); 570b57cec5SDimitry Andric if (!NamedMD || NamedMD->getNumOperands() <= 1) 580b57cec5SDimitry Andric return false; 590b57cec5SDimitry Andric MDNode *MaxMD = nullptr; 600b57cec5SDimitry Andric auto MaxVer = 0U; 61*bdd1243dSDimitry Andric for (auto *VersionMD : NamedMD->operands()) { 620b57cec5SDimitry Andric assert(VersionMD->getNumOperands() == 2); 630b57cec5SDimitry Andric auto CMajor = mdconst::extract<ConstantInt>(VersionMD->getOperand(0)); 640b57cec5SDimitry Andric auto VersionMajor = CMajor->getZExtValue(); 650b57cec5SDimitry Andric auto CMinor = mdconst::extract<ConstantInt>(VersionMD->getOperand(1)); 660b57cec5SDimitry Andric auto VersionMinor = CMinor->getZExtValue(); 670b57cec5SDimitry Andric auto Ver = (VersionMajor * 100) + (VersionMinor * 10); 680b57cec5SDimitry Andric if (Ver > MaxVer) { 690b57cec5SDimitry Andric MaxVer = Ver; 700b57cec5SDimitry Andric MaxMD = VersionMD; 710b57cec5SDimitry Andric } 720b57cec5SDimitry Andric if (PickFirst) 730b57cec5SDimitry Andric break; 740b57cec5SDimitry Andric } 750b57cec5SDimitry Andric NamedMD->eraseFromParent(); 760b57cec5SDimitry Andric NamedMD = M.getOrInsertNamedMetadata(Name); 770b57cec5SDimitry Andric NamedMD->addOperand(MaxMD); 780b57cec5SDimitry Andric return true; 790b57cec5SDimitry Andric } 800b57cec5SDimitry Andric 810b57cec5SDimitry Andric /// Unify version metadata. 820b57cec5SDimitry Andric /// \return true if changes are made. 830b57cec5SDimitry Andric /// Assume the named metadata has operands each of which is a list e.g. 840b57cec5SDimitry Andric /// !Name = {!n1, !n2} 850b57cec5SDimitry Andric /// !n1 = !{!"cl_khr_fp16", {!"cl_khr_fp64"}} 860b57cec5SDimitry Andric /// !n2 = !{!"cl_khr_image"} 870b57cec5SDimitry Andric /// Combine it into a single list with unique operands. unifyExtensionMD(Module & M,StringRef Name)880b57cec5SDimitry Andric bool unifyExtensionMD(Module &M, StringRef Name) { 890b57cec5SDimitry Andric auto NamedMD = M.getNamedMetadata(Name); 900b57cec5SDimitry Andric if (!NamedMD || NamedMD->getNumOperands() == 1) 910b57cec5SDimitry Andric return false; 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric SmallVector<Metadata *, 4> All; 94*bdd1243dSDimitry Andric for (auto *MD : NamedMD->operands()) 950b57cec5SDimitry Andric for (const auto &Op : MD->operands()) 96e8d8bef9SDimitry Andric if (!llvm::is_contained(All, Op.get())) 970b57cec5SDimitry Andric All.push_back(Op.get()); 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric NamedMD->eraseFromParent(); 1000b57cec5SDimitry Andric NamedMD = M.getOrInsertNamedMetadata(Name); 1010b57cec5SDimitry Andric for (const auto &MD : All) 1020b57cec5SDimitry Andric NamedMD->addOperand(MDNode::get(M.getContext(), MD)); 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric return true; 1050b57cec5SDimitry Andric } 1060b57cec5SDimitry Andric unifyMetadataImpl(Module & M)107e8d8bef9SDimitry Andric bool unifyMetadataImpl(Module &M) { 108e8d8bef9SDimitry Andric const char *Vers[] = {kOCLMD::SpirVer, kOCLMD::OCLVer}; 109e8d8bef9SDimitry Andric const char *Exts[] = {kOCLMD::UsedExt, kOCLMD::UsedOptCoreFeat, 110e8d8bef9SDimitry Andric kOCLMD::CompilerOptions, kOCLMD::LLVMIdent}; 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric bool Changed = false; 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric for (auto &I : Vers) 1150b57cec5SDimitry Andric Changed |= unifyVersionMD(M, I, true); 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric for (auto &I : Exts) 1180b57cec5SDimitry Andric Changed |= unifyExtensionMD(M, I); 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric return Changed; 1210b57cec5SDimitry Andric } 122e8d8bef9SDimitry Andric 123e8d8bef9SDimitry Andric } // end anonymous namespace 124e8d8bef9SDimitry Andric 125e8d8bef9SDimitry Andric char AMDGPUUnifyMetadata::ID = 0; 126e8d8bef9SDimitry Andric 127e8d8bef9SDimitry Andric char &llvm::AMDGPUUnifyMetadataID = AMDGPUUnifyMetadata::ID; 128e8d8bef9SDimitry Andric 129e8d8bef9SDimitry Andric INITIALIZE_PASS(AMDGPUUnifyMetadata, "amdgpu-unify-metadata", 130e8d8bef9SDimitry Andric "Unify multiple OpenCL metadata due to linking", false, false) 131e8d8bef9SDimitry Andric createAMDGPUUnifyMetadataPass()132e8d8bef9SDimitry Andric ModulePass *llvm::createAMDGPUUnifyMetadataPass() { 133e8d8bef9SDimitry Andric return new AMDGPUUnifyMetadata(); 134e8d8bef9SDimitry Andric } 135e8d8bef9SDimitry Andric runOnModule(Module & M)136e8d8bef9SDimitry Andric bool AMDGPUUnifyMetadata::runOnModule(Module &M) { 137e8d8bef9SDimitry Andric return unifyMetadataImpl(M); 138e8d8bef9SDimitry Andric } 139e8d8bef9SDimitry Andric run(Module & M,ModuleAnalysisManager & AM)140e8d8bef9SDimitry Andric PreservedAnalyses AMDGPUUnifyMetadataPass::run(Module &M, 141e8d8bef9SDimitry Andric ModuleAnalysisManager &AM) { 142e8d8bef9SDimitry Andric return unifyMetadataImpl(M) ? PreservedAnalyses::none() 143e8d8bef9SDimitry Andric : PreservedAnalyses::all(); 144e8d8bef9SDimitry Andric } 145