984 lines
59 KiB
C++
984 lines
59 KiB
C++
/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\
|
|
|* *|
|
|
|* Interface Declarations *|
|
|
|* *|
|
|
|* Automatically generated file, do not edit! *|
|
|
|* *|
|
|
\*===----------------------------------------------------------------------===*/
|
|
|
|
namespace mlir {
|
|
|
|
/// Contains helper functions to query properties and perform transformations
|
|
/// of a loop. Operations that implement this interface will be considered by
|
|
/// loop-invariant code motion.
|
|
///
|
|
/// Loop-carried variables can be exposed through this interface. There are
|
|
/// 3 components to a loop-carried variable.
|
|
/// - The "region iter_arg" is the block argument of the entry block that
|
|
/// represents the loop-carried variable in each iteration.
|
|
/// - The "init value" is an operand of the loop op that serves as the initial
|
|
/// region iter_arg value for the first iteration (if any).
|
|
/// - The "yielded" value is the value that is forwarded from one iteration to
|
|
/// serve as the region iter_arg of the next iteration.
|
|
///
|
|
/// If one of the respective interface methods is implemented, so must the other
|
|
/// two. The interface verifier ensures that the number of region iter_args,
|
|
/// init values and yielded values match. Note: the types are not required to
|
|
/// strictly match; if the op also implements `RegionBranchOpInterface`, type
|
|
/// compatibility is deferred to that interface's `areTypesCompatible` hook.
|
|
///
|
|
/// Optionally, "loop results" can be exposed through this interface. These are
|
|
/// the values that are returned from the loop op when there are no more
|
|
/// iterations. The number and types of the loop results must match with the
|
|
/// region iter_args. Note: Loop results are optional because some loops
|
|
/// (e.g., `scf.while`) may produce results that do match 1-to-1 with the
|
|
/// region iter_args.
|
|
class LoopLikeOpInterface;
|
|
|
|
} // namespace mlir
|
|
namespace mlir {
|
|
|
|
/// Contains helper functions to query properties and perform transformations
|
|
/// of a loop. Operations that implement this interface will be considered by
|
|
/// loop-invariant code motion.
|
|
///
|
|
/// Loop-carried variables can be exposed through this interface. There are
|
|
/// 3 components to a loop-carried variable.
|
|
/// - The "region iter_arg" is the block argument of the entry block that
|
|
/// represents the loop-carried variable in each iteration.
|
|
/// - The "init value" is an operand of the loop op that serves as the initial
|
|
/// region iter_arg value for the first iteration (if any).
|
|
/// - The "yielded" value is the value that is forwarded from one iteration to
|
|
/// serve as the region iter_arg of the next iteration.
|
|
///
|
|
/// If one of the respective interface methods is implemented, so must the other
|
|
/// two. The interface verifier ensures that the number of region iter_args,
|
|
/// init values and yielded values match. Note: the types are not required to
|
|
/// strictly match; if the op also implements `RegionBranchOpInterface`, type
|
|
/// compatibility is deferred to that interface's `areTypesCompatible` hook.
|
|
///
|
|
/// Optionally, "loop results" can be exposed through this interface. These are
|
|
/// the values that are returned from the loop op when there are no more
|
|
/// iterations. The number and types of the loop results must match with the
|
|
/// region iter_args. Note: Loop results are optional because some loops
|
|
/// (e.g., `scf.while`) may produce results that do match 1-to-1 with the
|
|
/// region iter_args.
|
|
namespace detail {
|
|
struct LoopLikeOpInterfaceInterfaceTraits {
|
|
struct Concept {
|
|
/// The methods defined by the interface.
|
|
bool (*isDefinedOutsideOfLoop)(const Concept *impl, ::mlir::Operation *, ::mlir::Value );
|
|
::llvm::SmallVector<::mlir::Region *> (*getLoopRegions)(const Concept *impl, ::mlir::Operation *);
|
|
void (*moveOutOfLoop)(const Concept *impl, ::mlir::Operation *, ::mlir::Operation *);
|
|
::llvm::LogicalResult (*promoteIfSingleIteration)(const Concept *impl, ::mlir::Operation *, ::mlir::RewriterBase &);
|
|
::std::optional<::llvm::SmallVector<::mlir::Value>> (*getLoopInductionVars)(const Concept *impl, ::mlir::Operation *);
|
|
::std::optional<::llvm::SmallVector<::mlir::OpFoldResult>> (*getLoopLowerBounds)(const Concept *impl, ::mlir::Operation *);
|
|
::std::optional<::llvm::SmallVector<::mlir::OpFoldResult>> (*getLoopSteps)(const Concept *impl, ::mlir::Operation *);
|
|
::std::optional<::llvm::SmallVector<::mlir::OpFoldResult>> (*getLoopUpperBounds)(const Concept *impl, ::mlir::Operation *);
|
|
::llvm::MutableArrayRef<::mlir::OpOperand> (*getInitsMutable)(const Concept *impl, ::mlir::Operation *);
|
|
::mlir::Block::BlockArgListType (*getRegionIterArgs)(const Concept *impl, ::mlir::Operation *);
|
|
::std::optional<::llvm::MutableArrayRef<::mlir::OpOperand>> (*getYieldedValuesMutable)(const Concept *impl, ::mlir::Operation *);
|
|
::std::optional<::mlir::ResultRange> (*getLoopResults)(const Concept *impl, ::mlir::Operation *);
|
|
::mlir::FailureOr<::mlir::LoopLikeOpInterface> (*replaceWithAdditionalYields)(const Concept *impl, ::mlir::Operation *, ::mlir::RewriterBase &, ::mlir::ValueRange, bool, const ::mlir::NewYieldValuesFn &);
|
|
::std::optional<::llvm::APInt> (*getStaticTripCount)(const Concept *impl, ::mlir::Operation *);
|
|
bool (*isValidInductionVarType)(const Concept *impl, ::mlir::Operation *, ::mlir::Type);
|
|
::mlir::LogicalResult (*setLoopLowerBounds)(const Concept *impl, ::mlir::Operation *, ::llvm::ArrayRef<::mlir::OpFoldResult>);
|
|
::mlir::LogicalResult (*setLoopUpperBounds)(const Concept *impl, ::mlir::Operation *, ::llvm::ArrayRef<::mlir::OpFoldResult>);
|
|
::mlir::LogicalResult (*setLoopSteps)(const Concept *impl, ::mlir::Operation *, ::llvm::ArrayRef<::mlir::OpFoldResult>);
|
|
};
|
|
template<typename ConcreteOp>
|
|
class Model : public Concept {
|
|
public:
|
|
using Interface = ::mlir::LoopLikeOpInterface;
|
|
Model() : Concept{isDefinedOutsideOfLoop, getLoopRegions, moveOutOfLoop, promoteIfSingleIteration, getLoopInductionVars, getLoopLowerBounds, getLoopSteps, getLoopUpperBounds, getInitsMutable, getRegionIterArgs, getYieldedValuesMutable, getLoopResults, replaceWithAdditionalYields, getStaticTripCount, isValidInductionVarType, setLoopLowerBounds, setLoopUpperBounds, setLoopSteps} {}
|
|
|
|
static inline bool isDefinedOutsideOfLoop(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::Value value);
|
|
static inline ::llvm::SmallVector<::mlir::Region *> getLoopRegions(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
|
|
static inline void moveOutOfLoop(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::Operation * op);
|
|
static inline ::llvm::LogicalResult promoteIfSingleIteration(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::RewriterBase & rewriter);
|
|
static inline ::std::optional<::llvm::SmallVector<::mlir::Value>> getLoopInductionVars(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
|
|
static inline ::std::optional<::llvm::SmallVector<::mlir::OpFoldResult>> getLoopLowerBounds(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
|
|
static inline ::std::optional<::llvm::SmallVector<::mlir::OpFoldResult>> getLoopSteps(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
|
|
static inline ::std::optional<::llvm::SmallVector<::mlir::OpFoldResult>> getLoopUpperBounds(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
|
|
static inline ::llvm::MutableArrayRef<::mlir::OpOperand> getInitsMutable(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
|
|
static inline ::mlir::Block::BlockArgListType getRegionIterArgs(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
|
|
static inline ::std::optional<::llvm::MutableArrayRef<::mlir::OpOperand>> getYieldedValuesMutable(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
|
|
static inline ::std::optional<::mlir::ResultRange> getLoopResults(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
|
|
static inline ::mlir::FailureOr<::mlir::LoopLikeOpInterface> replaceWithAdditionalYields(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::RewriterBase & rewriter, ::mlir::ValueRange newInitOperands, bool replaceInitOperandUsesInLoop, const ::mlir::NewYieldValuesFn & newYieldValuesFn);
|
|
static inline ::std::optional<::llvm::APInt> getStaticTripCount(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
|
|
static inline bool isValidInductionVarType(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::Type type);
|
|
static inline ::mlir::LogicalResult setLoopLowerBounds(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::llvm::ArrayRef<::mlir::OpFoldResult> bounds);
|
|
static inline ::mlir::LogicalResult setLoopUpperBounds(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::llvm::ArrayRef<::mlir::OpFoldResult> bounds);
|
|
static inline ::mlir::LogicalResult setLoopSteps(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::llvm::ArrayRef<::mlir::OpFoldResult> steps);
|
|
};
|
|
template<typename ConcreteOp>
|
|
class FallbackModel : public Concept {
|
|
public:
|
|
using Interface = ::mlir::LoopLikeOpInterface;
|
|
FallbackModel() : Concept{isDefinedOutsideOfLoop, getLoopRegions, moveOutOfLoop, promoteIfSingleIteration, getLoopInductionVars, getLoopLowerBounds, getLoopSteps, getLoopUpperBounds, getInitsMutable, getRegionIterArgs, getYieldedValuesMutable, getLoopResults, replaceWithAdditionalYields, getStaticTripCount, isValidInductionVarType, setLoopLowerBounds, setLoopUpperBounds, setLoopSteps} {}
|
|
|
|
static inline bool isDefinedOutsideOfLoop(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::Value value);
|
|
static inline ::llvm::SmallVector<::mlir::Region *> getLoopRegions(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
|
|
static inline void moveOutOfLoop(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::Operation * op);
|
|
static inline ::llvm::LogicalResult promoteIfSingleIteration(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::RewriterBase & rewriter);
|
|
static inline ::std::optional<::llvm::SmallVector<::mlir::Value>> getLoopInductionVars(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
|
|
static inline ::std::optional<::llvm::SmallVector<::mlir::OpFoldResult>> getLoopLowerBounds(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
|
|
static inline ::std::optional<::llvm::SmallVector<::mlir::OpFoldResult>> getLoopSteps(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
|
|
static inline ::std::optional<::llvm::SmallVector<::mlir::OpFoldResult>> getLoopUpperBounds(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
|
|
static inline ::llvm::MutableArrayRef<::mlir::OpOperand> getInitsMutable(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
|
|
static inline ::mlir::Block::BlockArgListType getRegionIterArgs(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
|
|
static inline ::std::optional<::llvm::MutableArrayRef<::mlir::OpOperand>> getYieldedValuesMutable(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
|
|
static inline ::std::optional<::mlir::ResultRange> getLoopResults(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
|
|
static inline ::mlir::FailureOr<::mlir::LoopLikeOpInterface> replaceWithAdditionalYields(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::RewriterBase & rewriter, ::mlir::ValueRange newInitOperands, bool replaceInitOperandUsesInLoop, const ::mlir::NewYieldValuesFn & newYieldValuesFn);
|
|
static inline ::std::optional<::llvm::APInt> getStaticTripCount(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
|
|
static inline bool isValidInductionVarType(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::Type type);
|
|
static inline ::mlir::LogicalResult setLoopLowerBounds(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::llvm::ArrayRef<::mlir::OpFoldResult> bounds);
|
|
static inline ::mlir::LogicalResult setLoopUpperBounds(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::llvm::ArrayRef<::mlir::OpFoldResult> bounds);
|
|
static inline ::mlir::LogicalResult setLoopSteps(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::llvm::ArrayRef<::mlir::OpFoldResult> steps);
|
|
};
|
|
template<typename ConcreteModel, typename ConcreteOp>
|
|
class ExternalModel : public FallbackModel<ConcreteModel> {
|
|
public:
|
|
using ConcreteEntity = ConcreteOp;
|
|
bool isDefinedOutsideOfLoop(::mlir::Operation *tablegen_opaque_val, ::mlir::Value value) const;
|
|
void moveOutOfLoop(::mlir::Operation *tablegen_opaque_val, ::mlir::Operation *op) const;
|
|
::llvm::LogicalResult promoteIfSingleIteration(::mlir::Operation *tablegen_opaque_val, ::mlir::RewriterBase &rewriter) const;
|
|
::std::optional<::llvm::SmallVector<::mlir::Value>> getLoopInductionVars(::mlir::Operation *tablegen_opaque_val) const;
|
|
::std::optional<::llvm::SmallVector<::mlir::OpFoldResult>> getLoopLowerBounds(::mlir::Operation *tablegen_opaque_val) const;
|
|
::std::optional<::llvm::SmallVector<::mlir::OpFoldResult>> getLoopSteps(::mlir::Operation *tablegen_opaque_val) const;
|
|
::std::optional<::llvm::SmallVector<::mlir::OpFoldResult>> getLoopUpperBounds(::mlir::Operation *tablegen_opaque_val) const;
|
|
::llvm::MutableArrayRef<::mlir::OpOperand> getInitsMutable(::mlir::Operation *tablegen_opaque_val) const;
|
|
::mlir::Block::BlockArgListType getRegionIterArgs(::mlir::Operation *tablegen_opaque_val) const;
|
|
::std::optional<::llvm::MutableArrayRef<::mlir::OpOperand>> getYieldedValuesMutable(::mlir::Operation *tablegen_opaque_val) const;
|
|
::std::optional<::mlir::ResultRange> getLoopResults(::mlir::Operation *tablegen_opaque_val) const;
|
|
::mlir::FailureOr<::mlir::LoopLikeOpInterface> replaceWithAdditionalYields(::mlir::Operation *tablegen_opaque_val, ::mlir::RewriterBase &rewriter, ::mlir::ValueRange newInitOperands, bool replaceInitOperandUsesInLoop, const ::mlir::NewYieldValuesFn &newYieldValuesFn) const;
|
|
::std::optional<::llvm::APInt> getStaticTripCount(::mlir::Operation *tablegen_opaque_val) const;
|
|
bool isValidInductionVarType(::mlir::Operation *tablegen_opaque_val, ::mlir::Type type) const;
|
|
::mlir::LogicalResult setLoopLowerBounds(::mlir::Operation *tablegen_opaque_val, ::llvm::ArrayRef<::mlir::OpFoldResult> bounds) const;
|
|
::mlir::LogicalResult setLoopUpperBounds(::mlir::Operation *tablegen_opaque_val, ::llvm::ArrayRef<::mlir::OpFoldResult> bounds) const;
|
|
::mlir::LogicalResult setLoopSteps(::mlir::Operation *tablegen_opaque_val, ::llvm::ArrayRef<::mlir::OpFoldResult> steps) const;
|
|
};
|
|
};
|
|
template <typename ConcreteOp>
|
|
struct LoopLikeOpInterfaceTrait;
|
|
|
|
} // namespace detail
|
|
class LoopLikeOpInterface : public ::mlir::OpInterface<LoopLikeOpInterface, detail::LoopLikeOpInterfaceInterfaceTraits> {
|
|
public:
|
|
using ::mlir::OpInterface<LoopLikeOpInterface, detail::LoopLikeOpInterfaceInterfaceTraits>::OpInterface;
|
|
template <typename ConcreteOp>
|
|
struct Trait : public detail::LoopLikeOpInterfaceTrait<ConcreteOp> {};
|
|
|
|
/// Returns true if the given value is defined outside of the loop.
|
|
/// A sensible implementation could be to check whether the value's defining
|
|
/// operation lies outside of the loops body region. If the loop uses
|
|
/// explicit capture of dependencies, an implementation could check whether
|
|
/// the value corresponds to a captured dependency.
|
|
bool isDefinedOutsideOfLoop(::mlir::Value value);
|
|
|
|
/// Returns the regions that make up the body of the loop and should be
|
|
/// inspected for loop-invariant operations.
|
|
::llvm::SmallVector<::mlir::Region *> getLoopRegions();
|
|
|
|
/// Moves the given loop-invariant operation out of the loop.
|
|
void moveOutOfLoop(::mlir::Operation * op);
|
|
|
|
/// Promotes the loop body to its containing block if the loop is known to
|
|
/// have a single iteration. Returns "success" if the promotion was
|
|
/// successful.
|
|
::llvm::LogicalResult promoteIfSingleIteration(::mlir::RewriterBase & rewriter);
|
|
|
|
/// Return all induction variables, if they exist. If the op has no notion of
|
|
/// induction variable, then return std::nullopt. If it does have
|
|
/// a notion but an instance doesn't have induction variables, then
|
|
/// return empty vector.
|
|
::std::optional<::llvm::SmallVector<::mlir::Value>> getLoopInductionVars();
|
|
|
|
/// Return all lower bounds, if they exist. If the op has no notion of
|
|
/// lower bounds, then return std::nullopt. If it does have
|
|
/// a notion but an instance doesn't have lower bounds, then
|
|
/// return empty vector.
|
|
::std::optional<::llvm::SmallVector<::mlir::OpFoldResult>> getLoopLowerBounds();
|
|
|
|
/// Return all steps, if they exist. If the op has no notion of
|
|
/// steps, then return std::nullopt. If it does have
|
|
/// a notion but an instance doesn't have steps, then
|
|
/// return empty vector.
|
|
::std::optional<::llvm::SmallVector<::mlir::OpFoldResult>> getLoopSteps();
|
|
|
|
/// Return all upper bounds, if they exist. If the op has no notion of
|
|
/// lower bounds, then return std::nullopt. If it does have
|
|
/// a notion but an instance doesn't have lower bounds, then
|
|
/// return empty vector.
|
|
::std::optional<::llvm::SmallVector<::mlir::OpFoldResult>> getLoopUpperBounds();
|
|
|
|
/// Return the mutable "init" operands that are used as initialization
|
|
/// values for the region "iter_args" of this loop.
|
|
::llvm::MutableArrayRef<::mlir::OpOperand> getInitsMutable();
|
|
|
|
/// Return the region "iter_args" (block arguments) that correspond to the
|
|
/// "init" operands. If the op has multiple regions, return the
|
|
/// corresponding block arguments of the entry region.
|
|
::mlir::Block::BlockArgListType getRegionIterArgs();
|
|
|
|
/// Return the mutable operand range of values that are yielded to the next
|
|
/// iteration by the loop terminator.
|
|
///
|
|
/// For loop operations that dont yield a value, this should return
|
|
/// std::nullopt.
|
|
::std::optional<::llvm::MutableArrayRef<::mlir::OpOperand>> getYieldedValuesMutable();
|
|
|
|
/// Return the range of results that are return from this loop and
|
|
/// correspond to the "init" operands.
|
|
///
|
|
/// Note: This interface method is optional. If loop results are not
|
|
/// exposed via this interface, "std::nullopt" should be returned.
|
|
/// Otherwise, the number and types of results must match with the
|
|
/// region iter_args, inits and yielded values that are exposed via this
|
|
/// interface. If loop results are exposed but this loop op has no
|
|
/// loop-carried variables, an empty result range (and not "std::nullopt")
|
|
/// should be returned.
|
|
::std::optional<::mlir::ResultRange> getLoopResults();
|
|
|
|
/// Append the specified additional "init" operands: replace this loop with
|
|
/// a new loop that has the additional init operands. The loop body of
|
|
/// this loop is moved over to the new loop.
|
|
///
|
|
/// `newInitOperands` specifies the additional "init" operands.
|
|
/// `newYieldValuesFn` is a function that returns the yielded values (which
|
|
/// can be computed based on the additional region iter_args). If
|
|
/// `replaceInitOperandUsesInLoop` is set, all uses of the additional init
|
|
/// operands inside of this loop are replaced with the corresponding, newly
|
|
/// added region iter_args.
|
|
///
|
|
/// Note: Loops that do not support init/iter_args should return "failure".
|
|
::mlir::FailureOr<::mlir::LoopLikeOpInterface> replaceWithAdditionalYields(::mlir::RewriterBase & rewriter, ::mlir::ValueRange newInitOperands, bool replaceInitOperandUsesInLoop, const ::mlir::NewYieldValuesFn & newYieldValuesFn);
|
|
|
|
/// Compute the static trip count if possible.
|
|
::std::optional<::llvm::APInt> getStaticTripCount();
|
|
|
|
/// Check if the given type is supported as a loop induction variable.
|
|
/// By default, only IndexType is supported.
|
|
bool isValidInductionVarType(::mlir::Type type);
|
|
|
|
/// Update the loop lower bounds. Returns failure if the loop doesn't
|
|
/// support updating bounds or if the number of bounds doesn't match.
|
|
::mlir::LogicalResult setLoopLowerBounds(::llvm::ArrayRef<::mlir::OpFoldResult> bounds);
|
|
|
|
/// Update the loop upper bounds. Returns failure if the loop doesn't
|
|
/// support updating bounds or if the number of bounds doesn't match.
|
|
::mlir::LogicalResult setLoopUpperBounds(::llvm::ArrayRef<::mlir::OpFoldResult> bounds);
|
|
|
|
/// Update the loop steps. Returns failure if the loop doesn't support
|
|
/// updating steps or if the number of steps doesn't match.
|
|
::mlir::LogicalResult setLoopSteps(::llvm::ArrayRef<::mlir::OpFoldResult> steps);
|
|
|
|
/// Returns if a block is inside a loop (within the current function). This
|
|
/// can either be because the block is nested inside a LoopLikeInterface, or
|
|
/// because the control flow graph is cyclic
|
|
static bool blockIsInLoop(::mlir::Block *block);
|
|
|
|
/// If there is a single induction variable return it, otherwise return
|
|
/// std::nullopt.
|
|
::std::optional<::mlir::Value> getSingleInductionVar() {
|
|
auto inductionVars = (*this).getLoopInductionVars();
|
|
if (inductionVars.has_value() && (*inductionVars).size() == 1)
|
|
return (*inductionVars)[0];
|
|
return ::std::nullopt;
|
|
}
|
|
/// Return the single lower bound value or attribute if it exists, otherwise
|
|
/// return std::nullopt.
|
|
::std::optional<::mlir::OpFoldResult> getSingleLowerBound() {
|
|
auto lowerBounds = (*this).getLoopLowerBounds();
|
|
if (lowerBounds.has_value() && (*lowerBounds).size() == 1)
|
|
return (*lowerBounds)[0];
|
|
return ::std::nullopt;
|
|
}
|
|
/// Return the single step value or attribute if it exists, otherwise
|
|
/// return std::nullopt.
|
|
::std::optional<::mlir::OpFoldResult> getSingleStep() {
|
|
auto steps = (*this).getLoopSteps();
|
|
if (steps.has_value() && (*steps).size() == 1)
|
|
return (*steps)[0];
|
|
return ::std::nullopt;
|
|
}
|
|
/// Return the single upper bound value or attribute if it exists, otherwise
|
|
/// return std::nullopt.
|
|
::std::optional<::mlir::OpFoldResult> getSingleUpperBound() {
|
|
auto upperBounds = (*this).getLoopUpperBounds();
|
|
if (upperBounds.has_value() && (*upperBounds).size() == 1)
|
|
return (*upperBounds)[0];
|
|
return ::std::nullopt;
|
|
}
|
|
|
|
/// Append the specified additional "init" operands: replace this loop with
|
|
/// a new loop that has the additional init operands. The loop body of this
|
|
/// loop is moved over to the new loop.
|
|
///
|
|
/// The newly added region iter_args are yielded from the loop.
|
|
::mlir::FailureOr<::mlir::LoopLikeOpInterface>
|
|
replaceWithAdditionalIterOperands(::mlir::RewriterBase &rewriter,
|
|
::mlir::ValueRange newInitOperands,
|
|
bool replaceInitOperandUsesInLoop) {
|
|
return (*this).replaceWithAdditionalYields(
|
|
rewriter, newInitOperands, replaceInitOperandUsesInLoop,
|
|
[](::mlir::OpBuilder &b, ::mlir::Location loc,
|
|
::mlir::ArrayRef<::mlir::BlockArgument> newBBArgs) {
|
|
return ::mlir::SmallVector<::mlir::Value>(newBBArgs);
|
|
});
|
|
}
|
|
|
|
/// Return the values that are yielded to the next iteration. If
|
|
/// the loop doesnt yield any values return `{}`.
|
|
::mlir::ValueRange getYieldedValues() {
|
|
auto mutableValues = (*this).getYieldedValuesMutable();
|
|
if (!mutableValues || mutableValues->empty())
|
|
return {};
|
|
::mlir::Operation *yieldOp = mutableValues->begin()->getOwner();
|
|
unsigned firstOperandIndex = mutableValues->begin()->getOperandNumber();
|
|
return ::mlir::OperandRange(
|
|
yieldOp->operand_begin() + firstOperandIndex,
|
|
yieldOp->operand_begin() + firstOperandIndex + mutableValues->size());
|
|
}
|
|
|
|
/// Return the "init" operands that are used as initialization values for
|
|
/// the region "iter_args" of this loop.
|
|
::mlir::OperandRange getInits() {
|
|
auto initsMutable = (*this).getInitsMutable();
|
|
if (initsMutable.empty())
|
|
return ::mlir::OperandRange((*this)->operand_end(), (*this)->operand_end());
|
|
unsigned firstOperandIndex = initsMutable.begin()->getOperandNumber();
|
|
return ::mlir::OperandRange(
|
|
(*this)->operand_begin() + firstOperandIndex,
|
|
(*this)->operand_begin() + firstOperandIndex + initsMutable.size());
|
|
}
|
|
|
|
/// Return the region iter_arg that corresponds to the given init operand.
|
|
/// Return an "empty" block argument if the given operand is not an init
|
|
/// operand of this loop op.
|
|
::mlir::BlockArgument getTiedLoopRegionIterArg(
|
|
::mlir::OpOperand *opOperand) {
|
|
auto initsMutable = (*this).getInitsMutable();
|
|
auto it = ::llvm::find(initsMutable, *opOperand);
|
|
if (it == initsMutable.end())
|
|
return {};
|
|
return (*this).getRegionIterArgs()[
|
|
::std::distance(initsMutable.begin(), it)];
|
|
}
|
|
|
|
/// Return the region iter_arg that corresponds to the given loop result.
|
|
/// Return an "empty" block argument if the given OpResult is not a loop
|
|
/// result or if this op does not expose any loop results.
|
|
::mlir::BlockArgument getTiedLoopRegionIterArg(::mlir::OpResult opResult) {
|
|
auto loopResults = (*this).getLoopResults();
|
|
if (!loopResults)
|
|
return {};
|
|
auto it = ::llvm::find(*loopResults, opResult);
|
|
if (it == loopResults->end())
|
|
return {};
|
|
return (*this).getRegionIterArgs()[
|
|
::std::distance(loopResults->begin(), it)];
|
|
}
|
|
|
|
/// Return the init operand that corresponds to the given region iter_arg.
|
|
/// Return "nullptr" if the given block argument is not a region iter_arg
|
|
/// of this loop op.
|
|
::mlir::OpOperand *getTiedLoopInit(::mlir::BlockArgument bbArg) {
|
|
auto iterArgs = (*this).getRegionIterArgs();
|
|
auto it = ::llvm::find(iterArgs, bbArg);
|
|
if (it == iterArgs.end())
|
|
return {};
|
|
return &(*this).getInitsMutable()[::std::distance(iterArgs.begin(), it)];
|
|
}
|
|
|
|
/// Return the init operand that corresponds to the given loop result.
|
|
/// Return "nullptr" if the given OpResult is not a loop result or if this
|
|
/// op does not expose any loop results.
|
|
::mlir::OpOperand *getTiedLoopInit(::mlir::OpResult opResult) {
|
|
auto loopResults = (*this).getLoopResults();
|
|
if (!loopResults)
|
|
return nullptr;
|
|
auto it = ::llvm::find(*loopResults, opResult);
|
|
if (it == loopResults->end())
|
|
return nullptr;
|
|
return &(*this).getInitsMutable()[::std::distance(
|
|
loopResults->begin(), it)];
|
|
}
|
|
|
|
/// Return the yielded value that corresponds to the given region iter_arg.
|
|
/// Return "nullptr" if the given block argument is not a region iter_arg
|
|
/// of this loop op or if there is no yield corresponding to this `bbArg`.
|
|
::mlir::OpOperand *getTiedLoopYieldedValue(::mlir::BlockArgument bbArg) {
|
|
auto iterArgs = (*this).getRegionIterArgs();
|
|
auto it = ::llvm::find(iterArgs, bbArg);
|
|
if (it == iterArgs.end())
|
|
return {};
|
|
::std::optional<::llvm::MutableArrayRef<::mlir::OpOperand>> yieldValues =
|
|
(*this).getYieldedValuesMutable();
|
|
if (!yieldValues)
|
|
return {};
|
|
return &yieldValues.value()[::std::distance(iterArgs.begin(), it)];
|
|
}
|
|
|
|
/// Return the loop result that corresponds to the given init operand.
|
|
/// Return an "empty" OpResult if the given operand is not an init operand
|
|
/// of this loop op or if this op does not expose any loop results.
|
|
::mlir::OpResult getTiedLoopResult(::mlir::OpOperand *opOperand) {
|
|
auto loopResults = (*this).getLoopResults();
|
|
if (!loopResults)
|
|
return {};
|
|
auto initsMutable = (*this).getInitsMutable();
|
|
auto it = ::llvm::find(initsMutable, *opOperand);
|
|
if (it == initsMutable.end())
|
|
return {};
|
|
return (*loopResults)[::std::distance(initsMutable.begin(), it)];
|
|
}
|
|
|
|
/// Return the loop result that corresponds to the given region iter_arg.
|
|
/// Return an "empty" OpResult if the given block argument is not a region
|
|
/// iter_arg of this loop op or if this op does not expose any loop results.
|
|
::mlir::OpResult getTiedLoopResult(::mlir::BlockArgument bbArg) {
|
|
auto loopResults = (*this).getLoopResults();
|
|
if (!loopResults)
|
|
return {};
|
|
auto iterArgs = (*this).getRegionIterArgs();
|
|
auto it = ::llvm::find(iterArgs, bbArg);
|
|
if (it == iterArgs.end())
|
|
return {};
|
|
return (*loopResults)[::std::distance(iterArgs.begin(), it)];
|
|
}
|
|
};
|
|
|
|
} // namespace mlir
|
|
namespace mlir::detail {
|
|
|
|
template <typename ConcreteOp>
|
|
struct LoopLikeOpInterfaceTrait : public ::mlir::OpInterface<LoopLikeOpInterface, detail::LoopLikeOpInterfaceInterfaceTraits>::Trait<ConcreteOp> {
|
|
|
|
/// Returns true if the given value is defined outside of the loop.
|
|
/// A sensible implementation could be to check whether the value's defining
|
|
/// operation lies outside of the loops body region. If the loop uses
|
|
/// explicit capture of dependencies, an implementation could check whether
|
|
/// the value corresponds to a captured dependency.
|
|
bool isDefinedOutsideOfLoop(::mlir::Value value) {
|
|
return !(*static_cast<ConcreteOp *>(this))->isAncestor(value.getParentRegion()->getParentOp());
|
|
}
|
|
|
|
/// Moves the given loop-invariant operation out of the loop.
|
|
void moveOutOfLoop(::mlir::Operation * op) {
|
|
op->moveBefore((*static_cast<ConcreteOp *>(this)));
|
|
}
|
|
|
|
/// Promotes the loop body to its containing block if the loop is known to
|
|
/// have a single iteration. Returns "success" if the promotion was
|
|
/// successful.
|
|
::llvm::LogicalResult promoteIfSingleIteration(::mlir::RewriterBase & rewriter) {
|
|
return ::mlir::failure();
|
|
}
|
|
|
|
/// Return all induction variables, if they exist. If the op has no notion of
|
|
/// induction variable, then return std::nullopt. If it does have
|
|
/// a notion but an instance doesn't have induction variables, then
|
|
/// return empty vector.
|
|
::std::optional<::llvm::SmallVector<::mlir::Value>> getLoopInductionVars() {
|
|
return ::std::nullopt;
|
|
}
|
|
|
|
/// Return all lower bounds, if they exist. If the op has no notion of
|
|
/// lower bounds, then return std::nullopt. If it does have
|
|
/// a notion but an instance doesn't have lower bounds, then
|
|
/// return empty vector.
|
|
::std::optional<::llvm::SmallVector<::mlir::OpFoldResult>> getLoopLowerBounds() {
|
|
return ::std::nullopt;
|
|
}
|
|
|
|
/// Return all steps, if they exist. If the op has no notion of
|
|
/// steps, then return std::nullopt. If it does have
|
|
/// a notion but an instance doesn't have steps, then
|
|
/// return empty vector.
|
|
::std::optional<::llvm::SmallVector<::mlir::OpFoldResult>> getLoopSteps() {
|
|
return ::std::nullopt;
|
|
}
|
|
|
|
/// Return all upper bounds, if they exist. If the op has no notion of
|
|
/// lower bounds, then return std::nullopt. If it does have
|
|
/// a notion but an instance doesn't have lower bounds, then
|
|
/// return empty vector.
|
|
::std::optional<::llvm::SmallVector<::mlir::OpFoldResult>> getLoopUpperBounds() {
|
|
return ::std::nullopt;
|
|
}
|
|
|
|
/// Return the mutable "init" operands that are used as initialization
|
|
/// values for the region "iter_args" of this loop.
|
|
::llvm::MutableArrayRef<::mlir::OpOperand> getInitsMutable() {
|
|
return {};
|
|
}
|
|
|
|
/// Return the region "iter_args" (block arguments) that correspond to the
|
|
/// "init" operands. If the op has multiple regions, return the
|
|
/// corresponding block arguments of the entry region.
|
|
::mlir::Block::BlockArgListType getRegionIterArgs() {
|
|
return ::mlir::Block::BlockArgListType();
|
|
}
|
|
|
|
/// Return the mutable operand range of values that are yielded to the next
|
|
/// iteration by the loop terminator.
|
|
///
|
|
/// For loop operations that dont yield a value, this should return
|
|
/// std::nullopt.
|
|
::std::optional<::llvm::MutableArrayRef<::mlir::OpOperand>> getYieldedValuesMutable() {
|
|
return ::std::nullopt;
|
|
}
|
|
|
|
/// Return the range of results that are return from this loop and
|
|
/// correspond to the "init" operands.
|
|
///
|
|
/// Note: This interface method is optional. If loop results are not
|
|
/// exposed via this interface, "std::nullopt" should be returned.
|
|
/// Otherwise, the number and types of results must match with the
|
|
/// region iter_args, inits and yielded values that are exposed via this
|
|
/// interface. If loop results are exposed but this loop op has no
|
|
/// loop-carried variables, an empty result range (and not "std::nullopt")
|
|
/// should be returned.
|
|
::std::optional<::mlir::ResultRange> getLoopResults() {
|
|
return ::std::nullopt;
|
|
}
|
|
|
|
/// Append the specified additional "init" operands: replace this loop with
|
|
/// a new loop that has the additional init operands. The loop body of
|
|
/// this loop is moved over to the new loop.
|
|
///
|
|
/// `newInitOperands` specifies the additional "init" operands.
|
|
/// `newYieldValuesFn` is a function that returns the yielded values (which
|
|
/// can be computed based on the additional region iter_args). If
|
|
/// `replaceInitOperandUsesInLoop` is set, all uses of the additional init
|
|
/// operands inside of this loop are replaced with the corresponding, newly
|
|
/// added region iter_args.
|
|
///
|
|
/// Note: Loops that do not support init/iter_args should return "failure".
|
|
::mlir::FailureOr<::mlir::LoopLikeOpInterface> replaceWithAdditionalYields(::mlir::RewriterBase & rewriter, ::mlir::ValueRange newInitOperands, bool replaceInitOperandUsesInLoop, const ::mlir::NewYieldValuesFn & newYieldValuesFn) {
|
|
return ::mlir::failure();
|
|
}
|
|
|
|
/// Compute the static trip count if possible.
|
|
::std::optional<::llvm::APInt> getStaticTripCount() {
|
|
return ::std::nullopt;
|
|
}
|
|
|
|
/// Check if the given type is supported as a loop induction variable.
|
|
/// By default, only IndexType is supported.
|
|
bool isValidInductionVarType(::mlir::Type type) {
|
|
return type.isIndex();
|
|
}
|
|
|
|
/// Update the loop lower bounds. Returns failure if the loop doesn't
|
|
/// support updating bounds or if the number of bounds doesn't match.
|
|
::mlir::LogicalResult setLoopLowerBounds(::llvm::ArrayRef<::mlir::OpFoldResult> bounds) {
|
|
return ::mlir::failure();
|
|
}
|
|
|
|
/// Update the loop upper bounds. Returns failure if the loop doesn't
|
|
/// support updating bounds or if the number of bounds doesn't match.
|
|
::mlir::LogicalResult setLoopUpperBounds(::llvm::ArrayRef<::mlir::OpFoldResult> bounds) {
|
|
return ::mlir::failure();
|
|
}
|
|
|
|
/// Update the loop steps. Returns failure if the loop doesn't support
|
|
/// updating steps or if the number of steps doesn't match.
|
|
::mlir::LogicalResult setLoopSteps(::llvm::ArrayRef<::mlir::OpFoldResult> steps) {
|
|
return ::mlir::failure();
|
|
}
|
|
static ::llvm::LogicalResult verifyRegionTrait(::mlir::Operation *op) {
|
|
return ::mlir::detail::verifyLoopLikeOpInterface(op);
|
|
}
|
|
|
|
/// If there is a single induction variable return it, otherwise return
|
|
/// std::nullopt.
|
|
::std::optional<::mlir::Value> getSingleInductionVar() {
|
|
auto inductionVars = (*static_cast<ConcreteOp *>(this)).getLoopInductionVars();
|
|
if (inductionVars.has_value() && (*inductionVars).size() == 1)
|
|
return (*inductionVars)[0];
|
|
return ::std::nullopt;
|
|
}
|
|
/// Return the single lower bound value or attribute if it exists, otherwise
|
|
/// return std::nullopt.
|
|
::std::optional<::mlir::OpFoldResult> getSingleLowerBound() {
|
|
auto lowerBounds = (*static_cast<ConcreteOp *>(this)).getLoopLowerBounds();
|
|
if (lowerBounds.has_value() && (*lowerBounds).size() == 1)
|
|
return (*lowerBounds)[0];
|
|
return ::std::nullopt;
|
|
}
|
|
/// Return the single step value or attribute if it exists, otherwise
|
|
/// return std::nullopt.
|
|
::std::optional<::mlir::OpFoldResult> getSingleStep() {
|
|
auto steps = (*static_cast<ConcreteOp *>(this)).getLoopSteps();
|
|
if (steps.has_value() && (*steps).size() == 1)
|
|
return (*steps)[0];
|
|
return ::std::nullopt;
|
|
}
|
|
/// Return the single upper bound value or attribute if it exists, otherwise
|
|
/// return std::nullopt.
|
|
::std::optional<::mlir::OpFoldResult> getSingleUpperBound() {
|
|
auto upperBounds = (*static_cast<ConcreteOp *>(this)).getLoopUpperBounds();
|
|
if (upperBounds.has_value() && (*upperBounds).size() == 1)
|
|
return (*upperBounds)[0];
|
|
return ::std::nullopt;
|
|
}
|
|
|
|
/// Append the specified additional "init" operands: replace this loop with
|
|
/// a new loop that has the additional init operands. The loop body of this
|
|
/// loop is moved over to the new loop.
|
|
///
|
|
/// The newly added region iter_args are yielded from the loop.
|
|
::mlir::FailureOr<::mlir::LoopLikeOpInterface>
|
|
replaceWithAdditionalIterOperands(::mlir::RewriterBase &rewriter,
|
|
::mlir::ValueRange newInitOperands,
|
|
bool replaceInitOperandUsesInLoop) {
|
|
return (*static_cast<ConcreteOp *>(this)).replaceWithAdditionalYields(
|
|
rewriter, newInitOperands, replaceInitOperandUsesInLoop,
|
|
[](::mlir::OpBuilder &b, ::mlir::Location loc,
|
|
::mlir::ArrayRef<::mlir::BlockArgument> newBBArgs) {
|
|
return ::mlir::SmallVector<::mlir::Value>(newBBArgs);
|
|
});
|
|
}
|
|
|
|
/// Return the values that are yielded to the next iteration. If
|
|
/// the loop doesnt yield any values return `{}`.
|
|
::mlir::ValueRange getYieldedValues() {
|
|
auto mutableValues = (*static_cast<ConcreteOp *>(this)).getYieldedValuesMutable();
|
|
if (!mutableValues || mutableValues->empty())
|
|
return {};
|
|
::mlir::Operation *yieldOp = mutableValues->begin()->getOwner();
|
|
unsigned firstOperandIndex = mutableValues->begin()->getOperandNumber();
|
|
return ::mlir::OperandRange(
|
|
yieldOp->operand_begin() + firstOperandIndex,
|
|
yieldOp->operand_begin() + firstOperandIndex + mutableValues->size());
|
|
}
|
|
|
|
/// Return the "init" operands that are used as initialization values for
|
|
/// the region "iter_args" of this loop.
|
|
::mlir::OperandRange getInits() {
|
|
auto initsMutable = (*static_cast<ConcreteOp *>(this)).getInitsMutable();
|
|
if (initsMutable.empty())
|
|
return ::mlir::OperandRange((*static_cast<ConcreteOp *>(this))->operand_end(), (*static_cast<ConcreteOp *>(this))->operand_end());
|
|
unsigned firstOperandIndex = initsMutable.begin()->getOperandNumber();
|
|
return ::mlir::OperandRange(
|
|
(*static_cast<ConcreteOp *>(this))->operand_begin() + firstOperandIndex,
|
|
(*static_cast<ConcreteOp *>(this))->operand_begin() + firstOperandIndex + initsMutable.size());
|
|
}
|
|
|
|
/// Return the region iter_arg that corresponds to the given init operand.
|
|
/// Return an "empty" block argument if the given operand is not an init
|
|
/// operand of this loop op.
|
|
::mlir::BlockArgument getTiedLoopRegionIterArg(
|
|
::mlir::OpOperand *opOperand) {
|
|
auto initsMutable = (*static_cast<ConcreteOp *>(this)).getInitsMutable();
|
|
auto it = ::llvm::find(initsMutable, *opOperand);
|
|
if (it == initsMutable.end())
|
|
return {};
|
|
return (*static_cast<ConcreteOp *>(this)).getRegionIterArgs()[
|
|
::std::distance(initsMutable.begin(), it)];
|
|
}
|
|
|
|
/// Return the region iter_arg that corresponds to the given loop result.
|
|
/// Return an "empty" block argument if the given OpResult is not a loop
|
|
/// result or if this op does not expose any loop results.
|
|
::mlir::BlockArgument getTiedLoopRegionIterArg(::mlir::OpResult opResult) {
|
|
auto loopResults = (*static_cast<ConcreteOp *>(this)).getLoopResults();
|
|
if (!loopResults)
|
|
return {};
|
|
auto it = ::llvm::find(*loopResults, opResult);
|
|
if (it == loopResults->end())
|
|
return {};
|
|
return (*static_cast<ConcreteOp *>(this)).getRegionIterArgs()[
|
|
::std::distance(loopResults->begin(), it)];
|
|
}
|
|
|
|
/// Return the init operand that corresponds to the given region iter_arg.
|
|
/// Return "nullptr" if the given block argument is not a region iter_arg
|
|
/// of this loop op.
|
|
::mlir::OpOperand *getTiedLoopInit(::mlir::BlockArgument bbArg) {
|
|
auto iterArgs = (*static_cast<ConcreteOp *>(this)).getRegionIterArgs();
|
|
auto it = ::llvm::find(iterArgs, bbArg);
|
|
if (it == iterArgs.end())
|
|
return {};
|
|
return &(*static_cast<ConcreteOp *>(this)).getInitsMutable()[::std::distance(iterArgs.begin(), it)];
|
|
}
|
|
|
|
/// Return the init operand that corresponds to the given loop result.
|
|
/// Return "nullptr" if the given OpResult is not a loop result or if this
|
|
/// op does not expose any loop results.
|
|
::mlir::OpOperand *getTiedLoopInit(::mlir::OpResult opResult) {
|
|
auto loopResults = (*static_cast<ConcreteOp *>(this)).getLoopResults();
|
|
if (!loopResults)
|
|
return nullptr;
|
|
auto it = ::llvm::find(*loopResults, opResult);
|
|
if (it == loopResults->end())
|
|
return nullptr;
|
|
return &(*static_cast<ConcreteOp *>(this)).getInitsMutable()[::std::distance(
|
|
loopResults->begin(), it)];
|
|
}
|
|
|
|
/// Return the yielded value that corresponds to the given region iter_arg.
|
|
/// Return "nullptr" if the given block argument is not a region iter_arg
|
|
/// of this loop op or if there is no yield corresponding to this `bbArg`.
|
|
::mlir::OpOperand *getTiedLoopYieldedValue(::mlir::BlockArgument bbArg) {
|
|
auto iterArgs = (*static_cast<ConcreteOp *>(this)).getRegionIterArgs();
|
|
auto it = ::llvm::find(iterArgs, bbArg);
|
|
if (it == iterArgs.end())
|
|
return {};
|
|
::std::optional<::llvm::MutableArrayRef<::mlir::OpOperand>> yieldValues =
|
|
(*static_cast<ConcreteOp *>(this)).getYieldedValuesMutable();
|
|
if (!yieldValues)
|
|
return {};
|
|
return &yieldValues.value()[::std::distance(iterArgs.begin(), it)];
|
|
}
|
|
|
|
/// Return the loop result that corresponds to the given init operand.
|
|
/// Return an "empty" OpResult if the given operand is not an init operand
|
|
/// of this loop op or if this op does not expose any loop results.
|
|
::mlir::OpResult getTiedLoopResult(::mlir::OpOperand *opOperand) {
|
|
auto loopResults = (*static_cast<ConcreteOp *>(this)).getLoopResults();
|
|
if (!loopResults)
|
|
return {};
|
|
auto initsMutable = (*static_cast<ConcreteOp *>(this)).getInitsMutable();
|
|
auto it = ::llvm::find(initsMutable, *opOperand);
|
|
if (it == initsMutable.end())
|
|
return {};
|
|
return (*loopResults)[::std::distance(initsMutable.begin(), it)];
|
|
}
|
|
|
|
/// Return the loop result that corresponds to the given region iter_arg.
|
|
/// Return an "empty" OpResult if the given block argument is not a region
|
|
/// iter_arg of this loop op or if this op does not expose any loop results.
|
|
::mlir::OpResult getTiedLoopResult(::mlir::BlockArgument bbArg) {
|
|
auto loopResults = (*static_cast<ConcreteOp *>(this)).getLoopResults();
|
|
if (!loopResults)
|
|
return {};
|
|
auto iterArgs = (*static_cast<ConcreteOp *>(this)).getRegionIterArgs();
|
|
auto it = ::llvm::find(iterArgs, bbArg);
|
|
if (it == iterArgs.end())
|
|
return {};
|
|
return (*loopResults)[::std::distance(iterArgs.begin(), it)];
|
|
}
|
|
|
|
};
|
|
|
|
} // namespace mlir::detail
|
|
namespace mlir {
|
|
|
|
template<typename ConcreteOp>
|
|
bool detail::LoopLikeOpInterfaceInterfaceTraits::Model<ConcreteOp>::isDefinedOutsideOfLoop(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::Value value) {
|
|
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).isDefinedOutsideOfLoop(value);
|
|
}
|
|
template<typename ConcreteOp>
|
|
::llvm::SmallVector<::mlir::Region *> detail::LoopLikeOpInterfaceInterfaceTraits::Model<ConcreteOp>::getLoopRegions(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
|
|
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getLoopRegions();
|
|
}
|
|
template<typename ConcreteOp>
|
|
void detail::LoopLikeOpInterfaceInterfaceTraits::Model<ConcreteOp>::moveOutOfLoop(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::Operation * op) {
|
|
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).moveOutOfLoop(op);
|
|
}
|
|
template<typename ConcreteOp>
|
|
::llvm::LogicalResult detail::LoopLikeOpInterfaceInterfaceTraits::Model<ConcreteOp>::promoteIfSingleIteration(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::RewriterBase & rewriter) {
|
|
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).promoteIfSingleIteration(rewriter);
|
|
}
|
|
template<typename ConcreteOp>
|
|
::std::optional<::llvm::SmallVector<::mlir::Value>> detail::LoopLikeOpInterfaceInterfaceTraits::Model<ConcreteOp>::getLoopInductionVars(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
|
|
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getLoopInductionVars();
|
|
}
|
|
template<typename ConcreteOp>
|
|
::std::optional<::llvm::SmallVector<::mlir::OpFoldResult>> detail::LoopLikeOpInterfaceInterfaceTraits::Model<ConcreteOp>::getLoopLowerBounds(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
|
|
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getLoopLowerBounds();
|
|
}
|
|
template<typename ConcreteOp>
|
|
::std::optional<::llvm::SmallVector<::mlir::OpFoldResult>> detail::LoopLikeOpInterfaceInterfaceTraits::Model<ConcreteOp>::getLoopSteps(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
|
|
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getLoopSteps();
|
|
}
|
|
template<typename ConcreteOp>
|
|
::std::optional<::llvm::SmallVector<::mlir::OpFoldResult>> detail::LoopLikeOpInterfaceInterfaceTraits::Model<ConcreteOp>::getLoopUpperBounds(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
|
|
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getLoopUpperBounds();
|
|
}
|
|
template<typename ConcreteOp>
|
|
::llvm::MutableArrayRef<::mlir::OpOperand> detail::LoopLikeOpInterfaceInterfaceTraits::Model<ConcreteOp>::getInitsMutable(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
|
|
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getInitsMutable();
|
|
}
|
|
template<typename ConcreteOp>
|
|
::mlir::Block::BlockArgListType detail::LoopLikeOpInterfaceInterfaceTraits::Model<ConcreteOp>::getRegionIterArgs(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
|
|
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getRegionIterArgs();
|
|
}
|
|
template<typename ConcreteOp>
|
|
::std::optional<::llvm::MutableArrayRef<::mlir::OpOperand>> detail::LoopLikeOpInterfaceInterfaceTraits::Model<ConcreteOp>::getYieldedValuesMutable(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
|
|
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getYieldedValuesMutable();
|
|
}
|
|
template<typename ConcreteOp>
|
|
::std::optional<::mlir::ResultRange> detail::LoopLikeOpInterfaceInterfaceTraits::Model<ConcreteOp>::getLoopResults(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
|
|
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getLoopResults();
|
|
}
|
|
template<typename ConcreteOp>
|
|
::mlir::FailureOr<::mlir::LoopLikeOpInterface> detail::LoopLikeOpInterfaceInterfaceTraits::Model<ConcreteOp>::replaceWithAdditionalYields(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::RewriterBase & rewriter, ::mlir::ValueRange newInitOperands, bool replaceInitOperandUsesInLoop, const ::mlir::NewYieldValuesFn & newYieldValuesFn) {
|
|
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).replaceWithAdditionalYields(rewriter, newInitOperands, replaceInitOperandUsesInLoop, newYieldValuesFn);
|
|
}
|
|
template<typename ConcreteOp>
|
|
::std::optional<::llvm::APInt> detail::LoopLikeOpInterfaceInterfaceTraits::Model<ConcreteOp>::getStaticTripCount(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
|
|
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getStaticTripCount();
|
|
}
|
|
template<typename ConcreteOp>
|
|
bool detail::LoopLikeOpInterfaceInterfaceTraits::Model<ConcreteOp>::isValidInductionVarType(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::Type type) {
|
|
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).isValidInductionVarType(type);
|
|
}
|
|
template<typename ConcreteOp>
|
|
::mlir::LogicalResult detail::LoopLikeOpInterfaceInterfaceTraits::Model<ConcreteOp>::setLoopLowerBounds(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::llvm::ArrayRef<::mlir::OpFoldResult> bounds) {
|
|
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).setLoopLowerBounds(bounds);
|
|
}
|
|
template<typename ConcreteOp>
|
|
::mlir::LogicalResult detail::LoopLikeOpInterfaceInterfaceTraits::Model<ConcreteOp>::setLoopUpperBounds(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::llvm::ArrayRef<::mlir::OpFoldResult> bounds) {
|
|
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).setLoopUpperBounds(bounds);
|
|
}
|
|
template<typename ConcreteOp>
|
|
::mlir::LogicalResult detail::LoopLikeOpInterfaceInterfaceTraits::Model<ConcreteOp>::setLoopSteps(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::llvm::ArrayRef<::mlir::OpFoldResult> steps) {
|
|
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).setLoopSteps(steps);
|
|
}
|
|
template<typename ConcreteOp>
|
|
bool detail::LoopLikeOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::isDefinedOutsideOfLoop(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::Value value) {
|
|
return static_cast<const ConcreteOp *>(impl)->isDefinedOutsideOfLoop(tablegen_opaque_val, value);
|
|
}
|
|
template<typename ConcreteOp>
|
|
::llvm::SmallVector<::mlir::Region *> detail::LoopLikeOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::getLoopRegions(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
|
|
return static_cast<const ConcreteOp *>(impl)->getLoopRegions(tablegen_opaque_val);
|
|
}
|
|
template<typename ConcreteOp>
|
|
void detail::LoopLikeOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::moveOutOfLoop(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::Operation * op) {
|
|
return static_cast<const ConcreteOp *>(impl)->moveOutOfLoop(tablegen_opaque_val, op);
|
|
}
|
|
template<typename ConcreteOp>
|
|
::llvm::LogicalResult detail::LoopLikeOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::promoteIfSingleIteration(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::RewriterBase & rewriter) {
|
|
return static_cast<const ConcreteOp *>(impl)->promoteIfSingleIteration(tablegen_opaque_val, rewriter);
|
|
}
|
|
template<typename ConcreteOp>
|
|
::std::optional<::llvm::SmallVector<::mlir::Value>> detail::LoopLikeOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::getLoopInductionVars(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
|
|
return static_cast<const ConcreteOp *>(impl)->getLoopInductionVars(tablegen_opaque_val);
|
|
}
|
|
template<typename ConcreteOp>
|
|
::std::optional<::llvm::SmallVector<::mlir::OpFoldResult>> detail::LoopLikeOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::getLoopLowerBounds(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
|
|
return static_cast<const ConcreteOp *>(impl)->getLoopLowerBounds(tablegen_opaque_val);
|
|
}
|
|
template<typename ConcreteOp>
|
|
::std::optional<::llvm::SmallVector<::mlir::OpFoldResult>> detail::LoopLikeOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::getLoopSteps(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
|
|
return static_cast<const ConcreteOp *>(impl)->getLoopSteps(tablegen_opaque_val);
|
|
}
|
|
template<typename ConcreteOp>
|
|
::std::optional<::llvm::SmallVector<::mlir::OpFoldResult>> detail::LoopLikeOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::getLoopUpperBounds(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
|
|
return static_cast<const ConcreteOp *>(impl)->getLoopUpperBounds(tablegen_opaque_val);
|
|
}
|
|
template<typename ConcreteOp>
|
|
::llvm::MutableArrayRef<::mlir::OpOperand> detail::LoopLikeOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::getInitsMutable(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
|
|
return static_cast<const ConcreteOp *>(impl)->getInitsMutable(tablegen_opaque_val);
|
|
}
|
|
template<typename ConcreteOp>
|
|
::mlir::Block::BlockArgListType detail::LoopLikeOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::getRegionIterArgs(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
|
|
return static_cast<const ConcreteOp *>(impl)->getRegionIterArgs(tablegen_opaque_val);
|
|
}
|
|
template<typename ConcreteOp>
|
|
::std::optional<::llvm::MutableArrayRef<::mlir::OpOperand>> detail::LoopLikeOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::getYieldedValuesMutable(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
|
|
return static_cast<const ConcreteOp *>(impl)->getYieldedValuesMutable(tablegen_opaque_val);
|
|
}
|
|
template<typename ConcreteOp>
|
|
::std::optional<::mlir::ResultRange> detail::LoopLikeOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::getLoopResults(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
|
|
return static_cast<const ConcreteOp *>(impl)->getLoopResults(tablegen_opaque_val);
|
|
}
|
|
template<typename ConcreteOp>
|
|
::mlir::FailureOr<::mlir::LoopLikeOpInterface> detail::LoopLikeOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::replaceWithAdditionalYields(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::RewriterBase & rewriter, ::mlir::ValueRange newInitOperands, bool replaceInitOperandUsesInLoop, const ::mlir::NewYieldValuesFn & newYieldValuesFn) {
|
|
return static_cast<const ConcreteOp *>(impl)->replaceWithAdditionalYields(tablegen_opaque_val, rewriter, newInitOperands, replaceInitOperandUsesInLoop, newYieldValuesFn);
|
|
}
|
|
template<typename ConcreteOp>
|
|
::std::optional<::llvm::APInt> detail::LoopLikeOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::getStaticTripCount(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
|
|
return static_cast<const ConcreteOp *>(impl)->getStaticTripCount(tablegen_opaque_val);
|
|
}
|
|
template<typename ConcreteOp>
|
|
bool detail::LoopLikeOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::isValidInductionVarType(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::Type type) {
|
|
return static_cast<const ConcreteOp *>(impl)->isValidInductionVarType(tablegen_opaque_val, type);
|
|
}
|
|
template<typename ConcreteOp>
|
|
::mlir::LogicalResult detail::LoopLikeOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::setLoopLowerBounds(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::llvm::ArrayRef<::mlir::OpFoldResult> bounds) {
|
|
return static_cast<const ConcreteOp *>(impl)->setLoopLowerBounds(tablegen_opaque_val, bounds);
|
|
}
|
|
template<typename ConcreteOp>
|
|
::mlir::LogicalResult detail::LoopLikeOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::setLoopUpperBounds(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::llvm::ArrayRef<::mlir::OpFoldResult> bounds) {
|
|
return static_cast<const ConcreteOp *>(impl)->setLoopUpperBounds(tablegen_opaque_val, bounds);
|
|
}
|
|
template<typename ConcreteOp>
|
|
::mlir::LogicalResult detail::LoopLikeOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::setLoopSteps(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::llvm::ArrayRef<::mlir::OpFoldResult> steps) {
|
|
return static_cast<const ConcreteOp *>(impl)->setLoopSteps(tablegen_opaque_val, steps);
|
|
}
|
|
template<typename ConcreteModel, typename ConcreteOp>
|
|
bool detail::LoopLikeOpInterfaceInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::isDefinedOutsideOfLoop(::mlir::Operation *tablegen_opaque_val, ::mlir::Value value) const {
|
|
return !(llvm::cast<ConcreteOp>(tablegen_opaque_val))->isAncestor(value.getParentRegion()->getParentOp());
|
|
}
|
|
template<typename ConcreteModel, typename ConcreteOp>
|
|
void detail::LoopLikeOpInterfaceInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::moveOutOfLoop(::mlir::Operation *tablegen_opaque_val, ::mlir::Operation *op) const {
|
|
op->moveBefore((llvm::cast<ConcreteOp>(tablegen_opaque_val)));
|
|
}
|
|
template<typename ConcreteModel, typename ConcreteOp>
|
|
::llvm::LogicalResult detail::LoopLikeOpInterfaceInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::promoteIfSingleIteration(::mlir::Operation *tablegen_opaque_val, ::mlir::RewriterBase &rewriter) const {
|
|
return ::mlir::failure();
|
|
}
|
|
template<typename ConcreteModel, typename ConcreteOp>
|
|
::std::optional<::llvm::SmallVector<::mlir::Value>> detail::LoopLikeOpInterfaceInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::getLoopInductionVars(::mlir::Operation *tablegen_opaque_val) const {
|
|
return ::std::nullopt;
|
|
}
|
|
template<typename ConcreteModel, typename ConcreteOp>
|
|
::std::optional<::llvm::SmallVector<::mlir::OpFoldResult>> detail::LoopLikeOpInterfaceInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::getLoopLowerBounds(::mlir::Operation *tablegen_opaque_val) const {
|
|
return ::std::nullopt;
|
|
}
|
|
template<typename ConcreteModel, typename ConcreteOp>
|
|
::std::optional<::llvm::SmallVector<::mlir::OpFoldResult>> detail::LoopLikeOpInterfaceInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::getLoopSteps(::mlir::Operation *tablegen_opaque_val) const {
|
|
return ::std::nullopt;
|
|
}
|
|
template<typename ConcreteModel, typename ConcreteOp>
|
|
::std::optional<::llvm::SmallVector<::mlir::OpFoldResult>> detail::LoopLikeOpInterfaceInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::getLoopUpperBounds(::mlir::Operation *tablegen_opaque_val) const {
|
|
return ::std::nullopt;
|
|
}
|
|
template<typename ConcreteModel, typename ConcreteOp>
|
|
::llvm::MutableArrayRef<::mlir::OpOperand> detail::LoopLikeOpInterfaceInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::getInitsMutable(::mlir::Operation *tablegen_opaque_val) const {
|
|
return {};
|
|
}
|
|
template<typename ConcreteModel, typename ConcreteOp>
|
|
::mlir::Block::BlockArgListType detail::LoopLikeOpInterfaceInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::getRegionIterArgs(::mlir::Operation *tablegen_opaque_val) const {
|
|
return ::mlir::Block::BlockArgListType();
|
|
}
|
|
template<typename ConcreteModel, typename ConcreteOp>
|
|
::std::optional<::llvm::MutableArrayRef<::mlir::OpOperand>> detail::LoopLikeOpInterfaceInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::getYieldedValuesMutable(::mlir::Operation *tablegen_opaque_val) const {
|
|
return ::std::nullopt;
|
|
}
|
|
template<typename ConcreteModel, typename ConcreteOp>
|
|
::std::optional<::mlir::ResultRange> detail::LoopLikeOpInterfaceInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::getLoopResults(::mlir::Operation *tablegen_opaque_val) const {
|
|
return ::std::nullopt;
|
|
}
|
|
template<typename ConcreteModel, typename ConcreteOp>
|
|
::mlir::FailureOr<::mlir::LoopLikeOpInterface> detail::LoopLikeOpInterfaceInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::replaceWithAdditionalYields(::mlir::Operation *tablegen_opaque_val, ::mlir::RewriterBase &rewriter, ::mlir::ValueRange newInitOperands, bool replaceInitOperandUsesInLoop, const ::mlir::NewYieldValuesFn &newYieldValuesFn) const {
|
|
return ::mlir::failure();
|
|
}
|
|
template<typename ConcreteModel, typename ConcreteOp>
|
|
::std::optional<::llvm::APInt> detail::LoopLikeOpInterfaceInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::getStaticTripCount(::mlir::Operation *tablegen_opaque_val) const {
|
|
return ::std::nullopt;
|
|
}
|
|
template<typename ConcreteModel, typename ConcreteOp>
|
|
bool detail::LoopLikeOpInterfaceInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::isValidInductionVarType(::mlir::Operation *tablegen_opaque_val, ::mlir::Type type) const {
|
|
return type.isIndex();
|
|
}
|
|
template<typename ConcreteModel, typename ConcreteOp>
|
|
::mlir::LogicalResult detail::LoopLikeOpInterfaceInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::setLoopLowerBounds(::mlir::Operation *tablegen_opaque_val, ::llvm::ArrayRef<::mlir::OpFoldResult> bounds) const {
|
|
return ::mlir::failure();
|
|
}
|
|
template<typename ConcreteModel, typename ConcreteOp>
|
|
::mlir::LogicalResult detail::LoopLikeOpInterfaceInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::setLoopUpperBounds(::mlir::Operation *tablegen_opaque_val, ::llvm::ArrayRef<::mlir::OpFoldResult> bounds) const {
|
|
return ::mlir::failure();
|
|
}
|
|
template<typename ConcreteModel, typename ConcreteOp>
|
|
::mlir::LogicalResult detail::LoopLikeOpInterfaceInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::setLoopSteps(::mlir::Operation *tablegen_opaque_val, ::llvm::ArrayRef<::mlir::OpFoldResult> steps) const {
|
|
return ::mlir::failure();
|
|
}
|
|
|
|
} // namespace mlir
|