Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:12

0001 //===---- Delinearization.h - MultiDimensional Index Delinearization ------===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This implements an analysis pass that tries to delinearize all GEP
0010 // instructions in all loops using the SCEV analysis functionality. This pass is
0011 // only used for testing purposes: if your pass needs delinearization, please
0012 // use the on-demand SCEVAddRecExpr::delinearize() function.
0013 //
0014 //===----------------------------------------------------------------------===//
0015 
0016 #ifndef LLVM_ANALYSIS_DELINEARIZATION_H
0017 #define LLVM_ANALYSIS_DELINEARIZATION_H
0018 
0019 #include "llvm/IR/PassManager.h"
0020 
0021 namespace llvm {
0022 class raw_ostream;
0023 template <typename T> class SmallVectorImpl;
0024 class GetElementPtrInst;
0025 class Instruction;
0026 class ScalarEvolution;
0027 class SCEV;
0028 
0029 /// Compute the array dimensions Sizes from the set of Terms extracted from
0030 /// the memory access function of this SCEVAddRecExpr (second step of
0031 /// delinearization).
0032 void findArrayDimensions(ScalarEvolution &SE,
0033                          SmallVectorImpl<const SCEV *> &Terms,
0034                          SmallVectorImpl<const SCEV *> &Sizes,
0035                          const SCEV *ElementSize);
0036 
0037 /// Collect parametric terms occurring in step expressions (first step of
0038 /// delinearization).
0039 void collectParametricTerms(ScalarEvolution &SE, const SCEV *Expr,
0040                             SmallVectorImpl<const SCEV *> &Terms);
0041 
0042 /// Return in Subscripts the access functions for each dimension in Sizes
0043 /// (third step of delinearization).
0044 void computeAccessFunctions(ScalarEvolution &SE, const SCEV *Expr,
0045                             SmallVectorImpl<const SCEV *> &Subscripts,
0046                             SmallVectorImpl<const SCEV *> &Sizes);
0047 /// Split this SCEVAddRecExpr into two vectors of SCEVs representing the
0048 /// subscripts and sizes of an array access.
0049 ///
0050 /// The delinearization is a 3 step process: the first two steps compute the
0051 /// sizes of each subscript and the third step computes the access functions
0052 /// for the delinearized array:
0053 ///
0054 /// 1. Find the terms in the step functions
0055 /// 2. Compute the array size
0056 /// 3. Compute the access function: divide the SCEV by the array size
0057 ///    starting with the innermost dimensions found in step 2. The Quotient
0058 ///    is the SCEV to be divided in the next step of the recursion. The
0059 ///    Remainder is the subscript of the innermost dimension. Loop over all
0060 ///    array dimensions computed in step 2.
0061 ///
0062 /// To compute a uniform array size for several memory accesses to the same
0063 /// object, one can collect in step 1 all the step terms for all the memory
0064 /// accesses, and compute in step 2 a unique array shape. This guarantees
0065 /// that the array shape will be the same across all memory accesses.
0066 ///
0067 /// FIXME: We could derive the result of steps 1 and 2 from a description of
0068 /// the array shape given in metadata.
0069 ///
0070 /// Example:
0071 ///
0072 /// A[][n][m]
0073 ///
0074 /// for i
0075 ///   for j
0076 ///     for k
0077 ///       A[j+k][2i][5i] =
0078 ///
0079 /// The initial SCEV:
0080 ///
0081 /// A[{{{0,+,2*m+5}_i, +, n*m}_j, +, n*m}_k]
0082 ///
0083 /// 1. Find the different terms in the step functions:
0084 /// -> [2*m, 5, n*m, n*m]
0085 ///
0086 /// 2. Compute the array size: sort and unique them
0087 /// -> [n*m, 2*m, 5]
0088 /// find the GCD of all the terms = 1
0089 /// divide by the GCD and erase constant terms
0090 /// -> [n*m, 2*m]
0091 /// GCD = m
0092 /// divide by GCD -> [n, 2]
0093 /// remove constant terms
0094 /// -> [n]
0095 /// size of the array is A[unknown][n][m]
0096 ///
0097 /// 3. Compute the access function
0098 /// a. Divide {{{0,+,2*m+5}_i, +, n*m}_j, +, n*m}_k by the innermost size m
0099 /// Quotient: {{{0,+,2}_i, +, n}_j, +, n}_k
0100 /// Remainder: {{{0,+,5}_i, +, 0}_j, +, 0}_k
0101 /// The remainder is the subscript of the innermost array dimension: [5i].
0102 ///
0103 /// b. Divide Quotient: {{{0,+,2}_i, +, n}_j, +, n}_k by next outer size n
0104 /// Quotient: {{{0,+,0}_i, +, 1}_j, +, 1}_k
0105 /// Remainder: {{{0,+,2}_i, +, 0}_j, +, 0}_k
0106 /// The Remainder is the subscript of the next array dimension: [2i].
0107 ///
0108 /// The subscript of the outermost dimension is the Quotient: [j+k].
0109 ///
0110 /// Overall, we have: A[][n][m], and the access function: A[j+k][2i][5i].
0111 void delinearize(ScalarEvolution &SE, const SCEV *Expr,
0112                  SmallVectorImpl<const SCEV *> &Subscripts,
0113                  SmallVectorImpl<const SCEV *> &Sizes, const SCEV *ElementSize);
0114 
0115 /// Gathers the individual index expressions from a GEP instruction.
0116 ///
0117 /// This function optimistically assumes the GEP references into a fixed size
0118 /// array. If this is actually true, this function returns a list of array
0119 /// subscript expressions in \p Subscripts and a list of integers describing
0120 /// the size of the individual array dimensions in \p Sizes. Both lists have
0121 /// either equal length or the size list is one element shorter in case there
0122 /// is no known size available for the outermost array dimension. Returns true
0123 /// if successful and false otherwise.
0124 bool getIndexExpressionsFromGEP(ScalarEvolution &SE,
0125                                 const GetElementPtrInst *GEP,
0126                                 SmallVectorImpl<const SCEV *> &Subscripts,
0127                                 SmallVectorImpl<int> &Sizes);
0128 
0129 /// Implementation of fixed size array delinearization. Try to delinearize
0130 /// access function for a fixed size multi-dimensional array, by deriving
0131 /// subscripts from GEP instructions. Returns true upon success and false
0132 /// otherwise. \p Inst is the load/store instruction whose pointer operand is
0133 /// the one we want to delinearize. \p AccessFn is its corresponding SCEV
0134 /// expression w.r.t. the surrounding loop.
0135 bool tryDelinearizeFixedSizeImpl(ScalarEvolution *SE, Instruction *Inst,
0136                                  const SCEV *AccessFn,
0137                                  SmallVectorImpl<const SCEV *> &Subscripts,
0138                                  SmallVectorImpl<int> &Sizes);
0139 
0140 struct DelinearizationPrinterPass
0141     : public PassInfoMixin<DelinearizationPrinterPass> {
0142   explicit DelinearizationPrinterPass(raw_ostream &OS);
0143   PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
0144   static bool isRequired() { return true; }
0145 
0146 private:
0147   raw_ostream &OS;
0148 };
0149 } // namespace llvm
0150 
0151 #endif // LLVM_ANALYSIS_DELINEARIZATION_H