106f32e7eSjoerg //===- CanonicalizeAliases.cpp - ThinLTO Support: Canonicalize Aliases ----===//
206f32e7eSjoerg //
306f32e7eSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406f32e7eSjoerg // See https://llvm.org/LICENSE.txt for license information.
506f32e7eSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606f32e7eSjoerg //
706f32e7eSjoerg //===----------------------------------------------------------------------===//
806f32e7eSjoerg //
906f32e7eSjoerg // Currently this file implements partial alias canonicalization, to
1006f32e7eSjoerg // flatten chains of aliases (also done by GlobalOpt, but not on for
1106f32e7eSjoerg // O0 compiles). E.g.
1206f32e7eSjoerg //  @a = alias i8, i8 *@b
1306f32e7eSjoerg //  @b = alias i8, i8 *@g
1406f32e7eSjoerg //
1506f32e7eSjoerg // will be converted to:
1606f32e7eSjoerg //  @a = alias i8, i8 *@g  <-- @a is now an alias to base object @g
1706f32e7eSjoerg //  @b = alias i8, i8 *@g
1806f32e7eSjoerg //
1906f32e7eSjoerg // Eventually this file will implement full alias canonicalation, so that
2006f32e7eSjoerg // all aliasees are private anonymous values. E.g.
2106f32e7eSjoerg //  @a = alias i8, i8 *@g
2206f32e7eSjoerg //  @g = global i8 0
2306f32e7eSjoerg //
2406f32e7eSjoerg // will be converted to:
2506f32e7eSjoerg //  @0 = private global
2606f32e7eSjoerg //  @a = alias i8, i8* @0
2706f32e7eSjoerg //  @g = alias i8, i8* @0
2806f32e7eSjoerg //
2906f32e7eSjoerg // This simplifies optimization and ThinLTO linking of the original symbols.
3006f32e7eSjoerg //===----------------------------------------------------------------------===//
3106f32e7eSjoerg 
3206f32e7eSjoerg #include "llvm/Transforms/Utils/CanonicalizeAliases.h"
3306f32e7eSjoerg #include "llvm/IR/Operator.h"
3406f32e7eSjoerg #include "llvm/IR/ValueHandle.h"
35*da58b97aSjoerg #include "llvm/InitializePasses.h"
3606f32e7eSjoerg #include "llvm/Pass.h"
3706f32e7eSjoerg 
3806f32e7eSjoerg using namespace llvm;
3906f32e7eSjoerg 
4006f32e7eSjoerg namespace {
4106f32e7eSjoerg 
canonicalizeAlias(Constant * C,bool & Changed)4206f32e7eSjoerg static Constant *canonicalizeAlias(Constant *C, bool &Changed) {
4306f32e7eSjoerg   if (auto *GA = dyn_cast<GlobalAlias>(C)) {
4406f32e7eSjoerg     auto *NewAliasee = canonicalizeAlias(GA->getAliasee(), Changed);
4506f32e7eSjoerg     if (NewAliasee != GA->getAliasee()) {
4606f32e7eSjoerg       GA->setAliasee(NewAliasee);
4706f32e7eSjoerg       Changed = true;
4806f32e7eSjoerg     }
4906f32e7eSjoerg     return NewAliasee;
5006f32e7eSjoerg   }
5106f32e7eSjoerg 
5206f32e7eSjoerg   auto *CE = dyn_cast<ConstantExpr>(C);
5306f32e7eSjoerg   if (!CE)
5406f32e7eSjoerg     return C;
5506f32e7eSjoerg 
5606f32e7eSjoerg   std::vector<Constant *> Ops;
5706f32e7eSjoerg   for (Use &U : CE->operands())
5806f32e7eSjoerg     Ops.push_back(canonicalizeAlias(cast<Constant>(U), Changed));
5906f32e7eSjoerg   return CE->getWithOperands(Ops);
6006f32e7eSjoerg }
6106f32e7eSjoerg 
6206f32e7eSjoerg /// Convert aliases to canonical form.
canonicalizeAliases(Module & M)6306f32e7eSjoerg static bool canonicalizeAliases(Module &M) {
6406f32e7eSjoerg   bool Changed = false;
6506f32e7eSjoerg   for (auto &GA : M.aliases())
6606f32e7eSjoerg     canonicalizeAlias(&GA, Changed);
6706f32e7eSjoerg   return Changed;
6806f32e7eSjoerg }
6906f32e7eSjoerg 
7006f32e7eSjoerg // Legacy pass that canonicalizes aliases.
7106f32e7eSjoerg class CanonicalizeAliasesLegacyPass : public ModulePass {
7206f32e7eSjoerg 
7306f32e7eSjoerg public:
7406f32e7eSjoerg   /// Pass identification, replacement for typeid
7506f32e7eSjoerg   static char ID;
7606f32e7eSjoerg 
7706f32e7eSjoerg   /// Specify pass name for debug output
getPassName() const7806f32e7eSjoerg   StringRef getPassName() const override { return "Canonicalize Aliases"; }
7906f32e7eSjoerg 
CanonicalizeAliasesLegacyPass()8006f32e7eSjoerg   explicit CanonicalizeAliasesLegacyPass() : ModulePass(ID) {}
8106f32e7eSjoerg 
runOnModule(Module & M)8206f32e7eSjoerg   bool runOnModule(Module &M) override { return canonicalizeAliases(M); }
8306f32e7eSjoerg };
8406f32e7eSjoerg char CanonicalizeAliasesLegacyPass::ID = 0;
8506f32e7eSjoerg 
8606f32e7eSjoerg } // anonymous namespace
8706f32e7eSjoerg 
run(Module & M,ModuleAnalysisManager & AM)8806f32e7eSjoerg PreservedAnalyses CanonicalizeAliasesPass::run(Module &M,
8906f32e7eSjoerg                                                ModuleAnalysisManager &AM) {
9006f32e7eSjoerg   if (!canonicalizeAliases(M))
9106f32e7eSjoerg     return PreservedAnalyses::all();
9206f32e7eSjoerg 
9306f32e7eSjoerg   return PreservedAnalyses::none();
9406f32e7eSjoerg }
9506f32e7eSjoerg 
9606f32e7eSjoerg INITIALIZE_PASS_BEGIN(CanonicalizeAliasesLegacyPass, "canonicalize-aliases",
9706f32e7eSjoerg                       "Canonicalize aliases", false, false)
9806f32e7eSjoerg INITIALIZE_PASS_END(CanonicalizeAliasesLegacyPass, "canonicalize-aliases",
9906f32e7eSjoerg                     "Canonicalize aliases", false, false)
10006f32e7eSjoerg 
10106f32e7eSjoerg namespace llvm {
createCanonicalizeAliasesPass()10206f32e7eSjoerg ModulePass *createCanonicalizeAliasesPass() {
10306f32e7eSjoerg   return new CanonicalizeAliasesLegacyPass();
10406f32e7eSjoerg }
10506f32e7eSjoerg } // namespace llvm
106