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