forked from OSchip/llvm-project
Remove const from mlir::Block.
This also eliminates some incorrect reinterpret_cast logic working around it, and numerous const-incorrect issues (like block argument iteration). PiperOrigin-RevId: 239712029
This commit is contained in:
parent
6ab2984b23
commit
3d6c74fff5
|
@ -142,11 +142,9 @@ public:
|
||||||
Block *createBody();
|
Block *createBody();
|
||||||
|
|
||||||
/// Get the body of the AffineForOp.
|
/// Get the body of the AffineForOp.
|
||||||
Block *getBody() { return &getRegion().front(); }
|
Block *getBody() const { return &getRegion().front(); }
|
||||||
const Block *getBody() const { return &getRegion().front(); }
|
|
||||||
|
|
||||||
/// Get the body region of the AffineForOp.
|
/// Get the body region of the AffineForOp.
|
||||||
Region &getRegion() { return getInstruction()->getRegion(0); }
|
|
||||||
Region &getRegion() const { return getInstruction()->getRegion(0); }
|
Region &getRegion() const { return getInstruction()->getRegion(0); }
|
||||||
|
|
||||||
/// Returns the induction variable for this loop.
|
/// Returns the induction variable for this loop.
|
||||||
|
|
|
@ -53,7 +53,7 @@ protected:
|
||||||
using super = DominanceInfoBase<IsPostDom>;
|
using super = DominanceInfoBase<IsPostDom>;
|
||||||
|
|
||||||
/// Return true if the specified block A properly dominates block B.
|
/// Return true if the specified block A properly dominates block B.
|
||||||
bool properlyDominates(const Block *a, const Block *b);
|
bool properlyDominates(Block *a, Block *b);
|
||||||
|
|
||||||
/// A mapping of regions to their base dominator tree.
|
/// A mapping of regions to their base dominator tree.
|
||||||
llvm::DenseMap<Region *, std::unique_ptr<base>> dominanceInfos;
|
llvm::DenseMap<Region *, std::unique_ptr<base>> dominanceInfos;
|
||||||
|
@ -82,12 +82,12 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return true if the specified block A dominates block B.
|
/// Return true if the specified block A dominates block B.
|
||||||
bool dominates(const Block *a, const Block *b) {
|
bool dominates(Block *a, Block *b) {
|
||||||
return a == b || properlyDominates(a, b);
|
return a == b || properlyDominates(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return true if the specified block A properly dominates block B.
|
/// Return true if the specified block A properly dominates block B.
|
||||||
bool properlyDominates(const Block *a, const Block *b) {
|
bool properlyDominates(Block *a, Block *b) {
|
||||||
return super::properlyDominates(a, b);
|
return super::properlyDominates(a, b);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -106,12 +106,12 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return true if the specified block A properly postdominates block B.
|
/// Return true if the specified block A properly postdominates block B.
|
||||||
bool properlyPostDominates(const Block *a, const Block *b) {
|
bool properlyPostDominates(Block *a, Block *b) {
|
||||||
return super::properlyDominates(a, b);
|
return super::properlyDominates(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return true if the specified block A postdominates block B.
|
/// Return true if the specified block A postdominates block B.
|
||||||
bool postDominates(const Block *a, const Block *b) {
|
bool postDominates(Block *a, Block *b) {
|
||||||
return a == b || properlyPostDominates(a, b);
|
return a == b || properlyPostDominates(a, b);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -230,8 +230,8 @@ public:
|
||||||
void operator()(ArrayRef<CapturableHandle> stmts);
|
void operator()(ArrayRef<CapturableHandle> stmts);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BlockBuilder(const BlockBuilder &) = delete;
|
BlockBuilder(BlockBuilder &) = delete;
|
||||||
BlockBuilder &operator=(const BlockBuilder &other) = delete;
|
BlockBuilder &operator=(BlockBuilder &other) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Base class for ValueHandle, InstructionHandle and BlockHandle.
|
/// Base class for ValueHandle, InstructionHandle and BlockHandle.
|
||||||
|
|
|
@ -76,8 +76,8 @@ class Function;
|
||||||
|
|
||||||
using BlockOperand = IROperandImpl<Block>;
|
using BlockOperand = IROperandImpl<Block>;
|
||||||
|
|
||||||
template <typename BlockType> class PredecessorIterator;
|
class PredecessorIterator;
|
||||||
template <typename BlockType> class SuccessorIterator;
|
class SuccessorIterator;
|
||||||
|
|
||||||
/// `Block` represents an ordered list of `Instruction`s.
|
/// `Block` represents an ordered list of `Instruction`s.
|
||||||
class Block : public IRObjectWithUseList,
|
class Block : public IRObjectWithUseList,
|
||||||
|
@ -97,19 +97,15 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Blocks are maintained in a Region.
|
/// Blocks are maintained in a Region.
|
||||||
Region *getParent() const { return parentValidInstOrderPair.getPointer(); }
|
Region *getParent() { return parentValidInstOrderPair.getPointer(); }
|
||||||
|
|
||||||
/// Returns the closest surrounding instruction that contains this block or
|
/// Returns the closest surrounding instruction that contains this block or
|
||||||
/// nullptr if this is a top-level block.
|
/// nullptr if this is a top-level block.
|
||||||
Instruction *getContainingInst();
|
Instruction *getContainingInst();
|
||||||
|
|
||||||
const Instruction *getContainingInst() const {
|
|
||||||
return const_cast<Block *>(this)->getContainingInst();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the function that this block is part of, even if the block is
|
/// Returns the function that this block is part of, even if the block is
|
||||||
/// nested under an operation region.
|
/// nested under an operation region.
|
||||||
Function *getFunction() const;
|
Function *getFunction();
|
||||||
|
|
||||||
/// Insert this block (which must not already be in a function) right before
|
/// Insert this block (which must not already be in a function) right before
|
||||||
/// the specified block.
|
/// the specified block.
|
||||||
|
@ -125,17 +121,16 @@ public:
|
||||||
// This is the list of arguments to the block.
|
// This is the list of arguments to the block.
|
||||||
using BlockArgListType = ArrayRef<BlockArgument *>;
|
using BlockArgListType = ArrayRef<BlockArgument *>;
|
||||||
|
|
||||||
// FIXME: Not const correct.
|
BlockArgListType getArguments() { return arguments; }
|
||||||
BlockArgListType getArguments() const { return arguments; }
|
|
||||||
|
|
||||||
using args_iterator = BlockArgListType::iterator;
|
using args_iterator = BlockArgListType::iterator;
|
||||||
using reverse_args_iterator = BlockArgListType::reverse_iterator;
|
using reverse_args_iterator = BlockArgListType::reverse_iterator;
|
||||||
args_iterator args_begin() const { return getArguments().begin(); }
|
args_iterator args_begin() { return getArguments().begin(); }
|
||||||
args_iterator args_end() const { return getArguments().end(); }
|
args_iterator args_end() { return getArguments().end(); }
|
||||||
reverse_args_iterator args_rbegin() const { return getArguments().rbegin(); }
|
reverse_args_iterator args_rbegin() { return getArguments().rbegin(); }
|
||||||
reverse_args_iterator args_rend() const { return getArguments().rend(); }
|
reverse_args_iterator args_rend() { return getArguments().rend(); }
|
||||||
|
|
||||||
bool args_empty() const { return arguments.empty(); }
|
bool args_empty() { return arguments.empty(); }
|
||||||
|
|
||||||
/// Add one value to the argument list.
|
/// Add one value to the argument list.
|
||||||
BlockArgument *addArgument(Type type);
|
BlockArgument *addArgument(Type type);
|
||||||
|
@ -146,9 +141,8 @@ public:
|
||||||
/// Erase the argument at 'index' and remove it from the argument list.
|
/// Erase the argument at 'index' and remove it from the argument list.
|
||||||
void eraseArgument(unsigned index);
|
void eraseArgument(unsigned index);
|
||||||
|
|
||||||
unsigned getNumArguments() const { return arguments.size(); }
|
unsigned getNumArguments() { return arguments.size(); }
|
||||||
BlockArgument *getArgument(unsigned i) { return arguments[i]; }
|
BlockArgument *getArgument(unsigned i) { return arguments[i]; }
|
||||||
const BlockArgument *getArgument(unsigned i) const { return arguments[i]; }
|
|
||||||
|
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
// Instruction list management
|
// Instruction list management
|
||||||
|
@ -157,44 +151,29 @@ public:
|
||||||
/// This is the list of instructions in the block.
|
/// This is the list of instructions in the block.
|
||||||
using InstListType = llvm::iplist<Instruction>;
|
using InstListType = llvm::iplist<Instruction>;
|
||||||
InstListType &getInstructions() { return instructions; }
|
InstListType &getInstructions() { return instructions; }
|
||||||
const InstListType &getInstructions() const { return instructions; }
|
|
||||||
|
|
||||||
// Iteration over the instructions in the block.
|
// Iteration over the instructions in the block.
|
||||||
using iterator = InstListType::iterator;
|
using iterator = InstListType::iterator;
|
||||||
using const_iterator = InstListType::const_iterator;
|
|
||||||
using reverse_iterator = InstListType::reverse_iterator;
|
using reverse_iterator = InstListType::reverse_iterator;
|
||||||
using const_reverse_iterator = InstListType::const_reverse_iterator;
|
|
||||||
|
|
||||||
iterator begin() { return instructions.begin(); }
|
iterator begin() { return instructions.begin(); }
|
||||||
iterator end() { return instructions.end(); }
|
iterator end() { return instructions.end(); }
|
||||||
const_iterator begin() const { return instructions.begin(); }
|
|
||||||
const_iterator end() const { return instructions.end(); }
|
|
||||||
reverse_iterator rbegin() { return instructions.rbegin(); }
|
reverse_iterator rbegin() { return instructions.rbegin(); }
|
||||||
reverse_iterator rend() { return instructions.rend(); }
|
reverse_iterator rend() { return instructions.rend(); }
|
||||||
const_reverse_iterator rbegin() const { return instructions.rbegin(); }
|
|
||||||
const_reverse_iterator rend() const { return instructions.rend(); }
|
|
||||||
|
|
||||||
bool empty() const { return instructions.empty(); }
|
bool empty() { return instructions.empty(); }
|
||||||
void push_back(Instruction *inst) { instructions.push_back(inst); }
|
void push_back(Instruction *inst) { instructions.push_back(inst); }
|
||||||
void push_front(Instruction *inst) { instructions.push_front(inst); }
|
void push_front(Instruction *inst) { instructions.push_front(inst); }
|
||||||
|
|
||||||
Instruction &back() { return instructions.back(); }
|
Instruction &back() { return instructions.back(); }
|
||||||
const Instruction &back() const { return const_cast<Block *>(this)->back(); }
|
|
||||||
Instruction &front() { return instructions.front(); }
|
Instruction &front() { return instructions.front(); }
|
||||||
const Instruction &front() const {
|
|
||||||
return const_cast<Block *>(this)->front();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns 'inst' if 'inst' lies in this block, or otherwise finds the
|
/// Returns 'inst' if 'inst' lies in this block, or otherwise finds the
|
||||||
/// ancestor instruction of 'inst' that lies in this block. Returns nullptr if
|
/// ancestor instruction of 'inst' that lies in this block. Returns nullptr if
|
||||||
/// the latter fails.
|
/// the latter fails.
|
||||||
/// TODO: This is very specific functionality that should live somewhere else,
|
/// TODO: This is very specific functionality that should live somewhere else,
|
||||||
/// probably in Dominance.cpp.
|
/// probably in Dominance.cpp.
|
||||||
Instruction *findAncestorInstInBlock(Instruction *inst);
|
Instruction *findAncestorInstInBlock(const Instruction &inst);
|
||||||
const Instruction *findAncestorInstInBlock(const Instruction &inst) const {
|
|
||||||
return const_cast<Block *>(this)->findAncestorInstInBlock(
|
|
||||||
const_cast<Instruction *>(&inst));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This drops all operand uses from instructions within this block, which is
|
/// This drops all operand uses from instructions within this block, which is
|
||||||
/// an essential step in breaking cyclic dependences between references when
|
/// an essential step in breaking cyclic dependences between references when
|
||||||
|
@ -203,7 +182,7 @@ public:
|
||||||
|
|
||||||
/// Returns true if the ordering of the child instructions is valid, false
|
/// Returns true if the ordering of the child instructions is valid, false
|
||||||
/// otherwise.
|
/// otherwise.
|
||||||
bool isInstOrderValid() const { return parentValidInstOrderPair.getInt(); }
|
bool isInstOrderValid() { return parentValidInstOrderPair.getInt(); }
|
||||||
|
|
||||||
/// Invalidates the current ordering of instructions.
|
/// Invalidates the current ordering of instructions.
|
||||||
void invalidateInstOrder() {
|
void invalidateInstOrder() {
|
||||||
|
@ -214,7 +193,7 @@ public:
|
||||||
|
|
||||||
/// Verifies the current ordering of child instructions matches the
|
/// Verifies the current ordering of child instructions matches the
|
||||||
/// validInstOrder flag. Returns false if the order is valid, true otherwise.
|
/// validInstOrder flag. Returns false if the order is valid, true otherwise.
|
||||||
bool verifyInstOrder() const;
|
bool verifyInstOrder();
|
||||||
|
|
||||||
/// Recomputes the ordering of child instructions within the block.
|
/// Recomputes the ordering of child instructions within the block.
|
||||||
void recomputeInstOrder();
|
void recomputeInstOrder();
|
||||||
|
@ -227,27 +206,18 @@ public:
|
||||||
/// the block has a valid terminator instruction.
|
/// the block has a valid terminator instruction.
|
||||||
Instruction *getTerminator();
|
Instruction *getTerminator();
|
||||||
|
|
||||||
const Instruction *getTerminator() const {
|
|
||||||
return const_cast<Block *>(this)->getTerminator();
|
|
||||||
}
|
|
||||||
|
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
// Predecessors and successors.
|
// Predecessors and successors.
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
|
|
||||||
// Predecessor iteration.
|
// Predecessor iteration.
|
||||||
using const_pred_iterator = PredecessorIterator<const Block>;
|
using pred_iterator = PredecessorIterator;
|
||||||
const_pred_iterator pred_begin() const;
|
|
||||||
const_pred_iterator pred_end() const;
|
|
||||||
llvm::iterator_range<const_pred_iterator> getPredecessors() const;
|
|
||||||
|
|
||||||
using pred_iterator = PredecessorIterator<Block>;
|
|
||||||
pred_iterator pred_begin();
|
pred_iterator pred_begin();
|
||||||
pred_iterator pred_end();
|
pred_iterator pred_end();
|
||||||
llvm::iterator_range<pred_iterator> getPredecessors();
|
llvm::iterator_range<pred_iterator> getPredecessors();
|
||||||
|
|
||||||
/// Return true if this block has no predecessors.
|
/// Return true if this block has no predecessors.
|
||||||
bool hasNoPredecessors() const;
|
bool hasNoPredecessors();
|
||||||
|
|
||||||
/// If this block has exactly one predecessor, return it. Otherwise, return
|
/// If this block has exactly one predecessor, return it. Otherwise, return
|
||||||
/// null.
|
/// null.
|
||||||
|
@ -257,24 +227,12 @@ public:
|
||||||
/// destinations) is not considered to be a single predecessor.
|
/// destinations) is not considered to be a single predecessor.
|
||||||
Block *getSinglePredecessor();
|
Block *getSinglePredecessor();
|
||||||
|
|
||||||
const Block *getSinglePredecessor() const {
|
|
||||||
return const_cast<Block *>(this)->getSinglePredecessor();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Indexed successor access.
|
// Indexed successor access.
|
||||||
unsigned getNumSuccessors() const;
|
unsigned getNumSuccessors();
|
||||||
const Block *getSuccessor(unsigned i) const {
|
|
||||||
return const_cast<Block *>(this)->getSuccessor(i);
|
|
||||||
}
|
|
||||||
Block *getSuccessor(unsigned i);
|
Block *getSuccessor(unsigned i);
|
||||||
|
|
||||||
// Successor iteration.
|
// Successor iteration.
|
||||||
using const_succ_iterator = SuccessorIterator<const Block>;
|
using succ_iterator = SuccessorIterator;
|
||||||
const_succ_iterator succ_begin() const;
|
|
||||||
const_succ_iterator succ_end() const;
|
|
||||||
llvm::iterator_range<const_succ_iterator> getSuccessors() const;
|
|
||||||
|
|
||||||
using succ_iterator = SuccessorIterator<Block>;
|
|
||||||
succ_iterator succ_begin();
|
succ_iterator succ_begin();
|
||||||
succ_iterator succ_end();
|
succ_iterator succ_end();
|
||||||
llvm::iterator_range<succ_iterator> getSuccessors();
|
llvm::iterator_range<succ_iterator> getSuccessors();
|
||||||
|
@ -325,8 +283,8 @@ public:
|
||||||
return &Block::instructions;
|
return &Block::instructions;
|
||||||
}
|
}
|
||||||
|
|
||||||
void print(raw_ostream &os) const;
|
void print(raw_ostream &os);
|
||||||
void dump() const;
|
void dump();
|
||||||
|
|
||||||
/// Print out the name of the block without printing its body.
|
/// Print out the name of the block without printing its body.
|
||||||
/// NOTE: The printType argument is ignored. We keep it for compatibility
|
/// NOTE: The printType argument is ignored. We keep it for compatibility
|
||||||
|
@ -344,8 +302,8 @@ private:
|
||||||
/// This is the list of arguments to the block.
|
/// This is the list of arguments to the block.
|
||||||
std::vector<BlockArgument *> arguments;
|
std::vector<BlockArgument *> arguments;
|
||||||
|
|
||||||
Block(const Block &) = delete;
|
Block(Block &) = delete;
|
||||||
void operator=(const Block &) = delete;
|
void operator=(Block &) = delete;
|
||||||
|
|
||||||
friend struct llvm::ilist_traits<Block>;
|
friend struct llvm::ilist_traits<Block>;
|
||||||
};
|
};
|
||||||
|
@ -437,28 +395,23 @@ private:
|
||||||
/// BlockOperands that are embedded into terminator instructions. From the
|
/// BlockOperands that are embedded into terminator instructions. From the
|
||||||
/// operand, we can get the terminator that contains it, and it's parent block
|
/// operand, we can get the terminator that contains it, and it's parent block
|
||||||
/// is the predecessor.
|
/// is the predecessor.
|
||||||
template <typename BlockType>
|
|
||||||
class PredecessorIterator
|
class PredecessorIterator
|
||||||
: public llvm::iterator_facade_base<PredecessorIterator<BlockType>,
|
: public llvm::iterator_facade_base<PredecessorIterator,
|
||||||
std::forward_iterator_tag,
|
std::forward_iterator_tag, Block *> {
|
||||||
BlockType *> {
|
|
||||||
public:
|
public:
|
||||||
PredecessorIterator(BlockOperand *firstOperand)
|
PredecessorIterator(BlockOperand *firstOperand)
|
||||||
: bbUseIterator(firstOperand) {}
|
: bbUseIterator(firstOperand) {}
|
||||||
|
|
||||||
PredecessorIterator &operator=(const PredecessorIterator &rhs) {
|
PredecessorIterator &operator=(const PredecessorIterator &rhs) {
|
||||||
bbUseIterator = rhs.bbUseIterator;
|
bbUseIterator = rhs.bbUseIterator;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const PredecessorIterator &rhs) const {
|
bool operator==(const PredecessorIterator &rhs) const {
|
||||||
return bbUseIterator == rhs.bbUseIterator;
|
return bbUseIterator == rhs.bbUseIterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockType *operator*() const {
|
Block *operator*() const;
|
||||||
// The use iterator points to an operand of a terminator. The predecessor
|
|
||||||
// we return is the block that the terminator is embedded into.
|
|
||||||
return bbUseIterator.getUser()->getBlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
PredecessorIterator &operator++() {
|
PredecessorIterator &operator++() {
|
||||||
++bbUseIterator;
|
++bbUseIterator;
|
||||||
|
@ -466,28 +419,13 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the successor number in the predecessor terminator.
|
/// Get the successor number in the predecessor terminator.
|
||||||
unsigned getSuccessorIndex() const {
|
unsigned getSuccessorIndex() const;
|
||||||
return bbUseIterator->getOperandNumber();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using BBUseIterator = ValueUseIterator<BlockOperand>;
|
using BBUseIterator = ValueUseIterator<BlockOperand>;
|
||||||
BBUseIterator bbUseIterator;
|
BBUseIterator bbUseIterator;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline auto Block::pred_begin() const -> const_pred_iterator {
|
|
||||||
return const_pred_iterator((BlockOperand *)getFirstUse());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline auto Block::pred_end() const -> const_pred_iterator {
|
|
||||||
return const_pred_iterator(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline auto Block::getPredecessors() const
|
|
||||||
-> llvm::iterator_range<const_pred_iterator> {
|
|
||||||
return {pred_begin(), pred_end()};
|
|
||||||
}
|
|
||||||
|
|
||||||
inline auto Block::pred_begin() -> pred_iterator {
|
inline auto Block::pred_begin() -> pred_iterator {
|
||||||
return pred_iterator((BlockOperand *)getFirstUse());
|
return pred_iterator((BlockOperand *)getFirstUse());
|
||||||
}
|
}
|
||||||
|
@ -505,46 +443,23 @@ inline auto Block::getPredecessors() -> llvm::iterator_range<pred_iterator> {
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
/// This template implements the successor iterators for Block.
|
/// This template implements the successor iterators for Block.
|
||||||
template <typename BlockType>
|
|
||||||
class SuccessorIterator final
|
class SuccessorIterator final
|
||||||
: public IndexedAccessorIterator<SuccessorIterator<BlockType>, BlockType,
|
: public IndexedAccessorIterator<SuccessorIterator, Block, Block> {
|
||||||
BlockType> {
|
|
||||||
public:
|
public:
|
||||||
/// Initializes the result iterator to the specified index.
|
/// Initializes the result iterator to the specified index.
|
||||||
SuccessorIterator(BlockType *object, unsigned index)
|
SuccessorIterator(Block *object, unsigned index)
|
||||||
: IndexedAccessorIterator<SuccessorIterator<BlockType>, BlockType,
|
: IndexedAccessorIterator<SuccessorIterator, Block, Block>(object,
|
||||||
BlockType>(object, index) {}
|
index) {}
|
||||||
|
|
||||||
SuccessorIterator(const SuccessorIterator &other)
|
SuccessorIterator(const SuccessorIterator &other)
|
||||||
: SuccessorIterator(other.object, other.index) {}
|
: SuccessorIterator(other.object, other.index) {}
|
||||||
|
|
||||||
/// Support converting to the const variant. This will be a no-op for const
|
Block *operator*() const { return this->object->getSuccessor(this->index); }
|
||||||
/// variant.
|
|
||||||
operator SuccessorIterator<const BlockType>() const {
|
|
||||||
return SuccessorIterator<const BlockType>(this->object, this->index);
|
|
||||||
}
|
|
||||||
|
|
||||||
BlockType *operator*() const {
|
|
||||||
return this->object->getSuccessor(this->index);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the successor number in the terminator.
|
/// Get the successor number in the terminator.
|
||||||
unsigned getSuccessorIndex() const { return this->index; }
|
unsigned getSuccessorIndex() const { return this->index; }
|
||||||
};
|
};
|
||||||
|
|
||||||
inline auto Block::succ_begin() const -> const_succ_iterator {
|
|
||||||
return const_succ_iterator(this, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline auto Block::succ_end() const -> const_succ_iterator {
|
|
||||||
return const_succ_iterator(this, getNumSuccessors());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline auto Block::getSuccessors() const
|
|
||||||
-> llvm::iterator_range<const_succ_iterator> {
|
|
||||||
return {succ_begin(), succ_end()};
|
|
||||||
}
|
|
||||||
|
|
||||||
inline auto Block::succ_begin() -> succ_iterator {
|
inline auto Block::succ_begin() -> succ_iterator {
|
||||||
return succ_iterator(this, 0);
|
return succ_iterator(this, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ class BlockAndValueMapping {
|
||||||
public:
|
public:
|
||||||
/// Inserts a new mapping for 'from' to 'to'. If there is an existing mapping,
|
/// Inserts a new mapping for 'from' to 'to'. If there is an existing mapping,
|
||||||
/// it is overwritten.
|
/// it is overwritten.
|
||||||
void map(const Block *from, Block *to) { valueMap[from] = to; }
|
void map(Block *from, Block *to) { valueMap[from] = to; }
|
||||||
void map(const Value *from, Value *to) { valueMap[from] = to; }
|
void map(const Value *from, Value *to) { valueMap[from] = to; }
|
||||||
|
|
||||||
/// Erases a mapping for 'from'.
|
/// Erases a mapping for 'from'.
|
||||||
|
@ -49,7 +49,7 @@ public:
|
||||||
|
|
||||||
/// Lookup a mapped value within the map. If a mapping for the provided value
|
/// Lookup a mapped value within the map. If a mapping for the provided value
|
||||||
/// does not exist then return nullptr.
|
/// does not exist then return nullptr.
|
||||||
Block *lookupOrNull(const Block *from) const {
|
Block *lookupOrNull(Block *from) const {
|
||||||
return lookupOrValue(from, (Block *)nullptr);
|
return lookupOrValue(from, (Block *)nullptr);
|
||||||
}
|
}
|
||||||
Value *lookupOrNull(const Value *from) const {
|
Value *lookupOrNull(const Value *from) const {
|
||||||
|
|
|
@ -41,19 +41,6 @@ template <> struct GraphTraits<mlir::Block *> {
|
||||||
static ChildIteratorType child_end(NodeRef node) { return node->succ_end(); }
|
static ChildIteratorType child_end(NodeRef node) { return node->succ_end(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> struct GraphTraits<const mlir::Block *> {
|
|
||||||
using ChildIteratorType = mlir::Block::const_succ_iterator;
|
|
||||||
using Node = const mlir::Block;
|
|
||||||
using NodeRef = Node *;
|
|
||||||
|
|
||||||
static NodeRef getEntryNode(NodeRef bb) { return bb; }
|
|
||||||
|
|
||||||
static ChildIteratorType child_begin(NodeRef node) {
|
|
||||||
return node->succ_begin();
|
|
||||||
}
|
|
||||||
static ChildIteratorType child_end(NodeRef node) { return node->succ_end(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <> struct GraphTraits<Inverse<mlir::Block *>> {
|
template <> struct GraphTraits<Inverse<mlir::Block *>> {
|
||||||
using ChildIteratorType = mlir::Block::pred_iterator;
|
using ChildIteratorType = mlir::Block::pred_iterator;
|
||||||
using Node = mlir::Block;
|
using Node = mlir::Block;
|
||||||
|
@ -69,22 +56,6 @@ template <> struct GraphTraits<Inverse<mlir::Block *>> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> struct GraphTraits<Inverse<const mlir::Block *>> {
|
|
||||||
using ChildIteratorType = mlir::Block::const_pred_iterator;
|
|
||||||
using Node = const mlir::Block;
|
|
||||||
using NodeRef = Node *;
|
|
||||||
|
|
||||||
static NodeRef getEntryNode(Inverse<NodeRef> inverseGraph) {
|
|
||||||
return inverseGraph.Graph;
|
|
||||||
}
|
|
||||||
static inline ChildIteratorType child_begin(NodeRef node) {
|
|
||||||
return node->pred_begin();
|
|
||||||
}
|
|
||||||
static inline ChildIteratorType child_end(NodeRef node) {
|
|
||||||
return node->pred_end();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct GraphTraits<mlir::Function *> : public GraphTraits<mlir::Block *> {
|
struct GraphTraits<mlir::Function *> : public GraphTraits<mlir::Block *> {
|
||||||
using GraphType = mlir::Function *;
|
using GraphType = mlir::Function *;
|
||||||
|
|
|
@ -88,8 +88,7 @@ public:
|
||||||
Instruction *clone(MLIRContext *context) const;
|
Instruction *clone(MLIRContext *context) const;
|
||||||
|
|
||||||
/// Returns the instruction block that contains this instruction.
|
/// Returns the instruction block that contains this instruction.
|
||||||
const Block *getBlock() const { return block; }
|
Block *getBlock() const { return block; }
|
||||||
Block *getBlock() { return block; }
|
|
||||||
|
|
||||||
/// Return the context this operation is associated with.
|
/// Return the context this operation is associated with.
|
||||||
MLIRContext *getContext() const;
|
MLIRContext *getContext() const;
|
||||||
|
@ -337,13 +336,10 @@ public:
|
||||||
return getTrailingObjects<unsigned>()[index];
|
return getTrailingObjects<unsigned>()[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
Block *getSuccessor(unsigned index) {
|
Block *getSuccessor(unsigned index) const {
|
||||||
assert(index < getNumSuccessors());
|
assert(index < getNumSuccessors());
|
||||||
return getBlockOperands()[index].get();
|
return getBlockOperands()[index].get();
|
||||||
}
|
}
|
||||||
const Block *getSuccessor(unsigned index) const {
|
|
||||||
return const_cast<Instruction *>(this)->getSuccessor(index);
|
|
||||||
}
|
|
||||||
void setSuccessor(Block *block, unsigned index);
|
void setSuccessor(Block *block, unsigned index);
|
||||||
|
|
||||||
/// Erase a specific operand from the operand list of the successor at
|
/// Erase a specific operand from the operand list of the successor at
|
||||||
|
@ -517,7 +513,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provide a 'getParent' method for ilist_node_with_parent methods.
|
// Provide a 'getParent' method for ilist_node_with_parent methods.
|
||||||
const Block *getParent() const { return getBlock(); }
|
Block *getParent() const { return getBlock(); }
|
||||||
|
|
||||||
/// The instruction block that containts this instruction.
|
/// The instruction block that containts this instruction.
|
||||||
Block *block = nullptr;
|
Block *block = nullptr;
|
||||||
|
|
|
@ -787,10 +787,7 @@ public:
|
||||||
return this->getInstruction()->getNumSuccessorOperands(index);
|
return this->getInstruction()->getNumSuccessorOperands(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Block *getSuccessor(unsigned index) const {
|
Block *getSuccessor(unsigned index) const {
|
||||||
return this->getInstruction()->getSuccessor(index);
|
|
||||||
}
|
|
||||||
Block *getSuccessor(unsigned index) {
|
|
||||||
return this->getInstruction()->getSuccessor(index);
|
return this->getInstruction()->getSuccessor(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -116,8 +116,7 @@ public:
|
||||||
/// Return the function that this argument is defined in.
|
/// Return the function that this argument is defined in.
|
||||||
Function *getFunction() const;
|
Function *getFunction() const;
|
||||||
|
|
||||||
Block *getOwner() { return owner; }
|
Block *getOwner() const { return owner; }
|
||||||
const Block *getOwner() const { return owner; }
|
|
||||||
|
|
||||||
/// Returns the number of this argument.
|
/// Returns the number of this argument.
|
||||||
unsigned getArgNumber() const;
|
unsigned getArgNumber() const;
|
||||||
|
|
|
@ -113,9 +113,7 @@ public:
|
||||||
|
|
||||||
/// Return the block this branch jumps to.
|
/// Return the block this branch jumps to.
|
||||||
Block *getDest();
|
Block *getDest();
|
||||||
const Block *getDest() const {
|
Block *getDest() const { return const_cast<BranchOp *>(this)->getDest(); }
|
||||||
return const_cast<BranchOp *>(this)->getDest();
|
|
||||||
}
|
|
||||||
void setDest(Block *block);
|
void setDest(Block *block);
|
||||||
|
|
||||||
/// Erase the operand at 'index' from the operand list.
|
/// Erase the operand at 'index' from the operand list.
|
||||||
|
@ -322,13 +320,13 @@ public:
|
||||||
|
|
||||||
/// Return the destination if the condition is true.
|
/// Return the destination if the condition is true.
|
||||||
Block *getTrueDest();
|
Block *getTrueDest();
|
||||||
const Block *getTrueDest() const {
|
Block *getTrueDest() const {
|
||||||
return const_cast<CondBranchOp *>(this)->getTrueDest();
|
return const_cast<CondBranchOp *>(this)->getTrueDest();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the destination if the condition is false.
|
/// Return the destination if the condition is false.
|
||||||
Block *getFalseDest();
|
Block *getFalseDest();
|
||||||
const Block *getFalseDest() const {
|
Block *getFalseDest() const {
|
||||||
return const_cast<CondBranchOp *>(this)->getFalseDest();
|
return const_cast<CondBranchOp *>(this)->getFalseDest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -576,7 +576,7 @@ bool AffineForOp::verify() const {
|
||||||
|
|
||||||
// Check that the body defines as single block argument for the induction
|
// Check that the body defines as single block argument for the induction
|
||||||
// variable.
|
// variable.
|
||||||
const auto *body = getBody();
|
auto *body = getBody();
|
||||||
if (body->getNumArguments() != 1 ||
|
if (body->getNumArguments() != 1 ||
|
||||||
!body->getArgument(0)->getType().isIndex())
|
!body->getArgument(0)->getType().isIndex())
|
||||||
return emitOpError("expected body to have a single index argument for the "
|
return emitOpError("expected body to have a single index argument for the "
|
||||||
|
@ -1068,7 +1068,7 @@ bool AffineIfOp::verify() const {
|
||||||
if (region.front().back().isKnownTerminator())
|
if (region.front().back().isKnownTerminator())
|
||||||
return emitOpError("expects region block to not have a terminator");
|
return emitOpError("expects region block to not have a terminator");
|
||||||
|
|
||||||
for (const auto &b : region)
|
for (auto &b : region)
|
||||||
if (b.getNumArguments() != 0)
|
if (b.getNumArguments() != 0)
|
||||||
return emitOpError(
|
return emitOpError(
|
||||||
"requires that child entry blocks have no arguments");
|
"requires that child entry blocks have no arguments");
|
||||||
|
|
|
@ -532,10 +532,10 @@ static unsigned getNumCommonLoops(const FlatAffineConstraints &srcDomain,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns Block common to 'srcAccess.opInst' and 'dstAccess.opInst'.
|
// Returns Block common to 'srcAccess.opInst' and 'dstAccess.opInst'.
|
||||||
static const Block *getCommonBlock(const MemRefAccess &srcAccess,
|
static Block *getCommonBlock(const MemRefAccess &srcAccess,
|
||||||
const MemRefAccess &dstAccess,
|
const MemRefAccess &dstAccess,
|
||||||
const FlatAffineConstraints &srcDomain,
|
const FlatAffineConstraints &srcDomain,
|
||||||
unsigned numCommonLoops) {
|
unsigned numCommonLoops) {
|
||||||
if (numCommonLoops == 0) {
|
if (numCommonLoops == 0) {
|
||||||
auto *block = srcAccess.opInst->getBlock();
|
auto *block = srcAccess.opInst->getBlock();
|
||||||
while (block->getContainingInst()) {
|
while (block->getContainingInst()) {
|
||||||
|
|
|
@ -60,8 +60,7 @@ void DominanceInfoBase<IsPostDom>::recalculate(Function *function) {
|
||||||
|
|
||||||
/// Return true if the specified block A properly dominates block B.
|
/// Return true if the specified block A properly dominates block B.
|
||||||
template <bool IsPostDom>
|
template <bool IsPostDom>
|
||||||
bool DominanceInfoBase<IsPostDom>::properlyDominates(const Block *a,
|
bool DominanceInfoBase<IsPostDom>::properlyDominates(Block *a, Block *b) {
|
||||||
const Block *b) {
|
|
||||||
// A block dominates itself but does not properly dominate itself.
|
// A block dominates itself but does not properly dominate itself.
|
||||||
if (a == b)
|
if (a == b)
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -433,11 +433,12 @@ template LogicalResult mlir::boundCheckLoadOrStoreOp(OpPointer<StoreOp> storeOp,
|
||||||
// Block from the Block containing instruction, stopping at 'limitBlock'.
|
// Block from the Block containing instruction, stopping at 'limitBlock'.
|
||||||
static void findInstPosition(const Instruction *inst, Block *limitBlock,
|
static void findInstPosition(const Instruction *inst, Block *limitBlock,
|
||||||
SmallVectorImpl<unsigned> *positions) {
|
SmallVectorImpl<unsigned> *positions) {
|
||||||
const Block *block = inst->getBlock();
|
Block *block = inst->getBlock();
|
||||||
while (block != limitBlock) {
|
while (block != limitBlock) {
|
||||||
// FIXME: This algorithm is unnecessarily O(n) and should be improved to not
|
// FIXME: This algorithm is unnecessarily O(n) and should be improved to not
|
||||||
// rely on linear scans.
|
// rely on linear scans.
|
||||||
int instPosInBlock = std::distance(block->begin(), inst->getIterator());
|
int instPosInBlock = std::distance(
|
||||||
|
block->begin(), const_cast<Instruction *>(inst)->getIterator());
|
||||||
positions->push_back(instPosInBlock);
|
positions->push_back(instPosInBlock);
|
||||||
inst = block->getContainingInst();
|
inst = block->getContainingInst();
|
||||||
block = inst->getBlock();
|
block = inst->getBlock();
|
||||||
|
@ -680,20 +681,15 @@ unsigned mlir::getNumCommonSurroundingLoops(const Instruction &A,
|
||||||
return numCommonLoops;
|
return numCommonLoops;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Optional<int64_t> getMemoryFootprintBytes(const Block &block,
|
static Optional<int64_t> getMemoryFootprintBytes(Block &block,
|
||||||
Block::const_iterator start,
|
Block::iterator start,
|
||||||
Block::const_iterator end,
|
Block::iterator end,
|
||||||
int memorySpace) {
|
int memorySpace) {
|
||||||
SmallDenseMap<Value *, std::unique_ptr<MemRefRegion>, 4> regions;
|
SmallDenseMap<Value *, std::unique_ptr<MemRefRegion>, 4> regions;
|
||||||
|
|
||||||
// Cast away constness since the walker uses non-const versions; but we
|
|
||||||
// guarantee that the visitor callback isn't mutating opInst.
|
|
||||||
auto *cStart = reinterpret_cast<Block::iterator *>(&start);
|
|
||||||
auto *cEnd = reinterpret_cast<Block::iterator *>(&end);
|
|
||||||
|
|
||||||
// Walk this 'for' instruction to gather all memory regions.
|
// Walk this 'for' instruction to gather all memory regions.
|
||||||
bool error = false;
|
bool error = false;
|
||||||
const_cast<Block *>(&block)->walk(*cStart, *cEnd, [&](Instruction *opInst) {
|
const_cast<Block *>(&block)->walk(start, end, [&](Instruction *opInst) {
|
||||||
if (!opInst->isa<LoadOp>() && !opInst->isa<StoreOp>()) {
|
if (!opInst->isa<LoadOp>() && !opInst->isa<StoreOp>()) {
|
||||||
// Neither load nor a store op.
|
// Neither load nor a store op.
|
||||||
return;
|
return;
|
||||||
|
@ -737,8 +733,8 @@ Optional<int64_t> mlir::getMemoryFootprintBytes(OpPointer<AffineForOp> forOp,
|
||||||
int memorySpace) {
|
int memorySpace) {
|
||||||
auto *forInst = forOp->getInstruction();
|
auto *forInst = forOp->getInstruction();
|
||||||
return ::getMemoryFootprintBytes(
|
return ::getMemoryFootprintBytes(
|
||||||
*forInst->getBlock(), Block::const_iterator(forInst),
|
*forInst->getBlock(), Block::iterator(forInst),
|
||||||
std::next(Block::const_iterator(forInst)), memorySpace);
|
std::next(Block::iterator(forInst)), memorySpace);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns in 'sequentialLoops' all sequential loops in loop nest rooted
|
/// Returns in 'sequentialLoops' all sequential loops in loop nest rooted
|
||||||
|
|
|
@ -60,7 +60,7 @@ public:
|
||||||
return fn.emitError(message);
|
return fn.emitError(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool failure(const Twine &message, const Block &bb) {
|
bool failure(const Twine &message, Block &bb) {
|
||||||
// Take the location information for the first instruction in the block.
|
// Take the location information for the first instruction in the block.
|
||||||
if (!bb.empty())
|
if (!bb.empty())
|
||||||
return failure(message, bb.front());
|
return failure(message, bb.front());
|
||||||
|
@ -107,9 +107,9 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool verify();
|
bool verify();
|
||||||
bool verifyBlock(const Block &block, bool isTopLevel);
|
bool verifyBlock(Block &block, bool isTopLevel);
|
||||||
bool verifyOperation(const Instruction &op);
|
bool verifyOperation(const Instruction &op);
|
||||||
bool verifyDominance(const Block &block);
|
bool verifyDominance(Block &block);
|
||||||
bool verifyInstDominance(const Instruction &inst);
|
bool verifyInstDominance(const Instruction &inst);
|
||||||
|
|
||||||
explicit FuncVerifier(Function &fn)
|
explicit FuncVerifier(Function &fn)
|
||||||
|
@ -221,7 +221,7 @@ bool FuncVerifier::verify() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns if the given block is allowed to have no terminator.
|
// Returns if the given block is allowed to have no terminator.
|
||||||
static bool canBlockHaveNoTerminator(const Block &block) {
|
static bool canBlockHaveNoTerminator(Block &block) {
|
||||||
// Allow the first block of an operation region to have no terminator if it is
|
// Allow the first block of an operation region to have no terminator if it is
|
||||||
// the only block in the region.
|
// the only block in the region.
|
||||||
auto *parentList = block.getParent();
|
auto *parentList = block.getParent();
|
||||||
|
@ -229,7 +229,7 @@ static bool canBlockHaveNoTerminator(const Block &block) {
|
||||||
std::next(parentList->begin()) == parentList->end();
|
std::next(parentList->begin()) == parentList->end();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FuncVerifier::verifyBlock(const Block &block, bool isTopLevel) {
|
bool FuncVerifier::verifyBlock(Block &block, bool isTopLevel) {
|
||||||
for (auto *arg : block.getArguments()) {
|
for (auto *arg : block.getArguments()) {
|
||||||
if (arg->getOwner() != &block)
|
if (arg->getOwner() != &block)
|
||||||
return failure("block argument not owned by block", block);
|
return failure("block argument not owned by block", block);
|
||||||
|
@ -262,7 +262,7 @@ bool FuncVerifier::verifyBlock(const Block &block, bool isTopLevel) {
|
||||||
|
|
||||||
// Verify that this block is not branching to a block of a different
|
// Verify that this block is not branching to a block of a different
|
||||||
// region.
|
// region.
|
||||||
for (const Block *successor : block.getSuccessors())
|
for (Block *successor : block.getSuccessors())
|
||||||
if (successor->getParent() != block.getParent())
|
if (successor->getParent() != block.getParent())
|
||||||
return failure("branching to block of a different region", block.back());
|
return failure("branching to block of a different region", block.back());
|
||||||
|
|
||||||
|
@ -314,7 +314,7 @@ bool FuncVerifier::verifyOperation(const Instruction &op) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FuncVerifier::verifyDominance(const Block &block) {
|
bool FuncVerifier::verifyDominance(Block &block) {
|
||||||
// Verify the dominance of each of the held instructions.
|
// Verify the dominance of each of the held instructions.
|
||||||
for (auto &inst : block)
|
for (auto &inst : block)
|
||||||
if (verifyInstDominance(inst))
|
if (verifyInstDominance(inst))
|
||||||
|
|
|
@ -1061,7 +1061,7 @@ public:
|
||||||
|
|
||||||
// Methods to print instructions.
|
// Methods to print instructions.
|
||||||
void print(const Instruction *inst);
|
void print(const Instruction *inst);
|
||||||
void print(const Block *block, bool printBlockArgs = true);
|
void print(Block *block, bool printBlockArgs = true);
|
||||||
|
|
||||||
void printOperation(const Instruction *op);
|
void printOperation(const Instruction *op);
|
||||||
void printGenericOp(const Instruction *op);
|
void printGenericOp(const Instruction *op);
|
||||||
|
@ -1094,7 +1094,7 @@ public:
|
||||||
|
|
||||||
enum { nameSentinel = ~0U };
|
enum { nameSentinel = ~0U };
|
||||||
|
|
||||||
void printBlockName(const Block *block) {
|
void printBlockName(Block *block) {
|
||||||
auto id = getBlockID(block);
|
auto id = getBlockID(block);
|
||||||
if (id != ~0U)
|
if (id != ~0U)
|
||||||
os << "^bb" << id;
|
os << "^bb" << id;
|
||||||
|
@ -1102,7 +1102,7 @@ public:
|
||||||
os << "^INVALIDBLOCK";
|
os << "^INVALIDBLOCK";
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned getBlockID(const Block *block) {
|
unsigned getBlockID(Block *block) {
|
||||||
auto it = blockIDs.find(block);
|
auto it = blockIDs.find(block);
|
||||||
return it != blockIDs.end() ? it->second : ~0U;
|
return it != blockIDs.end() ? it->second : ~0U;
|
||||||
}
|
}
|
||||||
|
@ -1128,7 +1128,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void numberValueID(const Value *value);
|
void numberValueID(const Value *value);
|
||||||
void numberValuesInBlock(const Block &block);
|
void numberValuesInBlock(Block &block);
|
||||||
void printValueID(const Value *value, bool printResultNo = true) const;
|
void printValueID(const Value *value, bool printResultNo = true) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -1140,7 +1140,7 @@ private:
|
||||||
DenseMap<const Value *, StringRef> valueNames;
|
DenseMap<const Value *, StringRef> valueNames;
|
||||||
|
|
||||||
/// This is the block ID for each block in the current function.
|
/// This is the block ID for each block in the current function.
|
||||||
DenseMap<const Block *, unsigned> blockIDs;
|
DenseMap<Block *, unsigned> blockIDs;
|
||||||
|
|
||||||
/// This keeps track of all of the non-numeric names that are in flight,
|
/// This keeps track of all of the non-numeric names that are in flight,
|
||||||
/// allowing us to check for duplicates.
|
/// allowing us to check for duplicates.
|
||||||
|
@ -1172,7 +1172,7 @@ FunctionPrinter::FunctionPrinter(Function *function, ModulePrinter &other)
|
||||||
/// Number all of the SSA values in the specified block. Values get numbered
|
/// Number all of the SSA values in the specified block. Values get numbered
|
||||||
/// continuously throughout regions. In particular, we traverse the regions
|
/// continuously throughout regions. In particular, we traverse the regions
|
||||||
/// held by operations and number values in depth-first pre-order.
|
/// held by operations and number values in depth-first pre-order.
|
||||||
void FunctionPrinter::numberValuesInBlock(const Block &block) {
|
void FunctionPrinter::numberValuesInBlock(Block &block) {
|
||||||
// Each block gets a unique ID, and all of the instructions within it get
|
// Each block gets a unique ID, and all of the instructions within it get
|
||||||
// numbered as well.
|
// numbered as well.
|
||||||
blockIDs[&block] = nextBlockID++;
|
blockIDs[&block] = nextBlockID++;
|
||||||
|
@ -1186,7 +1186,7 @@ void FunctionPrinter::numberValuesInBlock(const Block &block) {
|
||||||
if (inst.getNumResults() != 0)
|
if (inst.getNumResults() != 0)
|
||||||
numberValueID(inst.getResult(0));
|
numberValueID(inst.getResult(0));
|
||||||
for (auto ®ion : inst.getRegions())
|
for (auto ®ion : inst.getRegions())
|
||||||
for (const auto &block : region)
|
for (auto &block : region)
|
||||||
numberValuesInBlock(block);
|
numberValuesInBlock(block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1337,7 +1337,7 @@ void FunctionPrinter::printFunctionSignature() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FunctionPrinter::print(const Block *block, bool printBlockArgs) {
|
void FunctionPrinter::print(Block *block, bool printBlockArgs) {
|
||||||
// Print the block label and argument list if requested.
|
// Print the block label and argument list if requested.
|
||||||
if (printBlockArgs) {
|
if (printBlockArgs) {
|
||||||
os.indent(currentIndent);
|
os.indent(currentIndent);
|
||||||
|
@ -1346,7 +1346,7 @@ void FunctionPrinter::print(const Block *block, bool printBlockArgs) {
|
||||||
// Print the argument list if non-empty.
|
// Print the argument list if non-empty.
|
||||||
if (!block->args_empty()) {
|
if (!block->args_empty()) {
|
||||||
os << '(';
|
os << '(';
|
||||||
interleaveComma(block->getArguments(), [&](const BlockArgument *arg) {
|
interleaveComma(block->getArguments(), [&](BlockArgument *arg) {
|
||||||
printValueID(arg);
|
printValueID(arg);
|
||||||
os << ": ";
|
os << ": ";
|
||||||
printType(arg->getType());
|
printType(arg->getType());
|
||||||
|
@ -1366,14 +1366,14 @@ void FunctionPrinter::print(const Block *block, bool printBlockArgs) {
|
||||||
} else {
|
} else {
|
||||||
// We want to print the predecessors in increasing numeric order, not in
|
// We want to print the predecessors in increasing numeric order, not in
|
||||||
// whatever order the use-list is in, so gather and sort them.
|
// whatever order the use-list is in, so gather and sort them.
|
||||||
SmallVector<std::pair<unsigned, const Block *>, 4> predIDs;
|
SmallVector<std::pair<unsigned, Block *>, 4> predIDs;
|
||||||
for (auto *pred : block->getPredecessors())
|
for (auto *pred : block->getPredecessors())
|
||||||
predIDs.push_back({getBlockID(pred), pred});
|
predIDs.push_back({getBlockID(pred), pred});
|
||||||
llvm::array_pod_sort(predIDs.begin(), predIDs.end());
|
llvm::array_pod_sort(predIDs.begin(), predIDs.end());
|
||||||
|
|
||||||
os << "\t// " << predIDs.size() << " preds: ";
|
os << "\t// " << predIDs.size() << " preds: ";
|
||||||
|
|
||||||
interleaveComma(predIDs, [&](std::pair<unsigned, const Block *> pred) {
|
interleaveComma(predIDs, [&](std::pair<unsigned, Block *> pred) {
|
||||||
printBlockName(pred.second);
|
printBlockName(pred.second);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1615,7 +1615,7 @@ void Instruction::dump() const {
|
||||||
llvm::errs() << "\n";
|
llvm::errs() << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void Block::print(raw_ostream &os) const {
|
void Block::print(raw_ostream &os) {
|
||||||
auto *function = getFunction();
|
auto *function = getFunction();
|
||||||
if (!function) {
|
if (!function) {
|
||||||
os << "<<UNLINKED BLOCK>>\n";
|
os << "<<UNLINKED BLOCK>>\n";
|
||||||
|
@ -1627,7 +1627,7 @@ void Block::print(raw_ostream &os) const {
|
||||||
FunctionPrinter(function, modulePrinter).print(this);
|
FunctionPrinter(function, modulePrinter).print(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Block::dump() const { print(llvm::errs()); }
|
void Block::dump() { print(llvm::errs()); }
|
||||||
|
|
||||||
/// Print out the name of the block without printing its body.
|
/// Print out the name of the block without printing its body.
|
||||||
void Block::printAsOperand(raw_ostream &os, bool printType) {
|
void Block::printAsOperand(raw_ostream &os, bool printType) {
|
||||||
|
|
|
@ -49,8 +49,8 @@ Instruction *Block::getContainingInst() {
|
||||||
return getParent() ? getParent()->getContainingInst() : nullptr;
|
return getParent() ? getParent()->getContainingInst() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Function *Block::getFunction() const {
|
Function *Block::getFunction() {
|
||||||
const Block *block = this;
|
Block *block = this;
|
||||||
while (auto *inst = block->getContainingInst()) {
|
while (auto *inst = block->getContainingInst()) {
|
||||||
block = inst->getBlock();
|
block = inst->getBlock();
|
||||||
if (!block)
|
if (!block)
|
||||||
|
@ -78,10 +78,10 @@ void Block::eraseFromFunction() {
|
||||||
/// Returns 'inst' if 'inst' lies in this block, or otherwise finds the
|
/// Returns 'inst' if 'inst' lies in this block, or otherwise finds the
|
||||||
/// ancestor instruction of 'inst' that lies in this block. Returns nullptr if
|
/// ancestor instruction of 'inst' that lies in this block. Returns nullptr if
|
||||||
/// the latter fails.
|
/// the latter fails.
|
||||||
Instruction *Block::findAncestorInstInBlock(Instruction *inst) {
|
Instruction *Block::findAncestorInstInBlock(const Instruction &inst) {
|
||||||
// Traverse up the instruction hierarchy starting from the owner of operand to
|
// Traverse up the instruction hierarchy starting from the owner of operand to
|
||||||
// find the ancestor instruction that resides in the block of 'forInst'.
|
// find the ancestor instruction that resides in the block of 'forInst'.
|
||||||
auto *currInst = inst;
|
auto *currInst = const_cast<Instruction *>(&inst);
|
||||||
while (currInst->getBlock() != this) {
|
while (currInst->getBlock() != this) {
|
||||||
currInst = currInst->getParentInst();
|
currInst = currInst->getParentInst();
|
||||||
if (!currInst)
|
if (!currInst)
|
||||||
|
@ -100,7 +100,7 @@ void Block::dropAllReferences() {
|
||||||
|
|
||||||
/// Verifies the current ordering of child instructions. Returns false if the
|
/// Verifies the current ordering of child instructions. Returns false if the
|
||||||
/// order is valid, true otherwise.
|
/// order is valid, true otherwise.
|
||||||
bool Block::verifyInstOrder() const {
|
bool Block::verifyInstOrder() {
|
||||||
// The order is already known to be invalid.
|
// The order is already known to be invalid.
|
||||||
if (!isInstOrderValid())
|
if (!isInstOrderValid())
|
||||||
return false;
|
return false;
|
||||||
|
@ -131,6 +131,17 @@ void Block::recomputeInstOrder() {
|
||||||
inst.orderIndex = orderIndex++;
|
inst.orderIndex = orderIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Block *PredecessorIterator::operator*() const {
|
||||||
|
// The use iterator points to an operand of a terminator. The predecessor
|
||||||
|
// we return is the block that the terminator is embedded into.
|
||||||
|
return bbUseIterator.getUser()->getBlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the successor number in the predecessor terminator.
|
||||||
|
unsigned PredecessorIterator::getSuccessorIndex() const {
|
||||||
|
return bbUseIterator->getOperandNumber();
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Argument list management.
|
// Argument list management.
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -179,10 +190,10 @@ Instruction *Block::getTerminator() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return true if this block has no predecessors.
|
/// Return true if this block has no predecessors.
|
||||||
bool Block::hasNoPredecessors() const { return pred_begin() == pred_end(); }
|
bool Block::hasNoPredecessors() { return pred_begin() == pred_end(); }
|
||||||
|
|
||||||
// Indexed successor access.
|
// Indexed successor access.
|
||||||
unsigned Block::getNumSuccessors() const {
|
unsigned Block::getNumSuccessors() {
|
||||||
return empty() ? 0 : back().getNumSuccessors();
|
return empty() ? 0 : back().getNumSuccessors();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -288,7 +299,7 @@ void Region::cloneInto(Region *dest, BlockAndValueMapping &mapper,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
iterator lastOldBlock = --dest->end();
|
iterator lastOldBlock = --dest->end();
|
||||||
for (const Block &block : *this) {
|
for (Block &block : *this) {
|
||||||
Block *newBlock = new Block();
|
Block *newBlock = new Block();
|
||||||
mapper.map(&block, newBlock);
|
mapper.map(&block, newBlock);
|
||||||
|
|
||||||
|
|
|
@ -246,7 +246,7 @@ bool OpTrait::impl::verifySameOperandsAndResultType(const Instruction *op) {
|
||||||
|
|
||||||
static bool verifyBBArguments(
|
static bool verifyBBArguments(
|
||||||
llvm::iterator_range<Instruction::const_operand_iterator> operands,
|
llvm::iterator_range<Instruction::const_operand_iterator> operands,
|
||||||
const Block *destBB, const Instruction *op) {
|
Block *destBB, const Instruction *op) {
|
||||||
unsigned operandCount = std::distance(operands.begin(), operands.end());
|
unsigned operandCount = std::distance(operands.begin(), operands.end());
|
||||||
if (operandCount != destBB->getNumArguments())
|
if (operandCount != destBB->getNumArguments())
|
||||||
return op->emitError("branch has " + Twine(operandCount) +
|
return op->emitError("branch has " + Twine(operandCount) +
|
||||||
|
@ -276,7 +276,7 @@ static bool verifyTerminatorSuccessors(const Instruction *op) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpTrait::impl::verifyIsTerminator(const Instruction *op) {
|
bool OpTrait::impl::verifyIsTerminator(const Instruction *op) {
|
||||||
const Block *block = op->getBlock();
|
Block *block = op->getBlock();
|
||||||
// Verify that the operation is at the end of the respective parent block.
|
// Verify that the operation is at the end of the respective parent block.
|
||||||
if (!block || &block->back() != op)
|
if (!block || &block->back() != op)
|
||||||
return op->emitOpError("must be the last instruction in the parent block");
|
return op->emitOpError("must be the last instruction in the parent block");
|
||||||
|
|
|
@ -58,7 +58,7 @@ private:
|
||||||
bool convertFunctions();
|
bool convertFunctions();
|
||||||
bool convertOneFunction(Function &func);
|
bool convertOneFunction(Function &func);
|
||||||
void connectPHINodes(Function &func);
|
void connectPHINodes(Function &func);
|
||||||
bool convertBlock(const Block &bb, bool ignoreArguments);
|
bool convertBlock(Block &bb, bool ignoreArguments);
|
||||||
bool convertInstruction(const Instruction &inst, llvm::IRBuilder<> &builder);
|
bool convertInstruction(const Instruction &inst, llvm::IRBuilder<> &builder);
|
||||||
|
|
||||||
template <typename Range>
|
template <typename Range>
|
||||||
|
@ -74,7 +74,7 @@ private:
|
||||||
// Mappings between original and translated values, used for lookups.
|
// Mappings between original and translated values, used for lookups.
|
||||||
llvm::DenseMap<Function *, llvm::Function *> functionMapping;
|
llvm::DenseMap<Function *, llvm::Function *> functionMapping;
|
||||||
llvm::DenseMap<const Value *, llvm::Value *> valueMapping;
|
llvm::DenseMap<const Value *, llvm::Value *> valueMapping;
|
||||||
llvm::DenseMap<const Block *, llvm::BasicBlock *> blockMapping;
|
llvm::DenseMap<Block *, llvm::BasicBlock *> blockMapping;
|
||||||
};
|
};
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
|
||||||
|
@ -257,7 +257,7 @@ bool ModuleTranslation::convertInstruction(const Instruction &inst,
|
||||||
// Convert block to LLVM IR. Unless `ignoreArguments` is set, emit PHI nodes
|
// Convert block to LLVM IR. Unless `ignoreArguments` is set, emit PHI nodes
|
||||||
// to define values corresponding to the MLIR block arguments. These nodes
|
// to define values corresponding to the MLIR block arguments. These nodes
|
||||||
// are not connected to the source basic blocks, which may not exist yet.
|
// are not connected to the source basic blocks, which may not exist yet.
|
||||||
bool ModuleTranslation::convertBlock(const Block &bb, bool ignoreArguments) {
|
bool ModuleTranslation::convertBlock(Block &bb, bool ignoreArguments) {
|
||||||
llvm::IRBuilder<> builder(blockMapping[&bb]);
|
llvm::IRBuilder<> builder(blockMapping[&bb]);
|
||||||
|
|
||||||
// Before traversing instructions, make block arguments available through
|
// Before traversing instructions, make block arguments available through
|
||||||
|
@ -294,7 +294,7 @@ bool ModuleTranslation::convertBlock(const Block &bb, bool ignoreArguments) {
|
||||||
|
|
||||||
// Get the SSA value passed to the current block from the terminator instruction
|
// Get the SSA value passed to the current block from the terminator instruction
|
||||||
// of its predecessor.
|
// of its predecessor.
|
||||||
static const Value *getPHISourceValue(const Block *current, const Block *pred,
|
static const Value *getPHISourceValue(Block *current, Block *pred,
|
||||||
unsigned numArguments, unsigned index) {
|
unsigned numArguments, unsigned index) {
|
||||||
auto &terminator = *pred->getTerminator();
|
auto &terminator = *pred->getTerminator();
|
||||||
if (terminator.isa<LLVM::BrOp>()) {
|
if (terminator.isa<LLVM::BrOp>()) {
|
||||||
|
@ -320,7 +320,7 @@ void ModuleTranslation::connectPHINodes(Function &func) {
|
||||||
// Skip the first block, it cannot be branched to and its arguments correspond
|
// Skip the first block, it cannot be branched to and its arguments correspond
|
||||||
// to the arguments of the LLVM function.
|
// to the arguments of the LLVM function.
|
||||||
for (auto it = std::next(func.begin()), eit = func.end(); it != eit; ++it) {
|
for (auto it = std::next(func.begin()), eit = func.end(); it != eit; ++it) {
|
||||||
const Block *bb = &*it;
|
Block *bb = &*it;
|
||||||
llvm::BasicBlock *llvmBB = blockMapping.lookup(bb);
|
llvm::BasicBlock *llvmBB = blockMapping.lookup(bb);
|
||||||
auto phis = llvmBB->phis();
|
auto phis = llvmBB->phis();
|
||||||
auto numArguments = bb->getNumArguments();
|
auto numArguments = bb->getNumArguments();
|
||||||
|
@ -328,7 +328,7 @@ void ModuleTranslation::connectPHINodes(Function &func) {
|
||||||
for (auto &numberedPhiNode : llvm::enumerate(phis)) {
|
for (auto &numberedPhiNode : llvm::enumerate(phis)) {
|
||||||
auto &phiNode = numberedPhiNode.value();
|
auto &phiNode = numberedPhiNode.value();
|
||||||
unsigned index = numberedPhiNode.index();
|
unsigned index = numberedPhiNode.index();
|
||||||
for (const auto *pred : bb->getPredecessors()) {
|
for (auto *pred : bb->getPredecessors()) {
|
||||||
phiNode.addIncoming(valueMapping.lookup(getPHISourceValue(
|
phiNode.addIncoming(valueMapping.lookup(getPHISourceValue(
|
||||||
bb, pred, numArguments, index)),
|
bb, pred, numArguments, index)),
|
||||||
blockMapping.lookup(pred));
|
blockMapping.lookup(pred));
|
||||||
|
@ -338,22 +338,21 @@ void ModuleTranslation::connectPHINodes(Function &func) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(mlir-team): implement an iterative version
|
// TODO(mlir-team): implement an iterative version
|
||||||
static void topologicalSortImpl(llvm::SetVector<const Block *> &blocks,
|
static void topologicalSortImpl(llvm::SetVector<Block *> &blocks, Block *b) {
|
||||||
const Block *b) {
|
|
||||||
blocks.insert(b);
|
blocks.insert(b);
|
||||||
for (const Block *bb : b->getSuccessors()) {
|
for (Block *bb : b->getSuccessors()) {
|
||||||
if (blocks.count(bb) == 0)
|
if (blocks.count(bb) == 0)
|
||||||
topologicalSortImpl(blocks, bb);
|
topologicalSortImpl(blocks, bb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort function blocks topologically.
|
// Sort function blocks topologically.
|
||||||
static llvm::SetVector<const Block *> topologicalSort(Function &f) {
|
static llvm::SetVector<Block *> topologicalSort(Function &f) {
|
||||||
// For each blocks that has not been visited yet (i.e. that has no
|
// For each blocks that has not been visited yet (i.e. that has no
|
||||||
// predecessors), add it to the list and traverse its successors in DFS
|
// predecessors), add it to the list and traverse its successors in DFS
|
||||||
// preorder.
|
// preorder.
|
||||||
llvm::SetVector<const Block *> blocks;
|
llvm::SetVector<Block *> blocks;
|
||||||
for (const Block &b : f.getBlocks()) {
|
for (Block &b : f.getBlocks()) {
|
||||||
if (blocks.count(&b) == 0)
|
if (blocks.count(&b) == 0)
|
||||||
topologicalSortImpl(blocks, &b);
|
topologicalSortImpl(blocks, &b);
|
||||||
}
|
}
|
||||||
|
@ -373,7 +372,7 @@ bool ModuleTranslation::convertOneFunction(Function &func) {
|
||||||
unsigned int argIdx = 0;
|
unsigned int argIdx = 0;
|
||||||
for (const auto &kvp : llvm::zip(func.getArguments(), llvmFunc->args())) {
|
for (const auto &kvp : llvm::zip(func.getArguments(), llvmFunc->args())) {
|
||||||
llvm::Argument &llvmArg = std::get<1>(kvp);
|
llvm::Argument &llvmArg = std::get<1>(kvp);
|
||||||
const BlockArgument *mlirArg = std::get<0>(kvp);
|
BlockArgument *mlirArg = std::get<0>(kvp);
|
||||||
|
|
||||||
if (auto attr = func.getArgAttrOfType<BoolAttr>(argIdx, "llvm.noalias")) {
|
if (auto attr = func.getArgAttrOfType<BoolAttr>(argIdx, "llvm.noalias")) {
|
||||||
// NB: Attribute already verified to be boolean, so check if we can indeed
|
// NB: Attribute already verified to be boolean, so check if we can indeed
|
||||||
|
@ -392,7 +391,7 @@ bool ModuleTranslation::convertOneFunction(Function &func) {
|
||||||
|
|
||||||
// First, create all blocks so we can jump to them.
|
// First, create all blocks so we can jump to them.
|
||||||
llvm::LLVMContext &llvmContext = llvmFunc->getContext();
|
llvm::LLVMContext &llvmContext = llvmFunc->getContext();
|
||||||
for (const auto &bb : func) {
|
for (auto &bb : func) {
|
||||||
auto *llvmBB = llvm::BasicBlock::Create(llvmContext);
|
auto *llvmBB = llvm::BasicBlock::Create(llvmContext);
|
||||||
llvmBB->insertInto(llvmFunc);
|
llvmBB->insertInto(llvmFunc);
|
||||||
blockMapping[&bb] = llvmBB;
|
blockMapping[&bb] = llvmBB;
|
||||||
|
@ -402,7 +401,7 @@ bool ModuleTranslation::convertOneFunction(Function &func) {
|
||||||
// converted before uses.
|
// converted before uses.
|
||||||
auto blocks = topologicalSort(func);
|
auto blocks = topologicalSort(func);
|
||||||
for (auto indexedBB : llvm::enumerate(blocks)) {
|
for (auto indexedBB : llvm::enumerate(blocks)) {
|
||||||
const auto *bb = indexedBB.value();
|
auto *bb = indexedBB.value();
|
||||||
if (convertBlock(*bb, /*ignoreArguments=*/indexedBB.index() == 0))
|
if (convertBlock(*bb, /*ignoreArguments=*/indexedBB.index() == 0))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -205,7 +205,7 @@ static bool getFullMemRefAsRegion(Instruction *opInst, unsigned numParamLoopIVs,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emitNoteForBlock(const Block &block, const Twine &message) {
|
static void emitNoteForBlock(Block &block, const Twine &message) {
|
||||||
auto *inst = block.getContainingInst();
|
auto *inst = block.getContainingInst();
|
||||||
if (!inst) {
|
if (!inst) {
|
||||||
block.getFunction()->emitNote(message);
|
block.getFunction()->emitNote(message);
|
||||||
|
@ -543,11 +543,12 @@ bool DmaGeneration::runOnBlock(Block *block) {
|
||||||
/// in the block for placing incoming (read) and outgoing (write) DMAs
|
/// in the block for placing incoming (read) and outgoing (write) DMAs
|
||||||
/// respectively. The lowest depth depends on whether the region being accessed
|
/// respectively. The lowest depth depends on whether the region being accessed
|
||||||
/// is invariant with respect to one or more immediately surrounding loops.
|
/// is invariant with respect to one or more immediately surrounding loops.
|
||||||
static void findHighestBlockForPlacement(
|
static void
|
||||||
const MemRefRegion ®ion, const Block &block,
|
findHighestBlockForPlacement(const MemRefRegion ®ion, Block &block,
|
||||||
const Block::iterator &begin, const Block::iterator &end,
|
Block::iterator &begin, Block::iterator &end,
|
||||||
Block **dmaPlacementBlock, Block::iterator *dmaPlacementReadStart,
|
Block **dmaPlacementBlock,
|
||||||
Block::iterator *dmaPlacementWriteStart) {
|
Block::iterator *dmaPlacementReadStart,
|
||||||
|
Block::iterator *dmaPlacementWriteStart) {
|
||||||
const auto *cst = region.getConstraints();
|
const auto *cst = region.getConstraints();
|
||||||
SmallVector<Value *, 4> symbols;
|
SmallVector<Value *, 4> symbols;
|
||||||
cst->getIdValues(cst->getNumDimIds(), cst->getNumDimAndSymbolIds(), &symbols);
|
cst->getIdValues(cst->getNumDimIds(), cst->getNumDimAndSymbolIds(), &symbols);
|
||||||
|
|
|
@ -28,10 +28,10 @@ template <>
|
||||||
struct llvm::DOTGraphTraits<Function *> : public DefaultDOTGraphTraits {
|
struct llvm::DOTGraphTraits<Function *> : public DefaultDOTGraphTraits {
|
||||||
using DefaultDOTGraphTraits::DefaultDOTGraphTraits;
|
using DefaultDOTGraphTraits::DefaultDOTGraphTraits;
|
||||||
|
|
||||||
static std::string getNodeLabel(const Block *Block, Function *);
|
static std::string getNodeLabel(Block *Block, Function *);
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string llvm::DOTGraphTraits<Function *>::getNodeLabel(const Block *Block,
|
std::string llvm::DOTGraphTraits<Function *>::getNodeLabel(Block *Block,
|
||||||
Function *) {
|
Function *) {
|
||||||
// Reuse the print output for the node labels.
|
// Reuse the print output for the node labels.
|
||||||
std::string outStreamStr;
|
std::string outStreamStr;
|
||||||
|
|
Loading…
Reference in New Issue