106 lines
3.2 KiB
C++
106 lines
3.2 KiB
C++
//===- 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
|