1044eb2f6SDimitry Andric //===- AMDGPUUnifyMetadata.cpp - Unify OpenCL metadata --------------------===// 2b915e9e0SDimitry Andric // 3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6b915e9e0SDimitry Andric // 7b915e9e0SDimitry Andric //===----------------------------------------------------------------------===// 8b915e9e0SDimitry Andric // 9b915e9e0SDimitry Andric // \file 10eb11fae6SDimitry Andric // This pass that unifies multiple OpenCL metadata due to linking. 11b915e9e0SDimitry Andric // 12b915e9e0SDimitry Andric //===----------------------------------------------------------------------===// 13b915e9e0SDimitry Andric 14b915e9e0SDimitry Andric #include "AMDGPU.h" 15b915e9e0SDimitry Andric #include "llvm/IR/Constants.h" 16b915e9e0SDimitry Andric #include "llvm/IR/Module.h" 17b60736ecSDimitry Andric #include "llvm/IR/PassManager.h" 18b915e9e0SDimitry Andric #include "llvm/Pass.h" 19b915e9e0SDimitry Andric 20b915e9e0SDimitry Andric using namespace llvm; 21b915e9e0SDimitry Andric 22b915e9e0SDimitry Andric namespace { 2371d5a254SDimitry Andric 24b915e9e0SDimitry Andric namespace kOCLMD { 2571d5a254SDimitry Andric 26b915e9e0SDimitry Andric const char SpirVer[] = "opencl.spir.version"; 27b915e9e0SDimitry Andric const char OCLVer[] = "opencl.ocl.version"; 28b915e9e0SDimitry Andric const char UsedExt[] = "opencl.used.extensions"; 29b915e9e0SDimitry Andric const char UsedOptCoreFeat[] = "opencl.used.optional.core.features"; 30b915e9e0SDimitry Andric const char CompilerOptions[] = "opencl.compiler.options"; 31b915e9e0SDimitry Andric const char LLVMIdent[] = "llvm.ident"; 3271d5a254SDimitry Andric 3371d5a254SDimitry Andric } // end namespace kOCLMD 34b915e9e0SDimitry Andric 35eb11fae6SDimitry Andric /// Unify multiple OpenCL metadata due to linking. 3671d5a254SDimitry Andric class AMDGPUUnifyMetadata : public ModulePass { 37b915e9e0SDimitry Andric public: 38b915e9e0SDimitry Andric static char ID; 39044eb2f6SDimitry Andric AMDGPUUnifyMetadata()40044eb2f6SDimitry Andric explicit AMDGPUUnifyMetadata() : ModulePass(ID) {} 41b915e9e0SDimitry Andric 42b915e9e0SDimitry Andric private: 43044eb2f6SDimitry Andric bool runOnModule(Module &M) override; 44b60736ecSDimitry Andric }; 45b915e9e0SDimitry Andric 46eb11fae6SDimitry Andric /// Unify version metadata. 47b915e9e0SDimitry Andric /// \return true if changes are made. 48b915e9e0SDimitry Andric /// Assume the named metadata has operands each of which is a pair of 49b915e9e0SDimitry Andric /// integer constant, e.g. 50b915e9e0SDimitry Andric /// !Name = {!n1, !n2} 51b915e9e0SDimitry Andric /// !n1 = {i32 1, i32 2} 52b915e9e0SDimitry Andric /// !n2 = {i32 2, i32 0} 53b915e9e0SDimitry Andric /// Keep the largest version as the sole operand if PickFirst is false. 54b915e9e0SDimitry Andric /// Otherwise pick it from the first value, representing kernel module. unifyVersionMD(Module & M,StringRef Name,bool PickFirst)55b915e9e0SDimitry Andric bool unifyVersionMD(Module &M, StringRef Name, bool PickFirst) { 56b915e9e0SDimitry Andric auto NamedMD = M.getNamedMetadata(Name); 57b915e9e0SDimitry Andric if (!NamedMD || NamedMD->getNumOperands() <= 1) 58b915e9e0SDimitry Andric return false; 59b915e9e0SDimitry Andric MDNode *MaxMD = nullptr; 60b915e9e0SDimitry Andric auto MaxVer = 0U; 61e3b55780SDimitry Andric for (auto *VersionMD : NamedMD->operands()) { 62b915e9e0SDimitry Andric assert(VersionMD->getNumOperands() == 2); 63b915e9e0SDimitry Andric auto CMajor = mdconst::extract<ConstantInt>(VersionMD->getOperand(0)); 64b915e9e0SDimitry Andric auto VersionMajor = CMajor->getZExtValue(); 65b915e9e0SDimitry Andric auto CMinor = mdconst::extract<ConstantInt>(VersionMD->getOperand(1)); 66b915e9e0SDimitry Andric auto VersionMinor = CMinor->getZExtValue(); 67b915e9e0SDimitry Andric auto Ver = (VersionMajor * 100) + (VersionMinor * 10); 68b915e9e0SDimitry Andric if (Ver > MaxVer) { 69b915e9e0SDimitry Andric MaxVer = Ver; 70b915e9e0SDimitry Andric MaxMD = VersionMD; 71b915e9e0SDimitry Andric } 72b915e9e0SDimitry Andric if (PickFirst) 73b915e9e0SDimitry Andric break; 74b915e9e0SDimitry Andric } 75b915e9e0SDimitry Andric NamedMD->eraseFromParent(); 76b915e9e0SDimitry Andric NamedMD = M.getOrInsertNamedMetadata(Name); 77b915e9e0SDimitry Andric NamedMD->addOperand(MaxMD); 78b915e9e0SDimitry Andric return true; 79b915e9e0SDimitry Andric } 80b915e9e0SDimitry Andric 81eb11fae6SDimitry Andric /// Unify version metadata. 82b915e9e0SDimitry Andric /// \return true if changes are made. 83b915e9e0SDimitry Andric /// Assume the named metadata has operands each of which is a list e.g. 84b915e9e0SDimitry Andric /// !Name = {!n1, !n2} 85b915e9e0SDimitry Andric /// !n1 = !{!"cl_khr_fp16", {!"cl_khr_fp64"}} 86b915e9e0SDimitry Andric /// !n2 = !{!"cl_khr_image"} 87b915e9e0SDimitry Andric /// Combine it into a single list with unique operands. unifyExtensionMD(Module & M,StringRef Name)88b915e9e0SDimitry Andric bool unifyExtensionMD(Module &M, StringRef Name) { 89b915e9e0SDimitry Andric auto NamedMD = M.getNamedMetadata(Name); 90b915e9e0SDimitry Andric if (!NamedMD || NamedMD->getNumOperands() == 1) 91b915e9e0SDimitry Andric return false; 92b915e9e0SDimitry Andric 93b915e9e0SDimitry Andric SmallVector<Metadata *, 4> All; 94e3b55780SDimitry Andric for (auto *MD : NamedMD->operands()) 95b915e9e0SDimitry Andric for (const auto &Op : MD->operands()) 96b60736ecSDimitry Andric if (!llvm::is_contained(All, Op.get())) 97b915e9e0SDimitry Andric All.push_back(Op.get()); 98b915e9e0SDimitry Andric 99b915e9e0SDimitry Andric NamedMD->eraseFromParent(); 100b915e9e0SDimitry Andric NamedMD = M.getOrInsertNamedMetadata(Name); 101b915e9e0SDimitry Andric for (const auto &MD : All) 102b915e9e0SDimitry Andric NamedMD->addOperand(MDNode::get(M.getContext(), MD)); 103b915e9e0SDimitry Andric 104b915e9e0SDimitry Andric return true; 105b915e9e0SDimitry Andric } 106b915e9e0SDimitry Andric unifyMetadataImpl(Module & M)107b60736ecSDimitry Andric bool unifyMetadataImpl(Module &M) { 108b60736ecSDimitry Andric const char *Vers[] = {kOCLMD::SpirVer, kOCLMD::OCLVer}; 109b60736ecSDimitry Andric const char *Exts[] = {kOCLMD::UsedExt, kOCLMD::UsedOptCoreFeat, 110b60736ecSDimitry Andric kOCLMD::CompilerOptions, kOCLMD::LLVMIdent}; 111b915e9e0SDimitry Andric 112b915e9e0SDimitry Andric bool Changed = false; 113b915e9e0SDimitry Andric 114b915e9e0SDimitry Andric for (auto &I : Vers) 115b915e9e0SDimitry Andric Changed |= unifyVersionMD(M, I, true); 116b915e9e0SDimitry Andric 117b915e9e0SDimitry Andric for (auto &I : Exts) 118b915e9e0SDimitry Andric Changed |= unifyExtensionMD(M, I); 119b915e9e0SDimitry Andric 120b915e9e0SDimitry Andric return Changed; 121b915e9e0SDimitry Andric } 122b60736ecSDimitry Andric 123b60736ecSDimitry Andric } // end anonymous namespace 124b60736ecSDimitry Andric 125b60736ecSDimitry Andric char AMDGPUUnifyMetadata::ID = 0; 126b60736ecSDimitry Andric 127b60736ecSDimitry Andric char &llvm::AMDGPUUnifyMetadataID = AMDGPUUnifyMetadata::ID; 128b60736ecSDimitry Andric 129b60736ecSDimitry Andric INITIALIZE_PASS(AMDGPUUnifyMetadata, "amdgpu-unify-metadata", 130b60736ecSDimitry Andric "Unify multiple OpenCL metadata due to linking", false, false) 131b60736ecSDimitry Andric createAMDGPUUnifyMetadataPass()132b60736ecSDimitry Andric ModulePass *llvm::createAMDGPUUnifyMetadataPass() { 133b60736ecSDimitry Andric return new AMDGPUUnifyMetadata(); 134b60736ecSDimitry Andric } 135b60736ecSDimitry Andric runOnModule(Module & M)136b60736ecSDimitry Andric bool AMDGPUUnifyMetadata::runOnModule(Module &M) { 137b60736ecSDimitry Andric return unifyMetadataImpl(M); 138b60736ecSDimitry Andric } 139b60736ecSDimitry Andric run(Module & M,ModuleAnalysisManager & AM)140b60736ecSDimitry Andric PreservedAnalyses AMDGPUUnifyMetadataPass::run(Module &M, 141b60736ecSDimitry Andric ModuleAnalysisManager &AM) { 142b60736ecSDimitry Andric return unifyMetadataImpl(M) ? PreservedAnalyses::none() 143b60736ecSDimitry Andric : PreservedAnalyses::all(); 144b60736ecSDimitry Andric } 145