| //===- 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 |