Coverage Report

Created: 2019-07-24 05:18

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