1*06f32e7eSjoerg //===- CanonicalizeAliases.cpp - ThinLTO Support: Canonicalize Aliases ----===//
2*06f32e7eSjoerg //
3*06f32e7eSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*06f32e7eSjoerg // See https://llvm.org/LICENSE.txt for license information.
5*06f32e7eSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*06f32e7eSjoerg //
7*06f32e7eSjoerg //===----------------------------------------------------------------------===//
8*06f32e7eSjoerg //
9*06f32e7eSjoerg // Currently this file implements partial alias canonicalization, to
10*06f32e7eSjoerg // flatten chains of aliases (also done by GlobalOpt, but not on for
11*06f32e7eSjoerg // O0 compiles). E.g.
12*06f32e7eSjoerg //  @a = alias i8, i8 *@b
13*06f32e7eSjoerg //  @b = alias i8, i8 *@g
14*06f32e7eSjoerg //
15*06f32e7eSjoerg // will be converted to:
16*06f32e7eSjoerg //  @a = alias i8, i8 *@g  <-- @a is now an alias to base object @g
17*06f32e7eSjoerg //  @b = alias i8, i8 *@g
18*06f32e7eSjoerg //
19*06f32e7eSjoerg // Eventually this file will implement full alias canonicalation, so that
20*06f32e7eSjoerg // all aliasees are private anonymous values. E.g.
21*06f32e7eSjoerg //  @a = alias i8, i8 *@g
22*06f32e7eSjoerg //  @g = global i8 0
23*06f32e7eSjoerg //
24*06f32e7eSjoerg // will be converted to:
25*06f32e7eSjoerg //  @0 = private global
26*06f32e7eSjoerg //  @a = alias i8, i8* @0
27*06f32e7eSjoerg //  @g = alias i8, i8* @0
28*06f32e7eSjoerg //
29*06f32e7eSjoerg // This simplifies optimization and ThinLTO linking of the original symbols.
30*06f32e7eSjoerg //===----------------------------------------------------------------------===//
31*06f32e7eSjoerg 
32*06f32e7eSjoerg #include "llvm/Transforms/Utils/CanonicalizeAliases.h"
33*06f32e7eSjoerg 
34*06f32e7eSjoerg #include "llvm/IR/Operator.h"
35*06f32e7eSjoerg #include "llvm/IR/ValueHandle.h"
36*06f32e7eSjoerg #include "llvm/Pass.h"
37*06f32e7eSjoerg 
38*06f32e7eSjoerg using namespace llvm;
39*06f32e7eSjoerg 
40*06f32e7eSjoerg namespace {
41*06f32e7eSjoerg 
42*06f32e7eSjoerg static Constant *canonicalizeAlias(Constant *C, bool &Changed) {
43*06f32e7eSjoerg   if (auto *GA = dyn_cast<GlobalAlias>(C)) {
44*06f32e7eSjoerg     auto *NewAliasee = canonicalizeAlias(GA->getAliasee(), Changed);
45*06f32e7eSjoerg     if (NewAliasee != GA->getAliasee()) {
46*06f32e7eSjoerg       GA->setAliasee(NewAliasee);
47*06f32e7eSjoerg       Changed = true;
48*06f32e7eSjoerg     }
49*06f32e7eSjoerg     return NewAliasee;
50*06f32e7eSjoerg   }
51*06f32e7eSjoerg 
52*06f32e7eSjoerg   auto *CE = dyn_cast<ConstantExpr>(C);
53*06f32e7eSjoerg   if (!CE)
54*06f32e7eSjoerg     return C;
55*06f32e7eSjoerg 
56*06f32e7eSjoerg   std::vector<Constant *> Ops;
57*06f32e7eSjoerg   for (Use &U : CE->operands())
58*06f32e7eSjoerg     Ops.push_back(canonicalizeAlias(cast<Constant>(U), Changed));
59*06f32e7eSjoerg   return CE->getWithOperands(Ops);
60*06f32e7eSjoerg }
61*06f32e7eSjoerg 
62*06f32e7eSjoerg /// Convert aliases to canonical form.
63*06f32e7eSjoerg static bool canonicalizeAliases(Module &M) {
64*06f32e7eSjoerg   bool Changed = false;
65*06f32e7eSjoerg   for (auto &GA : M.aliases())
66*06f32e7eSjoerg     canonicalizeAlias(&GA, Changed);
67*06f32e7eSjoerg   return Changed;
68*06f32e7eSjoerg }
69*06f32e7eSjoerg 
70*06f32e7eSjoerg // Legacy pass that canonicalizes aliases.
71*06f32e7eSjoerg class CanonicalizeAliasesLegacyPass : public ModulePass {
72*06f32e7eSjoerg 
73*06f32e7eSjoerg public:
74*06f32e7eSjoerg   /// Pass identification, replacement for typeid
75*06f32e7eSjoerg   static char ID;
76*06f32e7eSjoerg 
77*06f32e7eSjoerg   /// Specify pass name for debug output
78*06f32e7eSjoerg   StringRef getPassName() const override { return "Canonicalize Aliases"; }
79*06f32e7eSjoerg 
80*06f32e7eSjoerg   explicit CanonicalizeAliasesLegacyPass() : ModulePass(ID) {}
81*06f32e7eSjoerg 
82*06f32e7eSjoerg   bool runOnModule(Module &M) override { return canonicalizeAliases(M); }
83*06f32e7eSjoerg };
84*06f32e7eSjoerg char CanonicalizeAliasesLegacyPass::ID = 0;
85*06f32e7eSjoerg 
86*06f32e7eSjoerg } // anonymous namespace
87*06f32e7eSjoerg 
88*06f32e7eSjoerg PreservedAnalyses CanonicalizeAliasesPass::run(Module &M,
89*06f32e7eSjoerg                                                ModuleAnalysisManager &AM) {
90*06f32e7eSjoerg   if (!canonicalizeAliases(M))
91*06f32e7eSjoerg     return PreservedAnalyses::all();
92*06f32e7eSjoerg 
93*06f32e7eSjoerg   return PreservedAnalyses::none();
94*06f32e7eSjoerg }
95*06f32e7eSjoerg 
96*06f32e7eSjoerg INITIALIZE_PASS_BEGIN(CanonicalizeAliasesLegacyPass, "canonicalize-aliases",
97*06f32e7eSjoerg                       "Canonicalize aliases", false, false)
98*06f32e7eSjoerg INITIALIZE_PASS_END(CanonicalizeAliasesLegacyPass, "canonicalize-aliases",
99*06f32e7eSjoerg                     "Canonicalize aliases", false, false)
100*06f32e7eSjoerg 
101*06f32e7eSjoerg namespace llvm {
102*06f32e7eSjoerg ModulePass *createCanonicalizeAliasesPass() {
103*06f32e7eSjoerg   return new CanonicalizeAliasesLegacyPass();
104*06f32e7eSjoerg }
105*06f32e7eSjoerg } // namespace llvm
106