LCOV - code coverage report
Current view: top level - src - llvm-propagate-addrspaces.cpp (source / functions) Hit Total Coverage
Test: [test only] commit 0f242327d2cc9bd130497f44b6350c924185606a Lines: 172 186 92.5 %
Date: 2022-07-16 23:42:53 Functions: 16 18 88.9 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 103 114 90.4 %

           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-c/Core.h>
       6                 :            : #include <llvm-c/Types.h>
       7                 :            : 
       8                 :            : #include <llvm/ADT/SmallPtrSet.h>
       9                 :            : #include <llvm/Analysis/CFG.h>
      10                 :            : #include <llvm/IR/Value.h>
      11                 :            : #include <llvm/IR/ValueMap.h>
      12                 :            : #include <llvm/IR/Constants.h>
      13                 :            : #include <llvm/IR/Dominators.h>
      14                 :            : #include <llvm/IR/LegacyPassManager.h>
      15                 :            : #include <llvm/IR/Function.h>
      16                 :            : #include <llvm/IR/Instructions.h>
      17                 :            : #include <llvm/IR/IntrinsicInst.h>
      18                 :            : #include <llvm/IR/InstVisitor.h>
      19                 :            : #include <llvm/IR/Module.h>
      20                 :            : #include <llvm/IR/IRBuilder.h>
      21                 :            : #include <llvm/IR/Verifier.h>
      22                 :            : #include <llvm/Pass.h>
      23                 :            : #include <llvm/Support/Debug.h>
      24                 :            : 
      25                 :            : #include "codegen_shared.h"
      26                 :            : #include "julia.h"
      27                 :            : #include "passes.h"
      28                 :            : 
      29                 :            : #define DEBUG_TYPE "propagate_julia_addrspaces"
      30                 :            : 
      31                 :            : using namespace llvm;
      32                 :            : 
      33                 :            : /* This pass performs propagation of addrspace information that is legal from
      34                 :            :    the frontend definition, but illegal by general IR semantics. In particular,
      35                 :            :    this includes:
      36                 :            :       - Changing the address space of a load/store if the base pointer is
      37                 :            :         in an untracked address space
      38                 :            :       - Commuting GEPs and addrspace casts
      39                 :            : 
      40                 :            :     This is most useful for removing superfluous casts that can inhibit LLVM
      41                 :            :     optimizations.
      42                 :            : */
      43                 :            : 
      44                 :            : struct PropagateJuliaAddrspacesVisitor : public InstVisitor<PropagateJuliaAddrspacesVisitor> {
      45                 :            :     DenseMap<Value *, Value *> LiftingMap;
      46                 :            :     SmallPtrSet<Value *, 4> Visited;
      47                 :            :     std::vector<Instruction *> ToDelete;
      48                 :            :     std::vector<std::pair<Instruction *, Instruction *>> ToInsert;
      49                 :            : 
      50                 :            : public:
      51                 :            :     Value *LiftPointer(Value *V, Instruction *InsertPt=nullptr);
      52                 :            :     void visitMemop(Instruction &I, Type *T, unsigned OpIndex);
      53                 :            :     void visitLoadInst(LoadInst &LI);
      54                 :            :     void visitStoreInst(StoreInst &SI);
      55                 :            :     void visitAtomicCmpXchgInst(AtomicCmpXchgInst &SI);
      56                 :            :     void visitAtomicRMWInst(AtomicRMWInst &SI);
      57                 :            :     void visitMemSetInst(MemSetInst &MI);
      58                 :            :     void visitMemTransferInst(MemTransferInst &MTI);
      59                 :            : 
      60                 :            : private:
      61                 :            :     void PoisonValues(std::vector<Value *> &Worklist);
      62                 :            : };
      63                 :            : 
      64                 :    2871390 : static unsigned getValueAddrSpace(Value *V) {
      65                 :    2871390 :     return cast<PointerType>(V->getType())->getAddressSpace();
      66                 :            : }
      67                 :            : 
      68                 :   20363800 : static bool isSpecialAS(unsigned AS) {
      69   [ +  +  +  - ]:   20363800 :     return AddressSpace::FirstSpecial <= AS && AS <= AddressSpace::LastSpecial;
      70                 :            : }
      71                 :            : 
      72                 :   58943500 : void PropagateJuliaAddrspacesVisitor::PoisonValues(std::vector<Value *> &Worklist) {
      73         [ +  + ]:   58943500 :     while (!Worklist.empty()) {
      74                 :   57235300 :         Value *CurrentV = Worklist.back();
      75                 :   57235300 :         Worklist.pop_back();
      76         [ +  + ]:  119216000 :         for (Value *User : CurrentV->users()) {
      77         [ +  + ]:   61980300 :             if (Visited.count(User))
      78                 :    6453250 :                 continue;
      79                 :   55527100 :             Visited.insert(CurrentV);
      80                 :   55527100 :             Worklist.push_back(User);
      81                 :            :         }
      82                 :            :     }
      83                 :    1708190 : }
      84                 :            : 
      85                 :    6904980 : Value *PropagateJuliaAddrspacesVisitor::LiftPointer(Value *V, Instruction *InsertPt) {
      86                 :   13810000 :     SmallVector<Value *, 4> Stack;
      87                 :   13810000 :     std::vector<Value *> Worklist;
      88                 :   13810000 :     std::set<Value *> LocalVisited;
      89                 :    6904980 :     Worklist.push_back(V);
      90                 :            :     // Follow pointer casts back, see if we're based on a pointer in
      91                 :            :     // an untracked address space, in which case we're allowed to drop
      92                 :            :     // intermediate addrspace casts.
      93         [ +  + ]:    7047940 :     while (!Worklist.empty()) {
      94                 :    7000460 :         Value *CurrentV = Worklist.back();
      95                 :    7000460 :         Worklist.pop_back();
      96         [ +  + ]:    7000460 :         if (LocalVisited.count(CurrentV)) {
      97                 :       1057 :             continue;
      98                 :            :         }
      99                 :            :         while (true) {
     100         [ +  + ]:   12632000 :             if (auto *BCI = dyn_cast<BitCastInst>(CurrentV))
     101                 :    3423660 :                 CurrentV = BCI->getOperand(0);
     102         [ +  + ]:    9208370 :             else if (auto *ACI = dyn_cast<AddrSpaceCastInst>(CurrentV)) {
     103                 :    1142580 :                 CurrentV = ACI->getOperand(0);
     104         [ -  + ]:    1142580 :                 if (!isSpecialAS(getValueAddrSpace(ACI)))
     105                 :          0 :                     break;
     106                 :            :             }
     107         [ +  + ]:    8065790 :             else if (auto *GEP = dyn_cast<GetElementPtrInst>(CurrentV)) {
     108         [ +  + ]:    6193260 :                 if (LiftingMap.count(GEP)) {
     109                 :      19877 :                     CurrentV = LiftingMap[GEP];
     110                 :      19877 :                     break;
     111         [ +  + ]:    6173380 :                 } else if (Visited.count(GEP)) {
     112                 :    6857500 :                     return nullptr;
     113                 :            :                 }
     114                 :    1049220 :                 Stack.push_back(GEP);
     115                 :    1049220 :                 LocalVisited.insert(GEP);
     116                 :    1049220 :                 CurrentV = GEP->getOperand(0);
     117         [ +  + ]:    1872530 :             } else if (auto *Phi = dyn_cast<PHINode>(CurrentV)) {
     118         [ +  + ]:      62779 :                 if (LiftingMap.count(Phi)) {
     119                 :       4776 :                     break;
     120                 :            :                 }
     121         [ +  + ]:     180064 :                 for (Value *Incoming : Phi->incoming_values()) {
     122                 :     122061 :                     Worklist.push_back(Incoming);
     123                 :            :                 }
     124                 :      58003 :                 Stack.push_back(Phi);
     125                 :      58003 :                 LocalVisited.insert(Phi);
     126                 :      58003 :                 break;
     127         [ +  + ]:    1809750 :             } else if (auto *Select = dyn_cast<SelectInst>(CurrentV)) {
     128         [ +  + ]:      52483 :                 if (LiftingMap.count(Select)) {
     129                 :      10169 :                     break;
     130         [ +  + ]:      42314 :                 } else if (Visited.count(Select)) {
     131                 :      25150 :                     return nullptr;
     132                 :            :                 }
     133                 :            :                 // Push one of the branches onto the worklist, continue with the other one
     134                 :            :                 // directly
     135                 :      17164 :                 Worklist.push_back(Select->getOperand(2));
     136                 :      17164 :                 Stack.push_back(Select);
     137                 :      17164 :                 LocalVisited.insert(Select);
     138                 :      17164 :                 CurrentV = Select->getOperand(1);
     139         [ +  + ]:    1757270 :             } else if (isa<ConstantPointerNull>(CurrentV)) {
     140                 :            :                 // It's always legal to lift null pointers into any address space
     141                 :      28463 :                 break;
     142                 :            :             } else {
     143                 :            :                 // Ok, we've reached a leaf - check if it is eligible for lifting
     144   [ +  -  +  +  :    3457610 :                 if (!CurrentV->getType()->isPointerTy() ||
                   +  + ]
     145                 :    1728800 :                     isSpecialAS(getValueAddrSpace(CurrentV))) {
     146                 :            :                     // If not, poison all (recursive) users of this value, to prevent
     147                 :            :                     // looking at them again in future iterations.
     148                 :    1708190 :                     Worklist.clear();
     149                 :    1708190 :                     Worklist.push_back(CurrentV);
     150                 :    1708190 :                     Visited.insert(CurrentV);
     151                 :    1708190 :                     PoisonValues(Worklist);
     152                 :    1708190 :                     return nullptr;
     153                 :            :                 }
     154                 :      20616 :                 break;
     155                 :            :             }
     156                 :    5632640 :         }
     157                 :            :     }
     158                 :            : 
     159                 :            :     // Go through and insert lifted versions of all instructions on the list.
     160                 :      94960 :     std::vector<Value *> ToRevisit;
     161         [ +  + ]:     101734 :     for (Value *V : Stack) {
     162         [ -  + ]:      54254 :         if (LiftingMap.count(V))
     163                 :          0 :             continue;
     164   [ +  +  +  +  :      54254 :         if (isa<GetElementPtrInst>(V) || isa<PHINode>(V) || isa<SelectInst>(V)) {
             +  -  +  - ]
     165                 :      54254 :             Instruction *InstV = cast<Instruction>(V);
     166                 :      54254 :             Instruction *NewV = InstV->clone();
     167                 :      54254 :             ToInsert.push_back(std::make_pair(NewV, InstV));
     168                 :      54254 :             Type *NewRetTy = PointerType::getWithSamePointeeType(cast<PointerType>(InstV->getType()), AddressSpace::Generic);
     169                 :      54254 :             NewV->mutateType(NewRetTy);
     170                 :      54254 :             LiftingMap[InstV] = NewV;
     171                 :      54254 :             ToRevisit.push_back(NewV);
     172                 :            :         }
     173                 :            :     }
     174                 :            : 
     175                 :     131361 :     auto CollapseCastsAndLift = [&](Value *CurrentV, Instruction *InsertPt) -> Value * {
     176                 :     131361 :         PointerType *TargetType = PointerType::getWithSamePointeeType(cast<PointerType>(CurrentV->getType()), AddressSpace::Generic);
     177         [ +  + ]:     304350 :         while (!LiftingMap.count(CurrentV)) {
     178         [ +  + ]:     214658 :             if (isa<BitCastInst>(CurrentV))
     179                 :     103837 :                 CurrentV = cast<BitCastInst>(CurrentV)->getOperand(0);
     180         [ +  + ]:     110821 :             else if (isa<AddrSpaceCastInst>(CurrentV))
     181                 :      69152 :                 CurrentV = cast<AddrSpaceCastInst>(CurrentV)->getOperand(0);
     182                 :            :             else
     183                 :      41669 :                 break;
     184                 :            :         }
     185         [ +  + ]:     131361 :         if (isa<ConstantPointerNull>(CurrentV)) {
     186                 :      24222 :             return ConstantPointerNull::get(TargetType);
     187                 :            :         }
     188         [ +  + ]:     107139 :         if (LiftingMap.count(CurrentV))
     189                 :      89692 :             CurrentV = LiftingMap[CurrentV];
     190         [ +  + ]:     107139 :         if (CurrentV->getType() != TargetType) {
     191                 :      82575 :             auto *BCI = new BitCastInst(CurrentV, TargetType);
     192                 :      82575 :             ToInsert.push_back(std::make_pair(BCI, InsertPt));
     193                 :      82575 :             CurrentV = BCI;
     194                 :            :         }
     195                 :     107139 :         return CurrentV;
     196                 :      47480 :     };
     197                 :            : 
     198                 :            :     // Now go through and update the operands
     199         [ +  + ]:     101734 :     for (Value *V : ToRevisit) {
     200         [ +  + ]:      54254 :         if (GetElementPtrInst *NewGEP = dyn_cast<GetElementPtrInst>(V)) {
     201                 :      27767 :             NewGEP->setOperand(GetElementPtrInst::getPointerOperandIndex(),
     202                 :            :                 CollapseCastsAndLift(NewGEP->getOperand(GetElementPtrInst::getPointerOperandIndex()),
     203                 :            :                 NewGEP));
     204         [ +  + ]:      26487 :         } else if (PHINode *NewPhi = dyn_cast<PHINode>(V)) {
     205         [ +  + ]:      42854 :             for (size_t i = 0; i < NewPhi->getNumIncomingValues(); ++i) {
     206                 :      29616 :                 NewPhi->setIncomingValue(i, CollapseCastsAndLift(NewPhi->getIncomingValue(i),
     207                 :            :                     NewPhi->getIncomingBlock(i)->getTerminator()));
     208                 :            :             }
     209         [ +  - ]:      13249 :         } else if (SelectInst *NewSelect = dyn_cast<SelectInst>(V)) {
     210                 :      13249 :             NewSelect->setOperand(1, CollapseCastsAndLift(NewSelect->getOperand(1), NewSelect));
     211                 :      13249 :             NewSelect->setOperand(2, CollapseCastsAndLift(NewSelect->getOperand(2), NewSelect));
     212                 :            :         } else {
     213                 :            :             assert(false && "Shouldn't have reached here");
     214                 :            :         }
     215                 :            :     }
     216                 :            : 
     217                 :      47480 :     return CollapseCastsAndLift(V, InsertPt);
     218                 :            : }
     219                 :            : 
     220                 :   14977900 : void PropagateJuliaAddrspacesVisitor::visitMemop(Instruction &I, Type *T, unsigned OpIndex) {
     221                 :   14977900 :     Value *Original = I.getOperand(OpIndex);
     222                 :   14977900 :     unsigned AS = Original->getType()->getPointerAddressSpace();
     223         [ +  + ]:   14977900 :     if (!isSpecialAS(AS))
     224                 :    8530320 :         return;
     225                 :    6447600 :     Value *Replacement = LiftPointer(Original, &I);
     226         [ +  + ]:    6447600 :     if (!Replacement)
     227                 :    6412220 :         return;
     228                 :      35379 :     I.setOperand(OpIndex, Replacement);
     229                 :            : }
     230                 :            : 
     231                 :   10193800 : void PropagateJuliaAddrspacesVisitor::visitLoadInst(LoadInst &LI) {
     232                 :   10193800 :     visitMemop(LI, LI.getType(), LoadInst::getPointerOperandIndex());
     233                 :   10193800 : }
     234                 :            : 
     235                 :    4775440 : void PropagateJuliaAddrspacesVisitor::visitStoreInst(StoreInst &SI) {
     236                 :    4775440 :     visitMemop(SI, SI.getValueOperand()->getType(), StoreInst::getPointerOperandIndex());
     237                 :    4775440 : }
     238                 :            : 
     239                 :       6019 : void PropagateJuliaAddrspacesVisitor::visitAtomicCmpXchgInst(AtomicCmpXchgInst &SI) {
     240                 :       6019 :     visitMemop(SI, SI.getNewValOperand()->getType(), AtomicCmpXchgInst::getPointerOperandIndex());
     241                 :       6019 : }
     242                 :            : 
     243                 :       2653 : void PropagateJuliaAddrspacesVisitor::visitAtomicRMWInst(AtomicRMWInst &SI) {
     244                 :       2653 :     visitMemop(SI, SI.getType(), AtomicRMWInst::getPointerOperandIndex());
     245                 :       2653 : }
     246                 :            : 
     247                 :       2747 : void PropagateJuliaAddrspacesVisitor::visitMemSetInst(MemSetInst &MI) {
     248                 :       2747 :     unsigned AS = MI.getDestAddressSpace();
     249         [ +  + ]:       2747 :     if (!isSpecialAS(AS))
     250                 :       2741 :         return;
     251                 :          6 :     Value *Replacement = LiftPointer(MI.getRawDest());
     252         [ +  - ]:          6 :     if (!Replacement)
     253                 :          6 :         return;
     254                 :          0 :     Function *TheFn = Intrinsic::getDeclaration(MI.getModule(), Intrinsic::memset,
     255                 :          0 :         {Replacement->getType(), MI.getOperand(1)->getType()});
     256                 :          0 :     MI.setCalledFunction(TheFn);
     257                 :          0 :     MI.setArgOperand(0, Replacement);
     258                 :            : }
     259                 :            : 
     260                 :     957881 : void PropagateJuliaAddrspacesVisitor::visitMemTransferInst(MemTransferInst &MTI) {
     261                 :     957881 :     unsigned DestAS = MTI.getDestAddressSpace();
     262                 :     957881 :     unsigned SrcAS = MTI.getSourceAddressSpace();
     263   [ +  +  +  +  :     957881 :     if (!isSpecialAS(DestAS) && !isSpecialAS(SrcAS))
                   +  + ]
     264                 :     563044 :         return;
     265                 :     394837 :     Value *Dest = MTI.getRawDest();
     266         [ +  + ]:     394837 :     if (isSpecialAS(DestAS)) {
     267                 :     193652 :         Value *Replacement = LiftPointer(Dest, &MTI);
     268         [ +  + ]:     193652 :         if (Replacement)
     269                 :          2 :             Dest = Replacement;
     270                 :            :     }
     271                 :     394837 :     Value *Src = MTI.getRawSource();
     272         [ +  + ]:     394837 :     if (isSpecialAS(SrcAS)) {
     273                 :     263719 :         Value *Replacement = LiftPointer(Src, &MTI);
     274         [ +  + ]:     263719 :         if (Replacement)
     275                 :      12099 :             Src = Replacement;
     276                 :            :     }
     277   [ +  +  +  +  :     394837 :     if (Dest == MTI.getRawDest() && Src == MTI.getRawSource())
                   +  + ]
     278                 :     382736 :         return;
     279                 :      12101 :     Function *TheFn = Intrinsic::getDeclaration(MTI.getModule(), MTI.getIntrinsicID(),
     280                 :      12101 :         {Dest->getType(), Src->getType(),
     281                 :      12101 :          MTI.getOperand(2)->getType()});
     282                 :      12101 :     MTI.setCalledFunction(TheFn);
     283                 :      12101 :     MTI.setArgOperand(0, Dest);
     284                 :      12101 :     MTI.setArgOperand(1, Src);
     285                 :            : }
     286                 :            : 
     287                 :     614971 : bool propagateJuliaAddrspaces(Function &F) {
     288                 :     614971 :     PropagateJuliaAddrspacesVisitor visitor;
     289                 :     614971 :     visitor.visit(F);
     290         [ +  + ]:     751800 :     for (auto it : visitor.ToInsert)
     291                 :     136829 :         it.first->insertBefore(it.second);
     292         [ -  + ]:     614971 :     for (Instruction *I : visitor.ToDelete)
     293                 :          0 :         I->eraseFromParent();
     294                 :     614971 :     visitor.ToInsert.clear();
     295                 :     614971 :     visitor.ToDelete.clear();
     296                 :     614971 :     visitor.LiftingMap.clear();
     297                 :     614971 :     visitor.Visited.clear();
     298                 :     614971 :     return true;
     299                 :            : }
     300                 :            : 
     301                 :            : struct PropagateJuliaAddrspacesLegacy : FunctionPass {
     302                 :            :     static char ID;
     303                 :            : 
     304                 :        574 :     PropagateJuliaAddrspacesLegacy() : FunctionPass(ID) {}
     305                 :     614971 :     bool runOnFunction(Function &F) override {
     306                 :     614971 :         return propagateJuliaAddrspaces(F);
     307                 :            :     }
     308                 :            : };
     309                 :            : 
     310                 :            : char PropagateJuliaAddrspacesLegacy::ID = 0;
     311                 :            : static RegisterPass<PropagateJuliaAddrspacesLegacy> X("PropagateJuliaAddrspaces", "Propagate (non-)rootedness information", false, false);
     312                 :            : 
     313                 :        574 : Pass *createPropagateJuliaAddrspaces() {
     314                 :        574 :     return new PropagateJuliaAddrspacesLegacy();
     315                 :            : }
     316                 :            : 
     317                 :          0 : PreservedAnalyses PropagateJuliaAddrspacesPass::run(Function &F, FunctionAnalysisManager &AM) {
     318         [ #  # ]:          0 :     if (propagateJuliaAddrspaces(F)) {
     319                 :          0 :         return PreservedAnalyses::allInSet<CFGAnalyses>();
     320                 :            :     } else {
     321                 :          0 :         return PreservedAnalyses::all();
     322                 :            :     }
     323                 :            : }
     324                 :            : 
     325                 :          0 : extern "C" JL_DLLEXPORT void LLVMExtraAddPropagateJuliaAddrspaces_impl(LLVMPassManagerRef PM)
     326                 :            : {
     327                 :          0 :     unwrap(PM)->add(createPropagateJuliaAddrspaces());
     328                 :          0 : }

Generated by: LCOV version 1.14