Delinearization.h 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===---- Delinearization.h - MultiDimensional Index Delinearization ------===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // This implements an analysis pass that tries to delinearize all GEP
  15. // instructions in all loops using the SCEV analysis functionality. This pass is
  16. // only used for testing purposes: if your pass needs delinearization, please
  17. // use the on-demand SCEVAddRecExpr::delinearize() function.
  18. //
  19. //===----------------------------------------------------------------------===//
  20. #ifndef LLVM_ANALYSIS_DELINEARIZATION_H
  21. #define LLVM_ANALYSIS_DELINEARIZATION_H
  22. #include "llvm/IR/PassManager.h"
  23. namespace llvm {
  24. class raw_ostream;
  25. template <typename T> class SmallVectorImpl;
  26. class GetElementPtrInst;
  27. class ScalarEvolution;
  28. class SCEV;
  29. /// Compute the array dimensions Sizes from the set of Terms extracted from
  30. /// the memory access function of this SCEVAddRecExpr (second step of
  31. /// delinearization).
  32. void findArrayDimensions(ScalarEvolution &SE,
  33. SmallVectorImpl<const SCEV *> &Terms,
  34. SmallVectorImpl<const SCEV *> &Sizes,
  35. const SCEV *ElementSize);
  36. /// Collect parametric terms occurring in step expressions (first step of
  37. /// delinearization).
  38. void collectParametricTerms(ScalarEvolution &SE, const SCEV *Expr,
  39. SmallVectorImpl<const SCEV *> &Terms);
  40. /// Return in Subscripts the access functions for each dimension in Sizes
  41. /// (third step of delinearization).
  42. void computeAccessFunctions(ScalarEvolution &SE, const SCEV *Expr,
  43. SmallVectorImpl<const SCEV *> &Subscripts,
  44. SmallVectorImpl<const SCEV *> &Sizes);
  45. /// Split this SCEVAddRecExpr into two vectors of SCEVs representing the
  46. /// subscripts and sizes of an array access.
  47. ///
  48. /// The delinearization is a 3 step process: the first two steps compute the
  49. /// sizes of each subscript and the third step computes the access functions
  50. /// for the delinearized array:
  51. ///
  52. /// 1. Find the terms in the step functions
  53. /// 2. Compute the array size
  54. /// 3. Compute the access function: divide the SCEV by the array size
  55. /// starting with the innermost dimensions found in step 2. The Quotient
  56. /// is the SCEV to be divided in the next step of the recursion. The
  57. /// Remainder is the subscript of the innermost dimension. Loop over all
  58. /// array dimensions computed in step 2.
  59. ///
  60. /// To compute a uniform array size for several memory accesses to the same
  61. /// object, one can collect in step 1 all the step terms for all the memory
  62. /// accesses, and compute in step 2 a unique array shape. This guarantees
  63. /// that the array shape will be the same across all memory accesses.
  64. ///
  65. /// FIXME: We could derive the result of steps 1 and 2 from a description of
  66. /// the array shape given in metadata.
  67. ///
  68. /// Example:
  69. ///
  70. /// A[][n][m]
  71. ///
  72. /// for i
  73. /// for j
  74. /// for k
  75. /// A[j+k][2i][5i] =
  76. ///
  77. /// The initial SCEV:
  78. ///
  79. /// A[{{{0,+,2*m+5}_i, +, n*m}_j, +, n*m}_k]
  80. ///
  81. /// 1. Find the different terms in the step functions:
  82. /// -> [2*m, 5, n*m, n*m]
  83. ///
  84. /// 2. Compute the array size: sort and unique them
  85. /// -> [n*m, 2*m, 5]
  86. /// find the GCD of all the terms = 1
  87. /// divide by the GCD and erase constant terms
  88. /// -> [n*m, 2*m]
  89. /// GCD = m
  90. /// divide by GCD -> [n, 2]
  91. /// remove constant terms
  92. /// -> [n]
  93. /// size of the array is A[unknown][n][m]
  94. ///
  95. /// 3. Compute the access function
  96. /// a. Divide {{{0,+,2*m+5}_i, +, n*m}_j, +, n*m}_k by the innermost size m
  97. /// Quotient: {{{0,+,2}_i, +, n}_j, +, n}_k
  98. /// Remainder: {{{0,+,5}_i, +, 0}_j, +, 0}_k
  99. /// The remainder is the subscript of the innermost array dimension: [5i].
  100. ///
  101. /// b. Divide Quotient: {{{0,+,2}_i, +, n}_j, +, n}_k by next outer size n
  102. /// Quotient: {{{0,+,0}_i, +, 1}_j, +, 1}_k
  103. /// Remainder: {{{0,+,2}_i, +, 0}_j, +, 0}_k
  104. /// The Remainder is the subscript of the next array dimension: [2i].
  105. ///
  106. /// The subscript of the outermost dimension is the Quotient: [j+k].
  107. ///
  108. /// Overall, we have: A[][n][m], and the access function: A[j+k][2i][5i].
  109. void delinearize(ScalarEvolution &SE, const SCEV *Expr,
  110. SmallVectorImpl<const SCEV *> &Subscripts,
  111. SmallVectorImpl<const SCEV *> &Sizes, const SCEV *ElementSize);
  112. /// Gathers the individual index expressions from a GEP instruction.
  113. ///
  114. /// This function optimistically assumes the GEP references into a fixed size
  115. /// array. If this is actually true, this function returns a list of array
  116. /// subscript expressions in \p Subscripts and a list of integers describing
  117. /// the size of the individual array dimensions in \p Sizes. Both lists have
  118. /// either equal length or the size list is one element shorter in case there
  119. /// is no known size available for the outermost array dimension. Returns true
  120. /// if successful and false otherwise.
  121. bool getIndexExpressionsFromGEP(ScalarEvolution &SE,
  122. const GetElementPtrInst *GEP,
  123. SmallVectorImpl<const SCEV *> &Subscripts,
  124. SmallVectorImpl<int> &Sizes);
  125. /// Implementation of fixed size array delinearization. Try to delinearize
  126. /// access function for a fixed size multi-dimensional array, by deriving
  127. /// subscripts from GEP instructions. Returns true upon success and false
  128. /// otherwise. \p Inst is the load/store instruction whose pointer operand is
  129. /// the one we want to delinearize. \p AccessFn is its corresponding SCEV
  130. /// expression w.r.t. the surrounding loop.
  131. bool tryDelinearizeFixedSizeImpl(ScalarEvolution *SE, Instruction *Inst,
  132. const SCEV *AccessFn,
  133. SmallVectorImpl<const SCEV *> &Subscripts,
  134. SmallVectorImpl<int> &Sizes);
  135. struct DelinearizationPrinterPass
  136. : public PassInfoMixin<DelinearizationPrinterPass> {
  137. explicit DelinearizationPrinterPass(raw_ostream &OS);
  138. PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
  139. private:
  140. raw_ostream &OS;
  141. };
  142. } // namespace llvm
  143. #endif // LLVM_ANALYSIS_DELINEARIZATION_H
  144. #ifdef __GNUC__
  145. #pragma GCC diagnostic pop
  146. #endif