//===- CanonicalizeAliases.cpp - ThinLTO Support: Canonicalize Aliases ----===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Currently this file implements partial alias canonicalization, to
// flatten chains of aliases (also done by GlobalOpt, but not on for
// O0 compiles). E.g.
//  @a = alias i8, i8 *@b
//  @b = alias i8, i8 *@g
//
// will be converted to:
//  @a = alias i8, i8 *@g  <-- @a is now an alias to base object @g
//  @b = alias i8, i8 *@g
//
// Eventually this file will implement full alias canonicalation, so that
// all aliasees are private anonymous values. E.g.
//  @a = alias i8, i8 *@g
//  @g = global i8 0
//
// will be converted to:
//  @0 = private global
//  @a = alias i8, i8* @0
//  @g = alias i8, i8* @0
//
// This simplifies optimization and ThinLTO linking of the original symbols.
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Utils/CanonicalizeAliases.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/InitializePasses.h"
#include "llvm/Pass.h"

using namespace llvm;

namespace {

static Constant *canonicalizeAlias(Constant *C, bool &Changed) {
  if (auto *GA = dyn_cast<GlobalAlias>(C)) {
    auto *NewAliasee = canonicalizeAlias(GA->getAliasee(), Changed);
    if (NewAliasee != GA->getAliasee()) {
      GA->setAliasee(NewAliasee);
      Changed = true;
    }
    return NewAliasee;
  }

  auto *CE = dyn_cast<ConstantExpr>(C);
  if (!CE)
    return C;

  std::vector<Constant *> Ops;
  for (Use &U : CE->operands())
    Ops.push_back(canonicalizeAlias(cast<Constant>(U), Changed));
  return CE->getWithOperands(Ops);
}

/// Convert aliases to canonical form.
static bool canonicalizeAliases(Module &M) {
  bool Changed = false;
  for (auto &GA : M.aliases())
    canonicalizeAlias(&GA, Changed);
  return Changed;
}

// Legacy pass that canonicalizes aliases.
class CanonicalizeAliasesLegacyPass : public ModulePass {

public:
  /// Pass identification, replacement for typeid
  static char ID;

  /// Specify pass name for debug output
  StringRef getPassName() const override { return "Canonicalize Aliases"; }

  explicit CanonicalizeAliasesLegacyPass() : ModulePass(ID) {}

  bool runOnModule(Module &M) override { return canonicalizeAliases(M); }
};
char CanonicalizeAliasesLegacyPass::ID = 0;

} // anonymous namespace

PreservedAnalyses CanonicalizeAliasesPass::run(Module &M,
                                               ModuleAnalysisManager &AM) {
  if (!canonicalizeAliases(M))
    return PreservedAnalyses::all();

  return PreservedAnalyses::none();
}

INITIALIZE_PASS_BEGIN(CanonicalizeAliasesLegacyPass, "canonicalize-aliases",
                      "Canonicalize aliases", false, false)
INITIALIZE_PASS_END(CanonicalizeAliasesLegacyPass, "canonicalize-aliases",
                    "Canonicalize aliases", false, false)

namespace llvm {
ModulePass *createCanonicalizeAliasesPass() {
  return new CanonicalizeAliasesLegacyPass();
}
} // namespace llvm
