Skip to content

Commit 5687e3b

Browse files
authored
Merge branch 'main' into reland-feature-reflect
2 parents 4a4cd53 + 001ba42 commit 5687e3b

File tree

5 files changed

+86
-68
lines changed

5 files changed

+86
-68
lines changed

libcxx/test/std/containers/Emplaceable.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ struct std::hash<Emplaceable> {
4545
typedef Emplaceable argument_type;
4646
typedef std::size_t result_type;
4747

48-
std::size_t operator()(const Emplaceable& x) const { return x.get(); }
48+
std::size_t operator()(const Emplaceable& x) const { return static_cast<std::size_t>(x.get()); }
4949
};
5050

5151
#endif // TEST_STD_VER >= 11

libcxx/test/std/containers/container.adaptors/flat.map/flat.map.access/at_transparent.pass.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ int main(int, char**) {
103103
TransparentComparator c(transparent_used);
104104
std::flat_map<int, int, TransparentComparator> m(std::sorted_unique, {{1, 1}, {2, 2}, {3, 3}}, c);
105105
assert(!transparent_used);
106-
m.at(Transparent<int>{3});
106+
TEST_IGNORE_NODISCARD m.at(Transparent<int>{3});
107107
assert(transparent_used);
108108
}
109109

mlir/include/mlir/Dialect/Affine/Analysis/Utils.h

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,11 @@ struct MemRefDependenceGraph {
139139

140140
// Map from node id to Node.
141141
DenseMap<unsigned, Node> nodes;
142-
// Map from node id to list of input edges.
142+
// Map from node id to list of input edges. The absence of an entry for a key
143+
// is also equivalent to the absence of any edges.
143144
DenseMap<unsigned, SmallVector<Edge, 2>> inEdges;
144-
// Map from node id to list of output edges.
145+
// Map from node id to list of output edges. The absence of an entry for a
146+
// node is also equivalent to the absence of any edges.
145147
DenseMap<unsigned, SmallVector<Edge, 2>> outEdges;
146148
// Map from memref to a count on the dependence edges associated with that
147149
// memref.
@@ -156,10 +158,21 @@ struct MemRefDependenceGraph {
156158
bool init();
157159

158160
// Returns the graph node for 'id'.
159-
Node *getNode(unsigned id);
161+
const Node *getNode(unsigned id) const;
162+
Node *getNode(unsigned id) {
163+
return const_cast<Node *>(
164+
static_cast<const MemRefDependenceGraph *>(this)->getNode(id));
165+
}
166+
167+
// Returns true if the graph has node with ID `id`.
168+
bool hasNode(unsigned id) const { return nodes.contains(id); }
160169

161170
// Returns the graph node for 'forOp'.
162-
Node *getForOpNode(AffineForOp forOp);
171+
const Node *getForOpNode(AffineForOp forOp) const;
172+
Node *getForOpNode(AffineForOp forOp) {
173+
return const_cast<Node *>(
174+
static_cast<const MemRefDependenceGraph *>(this)->getForOpNode(forOp));
175+
}
163176

164177
// Adds a node with 'op' to the graph and returns its unique identifier.
165178
unsigned addNode(Operation *op);
@@ -169,12 +182,12 @@ struct MemRefDependenceGraph {
169182

170183
// Returns true if node 'id' writes to any memref which escapes (or is an
171184
// argument to) the block. Returns false otherwise.
172-
bool writesToLiveInOrEscapingMemrefs(unsigned id);
185+
bool writesToLiveInOrEscapingMemrefs(unsigned id) const;
173186

174187
// Returns true iff there is an edge from node 'srcId' to node 'dstId' which
175188
// is for 'value' if non-null, or for any value otherwise. Returns false
176189
// otherwise.
177-
bool hasEdge(unsigned srcId, unsigned dstId, Value value = nullptr);
190+
bool hasEdge(unsigned srcId, unsigned dstId, Value value = nullptr) const;
178191

179192
// Adds an edge from node 'srcId' to node 'dstId' for 'value'.
180193
void addEdge(unsigned srcId, unsigned dstId, Value value);
@@ -185,23 +198,25 @@ struct MemRefDependenceGraph {
185198
// Returns true if there is a path in the dependence graph from node 'srcId'
186199
// to node 'dstId'. Returns false otherwise. `srcId`, `dstId`, and the
187200
// operations that the edges connected are expected to be from the same block.
188-
bool hasDependencePath(unsigned srcId, unsigned dstId);
201+
bool hasDependencePath(unsigned srcId, unsigned dstId) const;
189202

190203
// Returns the input edge count for node 'id' and 'memref' from src nodes
191204
// which access 'memref' with a store operation.
192-
unsigned getIncomingMemRefAccesses(unsigned id, Value memref);
205+
unsigned getIncomingMemRefAccesses(unsigned id, Value memref) const;
193206

194207
// Returns the output edge count for node 'id' and 'memref' (if non-null),
195208
// otherwise returns the total output edge count from node 'id'.
196-
unsigned getOutEdgeCount(unsigned id, Value memref = nullptr);
209+
unsigned getOutEdgeCount(unsigned id, Value memref = nullptr) const;
197210

198211
/// Return all nodes which define SSA values used in node 'id'.
199-
void gatherDefiningNodes(unsigned id, DenseSet<unsigned> &definingNodes);
212+
void gatherDefiningNodes(unsigned id,
213+
DenseSet<unsigned> &definingNodes) const;
200214

201215
// Computes and returns an insertion point operation, before which the
202216
// the fused <srcId, dstId> loop nest can be inserted while preserving
203217
// dependences. Returns nullptr if no such insertion point is found.
204-
Operation *getFusedLoopNestInsertionPoint(unsigned srcId, unsigned dstId);
218+
Operation *getFusedLoopNestInsertionPoint(unsigned srcId,
219+
unsigned dstId) const;
205220

206221
// Updates edge mappings from node 'srcId' to node 'dstId' after fusing them,
207222
// taking into account that:

mlir/lib/Dialect/Affine/Analysis/Utils.cpp

Lines changed: 38 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,9 @@ static void getEffectedValues(Operation *op, SmallVectorImpl<Value> &values) {
188188

189189
/// Add `op` to MDG creating a new node and adding its memory accesses (affine
190190
/// or non-affine to memrefAccesses (memref -> list of nodes with accesses) map.
191-
Node *addNodeToMDG(Operation *nodeOp, MemRefDependenceGraph &mdg,
192-
DenseMap<Value, SetVector<unsigned>> &memrefAccesses) {
191+
static Node *
192+
addNodeToMDG(Operation *nodeOp, MemRefDependenceGraph &mdg,
193+
DenseMap<Value, SetVector<unsigned>> &memrefAccesses) {
193194
auto &nodes = mdg.nodes;
194195
// Create graph node 'id' to represent top-level 'forOp' and record
195196
// all loads and store accesses it contains.
@@ -359,14 +360,14 @@ bool MemRefDependenceGraph::init() {
359360
}
360361

361362
// Returns the graph node for 'id'.
362-
Node *MemRefDependenceGraph::getNode(unsigned id) {
363+
const Node *MemRefDependenceGraph::getNode(unsigned id) const {
363364
auto it = nodes.find(id);
364365
assert(it != nodes.end());
365366
return &it->second;
366367
}
367368

368369
// Returns the graph node for 'forOp'.
369-
Node *MemRefDependenceGraph::getForOpNode(AffineForOp forOp) {
370+
const Node *MemRefDependenceGraph::getForOpNode(AffineForOp forOp) const {
370371
for (auto &idAndNode : nodes)
371372
if (idAndNode.second.op == forOp)
372373
return &idAndNode.second;
@@ -390,7 +391,7 @@ void MemRefDependenceGraph::removeNode(unsigned id) {
390391
}
391392
}
392393
// Remove each edge in 'outEdges[id]'.
393-
if (outEdges.count(id) > 0) {
394+
if (outEdges.contains(id)) {
394395
SmallVector<Edge, 2> oldOutEdges = outEdges[id];
395396
for (auto &outEdge : oldOutEdges) {
396397
removeEdge(id, outEdge.id, outEdge.value);
@@ -404,8 +405,8 @@ void MemRefDependenceGraph::removeNode(unsigned id) {
404405

405406
// Returns true if node 'id' writes to any memref which escapes (or is an
406407
// argument to) the block. Returns false otherwise.
407-
bool MemRefDependenceGraph::writesToLiveInOrEscapingMemrefs(unsigned id) {
408-
Node *node = getNode(id);
408+
bool MemRefDependenceGraph::writesToLiveInOrEscapingMemrefs(unsigned id) const {
409+
const Node *node = getNode(id);
409410
for (auto *storeOpInst : node->stores) {
410411
auto memref = cast<AffineWriteOpInterface>(storeOpInst).getMemRef();
411412
auto *op = memref.getDefiningOp();
@@ -425,14 +426,14 @@ bool MemRefDependenceGraph::writesToLiveInOrEscapingMemrefs(unsigned id) {
425426
// is for 'value' if non-null, or for any value otherwise. Returns false
426427
// otherwise.
427428
bool MemRefDependenceGraph::hasEdge(unsigned srcId, unsigned dstId,
428-
Value value) {
429-
if (outEdges.count(srcId) == 0 || inEdges.count(dstId) == 0) {
429+
Value value) const {
430+
if (!outEdges.contains(srcId) || !inEdges.contains(dstId)) {
430431
return false;
431432
}
432-
bool hasOutEdge = llvm::any_of(outEdges[srcId], [=](Edge &edge) {
433+
bool hasOutEdge = llvm::any_of(outEdges.lookup(srcId), [=](const Edge &edge) {
433434
return edge.id == dstId && (!value || edge.value == value);
434435
});
435-
bool hasInEdge = llvm::any_of(inEdges[dstId], [=](Edge &edge) {
436+
bool hasInEdge = llvm::any_of(inEdges.lookup(dstId), [=](const Edge &edge) {
436437
return edge.id == srcId && (!value || edge.value == value);
437438
});
438439
return hasOutEdge && hasInEdge;
@@ -477,7 +478,8 @@ void MemRefDependenceGraph::removeEdge(unsigned srcId, unsigned dstId,
477478
// Returns true if there is a path in the dependence graph from node 'srcId'
478479
// to node 'dstId'. Returns false otherwise. `srcId`, `dstId`, and the
479480
// operations that the edges connected are expected to be from the same block.
480-
bool MemRefDependenceGraph::hasDependencePath(unsigned srcId, unsigned dstId) {
481+
bool MemRefDependenceGraph::hasDependencePath(unsigned srcId,
482+
unsigned dstId) const {
481483
// Worklist state is: <node-id, next-output-edge-index-to-visit>
482484
SmallVector<std::pair<unsigned, unsigned>, 4> worklist;
483485
worklist.push_back({srcId, 0});
@@ -490,13 +492,13 @@ bool MemRefDependenceGraph::hasDependencePath(unsigned srcId, unsigned dstId) {
490492
return true;
491493
// Pop and continue if node has no out edges, or if all out edges have
492494
// already been visited.
493-
if (outEdges.count(idAndIndex.first) == 0 ||
494-
idAndIndex.second == outEdges[idAndIndex.first].size()) {
495+
if (!outEdges.contains(idAndIndex.first) ||
496+
idAndIndex.second == outEdges.lookup(idAndIndex.first).size()) {
495497
worklist.pop_back();
496498
continue;
497499
}
498500
// Get graph edge to traverse.
499-
Edge edge = outEdges[idAndIndex.first][idAndIndex.second];
501+
const Edge edge = outEdges.lookup(idAndIndex.first)[idAndIndex.second];
500502
// Increment next output edge index for 'idAndIndex'.
501503
++idAndIndex.second;
502504
// Add node at 'edge.id' to the worklist. We don't need to consider
@@ -512,34 +514,34 @@ bool MemRefDependenceGraph::hasDependencePath(unsigned srcId, unsigned dstId) {
512514
// Returns the input edge count for node 'id' and 'memref' from src nodes
513515
// which access 'memref' with a store operation.
514516
unsigned MemRefDependenceGraph::getIncomingMemRefAccesses(unsigned id,
515-
Value memref) {
517+
Value memref) const {
516518
unsigned inEdgeCount = 0;
517-
if (inEdges.count(id) > 0)
518-
for (auto &inEdge : inEdges[id])
519-
if (inEdge.value == memref) {
520-
Node *srcNode = getNode(inEdge.id);
521-
// Only count in edges from 'srcNode' if 'srcNode' accesses 'memref'
522-
if (srcNode->getStoreOpCount(memref) > 0)
523-
++inEdgeCount;
524-
}
519+
for (const Edge &inEdge : inEdges.lookup(id)) {
520+
if (inEdge.value == memref) {
521+
const Node *srcNode = getNode(inEdge.id);
522+
// Only count in edges from 'srcNode' if 'srcNode' accesses 'memref'
523+
if (srcNode->getStoreOpCount(memref) > 0)
524+
++inEdgeCount;
525+
}
526+
}
525527
return inEdgeCount;
526528
}
527529

528530
// Returns the output edge count for node 'id' and 'memref' (if non-null),
529531
// otherwise returns the total output edge count from node 'id'.
530-
unsigned MemRefDependenceGraph::getOutEdgeCount(unsigned id, Value memref) {
532+
unsigned MemRefDependenceGraph::getOutEdgeCount(unsigned id,
533+
Value memref) const {
531534
unsigned outEdgeCount = 0;
532-
if (outEdges.count(id) > 0)
533-
for (auto &outEdge : outEdges[id])
534-
if (!memref || outEdge.value == memref)
535-
++outEdgeCount;
535+
for (const auto &outEdge : outEdges.lookup(id))
536+
if (!memref || outEdge.value == memref)
537+
++outEdgeCount;
536538
return outEdgeCount;
537539
}
538540

539541
/// Return all nodes which define SSA values used in node 'id'.
540542
void MemRefDependenceGraph::gatherDefiningNodes(
541-
unsigned id, DenseSet<unsigned> &definingNodes) {
542-
for (MemRefDependenceGraph::Edge edge : inEdges[id])
543+
unsigned id, DenseSet<unsigned> &definingNodes) const {
544+
for (const Edge &edge : inEdges.lookup(id))
543545
// By definition of edge, if the edge value is a non-memref value,
544546
// then the dependence is between a graph node which defines an SSA value
545547
// and another graph node which uses the SSA value.
@@ -552,8 +554,8 @@ void MemRefDependenceGraph::gatherDefiningNodes(
552554
// dependences. Returns nullptr if no such insertion point is found.
553555
Operation *
554556
MemRefDependenceGraph::getFusedLoopNestInsertionPoint(unsigned srcId,
555-
unsigned dstId) {
556-
if (outEdges.count(srcId) == 0)
557+
unsigned dstId) const {
558+
if (!outEdges.contains(srcId))
557559
return getNode(dstId)->op;
558560

559561
// Skip if there is any defining node of 'dstId' that depends on 'srcId'.
@@ -569,13 +571,13 @@ MemRefDependenceGraph::getFusedLoopNestInsertionPoint(unsigned srcId,
569571

570572
// Build set of insts in range (srcId, dstId) which depend on 'srcId'.
571573
SmallPtrSet<Operation *, 2> srcDepInsts;
572-
for (auto &outEdge : outEdges[srcId])
574+
for (auto &outEdge : outEdges.lookup(srcId))
573575
if (outEdge.id != dstId)
574576
srcDepInsts.insert(getNode(outEdge.id)->op);
575577

576578
// Build set of insts in range (srcId, dstId) on which 'dstId' depends.
577579
SmallPtrSet<Operation *, 2> dstDepInsts;
578-
for (auto &inEdge : inEdges[dstId])
580+
for (auto &inEdge : inEdges.lookup(dstId))
579581
if (inEdge.id != srcId)
580582
dstDepInsts.insert(getNode(inEdge.id)->op);
581583

@@ -635,7 +637,7 @@ void MemRefDependenceGraph::updateEdges(unsigned srcId, unsigned dstId,
635637
SmallVector<Edge, 2> oldInEdges = inEdges[srcId];
636638
for (auto &inEdge : oldInEdges) {
637639
// Add edge from 'inEdge.id' to 'dstId' if it's not a private memref.
638-
if (privateMemRefs.count(inEdge.value) == 0)
640+
if (!privateMemRefs.contains(inEdge.value))
639641
addEdge(inEdge.id, dstId, inEdge.value);
640642
}
641643
}

mlir/lib/Dialect/Affine/Transforms/LoopFusion.cpp

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,13 @@ struct LoopFusion : public affine::impl::AffineLoopFusionBase<LoopFusion> {
7878
static bool canRemoveSrcNodeAfterFusion(
7979
unsigned srcId, unsigned dstId, const ComputationSliceState &fusionSlice,
8080
Operation *fusedLoopInsPoint, const DenseSet<Value> &escapingMemRefs,
81-
MemRefDependenceGraph *mdg) {
81+
const MemRefDependenceGraph &mdg) {
8282

83-
Operation *dstNodeOp = mdg->getNode(dstId)->op;
83+
Operation *dstNodeOp = mdg.getNode(dstId)->op;
8484
bool hasOutDepsAfterFusion = false;
8585

86-
for (auto &outEdge : mdg->outEdges[srcId]) {
87-
Operation *depNodeOp = mdg->getNode(outEdge.id)->op;
86+
for (auto &outEdge : mdg.outEdges.lookup(srcId)) {
87+
Operation *depNodeOp = mdg.getNode(outEdge.id)->op;
8888
// Skip dependence with dstOp since it will be removed after fusion.
8989
if (depNodeOp == dstNodeOp)
9090
continue;
@@ -134,22 +134,23 @@ static bool canRemoveSrcNodeAfterFusion(
134134
/// held if the 'mdg' is reused from a previous fusion step or if the node
135135
/// creation order changes in the future to support more advance cases.
136136
// TODO: Move this to a loop fusion utility once 'mdg' is also moved.
137-
static void getProducerCandidates(unsigned dstId, MemRefDependenceGraph *mdg,
137+
static void getProducerCandidates(unsigned dstId,
138+
const MemRefDependenceGraph &mdg,
138139
SmallVectorImpl<unsigned> &srcIdCandidates) {
139140
// Skip if no input edges along which to fuse.
140-
if (mdg->inEdges.count(dstId) == 0)
141+
if (mdg.inEdges.count(dstId) == 0)
141142
return;
142143

143144
// Gather memrefs from loads in 'dstId'.
144-
auto *dstNode = mdg->getNode(dstId);
145+
auto *dstNode = mdg.getNode(dstId);
145146
DenseSet<Value> consumedMemrefs;
146147
for (Operation *load : dstNode->loads)
147148
consumedMemrefs.insert(cast<AffineReadOpInterface>(load).getMemRef());
148149

149150
// Traverse 'dstId' incoming edges and gather the nodes that contain a store
150151
// to one of the consumed memrefs.
151-
for (auto &srcEdge : mdg->inEdges[dstId]) {
152-
auto *srcNode = mdg->getNode(srcEdge.id);
152+
for (const auto &srcEdge : mdg.inEdges.lookup(dstId)) {
153+
const auto *srcNode = mdg.getNode(srcEdge.id);
153154
// Skip if 'srcNode' is not a loop nest.
154155
if (!isa<AffineForOp>(srcNode->op))
155156
continue;
@@ -169,10 +170,10 @@ static void getProducerCandidates(unsigned dstId, MemRefDependenceGraph *mdg,
169170
/// producer-consumer dependence between 'srcId' and 'dstId'.
170171
static void
171172
gatherProducerConsumerMemrefs(unsigned srcId, unsigned dstId,
172-
MemRefDependenceGraph *mdg,
173+
const MemRefDependenceGraph &mdg,
173174
DenseSet<Value> &producerConsumerMemrefs) {
174-
auto *dstNode = mdg->getNode(dstId);
175-
auto *srcNode = mdg->getNode(srcId);
175+
auto *dstNode = mdg.getNode(dstId);
176+
auto *srcNode = mdg.getNode(srcId);
176177
gatherProducerConsumerMemrefs(srcNode->stores, dstNode->loads,
177178
producerConsumerMemrefs);
178179
}
@@ -214,14 +215,14 @@ static bool isEscapingMemref(Value memref, Block *block) {
214215

215216
/// Returns in 'escapingMemRefs' the memrefs from affine store ops in node 'id'
216217
/// that escape the block or are accessed in a non-affine way.
217-
static void gatherEscapingMemrefs(unsigned id, MemRefDependenceGraph *mdg,
218+
static void gatherEscapingMemrefs(unsigned id, const MemRefDependenceGraph &mdg,
218219
DenseSet<Value> &escapingMemRefs) {
219-
auto *node = mdg->getNode(id);
220+
auto *node = mdg.getNode(id);
220221
for (Operation *storeOp : node->stores) {
221222
auto memref = cast<AffineWriteOpInterface>(storeOp).getMemRef();
222223
if (escapingMemRefs.count(memref))
223224
continue;
224-
if (isEscapingMemref(memref, &mdg->block))
225+
if (isEscapingMemref(memref, &mdg.block))
225226
escapingMemRefs.insert(memref);
226227
}
227228
}
@@ -826,7 +827,7 @@ struct GreedyFusion {
826827
// in 'srcIdCandidates'.
827828
dstNodeChanged = false;
828829
SmallVector<unsigned, 16> srcIdCandidates;
829-
getProducerCandidates(dstId, mdg, srcIdCandidates);
830+
getProducerCandidates(dstId, *mdg, srcIdCandidates);
830831

831832
for (unsigned srcId : llvm::reverse(srcIdCandidates)) {
832833
// Get 'srcNode' from which to attempt fusion into 'dstNode'.
@@ -841,7 +842,7 @@ struct GreedyFusion {
841842
continue;
842843

843844
DenseSet<Value> producerConsumerMemrefs;
844-
gatherProducerConsumerMemrefs(srcId, dstId, mdg,
845+
gatherProducerConsumerMemrefs(srcId, dstId, *mdg,
845846
producerConsumerMemrefs);
846847

847848
// Skip if 'srcNode' out edge count on any memref is greater than
@@ -856,7 +857,7 @@ struct GreedyFusion {
856857
// block (e.g., memref block arguments, returned memrefs,
857858
// memrefs passed to function calls, etc.).
858859
DenseSet<Value> srcEscapingMemRefs;
859-
gatherEscapingMemrefs(srcNode->id, mdg, srcEscapingMemRefs);
860+
gatherEscapingMemrefs(srcNode->id, *mdg, srcEscapingMemRefs);
860861

861862
// Compute an operation list insertion point for the fused loop
862863
// nest which preserves dependences.
@@ -950,7 +951,7 @@ struct GreedyFusion {
950951
// insertion point.
951952
bool removeSrcNode = canRemoveSrcNodeAfterFusion(
952953
srcId, dstId, bestSlice, fusedLoopInsPoint, srcEscapingMemRefs,
953-
mdg);
954+
*mdg);
954955

955956
DenseSet<Value> privateMemrefs;
956957
for (Value memref : producerConsumerMemrefs) {

0 commit comments

Comments
 (0)