MLIR  18.0.0git
LoopAnalysis.h
Go to the documentation of this file.
1 //===- LoopAnalysis.h - loop analysis methods -------------------*- C++ -*-===//
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 header file defines prototypes for methods to analyze loops.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef MLIR_DIALECT_AFFINE_ANALYSIS_LOOPANALYSIS_H
14 #define MLIR_DIALECT_AFFINE_ANALYSIS_LOOPANALYSIS_H
15 
16 #include "mlir/Support/LLVM.h"
17 #include "llvm/ADT/ArrayRef.h"
18 #include <optional>
19 
20 namespace mlir {
21 class AffineExpr;
22 class AffineMap;
23 class BlockArgument;
24 class MemRefType;
25 class Operation;
26 class Value;
27 
28 namespace affine {
29 class AffineForOp;
30 class NestedPattern;
31 
32 /// Returns the trip count of the loop as an affine map with its corresponding
33 /// operands if the latter is expressible as an affine expression, and nullptr
34 /// otherwise. This method always succeeds as long as the lower bound is not a
35 /// multi-result map. The trip count expression is simplified before returning.
36 /// This method only utilizes map composition to construct lower and upper
37 /// bounds before computing the trip count expressions
38 void getTripCountMapAndOperands(AffineForOp forOp, AffineMap *map,
39  SmallVectorImpl<Value> *operands);
40 
41 /// Returns the trip count of the loop if it's a constant, std::nullopt
42 /// otherwise. This uses affine expression analysis and is able to determine
43 /// constant trip count in non-trivial cases.
44 std::optional<uint64_t> getConstantTripCount(AffineForOp forOp);
45 
46 /// Returns the greatest known integral divisor of the trip count. Affine
47 /// expression analysis is used (indirectly through getTripCount), and
48 /// this method is thus able to determine non-trivial divisors.
49 uint64_t getLargestDivisorOfTripCount(AffineForOp forOp);
50 
51 /// Given an induction variable `iv` of type AffineForOp and `indices` of type
52 /// IndexType, returns the set of `indices` that are independent of `iv`.
53 ///
54 /// Prerequisites (inherited from `isAccessInvariant` above):
55 /// 1. `iv` and `indices` of the proper type;
56 /// 2. at most one affine.apply is reachable from each index in `indices`;
57 ///
58 /// Emits a note if it encounters a chain of affine.apply and conservatively
59 /// those cases.
60 DenseSet<Value, DenseMapInfo<Value>>
61 getInvariantAccesses(Value iv, ArrayRef<Value> indices);
62 
63 using VectorizableLoopFun = std::function<bool(AffineForOp)>;
64 
65 /// Checks whether the loop is structurally vectorizable; i.e.:
66 /// 1. no conditionals are nested under the loop;
67 /// 2. all nested load/stores are to scalar MemRefs.
68 /// TODO: relax the no-conditionals restriction
69 bool isVectorizableLoopBody(AffineForOp loop,
70  NestedPattern &vectorTransferMatcher);
71 
72 /// Checks whether the loop is structurally vectorizable and that all the LoadOp
73 /// and StoreOp matched have access indexing functions that are either:
74 /// 1. invariant along the loop induction variable created by 'loop';
75 /// 2. varying along at most one memory dimension. If such a unique dimension
76 /// is found, it is written into `memRefDim`.
77 bool isVectorizableLoopBody(AffineForOp loop, int *memRefDim,
78  NestedPattern &vectorTransferMatcher);
79 
80 /// Checks where SSA dominance would be violated if a for op's body
81 /// operations are shifted by the specified shifts. This method checks if a
82 /// 'def' and all its uses have the same shift factor.
83 // TODO: extend this to check for memory-based dependence violation when we have
84 // the support.
85 bool isOpwiseShiftValid(AffineForOp forOp, ArrayRef<uint64_t> shifts);
86 
87 } // namespace affine
88 } // namespace mlir
89 
90 #endif // MLIR_DIALECT_AFFINE_ANALYSIS_LOOPANALYSIS_H
std::optional< uint64_t > getConstantTripCount(AffineForOp forOp)
Returns the trip count of the loop if it's a constant, std::nullopt otherwise.
bool isVectorizableLoopBody(AffineForOp loop, NestedPattern &vectorTransferMatcher)
Checks whether the loop is structurally vectorizable; i.e.
DenseSet< Value, DenseMapInfo< Value > > getInvariantAccesses(Value iv, ArrayRef< Value > indices)
Given an induction variable iv of type AffineForOp and indices of type IndexType, returns the set of ...
void getTripCountMapAndOperands(AffineForOp forOp, AffineMap *map, SmallVectorImpl< Value > *operands)
Returns the trip count of the loop as an affine map with its corresponding operands if the latter is ...
uint64_t getLargestDivisorOfTripCount(AffineForOp forOp)
Returns the greatest known integral divisor of the trip count.
std::function< bool(AffineForOp)> VectorizableLoopFun
Definition: LoopAnalysis.h:63
bool isOpwiseShiftValid(AffineForOp forOp, ArrayRef< uint64_t > shifts)
Checks where SSA dominance would be violated if a for op's body operations are shifted by the specifi...
Include the generated interface declarations.