| //===---- Delinearization.cpp - MultiDimensional Index Delinearization ----===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This implements an analysis pass that tries to delinearize all GEP |
| // instructions in all loops using the SCEV analysis functionality. This pass is |
| // only used for testing purposes: if your pass needs delinearization, please |
| // use the on-demand SCEVAddRecExpr::delinearize() function. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "llvm/Analysis/LoopInfo.h" |
| #include "llvm/Analysis/Passes.h" |
| #include "llvm/Analysis/ScalarEvolution.h" |
| #include "llvm/Analysis/ScalarEvolutionExpressions.h" |
| #include "llvm/IR/Constants.h" |
| #include "llvm/IR/DerivedTypes.h" |
| #include "llvm/IR/Function.h" |
| #include "llvm/IR/InstIterator.h" |
| #include "llvm/IR/Instructions.h" |
| #include "llvm/IR/LLVMContext.h" |
| #include "llvm/IR/Type.h" |
| #include "llvm/Pass.h" |
| #include "llvm/Support/Debug.h" |
| #include "llvm/Support/raw_ostream.h" |
| |
| using namespace llvm; |
| |
| #define DL_NAME "delinearize" |
| #define DEBUG_TYPE DL_NAME |
| |
| namespace { |
| |
| class Delinearization : public FunctionPass { |
| Delinearization(const Delinearization &); // do not implement |
| protected: |
| Function *F; |
| LoopInfo *LI; |
| ScalarEvolution *SE; |
| |
| public: |
| static char ID; // Pass identification, replacement for typeid |
| |
| Delinearization() : FunctionPass(ID) { |
| initializeDelinearizationPass(*PassRegistry::getPassRegistry()); |
| } |
| bool runOnFunction(Function &F) override; |
| void getAnalysisUsage(AnalysisUsage &AU) const override; |
| void print(raw_ostream &O, const Module *M = nullptr) const override; |
| }; |
| |
| } // end anonymous namespace |
| |
| void Delinearization::getAnalysisUsage(AnalysisUsage &AU) const { |
| AU.setPreservesAll(); |
| AU.addRequired<LoopInfoWrapperPass>(); |
| AU.addRequired<ScalarEvolutionWrapperPass>(); |
| } |
| |
| bool Delinearization::runOnFunction(Function &F) { |
| this->F = &F; |
| SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE(); |
| LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo(); |
| return false; |
| } |
| |
| void Delinearization::print(raw_ostream &O, const Module *) const { |
| O << "Delinearization on function " << F->getName() << ":\n"; |
| for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) { |
| Instruction *Inst = &(*I); |
| |
| // Only analyze loads and stores. |
| if (!isa<StoreInst>(Inst) && !isa<LoadInst>(Inst) && |
| !isa<GetElementPtrInst>(Inst)) |
| continue; |
| |
| const BasicBlock *BB = Inst->getParent(); |
| // Delinearize the memory access as analyzed in all the surrounding loops. |
| // Do not analyze memory accesses outside loops. |
| for (Loop *L = LI->getLoopFor(BB); L != nullptr; L = L->getParentLoop()) { |
| const SCEV *AccessFn = SE->getSCEVAtScope(getPointerOperand(Inst), L); |
| |
| const SCEVUnknown *BasePointer = |
| dyn_cast<SCEVUnknown>(SE->getPointerBase(AccessFn)); |
| // Do not delinearize if we cannot find the base pointer. |
| if (!BasePointer) |
| break; |
| AccessFn = SE->getMinusSCEV(AccessFn, BasePointer); |
| |
| O << "\n"; |
| O << "Inst:" << *Inst << "\n"; |
| O << "In Loop with Header: " << L->getHeader()->getName() << "\n"; |
| O << "AccessFunction: " << *AccessFn << "\n"; |
| |
| SmallVector<const SCEV *, 3> Subscripts, Sizes; |
| SE->delinearize(AccessFn, Subscripts, Sizes, SE->getElementSize(Inst)); |
| if (Subscripts.size() == 0 || Sizes.size() == 0 || |
| Subscripts.size() != Sizes.size()) { |
| O << "failed to delinearize\n"; |
| continue; |
| } |
| |
| O << "Base offset: " << *BasePointer << "\n"; |
| O << "ArrayDecl[UnknownSize]"; |
| int Size = Subscripts.size(); |
| for (int i = 0; i < Size - 1; i++) |
| O << "[" << *Sizes[i] << "]"; |
| O << " with elements of " << *Sizes[Size - 1] << " bytes.\n"; |
| |
| O << "ArrayRef"; |
| for (int i = 0; i < Size; i++) |
| O << "[" << *Subscripts[i] << "]"; |
| O << "\n"; |
| } |
| } |
| } |
| |
| char Delinearization::ID = 0; |
| static const char delinearization_name[] = "Delinearization"; |
| INITIALIZE_PASS_BEGIN(Delinearization, DL_NAME, delinearization_name, true, |
| true) |
| INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) |
| INITIALIZE_PASS_END(Delinearization, DL_NAME, delinearization_name, true, true) |
| |
| FunctionPass *llvm::createDelinearizationPass() { return new Delinearization; } |