Skip to content

Commit 3f9744a

Browse files
River707tensorflower-gardener
authored andcommitted
Refactor the Block support classes.
Each of the support classes for Block are now moved into a new header BlockSupport.h. The successor iterator class is also reimplemented as an indexed_accessor_range. This makes the class more efficient, and expands on its available functionality. PiperOrigin-RevId: 284646792
1 parent 7be6a40 commit 3f9744a

File tree

3 files changed

+177
-157
lines changed

3 files changed

+177
-157
lines changed

mlir/include/mlir/IR/Block.h

Lines changed: 12 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -22,60 +22,10 @@
2222
#ifndef MLIR_IR_BLOCK_H
2323
#define MLIR_IR_BLOCK_H
2424

25-
#include "mlir/IR/Value.h"
25+
#include "mlir/IR/BlockSupport.h"
2626
#include "mlir/IR/Visitors.h"
27-
#include "llvm/ADT/PointerUnion.h"
28-
#include "llvm/ADT/ilist.h"
29-
#include "llvm/ADT/ilist_node.h"
30-
31-
//===----------------------------------------------------------------------===//
32-
// ilist_traits for Operation
33-
//===----------------------------------------------------------------------===//
34-
35-
namespace llvm {
36-
namespace ilist_detail {
37-
// Explicitly define the node access for the operation list so that we can
38-
// break the dependence on the Operation class in this header. This allows for
39-
// operations to have trailing Regions without a circular include
40-
// dependence.
41-
template <>
42-
struct SpecificNodeAccess<
43-
typename compute_node_options<::mlir::Operation>::type> : NodeAccess {
44-
protected:
45-
using OptionsT = typename compute_node_options<mlir::Operation>::type;
46-
using pointer = typename OptionsT::pointer;
47-
using const_pointer = typename OptionsT::const_pointer;
48-
using node_type = ilist_node_impl<OptionsT>;
49-
50-
static node_type *getNodePtr(pointer N);
51-
static const node_type *getNodePtr(const_pointer N);
52-
53-
static pointer getValuePtr(node_type *N);
54-
static const_pointer getValuePtr(const node_type *N);
55-
};
56-
} // end namespace ilist_detail
57-
58-
template <> struct ilist_traits<::mlir::Operation> {
59-
using Operation = ::mlir::Operation;
60-
using op_iterator = simple_ilist<Operation>::iterator;
61-
62-
static void deleteNode(Operation *op);
63-
void addNodeToList(Operation *op);
64-
void removeNodeFromList(Operation *op);
65-
void transferNodesFromList(ilist_traits<Operation> &otherList,
66-
op_iterator first, op_iterator last);
67-
68-
private:
69-
mlir::Block *getContainingBlock();
70-
};
71-
} // end namespace llvm
7227

7328
namespace mlir {
74-
using BlockOperand = IROperandImpl<Block>;
75-
76-
class PredecessorIterator;
77-
class SuccessorIterator;
78-
7929
/// `Block` represents an ordered list of `Operation`s.
8030
class Block : public IRObjectWithUseList,
8131
public llvm::ilist_node_with_parent<Block, Region> {
@@ -272,9 +222,13 @@ class Block : public IRObjectWithUseList,
272222

273223
// Predecessor iteration.
274224
using pred_iterator = PredecessorIterator;
275-
pred_iterator pred_begin();
276-
pred_iterator pred_end();
277-
llvm::iterator_range<pred_iterator> getPredecessors();
225+
pred_iterator pred_begin() {
226+
return pred_iterator((BlockOperand *)getFirstUse());
227+
}
228+
pred_iterator pred_end() { return pred_iterator(nullptr); }
229+
llvm::iterator_range<pred_iterator> getPredecessors() {
230+
return {pred_begin(), pred_end()};
231+
}
278232

279233
/// Return true if this block has no predecessors.
280234
bool hasNoPredecessors();
@@ -292,10 +246,10 @@ class Block : public IRObjectWithUseList,
292246
Block *getSuccessor(unsigned i);
293247

294248
// Successor iteration.
295-
using succ_iterator = SuccessorIterator;
296-
succ_iterator succ_begin();
297-
succ_iterator succ_end();
298-
llvm::iterator_range<succ_iterator> getSuccessors();
249+
using succ_iterator = SuccessorRange::iterator;
250+
succ_iterator succ_begin() { return getSuccessors().begin(); }
251+
succ_iterator succ_end() { return getSuccessors().end(); }
252+
SuccessorRange getSuccessors() { return SuccessorRange(this); }
299253

300254
//===--------------------------------------------------------------------===//
301255
// Operation Walkers
@@ -381,105 +335,6 @@ class Block : public IRObjectWithUseList,
381335

382336
friend struct llvm::ilist_traits<Block>;
383337
};
384-
385-
} // end namespace mlir
386-
387-
//===----------------------------------------------------------------------===//
388-
// ilist_traits for Block
389-
//===----------------------------------------------------------------------===//
390-
391-
namespace llvm {
392-
393-
template <>
394-
struct ilist_traits<::mlir::Block> : public ilist_alloc_traits<::mlir::Block> {
395-
using Block = ::mlir::Block;
396-
using block_iterator = simple_ilist<::mlir::Block>::iterator;
397-
398-
void addNodeToList(Block *block);
399-
void removeNodeFromList(Block *block);
400-
void transferNodesFromList(ilist_traits<Block> &otherList,
401-
block_iterator first, block_iterator last);
402-
403-
private:
404-
mlir::Region *getParentRegion();
405-
};
406-
} // end namespace llvm
407-
408-
namespace mlir {
409-
//===----------------------------------------------------------------------===//
410-
// Predecessors
411-
//===----------------------------------------------------------------------===//
412-
413-
/// Implement a predecessor iterator for blocks. This works by walking the use
414-
/// lists of the blocks. The entries on this list are the BlockOperands that
415-
/// are embedded into terminator operations. From the operand, we can get the
416-
/// terminator that contains it, and its parent block is the predecessor.
417-
class PredecessorIterator final
418-
: public llvm::mapped_iterator<ValueUseIterator<BlockOperand>,
419-
Block *(*)(BlockOperand &)> {
420-
static Block *unwrap(BlockOperand &value);
421-
422-
public:
423-
using reference = Block *;
424-
425-
/// Initializes the operand type iterator to the specified operand iterator.
426-
PredecessorIterator(ValueUseIterator<BlockOperand> it)
427-
: llvm::mapped_iterator<ValueUseIterator<BlockOperand>,
428-
Block *(*)(BlockOperand &)>(it, &unwrap) {}
429-
explicit PredecessorIterator(BlockOperand *operand)
430-
: PredecessorIterator(ValueUseIterator<BlockOperand>(operand)) {}
431-
432-
/// Get the successor number in the predecessor terminator.
433-
unsigned getSuccessorIndex() const;
434-
};
435-
436-
inline auto Block::pred_begin() -> pred_iterator {
437-
return pred_iterator((BlockOperand *)getFirstUse());
438-
}
439-
440-
inline auto Block::pred_end() -> pred_iterator {
441-
return pred_iterator(nullptr);
442-
}
443-
444-
inline auto Block::getPredecessors() -> llvm::iterator_range<pred_iterator> {
445-
return {pred_begin(), pred_end()};
446-
}
447-
448-
//===----------------------------------------------------------------------===//
449-
// Successors
450-
//===----------------------------------------------------------------------===//
451-
452-
/// This template implements the successor iterators for Block.
453-
class SuccessorIterator final
454-
: public indexed_accessor_iterator<SuccessorIterator, Block *, Block *,
455-
Block *, Block *> {
456-
public:
457-
/// Initializes the result iterator to the specified index.
458-
SuccessorIterator(Block *object, unsigned index)
459-
: indexed_accessor_iterator<SuccessorIterator, Block *, Block *, Block *,
460-
Block *>(object, index) {}
461-
462-
SuccessorIterator(const SuccessorIterator &other)
463-
: SuccessorIterator(other.base, other.index) {}
464-
465-
Block *operator*() const { return this->base->getSuccessor(this->index); }
466-
467-
/// Get the successor number in the terminator.
468-
unsigned getSuccessorIndex() const { return this->index; }
469-
};
470-
471-
inline auto Block::succ_begin() -> succ_iterator {
472-
return succ_iterator(this, 0);
473-
}
474-
475-
inline auto Block::succ_end() -> succ_iterator {
476-
return succ_iterator(this, getNumSuccessors());
477-
}
478-
479-
inline auto Block::getSuccessors() -> llvm::iterator_range<succ_iterator> {
480-
return {succ_begin(), succ_end()};
481-
}
482-
483338
} // end namespace mlir
484339

485340
#endif // MLIR_IR_BLOCK_H

mlir/include/mlir/IR/BlockSupport.h

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
//===- BlockSupport.h -------------------------------------------*- C++ -*-===//
2+
//
3+
// Copyright 2019 The MLIR Authors.
4+
//
5+
// Licensed under the Apache License, Version 2.0 (the "License");
6+
// you may not use this file except in compliance with the License.
7+
// You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing, software
12+
// distributed under the License is distributed on an "AS IS" BASIS,
13+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
// See the License for the specific language governing permissions and
15+
// limitations under the License.
16+
// =============================================================================
17+
//
18+
// This file defines a number of support types for the Block class.
19+
//
20+
//===----------------------------------------------------------------------===//
21+
22+
#ifndef MLIR_IR_BLOCK_SUPPORT_H
23+
#define MLIR_IR_BLOCK_SUPPORT_H
24+
25+
#include "mlir/IR/Value.h"
26+
#include "llvm/ADT/PointerUnion.h"
27+
#include "llvm/ADT/ilist.h"
28+
#include "llvm/ADT/ilist_node.h"
29+
30+
namespace mlir {
31+
class Block;
32+
33+
using BlockOperand = IROperandImpl<Block>;
34+
35+
//===----------------------------------------------------------------------===//
36+
// Predecessors
37+
//===----------------------------------------------------------------------===//
38+
39+
/// Implement a predecessor iterator for blocks. This works by walking the use
40+
/// lists of the blocks. The entries on this list are the BlockOperands that
41+
/// are embedded into terminator operations. From the operand, we can get the
42+
/// terminator that contains it, and its parent block is the predecessor.
43+
class PredecessorIterator final
44+
: public llvm::mapped_iterator<ValueUseIterator<BlockOperand>,
45+
Block *(*)(BlockOperand &)> {
46+
static Block *unwrap(BlockOperand &value);
47+
48+
public:
49+
using reference = Block *;
50+
51+
/// Initializes the operand type iterator to the specified operand iterator.
52+
PredecessorIterator(ValueUseIterator<BlockOperand> it)
53+
: llvm::mapped_iterator<ValueUseIterator<BlockOperand>,
54+
Block *(*)(BlockOperand &)>(it, &unwrap) {}
55+
explicit PredecessorIterator(BlockOperand *operand)
56+
: PredecessorIterator(ValueUseIterator<BlockOperand>(operand)) {}
57+
58+
/// Get the successor number in the predecessor terminator.
59+
unsigned getSuccessorIndex() const;
60+
};
61+
62+
//===----------------------------------------------------------------------===//
63+
// Successors
64+
//===----------------------------------------------------------------------===//
65+
66+
/// This class implements the successor iterators for Block.
67+
class SuccessorRange final
68+
: public detail::indexed_accessor_range_base<SuccessorRange, BlockOperand *,
69+
Block *, Block *, Block *> {
70+
public:
71+
using detail::indexed_accessor_range_base<
72+
SuccessorRange, BlockOperand *, Block *, Block *,
73+
Block *>::indexed_accessor_range_base;
74+
SuccessorRange(Block *block);
75+
76+
private:
77+
/// See `detail::indexed_accessor_range_base` for details.
78+
static BlockOperand *offset_object(BlockOperand *object, ptrdiff_t index) {
79+
return object + index;
80+
}
81+
/// See `detail::indexed_accessor_range_base` for details.
82+
static Block *dereference_iterator(BlockOperand *object, ptrdiff_t index) {
83+
return object[index].get();
84+
}
85+
86+
/// Allow access to `offset_object` and `dereference_iterator`.
87+
friend detail::indexed_accessor_range_base<SuccessorRange, BlockOperand *,
88+
Block *, Block *, Block *>;
89+
};
90+
91+
} // end namespace mlir
92+
93+
namespace llvm {
94+
95+
//===----------------------------------------------------------------------===//
96+
// ilist_traits for Operation
97+
//===----------------------------------------------------------------------===//
98+
99+
namespace ilist_detail {
100+
// Explicitly define the node access for the operation list so that we can
101+
// break the dependence on the Operation class in this header. This allows for
102+
// operations to have trailing Regions without a circular include
103+
// dependence.
104+
template <>
105+
struct SpecificNodeAccess<
106+
typename compute_node_options<::mlir::Operation>::type> : NodeAccess {
107+
protected:
108+
using OptionsT = typename compute_node_options<mlir::Operation>::type;
109+
using pointer = typename OptionsT::pointer;
110+
using const_pointer = typename OptionsT::const_pointer;
111+
using node_type = ilist_node_impl<OptionsT>;
112+
113+
static node_type *getNodePtr(pointer N);
114+
static const node_type *getNodePtr(const_pointer N);
115+
116+
static pointer getValuePtr(node_type *N);
117+
static const_pointer getValuePtr(const node_type *N);
118+
};
119+
} // end namespace ilist_detail
120+
121+
template <> struct ilist_traits<::mlir::Operation> {
122+
using Operation = ::mlir::Operation;
123+
using op_iterator = simple_ilist<Operation>::iterator;
124+
125+
static void deleteNode(Operation *op);
126+
void addNodeToList(Operation *op);
127+
void removeNodeFromList(Operation *op);
128+
void transferNodesFromList(ilist_traits<Operation> &otherList,
129+
op_iterator first, op_iterator last);
130+
131+
private:
132+
mlir::Block *getContainingBlock();
133+
};
134+
135+
//===----------------------------------------------------------------------===//
136+
// ilist_traits for Block
137+
//===----------------------------------------------------------------------===//
138+
139+
template <>
140+
struct ilist_traits<::mlir::Block> : public ilist_alloc_traits<::mlir::Block> {
141+
using Block = ::mlir::Block;
142+
using block_iterator = simple_ilist<::mlir::Block>::iterator;
143+
144+
void addNodeToList(Block *block);
145+
void removeNodeFromList(Block *block);
146+
void transferNodesFromList(ilist_traits<Block> &otherList,
147+
block_iterator first, block_iterator last);
148+
149+
private:
150+
mlir::Region *getParentRegion();
151+
};
152+
153+
} // end namespace llvm
154+
155+
#endif // MLIR_IR_BLOCK_SUPPORT_H

mlir/lib/IR/Block.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,3 +257,13 @@ Block *PredecessorIterator::unwrap(BlockOperand &value) {
257257
unsigned PredecessorIterator::getSuccessorIndex() const {
258258
return I->getOperandNumber();
259259
}
260+
261+
//===----------------------------------------------------------------------===//
262+
// Successors
263+
//===----------------------------------------------------------------------===//
264+
265+
SuccessorRange::SuccessorRange(Block *block) : SuccessorRange(nullptr, 0) {
266+
if (Operation *term = block->getTerminator())
267+
if ((count = term->getNumSuccessors()))
268+
base = term->getBlockOperands().data();
269+
}

0 commit comments

Comments
 (0)