1 //===---- Delinearization.cpp - MultiDimensional Index Delinearization ----===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This implements an analysis pass that tries to delinearize all GEP
10 // instructions in all loops using the SCEV analysis functionality. This pass is
11 // only used for testing purposes: if your pass needs delinearization, please
12 // use the on-demand SCEVAddRecExpr::delinearize() function.
14 //===----------------------------------------------------------------------===//
16 #include "llvm/Analysis/LoopInfo.h"
17 #include "llvm/Analysis/Passes.h"
18 #include "llvm/Analysis/ScalarEvolution.h"
19 #include "llvm/Analysis/ScalarEvolutionExpressions.h"
20 #include "llvm/IR/Constants.h"
21 #include "llvm/IR/DerivedTypes.h"
22 #include "llvm/IR/Function.h"
23 #include "llvm/IR/InstIterator.h"
24 #include "llvm/IR/Instructions.h"
25 #include "llvm/IR/LLVMContext.h"
26 #include "llvm/IR/Type.h"
27 #include "llvm/Pass.h"
28 #include "llvm/Support/Debug.h"
29 #include "llvm/Support/raw_ostream.h"
33 #define DL_NAME "delinearize"
34 #define DEBUG_TYPE DL_NAME
38 class Delinearization
: public FunctionPass
{
39 Delinearization(const Delinearization
&); // do not implement
46 static char ID
; // Pass identification, replacement for typeid
48 Delinearization() : FunctionPass(ID
) {
49 initializeDelinearizationPass(*PassRegistry::getPassRegistry());
51 bool runOnFunction(Function
&F
) override
;
52 void getAnalysisUsage(AnalysisUsage
&AU
) const override
;
53 void print(raw_ostream
&O
, const Module
*M
= nullptr) const override
;
56 } // end anonymous namespace
58 void Delinearization::getAnalysisUsage(AnalysisUsage
&AU
) const {
60 AU
.addRequired
<LoopInfoWrapperPass
>();
61 AU
.addRequired
<ScalarEvolutionWrapperPass
>();
64 bool Delinearization::runOnFunction(Function
&F
) {
66 SE
= &getAnalysis
<ScalarEvolutionWrapperPass
>().getSE();
67 LI
= &getAnalysis
<LoopInfoWrapperPass
>().getLoopInfo();
71 void Delinearization::print(raw_ostream
&O
, const Module
*) const {
72 O
<< "Delinearization on function " << F
->getName() << ":\n";
73 for (inst_iterator I
= inst_begin(F
), E
= inst_end(F
); I
!= E
; ++I
) {
74 Instruction
*Inst
= &(*I
);
76 // Only analyze loads and stores.
77 if (!isa
<StoreInst
>(Inst
) && !isa
<LoadInst
>(Inst
) &&
78 !isa
<GetElementPtrInst
>(Inst
))
81 const BasicBlock
*BB
= Inst
->getParent();
82 // Delinearize the memory access as analyzed in all the surrounding loops.
83 // Do not analyze memory accesses outside loops.
84 for (Loop
*L
= LI
->getLoopFor(BB
); L
!= nullptr; L
= L
->getParentLoop()) {
85 const SCEV
*AccessFn
= SE
->getSCEVAtScope(getPointerOperand(Inst
), L
);
87 const SCEVUnknown
*BasePointer
=
88 dyn_cast
<SCEVUnknown
>(SE
->getPointerBase(AccessFn
));
89 // Do not delinearize if we cannot find the base pointer.
92 AccessFn
= SE
->getMinusSCEV(AccessFn
, BasePointer
);
95 O
<< "Inst:" << *Inst
<< "\n";
96 O
<< "In Loop with Header: " << L
->getHeader()->getName() << "\n";
97 O
<< "AccessFunction: " << *AccessFn
<< "\n";
99 SmallVector
<const SCEV
*, 3> Subscripts
, Sizes
;
100 SE
->delinearize(AccessFn
, Subscripts
, Sizes
, SE
->getElementSize(Inst
));
101 if (Subscripts
.size() == 0 || Sizes
.size() == 0 ||
102 Subscripts
.size() != Sizes
.size()) {
103 O
<< "failed to delinearize\n";
107 O
<< "Base offset: " << *BasePointer
<< "\n";
108 O
<< "ArrayDecl[UnknownSize]";
109 int Size
= Subscripts
.size();
110 for (int i
= 0; i
< Size
- 1; i
++)
111 O
<< "[" << *Sizes
[i
] << "]";
112 O
<< " with elements of " << *Sizes
[Size
- 1] << " bytes.\n";
115 for (int i
= 0; i
< Size
; i
++)
116 O
<< "[" << *Subscripts
[i
] << "]";
122 char Delinearization::ID
= 0;
123 static const char delinearization_name
[] = "Delinearization";
124 INITIALIZE_PASS_BEGIN(Delinearization
, DL_NAME
, delinearization_name
, true,
126 INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass
)
127 INITIALIZE_PASS_END(Delinearization
, DL_NAME
, delinearization_name
, true, true)
129 FunctionPass
*llvm::createDelinearizationPass() { return new Delinearization
; }