FLANG
ArraySectionAnalyzer.h
1//===- ArraySectionAnalyzer.h - Analyze array sections --------------------===//
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#ifndef FORTRAN_OPTIMIZER_ANALYSIS_ARRAYSECTIONANALYZER_H
10#define FORTRAN_OPTIMIZER_ANALYSIS_ARRAYSECTIONANALYZER_H
11
12#include "mlir/IR/Operation.h"
13#include "mlir/IR/Value.h"
14#include "llvm/ADT/STLFunctionalExtras.h"
15
16namespace mlir {
17class Operation;
18class Value;
19} // namespace mlir
20
21namespace hlfir {
22class ElementalOpInterface;
23class DesignateOp;
24} // namespace hlfir
25
26namespace fir {
28public:
29 // The result of the analyzis is one of the values below.
30 enum class SlicesOverlapKind {
31 // Slices overlap is unknown.
32 Unknown,
33 // Slices are definitely identical.
34 DefinitelyIdentical,
35 // Slices are definitely disjoint.
36 DefinitelyDisjoint,
37 // Slices may be either disjoint or identical,
38 // i.e. there is definitely no partial overlap.
39 EitherIdenticalOrDisjoint
40 };
41
48 llvm::function_ref<bool(mlir::Value, mlir::Value)>;
49
50 // Analyzes two hlfir.designate results and returns the overlap kind.
51 // The callers may use this method when the alias analysis reports
52 // an alias of some kind, so that we can run Fortran specific analysis
53 // on the array slices to see if they are identical or disjoint.
54 // Note that the alias analysis are not able to give such an answer
55 // about the references.
56 //
57 // \p areKnownEquivalent is an optional callback that the analyzer may use
58 // to recognize section subscripts that have the same value even when they
59 // are not the same SSA value (e.g., subscripts that are loads of the same
60 // Fortran variable from two different regions of the same WHERE construct).
61 static SlicesOverlapKind
62 analyze(mlir::Value ref1, mlir::Value ref2,
63 ValueEquivalenceCallback areKnownEquivalent = nullptr);
64
65 static bool isDesignatingArrayInOrder(hlfir::DesignateOp designate,
66 hlfir::ElementalOpInterface elemental);
67
68private:
69 struct SectionDesc {
70 // An array section is described by <lb, ub, stride> tuple.
71 // If the designator's subscript is not a triple, then
72 // the section descriptor is constructed as <lb, nullptr, nullptr>.
73 mlir::Value lb, ub, stride;
74
75 SectionDesc(mlir::Value lb, mlir::Value ub, mlir::Value stride);
76
77 // Normalize the section descriptor:
78 // 1. If UB is nullptr, then it is set to LB.
79 // 2. If LB==UB, then stride does not matter,
80 // so it is reset to nullptr.
81 // 3. If STRIDE==1, then it is reset to nullptr.
82 void normalize();
83
84 bool operator==(const SectionDesc &other) const;
85 };
86
87 // Given an operand_iterator over the indices operands,
88 // read the subscript values and return them as SectionDesc
89 // updating the iterator. If isTriplet is true,
90 // the subscript is a triplet, and the result is <lb, ub, stride>.
91 // Otherwise, the subscript is a scalar index, and the result
92 // is <index, nullptr, nullptr>.
93 static SectionDesc readSectionDesc(mlir::Operation::operand_iterator &it,
94 bool isTriplet);
95
96 // Return the ordered lower and upper bounds of the section.
97 // If stride is known to be non-negative, then the ordered
98 // bounds match the <lb, ub> of the descriptor.
99 // If stride is known to be negative, then the ordered
100 // bounds are <ub, lb> of the descriptor.
101 // If stride is unknown, we cannot deduce any order,
102 // so the result is <nullptr, nullptr>
103 static std::pair<mlir::Value, mlir::Value>
104 getOrderedBounds(const SectionDesc &desc);
105
106 // Given two array sections <lb1, ub1, stride1> and
107 // <lb2, ub2, stride2>, return true only if the sections
108 // are known to be disjoint.
109 //
110 // For example, for any positive constant C:
111 // X:Y does not overlap with (Y+C):Z
112 // X:Y does not overlap with Z:(X-C)
113 static bool areDisjointSections(const SectionDesc &desc1,
114 const SectionDesc &desc2);
115
116 // Given two array sections <lb1, ub1, stride1> and
117 // <lb2, ub2, stride2>, return true only if the sections
118 // are known to be identical.
119 //
120 // For example:
121 // <x, x, stride>
122 // <x, nullptr, nullptr>
123 //
124 // These sections are identical, from the point of which array
125 // elements are being addresses, even though the shape
126 // of the array slices might be different.
127 //
128 // When \p areKnownEquivalent is provided, it is used to compare the
129 // individual section components (lower bound, upper bound and stride)
130 // when they are not the same SSA value.
131 static bool
132 areIdenticalSections(const SectionDesc &desc1, const SectionDesc &desc2,
133 ValueEquivalenceCallback areKnownEquivalent = nullptr);
134
135 // Return true, if v1 is known to be less than v2.
136 static bool isLess(mlir::Value v1, mlir::Value v2);
137};
138} // namespace fir
139
140#endif // FORTRAN_OPTIMIZER_ANALYSIS_ARRAYSECTIONANALYZER_H
Definition ArraySectionAnalyzer.h:27
llvm::function_ref< bool(mlir::Value, mlir::Value)> ValueEquivalenceCallback
Definition ArraySectionAnalyzer.h:47
Definition AbstractConverter.h:37
Definition AbstractConverter.h:32