[flang-commits] [flang] ebfe8a7 - [flang] Lower F08 bitwise-reduction intrinsics (IALL, IANY, IPARITY)
Tarun Prabhu via flang-commits
flang-commits at lists.llvm.org
Mon Sep 26 09:31:21 PDT 2022
Author: Tarun Prabhu
Date: 2022-09-26T10:28:46-06:00
New Revision: ebfe8a741190070d7ed926bd20c97cd3690de84d
URL: https://github.com/llvm/llvm-project/commit/ebfe8a741190070d7ed926bd20c97cd3690de84d
DIFF: https://github.com/llvm/llvm-project/commit/ebfe8a741190070d7ed926bd20c97cd3690de84d.diff
LOG: [flang] Lower F08 bitwise-reduction intrinsics (IALL, IANY, IPARITY)
This calls the corresponding runtime functions when appropriate. The implementation
follows the pattern of the SUM and PRODUCT intrinsics.
Differential Revision: https://reviews.llvm.org/D129616
Added:
flang/test/Lower/Intrinsics/iall.f90
flang/test/Lower/Intrinsics/iany.f90
flang/test/Lower/Intrinsics/iparity.f90
Modified:
flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h
flang/include/flang/Optimizer/Builder/Runtime/Reduction.h
flang/lib/Lower/IntrinsicCall.cpp
flang/lib/Optimizer/Builder/Runtime/Reduction.cpp
Removed:
################################################################################
diff --git a/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h b/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h
index 2d674593511c7..b2e7abe893483 100644
--- a/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h
+++ b/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h
@@ -387,6 +387,7 @@ struct RuntimeTableEntry<RuntimeTableKey<KT>, RuntimeIdentifier<Cs...>> {
fir::runtime::RuntimeTableEntry<fir::runtime::RuntimeTableKey<decltype(X)>, \
FirAsSequence(X)>
#define mkRTKey(X) FirmkKey(RTNAME(X))
+#define EXPAND_AND_QUOTE_KEY(S) ExpandAndQuoteKey(RTNAME(S))
/// Get (or generate) the MLIR FuncOp for a given runtime function. Its template
/// argument is intended to be of the form: <mkRTKey(runtime function name)>.
diff --git a/flang/include/flang/Optimizer/Builder/Runtime/Reduction.h b/flang/include/flang/Optimizer/Builder/Runtime/Reduction.h
index 2554d6588007b..185dff89c8150 100644
--- a/flang/include/flang/Optimizer/Builder/Runtime/Reduction.h
+++ b/flang/include/flang/Optimizer/Builder/Runtime/Reduction.h
@@ -165,6 +165,42 @@ void genSumDim(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value resultBox, mlir::Value arrayBox, mlir::Value dim,
mlir::Value maskBox);
+/// Generate call to `IAll` intrinsic runtime routine. This is the version
+/// that does not take a dim argument.
+mlir::Value genIAll(fir::FirOpBuilder &builder, mlir::Location loc,
+ mlir::Value arrayBox, mlir::Value maskBox,
+ mlir::Value resultBox);
+
+/// Generate call to `IAllDim` intrinsic runtime routine. This is the version
+/// that takes arrays of any rank with a dim argument specified.
+void genIAllDim(fir::FirOpBuilder &builder, mlir::Location loc,
+ mlir::Value resultBox, mlir::Value arrayBox, mlir::Value dim,
+ mlir::Value maskBox);
+
+/// Generate call to `IAny` intrinsic runtime routine. This is the version
+/// that does not take a dim argument.
+mlir::Value genIAny(fir::FirOpBuilder &builder, mlir::Location loc,
+ mlir::Value arrayBox, mlir::Value maskBox,
+ mlir::Value resultBox);
+
+/// Generate call to `IAnyDim` intrinsic runtime routine. This is the version
+/// that takes arrays of any rank with a dim argument specified.
+void genIAnyDim(fir::FirOpBuilder &builder, mlir::Location loc,
+ mlir::Value resultBox, mlir::Value arrayBox, mlir::Value dim,
+ mlir::Value maskBox);
+
+/// Generate call to `IParity` intrinsic runtime routine. This is the version
+/// that does not take a dim argument.
+mlir::Value genIParity(fir::FirOpBuilder &builder, mlir::Location loc,
+ mlir::Value arrayBox, mlir::Value maskBox,
+ mlir::Value resultBox);
+
+/// Generate call to `IParityDim` intrinsic runtime routine. This is the version
+/// that takes arrays of any rank with a dim argument specified.
+void genIParityDim(fir::FirOpBuilder &builder, mlir::Location loc,
+ mlir::Value resultBox, mlir::Value arrayBox, mlir::Value dim,
+ mlir::Value maskBox);
+
} // namespace fir::runtime
#endif // FORTRAN_OPTIMIZER_BUILDER_RUNTIME_REDUCTION_H
diff --git a/flang/lib/Lower/IntrinsicCall.cpp b/flang/lib/Lower/IntrinsicCall.cpp
index cd5c1bbfc7131..10353d2184bc5 100644
--- a/flang/lib/Lower/IntrinsicCall.cpp
+++ b/flang/lib/Lower/IntrinsicCall.cpp
@@ -175,10 +175,10 @@ genFuncDim(FD funcDim, mlir::Type resultType, fir::FirOpBuilder &builder,
});
}
-/// Process calls to Product, Sum intrinsic functions
+/// Process calls to Product, Sum, IAll, IAny, IParity intrinsic functions
template <typename FN, typename FD>
static fir::ExtendedValue
-genProdOrSum(FN func, FD funcDim, mlir::Type resultType,
+genReduction(FN func, FD funcDim, mlir::Type resultType,
fir::FirOpBuilder &builder, mlir::Location loc,
Fortran::lower::StatementContext *stmtCtx, llvm::StringRef errMsg,
llvm::ArrayRef<fir::ExtendedValue> args) {
@@ -500,9 +500,11 @@ struct IntrinsicLibrary {
mlir::ArrayRef<mlir::Value> args);
void genGetCommandArgument(mlir::ArrayRef<fir::ExtendedValue> args);
void genGetEnvironmentVariable(llvm::ArrayRef<fir::ExtendedValue>);
+ fir::ExtendedValue genIall(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
/// Lowering for the IAND intrinsic. The IAND intrinsic expects two arguments
/// in the llvm::ArrayRef.
mlir::Value genIand(mlir::Type, llvm::ArrayRef<mlir::Value>);
+ fir::ExtendedValue genIany(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
mlir::Value genIbclr(mlir::Type, llvm::ArrayRef<mlir::Value>);
mlir::Value genIbits(mlir::Type, llvm::ArrayRef<mlir::Value>);
mlir::Value genIbset(mlir::Type, llvm::ArrayRef<mlir::Value>);
@@ -514,6 +516,7 @@ struct IntrinsicLibrary {
mlir::Value genIeor(mlir::Type, llvm::ArrayRef<mlir::Value>);
fir::ExtendedValue genIndex(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
mlir::Value genIor(mlir::Type, llvm::ArrayRef<mlir::Value>);
+ fir::ExtendedValue genIparity(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
mlir::Value genIshft(mlir::Type, llvm::ArrayRef<mlir::Value>);
mlir::Value genIshftc(mlir::Type, llvm::ArrayRef<mlir::Value>);
fir::ExtendedValue genLbound(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
@@ -802,7 +805,19 @@ static constexpr IntrinsicHandler handlers[]{
{"errmsg", asBox, handleDynamicOptional}}},
/*isElemental=*/false},
{"iachar", &I::genIchar},
+ {"iall",
+ &I::genIall,
+ {{{"array", asBox},
+ {"dim", asValue},
+ {"mask", asBox, handleDynamicOptional}}},
+ /*isElemental=*/false},
{"iand", &I::genIand},
+ {"iany",
+ &I::genIany,
+ {{{"array", asBox},
+ {"dim", asValue},
+ {"mask", asBox, handleDynamicOptional}}},
+ /*isElemental=*/false},
{"ibclr", &I::genIbclr},
{"ibits", &I::genIbits},
{"ibset", &I::genIbset},
@@ -820,6 +835,12 @@ static constexpr IntrinsicHandler handlers[]{
{"back", asValue, handleDynamicOptional},
{"kind", asValue}}}},
{"ior", &I::genIor},
+ {"iparity",
+ &I::genIparity,
+ {{{"array", asBox},
+ {"dim", asValue},
+ {"mask", asBox, handleDynamicOptional}}},
+ /*isElemental=*/false},
{"ishft", &I::genIshft},
{"ishftc", &I::genIshftc},
{"lbound",
@@ -3084,6 +3105,15 @@ void IntrinsicLibrary::genGetEnvironmentVariable(
}
}
+// IALL
+fir::ExtendedValue
+IntrinsicLibrary::genIall(mlir::Type resultType,
+ llvm::ArrayRef<fir::ExtendedValue> args) {
+ return genReduction(fir::runtime::genIAll, fir::runtime::genIAllDim,
+ resultType, builder, loc, stmtCtx,
+ "unexpected result for IALL", args);
+}
+
// IAND
mlir::Value IntrinsicLibrary::genIand(mlir::Type resultType,
llvm::ArrayRef<mlir::Value> args) {
@@ -3093,6 +3123,15 @@ mlir::Value IntrinsicLibrary::genIand(mlir::Type resultType,
return builder.create<mlir::arith::AndIOp>(loc, arg0, arg1);
}
+// IANY
+fir::ExtendedValue
+IntrinsicLibrary::genIany(mlir::Type resultType,
+ llvm::ArrayRef<fir::ExtendedValue> args) {
+ return genReduction(fir::runtime::genIAny, fir::runtime::genIAnyDim,
+ resultType, builder, loc, stmtCtx,
+ "unexpected result for IANY", args);
+}
+
// IBCLR
mlir::Value IntrinsicLibrary::genIbclr(mlir::Type resultType,
llvm::ArrayRef<mlir::Value> args) {
@@ -3317,6 +3356,15 @@ mlir::Value IntrinsicLibrary::genIor(mlir::Type resultType,
return builder.create<mlir::arith::OrIOp>(loc, args[0], args[1]);
}
+// IPARITY
+fir::ExtendedValue
+IntrinsicLibrary::genIparity(mlir::Type resultType,
+ llvm::ArrayRef<fir::ExtendedValue> args) {
+ return genReduction(fir::runtime::genIParity, fir::runtime::genIParityDim,
+ resultType, builder, loc, stmtCtx,
+ "unexpected result for IPARITY", args);
+}
+
// ISHFT
mlir::Value IntrinsicLibrary::genIshft(mlir::Type resultType,
llvm::ArrayRef<mlir::Value> args) {
@@ -3824,7 +3872,7 @@ IntrinsicLibrary::genPresent(mlir::Type,
fir::ExtendedValue
IntrinsicLibrary::genProduct(mlir::Type resultType,
llvm::ArrayRef<fir::ExtendedValue> args) {
- return genProdOrSum(fir::runtime::genProduct, fir::runtime::genProductDim,
+ return genReduction(fir::runtime::genProduct, fir::runtime::genProductDim,
resultType, builder, loc, stmtCtx,
"unexpected result for Product", args);
}
@@ -4424,7 +4472,7 @@ IntrinsicLibrary::genSpread(mlir::Type resultType,
fir::ExtendedValue
IntrinsicLibrary::genSum(mlir::Type resultType,
llvm::ArrayRef<fir::ExtendedValue> args) {
- return genProdOrSum(fir::runtime::genSum, fir::runtime::genSumDim, resultType,
+ return genReduction(fir::runtime::genSum, fir::runtime::genSumDim, resultType,
builder, loc, stmtCtx, "unexpected result for Sum", args);
}
diff --git a/flang/lib/Optimizer/Builder/Runtime/Reduction.cpp b/flang/lib/Optimizer/Builder/Runtime/Reduction.cpp
index 0fa035246b4cf..dd19b6589c06a 100644
--- a/flang/lib/Optimizer/Builder/Runtime/Reduction.cpp
+++ b/flang/lib/Optimizer/Builder/Runtime/Reduction.cpp
@@ -17,6 +17,10 @@
using namespace Fortran::runtime;
+#define STRINGIFY(S) #S
+#define JOIN2(A, B) A##B
+#define JOIN3(A, B, C) A##B##C
+
/// Placeholder for real*10 version of Maxval Intrinsic
struct ForcedMaxvalReal10 {
static constexpr const char *name = ExpandAndQuoteKey(RTNAME(MaxvalReal10));
@@ -368,6 +372,54 @@ struct ForcedSumComplex16 {
}
};
+/// Placeholder for integer(16) version of IAll Intrinsic
+struct ForcedIAll16 {
+ static constexpr const char *name = EXPAND_AND_QUOTE_KEY(IAll16);
+ static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
+ return [](mlir::MLIRContext *ctx) {
+ auto ty = mlir::IntegerType::get(ctx, 128);
+ auto boxTy =
+ fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
+ auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
+ auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
+ return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy},
+ {ty});
+ };
+ }
+};
+
+/// Placeholder for integer(16) version of IAny Intrinsic
+struct ForcedIAny16 {
+ static constexpr const char *name = EXPAND_AND_QUOTE_KEY(IAny16);
+ static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
+ return [](mlir::MLIRContext *ctx) {
+ auto ty = mlir::IntegerType::get(ctx, 128);
+ auto boxTy =
+ fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
+ auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
+ auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
+ return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy},
+ {ty});
+ };
+ }
+};
+
+/// Placeholder for integer(16) version of IParity Intrinsic
+struct ForcedIParity16 {
+ static constexpr const char *name = EXPAND_AND_QUOTE_KEY(IParity16);
+ static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
+ return [](mlir::MLIRContext *ctx) {
+ auto ty = mlir::IntegerType::get(ctx, 128);
+ auto boxTy =
+ fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
+ auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
+ auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
+ return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy},
+ {ty});
+ };
+ }
+};
+
/// Generate call to specialized runtime function that takes a mask and
/// dim argument. The All, Any, and Count intrinsics use this pattern.
template <typename FN>
@@ -942,3 +994,78 @@ mlir::Value fir::runtime::genSum(fir::FirOpBuilder &builder, mlir::Location loc,
return builder.create<fir::CallOp>(loc, func, args).getResult(0);
}
+
+// The IAll, IAny and IParity intrinsics have essentially the same
+// implementation. This macro will generate the function body given the
+// instrinsic name.
+#define GEN_IALL_IANY_IPARITY(F) \
+ mlir::Value fir::runtime::JOIN2(gen, F)( \
+ fir::FirOpBuilder & builder, mlir::Location loc, mlir::Value arrayBox, \
+ mlir::Value maskBox, mlir::Value resultBox) { \
+ mlir::func::FuncOp func; \
+ auto ty = arrayBox.getType(); \
+ auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty); \
+ auto eleTy = arrTy.cast<fir::SequenceType>().getEleTy(); \
+ auto dim = builder.createIntegerConstant(loc, builder.getIndexType(), 0); \
+ \
+ if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(1))) \
+ func = fir::runtime::getRuntimeFunc<mkRTKey(JOIN2(F, 1))>(loc, builder); \
+ else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(2))) \
+ func = fir::runtime::getRuntimeFunc<mkRTKey(JOIN2(F, 2))>(loc, builder); \
+ else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(4))) \
+ func = fir::runtime::getRuntimeFunc<mkRTKey(JOIN2(F, 4))>(loc, builder); \
+ else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(8))) \
+ func = fir::runtime::getRuntimeFunc<mkRTKey(JOIN2(F, 8))>(loc, builder); \
+ else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(16))) \
+ func = fir::runtime::getRuntimeFunc<JOIN3(Forced, F, 16)>(loc, builder); \
+ else \
+ fir::emitFatalError(loc, "invalid type in " STRINGIFY(F)); \
+ \
+ auto fTy = func.getFunctionType(); \
+ auto sourceFile = fir::factory::locationToFilename(builder, loc); \
+ auto sourceLine = \
+ fir::factory::locationToLineNo(builder, loc, fTy.getInput(2)); \
+ auto args = fir::runtime::createArguments( \
+ builder, loc, fTy, arrayBox, sourceFile, sourceLine, dim, maskBox); \
+ \
+ return builder.create<fir::CallOp>(loc, func, args).getResult(0); \
+ }
+
+/// Generate call to `IAllDim` intrinsic runtime routine. This is the version
+/// that handles any rank array with the dim argument specified.
+void fir::runtime::genIAllDim(fir::FirOpBuilder &builder, mlir::Location loc,
+ mlir::Value resultBox, mlir::Value arrayBox,
+ mlir::Value dim, mlir::Value maskBox) {
+ auto func = fir::runtime::getRuntimeFunc<mkRTKey(IAllDim)>(loc, builder);
+ genReduction3Args(func, builder, loc, resultBox, arrayBox, dim, maskBox);
+}
+
+/// Generate call to `IAll` intrinsic runtime routine. This is the version
+/// that does not take a dim argument.
+GEN_IALL_IANY_IPARITY(IAll)
+
+/// Generate call to `IAnyDim` intrinsic runtime routine. This is the version
+/// that handles any rank array with the dim argument specified.
+void fir::runtime::genIAnyDim(fir::FirOpBuilder &builder, mlir::Location loc,
+ mlir::Value resultBox, mlir::Value arrayBox,
+ mlir::Value dim, mlir::Value maskBox) {
+ auto func = fir::runtime::getRuntimeFunc<mkRTKey(IAnyDim)>(loc, builder);
+ genReduction3Args(func, builder, loc, resultBox, arrayBox, dim, maskBox);
+}
+
+/// Generate call to `IAny` intrinsic runtime routine. This is the version
+/// that does not take a dim argument.
+GEN_IALL_IANY_IPARITY(IAny)
+
+/// Generate call to `IParityDim` intrinsic runtime routine. This is the version
+/// that handles any rank array with the dim argument specified.
+void fir::runtime::genIParityDim(fir::FirOpBuilder &builder, mlir::Location loc,
+ mlir::Value resultBox, mlir::Value arrayBox,
+ mlir::Value dim, mlir::Value maskBox) {
+ auto func = fir::runtime::getRuntimeFunc<mkRTKey(IParityDim)>(loc, builder);
+ genReduction3Args(func, builder, loc, resultBox, arrayBox, dim, maskBox);
+}
+
+/// Generate call to `IParity` intrinsic runtime routine. This is the version
+/// that does not take a dim argument.
+GEN_IALL_IANY_IPARITY(IParity)
diff --git a/flang/test/Lower/Intrinsics/iall.f90 b/flang/test/Lower/Intrinsics/iall.f90
new file mode 100644
index 0000000000000..5688768fc3db1
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/iall.f90
@@ -0,0 +1,156 @@
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+
+! CHECK-LABEL: func @_QPiall_test_1(
+! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?xi8>>{{.*}}) -> i8 {
+integer(1) function iall_test_1(a)
+integer(1) :: a(:)
+! CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index
+! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box<i1>
+! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?xi8>>) -> !fir.box<none>
+! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32
+! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box<i1>) -> !fir.box<none>
+iall_test_1 = iall(a)
+! CHECK: %{{.*}} = fir.call @_FortranAIAll1(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i8
+end function
+
+! CHECK-LABEL: func @_QPiall_test_2(
+! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?xi16>>{{.*}}) -> i16 {
+integer(2) function iall_test_2(a)
+integer(2) :: a(:)
+! CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index
+! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box<i1>
+! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?xi16>>) -> !fir.box<none>
+! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32
+! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box<i1>) -> !fir.box<none>
+iall_test_2 = iall(a)
+! CHECK: %{{.*}} = fir.call @_FortranAIAll2(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i16
+end function
+
+! CHECK-LABEL: func @_QPiall_test_4(
+! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?xi32>>{{.*}}) -> i32 {
+integer function iall_test_4(a)
+integer :: a(:)
+! CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index
+! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box<i1>
+! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?xi32>>) -> !fir.box<none>
+! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32
+! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box<i1>) -> !fir.box<none>
+iall_test_4 = iall(a)
+! CHECK: %{{.*}} = fir.call @_FortranAIAll4(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i32
+end function
+
+! CHECK-LABEL: func @_QPiall_test_8(
+! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?xi64>>{{.*}}) -> i64 {
+integer(8) function iall_test_8(a)
+integer(8) :: a(:)
+! CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index
+! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box<i1>
+! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?xi64>>) -> !fir.box<none>
+! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32
+! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box<i1>) -> !fir.box<none>
+iall_test_8 = iall(a)
+! CHECK: %{{.*}} = fir.call @_FortranAIAll8(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i64
+end function
+
+! CHECK-LABEL: func @_QPiall_test_16(
+! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?xi128>>{{.*}}) -> i128 {
+integer(16) function iall_test_16(a)
+integer(16) :: a(:)
+! CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index
+! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box<i1>
+! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?xi128>>) -> !fir.box<none>
+! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32
+! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box<i1>) -> !fir.box<none>
+iall_test_16 = iall(a)
+! CHECK: %{{.*}} = fir.call @_FortranAIAll16(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i128
+end function
+
+! CHECK-LABEL: func @_QPiall_test2(
+! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?x?xi32>>{{.*}}, %[[arg1:.*]]: !fir.box<!fir.array<?xi32>>{{.*}}) {
+subroutine iall_test2(a,r)
+integer :: a(:,:)
+integer :: r(:)
+! CHECK-DAG: %[[c2_i32:.*]] = arith.constant 2 : i32
+! CHECK-DAG: %[[a0:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>>
+! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box<i1>
+! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a0]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<none>>
+! CHECK-DAG: %[[a7:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?x?xi32>>) -> !fir.box<none>
+! CHECK-DAG: %[[a9:.*]] = fir.convert %[[a1]] : (!fir.box<i1>) -> !fir.box<none>
+r = iall(a,dim=2)
+! CHECK: %{{.*}} = fir.call @_FortranAIAllDim(%[[a6]], %[[a7]], %[[c2_i32]], %{{.*}}, %{{.*}}, %[[a9]]) : (!fir.ref<!fir.box<none>>, !fir.box<none>, i32, !fir.ref<i8>, i32, !fir.box<none>) -> none
+! CHECK-DAG: %[[a11:.*]] = fir.load %[[a0]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
+! CHECK-DAG: %[[a13:.*]] = fir.box_addr %[[a11]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
+! CHECK-DAG: fir.freemem %[[a13]]
+end subroutine
+
+! CHECK-LABEL: func @_QPiall_test_optional(
+! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?x!fir.logical<4>>>
+integer function iall_test_optional(mask, x)
+integer :: x(:)
+logical, optional :: mask(:)
+iall_test_optional = iall(x, mask=mask)
+! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_0]] : (!fir.box<!fir.array<?x!fir.logical<4>>>) -> !fir.box<none>
+! CHECK: fir.call @_FortranAIAll4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_9]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i32
+end function
+
+! CHECK-LABEL: func @_QPiall_test_optional_2(
+! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>>
+integer function iall_test_optional_2(mask, x)
+integer :: x(:)
+logical, pointer :: mask(:)
+iall_test_optional_2 = iall(x, mask=mask)
+! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>>
+! CHECK: %[[VAL_5:.*]] = fir.box_addr %[[VAL_4]] : (!fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>) -> !fir.ptr<!fir.array<?x!fir.logical<4>>>
+! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_5]] : (!fir.ptr<!fir.array<?x!fir.logical<4>>>) -> i64
+! CHECK: %[[VAL_7:.*]] = arith.constant 0 : i64
+! CHECK: %[[VAL_8:.*]] = arith.cmpi ne, %[[VAL_6]], %[[VAL_7]] : i64
+! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>>
+! CHECK: %[[VAL_10:.*]] = fir.absent !fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>
+! CHECK: %[[VAL_11:.*]] = arith.select %[[VAL_8]], %[[VAL_9]], %[[VAL_10]] : !fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>
+! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_11]] : (!fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>) -> !fir.box<none>
+! CHECK: fir.call @_FortranAIAll4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_18]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i32
+end function
+
+! CHECK-LABEL: func @_QPiall_test_optional_3(
+! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<10x!fir.logical<4>>>
+integer function iall_test_optional_3(mask, x)
+integer :: x(:)
+logical, optional :: mask(10)
+iall_test_optional_3 = iall(x, mask=mask)
+! CHECK: %[[VAL_2:.*]] = arith.constant 10 : index
+! CHECK: %[[VAL_5:.*]] = fir.is_present %[[VAL_0]] : (!fir.ref<!fir.array<10x!fir.logical<4>>>) -> i1
+! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1>
+! CHECK: %[[VAL_7:.*]] = fir.embox %[[VAL_0]](%[[VAL_6]]) : (!fir.ref<!fir.array<10x!fir.logical<4>>>, !fir.shape<1>) -> !fir.box<!fir.array<10x!fir.logical<4>>>
+! CHECK: %[[VAL_8:.*]] = fir.absent !fir.box<!fir.array<10x!fir.logical<4>>>
+! CHECK: %[[VAL_9:.*]] = arith.select %[[VAL_5]], %[[VAL_7]], %[[VAL_8]] : !fir.box<!fir.array<10x!fir.logical<4>>>
+! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_9]] : (!fir.box<!fir.array<10x!fir.logical<4>>>) -> !fir.box<none>
+! CHECK: fir.call @_FortranAIAll4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_18]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i32
+end function
+
+! CHECK-LABEL: func @_QPiall_test_optional_4(
+integer function iall_test_optional_4(x, use_mask)
+! Test that local allocatable tracked in local variables
+! are dealt as optional argument correctly.
+integer :: x(:)
+logical :: use_mask
+logical, allocatable :: mask(:)
+if (use_mask) then
+ allocate(mask(size(x, 1)))
+ call set_mask(mask)
+ ! CHECK: fir.call @_QPset_mask
+end if
+iall_test_optional_4 = iall(x, mask=mask)
+! CHECK: %[[VAL_20:.*]] = fir.load %[[VAL_3:.*]] : !fir.ref<!fir.heap<!fir.array<?x!fir.logical<4>>>>
+! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (!fir.heap<!fir.array<?x!fir.logical<4>>>) -> i64
+! CHECK: %[[VAL_22:.*]] = arith.constant 0 : i64
+! CHECK: %[[VAL_23:.*]] = arith.cmpi ne, %[[VAL_21]], %[[VAL_22]] : i64
+! CHECK: %[[VAL_24:.*]] = fir.load %[[VAL_4:.*]] : !fir.ref<index>
+! CHECK: %[[VAL_25:.*]] = fir.load %[[VAL_5:.*]] : !fir.ref<index>
+! CHECK: %[[VAL_26:.*]] = fir.load %[[VAL_3]] : !fir.ref<!fir.heap<!fir.array<?x!fir.logical<4>>>>
+! CHECK: %[[VAL_27:.*]] = fir.shape_shift %[[VAL_24]], %[[VAL_25]] : (index, index) -> !fir.shapeshift<1>
+! CHECK: %[[VAL_28:.*]] = fir.embox %[[VAL_26]](%[[VAL_27]]) : (!fir.heap<!fir.array<?x!fir.logical<4>>>, !fir.shapeshift<1>) -> !fir.box<!fir.array<?x!fir.logical<4>>>
+! CHECK: %[[VAL_29:.*]] = fir.absent !fir.box<!fir.array<?x!fir.logical<4>>>
+! CHECK: %[[VAL_30:.*]] = arith.select %[[VAL_23]], %[[VAL_28]], %[[VAL_29]] : !fir.box<!fir.array<?x!fir.logical<4>>>
+! CHECK: %[[VAL_37:.*]] = fir.convert %[[VAL_30]] : (!fir.box<!fir.array<?x!fir.logical<4>>>) -> !fir.box<none>
+! CHECK: fir.call @_FortranAIAll4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_37]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i32
+end function
diff --git a/flang/test/Lower/Intrinsics/iany.f90 b/flang/test/Lower/Intrinsics/iany.f90
new file mode 100644
index 0000000000000..90518c3b3ca7a
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/iany.f90
@@ -0,0 +1,156 @@
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+
+! CHECK-LABEL: func @_QPiany_test_1(
+! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?xi8>>{{.*}}) -> i8 {
+integer(1) function iany_test_1(a)
+integer(1) :: a(:)
+! CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index
+! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box<i1>
+! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?xi8>>) -> !fir.box<none>
+! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32
+! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box<i1>) -> !fir.box<none>
+iany_test_1 = iany(a)
+! CHECK: %{{.*}} = fir.call @_FortranAIAny1(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i8
+end function
+
+! CHECK-LABEL: func @_QPiany_test_2(
+! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?xi16>>{{.*}}) -> i16 {
+integer(2) function iany_test_2(a)
+integer(2) :: a(:)
+! CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index
+! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box<i1>
+! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?xi16>>) -> !fir.box<none>
+! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32
+! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box<i1>) -> !fir.box<none>
+iany_test_2 = iany(a)
+! CHECK: %{{.*}} = fir.call @_FortranAIAny2(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i16
+end function
+
+! CHECK-LABEL: func @_QPiany_test_4(
+! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?xi32>>{{.*}}) -> i32 {
+integer function iany_test_4(a)
+integer :: a(:)
+! CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index
+! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box<i1>
+! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?xi32>>) -> !fir.box<none>
+! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32
+! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box<i1>) -> !fir.box<none>
+iany_test_4 = iany(a)
+! CHECK: %{{.*}} = fir.call @_FortranAIAny4(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i32
+end function
+
+! CHECK-LABEL: func @_QPiany_test_8(
+! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?xi64>>{{.*}}) -> i64 {
+integer(8) function iany_test_8(a)
+integer(8) :: a(:)
+! CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index
+! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box<i1>
+! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?xi64>>) -> !fir.box<none>
+! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32
+! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box<i1>) -> !fir.box<none>
+iany_test_8 = iany(a)
+! CHECK: %{{.*}} = fir.call @_FortranAIAny8(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i64
+end function
+
+! CHECK-LABEL: func @_QPiany_test_16(
+! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?xi128>>{{.*}}) -> i128 {
+integer(16) function iany_test_16(a)
+integer(16) :: a(:)
+! CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index
+! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box<i1>
+! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?xi128>>) -> !fir.box<none>
+! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32
+! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box<i1>) -> !fir.box<none>
+iany_test_16 = iany(a)
+! CHECK: %{{.*}} = fir.call @_FortranAIAny16(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i128
+end function
+
+! CHECK-LABEL: func @_QPiany_test2(
+! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?x?xi32>>{{.*}}, %[[arg1:.*]]: !fir.box<!fir.array<?xi32>>{{.*}}) {
+subroutine iany_test2(a,r)
+integer :: a(:,:)
+integer :: r(:)
+! CHECK-DAG: %[[c2_i32:.*]] = arith.constant 2 : i32
+! CHECK-DAG: %[[a0:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>>
+! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box<i1>
+! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a0]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<none>>
+! CHECK-DAG: %[[a7:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?x?xi32>>) -> !fir.box<none>
+! CHECK-DAG: %[[a9:.*]] = fir.convert %[[a1]] : (!fir.box<i1>) -> !fir.box<none>
+r = iany(a,dim=2)
+! CHECK: %{{.*}} = fir.call @_FortranAIAnyDim(%[[a6]], %[[a7]], %[[c2_i32]], %{{.*}}, %{{.*}}, %[[a9]]) : (!fir.ref<!fir.box<none>>, !fir.box<none>, i32, !fir.ref<i8>, i32, !fir.box<none>) -> none
+! CHECK-DAG: %[[a11:.*]] = fir.load %[[a0]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
+! CHECK-DAG: %[[a13:.*]] = fir.box_addr %[[a11]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
+! CHECK-DAG: fir.freemem %[[a13]]
+end subroutine
+
+! CHECK-LABEL: func @_QPiany_test_optional(
+! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?x!fir.logical<4>>>
+integer function iany_test_optional(mask, x)
+integer :: x(:)
+logical, optional :: mask(:)
+iany_test_optional = iany(x, mask=mask)
+! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_0]] : (!fir.box<!fir.array<?x!fir.logical<4>>>) -> !fir.box<none>
+! CHECK: fir.call @_FortranAIAny4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_9]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i32
+end function
+
+! CHECK-LABEL: func @_QPiany_test_optional_2(
+! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>>
+integer function iany_test_optional_2(mask, x)
+integer :: x(:)
+logical, pointer :: mask(:)
+iany_test_optional_2 = iany(x, mask=mask)
+! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>>
+! CHECK: %[[VAL_5:.*]] = fir.box_addr %[[VAL_4]] : (!fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>) -> !fir.ptr<!fir.array<?x!fir.logical<4>>>
+! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_5]] : (!fir.ptr<!fir.array<?x!fir.logical<4>>>) -> i64
+! CHECK: %[[VAL_7:.*]] = arith.constant 0 : i64
+! CHECK: %[[VAL_8:.*]] = arith.cmpi ne, %[[VAL_6]], %[[VAL_7]] : i64
+! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>>
+! CHECK: %[[VAL_10:.*]] = fir.absent !fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>
+! CHECK: %[[VAL_11:.*]] = arith.select %[[VAL_8]], %[[VAL_9]], %[[VAL_10]] : !fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>
+! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_11]] : (!fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>) -> !fir.box<none>
+! CHECK: fir.call @_FortranAIAny4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_18]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i32
+end function
+
+! CHECK-LABEL: func @_QPiany_test_optional_3(
+! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<10x!fir.logical<4>>>
+integer function iany_test_optional_3(mask, x)
+integer :: x(:)
+logical, optional :: mask(10)
+iany_test_optional_3 = iany(x, mask=mask)
+! CHECK: %[[VAL_2:.*]] = arith.constant 10 : index
+! CHECK: %[[VAL_5:.*]] = fir.is_present %[[VAL_0]] : (!fir.ref<!fir.array<10x!fir.logical<4>>>) -> i1
+! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1>
+! CHECK: %[[VAL_7:.*]] = fir.embox %[[VAL_0]](%[[VAL_6]]) : (!fir.ref<!fir.array<10x!fir.logical<4>>>, !fir.shape<1>) -> !fir.box<!fir.array<10x!fir.logical<4>>>
+! CHECK: %[[VAL_8:.*]] = fir.absent !fir.box<!fir.array<10x!fir.logical<4>>>
+! CHECK: %[[VAL_9:.*]] = arith.select %[[VAL_5]], %[[VAL_7]], %[[VAL_8]] : !fir.box<!fir.array<10x!fir.logical<4>>>
+! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_9]] : (!fir.box<!fir.array<10x!fir.logical<4>>>) -> !fir.box<none>
+! CHECK: fir.call @_FortranAIAny4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_18]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i32
+end function
+
+! CHECK-LABEL: func @_QPiany_test_optional_4(
+integer function iany_test_optional_4(x, use_mask)
+! Test that local allocatable tracked in local variables
+! are dealt as optional argument correctly.
+integer :: x(:)
+logical :: use_mask
+logical, allocatable :: mask(:)
+if (use_mask) then
+ allocate(mask(size(x, 1)))
+ call set_mask(mask)
+ ! CHECK: fir.call @_QPset_mask
+end if
+iany_test_optional_4 = iany(x, mask=mask)
+! CHECK: %[[VAL_20:.*]] = fir.load %[[VAL_3:.*]] : !fir.ref<!fir.heap<!fir.array<?x!fir.logical<4>>>>
+! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (!fir.heap<!fir.array<?x!fir.logical<4>>>) -> i64
+! CHECK: %[[VAL_22:.*]] = arith.constant 0 : i64
+! CHECK: %[[VAL_23:.*]] = arith.cmpi ne, %[[VAL_21]], %[[VAL_22]] : i64
+! CHECK: %[[VAL_24:.*]] = fir.load %[[VAL_4:.*]] : !fir.ref<index>
+! CHECK: %[[VAL_25:.*]] = fir.load %[[VAL_5:.*]] : !fir.ref<index>
+! CHECK: %[[VAL_26:.*]] = fir.load %[[VAL_3]] : !fir.ref<!fir.heap<!fir.array<?x!fir.logical<4>>>>
+! CHECK: %[[VAL_27:.*]] = fir.shape_shift %[[VAL_24]], %[[VAL_25]] : (index, index) -> !fir.shapeshift<1>
+! CHECK: %[[VAL_28:.*]] = fir.embox %[[VAL_26]](%[[VAL_27]]) : (!fir.heap<!fir.array<?x!fir.logical<4>>>, !fir.shapeshift<1>) -> !fir.box<!fir.array<?x!fir.logical<4>>>
+! CHECK: %[[VAL_29:.*]] = fir.absent !fir.box<!fir.array<?x!fir.logical<4>>>
+! CHECK: %[[VAL_30:.*]] = arith.select %[[VAL_23]], %[[VAL_28]], %[[VAL_29]] : !fir.box<!fir.array<?x!fir.logical<4>>>
+! CHECK: %[[VAL_37:.*]] = fir.convert %[[VAL_30]] : (!fir.box<!fir.array<?x!fir.logical<4>>>) -> !fir.box<none>
+! CHECK: fir.call @_FortranAIAny4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_37]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i32
+end function
diff --git a/flang/test/Lower/Intrinsics/iparity.f90 b/flang/test/Lower/Intrinsics/iparity.f90
new file mode 100644
index 0000000000000..b995725bb2282
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/iparity.f90
@@ -0,0 +1,156 @@
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+
+! CHECK-LABEL: func @_QPiparity_test_1(
+! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?xi8>>{{.*}}) -> i8 {
+integer(1) function iparity_test_1(a)
+integer(1) :: a(:)
+! CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index
+! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box<i1>
+! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?xi8>>) -> !fir.box<none>
+! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32
+! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box<i1>) -> !fir.box<none>
+iparity_test_1 = iparity(a)
+! CHECK: %{{.*}} = fir.call @_FortranAIParity1(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i8
+end function
+
+! CHECK-LABEL: func @_QPiparity_test_2(
+! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?xi16>>{{.*}}) -> i16 {
+integer(2) function iparity_test_2(a)
+integer(2) :: a(:)
+! CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index
+! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box<i1>
+! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?xi16>>) -> !fir.box<none>
+! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32
+! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box<i1>) -> !fir.box<none>
+iparity_test_2 = iparity(a)
+! CHECK: %{{.*}} = fir.call @_FortranAIParity2(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i16
+end function
+
+! CHECK-LABEL: func @_QPiparity_test_4(
+! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?xi32>>{{.*}}) -> i32 {
+integer function iparity_test_4(a)
+integer :: a(:)
+! CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index
+! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box<i1>
+! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?xi32>>) -> !fir.box<none>
+! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32
+! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box<i1>) -> !fir.box<none>
+iparity_test_4 = iparity(a)
+! CHECK: %{{.*}} = fir.call @_FortranAIParity4(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i32
+end function
+
+! CHECK-LABEL: func @_QPiparity_test_8(
+! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?xi64>>{{.*}}) -> i64 {
+integer(8) function iparity_test_8(a)
+integer(8) :: a(:)
+! CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index
+! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box<i1>
+! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?xi64>>) -> !fir.box<none>
+! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32
+! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box<i1>) -> !fir.box<none>
+iparity_test_8 = iparity(a)
+! CHECK: %{{.*}} = fir.call @_FortranAIParity8(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i64
+end function
+
+! CHECK-LABEL: func @_QPiparity_test_16(
+! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?xi128>>{{.*}}) -> i128 {
+integer(16) function iparity_test_16(a)
+integer(16) :: a(:)
+! CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index
+! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box<i1>
+! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?xi128>>) -> !fir.box<none>
+! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32
+! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box<i1>) -> !fir.box<none>
+iparity_test_16 = iparity(a)
+! CHECK: %{{.*}} = fir.call @_FortranAIParity16(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i128
+end function
+
+! CHECK-LABEL: func @_QPiparity_test2(
+! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?x?xi32>>{{.*}}, %[[arg1:.*]]: !fir.box<!fir.array<?xi32>>{{.*}}) {
+subroutine iparity_test2(a,r)
+integer :: a(:,:)
+integer :: r(:)
+! CHECK-DAG: %[[c2_i32:.*]] = arith.constant 2 : i32
+! CHECK-DAG: %[[a0:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>>
+! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box<i1>
+! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a0]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<none>>
+! CHECK-DAG: %[[a7:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?x?xi32>>) -> !fir.box<none>
+! CHECK-DAG: %[[a9:.*]] = fir.convert %[[a1]] : (!fir.box<i1>) -> !fir.box<none>
+r = iparity(a,dim=2)
+! CHECK: %{{.*}} = fir.call @_FortranAIParityDim(%[[a6]], %[[a7]], %[[c2_i32]], %{{.*}}, %{{.*}}, %[[a9]]) : (!fir.ref<!fir.box<none>>, !fir.box<none>, i32, !fir.ref<i8>, i32, !fir.box<none>) -> none
+! CHECK-DAG: %[[a11:.*]] = fir.load %[[a0]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
+! CHECK-DAG: %[[a13:.*]] = fir.box_addr %[[a11]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
+! CHECK-DAG: fir.freemem %[[a13]]
+end subroutine
+
+! CHECK-LABEL: func @_QPiparity_test_optional(
+! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?x!fir.logical<4>>>
+integer function iparity_test_optional(mask, x)
+integer :: x(:)
+logical, optional :: mask(:)
+iparity_test_optional = iparity(x, mask=mask)
+! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_0]] : (!fir.box<!fir.array<?x!fir.logical<4>>>) -> !fir.box<none>
+! CHECK: fir.call @_FortranAIParity4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_9]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i32
+end function
+
+! CHECK-LABEL: func @_QPiparity_test_optional_2(
+! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>>
+integer function iparity_test_optional_2(mask, x)
+integer :: x(:)
+logical, pointer :: mask(:)
+iparity_test_optional_2 = iparity(x, mask=mask)
+! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>>
+! CHECK: %[[VAL_5:.*]] = fir.box_addr %[[VAL_4]] : (!fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>) -> !fir.ptr<!fir.array<?x!fir.logical<4>>>
+! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_5]] : (!fir.ptr<!fir.array<?x!fir.logical<4>>>) -> i64
+! CHECK: %[[VAL_7:.*]] = arith.constant 0 : i64
+! CHECK: %[[VAL_8:.*]] = arith.cmpi ne, %[[VAL_6]], %[[VAL_7]] : i64
+! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>>
+! CHECK: %[[VAL_10:.*]] = fir.absent !fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>
+! CHECK: %[[VAL_11:.*]] = arith.select %[[VAL_8]], %[[VAL_9]], %[[VAL_10]] : !fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>
+! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_11]] : (!fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>) -> !fir.box<none>
+! CHECK: fir.call @_FortranAIParity4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_18]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i32
+end function
+
+! CHECK-LABEL: func @_QPiparity_test_optional_3(
+! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<10x!fir.logical<4>>>
+integer function iparity_test_optional_3(mask, x)
+integer :: x(:)
+logical, optional :: mask(10)
+iparity_test_optional_3 = iparity(x, mask=mask)
+! CHECK: %[[VAL_2:.*]] = arith.constant 10 : index
+! CHECK: %[[VAL_5:.*]] = fir.is_present %[[VAL_0]] : (!fir.ref<!fir.array<10x!fir.logical<4>>>) -> i1
+! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1>
+! CHECK: %[[VAL_7:.*]] = fir.embox %[[VAL_0]](%[[VAL_6]]) : (!fir.ref<!fir.array<10x!fir.logical<4>>>, !fir.shape<1>) -> !fir.box<!fir.array<10x!fir.logical<4>>>
+! CHECK: %[[VAL_8:.*]] = fir.absent !fir.box<!fir.array<10x!fir.logical<4>>>
+! CHECK: %[[VAL_9:.*]] = arith.select %[[VAL_5]], %[[VAL_7]], %[[VAL_8]] : !fir.box<!fir.array<10x!fir.logical<4>>>
+! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_9]] : (!fir.box<!fir.array<10x!fir.logical<4>>>) -> !fir.box<none>
+! CHECK: fir.call @_FortranAIParity4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_18]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i32
+end function
+
+! CHECK-LABEL: func @_QPiparity_test_optional_4(
+integer function iparity_test_optional_4(x, use_mask)
+! Test that local allocatable tracked in local variables
+! are dealt as optional argument correctly.
+integer :: x(:)
+logical :: use_mask
+logical, allocatable :: mask(:)
+if (use_mask) then
+ allocate(mask(size(x, 1)))
+ call set_mask(mask)
+ ! CHECK: fir.call @_QPset_mask
+end if
+iparity_test_optional_4 = iparity(x, mask=mask)
+! CHECK: %[[VAL_20:.*]] = fir.load %[[VAL_3:.*]] : !fir.ref<!fir.heap<!fir.array<?x!fir.logical<4>>>>
+! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (!fir.heap<!fir.array<?x!fir.logical<4>>>) -> i64
+! CHECK: %[[VAL_22:.*]] = arith.constant 0 : i64
+! CHECK: %[[VAL_23:.*]] = arith.cmpi ne, %[[VAL_21]], %[[VAL_22]] : i64
+! CHECK: %[[VAL_24:.*]] = fir.load %[[VAL_4:.*]] : !fir.ref<index>
+! CHECK: %[[VAL_25:.*]] = fir.load %[[VAL_5:.*]] : !fir.ref<index>
+! CHECK: %[[VAL_26:.*]] = fir.load %[[VAL_3]] : !fir.ref<!fir.heap<!fir.array<?x!fir.logical<4>>>>
+! CHECK: %[[VAL_27:.*]] = fir.shape_shift %[[VAL_24]], %[[VAL_25]] : (index, index) -> !fir.shapeshift<1>
+! CHECK: %[[VAL_28:.*]] = fir.embox %[[VAL_26]](%[[VAL_27]]) : (!fir.heap<!fir.array<?x!fir.logical<4>>>, !fir.shapeshift<1>) -> !fir.box<!fir.array<?x!fir.logical<4>>>
+! CHECK: %[[VAL_29:.*]] = fir.absent !fir.box<!fir.array<?x!fir.logical<4>>>
+! CHECK: %[[VAL_30:.*]] = arith.select %[[VAL_23]], %[[VAL_28]], %[[VAL_29]] : !fir.box<!fir.array<?x!fir.logical<4>>>
+! CHECK: %[[VAL_37:.*]] = fir.convert %[[VAL_30]] : (!fir.box<!fir.array<?x!fir.logical<4>>>) -> !fir.box<none>
+! CHECK: fir.call @_FortranAIParity4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_37]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i32
+end function
More information about the flang-commits
mailing list