LLVM API Documentation

Delinearization.cpp
Go to the documentation of this file.
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; }