Delinearization.cpp 21 KB

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