LCOV - code coverage report
Current view: top level - src - llvm-remove-addrspaces.cpp (source / functions) Hit Total Coverage
Test: [test only] commit 0f242327d2cc9bd130497f44b6350c924185606a Lines: 177 230 77.0 %
Date: 2022-07-16 23:42:53 Functions: 15 21 71.4 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 88 118 74.6 %

           Branch data     Line data    Source code
       1                 :            : // This file is a part of Julia. License is MIT: https://julialang.org/license
       2                 :            : 
       3                 :            : #include "llvm-version.h"
       4                 :            : 
       5                 :            : #include <llvm/IR/Module.h>
       6                 :            : #include <llvm/IR/Verifier.h>
       7                 :            : #include <llvm/IR/Constants.h>
       8                 :            : #include <llvm/IR/Instructions.h>
       9                 :            : #include <llvm/IR/InstIterator.h>
      10                 :            : #include <llvm/IR/LegacyPassManager.h>
      11                 :            : #include <llvm/Support/Debug.h>
      12                 :            : #include <llvm/Transforms/Utils/Cloning.h>
      13                 :            : #include <llvm/Transforms/Utils/ValueMapper.h>
      14                 :            : 
      15                 :            : #include "codegen_shared.h"
      16                 :            : #include "julia.h"
      17                 :            : #include "passes.h"
      18                 :            : 
      19                 :            : #define DEBUG_TYPE "remove_addrspaces"
      20                 :            : 
      21                 :            : using namespace llvm;
      22                 :            : 
      23                 :            : using AddrspaceRemapFunction = std::function<unsigned(unsigned)>;
      24                 :            : 
      25                 :            : 
      26                 :            : //
      27                 :            : // Helpers
      28                 :            : //
      29                 :            : 
      30                 :            : class AddrspaceRemoveTypeRemapper : public ValueMapTypeRemapper {
      31                 :            :     AddrspaceRemapFunction ASRemapper;
      32                 :            : 
      33                 :            : public:
      34                 :         49 :     AddrspaceRemoveTypeRemapper(AddrspaceRemapFunction ASRemapper)
      35                 :         49 :         : ASRemapper(ASRemapper)
      36                 :            :     {
      37                 :         49 :     }
      38                 :            : 
      39                 :      19716 :     Type *remapType(Type *SrcTy)
      40                 :            :     {
      41                 :            :         // If we already have an entry for this type, return it.
      42                 :      19716 :         Type *DstTy = MappedTypes[SrcTy];
      43         [ +  + ]:      19716 :         if (DstTy)
      44                 :      18634 :             return DstTy;
      45                 :            : 
      46                 :       1082 :         DstTy = SrcTy;
      47         [ +  + ]:       1082 :         if (auto Ty = dyn_cast<PointerType>(SrcTy)) {
      48         [ -  + ]:        616 :             if (Ty->isOpaque()) {
      49                 :          0 :                 DstTy = PointerType::get(Ty->getContext(), ASRemapper(Ty->getAddressSpace()));
      50                 :            :             }
      51                 :            :             else {
      52                 :            :                 //Remove once opaque pointer transition is complete
      53                 :       1232 :                 DstTy = PointerType::get(
      54                 :        616 :                         remapType(Ty->getPointerElementType()),
      55                 :            :                         ASRemapper(Ty->getAddressSpace()));
      56                 :            :             }
      57                 :            :         }
      58         [ +  + ]:        466 :         else if (auto Ty = dyn_cast<FunctionType>(SrcTy)) {
      59                 :         60 :             SmallVector<Type *, 4> Params;
      60         [ +  + ]:        135 :             for (unsigned Index = 0; Index < Ty->getNumParams(); ++Index)
      61                 :         75 :                 Params.push_back(remapType(Ty->getParamType(Index)));
      62                 :        120 :             DstTy = FunctionType::get(
      63                 :        120 :                     remapType(Ty->getReturnType()), Params, Ty->isVarArg());
      64                 :            :         }
      65         [ +  + ]:        406 :         else if (auto Ty = dyn_cast<StructType>(SrcTy)) {
      66         [ +  - ]:         66 :             if (Ty->isLiteral()) {
      67                 :            :                 // Since a literal type has to have the body when it is created,
      68                 :            :                 // we need to remap the element types first. This is safe only
      69                 :            :                 // for literal types (i.e., no self-reference) and thus treated
      70                 :            :                 // separately.
      71                 :            :                 assert(!Ty->hasName()); // literal type has no name.
      72                 :         66 :                 SmallVector<Type *, 4> NewElTys;
      73                 :         66 :                 NewElTys.reserve(Ty->getNumElements());
      74         [ +  + ]:        115 :                 for (auto E: Ty->elements())
      75                 :         49 :                     NewElTys.push_back(remapType(E));
      76                 :         66 :                 DstTy = StructType::get(Ty->getContext(), NewElTys, Ty->isPacked());
      77         [ #  # ]:          0 :             } else if (!Ty->isOpaque()) {
      78                 :            :                 // If the struct type is not literal and not opaque, it can have
      79                 :            :                 // self-referential fields (i.e., pointer type of itself as a
      80                 :            :                 // field).
      81                 :          0 :                 StructType *DstTy_ = StructType::create(Ty->getContext());
      82         [ #  # ]:          0 :                 if (Ty->hasName()) {
      83                 :          0 :                     auto Name = std::string(Ty->getName());
      84                 :          0 :                     Ty->setName(Name + ".bad");
      85                 :          0 :                     DstTy_->setName(Name);
      86                 :            :                 }
      87                 :            :                 // To avoid infinite recursion, shove the placeholder of the DstTy before
      88                 :            :                 // recursing into the element types:
      89                 :          0 :                 MappedTypes[SrcTy] = DstTy_;
      90                 :            : 
      91                 :          0 :                 auto Els = Ty->getNumElements();
      92                 :          0 :                 SmallVector<Type *, 4> NewElTys(Els);
      93         [ #  # ]:          0 :                 for (unsigned i = 0; i < Els; ++i)
      94                 :          0 :                     NewElTys[i] = remapType(Ty->getElementType(i));
      95                 :          0 :                 DstTy_->setBody(NewElTys, Ty->isPacked());
      96                 :          0 :                 DstTy = DstTy_;
      97                 :            :             }
      98                 :            :         }
      99         [ +  + ]:        340 :         else if (auto Ty = dyn_cast<ArrayType>(SrcTy))
     100                 :        116 :             DstTy = ArrayType::get(
     101                 :         58 :                     remapType(Ty->getElementType()), Ty->getNumElements());
     102         [ +  + ]:        282 :         else if (auto Ty = dyn_cast<VectorType>(SrcTy))
     103                 :          1 :             DstTy = VectorType::get(remapType(Ty->getElementType()), Ty);
     104                 :            : 
     105                 :       1082 :         if (DstTy != SrcTy)
     106                 :            :             LLVM_DEBUG(
     107                 :            :                     dbgs() << "Remapping type:\n"
     108                 :            :                            << "  from " << *SrcTy << "\n"
     109                 :            :                            << "  to   " << *DstTy << "\n");
     110                 :            : 
     111                 :       1082 :         MappedTypes[SrcTy] = DstTy;
     112                 :       1082 :         return DstTy;
     113                 :            :     }
     114                 :            : 
     115                 :            : private:
     116                 :            :     DenseMap<Type *, Type *> MappedTypes;
     117                 :            : };
     118                 :            : 
     119                 :            : 
     120                 :            : class AddrspaceRemoveValueMaterializer : public ValueMaterializer {
     121                 :            :     ValueToValueMapTy &VM;
     122                 :            :     RemapFlags Flags;
     123                 :            :     ValueMapTypeRemapper *TypeMapper = nullptr;
     124                 :            : 
     125                 :            : public:
     126                 :         49 :     AddrspaceRemoveValueMaterializer(
     127                 :            :             ValueToValueMapTy &VM,
     128                 :            :             RemapFlags Flags = RF_None,
     129                 :            :             ValueMapTypeRemapper *TypeMapper = nullptr)
     130                 :         49 :         : VM(VM), Flags(Flags), TypeMapper(TypeMapper)
     131                 :            :     {
     132                 :         49 :     }
     133                 :            : 
     134                 :       2198 :     Value *materialize(Value *SrcV)
     135                 :            :     {
     136                 :       2198 :         Value *DstV = nullptr;
     137         [ +  + ]:       2198 :         if (auto CE = dyn_cast<ConstantExpr>(SrcV)) {
     138                 :        765 :             Type *Ty = remapType(CE->getType());
     139         [ +  + ]:        765 :             if (CE->getOpcode() == Instruction::AddrSpaceCast) {
     140                 :            :                 // peek through addrspacecasts if their address spaces match
     141                 :            :                 // (like RemoveNoopAddrSpaceCasts, but for const exprs)
     142                 :        312 :                 Constant *Src = mapConstant(CE->getOperand(0));
     143         [ +  - ]:        624 :                 if (Src->getType()->getPointerAddressSpace() ==
     144                 :        312 :                     Ty->getPointerAddressSpace())
     145                 :        312 :                     DstV = Src;
     146                 :            :             }
     147                 :            :             else {
     148                 :            :                 // recreate other const exprs with their operands remapped
     149                 :        906 :                 SmallVector<Constant *, 4> Ops;
     150         [ +  + ]:        918 :                 for (unsigned Index = 0; Index < CE->getNumOperands();
     151                 :            :                      ++Index) {
     152                 :        465 :                     Constant *Op = CE->getOperand(Index);
     153                 :        465 :                     Constant *NewOp = mapConstant(Op);
     154         [ +  - ]:        465 :                     Ops.push_back(NewOp ? cast<Constant>(NewOp) : Op);
     155                 :            :                 }
     156                 :            : 
     157         [ +  + ]:        453 :                 if (CE->getOpcode() == Instruction::GetElementPtr) {
     158                 :            :                     // GEP const exprs need to know the type of the source.
     159                 :            :                     // asserts remapType(typeof arg0) == typeof mapValue(arg0).
     160                 :          6 :                     Constant *Src = CE->getOperand(0);
     161                 :          6 :                     auto ptrty = cast<PointerType>(Src->getType()->getScalarType());
     162                 :            :                     //Remove once opaque pointer transition is complete
     163         [ +  - ]:          6 :                     if (!ptrty->isOpaque()) {
     164                 :          6 :                         Type *SrcTy = remapType(ptrty->getPointerElementType());
     165                 :          6 :                         DstV = CE->getWithOperands(Ops, Ty, false, SrcTy);
     166                 :            :                     }
     167                 :            :                 }
     168                 :            :                 else
     169                 :        447 :                     DstV = CE->getWithOperands(Ops, Ty);
     170                 :            :             }
     171                 :            :         }
     172                 :            : 
     173                 :            :         if (DstV)
     174                 :            :             LLVM_DEBUG(
     175                 :            :                     dbgs() << "Materializing value:\n"
     176                 :            :                            << "  from " << *SrcV << "\n"
     177                 :            :                            << "  to   " << *DstV << "\n");
     178                 :       2198 :         return DstV;
     179                 :            :     }
     180                 :            : 
     181                 :            : private:
     182                 :        771 :     Type *remapType(Type *SrcTy)
     183                 :            :     {
     184         [ +  - ]:        771 :         if (TypeMapper)
     185                 :        771 :             return TypeMapper->remapType(SrcTy);
     186                 :            :         else
     187                 :          0 :             return SrcTy;
     188                 :            :     }
     189                 :            : 
     190                 :            :     Value *mapValue(Value *V)
     191                 :            :     {
     192                 :            :         return MapValue(V, VM, Flags, TypeMapper, this);
     193                 :            :     }
     194                 :            : 
     195                 :        777 :     Constant *mapConstant(Constant *V)
     196                 :            :     {
     197                 :        777 :         return MapValue(V, VM, Flags, TypeMapper, this);
     198                 :            :     }
     199                 :            : };
     200                 :            : 
     201                 :        113 : bool RemoveNoopAddrSpaceCasts(Function *F)
     202                 :            : {
     203                 :        113 :     bool Changed = false;
     204                 :            : 
     205                 :        113 :     SmallVector<AddrSpaceCastInst *, 4> NoopCasts;
     206         [ +  + ]:       8684 :     for (Instruction &I : instructions(F)) {
     207         [ +  + ]:       8571 :         if (auto *ASC = dyn_cast<AddrSpaceCastInst>(&I)) {
     208         [ +  - ]:        306 :             if (ASC->getSrcAddressSpace() == ASC->getDestAddressSpace()) {
     209                 :            :                 LLVM_DEBUG(
     210                 :            :                         dbgs() << "Removing noop address space cast:\n"
     211                 :            :                                << I << "\n");
     212                 :        306 :                 ASC->replaceAllUsesWith(ASC->getOperand(0));
     213                 :        306 :                 NoopCasts.push_back(ASC);
     214                 :            :             }
     215                 :            :         }
     216                 :            :     }
     217         [ +  + ]:        419 :     for (auto &I : NoopCasts)
     218                 :        306 :         I->eraseFromParent();
     219                 :            : 
     220                 :        113 :     return Changed;
     221                 :            : }
     222                 :            : 
     223                 :        129 : static void copyComdat(GlobalObject *Dst, const GlobalObject *Src)
     224                 :            : {
     225                 :        129 :     const Comdat *SC = Src->getComdat();
     226         [ +  - ]:        129 :     if (!SC)
     227                 :        129 :         return;
     228                 :          0 :     Comdat *DC = Dst->getParent()->getOrInsertComdat(SC->getName());
     229                 :          0 :     DC->setSelectionKind(SC->getSelectionKind());
     230                 :          0 :     Dst->setComdat(DC);
     231                 :            : }
     232                 :            : 
     233                 :            : 
     234                 :            : //
     235                 :            : // Actual pass
     236                 :            : //
     237                 :            : 
     238                 :          0 : unsigned removeAllAddrspaces(unsigned AS)
     239                 :            : {
     240                 :          0 :     return AddressSpace::Generic;
     241                 :            : }
     242                 :            : 
     243                 :         49 : bool removeAddrspaces(Module &M, AddrspaceRemapFunction ASRemapper)
     244                 :            : {
     245                 :         98 :     ValueToValueMapTy VMap;
     246                 :         98 :     AddrspaceRemoveTypeRemapper TypeRemapper(ASRemapper);
     247                 :            :     AddrspaceRemoveValueMaterializer Materializer(
     248                 :         49 :             VMap, RF_None, &TypeRemapper);
     249                 :            : 
     250                 :            :     // Loop over all of the global variables, creating versions without address
     251                 :            :     // spaces. We only add the new globals to the VMap, attributes and
     252                 :            :     // initializers come later.
     253                 :         98 :     SmallVector<GlobalVariable *, 4> Globals;
     254         [ +  + ]:         71 :     for (auto &GV : M.globals())
     255                 :         22 :         Globals.push_back(&GV);
     256         [ +  + ]:         71 :     for (auto &GV : Globals) {
     257                 :         22 :         std::string Name;
     258         [ +  + ]:         22 :         if (GV->hasName()) {
     259                 :         14 :             Name = std::string(GV->getName());
     260                 :         14 :             GV->setName(Name + ".bad");
     261                 :            :         }
     262                 :            :         else
     263                 :          8 :             Name = "";
     264                 :            : 
     265                 :            :         GlobalVariable *NGV = new GlobalVariable(
     266                 :            :                 M,
     267                 :         22 :                 TypeRemapper.remapType(GV->getValueType()),
     268                 :         22 :                 GV->isConstant(),
     269                 :         22 :                 GV->getLinkage(),
     270                 :            :                 (Constant *)nullptr,
     271                 :            :                 Name,
     272                 :            :                 (GlobalVariable *)nullptr,
     273                 :         22 :                 GV->getThreadLocalMode(),
     274                 :         22 :                 GV->getType()->getAddressSpace());
     275                 :         22 :         NGV->copyAttributesFrom(GV);
     276                 :         22 :         VMap[GV] = NGV;
     277                 :            :     }
     278                 :            : 
     279                 :            :     // Loop over the aliases in the module.
     280                 :         98 :     SmallVector<GlobalAlias *, 4> Aliases;
     281         [ -  + ]:         49 :     for (auto &GA : M.aliases())
     282                 :          0 :         Aliases.push_back(&GA);
     283         [ -  + ]:         49 :     for (auto &GA : Aliases) {
     284                 :          0 :         std::string Name;
     285         [ #  # ]:          0 :         if (GA->hasName()) {
     286                 :          0 :             Name = std::string(GA->getName());
     287                 :          0 :             GA->setName(Name + ".bad");
     288                 :            :         }
     289                 :            :         else
     290                 :          0 :             Name = "";
     291                 :            : 
     292                 :          0 :         auto *NGA = GlobalAlias::create(
     293                 :            :                 TypeRemapper.remapType(GA->getValueType()),
     294                 :          0 :                 GA->getType()->getPointerAddressSpace(),
     295                 :            :                 GA->getLinkage(),
     296                 :            :                 Name,
     297                 :            :                 &M);
     298                 :          0 :         NGA->copyAttributesFrom(GA);
     299                 :          0 :         VMap[GA] = NGA;
     300                 :            :     }
     301                 :            : 
     302                 :            :     // Loop over the functions in the module, creating new ones as before.
     303                 :         49 :     SmallVector<Function *, 4> Functions;
     304         [ +  + ]:        824 :     for (Function &F : M)
     305                 :        775 :         Functions.push_back(&F);
     306         [ +  + ]:        824 :     for (Function *F : Functions) {
     307                 :       1550 :         std::string Name;
     308         [ +  - ]:        775 :         if (F->hasName()) {
     309                 :        775 :             Name = std::string(F->getName());
     310                 :        775 :             F->setName(Name + ".bad");
     311                 :            :         }
     312                 :            :         else
     313                 :          0 :             Name = "";
     314                 :            : 
     315                 :        775 :         FunctionType *FTy = cast<FunctionType>(F->getValueType());
     316                 :        775 :         SmallVector<Type *, 3> Tys;
     317         [ +  + ]:       2299 :         for (Type *Ty : FTy->params())
     318                 :       1524 :             Tys.push_back(TypeRemapper.remapType(Ty));
     319                 :        775 :         FunctionType *NFTy = FunctionType::get(
     320                 :            :                 TypeRemapper.remapType(FTy->getReturnType()),
     321                 :            :                 Tys,
     322                 :        775 :                 FTy->isVarArg());
     323                 :            : 
     324                 :        775 :         Function *NF = Function::Create(
     325                 :            :                 NFTy, F->getLinkage(), F->getAddressSpace(), Name, &M);
     326                 :            :         // no need to copy attributes here, that's done by CloneFunctionInto
     327                 :        775 :         VMap[F] = NF;
     328                 :            :     }
     329                 :            : 
     330                 :            :     // Now that all of the things that global variable initializer can refer to
     331                 :            :     // have been created, loop through and copy the global variable referrers
     332                 :            :     // over...  We also set the attributes on the globals now.
     333         [ +  + ]:         71 :     for (GlobalVariable *GV : Globals) {
     334         [ +  + ]:         22 :         if (GV->isDeclaration())
     335                 :          6 :             continue;
     336                 :            : 
     337                 :         16 :         GlobalVariable *NGV = cast<GlobalVariable>(VMap[GV]);
     338         [ +  - ]:         16 :         if (GV->hasInitializer())
     339                 :         16 :             NGV->setInitializer(MapValue(GV->getInitializer(), VMap));
     340                 :            : 
     341                 :         32 :         SmallVector<std::pair<unsigned, MDNode *>, 1> MDs;
     342                 :         16 :         GV->getAllMetadata(MDs);
     343         [ -  + ]:         16 :         for (auto MD : MDs)
     344                 :          0 :             NGV->addMetadata(
     345                 :            :                     MD.first,
     346                 :            : #if JL_LLVM_VERSION >= 130000
     347                 :          0 :                     *MapMetadata(MD.second, VMap));
     348                 :            : #else
     349                 :            :                     *MapMetadata(MD.second, VMap, RF_MoveDistinctMDs));
     350                 :            : #endif
     351                 :            : 
     352                 :         16 :         copyComdat(NGV, GV);
     353                 :            : 
     354                 :         16 :         GV->setInitializer(nullptr);
     355                 :            :     }
     356                 :            : 
     357                 :            :     // Similarly, copy over and rewrite function bodies
     358         [ +  + ]:        824 :     for (Function *F : Functions) {
     359         [ +  + ]:        775 :         if (F->isDeclaration())
     360                 :        662 :             continue;
     361                 :            : 
     362                 :        113 :         Function *NF = cast<Function>(VMap[F]);
     363                 :            :         LLVM_DEBUG(dbgs() << "Processing function " << NF->getName() << "\n");
     364                 :            : 
     365                 :        113 :         Function::arg_iterator DestI = NF->arg_begin();
     366         [ +  + ]:        360 :         for (Function::const_arg_iterator I = F->arg_begin(); I != F->arg_end();
     367                 :            :              ++I) {
     368                 :        247 :             DestI->setName(I->getName());
     369                 :        247 :             VMap[&*I] = &*DestI++;
     370                 :            :         }
     371                 :            : 
     372                 :        226 :         SmallVector<ReturnInst *, 8> Returns; // Ignore returns cloned.
     373                 :        113 :         CloneFunctionInto(
     374                 :            :                 NF,
     375                 :            :                 F,
     376                 :            :                 VMap,
     377                 :            : #if JL_LLVM_VERSION >= 130000
     378                 :            :                 CloneFunctionChangeType::GlobalChanges,
     379                 :            : #else
     380                 :            :                 /*ModuleLevelChanges=*/true,
     381                 :            : #endif
     382                 :            :                 Returns,
     383                 :            :                 "",
     384                 :            :                 nullptr,
     385                 :            :                 &TypeRemapper,
     386                 :            :                 &Materializer);
     387                 :            : 
     388                 :            :         // CloneFunctionInto unconditionally copies the attributes from F to NF,
     389                 :            :         // without considering e.g. the byval attribute type.
     390                 :        113 :         AttributeList Attrs = F->getAttributes();
     391                 :        113 :         LLVMContext &C = F->getContext();
     392         [ +  + ]:        472 :         for (unsigned i = 0; i < Attrs.getNumAttrSets(); ++i) {
     393                 :       1077 :             for (Attribute::AttrKind TypedAttr :
     394         [ +  + ]:       1436 :                  {Attribute::ByVal, Attribute::StructRet, Attribute::ByRef}) {
     395                 :            : #if JL_LLVM_VERSION >= 140000
     396                 :       1077 :                 auto Attr = Attrs.getAttributeAtIndex(i, TypedAttr);
     397                 :            : #else
     398                 :            :                 auto Attr = Attrs.getAttribute(i, TypedAttr);
     399                 :            : #endif
     400         [ -  + ]:       1077 :                 if (Type *Ty = Attr.getValueAsType()) {
     401                 :            : #if JL_LLVM_VERSION >= 140000
     402                 :            :                     Attrs = Attrs.replaceAttributeTypeAtIndex(
     403                 :          0 :                         C, i, TypedAttr, TypeRemapper.remapType(Ty));
     404                 :            : #else
     405                 :            :                     Attrs = Attrs.replaceAttributeType(
     406                 :            :                         C, i, TypedAttr, TypeRemapper.remapType(Ty));
     407                 :            : #endif
     408                 :          0 :                     break;
     409                 :            :                 }
     410                 :            :             }
     411                 :            :         }
     412                 :        113 :         NF->setAttributes(Attrs);
     413                 :            : 
     414         [ -  + ]:        113 :         if (F->hasPersonalityFn())
     415                 :          0 :             NF->setPersonalityFn(MapValue(F->getPersonalityFn(), VMap));
     416                 :            : 
     417                 :        113 :         copyComdat(NF, F);
     418                 :            : 
     419                 :        113 :         RemoveNoopAddrSpaceCasts(NF);
     420                 :        113 :         F->deleteBody();
     421                 :            :     }
     422                 :            : 
     423                 :            :     // And aliases
     424         [ -  + ]:         49 :     for (GlobalAlias *GA : Aliases) {
     425                 :          0 :         GlobalAlias *NGA = cast<GlobalAlias>(VMap[GA]);
     426         [ #  # ]:          0 :         if (const Constant *C = GA->getAliasee())
     427                 :          0 :             NGA->setAliasee(MapValue(C, VMap));
     428                 :            : 
     429                 :          0 :         GA->setAliasee(nullptr);
     430                 :            :     }
     431                 :            : 
     432                 :            :     // And named metadata
     433         [ +  + ]:        147 :     for (auto &NMD : M.named_metadata()) {
     434         [ +  + ]:        294 :         for (unsigned i = 0, e = NMD.getNumOperands(); i != e; ++i)
     435                 :        196 :             NMD.setOperand(i, MapMetadata(NMD.getOperand(i), VMap));
     436                 :            :     }
     437                 :            : 
     438                 :            :     // Now that we've duplicated everything, remove the old references
     439         [ +  + ]:         71 :     for (GlobalVariable *GV : Globals)
     440                 :         22 :         GV->eraseFromParent();
     441         [ -  + ]:         49 :     for (GlobalAlias *GA : Aliases)
     442                 :          0 :         GA->eraseFromParent();
     443         [ +  + ]:        824 :     for (Function *F : Functions)
     444                 :        775 :         F->eraseFromParent();
     445                 :            : 
     446                 :            :     // Finally, remangle calls to intrinsic
     447         [ +  + ]:        833 :     for (Module::iterator FI = M.begin(), FE = M.end(); FI != FE;) {
     448                 :        784 :         Function *F = &*FI++;
     449         [ +  + ]:        784 :         if (auto Remangled = Intrinsic::remangleIntrinsicFunction(F)) {
     450                 :          9 :             F->replaceAllUsesWith(Remangled.getValue());
     451                 :          9 :             F->eraseFromParent();
     452                 :            :         }
     453                 :            :     }
     454                 :            : 
     455                 :         49 :     return true;
     456                 :            : }
     457                 :            : 
     458                 :            : 
     459                 :            : struct RemoveAddrspacesPassLegacy : public ModulePass {
     460                 :            :     static char ID;
     461                 :            :     AddrspaceRemapFunction ASRemapper;
     462                 :         49 :     RemoveAddrspacesPassLegacy(
     463                 :            :             AddrspaceRemapFunction ASRemapper = removeAllAddrspaces)
     464                 :         49 :         : ModulePass(ID), ASRemapper(ASRemapper){};
     465                 :            : 
     466                 :            : public:
     467                 :         49 :     bool runOnModule(Module &M) override {
     468                 :         49 :         return removeAddrspaces(M, ASRemapper);
     469                 :            :     }
     470                 :            : };
     471                 :            : 
     472                 :            : char RemoveAddrspacesPassLegacy::ID = 0;
     473                 :            : static RegisterPass<RemoveAddrspacesPassLegacy>
     474                 :            :         X("RemoveAddrspaces",
     475                 :            :           "Remove IR address space information.",
     476                 :            :           false,
     477                 :            :           false);
     478                 :            : 
     479                 :          0 : Pass *createRemoveAddrspacesPass(
     480                 :            :         AddrspaceRemapFunction ASRemapper = removeAllAddrspaces)
     481                 :            : {
     482                 :          0 :     return new RemoveAddrspacesPassLegacy(ASRemapper);
     483                 :            : }
     484                 :            : 
     485                 :          0 : RemoveAddrspacesPass::RemoveAddrspacesPass() : RemoveAddrspacesPass(removeAllAddrspaces) {}
     486                 :            : 
     487                 :          0 : PreservedAnalyses RemoveAddrspacesPass::run(Module &M, ModuleAnalysisManager &AM) {
     488         [ #  # ]:          0 :     if (removeAddrspaces(M, ASRemapper)) {
     489                 :          0 :         return PreservedAnalyses::allInSet<CFGAnalyses>();
     490                 :            :     } else {
     491                 :          0 :         return PreservedAnalyses::all();
     492                 :            :     }
     493                 :            : }
     494                 :            : 
     495                 :            : 
     496                 :            : //
     497                 :            : // Julia-specific pass
     498                 :            : //
     499                 :            : 
     500                 :        616 : unsigned removeJuliaAddrspaces(unsigned AS)
     501                 :            : {
     502   [ +  +  +  - ]:        616 :     if (AddressSpace::FirstSpecial <= AS && AS <= AddressSpace::LastSpecial)
     503                 :        220 :         return AddressSpace::Generic;
     504                 :            :     else
     505                 :        396 :         return AS;
     506                 :            : }
     507                 :            : 
     508                 :            : struct RemoveJuliaAddrspacesPassLegacy : public ModulePass {
     509                 :            :     static char ID;
     510                 :            :     RemoveAddrspacesPassLegacy Pass;
     511                 :         49 :     RemoveJuliaAddrspacesPassLegacy() : ModulePass(ID), Pass(removeJuliaAddrspaces){};
     512                 :            : 
     513                 :         49 :     bool runOnModule(Module &M) override { return Pass.runOnModule(M); }
     514                 :            : };
     515                 :            : 
     516                 :            : char RemoveJuliaAddrspacesPassLegacy::ID = 0;
     517                 :            : static RegisterPass<RemoveJuliaAddrspacesPassLegacy>
     518                 :            :         Y("RemoveJuliaAddrspaces",
     519                 :            :           "Remove IR address space information.",
     520                 :            :           false,
     521                 :            :           false);
     522                 :            : 
     523                 :         49 : Pass *createRemoveJuliaAddrspacesPass()
     524                 :            : {
     525                 :         49 :     return new RemoveJuliaAddrspacesPassLegacy();
     526                 :            : }
     527                 :            : 
     528                 :          0 : PreservedAnalyses RemoveJuliaAddrspacesPass::run(Module &M, ModuleAnalysisManager &AM) {
     529                 :          0 :     return RemoveAddrspacesPass(removeJuliaAddrspaces).run(M, AM);
     530                 :            : }
     531                 :            : 
     532                 :          0 : extern "C" JL_DLLEXPORT void LLVMExtraAddRemoveJuliaAddrspacesPass_impl(LLVMPassManagerRef PM)
     533                 :            : {
     534                 :          0 :     unwrap(PM)->add(createRemoveJuliaAddrspacesPass());
     535                 :          0 : }

Generated by: LCOV version 1.14