LLVM API Documentation
00001 //===---- Delinearization.cpp - MultiDimensional Index Delinearization ----===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This implements an analysis pass that tries to delinearize all GEP 00011 // instructions in all loops using the SCEV analysis functionality. This pass is 00012 // only used for testing purposes: if your pass needs delinearization, please 00013 // use the on-demand SCEVAddRecExpr::delinearize() function. 00014 // 00015 //===----------------------------------------------------------------------===// 00016 00017 #include "llvm/IR/Constants.h" 00018 #include "llvm/Analysis/LoopInfo.h" 00019 #include "llvm/Analysis/Passes.h" 00020 #include "llvm/Analysis/ScalarEvolution.h" 00021 #include "llvm/Analysis/ScalarEvolutionExpressions.h" 00022 #include "llvm/IR/DerivedTypes.h" 00023 #include "llvm/IR/Function.h" 00024 #include "llvm/IR/InstIterator.h" 00025 #include "llvm/IR/Instructions.h" 00026 #include "llvm/IR/LLVMContext.h" 00027 #include "llvm/IR/Type.h" 00028 #include "llvm/Pass.h" 00029 #include "llvm/Support/CommandLine.h" 00030 #include "llvm/Support/Debug.h" 00031 #include "llvm/Support/raw_ostream.h" 00032 00033 using namespace llvm; 00034 00035 #define DL_NAME "delinearize" 00036 #define DEBUG_TYPE DL_NAME 00037 00038 namespace { 00039 00040 class Delinearization : public FunctionPass { 00041 Delinearization(const Delinearization &); // do not implement 00042 protected: 00043 Function *F; 00044 LoopInfo *LI; 00045 ScalarEvolution *SE; 00046 00047 public: 00048 static char ID; // Pass identification, replacement for typeid 00049 00050 Delinearization() : FunctionPass(ID) { 00051 initializeDelinearizationPass(*PassRegistry::getPassRegistry()); 00052 } 00053 bool runOnFunction(Function &F) override; 00054 void getAnalysisUsage(AnalysisUsage &AU) const override; 00055 void print(raw_ostream &O, const Module *M = nullptr) const override; 00056 }; 00057 00058 } // end anonymous namespace 00059 00060 void Delinearization::getAnalysisUsage(AnalysisUsage &AU) const { 00061 AU.setPreservesAll(); 00062 AU.addRequired<LoopInfo>(); 00063 AU.addRequired<ScalarEvolution>(); 00064 } 00065 00066 bool Delinearization::runOnFunction(Function &F) { 00067 this->F = &F; 00068 SE = &getAnalysis<ScalarEvolution>(); 00069 LI = &getAnalysis<LoopInfo>(); 00070 return false; 00071 } 00072 00073 static Value *getPointerOperand(Instruction &Inst) { 00074 if (LoadInst *Load = dyn_cast<LoadInst>(&Inst)) 00075 return Load->getPointerOperand(); 00076 else if (StoreInst *Store = dyn_cast<StoreInst>(&Inst)) 00077 return Store->getPointerOperand(); 00078 else if (GetElementPtrInst *Gep = dyn_cast<GetElementPtrInst>(&Inst)) 00079 return Gep->getPointerOperand(); 00080 return nullptr; 00081 } 00082 00083 void Delinearization::print(raw_ostream &O, const Module *) const { 00084 O << "Delinearization on function " << F->getName() << ":\n"; 00085 for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) { 00086 Instruction *Inst = &(*I); 00087 00088 // Only analyze loads and stores. 00089 if (!isa<StoreInst>(Inst) && !isa<LoadInst>(Inst) && 00090 !isa<GetElementPtrInst>(Inst)) 00091 continue; 00092 00093 const BasicBlock *BB = Inst->getParent(); 00094 // Delinearize the memory access as analyzed in all the surrounding loops. 00095 // Do not analyze memory accesses outside loops. 00096 for (Loop *L = LI->getLoopFor(BB); L != nullptr; L = L->getParentLoop()) { 00097 const SCEV *AccessFn = SE->getSCEVAtScope(getPointerOperand(*Inst), L); 00098 00099 const SCEVUnknown *BasePointer = 00100 dyn_cast<SCEVUnknown>(SE->getPointerBase(AccessFn)); 00101 // Do not delinearize if we cannot find the base pointer. 00102 if (!BasePointer) 00103 break; 00104 AccessFn = SE->getMinusSCEV(AccessFn, BasePointer); 00105 const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(AccessFn); 00106 00107 // Do not try to delinearize memory accesses that are not AddRecs. 00108 if (!AR) 00109 break; 00110 00111 00112 O << "\n"; 00113 O << "Inst:" << *Inst << "\n"; 00114 O << "In Loop with Header: " << L->getHeader()->getName() << "\n"; 00115 O << "AddRec: " << *AR << "\n"; 00116 00117 SmallVector<const SCEV *, 3> Subscripts, Sizes; 00118 AR->delinearize(*SE, Subscripts, Sizes, SE->getElementSize(Inst)); 00119 if (Subscripts.size() == 0 || Sizes.size() == 0 || 00120 Subscripts.size() != Sizes.size()) { 00121 O << "failed to delinearize\n"; 00122 continue; 00123 } 00124 00125 O << "Base offset: " << *BasePointer << "\n"; 00126 O << "ArrayDecl[UnknownSize]"; 00127 int Size = Subscripts.size(); 00128 for (int i = 0; i < Size - 1; i++) 00129 O << "[" << *Sizes[i] << "]"; 00130 O << " with elements of " << *Sizes[Size - 1] << " bytes.\n"; 00131 00132 O << "ArrayRef"; 00133 for (int i = 0; i < Size; i++) 00134 O << "[" << *Subscripts[i] << "]"; 00135 O << "\n"; 00136 } 00137 } 00138 } 00139 00140 char Delinearization::ID = 0; 00141 static const char delinearization_name[] = "Delinearization"; 00142 INITIALIZE_PASS_BEGIN(Delinearization, DL_NAME, delinearization_name, true, 00143 true) 00144 INITIALIZE_PASS_DEPENDENCY(LoopInfo) 00145 INITIALIZE_PASS_END(Delinearization, DL_NAME, delinearization_name, true, true) 00146 00147 FunctionPass *llvm::createDelinearizationPass() { return new Delinearization; }