From 3ad26060e4bceb2cf9f4959d659cbb29d88344cf Mon Sep 17 00:00:00 2001 From: Tom Eccles Date: Tue, 17 Jan 2023 17:37:15 +0000 Subject: [PATCH] [flang] add hlfir.sum operation Add an HLFIR operation for the SUM transformational intrinsic, according to the design set out in flang/doc/HighLevelFIR.md. I decided to make hlfir.sum very lenient about the form of its arguments. This allows the sum intrinsic to be lowered to only this HLFIR operation, without needing several operations to convert and box arguments. Having only one operation generated for the intrinsic invocation should make optimisation passes on HLFIR simpler. Differential Revision: https://reviews.llvm.org/D142897 --- flang/include/flang/Optimizer/Builder/HLFIRTools.h | 1 + flang/include/flang/Optimizer/HLFIR/HLFIRDialect.h | 7 + flang/include/flang/Optimizer/HLFIR/HLFIROpBase.td | 15 ++ flang/include/flang/Optimizer/HLFIR/HLFIROps.h | 1 + flang/include/flang/Optimizer/HLFIR/HLFIROps.td | 27 +++ flang/lib/Optimizer/Builder/HLFIRTools.cpp | 2 + flang/lib/Optimizer/HLFIR/IR/HLFIRDialect.cpp | 41 ++++ flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp | 69 ++++++ flang/test/HLFIR/invalid.fir | 24 +++ flang/test/HLFIR/sum.fir | 239 +++++++++++++++++++++ 10 files changed, 426 insertions(+) create mode 100644 flang/test/HLFIR/sum.fir diff --git a/flang/include/flang/Optimizer/Builder/HLFIRTools.h b/flang/include/flang/Optimizer/Builder/HLFIRTools.h index e610478..389f5ce 100644 --- a/flang/include/flang/Optimizer/Builder/HLFIRTools.h +++ b/flang/include/flang/Optimizer/Builder/HLFIRTools.h @@ -373,6 +373,7 @@ convertToAddress(mlir::Location loc, fir::FirOpBuilder &builder, std::pair> convertToBox(mlir::Location loc, fir::FirOpBuilder &builder, const hlfir::Entity &entity, mlir::Type targetType); + } // namespace hlfir #endif // FORTRAN_OPTIMIZER_BUILDER_HLFIRTOOLS_H diff --git a/flang/include/flang/Optimizer/HLFIR/HLFIRDialect.h b/flang/include/flang/Optimizer/HLFIR/HLFIRDialect.h index 8aace6b..6a9acb4 100644 --- a/flang/include/flang/Optimizer/HLFIR/HLFIRDialect.h +++ b/flang/include/flang/Optimizer/HLFIR/HLFIRDialect.h @@ -69,6 +69,13 @@ inline bool isBoxAddressOrValueType(mlir::Type type) { return fir::unwrapRefType(type).isa(); } +bool isFortranScalarNumericalType(mlir::Type); +bool isFortranNumericalArrayObject(mlir::Type); +bool isPassByRefOrIntegerType(mlir::Type); +bool isI1Type(mlir::Type); +// scalar i1 or logical, or sequence of logical (via (boxed?) array or expr) +bool isMaskArgument(mlir::Type); + } // namespace hlfir #endif // FORTRAN_OPTIMIZER_HLFIR_HLFIRDIALECT_H diff --git a/flang/include/flang/Optimizer/HLFIR/HLFIROpBase.td b/flang/include/flang/Optimizer/HLFIR/HLFIROpBase.td index d17a4cb..23ad2eda 100644 --- a/flang/include/flang/Optimizer/HLFIR/HLFIROpBase.td +++ b/flang/include/flang/Optimizer/HLFIR/HLFIROpBase.td @@ -107,4 +107,19 @@ def IsFortranScalarCharacterExprPred def AnyScalarCharacterExpr : Type; +def IsFortranNumericalArrayObjectPred + : CPred<"::hlfir::isFortranNumericalArrayObject($_self)">; +def AnyFortranNumericalArrayObject : Type; + +def IsPassByRefOrIntegerTypePred + : CPred<"::hlfir::isPassByRefOrIntegerType($_self)">; +def AnyPassByRefOrIntegerType : Type; + +def IsMaskArgumentPred + : CPred<"::hlfir::isMaskArgument($_self)">; +def AnyFortranLogicalOrI1ArrayObject : Type; + #endif // FORTRAN_DIALECT_HLFIR_OP_BASE diff --git a/flang/include/flang/Optimizer/HLFIR/HLFIROps.h b/flang/include/flang/Optimizer/HLFIR/HLFIROps.h index 33530d1..e0e7183 100644 --- a/flang/include/flang/Optimizer/HLFIR/HLFIROps.h +++ b/flang/include/flang/Optimizer/HLFIR/HLFIROps.h @@ -13,6 +13,7 @@ #include "flang/Optimizer/Dialect/FIRType.h" #include "flang/Optimizer/Dialect/FortranVariableInterface.h" #include "flang/Optimizer/HLFIR/HLFIRDialect.h" +#include "mlir/Dialect/Arith/IR/Arith.h" #include "mlir/Interfaces/InferTypeOpInterface.h" #include "mlir/Interfaces/SideEffectInterfaces.h" diff --git a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td index 3228685..1321eab 100644 --- a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td +++ b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td @@ -18,6 +18,8 @@ include "flang/Optimizer/HLFIR/HLFIROpBase.td" include "flang/Optimizer/Dialect/FIRTypes.td" include "flang/Optimizer/Dialect/FIRAttr.td" include "flang/Optimizer/Dialect/FortranVariableInterface.td" +include "mlir/Dialect/Arith/IR/ArithBase.td" +include "mlir/Dialect/Arith/IR/ArithOpsInterfaces.td" include "mlir/IR/BuiltinAttributes.td" // Base class for FIR operations. @@ -256,6 +258,31 @@ def hlfir_SetLengthOp : hlfir_Op<"set_length", []> { let builders = [OpBuilder<(ins "mlir::Value":$string,"mlir::Value":$len)>]; } +def hlfir_SumOp : hlfir_Op<"sum", [AttrSizedOperandSegments, + DeclareOpInterfaceMethods]> { + let summary = "SUM transformational intrinsic"; + let description = [{ + Sums the elements of an array, optionally along a particular dimension, + optionally if a mask is true. + }]; + + let arguments = (ins + AnyFortranNumericalArrayObject:$array, + Optional:$dim, + Optional:$mask, + DefaultValuedAttr:$fastmath + ); + + let results = (outs hlfir_ExprType); + + let assemblyFormat = [{ + $array (`dim` $dim^)? (`mask` $mask^)? attr-dict `:` functional-type(operands, results) + }]; + + let hasVerifier = 1; +} + def hlfir_AssociateOp : hlfir_Op<"associate", [AttrSizedOperandSegments, DeclareOpInterfaceMethods]> { let summary = "Create a variable from an expression value"; diff --git a/flang/lib/Optimizer/Builder/HLFIRTools.cpp b/flang/lib/Optimizer/Builder/HLFIRTools.cpp index 41cc800..072fb5c 100644 --- a/flang/lib/Optimizer/Builder/HLFIRTools.cpp +++ b/flang/lib/Optimizer/Builder/HLFIRTools.cpp @@ -17,6 +17,8 @@ #include "flang/Optimizer/Builder/Todo.h" #include "flang/Optimizer/HLFIR/HLFIROps.h" #include "mlir/IR/IRMapping.h" +#include "mlir/Support/LLVM.h" +#include "llvm/ADT/TypeSwitch.h" #include // Return explicit extents. If the base is a fir.box, this won't read it to diff --git a/flang/lib/Optimizer/HLFIR/IR/HLFIRDialect.cpp b/flang/lib/Optimizer/HLFIR/IR/HLFIRDialect.cpp index fbb7d77..f23be5d 100644 --- a/flang/lib/Optimizer/HLFIR/IR/HLFIRDialect.cpp +++ b/flang/lib/Optimizer/HLFIR/IR/HLFIRDialect.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "flang/Optimizer/HLFIR/HLFIRDialect.h" +#include "flang/Optimizer/Dialect/FIRType.h" #include "flang/Optimizer/HLFIR/HLFIROps.h" #include "mlir/IR/Builders.h" #include "mlir/IR/BuiltinTypes.h" @@ -99,3 +100,43 @@ bool hlfir::isFortranScalarCharacterExprType(mlir::Type type) { exprType.getElementType().isa(); return false; } + +bool hlfir::isFortranScalarNumericalType(mlir::Type type) { + return fir::isa_integer(type) || fir::isa_real(type) || + fir::isa_complex(type); +} + +bool hlfir::isFortranNumericalArrayObject(mlir::Type type) { + if (isBoxAddressType(type)) + return false; + if (auto arrayTy = + getFortranElementOrSequenceType(type).dyn_cast()) + return isFortranScalarNumericalType(arrayTy.getEleTy()); + return false; +} + +bool hlfir::isPassByRefOrIntegerType(mlir::Type type) { + mlir::Type unwrappedType = fir::unwrapPassByRefType(type); + return fir::isa_integer(unwrappedType); +} + +bool hlfir::isI1Type(mlir::Type type) { + if (mlir::IntegerType integer = type.dyn_cast()) + if (integer.getWidth() == 1) + return true; + return false; +} + +bool hlfir::isMaskArgument(mlir::Type type) { + if (isBoxAddressType(type)) + return false; + + mlir::Type unwrappedType = fir::unwrapPassByRefType(fir::unwrapRefType(type)); + mlir::Type elementType = getFortranElementType(unwrappedType); + if (unwrappedType != elementType) + // input type is an array + return mlir::isa(elementType); + + // input is a scalar, so allow i1 too + return mlir::isa(elementType) || isI1Type(elementType); +} diff --git a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp index 9bf5601..feea448 100644 --- a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp +++ b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp @@ -11,7 +11,10 @@ //===----------------------------------------------------------------------===// #include "flang/Optimizer/HLFIR/HLFIROps.h" +#include "flang/Optimizer/Builder/HLFIRTools.h" #include "flang/Optimizer/Dialect/FIROpsSupport.h" +#include "flang/Optimizer/Dialect/FIRType.h" +#include "flang/Optimizer/HLFIR/HLFIRDialect.h" #include "mlir/IR/Builders.h" #include "mlir/IR/BuiltinTypes.h" #include "mlir/IR/DialectImplementation.h" @@ -421,6 +424,72 @@ void hlfir::SetLengthOp::build(mlir::OpBuilder &builder, } //===----------------------------------------------------------------------===// +// SumOp +//===----------------------------------------------------------------------===// + +mlir::LogicalResult hlfir::SumOp::verify() { + mlir::Operation *op = getOperation(); + + auto results = op->getResultTypes(); + assert(results.size() == 1); + + mlir::Value array = getArray(); + mlir::Value mask = getMask(); + + fir::SequenceType arrayTy = + hlfir::getFortranElementOrSequenceType(array.getType()) + .cast(); + mlir::Type numTy = arrayTy.getEleTy(); + llvm::ArrayRef arrayShape = arrayTy.getShape(); + hlfir::ExprType resultTy = results[0].cast(); + + if (mask) { + fir::SequenceType maskSeq = + hlfir::getFortranElementOrSequenceType(mask.getType()) + .dyn_cast(); + llvm::ArrayRef maskShape; + + if (maskSeq) + maskShape = maskSeq.getShape(); + + if (!maskShape.empty()) { + if (maskShape.size() != arrayShape.size()) + return emitWarning("MASK must be conformable to ARRAY"); + static_assert(fir::SequenceType::getUnknownExtent() == + hlfir::ExprType::getUnknownExtent()); + constexpr int64_t unknownExtent = fir::SequenceType::getUnknownExtent(); + for (std::size_t i = 0; i < arrayShape.size(); ++i) { + int64_t arrayExtent = arrayShape[i]; + int64_t maskExtent = maskShape[i]; + if ((arrayExtent != maskExtent) && (arrayExtent != unknownExtent) && + (maskExtent != unknownExtent)) + return emitWarning("MASK must be conformable to ARRAY"); + } + } + } + + if (resultTy.isArray()) { + // Result is of the same type as ARRAY + if (resultTy.getEleTy() != numTy) + return emitOpError( + "result must have the same element type as ARRAY argument"); + + llvm::ArrayRef resultShape = resultTy.getShape(); + + // Result has rank n-1 + if (resultShape.size() != (arrayShape.size() - 1)) + return emitOpError("result rank must be one less than ARRAY"); + } else { + // Result is of the same type as ARRAY + if (resultTy.getElementType() != numTy) + return emitOpError( + "result must have the same element type as ARRAY argument"); + } + + return mlir::success(); +} + +//===----------------------------------------------------------------------===// // AssociateOp //===----------------------------------------------------------------------===// diff --git a/flang/test/HLFIR/invalid.fir b/flang/test/HLFIR/invalid.fir index a7a3150..dd80163 100644 --- a/flang/test/HLFIR/invalid.fir +++ b/flang/test/HLFIR/invalid.fir @@ -295,3 +295,27 @@ func.func @bad_concat_4(%arg0: !fir.ref>) { %0 = hlfir.concat %arg0 len %c30 : (!fir.ref>, index) -> (!hlfir.expr>) return } + +// ----- +func.func @bad_sum1(%arg0: !hlfir.expr, %arg1: i32, %arg2: !fir.box>) { + // expected-error@+1 {{'hlfir.sum' op result must have the same element type as ARRAY argument}} + %0 = hlfir.sum %arg0 dim %arg1 mask %arg2 : (!hlfir.expr, i32, !fir.box>) -> !hlfir.expr +} + +// ----- +func.func @bad_sum2(%arg0: !hlfir.expr, %arg1: i32, %arg2: !fir.box>>) { + // expected-warning@+1 {{MASK must be conformable to ARRAY}} + %0 = hlfir.sum %arg0 dim %arg1 mask %arg2 : (!hlfir.expr, i32, !fir.box>>) -> !hlfir.expr +} + +// ----- +func.func @bad_sum3(%arg0: !hlfir.expr, %arg1: i32, %arg2: !fir.box>>) { + // expected-warning@+1 {{MASK must be conformable to ARRAY}} + %0 = hlfir.sum %arg0 dim %arg1 mask %arg2 : (!hlfir.expr, i32, !fir.box>>) -> !hlfir.expr +} + +// ----- +func.func @bad_sum4(%arg0: !hlfir.expr, %arg1: i32, %arg2: !fir.box>) { + // expected-error@+1 {{'hlfir.sum' op result rank must be one less than ARRAY}} + %0 = hlfir.sum %arg0 dim %arg1 mask %arg2 : (!hlfir.expr, i32, !fir.box>) -> !hlfir.expr +} diff --git a/flang/test/HLFIR/sum.fir b/flang/test/HLFIR/sum.fir new file mode 100644 index 0000000..45388c3 --- /dev/null +++ b/flang/test/HLFIR/sum.fir @@ -0,0 +1,239 @@ +// Test hlfir.sum operation parse, verify (no errors), and unparse + +// RUN: fir-opt %s | fir-opt | FileCheck %s + +// array is an expression of known shape +func.func @sum0(%arg0: !hlfir.expr<42xi32>) { + %mask = fir.alloca !fir.logical<4> + %c_1 = arith.constant 1 : index + %true = arith.constant true + %true_logical = fir.convert %true : (i1) -> !fir.logical<4> + fir.store %true_logical to %mask : !fir.ref> + %mask_box = fir.embox %mask : (!fir.ref>) -> !fir.box> + %0 = hlfir.sum %arg0 dim %c_1 mask %mask_box : (!hlfir.expr<42xi32>, index, !fir.box>) -> !hlfir.expr + return +} +// CHECK: func.func @sum0(%[[ARRAY:.*]]: !hlfir.expr<42xi32>) { +// CHECK-NEXT: %[[MASK:.*]] = fir.alloca !fir.logical<4> +// CHECK-NEXT: %[[C1:.*]] = arith.constant 1 : index +// CHECK-NEXT: %[[TRUE:.*]] = arith.constant true +// CHECK-NEXT: %[[LOGICAL:.*]] = fir.convert %[[TRUE]] : (i1) -> !fir.logical<4> +// CHECK-NEXT: fir.store %[[LOGICAL]] to %[[MASK]] : !fir.ref> +// CHECK-NEXT: %[[BOX:.*]] = fir.embox %0 : (!fir.ref>) -> !fir.box> +// CHECK-NEXT: hlfir.sum %[[ARRAY]] dim %[[C1]] mask %[[BOX]] : (!hlfir.expr<42xi32>, index, !fir.box>) -> !hlfir.expr +// CHECK-NEXT: return +// CHECK-NEXT: } + +// array is an expression of assumed shape +func.func @sum1(%arg0: !hlfir.expr) { + %mask = fir.alloca !fir.logical<4> + %c_1 = arith.constant 1 : index + %true = arith.constant true + %true_logical = fir.convert %true : (i1) -> !fir.logical<4> + fir.store %true_logical to %mask : !fir.ref> + %mask_box = fir.embox %mask : (!fir.ref>) -> !fir.box> + %0 = hlfir.sum %arg0 dim %c_1 mask %mask_box : (!hlfir.expr, index, !fir.box>) -> !hlfir.expr + return +} +// CHECK: func.func @sum1(%[[ARRAY:.*]]: !hlfir.expr) { +// CHECK-NEXT: %[[MASK:.*]] = fir.alloca !fir.logical<4> +// CHECK-NEXT: %[[C1:.*]] = arith.constant 1 : index +// CHECK-NEXT: %[[TRUE:.*]] = arith.constant true +// CHECK-NEXT: %[[LOGICAL:.*]] = fir.convert %[[TRUE]] : (i1) -> !fir.logical<4> +// CHECK-NEXT: fir.store %[[LOGICAL:.*]] to %[[MASK:.*]] : !fir.ref> +// CHECK-NEXT: %[[BOX:.*]] = fir.embox %[[MASK:.*]] : (!fir.ref>) -> !fir.box> +// CHECK-NEXT: hlfir.sum %[[ARRAY:.*]] dim %[[C1]] mask %[[BOX]] : (!hlfir.expr, index, !fir.box>) -> !hlfir.expr +// CHECK-NEXT: return +// CHECK-NEXT: } + +// boxed array +func.func @sum2(%arg0: !fir.box>) { + %mask = fir.alloca !fir.logical<4> + %c_1 = arith.constant 1 : index + %true = arith.constant true + %true_logical = fir.convert %true : (i1) -> !fir.logical<4> + fir.store %true_logical to %mask : !fir.ref> + %mask_box = fir.embox %mask : (!fir.ref>) -> !fir.box> + %0 = hlfir.sum %arg0 dim %c_1 mask %mask_box : (!fir.box>, index, !fir.box>) -> !hlfir.expr + return +} +// CHECK: func.func @sum2(%[[ARRAY:.*]]: !fir.box>) { +// CHECK-NEXT: %[[MASK:.*]] = fir.alloca !fir.logical<4> +// CHECK-NEXT: %[[C1:.*]] = arith.constant 1 : index +// CHECK-NEXT: %[[TRUE:.*]] = arith.constant true +// CHECK-NEXT: %[[LOGICAL:.*]] = fir.convert %[[TRUE]] : (i1) -> !fir.logical<4> +// CHECK-NEXT: fir.store %[[LOGICAL:.*]] to %[[MASK:.*]] : !fir.ref> +// CHECK-NEXT: %[[BOX:.*]] = fir.embox %[[MASK:.*]] : (!fir.ref>) -> !fir.box> +// CHECK-NEXT: hlfir.sum %[[ARRAY:.*]] dim %[[C1]] mask %[[BOX]] : (!fir.box>, index, !fir.box>) -> !hlfir.expr +// CHECK-NEXT: return +// CHECK-NEXT: } + +// assumed shape boxed array +func.func @sum3(%arg0: !fir.box>) { + %mask = fir.alloca !fir.logical<4> + %c_1 = arith.constant 1 : index + %true = arith.constant true + %true_logical = fir.convert %true : (i1) -> !fir.logical<4> + fir.store %true_logical to %mask : !fir.ref> + %mask_box = fir.embox %mask : (!fir.ref>) -> !fir.box> + %0 = hlfir.sum %arg0 dim %c_1 mask %mask_box : (!fir.box>, index, !fir.box>) -> !hlfir.expr + return +} +// CHECK: func.func @sum3(%[[ARRAY:.*]]: !fir.box>) { +// CHECK-NEXT: %[[MASK:.*]] = fir.alloca !fir.logical<4> +// CHECK-NEXT: %[[C1:.*]] = arith.constant 1 : index +// CHECK-NEXT: %[[TRUE:.*]] = arith.constant true +// CHECK-NEXT: %[[LOGICAL:.*]] = fir.convert %[[TRUE]] : (i1) -> !fir.logical<4> +// CHECK-NEXT: fir.store %[[LOGICAL:.*]] to %[[MASK:.*]] : !fir.ref> +// CHECK-NEXT: %[[BOX:.*]] = fir.embox %[[MASK:.*]] : (!fir.ref>) -> !fir.box> +// CHECK-NEXT: hlfir.sum %[[ARRAY:.*]] dim %[[C1]] mask %[[BOX]] : (!fir.box>, index, !fir.box>) -> !hlfir.expr +// CHECK-NEXT: return +// CHECK-NEXT: } + +// known shape expr mask +func.func @sum4(%arg0: !fir.box>, %arg1: !hlfir.expr<42x!fir.logical<4>>) { + %c_1 = arith.constant 1 : index + %0 = hlfir.sum %arg0 dim %c_1 mask %arg1 : (!fir.box>, index, !hlfir.expr<42x!fir.logical<4>>) -> !hlfir.expr + return +} +// CHECK: func.func @sum4(%[[ARRAY:.*]]: !fir.box>, %[[MASK:.*]]: !hlfir.expr<42x!fir.logical<4>>) { +// CHECK-NEXT: %[[C1:.*]] = arith.constant 1 : index +// CHECK-NEXT: hlfir.sum %[[ARRAY]] dim %[[C1]] mask %[[MASK]] : (!fir.box>, index, !hlfir.expr<42x!fir.logical<4>>) -> !hlfir.expr +// CHECK-NEXT: return +// CHECK-NEXT: } + +// assumed shape expr mask +func.func @sum5(%arg0: !fir.box>, %arg1: !hlfir.expr>) { + %c_1 = arith.constant 1 : index + %0 = hlfir.sum %arg0 dim %c_1 mask %arg1 : (!fir.box>, index, !hlfir.expr>) -> !hlfir.expr + return +} +// CHECK: func.func @sum5(%[[ARRAY:.*]]: !fir.box>, %[[MASK:.*]]: !hlfir.expr>) { +// CHECK-NEXT: %[[C1:.*]] = arith.constant 1 : index +// CHECK-NEXT: hlfir.sum %[[ARRAY]] dim %[[C1]] mask %[[MASK]] : (!fir.box>, index, !hlfir.expr>) -> !hlfir.expr +// CHECK-NEXT: return +// CHECK-NEXT: } + +// known shape array mask +func.func @sum6(%arg0: !fir.box>, %arg1: !fir.box>>) { + %c_1 = arith.constant 1 : index + %0 = hlfir.sum %arg0 dim %c_1 mask %arg1 : (!fir.box>, index, !fir.box>>) -> !hlfir.expr + return +} +// CHECK: func.func @sum6(%[[ARRAY:.*]]: !fir.box>, %[[MASK:.*]]: !fir.box>>) { +// CHECK-NEXT: %[[C1:.*]] = arith.constant 1 : index +// CHECK-NEXT: hlfir.sum %[[ARRAY]] dim %[[C1]] mask %[[MASK]] : (!fir.box>, index, !fir.box>>) -> !hlfir.expr +// CHECK-NEXT: return +// CHECK-NEXT: } + +// assumed shape array mask +func.func @sum7(%arg0: !fir.box>, %arg1: !fir.box>>) { + %c_1 = arith.constant 1 : index + %0 = hlfir.sum %arg0 dim %c_1 mask %arg1 : (!fir.box>, index, !fir.box>>) -> !hlfir.expr + return +} +// CHECK: func.func @sum7(%[[ARRAY:.*]]: !fir.box>, %[[MASK:.*]]: !fir.box>>) { +// CHECK-NEXT: %[[C1:.*]] = arith.constant 1 : index +// CHECK-NEXT: hlfir.sum %[[ARRAY]] dim %[[C1]] mask %[[MASK]] : (!fir.box>, index, !fir.box>>) -> !hlfir.expr +// CHECK-NEXT: return +// CHECK-NEXT: } + +// known shape expr return +func.func @sum8(%arg0: !fir.box>, %arg1: i32) { + %mask = fir.alloca !fir.logical<4> + %true = arith.constant true + %true_logical = fir.convert %true : (i1) -> !fir.logical<4> + fir.store %true_logical to %mask : !fir.ref> + %mask_box = fir.embox %mask : (!fir.ref>) -> !fir.box> + %0 = hlfir.sum %arg0 dim %arg1 mask %mask_box : (!fir.box>, i32, !fir.box>) -> !hlfir.expr<2xi32> + return +} +// CHECK: func.func @sum8(%[[ARRAY:.*]]: !fir.box>, %[[DIM:.*]]: i32) { +// CHECK-NEXT: %[[MASK:.*]] = fir.alloca !fir.logical<4> +// CHECK-NEXT: %[[TRUE:.*]] = arith.constant true +// CHECK-NEXT: %[[LOGICAL:.*]] = fir.convert %[[TRUE]] : (i1) -> !fir.logical<4> +// CHECK-NEXT: fir.store %[[LOGICAL]] to %[[MASK]] : !fir.ref> +// CHECK-NEXT: %[[BOX:.*]] = fir.embox %0 : (!fir.ref>) -> !fir.box> +// CHECK-NEXT: hlfir.sum %[[ARRAY]] dim %[[DIM]] mask %[[BOX]] : (!fir.box>, i32, !fir.box>) -> !hlfir.expr<2xi32> +// CHECK-NEXT: return +// CHECK-NEXT: } + +// assumed shape expr return +func.func @sum9(%arg0: !fir.box>, %arg1: i32) { + %mask = fir.alloca !fir.logical<4> + %true = arith.constant true + %true_logical = fir.convert %true : (i1) -> !fir.logical<4> + fir.store %true_logical to %mask : !fir.ref> + %mask_box = fir.embox %mask : (!fir.ref>) -> !fir.box> + %0 = hlfir.sum %arg0 dim %arg1 mask %mask_box : (!fir.box>, i32, !fir.box>) -> !hlfir.expr + return +} +// CHECK: func.func @sum9(%[[ARRAY:.*]]: !fir.box>, %[[DIM:.*]]: i32) { +// CHECK-NEXT: %[[MASK:.*]] = fir.alloca !fir.logical<4> +// CHECK-NEXT: %[[TRUE:.*]] = arith.constant true +// CHECK-NEXT: %[[LOGICAL:.*]] = fir.convert %[[TRUE]] : (i1) -> !fir.logical<4> +// CHECK-NEXT: fir.store %[[LOGICAL]] to %[[MASK]] : !fir.ref> +// CHECK-NEXT: %[[BOX:.*]] = fir.embox %0 : (!fir.ref>) -> !fir.box> +// CHECK-NEXT: hlfir.sum %[[ARRAY]] dim %[[DIM]] mask %[[BOX]] : (!fir.box>, i32, !fir.box>) -> !hlfir.expr +// CHECK-NEXT: return +// CHECK-NEXT: } + +// hlfir.sum with only an array argument +func.func @sum10(%arg0: !fir.box>) { + %sum = hlfir.sum %arg0 : (!fir.box>) -> !hlfir.expr + return +} +// CHECK: func.func @sum10(%[[ARRAY:.*]]: !fir.box> +// CHECK-NEXT: %[[SUM:.*]] = hlfir.sum %[[ARRAY]] : (!fir.box>) -> !hlfir.expr +// CHECK-NEXT: return +// CHECK-NEXT: } + +// hlfir.sum with array and dim argument +func.func @sum11(%arg0: !fir.box>, %arg1: i32) { + %sum = hlfir.sum %arg0 dim %arg1 : (!fir.box>, i32) -> !hlfir.expr + return +} +// CHECK: func.func @sum11(%[[ARRAY:.*]]: !fir.box>, %[[DIM:.*]]: i32 +// CHECK-NEXT: %[[SUM:.*]] = hlfir.sum %[[ARRAY]] dim %[[DIM]] : (!fir.box>, i32) -> !hlfir.expr +// CHECK-NEXT: return +// CHECK-NEXT: } + +// hlfir.sum with array and mask argument +func.func @sum12(%arg0: !fir.box>, %arg1: !fir.logical<4>) { + %sum = hlfir.sum %arg0 mask %arg1 : (!fir.box>, !fir.logical<4>) -> !hlfir.expr + return +} +// CHECK: func.func @sum12(%[[ARRAY:.*]]: !fir.box>, %[[MASK:.*]]: !fir.logical<4> +// CHECK-NEXT: %[[SUM:.*]] = hlfir.sum %[[ARRAY]] mask %[[MASK]] : (!fir.box>, !fir.logical<4>) -> !hlfir.expr +// CHECK-NEXT: return +// CHECK-NEXT: } + +// hlfir.sum with dim argument with an unusual type +func.func @sum13(%arg0: !fir.box>, %arg1: index) { + %sum = hlfir.sum %arg0 dim %arg1 : (!fir.box>, index) -> !hlfir.expr + return +} +// CHECK: func.func @sum13(%[[ARRAY:.*]]: !fir.box>, %[[DIM:.*]]: index +// CHECK-NEXT: %[[SUM:.*]] = hlfir.sum %[[ARRAY]] dim %[[DIM]] : (!fir.box>, index) -> !hlfir.expr +// CHECK-NEXT: return +// CHECK-NEXT: } + +// hlfir.sum with mask argument of unusual type +func.func @sum14(%arg0: !fir.box>, %arg1: i1) { + %sum = hlfir.sum %arg0 mask %arg1 : (!fir.box>, i1) -> !hlfir.expr + return +} +// CHECK: func.func @sum14(%[[ARRAY:.*]]: !fir.box>, %[[MASK:.*]]: i1 +// CHECK-NEXT: %[[SUM:.*]] = hlfir.sum %[[ARRAY]] mask %[[MASK]] : (!fir.box>, i1) -> !hlfir.expr +// CHECK-NEXT: return +// CHECK-NEXT: } + +// hlfir.sum with mask argument of ref> type +func.func @sum15(%arg0: !fir.box>, %arg1: !fir.ref>>) { + %sum = hlfir.sum %arg0 mask %arg1 : (!fir.box>, !fir.ref>>) -> !hlfir.expr + return +} +// CHECK: func.func @sum15(%[[ARRAY:.*]]: !fir.box>, %[[MASK:.*]]: !fir.ref>> +// CHECK-NEXT: %[[SUM:.*]] = hlfir.sum %[[ARRAY]] mask %[[MASK]] : (!fir.box>, !fir.ref>>) -> !hlfir.expr +// CHECK-NEXT: return +// CHECK-NEXT: } -- 2.7.4