diff --git a/flang/include/flang/Optimizer/Builder/Runtime/Reduction.h b/flang/include/flang/Optimizer/Builder/Runtime/Reduction.h --- a/flang/include/flang/Optimizer/Builder/Runtime/Reduction.h +++ b/flang/include/flang/Optimizer/Builder/Runtime/Reduction.h @@ -75,6 +75,19 @@ 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 --- a/flang/lib/Lower/IntrinsicCall.cpp +++ b/flang/lib/Lower/IntrinsicCall.cpp @@ -516,6 +516,7 @@ mlir::Value genIbits(mlir::Type, llvm::ArrayRef); mlir::Value genIbset(mlir::Type, llvm::ArrayRef); fir::ExtendedValue genIchar(mlir::Type, llvm::ArrayRef); + fir::ExtendedValue genFindloc(mlir::Type, llvm::ArrayRef); mlir::Value genIeeeIsFinite(mlir::Type, llvm::ArrayRef); template fir::ExtendedValue genIeeeTypeCompare(mlir::Type, @@ -801,6 +802,15 @@ {{{"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 @@ fir::getBase(args[0]))); } +// FINDLOC +fir::ExtendedValue +IntrinsicLibrary::genFindloc(mlir::Type resultType, + llvm::ArrayRef 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( + 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(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 args) { diff --git a/flang/lib/Optimizer/Builder/Runtime/Reduction.cpp b/flang/lib/Optimizer/Builder/Runtime/Reduction.cpp --- a/flang/lib/Optimizer/Builder/Runtime/Reduction.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Reduction.cpp @@ -576,6 +576,41 @@ builder.create(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(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(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(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(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 --- a/flang/runtime/reduction-templates.h +++ b/flang/runtime/reduction-templates.h @@ -57,7 +57,8 @@ for (auto elements{x.Elements()}; elements--; x.IncrementSubscripts(xAt), mask->IncrementSubscripts(maskAt)) { if (IsLogicalElementTrue(*mask, maskAt)) { - accumulator.template AccumulateAt(xAt); + if (!accumulator.template AccumulateAt(xAt)) + break; } } return; diff --git a/flang/test/Lower/Intrinsics/findloc.f90 b/flang/test/Lower/Intrinsics/findloc.f90 new file mode 100644 --- /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>{{.*}}, %[[arg1:.*]]: !fir.ref{{.*}}) -> !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>> + ! CHECK-DAG: %[[v:.*]] = fir.embox %[[arg1]] : (!fir.ref) -> !fir.box + ! CHECK-DAG: %[[m:.*]] = fir.absent !fir.box + ! CHECK-DAG: %[[c4:.*]] = arith.constant 4 : index + ! CHECK-DAG: %[[false:.*]] = arith.constant false + ! CHECK-DAG: %[[res:.*]] = fir.convert %[[r]] : (!fir.ref>>>) -> !fir.ref> + ! CHECK-DAG: %[[arr:.*]] = fir.convert %[[arg0]] : (!fir.box>) -> !fir.box + ! CHECK-DAG: %[[val:.*]] = fir.convert %[[v]] : (!fir.box) -> !fir.box + ! CHECK-DAG: %[[mask:.*]] = fir.convert %[[m]] : (!fir.box) -> !fir.box + ! 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 : (!fir.ref>, !fir.box, !fir.box, i32, !fir.ref, i32, !fir.box, i1) -> none + ! CHECK: %[[box:.*]] = fir.load %[[r]] : !fir.ref>>> + ! CHECK: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box>>) -> !fir.heap> + ! CHECK: fir.freemem %[[addr]] : !fir.heap> +end function findloc_test_1d + +! CHECK-LABEL: func @_QPfindloc_test_2d( +! CHECK-SAME: %[[arg0:.*]]: !fir.box>{{.*}}, %[[arg1:.*]]: !fir.ref{{.*}}) -> !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>> + ! CHECK-DAG: %[[v:.*]] = fir.embox %[[arg1]] : (!fir.ref) -> !fir.box + ! CHECK-DAG: %[[m:.*]] = fir.absent !fir.box + ! CHECK-DAG: %[[c4:.*]] = arith.constant 4 : index + ! CHECK-DAG: %[[false:.*]] = arith.constant false + ! CHECK-DAG: %[[res:.*]] = fir.convert %[[r]] : (!fir.ref>>>) -> !fir.ref> + ! CHECK-DAG: %[[arr:.*]] = fir.convert %[[arg0]] : (!fir.box>) -> !fir.box + ! CHECK-DAG: %[[val:.*]] = fir.convert %[[v]] : (!fir.box) -> !fir.box + ! CHECK-DAG: %[[mask:.*]] = fir.convert %[[m]] : (!fir.box) -> !fir.box + ! 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 : (!fir.ref>, !fir.box, !fir.box, i32, !fir.ref, i32, !fir.box, i1) -> none + ! CHECK: %[[box:.*]] = fir.load %[[r]] : !fir.ref>>> + ! CHECK: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box>>) -> !fir.heap> + ! CHECK: fir.freemem %[[addr]] : !fir.heap> +end function findloc_test_2d + +! CHECK-LABEL: func @_QPfindloc_test_byval( +! CHECK-SAME: %[[arg0:.*]]: !fir.box>{{.*}}, %[[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 + ! CHECK-DAG: %[[r:.*]] = fir.alloca !fir.box>> + ! CHECK-DAG: %[[v:.*]] = fir.embox %[[a1]] : (!fir.ref) -> !fir.box + ! CHECK-DAG: %[[m:.*]] = fir.absent !fir.box + ! CHECK-DAG: %[[c4:.*]] = arith.constant 4 : index + ! CHECK-DAG: %[[false:.*]] = arith.constant false + ! CHECK-DAG: %[[res:.*]] = fir.convert %[[r]] : (!fir.ref>>>) -> !fir.ref> + ! CHECK-DAG: %[[arr:.*]] = fir.convert %[[arg0]] : (!fir.box>) -> !fir.box + ! CHECK-DAG: %[[val:.*]] = fir.convert %[[v]] : (!fir.box) -> !fir.box + ! CHECK-DAG: %[[mask:.*]] = fir.convert %[[m]] : (!fir.box) -> !fir.box + ! 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 : (!fir.ref>, !fir.box, !fir.box, i32, !fir.ref, i32, !fir.box, i1) -> none + ! CHECK: %[[box:.*]] = fir.load %[[r]] : !fir.ref>>> + ! CHECK: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box>>) -> !fir.heap> + ! CHECK: fir.freemem %[[addr]] : !fir.heap> +end function findloc_test_byval + +! CHECK-LABEL: func @_QPfindloc_test_back_true( +! CHECK-SAME: %[[arg0:.*]]: !fir.box>{{.*}}, %[[arg1:.*]]: !fir.ref{{.*}}) -> !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>> + ! CHECK-DAG: %[[v:.*]] = fir.embox %[[arg1]] : (!fir.ref) -> !fir.box + ! CHECK-DAG: %[[m:.*]] = fir.absent !fir.box + ! CHECK-DAG: %[[c4:.*]] = arith.constant 4 : index + ! CHECK-DAG: %[[true:.*]] = arith.constant true + ! CHECK-DAG: %[[res:.*]] = fir.convert %[[r]] : (!fir.ref>>>) -> !fir.ref> + ! CHECK-DAG: %[[arr:.*]] = fir.convert %[[arg0]] : (!fir.box>) -> !fir.box + ! CHECK-DAG: %[[val:.*]] = fir.convert %[[v]] : (!fir.box) -> !fir.box + ! CHECK-DAG: %[[mask:.*]] = fir.convert %[[m]] : (!fir.box) -> !fir.box + ! 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 : (!fir.ref>, !fir.box, !fir.box, i32, !fir.ref, i32, !fir.box, i1) -> none + ! CHECK: %[[box:.*]] = fir.load %[[r]] : !fir.ref>>> + ! CHECK: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box>>) -> !fir.heap> + ! CHECK: fir.freemem %[[addr]] : !fir.heap> +end function findloc_test_back_true + +! CHECK-LABEL: func @_QPfindloc_test_back( +! CHECK-SAME: %[[arg0:.*]]: !fir.box>{{.*}}, %[[arg1:.*]]: !fir.ref{{.*}}, %[[arg2:.*]]: !fir.ref>{{.*}}) -> !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>> + ! CHECK-DAG: %[[v:.*]] = fir.embox %[[arg1]] : (!fir.ref) -> !fir.box + ! CHECK-DAG: %[[m:.*]] = fir.absent !fir.box + ! CHECK-DAG: %[[b:.*]] = fir.load %[[arg2]] : !fir.ref> + ! CHECK-DAG: %[[c4:.*]] = arith.constant 4 : index + ! CHECK-DAG: %[[res:.*]] = fir.convert %[[r]] : (!fir.ref>>>) -> !fir.ref> + ! CHECK-DAG: %[[arr:.*]] = fir.convert %[[arg0]] : (!fir.box>) -> !fir.box + ! CHECK-DAG: %[[val:.*]] = fir.convert %[[v]] : (!fir.box) -> !fir.box + ! CHECK-DAG: %[[mask:.*]] = fir.convert %[[m]] : (!fir.box) -> !fir.box + ! 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 : (!fir.ref>, !fir.box, !fir.box, i32, !fir.ref, i32, !fir.box, i1) -> none + ! CHECK: %[[box:.*]] = fir.load %[[r]] : !fir.ref>>> + ! CHECK: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box>>) -> !fir.heap> + ! CHECK: fir.freemem %[[addr]] : !fir.heap> +end function findloc_test_back + +! CHECK-LABEL: func @_QPfindloc_test_dim( +! CHECK-SAME: %[[arg0:.*]]: !fir.box>{{.*}}, %[[arg1:.*]]: !fir.ref{{.*}}, %[[arg2:.*]]: !fir.box>{{.*}}) +subroutine findloc_test_dim(a, v, res) + integer :: a(:,:) + integer :: v + integer :: res(:) + ! CHECK-DAG: %[[r:.*]] = fir.alloca !fir.box>> + ! CHECK-DAG: %[[v:.*]] = fir.embox %[[arg1]] : (!fir.ref) -> !fir.box + ! CHECK-DAG: %[[m:.*]] = fir.absent !fir.box + ! 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.ref> + ! CHECK-DAG: %[[arr:.*]] = fir.convert %[[arg0]] : (!fir.box>) -> !fir.box + ! CHECK-DAG: %[[val:.*]] = fir.convert %[[v]] : (!fir.box) -> !fir.box + ! CHECK-DAG: %[[mask:.*]] = fir.convert %[[m]] : (!fir.box) -> !fir.box + ! 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 : (!fir.ref>, !fir.box, !fir.box, i32, i32, !fir.ref, i32, !fir.box, i1) -> none + ! CHECK: %[[box:.*]] = fir.load %[[r]] : !fir.ref>>> + ! CHECK: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box>>) -> !fir.heap> + ! CHECK: fir.freemem %[[addr]] : !fir.heap> +end subroutine findloc_test_dim + +! CHECK-LABEL: func @_QPfindloc_test_dim_unknown( +! CHECK-SAME: %[[arg0:.*]]: !fir.box>{{.*}}, %[[arg1:.*]]: !fir.ref{{.*}}, %[[arg2:.*]]: !fir.ref{{.*}}, %[[arg3:.*]]: !fir.box>{{.*}}) +subroutine findloc_test_dim_unknown(a, v, dim, res) + integer :: a(:,:) + integer :: v + integer :: dim + integer :: res(:) + ! CHECK-DAG: %[[r:.*]] = fir.alloca !fir.box>> + ! CHECK-DAG: %[[v:.*]] = fir.embox %[[arg1]] : (!fir.ref) -> !fir.box + ! CHECK-DAG: %[[m:.*]] = fir.absent !fir.box + ! CHECK-DAG: %[[dim:.*]] = fir.load %[[arg2]] : !fir.ref + ! CHECK-DAG: %[[c4:.*]] = arith.constant 4 : index + ! CHECK-DAG: %[[false:.*]] = arith.constant false + ! CHECK-DAG: %[[res:.*]] = fir.convert %[[r]] : (!fir.ref>>>) -> !fir.ref> + ! CHECK-DAG: %[[arr:.*]] = fir.convert %[[arg0]] : (!fir.box>) -> !fir.box + ! CHECK-DAG: %[[val:.*]] = fir.convert %[[v]] : (!fir.box) -> !fir.box + ! CHECK-DAG: %[[mask:.*]] = fir.convert %[[m]] : (!fir.box) -> !fir.box + ! 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 : (!fir.ref>, !fir.box, !fir.box, i32, i32, !fir.ref, i32, !fir.box, i1) -> none + ! CHECK: %[[box:.*]] = fir.load %[[r]] : !fir.ref>>> + ! CHECK: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box>>) -> !fir.heap> + ! CHECK: fir.freemem %[[addr]] : !fir.heap> +end subroutine findloc_test_dim_unknown + +! CHECK-LABEL: func @_QPfindloc_test_kind( +! CHECK-SAME: %[[arg0:.*]]: !fir.box>{{.*}}, %[[arg1:.*]]: !fir.ref{{.*}}, %[[arg2:.*]]: !fir.box>{{.*}}) +subroutine findloc_test_kind(a, v, res) + integer :: a(:,:) + integer :: v + integer(8) :: res(:) + ! CHECK-DAG: %[[r:.*]] = fir.alloca !fir.box>> + ! CHECK-DAG: %[[v:.*]] = fir.embox %[[arg1]] : (!fir.ref) -> !fir.box + ! CHECK-DAG: %[[m:.*]] = fir.absent !fir.box + ! CHECK-DAG: %[[kind:.*]] = arith.constant 8 : i32 + ! CHECK-DAG: %[[false:.*]] = arith.constant false + ! CHECK-DAG: %[[res:.*]] = fir.convert %[[r]] : (!fir.ref>>>) -> !fir.ref> + ! CHECK-DAG: %[[arr:.*]] = fir.convert %[[arg0]] : (!fir.box>) -> !fir.box + ! CHECK-DAG: %[[val:.*]] = fir.convert %[[v]] : (!fir.box) -> !fir.box + ! CHECK-DAG: %[[mask:.*]] = fir.convert %[[m]] : (!fir.box) -> !fir.box + res = findloc(a, v, kind=8) + ! CHECK: %{{.*}} = fir.call @_FortranAFindloc(%[[res]], %[[arr]], %[[val]], %[[kind]], %{{.*}}, %{{.*}}, %[[mask]], %false) fastmath : (!fir.ref>, !fir.box, !fir.box, i32, !fir.ref, i32, !fir.box, i1) -> none + ! CHECK: %[[box:.*]] = fir.load %[[r]] : !fir.ref>>> + ! CHECK: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box>>) -> !fir.heap> + ! CHECK: fir.freemem %[[addr]] : !fir.heap> +end subroutine findloc_test_kind + +! CHECK-LABEL: func @_QPfindloc_test_non_scalar_mask( +! CHECK-SAME: %[[arg0:.*]]: !fir.box>{{.*}}, %[[arg1:.*]]: !fir.ref{{.*}}, %[[arg2:.*]]: !fir.box>>{{.*}} +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>> + ! CHECK-DAG: %[[v:.*]] = fir.embox %[[arg1]] : (!fir.ref) -> !fir.box + ! CHECK-DAG: %[[c4:.*]] = arith.constant 4 : index + ! CHECK-DAG: %[[false:.*]] = arith.constant false + ! CHECK-DAG: %[[res:.*]] = fir.convert %[[r]] : (!fir.ref>>>) -> !fir.ref> + ! CHECK-DAG: %[[arr:.*]] = fir.convert %[[arg0]] : (!fir.box>) -> !fir.box + ! CHECK-DAG: %[[val:.*]] = fir.convert %[[v]] : (!fir.box) -> !fir.box + ! CHECK-DAG: %[[mask:.*]] = fir.convert %[[arg2]] : (!fir.box>>) -> !fir.box + ! 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 : (!fir.ref>, !fir.box, !fir.box, i32, !fir.ref, i32, !fir.box, i1) -> none + ! CHECK: %[[box:.*]] = fir.load %[[r]] : !fir.ref>>> + ! CHECK: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box>>) -> !fir.heap> + ! CHECK: fir.freemem %[[addr]] : !fir.heap> +end subroutine findloc_test_non_scalar_mask + +! CHECK-LABEL: func @_QPfindloc_test_scalar_mask( +! CHECK-SAME: %[[arg0:.*]]: !fir.box>{{.*}}, %[[arg1:.*]]: !fir.ref{{.*}}, %[[arg2:.*]]: !fir.ref>{{.*}}, %[[arg3:.*]]: !fir.box>{{.*}}) +subroutine findloc_test_scalar_mask(a, v, mask, res) + integer :: a(:,:) + integer :: v + logical :: mask + integer :: res(:) + ! CHECK-DAG: %[[r:.*]] = fir.alloca !fir.box>> + ! CHECK-DAG: %[[v:.*]] = fir.embox %[[arg1]] : (!fir.ref) -> !fir.box + ! CHECK-DAG: %[[m:.*]] = fir.embox %[[arg2]] : (!fir.ref>) -> !fir.box> + ! CHECK-DAG: %[[c4:.*]] = arith.constant 4 : index + ! CHECK-DAG: %[[false:.*]] = arith.constant false + ! CHECK-DAG: %[[res:.*]] = fir.convert %[[r]] : (!fir.ref>>>) -> !fir.ref> + ! CHECK-DAG: %[[arr:.*]] = fir.convert %[[arg0]] : (!fir.box>) -> !fir.box + ! CHECK-DAG: %[[val:.*]] = fir.convert %[[v]] : (!fir.box) -> !fir.box + ! CHECK-DAG: %[[mask:.*]] = fir.convert %[[m]] : (!fir.box>) -> !fir.box + ! 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 : (!fir.ref>, !fir.box, !fir.box, i32, !fir.ref, i32, !fir.box, i1) -> none + ! CHECK: %[[box:.*]] = fir.load %[[r]] : !fir.ref>>> + ! CHECK: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box>>) -> !fir.heap> + ! CHECK: fir.freemem %[[addr]] : !fir.heap> +end subroutine findloc_test_scalar_mask + +! CHECK-LABEL: func @_QPfindloc_test_all( +! CHECK-SAME: %[[arg0:.*]]: !fir.box>{{.*}}, %[[arg1:.*]]: !fir.ref{{.*}}, %[[arg2:.*]]: !fir.ref{{.*}}, %[[arg3:.*]]: !fir.box>>{{.*}}, %[[arg4:.*]]: !fir.ref>{{.*}}, %[[arg5:.*]]: !fir.box>{{.*}} +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>> + ! CHECK-DAG: %[[v:.*]] = fir.embox %[[arg1]] : (!fir.ref) -> !fir.box + ! CHECK-DAG: %[[b:.*]] = fir.load %[[arg4]] : !fir.ref> + ! CHECK-DAG: %[[kind:.*]] = arith.constant 8 : i32 + ! CHECK-DAG: %[[dim:.*]] = fir.load %[[arg2]] : !fir.ref + ! CHECK-DAG: %[[res:.*]] = fir.convert %[[r]] : (!fir.ref>>>) -> !fir.ref> + ! CHECK-DAG: %[[arr:.*]] = fir.convert %[[arg0]] : (!fir.box>) -> !fir.box + ! CHECK-DAG: %[[val:.*]] = fir.convert %[[v]] : (!fir.box) -> !fir.box + ! CHECK-DAG: %[[mask:.*]] = fir.convert %[[arg3]] : (!fir.box>>) -> !fir.box + ! 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 : (!fir.ref>, !fir.box, !fir.box, i32, i32, !fir.ref, i32, !fir.box, i1) -> none + ! CHECK: %[[box:.*]] = fir.load %[[r]] : !fir.ref>>> + ! CHECK: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box>>) -> !fir.heap> + ! CHECK: fir.freemem %[[addr]] : !fir.heap> +end subroutine findloc_test_all