[llvm-branch-commits] [mlir] 28070f1 - xla_lhlo dialect fixes to work with upstream
Author: Uday Bondhugula Date: 2021-09-22T14:28:52+05:30 New Revision: 28070f1be700f812dd228e51ecbe1efb3b4a73ea URL: https://github.com/llvm/llvm-project/commit/28070f1be700f812dd228e51ecbe1efb3b4a73ea DIFF: https://github.com/llvm/llvm-project/commit/28070f1be700f812dd228e51ecbe1efb3b4a73ea.diff LOG: xla_lhlo dialect fixes to work with upstream Added: Modified: mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.h mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td mlir/include/mlir/InitAllDialects.h mlir/lib/Dialect/LHLO/IR/CMakeLists.txt mlir/lib/Dialect/LHLO/IR/LHLOOps.cc mlir/test/Dialect/LHLO/lhlo_ops.mlir Removed: diff --git a/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.h b/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.h index 45309f5110ad..c17ee6d63bd4 100644 --- a/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.h +++ b/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.h @@ -20,28 +20,25 @@ limitations under the License. #include "llvm/ADT/StringRef.h" #include "mlir/IR/Attributes.h" // from @llvm-project +#include "mlir/IR/BuiltinTypes.h" // from @llvm-project #include "mlir/IR/Dialect.h" // from @llvm-project #include "mlir/IR/Location.h" // from @llvm-project #include "mlir/IR/MLIRContext.h" // from @llvm-project #include "mlir/IR/OpDefinition.h" // from @llvm-project #include "mlir/IR/Operation.h" // from @llvm-project -#include "mlir/IR/StandardTypes.h" // from @llvm-project #include "mlir/IR/Types.h" // from @llvm-project #include "mlir/Interfaces/SideEffectInterfaces.h" // from @llvm-project namespace mlir { class OpBuilder; +} // end namespace mlir #include "mlir/Dialect/LHLO/IR/LHLOStructs.h.inc" -namespace xla_lhlo { - #include "mlir/Dialect/LHLO/IR/LHLOOpsDialect.h.inc" #define GET_OP_CLASSES #include "mlir/Dialect/LHLO/IR/LHLOOps.h.inc" -} // namespace xla_lhlo -} // end namespace mlir #endif // MLIR_DIALECT_LHLO_IR_LHLO_OPS_H_ diff --git a/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td b/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td index 3ae266e82c3c..7f83425f138c 100644 --- a/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td +++ b/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td @@ -24,7 +24,7 @@ include "mlir/Dialect/LHLO/IR/HLOOpsBase.td" def LHLO_Dialect : Dialect { let name = "xla_lhlo"; - let cppNamespace = "xla_lhlo"; + let cppNamespace = "::mlir::xla_lhlo"; } //===--===// @@ -382,7 +382,7 @@ def ConvDimensionNumbers : StructAttr<"ConvDimensionNumbers", LHLO_Dialect, [ StructFieldAttr<"output_feature_dimension", I64Attr>, StructFieldAttr<"output_spatial_dimensions", I64ElementsAttr>] > { - let description = "Structure of dimension information for conv op"; + let summary = "Structure of dimension information for conv op"; } def LHLO_ConvOp : LHLO_Op<"convolution", []>, BASE_HLO_ConvOp { @@ -427,7 +427,7 @@ def DotDimensionNumbers : StructAttr<"DotDimensionNumbers", LHLO_Dialect, [ StructFieldAttr<"lhs_contracting_dimensions", I64ElementsAttr>, StructFieldAttr<"rhs_contracting_dimensions", I64ElementsAttr> ]> { - let description = "Structure of dimension information for dot product"; + let summary = "Structure of dimension information for dot product"; } def LHLO_DotGeneralOp : LHLO_Op<"dot_general", []>, BASE_HLO_DotGeneralOp { @@ -452,7 +452,7 @@ def GatherDimensionNumbers: StructAttr<"GatherDimensionNumbers", LHLO_Dialect, StructFieldAttr<"collapsed_slice_dims", I64ElementsAttr>, StructFieldAttr<"start_index_map", I64ElementsAttr>, StructFieldAttr<"index_vector_dim", I64Attr>]> { - let description = "Structure of dimension information for gather"; + let summary = "Structure of dimension information for gather"; } def LHLO_GatherOp: LHLO_Op<"gather", []>, BASE_HLO_GatherOp { @@ -489,7 +489,7 @@ def ScatterDimensionNumbers StructFieldAttr<"scatter_dims_to_operand_dims", I64ElementsAttr>, StructFieldAttr<"index_vector_dim", I64Attr> ]> { - let description = "Structure of dimension information for scatter"; + let summary = "Structure of dimension information for scatter"; } def LHLO_ScatterOp: LHLO_Op<"scatter", [RecursiveSideEffects]>, @@ -597,9 +597,7 @@ def LHLO_TupleOp : LHLO_ReadOnlyOp<"tuple", [NoSideEffect]>, BASE_HLO_TupleOp { let arguments = (ins Arg, "", [MemRead]>:$input); let results = (outs NestedTupleOf<[LHLO_BufferOrIntOrFP]>); - let builders = [OpBuilder< - "OpBuilder &builder, OperationState &results, " - "ValueRange values">]; + let builders = [OpBuilder<(ins "ValueRange":$values)>]; } def LHLO_WhileOp @@ -642,8 +640,7 @@ def FusionOp : LHLO_Op<"fusion", [SingleBlockImplicitTerminator<"TerminatorOp">] let skipDefaultBuilders = 1; let builders = [ - OpBuilder<"OpBuilder &builder, Operatio
[llvm-branch-commits] [mlir] 1e17c40 - [MLIR] Introduce trait EquiMemRefAndEltTypeOperands
Author: Uday Bondhugula Date: 2021-09-22T14:23:45+05:30 New Revision: 1e17c40c4ce8daf46bf5df28a04d1e9ea5690cb2 URL: https://github.com/llvm/llvm-project/commit/1e17c40c4ce8daf46bf5df28a04d1e9ea5690cb2 DIFF: https://github.com/llvm/llvm-project/commit/1e17c40c4ce8daf46bf5df28a04d1e9ea5690cb2.diff LOG: [MLIR] Introduce trait EquiMemRefAndEltTypeOperands This trait is used by LHLO ops where the operands and result may either have operands of the same type or equivalent types where a 0-d memref of an elemental type is considered equivalent to that elemental type. TODO: add a test dialect test case here. Added: Modified: mlir/include/mlir/IR/OpBase.td mlir/include/mlir/IR/OpDefinition.h mlir/lib/IR/Operation.cpp Removed: diff --git a/mlir/include/mlir/IR/OpBase.td b/mlir/include/mlir/IR/OpBase.td index ac99ac4d0897d..d82b734a329a8 100644 --- a/mlir/include/mlir/IR/OpBase.td +++ b/mlir/include/mlir/IR/OpBase.td @@ -1889,6 +1889,9 @@ def IsolatedFromAbove : NativeOpTrait<"IsIsolatedFromAbove">; def ResultsAreFloatLike : NativeOpTrait<"ResultsAreFloatLike">; // Op has the same operand type. def SameTypeOperands : NativeOpTrait<"SameTypeOperands">; +// Op has the same operand type or 0-d memref equivalent type. +def EquiMemRefAndEltTypeOperands +: NativeOpTrait<"EquiMemRefAndEltTypeOperands">; // Op has same shape for all operands. def SameOperandsShape : NativeOpTrait<"SameOperandsShape">; // Op has same operand and result shape. diff --git a/mlir/include/mlir/IR/OpDefinition.h b/mlir/include/mlir/IR/OpDefinition.h index e7f644f456b22..932ef0542781e 100644 --- a/mlir/include/mlir/IR/OpDefinition.h +++ b/mlir/include/mlir/IR/OpDefinition.h @@ -248,6 +248,7 @@ LogicalResult verifyAtLeastNOperands(Operation *op, unsigned numOperands); LogicalResult verifyOperandsAreFloatLike(Operation *op); LogicalResult verifyOperandsAreSignlessIntegerLike(Operation *op); LogicalResult verifySameTypeOperands(Operation *op); +LogicalResult verifyEquiMemRefAndEltTypeOperands(Operation *op); LogicalResult verifyZeroRegion(Operation *op); LogicalResult verifyOneRegion(Operation *op); LogicalResult verifyNRegions(Operation *op, unsigned numRegions); @@ -1143,6 +1144,18 @@ class SameTypeOperands : public TraitBase { } }; +/// This class verifies that all operands of the specified op have the same +/// type with the exception that 0-d memref type of an elemental type is treated +/// the same as that elemental type. +template +class EquiMemRefAndEltTypeOperands +: public TraitBase { +public: + static LogicalResult verifyTrait(Operation *op) { +return impl::verifyEquiMemRefAndEltTypeOperands(op); + } +}; + /// This class provides the API for a sub-set of ops that are known to be /// constant-like. These are non-side effecting operations with one result and /// zero operands that can always be folded to a specific attribute value. diff --git a/mlir/lib/IR/Operation.cpp b/mlir/lib/IR/Operation.cpp index 457c993b92ad3..657b612ccce16 100644 --- a/mlir/lib/IR/Operation.cpp +++ b/mlir/lib/IR/Operation.cpp @@ -792,6 +792,32 @@ LogicalResult OpTrait::impl::verifySameTypeOperands(Operation *op) { return success(); } +LogicalResult OpTrait::impl::verifyEquiMemRefAndEltTypeOperands(Operation *op) { + // Zero or one operand always have the "same" type. + unsigned nOperands = op->getNumOperands(); + if (nOperands < 2) +return success(); + + StringRef msg = + "requires all operands to have the same or equivalent type where a 0-d " + "memref type is considered equivalent to its elemental type"; + + auto prevType = op->getOperand(0).getType(); + for (auto opType : llvm::drop_begin(op->getOperandTypes(), 1)) { +if (opType != prevType) { + if (auto opMemRefType = opType.dyn_cast()) +if (opMemRefType.getRank() != 0 || +opMemRefType.getElementType() != prevType) + return op->emitOpError(msg); + if (auto prevMemRefType = prevType.dyn_cast()) +if (prevMemRefType.getRank() != 0 && +prevMemRefType.getElementType() != opType) + return op->emitOpError(msg); +} + } + return success(); +} + LogicalResult OpTrait::impl::verifyZeroRegion(Operation *op) { if (op->getNumRegions() != 0) return op->emitOpError() << "requires zero regions"; ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] 7a34031 - [MLIR] Add verifier for LHLO get tuple element op
Author: Uday Bondhugula Date: 2021-09-23T05:52:22+05:30 New Revision: 7a34031a8fdabe5f484a537c96a7cd31999c51d5 URL: https://github.com/llvm/llvm-project/commit/7a34031a8fdabe5f484a537c96a7cd31999c51d5 DIFF: https://github.com/llvm/llvm-project/commit/7a34031a8fdabe5f484a537c96a7cd31999c51d5.diff LOG: [MLIR] Add verifier for LHLO get tuple element op The LHLO GetTupleElementOp was missing its verifier. Add the verifier. Added: mlir/test/Dialect/LHLO/invalid.mlir Modified: mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td mlir/lib/Dialect/LHLO/IR/LHLOOps.cc Removed: diff --git a/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td b/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td index 15c17ee3b85c..104e9c011de6 100644 --- a/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td +++ b/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td @@ -251,6 +251,8 @@ def LHLO_GetTupleElementOp: LHLO_Op<"get_tuple_element", []>, BASE_HLO_GetTupleE ); let results = (outs Arg); + + let verifier = [{ return ::verify(*this); }]; } def LHLO_CompareOp: LHLO_Op<"compare", []>, BASE_HLO_CompareOp { diff --git a/mlir/lib/Dialect/LHLO/IR/LHLOOps.cc b/mlir/lib/Dialect/LHLO/IR/LHLOOps.cc index 26251379be8f..01b0da948dea 100644 --- a/mlir/lib/Dialect/LHLO/IR/LHLOOps.cc +++ b/mlir/lib/Dialect/LHLO/IR/LHLOOps.cc @@ -59,11 +59,10 @@ void LHLODialect::initialize() { >(); } -#define GET_OP_CLASSES -#include "mlir/Dialect/LHLO/IR/LHLOOps.cpp.inc" - -namespace mlir { -namespace xla_lhlo { +using xla_lhlo::ConstOp; +using xla_lhlo::FusionOp; +using xla_lhlo::GetTupleElementOp; +using xla_lhlo::TupleOp; //===--===// // ConstOp. @@ -123,5 +122,30 @@ void TupleOp::build(OpBuilder& builder, OperationState& result, build(builder, result, builder.getTupleType(types), values); } -} // namespace xla_lhlo -} // namespace mlir +//===--===// +// GetTupleElementOp +//===--===// + +static LogicalResult verify(GetTupleElementOp op) { + unsigned index = op.index(); + auto operandType = op.getOperand().getType().cast(); + if (index >= operandType.size()) { +return op.emitOpError( +llvm::formatv("index {0} is out of bounds of operand with size {1}", + index, operandType.size())); + } + + Type expectedType = operandType.getType(index); + if (op.getType() != expectedType) { +return op.emitOpError(llvm::formatv("has return type {0}, but expected {1}", +op.getType(), expectedType)); + } + return success(); +} + +//===--===// +// TableGen'd op method definitions +//===--===// + +#define GET_OP_CLASSES +#include "mlir/Dialect/LHLO/IR/LHLOOps.cpp.inc" diff --git a/mlir/test/Dialect/LHLO/invalid.mlir b/mlir/test/Dialect/LHLO/invalid.mlir new file mode 100644 index ..0e269535d00c --- /dev/null +++ b/mlir/test/Dialect/LHLO/invalid.mlir @@ -0,0 +1,10 @@ +// RUN: mlir-opt %s -split-input-file -verify-diagnostics + +func @passthrough(%arg : memref<8xi32>) { + %c0_i32 = constant 0 : i32 + %tuple = "xla_lhlo.tuple"(%c0_i32, %arg) : (i32, memref<8xi32>) -> (tuple>) + %elt = "xla_lhlo.get_tuple_element"(%tuple) {index = 0 : i32} : (tuple>) -> i32 + // expected-error@+1{{'xla_lhlo.get_tuple_element' op has return type memref<8xi32>, but expected i32}} + %mem = "xla_lhlo.get_tuple_element"(%tuple) {index = 0 : i32} : (tuple>) -> memref<8xi32> + return +} ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] 071e483 - Add verifier for the LHLO TupleOp
Author: Prateek Gupta Date: 2021-09-23T05:53:52+05:30 New Revision: 071e483b072ee7ff59ec3386b6bc0155c7a230b3 URL: https://github.com/llvm/llvm-project/commit/071e483b072ee7ff59ec3386b6bc0155c7a230b3 DIFF: https://github.com/llvm/llvm-project/commit/071e483b072ee7ff59ec3386b6bc0155c7a230b3.diff LOG: Add verifier for the LHLO TupleOp Added verification support for LHLO TupleOp, so that inconsistency between input and output types for the LHLO TupleOp can be checked. Added: Modified: mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td mlir/lib/Dialect/LHLO/IR/LHLOOps.cc mlir/test/Dialect/LHLO/invalid.mlir Removed: diff --git a/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td b/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td index 104e9c011de6..752992761485 100644 --- a/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td +++ b/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td @@ -600,6 +600,8 @@ def LHLO_TupleOp : LHLO_ReadOnlyOp<"tuple", [NoSideEffect]>, BASE_HLO_TupleOp { let results = (outs NestedTupleOf<[LHLO_BufferOrIntOrFP]>); let builders = [OpBuilder<(ins "ValueRange":$values)>]; + + let verifier = [{ return::verify(*this);}]; } def LHLO_WhileOp diff --git a/mlir/lib/Dialect/LHLO/IR/LHLOOps.cc b/mlir/lib/Dialect/LHLO/IR/LHLOOps.cc index 01b0da948dea..27d2596f167e 100644 --- a/mlir/lib/Dialect/LHLO/IR/LHLOOps.cc +++ b/mlir/lib/Dialect/LHLO/IR/LHLOOps.cc @@ -122,6 +122,17 @@ void TupleOp::build(OpBuilder& builder, OperationState& result, build(builder, result, builder.getTupleType(types), values); } +static LogicalResult verify(TupleOp op) { + SmallVector operandTypes = {op.operand_type_begin(), + op.operand_type_end()}; + auto expectedType = TupleType::get(op.getContext(), operandTypes); + if (op.getType() != expectedType) { +return op.emitOpError(llvm::formatv("has return type {0}, but expected {1}", +op.getType(), expectedType)); + } + return success(); +} + //===--===// // GetTupleElementOp //===--===// diff --git a/mlir/test/Dialect/LHLO/invalid.mlir b/mlir/test/Dialect/LHLO/invalid.mlir index 0e269535d00c..98e744c0167c 100644 --- a/mlir/test/Dialect/LHLO/invalid.mlir +++ b/mlir/test/Dialect/LHLO/invalid.mlir @@ -8,3 +8,30 @@ func @passthrough(%arg : memref<8xi32>) { %mem = "xla_lhlo.get_tuple_element"(%tuple) {index = 0 : i32} : (tuple>) -> memref<8xi32> return } + +// - + +func @pass_wrong_number_of_arguments(%arg : memref<8xi32>){ +%c0 = constant 0 : i32 +%c1 = constant 1 : i32 +// expected-error@+1{{'xla_lhlo.tuple' op has return type tuple, but expected tuple, i32>}} +%tuple = "xla_lhlo.tuple"(%c0, %arg, %c1) : (i32, memref<8xi32>, i32) -> (tuple) +} + +// - + +func @pass_wrong_type(%arg : i32){ +%c = constant 0 : i32 +// expected-error@+1{{'xla_lhlo.tuple' op has return type tuple>, but expected tuple}} +%tuple = "xla_lhlo.tuple"(%c, %arg) : (i32, i32) -> (tuple>) +return +} + +// - + +func @pass_wrong_order(%arg : memref<8xi32>){ +%c = constant 0 : i32 +// expected-error@+1{{'xla_lhlo.tuple' op has return type tuple, i32>, but expected tuple>}} +%tuple = "xla_lhlo.tuple"(%c, %arg) : (i32, memref<8xi32>) -> (tuple, i32>) +return +} \ No newline at end of file ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] 87b4572 - [MLIR] [NFC] Update xla_lhlo WhileOp documentation
Author: Uday Bondhugula Date: 2021-09-23T05:33:00+05:30 New Revision: 87b4572a6b574fba930770d0c8c96455d0340809 URL: https://github.com/llvm/llvm-project/commit/87b4572a6b574fba930770d0c8c96455d0340809 DIFF: https://github.com/llvm/llvm-project/commit/87b4572a6b574fba930770d0c8c96455d0340809.diff LOG: [MLIR] [NFC] Update xla_lhlo WhileOp documentation Update xla_lhlo WhileOp documentation. NFC. Added: Modified: mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td Removed: diff --git a/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td b/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td index 7f83425f138c..15c17ee3b85c 100644 --- a/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td +++ b/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td @@ -607,7 +607,11 @@ def LHLO_WhileOp string description = [{ Returns the result of executing a body function until the cond body returns -true. +true. The `body` and `cond` regions are expected to have a single block +terminated with a `yield`. The operand (`init`), the result, the argument to +the body, the yield value from the body, and the argument to the conditional +are all a single tuple value of the same type. The yield value from the +conditional is always a boolean of type i1. See https://www.tensorflow.org/xla/operation_semantics#while. }]; ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] eff9b54 - [MLIR] Introduce IfOp in the xla_lhlo dialect
Author: Uday Bondhugula Date: 2021-09-23T05:56:13+05:30 New Revision: eff9b542c7e3cbc44faac86046461a982ac9dcdc URL: https://github.com/llvm/llvm-project/commit/eff9b542c7e3cbc44faac86046461a982ac9dcdc DIFF: https://github.com/llvm/llvm-project/commit/eff9b542c7e3cbc44faac86046461a982ac9dcdc.diff LOG: [MLIR] Introduce IfOp in the xla_lhlo dialect Introduce LHLO IfOp to model conditionals on the memref form. This is lowered form form of HLO IfOp (the latter operates on tensors). Its design is similar to that of the LHLO WhileOp, taking in tuples of memrefs or elemental types. The true and the false bodies return a tuple of the same type. Added: Modified: mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td mlir/test/Dialect/LHLO/lhlo_ops.mlir Removed: diff --git a/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td b/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td index 752992761485..711549940570 100644 --- a/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td +++ b/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td @@ -467,6 +467,53 @@ def LHLO_GatherOp: LHLO_Op<"gather", []>, BASE_HLO_GatherOp { ); } +def LHLO_IfOp : LHLO_Op<"if", [AffineScope, RecursiveSideEffects]> { + string summary = "If operator"; + + string description = [{ +Returns the result of executing either a true or false function depending on +the result of a condition function. In contrast to the HLO version, the +tuple operands for the true or false branch are a tuple of memrefs or int/fp +types. Both the true and false branches also return such a tuple type: they +both return the same type and this match the result type of the op. + +Example: + +```mlir +func @lhlo_if(%arg0: memref<1x1x10xf32>, %arg1: memref<1x1x10xf32>, %arg2: memref) { + %0 = "xla_lhlo.tuple"(%arg0, %arg1) : (memref<1x1x10xf32>, memref<1x1x10xf32>) -> tuple, memref<1x1x10xf32>> + %1 = "xla_lhlo.if"(%arg2, %0, %0) ( { +^bb0(%arg3: tuple, memref<1x1x10xf32>>): +%2 = "xla_lhlo.get_tuple_element"(%arg3) {index = 0 : i32} : (tuple, memref<1x1x10xf32>>) -> memref<1x1x10xf32> +%3 = "xla_lhlo.tuple"(%2) : (memref<1x1x10xf32>) -> tuple> +"xla_lhlo.yield"(%3) : (tuple>) -> () + }, { +^bb0(%arg3: tuple, memref<1x1x10xf32>>): // no predecessors +%2 = "xla_lhlo.get_tuple_element"(%arg3) {index = 1 : i32} : (tuple, memref<1x1x10xf32>>) -> memref<1x1x10xf32> +%3 = "xla_lhlo.tuple"(%2) : (memref<1x1x10xf32>) -> tuple> +"xla_lhlo.yield"(%3) : (tuple>) -> () + }) : (memref, tuple, memref<1x1x10xf32>>, tuple, memref<1x1x10xf32>>) -> tuple> + "xla_lhlo.terminator"() : () -> () +} +``` + +See https://www.tensorflow.org/xla/operation_semantics#conditional. + }]; + + let arguments = (ins Arg : $init); + + let arguments = (ins +LHLO_PredBufferOrI1:$pred, +LHLO_TupleOfBufferOrIntOrFP:$true_arg, +LHLO_TupleOfBufferOrIntOrFP:$false_arg + ); + + let regions = (region AnyRegion:$true_branch, +AnyRegion:$false_branch); + + let results = (outs Arg); +} + def LHLO_MapOp : LHLO_Op<"map", [RecursiveSideEffects, SameOperandsShape]>, BASE_HLO_MapOp { let description = [{ diff --git a/mlir/test/Dialect/LHLO/lhlo_ops.mlir b/mlir/test/Dialect/LHLO/lhlo_ops.mlir index 30a84c5b4bcb..59ccfc8113be 100644 --- a/mlir/test/Dialect/LHLO/lhlo_ops.mlir +++ b/mlir/test/Dialect/LHLO/lhlo_ops.mlir @@ -235,3 +235,40 @@ func @while_op(%arg0: memref<4x?x16xf32>, %arg1: memref<4x?x16xf32>) { }) : (tuple>) -> tuple> "xla_lhlo.terminator"() : () -> () } + +// - + +func @lhlo_if(%arg0: memref<1x1x10xf32>, %arg1: memref<1x1x10xf32>, %arg2: memref) { + %0 = "xla_lhlo.tuple"(%arg0, %arg1) : (memref<1x1x10xf32>, memref<1x1x10xf32>) -> tuple, memref<1x1x10xf32>> + // CHECK: xla_lhlo.if + %1 = "xla_lhlo.if"(%arg2, %0, %0) ( { +^bb0(%arg3: tuple, memref<1x1x10xf32>>): +%2 = "xla_lhlo.get_tuple_element"(%arg3) {index = 0 : i32} : (tuple, memref<1x1x10xf32>>) -> memref<1x1x10xf32> +%3 = "xla_lhlo.tuple"(%2) : (memref<1x1x10xf32>) -> tuple> +"xla_lhlo.yield"(%3) : (tuple>) -> () + }, { +^bb0(%arg3: tuple, memref<1x1x10xf32>>): // no predecessors +%2 = "xla_lhlo.get_tuple_element"(%arg3) {index = 1 : i32} : (tuple, memref<1x1x10xf32>>) -> memref<1x1x10xf32> +%3 = "xla_lhlo.tuple"(%2) : (memref<1x1x10xf32>) -> tuple> +"xla_lhlo.yield"(%3) : (tuple>) -> () + }) : (memref, tuple, memref<1x1x10xf32>>, tuple, memref<1x1x10xf32>>) -> tuple> + "xla_lhlo.terminator"() : () -> () +} + +// CHECK-LABEL: func @lhlo_if_empty_arg +func @lhlo_if_empty_arg(%arg0: memref) { + %cst = constant 1.00e+00 : f32 + %cst_0 = constant 0.00e+00 : f32 + %0 = "xla_lhlo.tuple"() : () -> tuple<> + // CHECK: xla_lhlo.if + %1 = "xla_lhlo.if"(%arg0, %0, %0) ( { +^bb0(%arg1: tuple<>): +%2
[llvm-branch-commits] [mlir] 51de919 - Rename xla_lhlo dialect and namespace -> lmhlo
Author: Uday Bondhugula Date: 2021-09-23T06:12:54+05:30 New Revision: 51de91957abebee3c6fdf870f1388b266ea011b1 URL: https://github.com/llvm/llvm-project/commit/51de91957abebee3c6fdf870f1388b266ea011b1 DIFF: https://github.com/llvm/llvm-project/commit/51de91957abebee3c6fdf870f1388b266ea011b1.diff LOG: Rename xla_lhlo dialect and namespace -> lmhlo This change of name is being done to avoid a clash in the python binding with the xla_lhlo in Monolith's TensorFlow. While xla_lhlo was moved to MLIR proper in our branches, Monolith's TensorFlow still has it and its methods would get called instead of those in MLIR linked in by Monolith. Added: Modified: mlir/include/mlir/Dialect/LHLO/IR/CMakeLists.txt mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.h mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td mlir/include/mlir/InitAllDialects.h mlir/lib/Dialect/LHLO/IR/LHLOOps.cc mlir/test/Dialect/LHLO/invalid.mlir mlir/test/Dialect/LHLO/lhlo_ops.mlir mlir/test/mlir-opt/commandline.mlir Removed: diff --git a/mlir/include/mlir/Dialect/LHLO/IR/CMakeLists.txt b/mlir/include/mlir/Dialect/LHLO/IR/CMakeLists.txt index f5c4548ccf534..b852d42171bd7 100644 --- a/mlir/include/mlir/Dialect/LHLO/IR/CMakeLists.txt +++ b/mlir/include/mlir/Dialect/LHLO/IR/CMakeLists.txt @@ -1,4 +1,4 @@ -add_mlir_dialect(LHLOOps xla_lhlo) +add_mlir_dialect(LHLOOps lmhlo) set(LLVM_TARGET_DEFINITIONS LHLOOps.td) mlir_tablegen(LHLOStructs.h.inc -gen-struct-attr-decls) diff --git a/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.h b/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.h index c17ee6d63bd40..94a9de69cfd27 100644 --- a/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.h +++ b/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.h @@ -40,5 +40,4 @@ class OpBuilder; #define GET_OP_CLASSES #include "mlir/Dialect/LHLO/IR/LHLOOps.h.inc" - #endif // MLIR_DIALECT_LHLO_IR_LHLO_OPS_H_ diff --git a/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td b/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td index 711549940570c..0ee24446cad8b 100644 --- a/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td +++ b/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td @@ -23,8 +23,8 @@ include "mlir/Interfaces/SideEffectInterfaces.td" include "mlir/Dialect/LHLO/IR/HLOOpsBase.td" def LHLO_Dialect : Dialect { - let name = "xla_lhlo"; - let cppNamespace = "::mlir::xla_lhlo"; + let name = "lmhlo"; + let cppNamespace = "::mlir::lmhlo"; } //===--===// @@ -481,19 +481,19 @@ def LHLO_IfOp : LHLO_Op<"if", [AffineScope, RecursiveSideEffects]> { ```mlir func @lhlo_if(%arg0: memref<1x1x10xf32>, %arg1: memref<1x1x10xf32>, %arg2: memref) { - %0 = "xla_lhlo.tuple"(%arg0, %arg1) : (memref<1x1x10xf32>, memref<1x1x10xf32>) -> tuple, memref<1x1x10xf32>> - %1 = "xla_lhlo.if"(%arg2, %0, %0) ( { + %0 = "lmhlo.tuple"(%arg0, %arg1) : (memref<1x1x10xf32>, memref<1x1x10xf32>) -> tuple, memref<1x1x10xf32>> + %1 = "lmhlo.if"(%arg2, %0, %0) ( { ^bb0(%arg3: tuple, memref<1x1x10xf32>>): -%2 = "xla_lhlo.get_tuple_element"(%arg3) {index = 0 : i32} : (tuple, memref<1x1x10xf32>>) -> memref<1x1x10xf32> -%3 = "xla_lhlo.tuple"(%2) : (memref<1x1x10xf32>) -> tuple> -"xla_lhlo.yield"(%3) : (tuple>) -> () +%2 = "lmhlo.get_tuple_element"(%arg3) {index = 0 : i32} : (tuple, memref<1x1x10xf32>>) -> memref<1x1x10xf32> +%3 = "lmhlo.tuple"(%2) : (memref<1x1x10xf32>) -> tuple> +"lmhlo.yield"(%3) : (tuple>) -> () }, { ^bb0(%arg3: tuple, memref<1x1x10xf32>>): // no predecessors -%2 = "xla_lhlo.get_tuple_element"(%arg3) {index = 1 : i32} : (tuple, memref<1x1x10xf32>>) -> memref<1x1x10xf32> -%3 = "xla_lhlo.tuple"(%2) : (memref<1x1x10xf32>) -> tuple> -"xla_lhlo.yield"(%3) : (tuple>) -> () +%2 = "lmhlo.get_tuple_element"(%arg3) {index = 1 : i32} : (tuple, memref<1x1x10xf32>>) -> memref<1x1x10xf32> +%3 = "lmhlo.tuple"(%2) : (memref<1x1x10xf32>) -> tuple> +"lmhlo.yield"(%3) : (tuple>) -> () }) : (memref, tuple, memref<1x1x10xf32>>, tuple, memref<1x1x10xf32>>) -> tuple> - "xla_lhlo.terminator"() : () -> () + "lmhlo.terminator"() : () -> () } ``` diff --git a/mlir/include/mlir/InitAllDialects.h b/mlir/include/mlir/InitAllDialects.h index e9869365e54eb..43712b70d5362 100644 --- a/mlir/include/mlir/InitAllDialects.h +++ b/mlir/include/mlir/InitAllDialects.h @@ -80,7 +80,7 @@ inline void registerAllDialects(DialectRegistry ®istry) { tensor::TensorDialect, tosa::TosaDialect, x86vector::X86VectorDialect, - xla_lhlo::LHLODialect>(); + lmhlo::LHLODialect>(); // clang-format on } diff --git a/mlir/lib/Dialect/LHLO/IR/LHLOOps.cc b/mlir/lib/Dialect/LHLO/IR/LHLOOps.cc index 27d259
[llvm-branch-commits] [mlir] c6b7f22 - [MLIR] Add xla_lhlo dialect from tensorflow
Author: Uday Bondhugula Date: 2021-09-22T14:23:46+05:30 New Revision: c6b7f22240229f69af9ebb75d4b7a9b5f1dd0da1 URL: https://github.com/llvm/llvm-project/commit/c6b7f22240229f69af9ebb75d4b7a9b5f1dd0da1 DIFF: https://github.com/llvm/llvm-project/commit/c6b7f22240229f69af9ebb75d4b7a9b5f1dd0da1.diff LOG: [MLIR] Add xla_lhlo dialect from tensorflow Add xla_lhlo dialect from tensorflow (the version used by the right branch of the private repo). This commit brings in just the LHLO ops part of it. So, LHLO transforms or any conversions out of LHLO are not included. This is to mainly to allow the use of xla_lhlo dialect ops along with MLIR. So, the users would be aware of LHLO ops (make use of its accessors) as the xla_lhlo dialect would be registered. This is a temporary arrangement before we can migrate to depending on mlir-hlo. Depending on tensorflow just for xla_lhlo isn't really feasible. Added: mlir/include/mlir/Dialect/LHLO/CMakeLists.txt mlir/include/mlir/Dialect/LHLO/IR/CMakeLists.txt mlir/include/mlir/Dialect/LHLO/IR/HLOOpsBase.td mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.h mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td mlir/lib/Dialect/LHLO/CMakeLists.txt mlir/lib/Dialect/LHLO/IR/CMakeLists.txt mlir/lib/Dialect/LHLO/IR/LHLOOps.cc mlir/test/Dialect/LHLO/lhlo_ops.mlir Modified: mlir/include/mlir/Dialect/CMakeLists.txt mlir/include/mlir/InitAllDialects.h mlir/lib/Dialect/CMakeLists.txt Removed: diff --git a/mlir/include/mlir/Dialect/CMakeLists.txt b/mlir/include/mlir/Dialect/CMakeLists.txt index 44a9249cef839..60e31ed7cac55 100644 --- a/mlir/include/mlir/Dialect/CMakeLists.txt +++ b/mlir/include/mlir/Dialect/CMakeLists.txt @@ -9,6 +9,7 @@ add_subdirectory(EmitC) add_subdirectory(GPU) add_subdirectory(Math) add_subdirectory(Linalg) +add_subdirectory(LHLO) add_subdirectory(LLVMIR) add_subdirectory(MemRef) add_subdirectory(OpenACC) diff --git a/mlir/include/mlir/Dialect/LHLO/CMakeLists.txt b/mlir/include/mlir/Dialect/LHLO/CMakeLists.txt new file mode 100644 index 0..f33061b2d87cf --- /dev/null +++ b/mlir/include/mlir/Dialect/LHLO/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(IR) diff --git a/mlir/include/mlir/Dialect/LHLO/IR/CMakeLists.txt b/mlir/include/mlir/Dialect/LHLO/IR/CMakeLists.txt new file mode 100644 index 0..f5c4548ccf534 --- /dev/null +++ b/mlir/include/mlir/Dialect/LHLO/IR/CMakeLists.txt @@ -0,0 +1,8 @@ +add_mlir_dialect(LHLOOps xla_lhlo) + +set(LLVM_TARGET_DEFINITIONS LHLOOps.td) +mlir_tablegen(LHLOStructs.h.inc -gen-struct-attr-decls) +mlir_tablegen(LHLOStructs.cpp.inc -gen-struct-attr-defs) +add_public_tablegen_target(MLIRLHLOStructsGen) + +add_mlir_doc(LHLOOps -gen-op-doc LHLOOps Dialects/) diff --git a/mlir/include/mlir/Dialect/LHLO/IR/HLOOpsBase.td b/mlir/include/mlir/Dialect/LHLO/IR/HLOOpsBase.td new file mode 100644 index 0..9312ed9e96f9f --- /dev/null +++ b/mlir/include/mlir/Dialect/LHLO/IR/HLOOpsBase.td @@ -0,0 +1,1260 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==*/ + +#ifndef HLO_OPS_BASE +#define HLO_OPS_BASE + +include "mlir/IR/OpBase.td" + +def HLO_Pred : TypeAlias; + +// TODO(hinsu): Use signed integers instead of signless integer which is being +// used for legacy reasons. +def HLO_SInt : SignlessIntOfWidths<[8, 16, 32, 64]>; +def HLO_UInt : UnsignedIntOfWidths<[8, 16, 32, 64]>; +def HLO_Int : AnyTypeOf<[HLO_SInt, HLO_UInt]>; +def HLO_I1 : SignlessIntOfWidths<[1]>; + +def HLO_Complex : Complex>; + +// The broadcasting dimensions correspond to a tuple that describes how a +// smaller rank shape is broadcast into a larger rank shape. For example, +// given a 2x3x4 cuboid and a 3x4 matrix, a broadcasting tuple (1,2) means +// matching the matrix to dimensions 1 and 2 of the cuboid. +defvar BroadcastDimAttr = I64ElementsAttr; + +//===--===// +// XLA on tensors type definitions. +//===--===// + +// Token type. +def HLO_Token : Type()">, "token">; + +// Any integer tensor types +def HLO_IntTensor : TensorOf<[HLO_Int]>; + +// Any integer tensor type with rank 0 (i.e. representing a single integer). +def HLO_ScalarIntTensor : Shaped
[llvm-branch-commits] [mlir] db04767 - [MLIR] Add the seed attribute for random_uniform ops in lmhlo dialect. (#35)
Author: Prashant Kumar Date: 2021-09-23T06:20:43+05:30 New Revision: db04767afbea48b62a7a25017e42248a5d83480c URL: https://github.com/llvm/llvm-project/commit/db04767afbea48b62a7a25017e42248a5d83480c DIFF: https://github.com/llvm/llvm-project/commit/db04767afbea48b62a7a25017e42248a5d83480c.diff LOG: [MLIR] Add the seed attribute for random_uniform ops in lmhlo dialect. (#35) The `seed` and `seed2` attribute are added to lmhlo dialect in case of random_uniform ops. The changes are made as a part of hlo-legalize-to-lhlo` pass. Added: Modified: mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td Removed: diff --git a/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td b/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td index 0ee24446cad8..16fff82d6c7a 100644 --- a/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td +++ b/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td @@ -568,10 +568,17 @@ def LHLO_ReshapeOp: LHLO_Op<"reshape", []>, BASE_HLO_ReshapeOp { // output memref consistent with HLO op xla_hlo::rng_uniform. //===--===// def LHLO_RngUniformOp : LHLO_Op<"rng_uniform", []>, BASE_HLO_RngUniformOp { + let summary = [{ + The generated values follow a uniform distribution in the range [minval, maxval]. + Operations that rely on a random seed actually derive it from two seeds: + the global and operation-level seeds which are `seed` and `seed2` respectively. + }]; let arguments = (ins AnyTypeOf<[AnyInteger, AnyFloat]>:$a, AnyTypeOf<[AnyInteger, AnyFloat]>:$b, -Arg:$output +Arg:$output, +OptionalAttr:$seed, +OptionalAttr:$seed2 ); } ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] 10cf6d4 - [MLIR] Add RngNormalOp in LHLO dialect (#60)
Author: Abhishek Varma Date: 2021-09-23T06:20:44+05:30 New Revision: 10cf6d43c473449402675de0d06650464f01bc9f URL: https://github.com/llvm/llvm-project/commit/10cf6d43c473449402675de0d06650464f01bc9f DIFF: https://github.com/llvm/llvm-project/commit/10cf6d43c473449402675de0d06650464f01bc9f.diff LOG: [MLIR] Add RngNormalOp in LHLO dialect (#60) -- This commit introduces RngNormalOp as part of LHLO dialect. Signed-off-by: Abhishek Varma Added: Modified: mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td Removed: diff --git a/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td b/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td index 16fff82d6c7a..394f6c6679a8 100644 --- a/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td +++ b/mlir/include/mlir/Dialect/LHLO/IR/LHLOOps.td @@ -582,6 +582,26 @@ def LHLO_RngUniformOp : LHLO_Op<"rng_uniform", []>, BASE_HLO_RngUniformOp { ); } +//===--===// +// RngNormal operator that takes scalar low and high values and populates the +// output memref consistent with HLO op xla_hlo::rng_normal. +//===--===// +def LHLO_RngNormalOp : LHLO_Op<"rng_normal", []>, BASE_HLO_RngNormalOp { + let summary = [{ + The generated values follow a standard normal distribution in the range + [minval, maxval]. Operations that rely on a random seed actually derive it + from two seeds: the global and operation-level seeds which are `seed` and + `seed2` respectively. + }]; + let arguments = (ins +AnyTypeOf<[AnyInteger, AnyFloat]>:$a, +AnyTypeOf<[AnyInteger, AnyFloat]>:$b, +Arg:$output, +OptionalAttr:$seed, +OptionalAttr:$seed2 + ); +} + def LHLO_SelectOp: LHLO_Op<"select", []>, BASE_HLO_SelectOp { let arguments = (ins Arg:$pred, ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] 81fe64d - [MLIR] Add AffineMap::isPureAffine
Author: Uday Bondhugula Date: 2021-09-23T08:19:19+05:30 New Revision: 81fe64da18fa4d4c9252b2ddd646f6623e1d1704 URL: https://github.com/llvm/llvm-project/commit/81fe64da18fa4d4c9252b2ddd646f6623e1d1704 DIFF: https://github.com/llvm/llvm-project/commit/81fe64da18fa4d4c9252b2ddd646f6623e1d1704.diff LOG: [MLIR] Add AffineMap::isPureAffine Signed-off-by: Uday Bondhugula Added: Modified: mlir/include/mlir/IR/AffineMap.h mlir/lib/IR/AffineMap.cpp Removed: diff --git a/mlir/include/mlir/IR/AffineMap.h b/mlir/include/mlir/IR/AffineMap.h index 906c53db4b32..f1f00acd8022 100644 --- a/mlir/include/mlir/IR/AffineMap.h +++ b/mlir/include/mlir/IR/AffineMap.h @@ -81,6 +81,11 @@ class AffineMap { static AffineMap getPermutationMap(ArrayRef permutation, MLIRContext *context); + /// Returns true if all of this map's result expressions are pure affine, + /// i.e., multiplication, floordiv, ceildiv, and mod is only allowed w.r.t + /// constants. + bool isPureAffine() const; + /// Returns a vector of AffineMaps; each with as many results as /// `exprs.size()`, as many dims as the largest dim in `exprs` and as many /// symbols as the largest symbol in `exprs`. diff --git a/mlir/lib/IR/AffineMap.cpp b/mlir/lib/IR/AffineMap.cpp index 9c6f25d3c53e..0989d821655d 100644 --- a/mlir/lib/IR/AffineMap.cpp +++ b/mlir/lib/IR/AffineMap.cpp @@ -344,6 +344,12 @@ unsigned AffineMap::getPermutedPosition(unsigned input) const { llvm_unreachable("incorrect permutation request"); } +bool AffineMap::isPureAffine() const { + return llvm::all_of(getResults(), [](AffineExpr expr) { +return expr.isPureAffine(); + }); +} + /// Folds the results of the application of an affine map on the provided /// operands to a constant if possible. Returns false if the folding happens, /// true otherwise. ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] eb1aacd - [MLIR-LAIR] Custom printing for multi-dim affine index maps
Author: Uday Bondhugula Date: 2021-09-23T08:19:53+05:30 New Revision: eb1aacd495d84384e2d2e4e40c893aebfbd19837 URL: https://github.com/llvm/llvm-project/commit/eb1aacd495d84384e2d2e4e40c893aebfbd19837 DIFF: https://github.com/llvm/llvm-project/commit/eb1aacd495d84384e2d2e4e40c893aebfbd19837.diff LOG: [MLIR-LAIR] Custom printing for multi-dim affine index maps Custom printing for AffineMaps with named SSA values - to aid printing NGDL accesses. Added: Modified: mlir/include/mlir/IR/AffineMap.h mlir/lib/IR/AsmPrinter.cpp Removed: diff --git a/mlir/include/mlir/IR/AffineMap.h b/mlir/include/mlir/IR/AffineMap.h index f1f00acd8022..4ab75ad3ea64 100644 --- a/mlir/include/mlir/IR/AffineMap.h +++ b/mlir/include/mlir/IR/AffineMap.h @@ -534,6 +534,11 @@ inline raw_ostream &operator<<(raw_ostream &os, AffineMap map) { map.print(os); return os; } + +/// Prints an affine map index in the form [expr_1][expr_2] with the supplied +/// names used for the inputs. +void printAffineMapAccess(AffineMap map, ArrayRef names, + raw_ostream &os); } // end namespace mlir namespace llvm { diff --git a/mlir/lib/IR/AsmPrinter.cpp b/mlir/lib/IR/AsmPrinter.cpp index b6d072f9f60a..9c717eef111c 100644 --- a/mlir/lib/IR/AsmPrinter.cpp +++ b/mlir/lib/IR/AsmPrinter.cpp @@ -2241,6 +2241,18 @@ void ModulePrinter::printAffineConstraint(AffineExpr expr, bool isEq) { isEq ? os << " == 0" : os << " >= 0"; } +void mlir::printAffineMapAccess(AffineMap map, ArrayRef names, +raw_ostream &os) { + assert(map.getNumInputs() == names.size() && "too few/many names"); + ModulePrinter p(os); + auto printValueName = [&](unsigned pos, bool isSymbol) { os << names[pos]; }; + for (auto expr : map.getResults()) { +os << '['; +p.printAffineExpr(expr, printValueName); +os << ']'; + } +} + void ModulePrinter::printAffineMap(AffineMap map) { // Dimension identifiers. os << '('; ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] 5a72ea0 - [MLIR] Add method mlir::isPerfectNestRoot
Author: Uday Bondhugula Date: 2021-09-23T08:20:06+05:30 New Revision: 5a72ea079cde160b044ec7241928bb9520a5ae75 URL: https://github.com/llvm/llvm-project/commit/5a72ea079cde160b044ec7241928bb9520a5ae75 DIFF: https://github.com/llvm/llvm-project/commit/5a72ea079cde160b044ec7241928bb9520a5ae75.diff LOG: [MLIR] Add method mlir::isPerfectNestRoot Add method to check if an affine.for op is the root of a nest that is nested perfectly all the way. Added: Modified: mlir/include/mlir/Transforms/LoopUtils.h mlir/lib/Transforms/Utils/LoopUtils.cpp Removed: diff --git a/mlir/include/mlir/Transforms/LoopUtils.h b/mlir/include/mlir/Transforms/LoopUtils.h index 8c851215e3c08..fe89a86c4d2e8 100644 --- a/mlir/include/mlir/Transforms/LoopUtils.h +++ b/mlir/include/mlir/Transforms/LoopUtils.h @@ -57,6 +57,9 @@ LogicalResult loopUnrollUpToFactor(AffineForOp forOp, uint64_t unrollFactor); /// in it from outermost to innermost. bool LLVM_ATTRIBUTE_UNUSED isPerfectlyNested(ArrayRef loops); +/// Returns true if the nest rooted at `loop` is a perfectly nested loop nest. +bool isPerfectNestRoot(AffineForOp loop); + /// Get perfectly nested sequence of loops starting at root of loop nest /// (the first op being another AffineFor, and the second op - a terminator). /// A loop is perfectly nested iff: the first op in the loop's body is another diff --git a/mlir/lib/Transforms/Utils/LoopUtils.cpp b/mlir/lib/Transforms/Utils/LoopUtils.cpp index 4427001be2204..41a6aa692ee7c 100644 --- a/mlir/lib/Transforms/Utils/LoopUtils.cpp +++ b/mlir/lib/Transforms/Utils/LoopUtils.cpp @@ -1543,6 +1543,24 @@ mlir::isPerfectlyNested(ArrayRef loops) { return true; } +/// Returns true if no other affine for op's are nested within `forOp`. +static bool isInnermostAffineForOp(AffineForOp forOp) { + // Only for the innermost affine.for op's. + bool isInnermost = true; + forOp.walk([&](AffineForOp thisForOp) { +isInnermost = (thisForOp == forOp); +return WalkResult::interrupt(); + }); + return isInnermost; +} + +/// Returns true if the nest rooted at `loop` is a perfectly nested loop nest. +bool mlir::isPerfectNestRoot(AffineForOp loop) { + SmallVector nest; + getPerfectlyNestedLoops(nest, loop); + return isInnermostAffineForOp(nest.back()); +} + // input[i] should move from position i -> permMap[i]. Returns the position in // `input` that becomes the new outermost loop. unsigned mlir::permuteLoops(MutableArrayRef input, ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] 3e07b0b - [MLIR] Fix lowering of affine operations with return values
Author: Prateek Gupta Date: 2020-12-22T21:44:31+05:30 New Revision: 3e07b0b9d3363fb767cbbaa2593fa91ac393fb7e URL: https://github.com/llvm/llvm-project/commit/3e07b0b9d3363fb767cbbaa2593fa91ac393fb7e DIFF: https://github.com/llvm/llvm-project/commit/3e07b0b9d3363fb767cbbaa2593fa91ac393fb7e.diff LOG: [MLIR] Fix lowering of affine operations with return values This commit addresses the issue of lowering affine.for and affine.parallel having return values. Relevant test cases are also added. Signed-off-by: Prateek Gupta Differential Revision: https://reviews.llvm.org/D93090 Added: Modified: mlir/lib/Conversion/AffineToStandard/AffineToStandard.cpp mlir/test/Conversion/AffineToStandard/lower-affine.mlir Removed: diff --git a/mlir/lib/Conversion/AffineToStandard/AffineToStandard.cpp b/mlir/lib/Conversion/AffineToStandard/AffineToStandard.cpp index 58f44b6ed207..8721e6b96ed7 100644 --- a/mlir/lib/Conversion/AffineToStandard/AffineToStandard.cpp +++ b/mlir/lib/Conversion/AffineToStandard/AffineToStandard.cpp @@ -334,7 +334,13 @@ class AffineYieldOpLowering : public OpRewritePattern { LogicalResult matchAndRewrite(AffineYieldOp op, PatternRewriter &rewriter) const override { -rewriter.replaceOpWithNewOp(op); +if (isa(op.getParentOp())) { + // scf.parallel does not yield any values via its terminator scf.yield but + // models reductions diff erently using additional ops in its region. + rewriter.replaceOpWithNewOp(op); + return success(); +} +rewriter.replaceOpWithNewOp(op, op.operands()); return success(); } }; @@ -349,14 +355,55 @@ class AffineForLowering : public OpRewritePattern { Value lowerBound = lowerAffineLowerBound(op, rewriter); Value upperBound = lowerAffineUpperBound(op, rewriter); Value step = rewriter.create(loc, op.getStep()); -auto f = rewriter.create(loc, lowerBound, upperBound, step); -rewriter.eraseBlock(f.getBody()); -rewriter.inlineRegionBefore(op.region(), f.region(), f.region().end()); -rewriter.eraseOp(op); +auto scfForOp = rewriter.create(loc, lowerBound, upperBound, +step, op.getIterOperands()); +rewriter.eraseBlock(scfForOp.getBody()); +rewriter.inlineRegionBefore(op.region(), scfForOp.region(), +scfForOp.region().end()); +rewriter.replaceOp(op, scfForOp.results()); return success(); } }; +/// Returns the identity value associated with an AtomicRMWKind op. +static Value getIdentityValue(AtomicRMWKind op, OpBuilder &builder, + Location loc) { + switch (op) { + case AtomicRMWKind::addf: +return builder.create(loc, builder.getF32FloatAttr(0)); + case AtomicRMWKind::addi: +return builder.create(loc, builder.getI32IntegerAttr(0)); + case AtomicRMWKind::mulf: +return builder.create(loc, builder.getF32FloatAttr(1)); + case AtomicRMWKind::muli: +return builder.create(loc, builder.getI32IntegerAttr(1)); + // TODO: Add remaining reduction operations. + default: +emitOptionalError(loc, "Reduction operation type not supported"); + } + return nullptr; +} + +/// Return the value obtained by applying the reduction operation kind +/// associated with a binary AtomicRMWKind op to `lhs` and `rhs`. +static Value getReductionOp(AtomicRMWKind op, OpBuilder &builder, Location loc, +Value lhs, Value rhs) { + switch (op) { + case AtomicRMWKind::addf: +return builder.create(loc, lhs, rhs); + case AtomicRMWKind::addi: +return builder.create(loc, lhs, rhs); + case AtomicRMWKind::mulf: +return builder.create(loc, lhs, rhs); + case AtomicRMWKind::muli: +return builder.create(loc, lhs, rhs); + // TODO: Add remaining reduction operations. + default: +emitOptionalError(loc, "Reduction operation type not supported"); + } + return nullptr; +} + /// Convert an `affine.parallel` (loop nest) operation into a `scf.parallel` /// operation. class AffineParallelLowering : public OpRewritePattern { @@ -369,12 +416,13 @@ class AffineParallelLowering : public OpRewritePattern { SmallVector steps; SmallVector upperBoundTuple; SmallVector lowerBoundTuple; +SmallVector identityVals; // Finding lower and upper bound by expanding the map expression. // Checking if expandAffineMap is not giving NULL. -Optional> upperBound = expandAffineMap( -rewriter, loc, op.upperBoundsMap(), op.getUpperBoundsOperands()); Optional> lowerBound = expandAffineMap( rewriter, loc, op.lowerBoundsMap(), op.getLowerBoundsOperands()); +Optional> upperBound = expandAffineMap( +rewriter, loc, op.upperBoundsMap(), op.getUpperBoundsOperands()); if (!lowerBound || !upperBound) return failure(); upperBoundTuple = *upperBound; @@ -38
[llvm-branch-commits] [mlir] 3bcca6b - [MLIR] Fix affine_map compose with multi-symbols
Author: Chengji Yao Date: 2021-01-02T06:57:16+05:30 New Revision: 3bcca6b12d4cbe9d4571e799899e9b956e4711bf URL: https://github.com/llvm/llvm-project/commit/3bcca6b12d4cbe9d4571e799899e9b956e4711bf DIFF: https://github.com/llvm/llvm-project/commit/3bcca6b12d4cbe9d4571e799899e9b956e4711bf.diff LOG: [MLIR] Fix affine_map compose with multi-symbols Fix bug: https://bugs.llvm.org/show_bug.cgi?id=46845 Differential Revision: https://reviews.llvm.org/D93831 Added: Modified: mlir/lib/IR/AffineMap.cpp mlir/test/Dialect/Affine/canonicalize.mlir Removed: diff --git a/mlir/lib/IR/AffineMap.cpp b/mlir/lib/IR/AffineMap.cpp index 634917fe0faf..b51636091aad 100644 --- a/mlir/lib/IR/AffineMap.cpp +++ b/mlir/lib/IR/AffineMap.cpp @@ -319,7 +319,7 @@ AffineMap AffineMap::compose(AffineMap map) { for (unsigned idx = 0; idx < numDims; ++idx) { newDims[idx] = getAffineDimExpr(idx, getContext()); } - SmallVector newSymbols(numSymbols); + SmallVector newSymbols(numSymbols - numSymbolsThisMap); for (unsigned idx = numSymbolsThisMap; idx < numSymbols; ++idx) { newSymbols[idx - numSymbolsThisMap] = getAffineSymbolExpr(idx, getContext()); diff --git a/mlir/test/Dialect/Affine/canonicalize.mlir b/mlir/test/Dialect/Affine/canonicalize.mlir index 0e452b0c6338..b185e1c8b707 100644 --- a/mlir/test/Dialect/Affine/canonicalize.mlir +++ b/mlir/test/Dialect/Affine/canonicalize.mlir @@ -24,6 +24,9 @@ // CHECK-DAG: [[$MAP13A:#map[0-9]+]] = affine_map<(d0) -> ((d0 + 6) ceildiv 8)> // CHECK-DAG: [[$MAP13B:#map[0-9]+]] = affine_map<(d0) -> ((d0 * 4 - 4) floordiv 3)> +// Affine maps for test case: compose_affine_maps_multiple_symbols +// CHECK-DAG: [[$MAP14:#map[0-9]+]] = affine_map<()[s0, s1] -> (((s1 + s0) * 4) floordiv s0)> + // Affine maps for test case: partial_fold_map // CHECK-DAG: [[$MAP15:#map[0-9]+]] = affine_map<()[s0] -> (s0 - 42)> @@ -218,6 +221,15 @@ func @compose_affine_maps_diamond_dependency(%arg0: f32, %arg1: memref<4x4xf32>) return } +// CHECK-LABEL: func @compose_affine_maps_multiple_symbols +func @compose_affine_maps_multiple_symbols(%arg0: index, %arg1: index) -> index { + %a = affine.apply affine_map<(d0)[s0] -> (s0 + d0)> (%arg0)[%arg1] + %c = affine.apply affine_map<(d0) -> (d0 * 4)> (%a) + %e = affine.apply affine_map<(d0)[s0] -> (d0 floordiv s0)> (%c)[%arg1] + // CHECK: [[I0:%[0-9]+]] = affine.apply [[$MAP14]]()[%{{.*}}, %{{.*}}] + return %e : index +} + // CHECK-LABEL: func @arg_used_as_dim_and_symbol func @arg_used_as_dim_and_symbol(%arg0: memref<100x100xf32>, %arg1: index, %arg2: f32) { %c9 = constant 9 : index ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] b276bf5 - [MLIR][NFC] Fix mix up between dialect attribute values and names
Author: Uday Bondhugula Date: 2020-12-03T02:34:15+05:30 New Revision: b276bf5a572b64a02bd4b067125d4f2c9cf6fb6b URL: https://github.com/llvm/llvm-project/commit/b276bf5a572b64a02bd4b067125d4f2c9cf6fb6b DIFF: https://github.com/llvm/llvm-project/commit/b276bf5a572b64a02bd4b067125d4f2c9cf6fb6b.diff LOG: [MLIR][NFC] Fix mix up between dialect attribute values and names Clear up documentation on dialect attribute values. Fix/improve ModuleOp verifier error message on dialect prefixed attribute names. Additional discussion is here: https://llvm.discourse.group/t/moduleop-attributes/2325 Differential Revision: https://reviews.llvm.org/D92502 Added: Modified: mlir/docs/LangRef.md mlir/lib/IR/BuiltinDialect.cpp mlir/test/IR/invalid-module-op.mlir Removed: diff --git a/mlir/docs/LangRef.md b/mlir/docs/LangRef.md index 82272d1b729f..fd78d51afd6d 100644 --- a/mlir/docs/LangRef.md +++ b/mlir/docs/LangRef.md @@ -1369,39 +1369,39 @@ Example: Similarly to operations, dialects may define custom attribute values. The syntactic structure of these values is identical to custom dialect type values, -except that dialect attributes values are distinguished with a leading '#', -while dialect types are distinguished with a leading '!'. +except that dialect attribute values are distinguished with a leading '#', while +dialect types are distinguished with a leading '!'. ``` -dialect-attribute ::= '#' opaque-dialect-item -dialect-attribute ::= '#' pretty-dialect-item +dialect-attribute-value ::= '#' opaque-dialect-item +dialect-attribute-value ::= '#' pretty-dialect-item ``` -Dialect attributes can be specified in a verbose form, e.g. like this: +Dialect attribute values can be specified in a verbose form, e.g. like this: ```mlir -// Complex attribute +// Complex attribute value. #foo<"something"> -// Even more complex attribute +// Even more complex attribute value. #foo<"something>>"> ``` -Dialect attributes that are simple enough can use the pretty format, which is a -lighter weight syntax that is equivalent to the above forms: +Dialect attribute values that are simple enough can use the pretty format, which +is a lighter weight syntax that is equivalent to the above forms: ```mlir // Complex attribute #foo.something ``` -Sufficiently complex dialect attributes are required to use the verbose form for -generality. For example, the more complex type shown above wouldn't be valid in -the lighter syntax: `#foo.something>>` because it contains characters -that are not allowed in the lighter syntax, as well as unbalanced `<>` -characters. +Sufficiently complex dialect attribute values are required to use the verbose +form for generality. For example, the more complex type shown above would not be +valid in the lighter syntax: `#foo.something>>` because it contains +characters that are not allowed in the lighter syntax, as well as unbalanced +`<>` characters. -See [here](Tutorials/DefiningAttributesAndTypes.md) to learn how to define dialect +See [here](Tutorials/DefiningAttributesAndTypes.md) on how to define dialect attribute values. ### Standard Attribute Values diff --git a/mlir/lib/IR/BuiltinDialect.cpp b/mlir/lib/IR/BuiltinDialect.cpp index 5c0a0380f9af..8f872ac7c9ab 100644 --- a/mlir/lib/IR/BuiltinDialect.cpp +++ b/mlir/lib/IR/BuiltinDialect.cpp @@ -228,9 +228,9 @@ static LogicalResult verify(ModuleOp op) { ArrayRef{mlir::SymbolTable::getSymbolAttrName(), mlir::SymbolTable::getVisibilityAttrName()}, attr.first.strref())) - return op.emitOpError() - << "can only contain dialect-specific attributes, found: '" - << attr.first << "'"; + return op.emitOpError() << "can only contain attributes with " + "dialect-prefixed names, found: '" + << attr.first << "'"; } return success(); diff --git a/mlir/test/IR/invalid-module-op.mlir b/mlir/test/IR/invalid-module-op.mlir index 73fe188209d1..520821a7b0b4 100644 --- a/mlir/test/IR/invalid-module-op.mlir +++ b/mlir/test/IR/invalid-module-op.mlir @@ -44,7 +44,7 @@ func @module_op() { // - -// expected-error@+1 {{can only contain dialect-specific attributes}} +// expected-error@+1 {{can only contain attributes with dialect-prefixed names}} module attributes {attr} { } ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] b2391d5 - [MLIR] Normalize the results of normalizable operations
Author: Haruki Imai Date: 2020-12-03T19:34:07+05:30 New Revision: b2391d5f0da2a9122d337de6fa1a6aa9baad3fb4 URL: https://github.com/llvm/llvm-project/commit/b2391d5f0da2a9122d337de6fa1a6aa9baad3fb4 DIFF: https://github.com/llvm/llvm-project/commit/b2391d5f0da2a9122d337de6fa1a6aa9baad3fb4.diff LOG: [MLIR] Normalize the results of normalizable operations Memrefs with affine_map in the results of normalizable operation were not normalized by `--normalize-memrefs` option. This patch normalizes them. Differential Revision: https://reviews.llvm.org/D88719 Added: Modified: mlir/lib/Transforms/NormalizeMemRefs.cpp mlir/test/Transforms/normalize-memrefs-ops.mlir mlir/test/lib/Dialect/Test/TestOps.td Removed: diff --git a/mlir/lib/Transforms/NormalizeMemRefs.cpp b/mlir/lib/Transforms/NormalizeMemRefs.cpp index 44b3ccbd2c3f..d7fa212baa73 100644 --- a/mlir/lib/Transforms/NormalizeMemRefs.cpp +++ b/mlir/lib/Transforms/NormalizeMemRefs.cpp @@ -36,6 +36,7 @@ struct NormalizeMemRefs : public NormalizeMemRefsBase { void updateFunctionSignature(FuncOp funcOp, ModuleOp moduleOp); void setCalleesAndCallersNonNormalizable(FuncOp funcOp, ModuleOp moduleOp, DenseSet &normalizableFuncs); + Operation *createOpResultsNormalized(FuncOp funcOp, Operation *oldOp); }; } // end anonymous namespace @@ -384,6 +385,59 @@ void NormalizeMemRefs::normalizeFuncOpMemRefs(FuncOp funcOp, funcOp.front().eraseArgument(argIndex + 1); } + // Walk over normalizable operations to normalize memrefs of the operation + // results. When `op` has memrefs with affine map in the operation results, + // new operation containin normalized memrefs is created. Then, the memrefs + // are replaced. `CallOp` is skipped here because it is handled in + // `updateFunctionSignature()`. + funcOp.walk([&](Operation *op) { +if (op->hasTrait() && +op->getNumResults() > 0 && !isa(op) && !funcOp.isExternal()) { + // Create newOp containing normalized memref in the operation result. + Operation *newOp = createOpResultsNormalized(funcOp, op); + // When all of the operation results have no memrefs or memrefs without + // affine map, `newOp` is the same with `op` and following process is + // skipped. + if (op != newOp) { +bool replacingMemRefUsesFailed = false; +for (unsigned resIndex : llvm::seq(0, op->getNumResults())) { + // Replace all uses of the old memrefs. + Value oldMemRef = op->getResult(resIndex); + Value newMemRef = newOp->getResult(resIndex); + MemRefType oldMemRefType = oldMemRef.getType().dyn_cast(); + // Check whether the operation result is MemRef type. + if (!oldMemRefType) +continue; + MemRefType newMemRefType = newMemRef.getType().cast(); + if (oldMemRefType == newMemRefType) +continue; + // TODO: Assume single layout map. Multiple maps not supported. + AffineMap layoutMap = oldMemRefType.getAffineMaps().front(); + if (failed(replaceAllMemRefUsesWith(oldMemRef, + /*newMemRef=*/newMemRef, + /*extraIndices=*/{}, + /*indexRemap=*/layoutMap, + /*extraOperands=*/{}, + /*symbolOperands=*/{}, + /*domInstFilter=*/nullptr, + /*postDomInstFilter=*/nullptr, + /*allowDereferencingOps=*/true, + /*replaceInDeallocOp=*/true))) { +newOp->erase(); +replacingMemRefUsesFailed = true; +continue; + } +} +if (!replacingMemRefUsesFailed) { + // Replace other ops with new op and delete the old op when the + // replacement succeeded. + op->replaceAllUsesWith(newOp); + op->erase(); +} + } +} + }); + // In a normal function, memrefs in the return type signature gets normalized // as a result of normalization of functions arguments, AllocOps or CallOps' // result types. Since an external function doesn't have a body, memrefs in @@ -417,3 +471,49 @@ void NormalizeMemRefs::normalizeFuncOpMemRefs(FuncOp funcOp, } updateFunctionSignature(funcOp, moduleOp); } + +/// Create an operation containing normalized memrefs in the operation results. +/// When the results of `oldOp` have memrefs with affine map, the memrefs are +/// normalized, and new operation containing them in the operation results is +/// returned. If all of the results of `oldOp` have no memrefs or memrefs +/// without affine map, `ol
[llvm-branch-commits] [mlir] dc930e5 - [MLIR][Affine] Add affine.for normalization support
Author: Navdeep Kumar Date: 2020-12-07T22:04:07+05:30 New Revision: dc930e5f2f91e7eb5ebc9cb61f6a71bc8924559e URL: https://github.com/llvm/llvm-project/commit/dc930e5f2f91e7eb5ebc9cb61f6a71bc8924559e DIFF: https://github.com/llvm/llvm-project/commit/dc930e5f2f91e7eb5ebc9cb61f6a71bc8924559e.diff LOG: [MLIR][Affine] Add affine.for normalization support Add support to normalize affine.for ops i.e., convert the lower bound to zero and loop step to one. The Upper bound is set to the trip count of the loop. The exact value of loopIV is calculated just inside the body of affine.for. Currently loops with lower bounds having single result are supported. No such restriction exists on upper bounds. Differential Revision: https://reviews.llvm.org/D92233 Added: Modified: mlir/lib/Dialect/Affine/Transforms/AffineLoopNormalize.cpp mlir/test/Dialect/Affine/affine-loop-normalize.mlir Removed: diff --git a/mlir/lib/Dialect/Affine/Transforms/AffineLoopNormalize.cpp b/mlir/lib/Dialect/Affine/Transforms/AffineLoopNormalize.cpp index 2ad403e73f72..d863663f86bd 100644 --- a/mlir/lib/Dialect/Affine/Transforms/AffineLoopNormalize.cpp +++ b/mlir/lib/Dialect/Affine/Transforms/AffineLoopNormalize.cpp @@ -79,14 +79,104 @@ void mlir::normalizeAffineParallel(AffineParallelOp op) { op.setUpperBounds(ranges.getOperands(), newUpperMap); } -/// Normalization transformations for affine.for ops. For now, it only removes -/// single iteration loops. We may want to consider separating redundant loop -/// elimitation from loop bound normalization, if needed in the future. +/// Normalizes affine.for ops. If the affine.for op has only a single iteration +/// only then it is simply promoted, else it is normalized in the traditional +/// way, by converting the lower bound to zero and loop step to one. The upper +/// bound is set to the trip count of the loop. For now, original loops must +/// have lower bound with a single result only. There is no such restriction on +/// upper bounds. static void normalizeAffineFor(AffineForOp op) { if (succeeded(promoteIfSingleIteration(op))) return; - // TODO: Normalize loop bounds. + // Check if the forop is already normalized. + if (op.hasConstantLowerBound() && (op.getConstantLowerBound() == 0) && + (op.getStep() == 1)) +return; + + // Check if the lower bound has a single result only. Loops with a max lower + // bound can't be normalized without additional support like + // affine.execute_region's. If the lower bound does not have a single result + // then skip this op. + if (op.getLowerBoundMap().getNumResults() != 1) +return; + + Location loc = op.getLoc(); + OpBuilder opBuilder(op); + int64_t origLoopStep = op.getStep(); + + // Calculate upperBound for normalized loop. + SmallVector ubOperands; + AffineBound lb = op.getLowerBound(); + AffineBound ub = op.getUpperBound(); + ubOperands.reserve(ub.getNumOperands() + lb.getNumOperands()); + AffineMap origLbMap = lb.getMap(); + AffineMap origUbMap = ub.getMap(); + + // Add dimension operands from upper/lower bound. + for (unsigned j = 0, e = origUbMap.getNumDims(); j < e; ++j) +ubOperands.push_back(ub.getOperand(j)); + for (unsigned j = 0, e = origLbMap.getNumDims(); j < e; ++j) +ubOperands.push_back(lb.getOperand(j)); + + // Add symbol operands from upper/lower bound. + for (unsigned j = 0, e = origUbMap.getNumSymbols(); j < e; ++j) +ubOperands.push_back(ub.getOperand(origUbMap.getNumDims() + j)); + for (unsigned j = 0, e = origLbMap.getNumSymbols(); j < e; ++j) +ubOperands.push_back(lb.getOperand(origLbMap.getNumDims() + j)); + + // Add original result expressions from lower/upper bound map. + SmallVector origLbExprs(origLbMap.getResults().begin(), + origLbMap.getResults().end()); + SmallVector origUbExprs(origUbMap.getResults().begin(), + origUbMap.getResults().end()); + SmallVector newUbExprs; + + // The original upperBound can have more than one result. For the new + // upperBound of this loop, take diff erence of all possible combinations of + // the ub results and lb result and ceildiv with the loop step. For e.g., + // + // affine.for %i1 = 0 to min affine_map<(d0)[] -> (d0 + 32, 1024)>(%i0) + // will have an upperBound map as, + // affine_map<(d0)[] -> (((d0 + 32) - 0) ceildiv 1, (1024 - 0) ceildiv + // 1)>(%i0) + // + // Insert all combinations of upper/lower bound results. + for (unsigned i = 0, e = origUbExprs.size(); i < e; ++i) { +newUbExprs.push_back( +(origUbExprs[i] - origLbExprs[0]).ceilDiv(origLoopStep)); + } + + // Construct newUbMap. + AffineMap newUbMap = + AffineMap::get(origLbMap.getNumDims() + origUbMap.getNumDims(), + origLbMap.getNumSymbols() + origUbMap.getNumSymbols(), + newUbExprs, opBuilder.g