[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