//===- AMDGPUUnifyMetadata.cpp - Unify OpenCL metadata --------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// \file
// This pass that unifies multiple OpenCL metadata due to linking.
//
//===----------------------------------------------------------------------===//

#include "AMDGPU.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Pass.h"

using namespace llvm;

namespace {

  namespace kOCLMD {

    const char SpirVer[]            = "opencl.spir.version";
    const char OCLVer[]             = "opencl.ocl.version";
    const char UsedExt[]            = "opencl.used.extensions";
    const char UsedOptCoreFeat[]    = "opencl.used.optional.core.features";
    const char CompilerOptions[]    = "opencl.compiler.options";
    const char LLVMIdent[]          = "llvm.ident";

  } // end namespace kOCLMD

  /// Unify multiple OpenCL metadata due to linking.
  class AMDGPUUnifyMetadata : public ModulePass {
  public:
    static char ID;

    explicit AMDGPUUnifyMetadata() : ModulePass(ID) {}

  private:
    bool runOnModule(Module &M) override;
  };

    /// Unify version metadata.
    /// \return true if changes are made.
    /// Assume the named metadata has operands each of which is a pair of
    /// integer constant, e.g.
    /// !Name = {!n1, !n2}
    /// !n1 = {i32 1, i32 2}
    /// !n2 = {i32 2, i32 0}
    /// Keep the largest version as the sole operand if PickFirst is false.
    /// Otherwise pick it from the first value, representing kernel module.
    bool unifyVersionMD(Module &M, StringRef Name, bool PickFirst) {
      auto NamedMD = M.getNamedMetadata(Name);
      if (!NamedMD || NamedMD->getNumOperands() <= 1)
        return false;
      MDNode *MaxMD = nullptr;
      auto MaxVer = 0U;
      for (auto VersionMD : NamedMD->operands()) {
        assert(VersionMD->getNumOperands() == 2);
        auto CMajor = mdconst::extract<ConstantInt>(VersionMD->getOperand(0));
        auto VersionMajor = CMajor->getZExtValue();
        auto CMinor = mdconst::extract<ConstantInt>(VersionMD->getOperand(1));
        auto VersionMinor = CMinor->getZExtValue();
        auto Ver = (VersionMajor * 100) + (VersionMinor * 10);
        if (Ver > MaxVer) {
          MaxVer = Ver;
          MaxMD = VersionMD;
        }
        if (PickFirst)
          break;
      }
      NamedMD->eraseFromParent();
      NamedMD = M.getOrInsertNamedMetadata(Name);
      NamedMD->addOperand(MaxMD);
      return true;
    }

  /// Unify version metadata.
  /// \return true if changes are made.
  /// Assume the named metadata has operands each of which is a list e.g.
  /// !Name = {!n1, !n2}
  /// !n1 = !{!"cl_khr_fp16", {!"cl_khr_fp64"}}
  /// !n2 = !{!"cl_khr_image"}
  /// Combine it into a single list with unique operands.
  bool unifyExtensionMD(Module &M, StringRef Name) {
    auto NamedMD = M.getNamedMetadata(Name);
    if (!NamedMD || NamedMD->getNumOperands() == 1)
      return false;

    SmallVector<Metadata *, 4> All;
    for (auto MD : NamedMD->operands())
      for (const auto &Op : MD->operands())
        if (!llvm::is_contained(All, Op.get()))
          All.push_back(Op.get());

    NamedMD->eraseFromParent();
    NamedMD = M.getOrInsertNamedMetadata(Name);
    for (const auto &MD : All)
      NamedMD->addOperand(MDNode::get(M.getContext(), MD));

    return true;
  }

  bool unifyMetadataImpl(Module &M) {
    const char *Vers[] = {kOCLMD::SpirVer, kOCLMD::OCLVer};
    const char *Exts[] = {kOCLMD::UsedExt, kOCLMD::UsedOptCoreFeat,
                          kOCLMD::CompilerOptions, kOCLMD::LLVMIdent};

    bool Changed = false;

    for (auto &I : Vers)
      Changed |= unifyVersionMD(M, I, true);

    for (auto &I : Exts)
      Changed |= unifyExtensionMD(M, I);

    return Changed;
  }

  } // end anonymous namespace

  char AMDGPUUnifyMetadata::ID = 0;

  char &llvm::AMDGPUUnifyMetadataID = AMDGPUUnifyMetadata::ID;

  INITIALIZE_PASS(AMDGPUUnifyMetadata, "amdgpu-unify-metadata",
                  "Unify multiple OpenCL metadata due to linking", false, false)

  ModulePass *llvm::createAMDGPUUnifyMetadataPass() {
    return new AMDGPUUnifyMetadata();
  }

  bool AMDGPUUnifyMetadata::runOnModule(Module &M) {
    return unifyMetadataImpl(M);
  }

  PreservedAnalyses AMDGPUUnifyMetadataPass::run(Module &M,
                                                 ModuleAnalysisManager &AM) {
    return unifyMetadataImpl(M) ? PreservedAnalyses::none()
                                : PreservedAnalyses::all();
  }
