LCOV - code coverage report
Current view: top level - lib/Target/AMDGPU - AMDGPUUnifyMetadata.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 46 46 100.0 %
Date: 2017-09-14 15:23:50 Functions: 7 8 87.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- AMDGPUUnifyMetadata.cpp - Unify OpenCL metadata --------------------===//
       2             : //
       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
      11             : // \brief This pass that unifies multiple OpenCL metadata due to linking.
      12             : //
      13             : //===----------------------------------------------------------------------===//
      14             : 
      15             : #include "AMDGPU.h"
      16             : #include "llvm/ADT/SmallVector.h"
      17             : #include "llvm/ADT/StringRef.h"
      18             : #include "llvm/IR/Constants.h"
      19             : #include "llvm/IR/Metadata.h"
      20             : #include "llvm/IR/Module.h"
      21             : #include "llvm/Pass.h"
      22             : #include <algorithm>
      23             : #include <cassert>
      24             : 
      25             : using namespace llvm;
      26             : 
      27             : namespace {
      28             : 
      29             :   namespace kOCLMD {
      30             : 
      31             :     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";
      37             : 
      38             :   } // end namespace kOCLMD
      39             : 
      40             :   /// \brief Unify multiple OpenCL metadata due to linking.
      41          54 :   class AMDGPUUnifyMetadata : public ModulePass {
      42             :   public:
      43             :     static char ID;
      44             : 
      45         108 :     explicit AMDGPUUnifyMetadata() : ModulePass(ID) {}
      46             : 
      47             :   private:
      48             :     bool runOnModule(Module &M) override;
      49             : 
      50             :     /// \brief Unify version metadata.
      51             :     /// \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         108 :     bool unifyVersionMD(Module &M, StringRef Name, bool PickFirst) {
      60         108 :       auto NamedMD = M.getNamedMetadata(Name);
      61         108 :       if (!NamedMD || NamedMD->getNumOperands() <= 1)
      62             :         return false;
      63           1 :       MDNode *MaxMD = nullptr;
      64           1 :       auto MaxVer = 0U;
      65           2 :       for (const auto &VersionMD : NamedMD->operands()) {
      66             :         assert(VersionMD->getNumOperands() == 2);
      67           3 :         auto CMajor = mdconst::extract<ConstantInt>(VersionMD->getOperand(0));
      68           1 :         auto VersionMajor = CMajor->getZExtValue();
      69           3 :         auto CMinor = mdconst::extract<ConstantInt>(VersionMD->getOperand(1));
      70           1 :         auto VersionMinor = CMinor->getZExtValue();
      71           1 :         auto Ver = (VersionMajor * 100) + (VersionMinor * 10);
      72           1 :         if (Ver > MaxVer) {
      73           1 :           MaxVer = Ver;
      74           1 :           MaxMD = VersionMD;
      75             :         }
      76           1 :         if (PickFirst)
      77             :           break;
      78             :       }
      79           1 :       NamedMD->eraseFromParent();
      80           1 :       NamedMD = M.getOrInsertNamedMetadata(Name);
      81           1 :       NamedMD->addOperand(MaxMD);
      82           1 :       return true;
      83             :     }
      84             : 
      85             :   /// \brief Unify version metadata.
      86             :   /// \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         216 :   bool unifyExtensionMD(Module &M, StringRef Name) {
      93         216 :     auto NamedMD = M.getNamedMetadata(Name);
      94         216 :     if (!NamedMD || NamedMD->getNumOperands() == 1)
      95             :       return false;
      96             : 
      97           2 :     SmallVector<Metadata *, 4> All;
      98          11 :     for (const auto &MD : NamedMD->operands())
      99          29 :       for (const auto &Op : MD->operands())
     100          44 :         if (std::find(All.begin(), All.end(), Op.get()) == All.end())
     101           5 :           All.push_back(Op.get());
     102             : 
     103           2 :     NamedMD->eraseFromParent();
     104           2 :     NamedMD = M.getOrInsertNamedMetadata(Name);
     105          11 :     for (const auto &MD : All)
     106          10 :       NamedMD->addOperand(MDNode::get(M.getContext(), MD));
     107             : 
     108           2 :     return true;
     109             :   }
     110             : };
     111             : 
     112             : } // end anonymous namespace
     113             : 
     114             : char AMDGPUUnifyMetadata::ID = 0;
     115             : 
     116             : char &llvm::AMDGPUUnifyMetadataID = AMDGPUUnifyMetadata::ID;
     117             : 
     118      312538 : INITIALIZE_PASS(AMDGPUUnifyMetadata, "amdgpu-unify-metadata",
     119             :                 "Unify multiple OpenCL metadata due to linking",
     120             :                 false, false)
     121             : 
     122          53 : ModulePass* llvm::createAMDGPUUnifyMetadataPass() {
     123         106 :   return new AMDGPUUnifyMetadata();
     124             : }
     125             : 
     126          54 : bool AMDGPUUnifyMetadata::runOnModule(Module &M) {
     127          54 :   const char* Vers[] = {
     128             :       kOCLMD::SpirVer,
     129             :       kOCLMD::OCLVer
     130             :   };
     131          54 :   const char* Exts[] = {
     132             :       kOCLMD::UsedExt,
     133             :       kOCLMD::UsedOptCoreFeat,
     134             :       kOCLMD::CompilerOptions,
     135             :       kOCLMD::LLVMIdent
     136             :   };
     137             : 
     138          54 :   bool Changed = false;
     139             : 
     140         162 :   for (auto &I : Vers)
     141         216 :     Changed |= unifyVersionMD(M, I, true);
     142             : 
     143         486 :   for (auto &I : Exts)
     144         432 :     Changed |= unifyExtensionMD(M, I);
     145             : 
     146          54 :   return Changed;
     147             : }

Generated by: LCOV version 1.13