This repository has been archived by the owner on Apr 23, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 258
/
DependenceAnalysis.h
137 lines (116 loc) · 5.58 KB
/
DependenceAnalysis.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
//===- DependenceAnalysis.h - Dependence analysis on SSA views --*- C++ -*-===//
//
// Copyright 2019 The MLIR Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// =============================================================================
#ifndef MLIR_DIALECT_LINALG_ANALYSIS_DEPENDENCEANALYSIS_H_
#define MLIR_DIALECT_LINALG_ANALYSIS_DEPENDENCEANALYSIS_H_
#include "mlir/IR/Builders.h"
#include "mlir/IR/OpDefinition.h"
namespace mlir {
namespace linalg {
class LinalgOp;
/// A very primitive alias analysis which just records for each view, either:
/// 1. The base buffer, or
/// 2. The block argument view
/// that it indexes into.
/// This does not perform inter-block or inter-procedural analysis and assumes
/// that different block argument views do not alias.
class Aliases {
public:
/// Returns true if v1 and v2 alias.
bool alias(Value *v1, Value *v2) { return find(v1) == find(v2); }
private:
/// Returns the base buffer or block argument into which the view `v` aliases.
/// This lazily records the new aliases discovered while walking back the
/// use-def chain.
Value *find(Value *v);
DenseMap<Value *, Value *> aliases;
};
/// Data structure for holding a dependence graph that operates on LinalgOp and
/// views as SSA values.
class LinalgDependenceGraph {
public:
struct LinalgOpView {
Operation *op;
Value *view;
};
struct LinalgDependenceGraphElem {
// dependentOpView may be either:
// 1. src in the case of dependencesIntoGraphs.
// 2. dst in the case of dependencesFromDstGraphs.
LinalgOpView dependentOpView;
// View in the op that is used to index in the graph:
// 1. src in the case of dependencesFromDstGraphs.
// 2. dst in the case of dependencesIntoGraphs.
Value *indexingView;
};
using LinalgDependences = llvm::SmallVector<LinalgDependenceGraphElem, 8>;
using DependenceGraph = DenseMap<Operation *, LinalgDependences>;
using dependence_iterator = LinalgDependences::iterator;
using dependence_range = llvm::iterator_range<dependence_iterator>;
enum DependenceType { RAR = 0, RAW, WAR, WAW, NumTypes };
LinalgDependenceGraph(Aliases &aliases, ArrayRef<Operation *> ops);
/// Returns the X such that op -> X is a dependence of type dt.
dependence_range getDependencesFrom(Operation *src, DependenceType dt);
dependence_range getDependencesFrom(LinalgOp src, DependenceType dt);
/// Returns the X such that X -> op is a dependence of type dt.
dependence_range getDependencesInto(Operation *dst, DependenceType dt);
dependence_range getDependencesInto(LinalgOp dst, DependenceType dt);
/// Returns the operations that are interleaved between `srcLinalgOp` and
/// `dstLinalgOp` and that are involved in any RAW, WAR or WAW dependence
/// relation with `srcLinalgOp`, on any view.
/// Any such operation prevents reordering.
SmallVector<Operation *, 8> findCoveringDependences(LinalgOp srcLinalgOp,
LinalgOp dstLinalgOp);
/// Returns the operations that are interleaved between `srcLinalgOp` and
/// `dstLinalgOp` and that are involved in a RAR or RAW with `srcLinalgOp`.
/// Dependences are restricted to views aliasing `view`.
SmallVector<Operation *, 8>
findCoveringReads(LinalgOp srcLinalgOp, LinalgOp dstLinalgOp, Value *view);
/// Returns the operations that are interleaved between `srcLinalgOp` and
/// `dstLinalgOp` and that are involved in a WAR or WAW with `srcLinalgOp`.
/// Dependences are restricted to views aliasing `view`.
SmallVector<Operation *, 8>
findCoveringWrites(LinalgOp srcLinalgOp, LinalgOp dstLinalgOp, Value *view);
private:
// Keep dependences in both directions, this is not just a performance gain
// but it also reduces usage errors.
// Dependence information is stored as a map of:
// (source operation -> LinalgDependenceGraphElem)
DependenceGraph dependencesFromGraphs[DependenceType::NumTypes];
// Reverse dependence information is stored as a map of:
// (destination operation -> LinalgDependenceGraphElem)
DependenceGraph dependencesIntoGraphs[DependenceType::NumTypes];
/// Analyses the aliasing views between `src` and `dst` and inserts the proper
/// dependences in the graph.
void addDependencesBetween(LinalgOp src, LinalgOp dst);
// Adds an new dependence unit in the proper graph.
// Uses std::pair to keep operations and view together and avoid usage errors
// related to src/dst and producer/consumer terminology in the context of
// dependences.
void addDependenceElem(DependenceType dt, LinalgOpView indexingOpView,
LinalgOpView dependentOpView);
/// Implementation detail for findCoveringxxx.
SmallVector<Operation *, 8>
findOperationsWithCoveringDependences(LinalgOp srcLinalgOp,
LinalgOp dstLinalgOp, Value *view,
ArrayRef<DependenceType> types);
Aliases &aliases;
SmallVector<Operation *, 8> linalgOps;
DenseMap<Operation *, unsigned> linalgOpPositions;
};
} // namespace linalg
} // namespace mlir
#endif // MLIR_DIALECT_LINALG_ANALYSIS_DEPENDENCEANALYSIS_H_