diff --git a/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h b/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h --- a/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h +++ b/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h @@ -387,6 +387,7 @@ fir::runtime::RuntimeTableEntry, \ 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: . 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 @@ -165,6 +165,42 @@ 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 --- a/flang/lib/Lower/IntrinsicCall.cpp +++ b/flang/lib/Lower/IntrinsicCall.cpp @@ -175,10 +175,10 @@ }); } -/// Process calls to Product, Sum intrinsic functions +/// Process calls to Product, Sum, IAll, IAny, IParity intrinsic functions template 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 args) { @@ -500,9 +500,11 @@ mlir::ArrayRef args); void genGetCommandArgument(mlir::ArrayRef args); void genGetEnvironmentVariable(llvm::ArrayRef); + fir::ExtendedValue genIall(mlir::Type, llvm::ArrayRef); /// Lowering for the IAND intrinsic. The IAND intrinsic expects two arguments /// in the llvm::ArrayRef. mlir::Value genIand(mlir::Type, llvm::ArrayRef); + fir::ExtendedValue genIany(mlir::Type, llvm::ArrayRef); mlir::Value genIbclr(mlir::Type, llvm::ArrayRef); mlir::Value genIbits(mlir::Type, llvm::ArrayRef); mlir::Value genIbset(mlir::Type, llvm::ArrayRef); @@ -514,6 +516,7 @@ mlir::Value genIeor(mlir::Type, llvm::ArrayRef); fir::ExtendedValue genIndex(mlir::Type, llvm::ArrayRef); mlir::Value genIor(mlir::Type, llvm::ArrayRef); + fir::ExtendedValue genIparity(mlir::Type, llvm::ArrayRef); mlir::Value genIshft(mlir::Type, llvm::ArrayRef); mlir::Value genIshftc(mlir::Type, llvm::ArrayRef); fir::ExtendedValue genLbound(mlir::Type, llvm::ArrayRef); @@ -802,7 +805,19 @@ {"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 @@ {"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 @@ } } +// IALL +fir::ExtendedValue +IntrinsicLibrary::genIall(mlir::Type resultType, + llvm::ArrayRef 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 args) { @@ -3093,6 +3123,15 @@ return builder.create(loc, arg0, arg1); } +// IANY +fir::ExtendedValue +IntrinsicLibrary::genIany(mlir::Type resultType, + llvm::ArrayRef 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 args) { @@ -3317,6 +3356,15 @@ return builder.create(loc, args[0], args[1]); } +// IPARITY +fir::ExtendedValue +IntrinsicLibrary::genIparity(mlir::Type resultType, + llvm::ArrayRef 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 args) { @@ -3824,7 +3872,7 @@ fir::ExtendedValue IntrinsicLibrary::genProduct(mlir::Type resultType, llvm::ArrayRef 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 @@ fir::ExtendedValue IntrinsicLibrary::genSum(mlir::Type resultType, llvm::ArrayRef 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 --- 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 @@ } }; +/// 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()(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()(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()(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 @@ -942,3 +994,78 @@ return builder.create(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().getEleTy(); \ + auto dim = builder.createIntegerConstant(loc, builder.getIndexType(), 0); \ + \ + if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(1))) \ + func = fir::runtime::getRuntimeFunc(loc, builder); \ + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(2))) \ + func = fir::runtime::getRuntimeFunc(loc, builder); \ + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(4))) \ + func = fir::runtime::getRuntimeFunc(loc, builder); \ + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(8))) \ + func = fir::runtime::getRuntimeFunc(loc, builder); \ + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(16))) \ + func = fir::runtime::getRuntimeFunc(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(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(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(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(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 --- /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>{{.*}}) -> 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 +! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box>) -> !fir.box +! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32 +! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box) -> !fir.box +iall_test_1 = iall(a) +! CHECK: %{{.*}} = fir.call @_FortranAIAll1(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box, !fir.ref, i32, i32, !fir.box) -> i8 +end function + +! CHECK-LABEL: func @_QPiall_test_2( +! CHECK-SAME: %[[arg0:.*]]: !fir.box>{{.*}}) -> 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 +! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box>) -> !fir.box +! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32 +! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box) -> !fir.box +iall_test_2 = iall(a) +! CHECK: %{{.*}} = fir.call @_FortranAIAll2(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box, !fir.ref, i32, i32, !fir.box) -> i16 +end function + +! CHECK-LABEL: func @_QPiall_test_4( +! CHECK-SAME: %[[arg0:.*]]: !fir.box>{{.*}}) -> i32 { +integer function iall_test_4(a) +integer :: a(:) +! CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index +! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box +! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box>) -> !fir.box +! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32 +! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box) -> !fir.box +iall_test_4 = iall(a) +! CHECK: %{{.*}} = fir.call @_FortranAIAll4(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box, !fir.ref, i32, i32, !fir.box) -> i32 +end function + +! CHECK-LABEL: func @_QPiall_test_8( +! CHECK-SAME: %[[arg0:.*]]: !fir.box>{{.*}}) -> 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 +! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box>) -> !fir.box +! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32 +! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box) -> !fir.box +iall_test_8 = iall(a) +! CHECK: %{{.*}} = fir.call @_FortranAIAll8(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box, !fir.ref, i32, i32, !fir.box) -> i64 +end function + +! CHECK-LABEL: func @_QPiall_test_16( +! CHECK-SAME: %[[arg0:.*]]: !fir.box>{{.*}}) -> 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 +! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box>) -> !fir.box +! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32 +! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box) -> !fir.box +iall_test_16 = iall(a) +! CHECK: %{{.*}} = fir.call @_FortranAIAll16(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box, !fir.ref, i32, i32, !fir.box) -> i128 +end function + +! CHECK-LABEL: func @_QPiall_test2( +! CHECK-SAME: %[[arg0:.*]]: !fir.box>{{.*}}, %[[arg1:.*]]: !fir.box>{{.*}}) { +subroutine iall_test2(a,r) +integer :: a(:,:) +integer :: r(:) +! CHECK-DAG: %[[c2_i32:.*]] = arith.constant 2 : i32 +! CHECK-DAG: %[[a0:.*]] = fir.alloca !fir.box>> +! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box +! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a0]] : (!fir.ref>>>) -> !fir.ref> +! CHECK-DAG: %[[a7:.*]] = fir.convert %[[arg0]] : (!fir.box>) -> !fir.box +! CHECK-DAG: %[[a9:.*]] = fir.convert %[[a1]] : (!fir.box) -> !fir.box +r = iall(a,dim=2) +! CHECK: %{{.*}} = fir.call @_FortranAIAllDim(%[[a6]], %[[a7]], %[[c2_i32]], %{{.*}}, %{{.*}}, %[[a9]]) : (!fir.ref>, !fir.box, i32, !fir.ref, i32, !fir.box) -> none +! CHECK-DAG: %[[a11:.*]] = fir.load %[[a0]] : !fir.ref>>> +! CHECK-DAG: %[[a13:.*]] = fir.box_addr %[[a11]] : (!fir.box>>) -> !fir.heap> +! CHECK-DAG: fir.freemem %[[a13]] +end subroutine + +! CHECK-LABEL: func @_QPiall_test_optional( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.box>> +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.box +! CHECK: fir.call @_FortranAIAll4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_9]]) : (!fir.box, !fir.ref, i32, i32, !fir.box) -> i32 +end function + +! CHECK-LABEL: func @_QPiall_test_optional_2( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref>>>> +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>>>> +! CHECK: %[[VAL_5:.*]] = fir.box_addr %[[VAL_4]] : (!fir.box>>>) -> !fir.ptr>> +! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_5]] : (!fir.ptr>>) -> 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>>>> +! CHECK: %[[VAL_10:.*]] = fir.absent !fir.box>>> +! CHECK: %[[VAL_11:.*]] = arith.select %[[VAL_8]], %[[VAL_9]], %[[VAL_10]] : !fir.box>>> +! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_11]] : (!fir.box>>>) -> !fir.box +! CHECK: fir.call @_FortranAIAll4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_18]]) : (!fir.box, !fir.ref, i32, i32, !fir.box) -> i32 +end function + +! CHECK-LABEL: func @_QPiall_test_optional_3( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref>> +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>>) -> i1 +! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_7:.*]] = fir.embox %[[VAL_0]](%[[VAL_6]]) : (!fir.ref>>, !fir.shape<1>) -> !fir.box>> +! CHECK: %[[VAL_8:.*]] = fir.absent !fir.box>> +! CHECK: %[[VAL_9:.*]] = arith.select %[[VAL_5]], %[[VAL_7]], %[[VAL_8]] : !fir.box>> +! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_9]] : (!fir.box>>) -> !fir.box +! CHECK: fir.call @_FortranAIAll4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_18]]) : (!fir.box, !fir.ref, i32, i32, !fir.box) -> 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>>> +! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (!fir.heap>>) -> 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 +! CHECK: %[[VAL_25:.*]] = fir.load %[[VAL_5:.*]] : !fir.ref +! CHECK: %[[VAL_26:.*]] = fir.load %[[VAL_3]] : !fir.ref>>> +! 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.shapeshift<1>) -> !fir.box>> +! CHECK: %[[VAL_29:.*]] = fir.absent !fir.box>> +! CHECK: %[[VAL_30:.*]] = arith.select %[[VAL_23]], %[[VAL_28]], %[[VAL_29]] : !fir.box>> +! CHECK: %[[VAL_37:.*]] = fir.convert %[[VAL_30]] : (!fir.box>>) -> !fir.box +! CHECK: fir.call @_FortranAIAll4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_37]]) : (!fir.box, !fir.ref, i32, i32, !fir.box) -> i32 +end function diff --git a/flang/test/Lower/Intrinsics/iany.f90 b/flang/test/Lower/Intrinsics/iany.f90 new file mode 100644 --- /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>{{.*}}) -> 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 +! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box>) -> !fir.box +! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32 +! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box) -> !fir.box +iany_test_1 = iany(a) +! CHECK: %{{.*}} = fir.call @_FortranAIAny1(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box, !fir.ref, i32, i32, !fir.box) -> i8 +end function + +! CHECK-LABEL: func @_QPiany_test_2( +! CHECK-SAME: %[[arg0:.*]]: !fir.box>{{.*}}) -> 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 +! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box>) -> !fir.box +! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32 +! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box) -> !fir.box +iany_test_2 = iany(a) +! CHECK: %{{.*}} = fir.call @_FortranAIAny2(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box, !fir.ref, i32, i32, !fir.box) -> i16 +end function + +! CHECK-LABEL: func @_QPiany_test_4( +! CHECK-SAME: %[[arg0:.*]]: !fir.box>{{.*}}) -> i32 { +integer function iany_test_4(a) +integer :: a(:) +! CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index +! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box +! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box>) -> !fir.box +! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32 +! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box) -> !fir.box +iany_test_4 = iany(a) +! CHECK: %{{.*}} = fir.call @_FortranAIAny4(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box, !fir.ref, i32, i32, !fir.box) -> i32 +end function + +! CHECK-LABEL: func @_QPiany_test_8( +! CHECK-SAME: %[[arg0:.*]]: !fir.box>{{.*}}) -> 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 +! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box>) -> !fir.box +! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32 +! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box) -> !fir.box +iany_test_8 = iany(a) +! CHECK: %{{.*}} = fir.call @_FortranAIAny8(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box, !fir.ref, i32, i32, !fir.box) -> i64 +end function + +! CHECK-LABEL: func @_QPiany_test_16( +! CHECK-SAME: %[[arg0:.*]]: !fir.box>{{.*}}) -> 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 +! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box>) -> !fir.box +! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32 +! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box) -> !fir.box +iany_test_16 = iany(a) +! CHECK: %{{.*}} = fir.call @_FortranAIAny16(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box, !fir.ref, i32, i32, !fir.box) -> i128 +end function + +! CHECK-LABEL: func @_QPiany_test2( +! CHECK-SAME: %[[arg0:.*]]: !fir.box>{{.*}}, %[[arg1:.*]]: !fir.box>{{.*}}) { +subroutine iany_test2(a,r) +integer :: a(:,:) +integer :: r(:) +! CHECK-DAG: %[[c2_i32:.*]] = arith.constant 2 : i32 +! CHECK-DAG: %[[a0:.*]] = fir.alloca !fir.box>> +! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box +! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a0]] : (!fir.ref>>>) -> !fir.ref> +! CHECK-DAG: %[[a7:.*]] = fir.convert %[[arg0]] : (!fir.box>) -> !fir.box +! CHECK-DAG: %[[a9:.*]] = fir.convert %[[a1]] : (!fir.box) -> !fir.box +r = iany(a,dim=2) +! CHECK: %{{.*}} = fir.call @_FortranAIAnyDim(%[[a6]], %[[a7]], %[[c2_i32]], %{{.*}}, %{{.*}}, %[[a9]]) : (!fir.ref>, !fir.box, i32, !fir.ref, i32, !fir.box) -> none +! CHECK-DAG: %[[a11:.*]] = fir.load %[[a0]] : !fir.ref>>> +! CHECK-DAG: %[[a13:.*]] = fir.box_addr %[[a11]] : (!fir.box>>) -> !fir.heap> +! CHECK-DAG: fir.freemem %[[a13]] +end subroutine + +! CHECK-LABEL: func @_QPiany_test_optional( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.box>> +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.box +! CHECK: fir.call @_FortranAIAny4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_9]]) : (!fir.box, !fir.ref, i32, i32, !fir.box) -> i32 +end function + +! CHECK-LABEL: func @_QPiany_test_optional_2( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref>>>> +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>>>> +! CHECK: %[[VAL_5:.*]] = fir.box_addr %[[VAL_4]] : (!fir.box>>>) -> !fir.ptr>> +! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_5]] : (!fir.ptr>>) -> 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>>>> +! CHECK: %[[VAL_10:.*]] = fir.absent !fir.box>>> +! CHECK: %[[VAL_11:.*]] = arith.select %[[VAL_8]], %[[VAL_9]], %[[VAL_10]] : !fir.box>>> +! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_11]] : (!fir.box>>>) -> !fir.box +! CHECK: fir.call @_FortranAIAny4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_18]]) : (!fir.box, !fir.ref, i32, i32, !fir.box) -> i32 +end function + +! CHECK-LABEL: func @_QPiany_test_optional_3( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref>> +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>>) -> i1 +! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_7:.*]] = fir.embox %[[VAL_0]](%[[VAL_6]]) : (!fir.ref>>, !fir.shape<1>) -> !fir.box>> +! CHECK: %[[VAL_8:.*]] = fir.absent !fir.box>> +! CHECK: %[[VAL_9:.*]] = arith.select %[[VAL_5]], %[[VAL_7]], %[[VAL_8]] : !fir.box>> +! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_9]] : (!fir.box>>) -> !fir.box +! CHECK: fir.call @_FortranAIAny4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_18]]) : (!fir.box, !fir.ref, i32, i32, !fir.box) -> 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>>> +! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (!fir.heap>>) -> 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 +! CHECK: %[[VAL_25:.*]] = fir.load %[[VAL_5:.*]] : !fir.ref +! CHECK: %[[VAL_26:.*]] = fir.load %[[VAL_3]] : !fir.ref>>> +! 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.shapeshift<1>) -> !fir.box>> +! CHECK: %[[VAL_29:.*]] = fir.absent !fir.box>> +! CHECK: %[[VAL_30:.*]] = arith.select %[[VAL_23]], %[[VAL_28]], %[[VAL_29]] : !fir.box>> +! CHECK: %[[VAL_37:.*]] = fir.convert %[[VAL_30]] : (!fir.box>>) -> !fir.box +! CHECK: fir.call @_FortranAIAny4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_37]]) : (!fir.box, !fir.ref, i32, i32, !fir.box) -> i32 +end function diff --git a/flang/test/Lower/Intrinsics/iparity.f90 b/flang/test/Lower/Intrinsics/iparity.f90 new file mode 100644 --- /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>{{.*}}) -> 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 +! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box>) -> !fir.box +! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32 +! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box) -> !fir.box +iparity_test_1 = iparity(a) +! CHECK: %{{.*}} = fir.call @_FortranAIParity1(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box, !fir.ref, i32, i32, !fir.box) -> i8 +end function + +! CHECK-LABEL: func @_QPiparity_test_2( +! CHECK-SAME: %[[arg0:.*]]: !fir.box>{{.*}}) -> 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 +! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box>) -> !fir.box +! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32 +! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box) -> !fir.box +iparity_test_2 = iparity(a) +! CHECK: %{{.*}} = fir.call @_FortranAIParity2(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box, !fir.ref, i32, i32, !fir.box) -> i16 +end function + +! CHECK-LABEL: func @_QPiparity_test_4( +! CHECK-SAME: %[[arg0:.*]]: !fir.box>{{.*}}) -> i32 { +integer function iparity_test_4(a) +integer :: a(:) +! CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index +! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box +! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box>) -> !fir.box +! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32 +! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box) -> !fir.box +iparity_test_4 = iparity(a) +! CHECK: %{{.*}} = fir.call @_FortranAIParity4(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box, !fir.ref, i32, i32, !fir.box) -> i32 +end function + +! CHECK-LABEL: func @_QPiparity_test_8( +! CHECK-SAME: %[[arg0:.*]]: !fir.box>{{.*}}) -> 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 +! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box>) -> !fir.box +! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32 +! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box) -> !fir.box +iparity_test_8 = iparity(a) +! CHECK: %{{.*}} = fir.call @_FortranAIParity8(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box, !fir.ref, i32, i32, !fir.box) -> i64 +end function + +! CHECK-LABEL: func @_QPiparity_test_16( +! CHECK-SAME: %[[arg0:.*]]: !fir.box>{{.*}}) -> 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 +! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box>) -> !fir.box +! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32 +! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box) -> !fir.box +iparity_test_16 = iparity(a) +! CHECK: %{{.*}} = fir.call @_FortranAIParity16(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box, !fir.ref, i32, i32, !fir.box) -> i128 +end function + +! CHECK-LABEL: func @_QPiparity_test2( +! CHECK-SAME: %[[arg0:.*]]: !fir.box>{{.*}}, %[[arg1:.*]]: !fir.box>{{.*}}) { +subroutine iparity_test2(a,r) +integer :: a(:,:) +integer :: r(:) +! CHECK-DAG: %[[c2_i32:.*]] = arith.constant 2 : i32 +! CHECK-DAG: %[[a0:.*]] = fir.alloca !fir.box>> +! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box +! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a0]] : (!fir.ref>>>) -> !fir.ref> +! CHECK-DAG: %[[a7:.*]] = fir.convert %[[arg0]] : (!fir.box>) -> !fir.box +! CHECK-DAG: %[[a9:.*]] = fir.convert %[[a1]] : (!fir.box) -> !fir.box +r = iparity(a,dim=2) +! CHECK: %{{.*}} = fir.call @_FortranAIParityDim(%[[a6]], %[[a7]], %[[c2_i32]], %{{.*}}, %{{.*}}, %[[a9]]) : (!fir.ref>, !fir.box, i32, !fir.ref, i32, !fir.box) -> none +! CHECK-DAG: %[[a11:.*]] = fir.load %[[a0]] : !fir.ref>>> +! CHECK-DAG: %[[a13:.*]] = fir.box_addr %[[a11]] : (!fir.box>>) -> !fir.heap> +! CHECK-DAG: fir.freemem %[[a13]] +end subroutine + +! CHECK-LABEL: func @_QPiparity_test_optional( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.box>> +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.box +! CHECK: fir.call @_FortranAIParity4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_9]]) : (!fir.box, !fir.ref, i32, i32, !fir.box) -> i32 +end function + +! CHECK-LABEL: func @_QPiparity_test_optional_2( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref>>>> +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>>>> +! CHECK: %[[VAL_5:.*]] = fir.box_addr %[[VAL_4]] : (!fir.box>>>) -> !fir.ptr>> +! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_5]] : (!fir.ptr>>) -> 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>>>> +! CHECK: %[[VAL_10:.*]] = fir.absent !fir.box>>> +! CHECK: %[[VAL_11:.*]] = arith.select %[[VAL_8]], %[[VAL_9]], %[[VAL_10]] : !fir.box>>> +! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_11]] : (!fir.box>>>) -> !fir.box +! CHECK: fir.call @_FortranAIParity4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_18]]) : (!fir.box, !fir.ref, i32, i32, !fir.box) -> i32 +end function + +! CHECK-LABEL: func @_QPiparity_test_optional_3( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref>> +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>>) -> i1 +! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_7:.*]] = fir.embox %[[VAL_0]](%[[VAL_6]]) : (!fir.ref>>, !fir.shape<1>) -> !fir.box>> +! CHECK: %[[VAL_8:.*]] = fir.absent !fir.box>> +! CHECK: %[[VAL_9:.*]] = arith.select %[[VAL_5]], %[[VAL_7]], %[[VAL_8]] : !fir.box>> +! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_9]] : (!fir.box>>) -> !fir.box +! CHECK: fir.call @_FortranAIParity4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_18]]) : (!fir.box, !fir.ref, i32, i32, !fir.box) -> 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>>> +! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (!fir.heap>>) -> 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 +! CHECK: %[[VAL_25:.*]] = fir.load %[[VAL_5:.*]] : !fir.ref +! CHECK: %[[VAL_26:.*]] = fir.load %[[VAL_3]] : !fir.ref>>> +! 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.shapeshift<1>) -> !fir.box>> +! CHECK: %[[VAL_29:.*]] = fir.absent !fir.box>> +! CHECK: %[[VAL_30:.*]] = arith.select %[[VAL_23]], %[[VAL_28]], %[[VAL_29]] : !fir.box>> +! CHECK: %[[VAL_37:.*]] = fir.convert %[[VAL_30]] : (!fir.box>>) -> !fir.box +! CHECK: fir.call @_FortranAIParity4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_37]]) : (!fir.box, !fir.ref, i32, i32, !fir.box) -> i32 +end function