Delinearization.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631
  1. //===---- Delinearization.cpp - MultiDimensional Index Delinearization ----===//
  2. //
  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
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  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.
  13. //
  14. //===----------------------------------------------------------------------===//
  15. #include "llvm/Analysis/Delinearization.h"
  16. #include "llvm/Analysis/LoopInfo.h"
  17. #include "llvm/Analysis/Passes.h"
  18. #include "llvm/Analysis/ScalarEvolution.h"
  19. #include "llvm/Analysis/ScalarEvolutionDivision.h"
  20. #include "llvm/Analysis/ScalarEvolutionExpressions.h"
  21. #include "llvm/IR/Constants.h"
  22. #include "llvm/IR/DerivedTypes.h"
  23. #include "llvm/IR/Function.h"
  24. #include "llvm/IR/InstIterator.h"
  25. #include "llvm/IR/Instructions.h"
  26. #include "llvm/IR/LLVMContext.h"
  27. #include "llvm/IR/PassManager.h"
  28. #include "llvm/IR/Type.h"
  29. #include "llvm/InitializePasses.h"
  30. #include "llvm/Pass.h"
  31. #include "llvm/Support/Debug.h"
  32. #include "llvm/Support/raw_ostream.h"
  33. using namespace llvm;
  34. #define DL_NAME "delinearize"
  35. #define DEBUG_TYPE DL_NAME
  36. // Return true when S contains at least an undef value.
  37. static inline bool containsUndefs(const SCEV *S) {
  38. return SCEVExprContains(S, [](const SCEV *S) {
  39. if (const auto *SU = dyn_cast<SCEVUnknown>(S))
  40. return isa<UndefValue>(SU->getValue());
  41. return false;
  42. });
  43. }
  44. namespace {
  45. // Collect all steps of SCEV expressions.
  46. struct SCEVCollectStrides {
  47. ScalarEvolution &SE;
  48. SmallVectorImpl<const SCEV *> &Strides;
  49. SCEVCollectStrides(ScalarEvolution &SE, SmallVectorImpl<const SCEV *> &S)
  50. : SE(SE), Strides(S) {}
  51. bool follow(const SCEV *S) {
  52. if (const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(S))
  53. Strides.push_back(AR->getStepRecurrence(SE));
  54. return true;
  55. }
  56. bool isDone() const { return false; }
  57. };
  58. // Collect all SCEVUnknown and SCEVMulExpr expressions.
  59. struct SCEVCollectTerms {
  60. SmallVectorImpl<const SCEV *> &Terms;
  61. SCEVCollectTerms(SmallVectorImpl<const SCEV *> &T) : Terms(T) {}
  62. bool follow(const SCEV *S) {
  63. if (isa<SCEVUnknown>(S) || isa<SCEVMulExpr>(S) ||
  64. isa<SCEVSignExtendExpr>(S)) {
  65. if (!containsUndefs(S))
  66. Terms.push_back(S);
  67. // Stop recursion: once we collected a term, do not walk its operands.
  68. return false;
  69. }
  70. // Keep looking.
  71. return true;
  72. }
  73. bool isDone() const { return false; }
  74. };
  75. // Check if a SCEV contains an AddRecExpr.
  76. struct SCEVHasAddRec {
  77. bool &ContainsAddRec;
  78. SCEVHasAddRec(bool &ContainsAddRec) : ContainsAddRec(ContainsAddRec) {
  79. ContainsAddRec = false;
  80. }
  81. bool follow(const SCEV *S) {
  82. if (isa<SCEVAddRecExpr>(S)) {
  83. ContainsAddRec = true;
  84. // Stop recursion: once we collected a term, do not walk its operands.
  85. return false;
  86. }
  87. // Keep looking.
  88. return true;
  89. }
  90. bool isDone() const { return false; }
  91. };
  92. // Find factors that are multiplied with an expression that (possibly as a
  93. // subexpression) contains an AddRecExpr. In the expression:
  94. //
  95. // 8 * (100 + %p * %q * (%a + {0, +, 1}_loop))
  96. //
  97. // "%p * %q" are factors multiplied by the expression "(%a + {0, +, 1}_loop)"
  98. // that contains the AddRec {0, +, 1}_loop. %p * %q are likely to be array size
  99. // parameters as they form a product with an induction variable.
  100. //
  101. // This collector expects all array size parameters to be in the same MulExpr.
  102. // It might be necessary to later add support for collecting parameters that are
  103. // spread over different nested MulExpr.
  104. struct SCEVCollectAddRecMultiplies {
  105. SmallVectorImpl<const SCEV *> &Terms;
  106. ScalarEvolution &SE;
  107. SCEVCollectAddRecMultiplies(SmallVectorImpl<const SCEV *> &T,
  108. ScalarEvolution &SE)
  109. : Terms(T), SE(SE) {}
  110. bool follow(const SCEV *S) {
  111. if (auto *Mul = dyn_cast<SCEVMulExpr>(S)) {
  112. bool HasAddRec = false;
  113. SmallVector<const SCEV *, 0> Operands;
  114. for (auto Op : Mul->operands()) {
  115. const SCEVUnknown *Unknown = dyn_cast<SCEVUnknown>(Op);
  116. if (Unknown && !isa<CallInst>(Unknown->getValue())) {
  117. Operands.push_back(Op);
  118. } else if (Unknown) {
  119. HasAddRec = true;
  120. } else {
  121. bool ContainsAddRec = false;
  122. SCEVHasAddRec ContiansAddRec(ContainsAddRec);
  123. visitAll(Op, ContiansAddRec);
  124. HasAddRec |= ContainsAddRec;
  125. }
  126. }
  127. if (Operands.size() == 0)
  128. return true;
  129. if (!HasAddRec)
  130. return false;
  131. Terms.push_back(SE.getMulExpr(Operands));
  132. // Stop recursion: once we collected a term, do not walk its operands.
  133. return false;
  134. }
  135. // Keep looking.
  136. return true;
  137. }
  138. bool isDone() const { return false; }
  139. };
  140. } // end anonymous namespace
  141. /// Find parametric terms in this SCEVAddRecExpr. We first for parameters in
  142. /// two places:
  143. /// 1) The strides of AddRec expressions.
  144. /// 2) Unknowns that are multiplied with AddRec expressions.
  145. void llvm::collectParametricTerms(ScalarEvolution &SE, const SCEV *Expr,
  146. SmallVectorImpl<const SCEV *> &Terms) {
  147. SmallVector<const SCEV *, 4> Strides;
  148. SCEVCollectStrides StrideCollector(SE, Strides);
  149. visitAll(Expr, StrideCollector);
  150. LLVM_DEBUG({
  151. dbgs() << "Strides:\n";
  152. for (const SCEV *S : Strides)
  153. dbgs() << *S << "\n";
  154. });
  155. for (const SCEV *S : Strides) {
  156. SCEVCollectTerms TermCollector(Terms);
  157. visitAll(S, TermCollector);
  158. }
  159. LLVM_DEBUG({
  160. dbgs() << "Terms:\n";
  161. for (const SCEV *T : Terms)
  162. dbgs() << *T << "\n";
  163. });
  164. SCEVCollectAddRecMultiplies MulCollector(Terms, SE);
  165. visitAll(Expr, MulCollector);
  166. }
  167. static bool findArrayDimensionsRec(ScalarEvolution &SE,
  168. SmallVectorImpl<const SCEV *> &Terms,
  169. SmallVectorImpl<const SCEV *> &Sizes) {
  170. int Last = Terms.size() - 1;
  171. const SCEV *Step = Terms[Last];
  172. // End of recursion.
  173. if (Last == 0) {
  174. if (const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(Step)) {
  175. SmallVector<const SCEV *, 2> Qs;
  176. for (const SCEV *Op : M->operands())
  177. if (!isa<SCEVConstant>(Op))
  178. Qs.push_back(Op);
  179. Step = SE.getMulExpr(Qs);
  180. }
  181. Sizes.push_back(Step);
  182. return true;
  183. }
  184. for (const SCEV *&Term : Terms) {
  185. // Normalize the terms before the next call to findArrayDimensionsRec.
  186. const SCEV *Q, *R;
  187. SCEVDivision::divide(SE, Term, Step, &Q, &R);
  188. // Bail out when GCD does not evenly divide one of the terms.
  189. if (!R->isZero())
  190. return false;
  191. Term = Q;
  192. }
  193. // Remove all SCEVConstants.
  194. erase_if(Terms, [](const SCEV *E) { return isa<SCEVConstant>(E); });
  195. if (Terms.size() > 0)
  196. if (!findArrayDimensionsRec(SE, Terms, Sizes))
  197. return false;
  198. Sizes.push_back(Step);
  199. return true;
  200. }
  201. // Returns true when one of the SCEVs of Terms contains a SCEVUnknown parameter.
  202. static inline bool containsParameters(SmallVectorImpl<const SCEV *> &Terms) {
  203. for (const SCEV *T : Terms)
  204. if (SCEVExprContains(T, [](const SCEV *S) { return isa<SCEVUnknown>(S); }))
  205. return true;
  206. return false;
  207. }
  208. // Return the number of product terms in S.
  209. static inline int numberOfTerms(const SCEV *S) {
  210. if (const SCEVMulExpr *Expr = dyn_cast<SCEVMulExpr>(S))
  211. return Expr->getNumOperands();
  212. return 1;
  213. }
  214. static const SCEV *removeConstantFactors(ScalarEvolution &SE, const SCEV *T) {
  215. if (isa<SCEVConstant>(T))
  216. return nullptr;
  217. if (isa<SCEVUnknown>(T))
  218. return T;
  219. if (const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(T)) {
  220. SmallVector<const SCEV *, 2> Factors;
  221. for (const SCEV *Op : M->operands())
  222. if (!isa<SCEVConstant>(Op))
  223. Factors.push_back(Op);
  224. return SE.getMulExpr(Factors);
  225. }
  226. return T;
  227. }
  228. void llvm::findArrayDimensions(ScalarEvolution &SE,
  229. SmallVectorImpl<const SCEV *> &Terms,
  230. SmallVectorImpl<const SCEV *> &Sizes,
  231. const SCEV *ElementSize) {
  232. if (Terms.size() < 1 || !ElementSize)
  233. return;
  234. // Early return when Terms do not contain parameters: we do not delinearize
  235. // non parametric SCEVs.
  236. if (!containsParameters(Terms))
  237. return;
  238. LLVM_DEBUG({
  239. dbgs() << "Terms:\n";
  240. for (const SCEV *T : Terms)
  241. dbgs() << *T << "\n";
  242. });
  243. // Remove duplicates.
  244. array_pod_sort(Terms.begin(), Terms.end());
  245. Terms.erase(std::unique(Terms.begin(), Terms.end()), Terms.end());
  246. // Put larger terms first.
  247. llvm::sort(Terms, [](const SCEV *LHS, const SCEV *RHS) {
  248. return numberOfTerms(LHS) > numberOfTerms(RHS);
  249. });
  250. // Try to divide all terms by the element size. If term is not divisible by
  251. // element size, proceed with the original term.
  252. for (const SCEV *&Term : Terms) {
  253. const SCEV *Q, *R;
  254. SCEVDivision::divide(SE, Term, ElementSize, &Q, &R);
  255. if (!Q->isZero())
  256. Term = Q;
  257. }
  258. SmallVector<const SCEV *, 4> NewTerms;
  259. // Remove constant factors.
  260. for (const SCEV *T : Terms)
  261. if (const SCEV *NewT = removeConstantFactors(SE, T))
  262. NewTerms.push_back(NewT);
  263. LLVM_DEBUG({
  264. dbgs() << "Terms after sorting:\n";
  265. for (const SCEV *T : NewTerms)
  266. dbgs() << *T << "\n";
  267. });
  268. if (NewTerms.empty() || !findArrayDimensionsRec(SE, NewTerms, Sizes)) {
  269. Sizes.clear();
  270. return;
  271. }
  272. // The last element to be pushed into Sizes is the size of an element.
  273. Sizes.push_back(ElementSize);
  274. LLVM_DEBUG({
  275. dbgs() << "Sizes:\n";
  276. for (const SCEV *S : Sizes)
  277. dbgs() << *S << "\n";
  278. });
  279. }
  280. void llvm::computeAccessFunctions(ScalarEvolution &SE, const SCEV *Expr,
  281. SmallVectorImpl<const SCEV *> &Subscripts,
  282. SmallVectorImpl<const SCEV *> &Sizes) {
  283. // Early exit in case this SCEV is not an affine multivariate function.
  284. if (Sizes.empty())
  285. return;
  286. if (auto *AR = dyn_cast<SCEVAddRecExpr>(Expr))
  287. if (!AR->isAffine())
  288. return;
  289. const SCEV *Res = Expr;
  290. int Last = Sizes.size() - 1;
  291. for (int i = Last; i >= 0; i--) {
  292. const SCEV *Q, *R;
  293. SCEVDivision::divide(SE, Res, Sizes[i], &Q, &R);
  294. LLVM_DEBUG({
  295. dbgs() << "Res: " << *Res << "\n";
  296. dbgs() << "Sizes[i]: " << *Sizes[i] << "\n";
  297. dbgs() << "Res divided by Sizes[i]:\n";
  298. dbgs() << "Quotient: " << *Q << "\n";
  299. dbgs() << "Remainder: " << *R << "\n";
  300. });
  301. Res = Q;
  302. // Do not record the last subscript corresponding to the size of elements in
  303. // the array.
  304. if (i == Last) {
  305. // Bail out if the byte offset is non-zero.
  306. if (!R->isZero()) {
  307. Subscripts.clear();
  308. Sizes.clear();
  309. return;
  310. }
  311. continue;
  312. }
  313. // Record the access function for the current subscript.
  314. Subscripts.push_back(R);
  315. }
  316. // Also push in last position the remainder of the last division: it will be
  317. // the access function of the innermost dimension.
  318. Subscripts.push_back(Res);
  319. std::reverse(Subscripts.begin(), Subscripts.end());
  320. LLVM_DEBUG({
  321. dbgs() << "Subscripts:\n";
  322. for (const SCEV *S : Subscripts)
  323. dbgs() << *S << "\n";
  324. });
  325. }
  326. /// Splits the SCEV into two vectors of SCEVs representing the subscripts and
  327. /// sizes of an array access. Returns the remainder of the delinearization that
  328. /// is the offset start of the array. The SCEV->delinearize algorithm computes
  329. /// the multiples of SCEV coefficients: that is a pattern matching of sub
  330. /// expressions in the stride and base of a SCEV corresponding to the
  331. /// computation of a GCD (greatest common divisor) of base and stride. When
  332. /// SCEV->delinearize fails, it returns the SCEV unchanged.
  333. ///
  334. /// For example: when analyzing the memory access A[i][j][k] in this loop nest
  335. ///
  336. /// void foo(long n, long m, long o, double A[n][m][o]) {
  337. ///
  338. /// for (long i = 0; i < n; i++)
  339. /// for (long j = 0; j < m; j++)
  340. /// for (long k = 0; k < o; k++)
  341. /// A[i][j][k] = 1.0;
  342. /// }
  343. ///
  344. /// the delinearization input is the following AddRec SCEV:
  345. ///
  346. /// AddRec: {{{%A,+,(8 * %m * %o)}<%for.i>,+,(8 * %o)}<%for.j>,+,8}<%for.k>
  347. ///
  348. /// From this SCEV, we are able to say that the base offset of the access is %A
  349. /// because it appears as an offset that does not divide any of the strides in
  350. /// the loops:
  351. ///
  352. /// CHECK: Base offset: %A
  353. ///
  354. /// and then SCEV->delinearize determines the size of some of the dimensions of
  355. /// the array as these are the multiples by which the strides are happening:
  356. ///
  357. /// CHECK: ArrayDecl[UnknownSize][%m][%o] with elements of sizeof(double)
  358. /// bytes.
  359. ///
  360. /// Note that the outermost dimension remains of UnknownSize because there are
  361. /// no strides that would help identifying the size of the last dimension: when
  362. /// the array has been statically allocated, one could compute the size of that
  363. /// dimension by dividing the overall size of the array by the size of the known
  364. /// dimensions: %m * %o * 8.
  365. ///
  366. /// Finally delinearize provides the access functions for the array reference
  367. /// that does correspond to A[i][j][k] of the above C testcase:
  368. ///
  369. /// CHECK: ArrayRef[{0,+,1}<%for.i>][{0,+,1}<%for.j>][{0,+,1}<%for.k>]
  370. ///
  371. /// The testcases are checking the output of a function pass:
  372. /// DelinearizationPass that walks through all loads and stores of a function
  373. /// asking for the SCEV of the memory access with respect to all enclosing
  374. /// loops, calling SCEV->delinearize on that and printing the results.
  375. void llvm::delinearize(ScalarEvolution &SE, const SCEV *Expr,
  376. SmallVectorImpl<const SCEV *> &Subscripts,
  377. SmallVectorImpl<const SCEV *> &Sizes,
  378. const SCEV *ElementSize) {
  379. // First step: collect parametric terms.
  380. SmallVector<const SCEV *, 4> Terms;
  381. collectParametricTerms(SE, Expr, Terms);
  382. if (Terms.empty())
  383. return;
  384. // Second step: find subscript sizes.
  385. findArrayDimensions(SE, Terms, Sizes, ElementSize);
  386. if (Sizes.empty())
  387. return;
  388. // Third step: compute the access functions for each subscript.
  389. computeAccessFunctions(SE, Expr, Subscripts, Sizes);
  390. if (Subscripts.empty())
  391. return;
  392. LLVM_DEBUG({
  393. dbgs() << "succeeded to delinearize " << *Expr << "\n";
  394. dbgs() << "ArrayDecl[UnknownSize]";
  395. for (const SCEV *S : Sizes)
  396. dbgs() << "[" << *S << "]";
  397. dbgs() << "\nArrayRef";
  398. for (const SCEV *S : Subscripts)
  399. dbgs() << "[" << *S << "]";
  400. dbgs() << "\n";
  401. });
  402. }
  403. bool llvm::getIndexExpressionsFromGEP(ScalarEvolution &SE,
  404. const GetElementPtrInst *GEP,
  405. SmallVectorImpl<const SCEV *> &Subscripts,
  406. SmallVectorImpl<int> &Sizes) {
  407. assert(Subscripts.empty() && Sizes.empty() &&
  408. "Expected output lists to be empty on entry to this function.");
  409. assert(GEP && "getIndexExpressionsFromGEP called with a null GEP");
  410. Type *Ty = nullptr;
  411. bool DroppedFirstDim = false;
  412. for (unsigned i = 1; i < GEP->getNumOperands(); i++) {
  413. const SCEV *Expr = SE.getSCEV(GEP->getOperand(i));
  414. if (i == 1) {
  415. Ty = GEP->getSourceElementType();
  416. if (auto *Const = dyn_cast<SCEVConstant>(Expr))
  417. if (Const->getValue()->isZero()) {
  418. DroppedFirstDim = true;
  419. continue;
  420. }
  421. Subscripts.push_back(Expr);
  422. continue;
  423. }
  424. auto *ArrayTy = dyn_cast<ArrayType>(Ty);
  425. if (!ArrayTy) {
  426. Subscripts.clear();
  427. Sizes.clear();
  428. return false;
  429. }
  430. Subscripts.push_back(Expr);
  431. if (!(DroppedFirstDim && i == 2))
  432. Sizes.push_back(ArrayTy->getNumElements());
  433. Ty = ArrayTy->getElementType();
  434. }
  435. return !Subscripts.empty();
  436. }
  437. namespace {
  438. class Delinearization : public FunctionPass {
  439. Delinearization(const Delinearization &); // do not implement
  440. protected:
  441. Function *F;
  442. LoopInfo *LI;
  443. ScalarEvolution *SE;
  444. public:
  445. static char ID; // Pass identification, replacement for typeid
  446. Delinearization() : FunctionPass(ID) {
  447. initializeDelinearizationPass(*PassRegistry::getPassRegistry());
  448. }
  449. bool runOnFunction(Function &F) override;
  450. void getAnalysisUsage(AnalysisUsage &AU) const override;
  451. void print(raw_ostream &O, const Module *M = nullptr) const override;
  452. };
  453. void printDelinearization(raw_ostream &O, Function *F, LoopInfo *LI,
  454. ScalarEvolution *SE) {
  455. O << "Delinearization on function " << F->getName() << ":\n";
  456. for (Instruction &Inst : instructions(F)) {
  457. // Only analyze loads and stores.
  458. if (!isa<StoreInst>(&Inst) && !isa<LoadInst>(&Inst) &&
  459. !isa<GetElementPtrInst>(&Inst))
  460. continue;
  461. const BasicBlock *BB = Inst.getParent();
  462. // Delinearize the memory access as analyzed in all the surrounding loops.
  463. // Do not analyze memory accesses outside loops.
  464. for (Loop *L = LI->getLoopFor(BB); L != nullptr; L = L->getParentLoop()) {
  465. const SCEV *AccessFn = SE->getSCEVAtScope(getPointerOperand(&Inst), L);
  466. const SCEVUnknown *BasePointer =
  467. dyn_cast<SCEVUnknown>(SE->getPointerBase(AccessFn));
  468. // Do not delinearize if we cannot find the base pointer.
  469. if (!BasePointer)
  470. break;
  471. AccessFn = SE->getMinusSCEV(AccessFn, BasePointer);
  472. O << "\n";
  473. O << "Inst:" << Inst << "\n";
  474. O << "In Loop with Header: " << L->getHeader()->getName() << "\n";
  475. O << "AccessFunction: " << *AccessFn << "\n";
  476. SmallVector<const SCEV *, 3> Subscripts, Sizes;
  477. delinearize(*SE, AccessFn, Subscripts, Sizes, SE->getElementSize(&Inst));
  478. if (Subscripts.size() == 0 || Sizes.size() == 0 ||
  479. Subscripts.size() != Sizes.size()) {
  480. O << "failed to delinearize\n";
  481. continue;
  482. }
  483. O << "Base offset: " << *BasePointer << "\n";
  484. O << "ArrayDecl[UnknownSize]";
  485. int Size = Subscripts.size();
  486. for (int i = 0; i < Size - 1; i++)
  487. O << "[" << *Sizes[i] << "]";
  488. O << " with elements of " << *Sizes[Size - 1] << " bytes.\n";
  489. O << "ArrayRef";
  490. for (int i = 0; i < Size; i++)
  491. O << "[" << *Subscripts[i] << "]";
  492. O << "\n";
  493. }
  494. }
  495. }
  496. } // end anonymous namespace
  497. void Delinearization::getAnalysisUsage(AnalysisUsage &AU) const {
  498. AU.setPreservesAll();
  499. AU.addRequired<LoopInfoWrapperPass>();
  500. AU.addRequired<ScalarEvolutionWrapperPass>();
  501. }
  502. bool Delinearization::runOnFunction(Function &F) {
  503. this->F = &F;
  504. SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
  505. LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
  506. return false;
  507. }
  508. void Delinearization::print(raw_ostream &O, const Module *) const {
  509. printDelinearization(O, F, LI, SE);
  510. }
  511. char Delinearization::ID = 0;
  512. static const char delinearization_name[] = "Delinearization";
  513. INITIALIZE_PASS_BEGIN(Delinearization, DL_NAME, delinearization_name, true,
  514. true)
  515. INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
  516. INITIALIZE_PASS_END(Delinearization, DL_NAME, delinearization_name, true, true)
  517. FunctionPass *llvm::createDelinearizationPass() { return new Delinearization; }
  518. DelinearizationPrinterPass::DelinearizationPrinterPass(raw_ostream &OS)
  519. : OS(OS) {}
  520. PreservedAnalyses DelinearizationPrinterPass::run(Function &F,
  521. FunctionAnalysisManager &AM) {
  522. printDelinearization(OS, &F, &AM.getResult<LoopAnalysis>(F),
  523. &AM.getResult<ScalarEvolutionAnalysis>(F));
  524. return PreservedAnalyses::all();
  525. }