[flang-commits] [flang] d43a2f0 - [flang] Lower F08 FINDLOC intrinsic

Tarun Prabhu via flang-commits flang-commits at lists.llvm.org
Tue Nov 29 09:22:40 PST 2022


Author: Tarun Prabhu
Date: 2022-11-29T10:18:38-07:00
New Revision: d43a2f09de518248631d4baa9f676c5de8a058a5

URL: https://github.com/llvm/llvm-project/commit/d43a2f09de518248631d4baa9f676c5de8a058a5
DIFF: https://github.com/llvm/llvm-project/commit/d43a2f09de518248631d4baa9f676c5de8a058a5.diff

LOG: [flang] Lower F08 FINDLOC intrinsic

The implementation follows the patterns established by the lowering of other
similar intrinsics.

In addition to the code for lowering, the DoTotalReduction template had to be
fixed to correctly break when signaled to do so by the accumulator function.

Differential Revision: https://reviews.llvm.org/D138140

Added: 
    flang/test/Lower/Intrinsics/findloc.f90

Modified: 
    flang/include/flang/Optimizer/Builder/Runtime/Reduction.h
    flang/lib/Lower/IntrinsicCall.cpp
    flang/lib/Optimizer/Builder/Runtime/Reduction.cpp
    flang/runtime/reduction-templates.h

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Optimizer/Builder/Runtime/Reduction.h b/flang/include/flang/Optimizer/Builder/Runtime/Reduction.h
index 185dff89c8150..8faf568d500d9 100644
--- a/flang/include/flang/Optimizer/Builder/Runtime/Reduction.h
+++ b/flang/include/flang/Optimizer/Builder/Runtime/Reduction.h
@@ -75,6 +75,19 @@ mlir::Value genDotProduct(fir::FirOpBuilder &builder, mlir::Location loc,
                           mlir::Value vectorABox, mlir::Value vectorBBox,
                           mlir::Value resultBox);
 
+/// Generate call to `Findloc` intrinsic runtime routine. This is the version
+/// that does not take a dim argument.
+void genFindloc(fir::FirOpBuilder &builder, mlir::Location loc,
+                mlir::Value resultBox, mlir::Value arrayBox, mlir::Value val,
+                mlir::Value maskBox, mlir::Value kind, mlir::Value back);
+
+/// Generate call to `FindlocDim` intrinsic runtime routine. This is the version
+/// that takes a dim argument.
+void genFindlocDim(fir::FirOpBuilder &builder, mlir::Location loc,
+                   mlir::Value resultBox, mlir::Value arrayBox, mlir::Value val,
+                   mlir::Value dim, mlir::Value maskBox, mlir::Value kind,
+                   mlir::Value back);
+
 /// Generate call to `Maxloc` intrinsic runtime routine. This is the version
 /// that does not take a dim argument.
 void genMaxloc(fir::FirOpBuilder &builder, mlir::Location loc,

diff  --git a/flang/lib/Lower/IntrinsicCall.cpp b/flang/lib/Lower/IntrinsicCall.cpp
index ab930e32229fe..76ee6a9a37100 100644
--- a/flang/lib/Lower/IntrinsicCall.cpp
+++ b/flang/lib/Lower/IntrinsicCall.cpp
@@ -516,6 +516,7 @@ struct IntrinsicLibrary {
   mlir::Value genIbits(mlir::Type, llvm::ArrayRef<mlir::Value>);
   mlir::Value genIbset(mlir::Type, llvm::ArrayRef<mlir::Value>);
   fir::ExtendedValue genIchar(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
+  fir::ExtendedValue genFindloc(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
   mlir::Value genIeeeIsFinite(mlir::Type, llvm::ArrayRef<mlir::Value>);
   template <mlir::arith::CmpIPredicate pred>
   fir::ExtendedValue genIeeeTypeCompare(mlir::Type,
@@ -801,6 +802,15 @@ static constexpr IntrinsicHandler handlers[]{
      {{{"status", asValue, handleDynamicOptional}}},
      /*isElemental=*/false},
     {"exponent", &I::genExponent},
+    {"findloc",
+     &I::genFindloc,
+     {{{"array", asBox},
+       {"value", asAddr},
+       {"dim", asValue},
+       {"mask", asBox, handleDynamicOptional},
+       {"kind", asValue},
+       {"back", asValue, handleDynamicOptional}}},
+     /*isElemental=*/false},
     {"floor", &I::genFloor},
     {"fraction", &I::genFraction},
     {"get_command",
@@ -3181,6 +3191,98 @@ mlir::Value IntrinsicLibrary::genExponent(mlir::Type resultType,
                                 fir::getBase(args[0])));
 }
 
+// FINDLOC
+fir::ExtendedValue
+IntrinsicLibrary::genFindloc(mlir::Type resultType,
+                             llvm::ArrayRef<fir::ExtendedValue> args) {
+  assert(args.size() == 6);
+
+  llvm::StringRef errMsg = "unexpected result for Findloc";
+
+  // Handle required array argument
+  mlir::Value array = builder.createBox(loc, args[0]);
+  unsigned rank = fir::BoxValue(array).rank();
+  assert(rank >= 1);
+
+  // Handle required value argument
+  mlir::Value val = builder.createBox(loc, args[1]);
+
+  // Check if dim argument is present
+  bool absentDim = isStaticallyAbsent(args[2]);
+
+  // Handle optional mask argument
+  auto mask = isStaticallyAbsent(args[3])
+                  ? builder.create<fir::AbsentOp>(
+                        loc, fir::BoxType::get(builder.getI1Type()))
+                  : builder.createBox(loc, args[3]);
+
+  // Handle optional kind argument
+  auto kind = isStaticallyAbsent(args[4])
+                  ? builder.createIntegerConstant(
+                        loc, builder.getIndexType(),
+                        builder.getKindMap().defaultIntegerKind())
+                  : fir::getBase(args[4]);
+
+  // Handle optional back argument
+  auto back = isStaticallyAbsent(args[5]) ? builder.createBool(loc, false)
+                                          : fir::getBase(args[5]);
+
+  if (!absentDim && rank == 1) {
+    // If dim argument is present and the array is rank 1, then the result is
+    // a scalar (since the the result is rank-1 or 0).
+    // Therefore, we use a scalar result descriptor with FindlocDim().
+    // Create mutable fir.box to be passed to the runtime for the result.
+    fir::MutableBoxValue resultMutableBox =
+        fir::factory::createTempMutableBox(builder, loc, resultType);
+    mlir::Value resultIrBox =
+        fir::factory::getMutableIRBox(builder, loc, resultMutableBox);
+    mlir::Value dim = fir::getBase(args[2]);
+
+    fir::runtime::genFindlocDim(builder, loc, resultIrBox, array, val, dim,
+                                mask, kind, back);
+
+    // Handle cleanup of allocatable result descriptor and return
+    fir::ExtendedValue res =
+        fir::factory::genMutableBoxRead(builder, loc, resultMutableBox);
+    return res.match(
+        [&](const mlir::Value &addr) -> fir::ExtendedValue {
+          addCleanUpForTemp(loc, addr);
+          return builder.create<fir::LoadOp>(loc, resultType, addr);
+        },
+        [&](const auto &) -> fir::ExtendedValue {
+          fir::emitFatalError(loc, errMsg);
+        });
+  }
+
+  // The result will be an array. Create mutable fir.box to be passed to the
+  // runtime for the result.
+  mlir::Type resultArrayType =
+      builder.getVarLenSeqTy(resultType, absentDim ? 1 : rank - 1);
+  fir::MutableBoxValue resultMutableBox =
+      fir::factory::createTempMutableBox(builder, loc, resultArrayType);
+  mlir::Value resultIrBox =
+      fir::factory::getMutableIRBox(builder, loc, resultMutableBox);
+
+  if (absentDim) {
+    fir::runtime::genFindloc(builder, loc, resultIrBox, array, val, mask, kind,
+                             back);
+  } else {
+    mlir::Value dim = fir::getBase(args[2]);
+    fir::runtime::genFindlocDim(builder, loc, resultIrBox, array, val, dim,
+                                mask, kind, back);
+  }
+
+  return fir::factory::genMutableBoxRead(builder, loc, resultMutableBox)
+      .match(
+          [&](const fir::ArrayBoxValue &box) -> fir::ExtendedValue {
+            addCleanUpForTemp(loc, box.getAddr());
+            return box;
+          },
+          [&](const auto &) -> fir::ExtendedValue {
+            fir::emitFatalError(loc, errMsg);
+          });
+}
+
 // FLOOR
 mlir::Value IntrinsicLibrary::genFloor(mlir::Type resultType,
                                        llvm::ArrayRef<mlir::Value> args) {

diff  --git a/flang/lib/Optimizer/Builder/Runtime/Reduction.cpp b/flang/lib/Optimizer/Builder/Runtime/Reduction.cpp
index bd90741114249..b1c7bae2ee0b7 100644
--- a/flang/lib/Optimizer/Builder/Runtime/Reduction.cpp
+++ b/flang/lib/Optimizer/Builder/Runtime/Reduction.cpp
@@ -576,6 +576,41 @@ void fir::runtime::genCountDim(fir::FirOpBuilder &builder, mlir::Location loc,
   builder.create<fir::CallOp>(loc, func, args);
 }
 
+/// Generate call to `Findloc` intrinsic runtime routine. This is the version
+/// that does not take a dim argument.
+void fir::runtime::genFindloc(fir::FirOpBuilder &builder, mlir::Location loc,
+                              mlir::Value resultBox, mlir::Value arrayBox,
+                              mlir::Value valBox, mlir::Value maskBox,
+                              mlir::Value kind, mlir::Value back) {
+  auto func = fir::runtime::getRuntimeFunc<mkRTKey(Findloc)>(loc, builder);
+  auto fTy = func.getFunctionType();
+  auto sourceFile = fir::factory::locationToFilename(builder, loc);
+  auto sourceLine =
+      fir::factory::locationToLineNo(builder, loc, fTy.getInput(5));
+  auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox,
+                                            arrayBox, valBox, kind, sourceFile,
+                                            sourceLine, maskBox, back);
+  builder.create<fir::CallOp>(loc, func, args);
+}
+
+/// Generate call to `FindlocDim` intrinsic runtime routine. This is the version
+/// that takes a dim argument.
+void fir::runtime::genFindlocDim(fir::FirOpBuilder &builder, mlir::Location loc,
+                                 mlir::Value resultBox, mlir::Value arrayBox,
+                                 mlir::Value valBox, mlir::Value dim,
+                                 mlir::Value maskBox, mlir::Value kind,
+                                 mlir::Value back) {
+  auto func = fir::runtime::getRuntimeFunc<mkRTKey(FindlocDim)>(loc, builder);
+  auto fTy = func.getFunctionType();
+  auto sourceFile = fir::factory::locationToFilename(builder, loc);
+  auto sourceLine =
+      fir::factory::locationToLineNo(builder, loc, fTy.getInput(6));
+  auto args = fir::runtime::createArguments(
+      builder, loc, fTy, resultBox, arrayBox, valBox, kind, dim, sourceFile,
+      sourceLine, maskBox, back);
+  builder.create<fir::CallOp>(loc, func, args);
+}
+
 /// Generate call to `Maxloc` intrinsic runtime routine. This is the version
 /// that does not take a dim argument.
 void fir::runtime::genMaxloc(fir::FirOpBuilder &builder, mlir::Location loc,

diff  --git a/flang/runtime/reduction-templates.h b/flang/runtime/reduction-templates.h
index 2b7b03572ca8e..2aaf5c102a9ca 100644
--- a/flang/runtime/reduction-templates.h
+++ b/flang/runtime/reduction-templates.h
@@ -57,7 +57,8 @@ inline void DoTotalReduction(const Descriptor &x, int dim,
       for (auto elements{x.Elements()}; elements--;
            x.IncrementSubscripts(xAt), mask->IncrementSubscripts(maskAt)) {
         if (IsLogicalElementTrue(*mask, maskAt)) {
-          accumulator.template AccumulateAt<TYPE>(xAt);
+          if (!accumulator.template AccumulateAt<TYPE>(xAt))
+            break;
         }
       }
       return;

diff  --git a/flang/test/Lower/Intrinsics/findloc.f90 b/flang/test/Lower/Intrinsics/findloc.f90
new file mode 100644
index 0000000000000..e4a9ab9af6ea5
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/findloc.f90
@@ -0,0 +1,265 @@
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s
+
+! CHECK-LABEL: func @_QPfindloc_test_1d(
+! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?xi32>>{{.*}}, %[[arg1:.*]]: !fir.ref<i32>{{.*}}) -> !fir.array<1xi32>
+function findloc_test_1d(a, v)
+  integer :: a(:)
+  integer :: v
+  integer, dimension(1) :: findloc_test_1d
+  ! CHECK-DAG: %[[r:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>>
+  ! CHECK-DAG: %[[v:.*]] = fir.embox %[[arg1]] : (!fir.ref<i32>) -> !fir.box<i32>
+  ! CHECK-DAG: %[[m:.*]] = fir.absent !fir.box<i1>
+  ! CHECK-DAG: %[[c4:.*]] = arith.constant 4 : index
+  ! CHECK-DAG: %[[false:.*]] = arith.constant false
+  ! CHECK-DAG: %[[res:.*]] = fir.convert %[[r]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<none>>
+  ! CHECK-DAG: %[[arr:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?xi32>>) -> !fir.box<none>
+  ! CHECK-DAG: %[[val:.*]] = fir.convert %[[v]] : (!fir.box<i32>) -> !fir.box<none>
+  ! CHECK-DAG: %[[mask:.*]] = fir.convert %[[m]] : (!fir.box<i1>) -> !fir.box<none>
+  ! CHECK-DAG: %[[kind:.*]] = fir.convert %[[c4]] : (index) -> i32
+  findloc_test_1d = findloc(a, v)
+  ! CHECK:  %{{.*}} = fir.call @_FortranAFindloc(%[[res]], %[[arr]], %[[val]], %[[kind]], %{{.*}}, %{{.*}}, %[[mask]], %false) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.box<none>, i32, !fir.ref<i8>, i32, !fir.box<none>, i1) -> none
+  ! CHECK: %[[box:.*]] = fir.load %[[r]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
+  ! CHECK: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
+  ! CHECK: fir.freemem %[[addr]] : !fir.heap<!fir.array<?xi32>>
+end function findloc_test_1d
+
+! CHECK-LABEL: func @_QPfindloc_test_2d(
+! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?x?xi32>>{{.*}}, %[[arg1:.*]]: !fir.ref<i32>{{.*}}) -> !fir.array<2xi32>
+function findloc_test_2d(a, v)
+  integer :: a(:,:)
+  integer :: v
+  integer, dimension(2) :: findloc_test_2d
+  ! CHECK-DAG: %[[r:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>>
+  ! CHECK-DAG: %[[v:.*]] = fir.embox %[[arg1]] : (!fir.ref<i32>) -> !fir.box<i32>
+  ! CHECK-DAG: %[[m:.*]] = fir.absent !fir.box<i1>
+  ! CHECK-DAG: %[[c4:.*]] = arith.constant 4 : index
+  ! CHECK-DAG: %[[false:.*]] = arith.constant false
+  ! CHECK-DAG: %[[res:.*]] = fir.convert %[[r]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<none>>
+  ! CHECK-DAG: %[[arr:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?x?xi32>>) -> !fir.box<none>
+  ! CHECK-DAG: %[[val:.*]] = fir.convert %[[v]] : (!fir.box<i32>) -> !fir.box<none>
+  ! CHECK-DAG: %[[mask:.*]] = fir.convert %[[m]] : (!fir.box<i1>) -> !fir.box<none>
+  ! CHECK-DAG: %[[kind:.*]] = fir.convert %[[c4]] : (index) -> i32
+  findloc_test_2d = findloc(a, v)
+  ! CHECK:  %{{.*}} = fir.call @_FortranAFindloc(%[[res]], %[[arr]], %[[val]], %[[kind]], %{{.*}}, %{{.*}}, %[[mask]], %false) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.box<none>, i32, !fir.ref<i8>, i32, !fir.box<none>, i1) -> none
+  ! CHECK: %[[box:.*]] = fir.load %[[r]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
+  ! CHECK: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
+  ! CHECK: fir.freemem %[[addr]] : !fir.heap<!fir.array<?xi32>>
+end function findloc_test_2d
+
+! CHECK-LABEL: func @_QPfindloc_test_byval(
+! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?x?xi32>>{{.*}}, %[[arg1:.*]]: i32{{.*}}) -> !fir.array<2xi32>
+function findloc_test_byval(a, v)
+  integer :: a(:,:)
+  integer, value :: v
+  integer, dimension(2) :: findloc_test_byval
+  ! CHECK-DAG: %[[a1:.*]] = fir.alloca i32
+  ! CHECK-DAG: fir.store %[[arg1]] to %[[a1]] : !fir.ref<i32>
+  ! CHECK-DAG: %[[r:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>>
+  ! CHECK-DAG: %[[v:.*]] = fir.embox %[[a1]] : (!fir.ref<i32>) -> !fir.box<i32>
+  ! CHECK-DAG: %[[m:.*]] = fir.absent !fir.box<i1>
+  ! CHECK-DAG: %[[c4:.*]] = arith.constant 4 : index
+  ! CHECK-DAG: %[[false:.*]] = arith.constant false
+  ! CHECK-DAG: %[[res:.*]] = fir.convert %[[r]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<none>>
+  ! CHECK-DAG: %[[arr:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?x?xi32>>) -> !fir.box<none>
+  ! CHECK-DAG: %[[val:.*]] = fir.convert %[[v]] : (!fir.box<i32>) -> !fir.box<none>
+  ! CHECK-DAG: %[[mask:.*]] = fir.convert %[[m]] : (!fir.box<i1>) -> !fir.box<none>
+  ! CHECK-DAG: %[[kind:.*]] = fir.convert %[[c4]] : (index) -> i32
+  findloc_test_byval = findloc(a, v)
+  ! CHECK:  %{{.*}} = fir.call @_FortranAFindloc(%[[res]], %[[arr]], %[[val]], %[[kind]], %{{.*}}, %{{.*}}, %[[mask]], %false) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.box<none>, i32, !fir.ref<i8>, i32, !fir.box<none>, i1) -> none
+  ! CHECK: %[[box:.*]] = fir.load %[[r]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
+  ! CHECK: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
+  ! CHECK: fir.freemem %[[addr]] : !fir.heap<!fir.array<?xi32>>
+end function findloc_test_byval
+
+! CHECK-LABEL: func @_QPfindloc_test_back_true(
+! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?x?xi32>>{{.*}}, %[[arg1:.*]]: !fir.ref<i32>{{.*}}) -> !fir.array<2xi32>
+function findloc_test_back_true(a, v)
+  integer :: a(:,:)
+  integer :: v
+  integer, dimension(2) :: findloc_test_back_true
+  ! CHECK-DAG: %[[r:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>>
+  ! CHECK-DAG: %[[v:.*]] = fir.embox %[[arg1]] : (!fir.ref<i32>) -> !fir.box<i32>
+  ! CHECK-DAG: %[[m:.*]] = fir.absent !fir.box<i1>
+  ! CHECK-DAG: %[[c4:.*]] = arith.constant 4 : index
+  ! CHECK-DAG: %[[true:.*]] = arith.constant true
+  ! CHECK-DAG: %[[res:.*]] = fir.convert %[[r]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<none>>
+  ! CHECK-DAG: %[[arr:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?x?xi32>>) -> !fir.box<none>
+  ! CHECK-DAG: %[[val:.*]] = fir.convert %[[v]] : (!fir.box<i32>) -> !fir.box<none>
+  ! CHECK-DAG: %[[mask:.*]] = fir.convert %[[m]] : (!fir.box<i1>) -> !fir.box<none>
+  ! CHECK-DAG: %[[kind:.*]] = fir.convert %[[c4]] : (index) -> i32
+  findloc_test_back_true = findloc(a, v, back=.true.)
+  ! CHECK:  %{{.*}} = fir.call @_FortranAFindloc(%[[res]], %[[arr]], %[[val]], %[[kind]], %{{.*}}, %{{.*}}, %[[mask]], %true) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.box<none>, i32, !fir.ref<i8>, i32, !fir.box<none>, i1) -> none
+  ! CHECK: %[[box:.*]] = fir.load %[[r]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
+  ! CHECK: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
+  ! CHECK: fir.freemem %[[addr]] : !fir.heap<!fir.array<?xi32>>
+end function findloc_test_back_true
+
+! CHECK-LABEL: func @_QPfindloc_test_back(
+! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?x?xi32>>{{.*}}, %[[arg1:.*]]: !fir.ref<i32>{{.*}}, %[[arg2:.*]]: !fir.ref<!fir.logical<4>>{{.*}}) -> !fir.array<2xi32>
+function findloc_test_back(a, v, back)
+  integer :: a(:,:)
+  integer :: v
+  logical :: back
+  integer, dimension(2) :: findloc_test_back
+  ! CHECK-DAG: %[[r:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>>
+  ! CHECK-DAG: %[[v:.*]] = fir.embox %[[arg1]] : (!fir.ref<i32>) -> !fir.box<i32>
+  ! CHECK-DAG: %[[m:.*]] = fir.absent !fir.box<i1>
+  ! CHECK-DAG: %[[b:.*]] = fir.load %[[arg2]] : !fir.ref<!fir.logical<4>>
+  ! CHECK-DAG: %[[c4:.*]] = arith.constant 4 : index
+  ! CHECK-DAG: %[[res:.*]] = fir.convert %[[r]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<none>>
+  ! CHECK-DAG: %[[arr:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?x?xi32>>) -> !fir.box<none>
+  ! CHECK-DAG: %[[val:.*]] = fir.convert %[[v]] : (!fir.box<i32>) -> !fir.box<none>
+  ! CHECK-DAG: %[[mask:.*]] = fir.convert %[[m]] : (!fir.box<i1>) -> !fir.box<none>
+  ! CHECK-DAG: %[[kind:.*]] = fir.convert %[[c4]] : (index) -> i32
+  ! CHECK-DAG: %[[back:.*]] = fir.convert %[[b]] : (!fir.logical<4>) -> i1
+  findloc_test_back = findloc(a, v, back=back)
+  ! CHECK:  %{{.*}} = fir.call @_FortranAFindloc(%[[res]], %[[arr]], %[[val]], %[[kind]], %{{.*}}, %{{.*}}, %[[mask]], %[[back]]) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.box<none>, i32, !fir.ref<i8>, i32, !fir.box<none>, i1) -> none
+  ! CHECK: %[[box:.*]] = fir.load %[[r]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
+  ! CHECK: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
+  ! CHECK: fir.freemem %[[addr]] : !fir.heap<!fir.array<?xi32>>
+end function findloc_test_back
+
+! CHECK-LABEL: func @_QPfindloc_test_dim(
+! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?x?xi32>>{{.*}}, %[[arg1:.*]]: !fir.ref<i32>{{.*}}, %[[arg2:.*]]: !fir.box<!fir.array<?xi32>>{{.*}})
+subroutine findloc_test_dim(a, v, res)
+  integer :: a(:,:)
+  integer :: v
+  integer :: res(:)
+  ! CHECK-DAG: %[[r:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>>
+  ! CHECK-DAG: %[[v:.*]] = fir.embox %[[arg1]] : (!fir.ref<i32>) -> !fir.box<i32>
+  ! CHECK-DAG: %[[m:.*]] = fir.absent !fir.box<i1>
+  ! CHECK-DAG: %[[c1:.*]] = arith.constant 1 : i32
+  ! CHECK-DAG: %[[c4:.*]] = arith.constant 4 : index
+  ! CHECK-DAG: %[[false:.*]] = arith.constant false
+  ! CHECK-DAG: %[[res:.*]] = fir.convert %[[r]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<none>>
+  ! CHECK-DAG: %[[arr:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?x?xi32>>) -> !fir.box<none>
+  ! CHECK-DAG: %[[val:.*]] = fir.convert %[[v]] : (!fir.box<i32>) -> !fir.box<none>
+  ! CHECK-DAG: %[[mask:.*]] = fir.convert %[[m]] : (!fir.box<i1>) -> !fir.box<none>
+  ! CHECK-DAG: %[[kind:.*]] = fir.convert %[[c4]] : (index) -> i32
+  res = findloc(a, v, dim=1)
+  ! CHECK:  %{{.*}} = fir.call @_FortranAFindlocDim(%[[res]], %[[arr]], %[[val]], %[[kind]], %[[c1]], %{{.*}}, %{{.*}}, %[[mask]], %false) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.box<none>, i32, i32, !fir.ref<i8>, i32, !fir.box<none>, i1) -> none
+  ! CHECK: %[[box:.*]] = fir.load %[[r]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
+  ! CHECK: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
+  ! CHECK: fir.freemem %[[addr]] : !fir.heap<!fir.array<?xi32>>
+end subroutine findloc_test_dim
+
+! CHECK-LABEL: func @_QPfindloc_test_dim_unknown(
+! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?x?xi32>>{{.*}}, %[[arg1:.*]]: !fir.ref<i32>{{.*}}, %[[arg2:.*]]: !fir.ref<i32>{{.*}}, %[[arg3:.*]]: !fir.box<!fir.array<?xi32>>{{.*}})
+subroutine findloc_test_dim_unknown(a, v, dim, res)
+  integer :: a(:,:)
+  integer :: v
+  integer :: dim
+  integer :: res(:)
+  ! CHECK-DAG: %[[r:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>>
+  ! CHECK-DAG: %[[v:.*]] = fir.embox %[[arg1]] : (!fir.ref<i32>) -> !fir.box<i32>
+  ! CHECK-DAG: %[[m:.*]] = fir.absent !fir.box<i1>
+  ! CHECK-DAG: %[[dim:.*]] = fir.load %[[arg2]] : !fir.ref<i32>
+  ! CHECK-DAG: %[[c4:.*]] = arith.constant 4 : index
+  ! CHECK-DAG: %[[false:.*]] = arith.constant false
+  ! CHECK-DAG: %[[res:.*]] = fir.convert %[[r]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<none>>
+  ! CHECK-DAG: %[[arr:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?x?xi32>>) -> !fir.box<none>
+  ! CHECK-DAG: %[[val:.*]] = fir.convert %[[v]] : (!fir.box<i32>) -> !fir.box<none>
+  ! CHECK-DAG: %[[mask:.*]] = fir.convert %[[m]] : (!fir.box<i1>) -> !fir.box<none>
+  ! CHECK-DAG: %[[kind:.*]] = fir.convert %[[c4]] : (index) -> i32
+  res = findloc(a, v, dim=dim)
+  ! CHECK:  %{{.*}} = fir.call @_FortranAFindlocDim(%[[res]], %[[arr]], %[[val]], %[[kind]], %[[dim]], %{{.*}}, %{{.*}}, %[[mask]], %false) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.box<none>, i32, i32, !fir.ref<i8>, i32, !fir.box<none>, i1) -> none
+  ! CHECK: %[[box:.*]] = fir.load %[[r]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
+  ! CHECK: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
+  ! CHECK: fir.freemem %[[addr]] : !fir.heap<!fir.array<?xi32>>
+end subroutine findloc_test_dim_unknown
+
+! CHECK-LABEL: func @_QPfindloc_test_kind(
+! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?x?xi32>>{{.*}}, %[[arg1:.*]]: !fir.ref<i32>{{.*}}, %[[arg2:.*]]: !fir.box<!fir.array<?xi64>>{{.*}})
+subroutine findloc_test_kind(a, v, res)
+  integer :: a(:,:)
+  integer :: v
+  integer(8) :: res(:)
+  ! CHECK-DAG: %[[r:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi64>>>
+  ! CHECK-DAG: %[[v:.*]] = fir.embox %[[arg1]] : (!fir.ref<i32>) -> !fir.box<i32>
+  ! CHECK-DAG: %[[m:.*]] = fir.absent !fir.box<i1>
+  ! CHECK-DAG: %[[kind:.*]] = arith.constant 8 : i32
+  ! CHECK-DAG: %[[false:.*]] = arith.constant false
+  ! CHECK-DAG: %[[res:.*]] = fir.convert %[[r]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi64>>>>) -> !fir.ref<!fir.box<none>>
+  ! CHECK-DAG: %[[arr:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?x?xi32>>) -> !fir.box<none>
+  ! CHECK-DAG: %[[val:.*]] = fir.convert %[[v]] : (!fir.box<i32>) -> !fir.box<none>
+  ! CHECK-DAG: %[[mask:.*]] = fir.convert %[[m]] : (!fir.box<i1>) -> !fir.box<none>
+  res = findloc(a, v, kind=8)
+  ! CHECK:  %{{.*}} = fir.call @_FortranAFindloc(%[[res]], %[[arr]], %[[val]], %[[kind]], %{{.*}}, %{{.*}}, %[[mask]], %false) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.box<none>, i32, !fir.ref<i8>, i32, !fir.box<none>, i1) -> none
+  ! CHECK: %[[box:.*]] = fir.load %[[r]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi64>>>>
+  ! CHECK: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box<!fir.heap<!fir.array<?xi64>>>) -> !fir.heap<!fir.array<?xi64>>
+  ! CHECK: fir.freemem %[[addr]] : !fir.heap<!fir.array<?xi64>>
+end subroutine findloc_test_kind
+
+! CHECK-LABEL: func @_QPfindloc_test_non_scalar_mask(
+! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?x?xi32>>{{.*}}, %[[arg1:.*]]: !fir.ref<i32>{{.*}}, %[[arg2:.*]]: !fir.box<!fir.array<?x?x!fir.logical<4>>>{{.*}}
+subroutine findloc_test_non_scalar_mask(a, v, mask, res)
+  integer :: a(:,:)
+  integer :: v
+  logical :: mask(:,:)
+  integer :: res(:)
+  ! CHECK-DAG: %[[r:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>>
+  ! CHECK-DAG: %[[v:.*]] = fir.embox %[[arg1]] : (!fir.ref<i32>) -> !fir.box<i32>
+  ! CHECK-DAG: %[[c4:.*]] = arith.constant 4 : index
+  ! CHECK-DAG: %[[false:.*]] = arith.constant false
+  ! CHECK-DAG: %[[res:.*]] = fir.convert %[[r]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<none>>
+  ! CHECK-DAG: %[[arr:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?x?xi32>>) -> !fir.box<none>
+  ! CHECK-DAG: %[[val:.*]] = fir.convert %[[v]] : (!fir.box<i32>) -> !fir.box<none>
+  ! CHECK-DAG: %[[mask:.*]] = fir.convert %[[arg2]] : (!fir.box<!fir.array<?x?x!fir.logical<4>>>) -> !fir.box<none>
+  ! CHECK-DAG: %[[kind:.*]] = fir.convert %[[c4]] : (index) -> i32
+  res = findloc(a, v, mask=mask)
+  ! CHECK:  %{{.*}} = fir.call @_FortranAFindloc(%[[res]], %[[arr]], %[[val]], %[[kind]], %{{.*}}, %{{.*}}, %[[mask]], %false) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.box<none>, i32, !fir.ref<i8>, i32, !fir.box<none>, i1) -> none
+  ! CHECK: %[[box:.*]] = fir.load %[[r]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
+  ! CHECK: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
+  ! CHECK: fir.freemem %[[addr]] : !fir.heap<!fir.array<?xi32>>
+end subroutine findloc_test_non_scalar_mask
+
+! CHECK-LABEL: func @_QPfindloc_test_scalar_mask(
+! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?x?xi32>>{{.*}}, %[[arg1:.*]]: !fir.ref<i32>{{.*}}, %[[arg2:.*]]: !fir.ref<!fir.logical<4>>{{.*}}, %[[arg3:.*]]: !fir.box<!fir.array<?xi32>>{{.*}})
+subroutine findloc_test_scalar_mask(a, v, mask, res)
+  integer :: a(:,:)
+  integer :: v
+  logical :: mask
+  integer :: res(:)
+  ! CHECK-DAG: %[[r:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>>
+  ! CHECK-DAG: %[[v:.*]] = fir.embox %[[arg1]] : (!fir.ref<i32>) -> !fir.box<i32>
+  ! CHECK-DAG: %[[m:.*]] = fir.embox %[[arg2]] : (!fir.ref<!fir.logical<4>>) -> !fir.box<!fir.logical<4>>
+  ! CHECK-DAG: %[[c4:.*]] = arith.constant 4 : index
+  ! CHECK-DAG: %[[false:.*]] = arith.constant false
+  ! CHECK-DAG: %[[res:.*]] = fir.convert %[[r]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<none>>
+  ! CHECK-DAG: %[[arr:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?x?xi32>>) -> !fir.box<none>
+  ! CHECK-DAG: %[[val:.*]] = fir.convert %[[v]] : (!fir.box<i32>) -> !fir.box<none>
+  ! CHECK-DAG: %[[mask:.*]] = fir.convert %[[m]] : (!fir.box<!fir.logical<4>>) -> !fir.box<none>
+  ! CHECK-DAG: %[[kind:.*]] = fir.convert %[[c4]] : (index) -> i32
+  res = findloc(a, v, mask=mask)
+  ! CHECK:  %{{.*}} = fir.call @_FortranAFindloc(%[[res]], %[[arr]], %[[val]], %[[kind]], %{{.*}}, %{{.*}}, %[[mask]], %false) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.box<none>, i32, !fir.ref<i8>, i32, !fir.box<none>, i1) -> none
+  ! CHECK: %[[box:.*]] = fir.load %[[r]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
+  ! CHECK: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
+  ! CHECK: fir.freemem %[[addr]] : !fir.heap<!fir.array<?xi32>>
+end subroutine findloc_test_scalar_mask
+
+! CHECK-LABEL: func @_QPfindloc_test_all(
+! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?x?xi32>>{{.*}}, %[[arg1:.*]]: !fir.ref<i32>{{.*}}, %[[arg2:.*]]: !fir.ref<i32>{{.*}}, %[[arg3:.*]]: !fir.box<!fir.array<?x?x!fir.logical<4>>>{{.*}}, %[[arg4:.*]]: !fir.ref<!fir.logical<4>>{{.*}}, %[[arg5:.*]]: !fir.box<!fir.array<?xi64>>{{.*}}
+subroutine findloc_test_all(a, v, dim, mask, back, res)
+  integer :: a(:,:)
+  integer :: v
+  integer :: dim
+  logical :: mask(:,:)
+  logical :: back
+  integer(8) :: res(:)
+  ! CHECK-DAG: %[[r:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi64>>>
+  ! CHECK-DAG: %[[v:.*]] = fir.embox %[[arg1]] : (!fir.ref<i32>) -> !fir.box<i32>
+  ! CHECK-DAG: %[[b:.*]] = fir.load %[[arg4]] : !fir.ref<!fir.logical<4>>
+  ! CHECK-DAG: %[[kind:.*]] = arith.constant 8 : i32
+  ! CHECK-DAG: %[[dim:.*]] = fir.load %[[arg2]] : !fir.ref<i32>
+  ! CHECK-DAG: %[[res:.*]] = fir.convert %[[r]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi64>>>>) -> !fir.ref<!fir.box<none>>
+  ! CHECK-DAG: %[[arr:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?x?xi32>>) -> !fir.box<none>
+  ! CHECK-DAG: %[[val:.*]] = fir.convert %[[v]] : (!fir.box<i32>) -> !fir.box<none>
+  ! CHECK-DAG: %[[mask:.*]] = fir.convert %[[arg3]] : (!fir.box<!fir.array<?x?x!fir.logical<4>>>) -> !fir.box<none>
+  ! CHECK-DAG: %[[back:.*]] = fir.convert %[[b]] : (!fir.logical<4>) -> i1
+  res = findloc(a, v, dim=dim, mask=mask, kind=8, back=back)
+  ! CHECK:  %{{.*}} = fir.call @_FortranAFindlocDim(%[[res]], %[[arr]], %[[val]], %[[kind]], %[[dim]], %{{.*}}, %{{.*}}, %[[mask]], %[[back]]) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.box<none>, i32, i32, !fir.ref<i8>, i32, !fir.box<none>, i1) -> none
+  ! CHECK: %[[box:.*]] = fir.load %[[r]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi64>>>>
+  ! CHECK: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box<!fir.heap<!fir.array<?xi64>>>) -> !fir.heap<!fir.array<?xi64>>
+  ! CHECK: fir.freemem %[[addr]] : !fir.heap<!fir.array<?xi64>>
+end subroutine findloc_test_all


        


More information about the flang-commits mailing list