//===- Utils.h - General Arith transformation utilities ----*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This header file defines prototypes for various transformation utilities for // the Arith dialect. These are not passes by themselves but are used // either by passes, optimization sequences, or in turn by other transformation // utilities. // //===----------------------------------------------------------------------===// #ifndef MLIR_DIALECT_ARITH_UTILS_UTILS_H #define MLIR_DIALECT_ARITH_UTILS_UTILS_H #include "mlir/Dialect/Arith/IR/Arith.h" #include "mlir/IR/Matchers.h" #include "mlir/IR/PatternMatch.h" #include "mlir/IR/Value.h" #include "llvm/ADT/ArrayRef.h" namespace mlir { using ReassociationIndices = SmallVector; /// Infer the output shape for a {memref|tensor}.expand_shape when it is /// possible to do so. /// /// Note: This should *only* be used to implement /// `ExpandShapeOp::inferOutputShape` in both the memref and tensor namespaces. /// If you need to infer the output shape you should use the static method of /// `ExpandShapeOp` instead of calling this. /// /// `inputShape` is the shape of the tensor or memref being expanded as a /// sequence of SSA values or constants. `expandedType` is the output shape of /// the expand_shape operation. `reassociation` is the reassociation denoting /// the output dims each input dim is mapped to. /// /// Returns the output shape in `outputShape` and `staticOutputShape`, following /// the conventions for the output_shape and static_output_shape inputs to the /// expand_shape ops. std::optional> inferExpandShapeOutputShape(OpBuilder &b, Location loc, ShapedType expandedType, ArrayRef reassociation, ArrayRef inputShape); /// Matches a ConstantIndexOp. detail::op_matcher matchConstantIndex(); llvm::SmallBitVector getPositionsOfShapeOne(unsigned rank, ArrayRef shape); /// Converts an OpFoldResult to a Value. Returns the fold result if it casts to /// a Value or creates a ConstantOp if it casts to an Integer Attribute. /// Other attribute types are not supported. Value getValueOrCreateConstantIntOp(OpBuilder &b, Location loc, OpFoldResult ofr); /// Converts an OpFoldResult to a Value. Returns the fold result if it casts to /// a Value or creates a ConstantIndexOp if it casts to an Integer Attribute. /// Other attribute types are not supported. Value getValueOrCreateConstantIndexOp(OpBuilder &b, Location loc, OpFoldResult ofr); /// Similar to the other overload, but converts multiple OpFoldResults into /// Values. SmallVector getValueOrCreateConstantIndexOp(OpBuilder &b, Location loc, ArrayRef valueOrAttrVec); /// Create a cast from an index-like value (index or integer) to another /// index-like value. If the value type and the target type are the same, it /// returns the original value. Value getValueOrCreateCastToIndexLike(OpBuilder &b, Location loc, Type targetType, Value value); /// Converts a scalar value `operand` to type `toType`. If the value doesn't /// convert, a warning will be issued and the operand is returned as is (which /// will presumably yield a verification issue downstream). Value convertScalarToDtype(OpBuilder &b, Location loc, Value operand, Type toType, bool isUnsignedCast); /// Create a constant of type `type` at location `loc` whose value is `value` /// (an APInt or APFloat whose type must match the element type of `type`). /// If `type` is a shaped type, create a splat constant of the given value. /// Constants are folded if possible. Value createScalarOrSplatConstant(OpBuilder &builder, Location loc, Type type, const APInt &value); Value createScalarOrSplatConstant(OpBuilder &builder, Location loc, Type type, int64_t value); Value createScalarOrSplatConstant(OpBuilder &builder, Location loc, Type type, const APFloat &value); /// Returns the int type of the integer in ofr. /// Other attribute types are not supported. Type getType(OpFoldResult ofr); /// Helper struct to build simple arithmetic quantities with minimal type /// inference support. struct ArithBuilder { ArithBuilder( OpBuilder &b, Location loc, arith::IntegerOverflowFlags ovf = arith::IntegerOverflowFlags::none) : b(b), loc(loc), ovf(ovf) {} Value _and(Value lhs, Value rhs); Value add(Value lhs, Value rhs); Value sub(Value lhs, Value rhs); Value mul(Value lhs, Value rhs); Value select(Value cmp, Value lhs, Value rhs); Value sgt(Value lhs, Value rhs); Value slt(Value lhs, Value rhs); private: OpBuilder &b; Location loc; arith::IntegerOverflowFlags ovf; }; /// ArithBuilder specialized specifically for tensor/memref indexing /// calculations. Those calculations generally should never signed overflow and /// always use signed integers, so we can set oveflow flags accordingly. struct ArithIndexingBuilder : public ArithBuilder { ArithIndexingBuilder(OpBuilder &b, Location loc) : ArithBuilder(b, loc, arith::IntegerOverflowFlags::nsw) {} }; namespace arith { // Build the product of a sequence. // If values = (v0, v1, ..., vn) than the returned // value is v0 * v1 * ... * vn. // All values must have the same type. // // The version without `resultType` must contain at least one element in values. // Then the result will have the same type as the elements in `values`. // If `values` is empty in the version with `resultType` returns 1 with type // `resultType`. Value createProduct(OpBuilder &builder, Location loc, ArrayRef values); Value createProduct(OpBuilder &builder, Location loc, ArrayRef values, Type resultType); // Map strings to float types. Returns nullptr if the name is not a known // floating-point type. FloatType parseFloatType(MLIRContext *ctx, StringRef name); } // namespace arith } // namespace mlir #endif // MLIR_DIALECT_ARITH_UTILS_UTILS_H