diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Analysis/Delinearization.cpp')
| -rw-r--r-- | contrib/llvm-project/llvm/lib/Analysis/Delinearization.cpp | 129 | 
1 files changed, 129 insertions, 0 deletions
diff --git a/contrib/llvm-project/llvm/lib/Analysis/Delinearization.cpp b/contrib/llvm-project/llvm/lib/Analysis/Delinearization.cpp new file mode 100644 index 000000000000..c1043e446beb --- /dev/null +++ b/contrib/llvm-project/llvm/lib/Analysis/Delinearization.cpp @@ -0,0 +1,129 @@ +//===---- Delinearization.cpp - MultiDimensional Index Delinearization ----===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// 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; }  | 
