[flang-commits] [flang] [flang] Improve disjoint/identical slices recognition in opt-bufferization. (PR #119780)
via flang-commits
flang-commits at lists.llvm.org
Fri Dec 13 08:31:34 PST 2024
================
@@ -159,28 +159,162 @@ containsReadOrWriteEffectOn(const mlir::MemoryEffects::EffectInstance &effect,
return mlir::AliasResult::NoAlias;
}
-// Returns true if the given array references represent identical
-// or completely disjoint array slices. The callers may use this
-// method when the alias analysis reports an alias of some kind,
-// so that we can run Fortran specific analysis on the array slices
-// to see if they are identical or disjoint. Note that the alias
-// analysis are not able to give such an answer about the references.
-static bool areIdenticalOrDisjointSlices(mlir::Value ref1, mlir::Value ref2) {
+// Helper class for analyzing two array slices represented
+// by two hlfir.designate operations.
+class ArraySectionAnalyzer {
+public:
+ // The result of the analyzis is one of the values below.
+ enum class SlicesOverlapKind {
+ // Slices overlap is unknown.
+ Unknown,
+ // Slices are definitely disjoint.
+ DefinitelyIdentical,
+ // Slices are definitely identical.
+ DefinitelyDisjoint,
+ // Slices may be either disjoint or identical,
+ // i.e. there is definitely no partial overlap.
+ EitherIdenticalOrDisjoint
+ };
+
+ // Analyzes two hlfir.designate results and returns the overlap kind.
+ // The callers may use this method when the alias analysis reports
+ // an alias of some kind, so that we can run Fortran specific analysis
+ // on the array slices to see if they are identical or disjoint.
+ // Note that the alias analysis are not able to give such an answer
+ // about the references.
+ static SlicesOverlapKind analyze(mlir::Value ref1, mlir::Value ref2);
+
+private:
+ struct SectionDesc {
+ // An array section is described by <lb, ub, stride> tuple.
+ // If the designator's subscript is not a triple, then
+ // the section descriptor is constructed as <lb, nullptr, nullptr>.
+ mlir::Value lb, ub, stride;
+
+ SectionDesc(mlir::Value lb, mlir::Value ub, mlir::Value stride)
+ : lb(lb), ub(ub), stride(stride) {
+ assert(lb && "lower bound or index must be specified");
+ normalize();
+ }
+
+ // Normalize the section descriptor:
+ // 1. If UB is nullptr, then it is set to LB.
+ // 2. If LB==UB, then stride does not matter,
+ // so it is reset to nullptr.
+ // 3. If STRIDE==1, then it is reset to nullptr.
+ void normalize() {
+ if (!ub)
+ ub = lb;
+ if (lb == ub)
+ stride = nullptr;
+ if (stride)
+ if (auto val = fir::getIntIfConstant(stride))
+ if (*val == 1)
+ stride = nullptr;
+ }
+
+ bool operator==(const SectionDesc &other) const {
+ return lb == other.lb && ub == other.ub && stride == other.stride;
+ }
+ };
+
+ // Given an operand_iterator over the indices operands,
+ // read the subscript values and return them as SectionDesc
+ // updating the iterator. If isTriplet is true,
+ // the subscript is a triplet, and the result is <lb, ub, stride>.
+ // Otherwise, the subscript is a scalar index, and the result
+ // is <index, nullptr, nullptr>.
+ static SectionDesc readSectionDesc(mlir::Operation::operand_iterator &it,
+ bool isTriplet) {
+ if (isTriplet)
+ return {*it++, *it++, *it++};
+ return {*it++, nullptr, nullptr};
+ }
+
+ // Return the ordered lower and upper bounds of the section.
+ // If stride is known to be non-negative, then the ordered
+ // bounds match the <lb, ub> of the descriptor.
+ // If stride is known to be negative, then the ordered
+ // bounds are <ub, lb> of the descriptor.
+ // If stride is unknown, we cannot deduce any order,
+ // so the result is <nullptr, nullptr>
+ static std::pair<mlir::Value, mlir::Value>
+ getOrderedBounds(const SectionDesc &desc) {
+ mlir::Value stride = desc.stride;
+ // Null stride means stride-1.
----------------
jeanPerier wrote:
```suggestion
// Null stride means stride=1.
```
https://github.com/llvm/llvm-project/pull/119780
More information about the flang-commits
mailing list