Coverage Report

Created: 2017-10-03 07:32

/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/Target/AMDGPU/AMDGPUUnifyMetadata.cpp
Line
Count
Source
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
  class AMDGPUUnifyMetadata : public ModulePass {
42
  public:
43
    static char ID;
44
45
56
    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
112
    bool unifyVersionMD(Module &M, StringRef Name, bool PickFirst) {
60
112
      auto NamedMD = M.getNamedMetadata(Name);
61
112
      if (
!NamedMD || 112
NamedMD->getNumOperands() <= 143
)
62
111
        return false;
63
1
      MDNode *MaxMD = nullptr;
64
1
      auto MaxVer = 0U;
65
1
      for (const auto &VersionMD : NamedMD->operands()) {
66
1
        assert(VersionMD->getNumOperands() == 2);
67
1
        auto CMajor = mdconst::extract<ConstantInt>(VersionMD->getOperand(0));
68
1
        auto VersionMajor = CMajor->getZExtValue();
69
1
        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 > MaxVer1
) {
73
1
          MaxVer = Ver;
74
1
          MaxMD = VersionMD;
75
1
        }
76
1
        if (PickFirst)
77
1
          break;
78
1
      }
79
1
      NamedMD->eraseFromParent();
80
112
      NamedMD = M.getOrInsertNamedMetadata(Name);
81
112
      NamedMD->addOperand(MaxMD);
82
112
      return true;
83
112
    }
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
224
  bool unifyExtensionMD(Module &M, StringRef Name) {
93
224
    auto NamedMD = M.getNamedMetadata(Name);
94
224
    if (
!NamedMD || 224
NamedMD->getNumOperands() == 144
)
95
222
      return false;
96
2
97
2
    SmallVector<Metadata *, 4> All;
98
2
    for (const auto &MD : NamedMD->operands())
99
9
      for (const auto &Op : MD->operands())
100
11
        
if (11
std::find(All.begin(), All.end(), Op.get()) == All.end()11
)
101
5
          All.push_back(Op.get());
102
2
103
2
    NamedMD->eraseFromParent();
104
2
    NamedMD = M.getOrInsertNamedMetadata(Name);
105
2
    for (const auto &MD : All)
106
5
      NamedMD->addOperand(MDNode::get(M.getContext(), MD));
107
224
108
224
    return true;
109
224
  }
110
};
111
112
} // end anonymous namespace
113
114
char AMDGPUUnifyMetadata::ID = 0;
115
116
char &llvm::AMDGPUUnifyMetadataID = AMDGPUUnifyMetadata::ID;
117
118
INITIALIZE_PASS(AMDGPUUnifyMetadata, "amdgpu-unify-metadata",
119
                "Unify multiple OpenCL metadata due to linking",
120
                false, false)
121
122
55
ModulePass* llvm::createAMDGPUUnifyMetadataPass() {
123
55
  return new AMDGPUUnifyMetadata();
124
55
}
125
126
56
bool AMDGPUUnifyMetadata::runOnModule(Module &M) {
127
56
  const char* Vers[] = {
128
56
      kOCLMD::SpirVer,
129
56
      kOCLMD::OCLVer
130
56
  };
131
56
  const char* Exts[] = {
132
56
      kOCLMD::UsedExt,
133
56
      kOCLMD::UsedOptCoreFeat,
134
56
      kOCLMD::CompilerOptions,
135
56
      kOCLMD::LLVMIdent
136
56
  };
137
56
138
56
  bool Changed = false;
139
56
140
56
  for (auto &I : Vers)
141
112
    Changed |= unifyVersionMD(M, I, true);
142
56
143
56
  for (auto &I : Exts)
144
224
    Changed |= unifyExtensionMD(M, I);
145
56
146
56
  return Changed;
147
56
}