xref: /netbsd-src/external/apache2/llvm/dist/llvm/lib/Analysis/Delinearization.cpp (revision 82d56013d7b633d116a93943de88e08335357a7c)
17330f729Sjoerg //===---- Delinearization.cpp - MultiDimensional Index Delinearization ----===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg // This implements an analysis pass that tries to delinearize all GEP
107330f729Sjoerg // instructions in all loops using the SCEV analysis functionality. This pass is
117330f729Sjoerg // only used for testing purposes: if your pass needs delinearization, please
127330f729Sjoerg // use the on-demand SCEVAddRecExpr::delinearize() function.
137330f729Sjoerg //
147330f729Sjoerg //===----------------------------------------------------------------------===//
157330f729Sjoerg 
16*82d56013Sjoerg #include "llvm/Analysis/Delinearization.h"
177330f729Sjoerg #include "llvm/Analysis/LoopInfo.h"
187330f729Sjoerg #include "llvm/Analysis/Passes.h"
197330f729Sjoerg #include "llvm/Analysis/ScalarEvolution.h"
207330f729Sjoerg #include "llvm/Analysis/ScalarEvolutionExpressions.h"
217330f729Sjoerg #include "llvm/IR/Constants.h"
227330f729Sjoerg #include "llvm/IR/DerivedTypes.h"
237330f729Sjoerg #include "llvm/IR/Function.h"
247330f729Sjoerg #include "llvm/IR/InstIterator.h"
257330f729Sjoerg #include "llvm/IR/Instructions.h"
267330f729Sjoerg #include "llvm/IR/LLVMContext.h"
27*82d56013Sjoerg #include "llvm/IR/PassManager.h"
287330f729Sjoerg #include "llvm/IR/Type.h"
29*82d56013Sjoerg #include "llvm/InitializePasses.h"
307330f729Sjoerg #include "llvm/Pass.h"
317330f729Sjoerg #include "llvm/Support/Debug.h"
327330f729Sjoerg #include "llvm/Support/raw_ostream.h"
337330f729Sjoerg 
347330f729Sjoerg using namespace llvm;
357330f729Sjoerg 
367330f729Sjoerg #define DL_NAME "delinearize"
377330f729Sjoerg #define DEBUG_TYPE DL_NAME
387330f729Sjoerg 
397330f729Sjoerg namespace {
407330f729Sjoerg 
417330f729Sjoerg class Delinearization : public FunctionPass {
427330f729Sjoerg   Delinearization(const Delinearization &); // do not implement
437330f729Sjoerg protected:
447330f729Sjoerg   Function *F;
457330f729Sjoerg   LoopInfo *LI;
467330f729Sjoerg   ScalarEvolution *SE;
477330f729Sjoerg 
487330f729Sjoerg public:
497330f729Sjoerg   static char ID; // Pass identification, replacement for typeid
507330f729Sjoerg 
Delinearization()517330f729Sjoerg   Delinearization() : FunctionPass(ID) {
527330f729Sjoerg     initializeDelinearizationPass(*PassRegistry::getPassRegistry());
537330f729Sjoerg   }
547330f729Sjoerg   bool runOnFunction(Function &F) override;
557330f729Sjoerg   void getAnalysisUsage(AnalysisUsage &AU) const override;
567330f729Sjoerg   void print(raw_ostream &O, const Module *M = nullptr) const override;
577330f729Sjoerg };
587330f729Sjoerg 
printDelinearization(raw_ostream & O,Function * F,LoopInfo * LI,ScalarEvolution * SE)59*82d56013Sjoerg void printDelinearization(raw_ostream &O, Function *F, LoopInfo *LI,
60*82d56013Sjoerg                           ScalarEvolution *SE) {
617330f729Sjoerg   O << "Delinearization on function " << F->getName() << ":\n";
62*82d56013Sjoerg   for (Instruction &Inst : instructions(F)) {
637330f729Sjoerg     // Only analyze loads and stores.
64*82d56013Sjoerg     if (!isa<StoreInst>(&Inst) && !isa<LoadInst>(&Inst) &&
65*82d56013Sjoerg         !isa<GetElementPtrInst>(&Inst))
667330f729Sjoerg       continue;
677330f729Sjoerg 
68*82d56013Sjoerg     const BasicBlock *BB = Inst.getParent();
697330f729Sjoerg     // Delinearize the memory access as analyzed in all the surrounding loops.
707330f729Sjoerg     // Do not analyze memory accesses outside loops.
717330f729Sjoerg     for (Loop *L = LI->getLoopFor(BB); L != nullptr; L = L->getParentLoop()) {
72*82d56013Sjoerg       const SCEV *AccessFn = SE->getSCEVAtScope(getPointerOperand(&Inst), L);
737330f729Sjoerg 
747330f729Sjoerg       const SCEVUnknown *BasePointer =
757330f729Sjoerg           dyn_cast<SCEVUnknown>(SE->getPointerBase(AccessFn));
767330f729Sjoerg       // Do not delinearize if we cannot find the base pointer.
777330f729Sjoerg       if (!BasePointer)
787330f729Sjoerg         break;
797330f729Sjoerg       AccessFn = SE->getMinusSCEV(AccessFn, BasePointer);
807330f729Sjoerg 
817330f729Sjoerg       O << "\n";
82*82d56013Sjoerg       O << "Inst:" << Inst << "\n";
837330f729Sjoerg       O << "In Loop with Header: " << L->getHeader()->getName() << "\n";
847330f729Sjoerg       O << "AccessFunction: " << *AccessFn << "\n";
857330f729Sjoerg 
867330f729Sjoerg       SmallVector<const SCEV *, 3> Subscripts, Sizes;
87*82d56013Sjoerg       SE->delinearize(AccessFn, Subscripts, Sizes, SE->getElementSize(&Inst));
887330f729Sjoerg       if (Subscripts.size() == 0 || Sizes.size() == 0 ||
897330f729Sjoerg           Subscripts.size() != Sizes.size()) {
907330f729Sjoerg         O << "failed to delinearize\n";
917330f729Sjoerg         continue;
927330f729Sjoerg       }
937330f729Sjoerg 
947330f729Sjoerg       O << "Base offset: " << *BasePointer << "\n";
957330f729Sjoerg       O << "ArrayDecl[UnknownSize]";
967330f729Sjoerg       int Size = Subscripts.size();
977330f729Sjoerg       for (int i = 0; i < Size - 1; i++)
987330f729Sjoerg         O << "[" << *Sizes[i] << "]";
997330f729Sjoerg       O << " with elements of " << *Sizes[Size - 1] << " bytes.\n";
1007330f729Sjoerg 
1017330f729Sjoerg       O << "ArrayRef";
1027330f729Sjoerg       for (int i = 0; i < Size; i++)
1037330f729Sjoerg         O << "[" << *Subscripts[i] << "]";
1047330f729Sjoerg       O << "\n";
1057330f729Sjoerg     }
1067330f729Sjoerg   }
1077330f729Sjoerg }
1087330f729Sjoerg 
109*82d56013Sjoerg } // end anonymous namespace
110*82d56013Sjoerg 
getAnalysisUsage(AnalysisUsage & AU) const111*82d56013Sjoerg void Delinearization::getAnalysisUsage(AnalysisUsage &AU) const {
112*82d56013Sjoerg   AU.setPreservesAll();
113*82d56013Sjoerg   AU.addRequired<LoopInfoWrapperPass>();
114*82d56013Sjoerg   AU.addRequired<ScalarEvolutionWrapperPass>();
115*82d56013Sjoerg }
116*82d56013Sjoerg 
runOnFunction(Function & F)117*82d56013Sjoerg bool Delinearization::runOnFunction(Function &F) {
118*82d56013Sjoerg   this->F = &F;
119*82d56013Sjoerg   SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
120*82d56013Sjoerg   LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
121*82d56013Sjoerg   return false;
122*82d56013Sjoerg }
123*82d56013Sjoerg 
print(raw_ostream & O,const Module *) const124*82d56013Sjoerg void Delinearization::print(raw_ostream &O, const Module *) const {
125*82d56013Sjoerg   printDelinearization(O, F, LI, SE);
126*82d56013Sjoerg }
127*82d56013Sjoerg 
1287330f729Sjoerg char Delinearization::ID = 0;
1297330f729Sjoerg static const char delinearization_name[] = "Delinearization";
INITIALIZE_PASS_BEGIN(Delinearization,DL_NAME,delinearization_name,true,true)1307330f729Sjoerg INITIALIZE_PASS_BEGIN(Delinearization, DL_NAME, delinearization_name, true,
1317330f729Sjoerg                       true)
1327330f729Sjoerg INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
1337330f729Sjoerg INITIALIZE_PASS_END(Delinearization, DL_NAME, delinearization_name, true, true)
1347330f729Sjoerg 
1357330f729Sjoerg FunctionPass *llvm::createDelinearizationPass() { return new Delinearization; }
136*82d56013Sjoerg 
DelinearizationPrinterPass(raw_ostream & OS)137*82d56013Sjoerg DelinearizationPrinterPass::DelinearizationPrinterPass(raw_ostream &OS)
138*82d56013Sjoerg     : OS(OS) {}
run(Function & F,FunctionAnalysisManager & AM)139*82d56013Sjoerg PreservedAnalyses DelinearizationPrinterPass::run(Function &F,
140*82d56013Sjoerg                                                   FunctionAnalysisManager &AM) {
141*82d56013Sjoerg   printDelinearization(OS, &F, &AM.getResult<LoopAnalysis>(F),
142*82d56013Sjoerg                        &AM.getResult<ScalarEvolutionAnalysis>(F));
143*82d56013Sjoerg   return PreservedAnalyses::all();
144*82d56013Sjoerg }
145