[flang] Lower F08 bitwise-reduction intrinsics (IALL, IANY, IPARITY)

This calls the corresponding runtime functions when appropriate. The implementation
follows the pattern of the SUM and PRODUCT intrinsics.

Differential Revision: https://reviews.llvm.org/D129616
This commit is contained in:
Tarun Prabhu 2022-09-26 10:14:17 -06:00
parent 9d259916e1
commit ebfe8a7411
7 changed files with 684 additions and 4 deletions

View File

@ -387,6 +387,7 @@ struct RuntimeTableEntry<RuntimeTableKey<KT>, RuntimeIdentifier<Cs...>> {
fir::runtime::RuntimeTableEntry<fir::runtime::RuntimeTableKey<decltype(X)>, \
FirAsSequence(X)>
#define mkRTKey(X) FirmkKey(RTNAME(X))
#define EXPAND_AND_QUOTE_KEY(S) ExpandAndQuoteKey(RTNAME(S))
/// Get (or generate) the MLIR FuncOp for a given runtime function. Its template
/// argument is intended to be of the form: <mkRTKey(runtime function name)>.

View File

@ -165,6 +165,42 @@ void genSumDim(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value resultBox, mlir::Value arrayBox, mlir::Value dim,
mlir::Value maskBox);
/// Generate call to `IAll` intrinsic runtime routine. This is the version
/// that does not take a dim argument.
mlir::Value genIAll(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value arrayBox, mlir::Value maskBox,
mlir::Value resultBox);
/// Generate call to `IAllDim` intrinsic runtime routine. This is the version
/// that takes arrays of any rank with a dim argument specified.
void genIAllDim(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value resultBox, mlir::Value arrayBox, mlir::Value dim,
mlir::Value maskBox);
/// Generate call to `IAny` intrinsic runtime routine. This is the version
/// that does not take a dim argument.
mlir::Value genIAny(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value arrayBox, mlir::Value maskBox,
mlir::Value resultBox);
/// Generate call to `IAnyDim` intrinsic runtime routine. This is the version
/// that takes arrays of any rank with a dim argument specified.
void genIAnyDim(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value resultBox, mlir::Value arrayBox, mlir::Value dim,
mlir::Value maskBox);
/// Generate call to `IParity` intrinsic runtime routine. This is the version
/// that does not take a dim argument.
mlir::Value genIParity(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value arrayBox, mlir::Value maskBox,
mlir::Value resultBox);
/// Generate call to `IParityDim` intrinsic runtime routine. This is the version
/// that takes arrays of any rank with a dim argument specified.
void genIParityDim(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value resultBox, mlir::Value arrayBox, mlir::Value dim,
mlir::Value maskBox);
} // namespace fir::runtime
#endif // FORTRAN_OPTIMIZER_BUILDER_RUNTIME_REDUCTION_H

View File

@ -175,10 +175,10 @@ genFuncDim(FD funcDim, mlir::Type resultType, fir::FirOpBuilder &builder,
});
}
/// Process calls to Product, Sum intrinsic functions
/// Process calls to Product, Sum, IAll, IAny, IParity intrinsic functions
template <typename FN, typename FD>
static fir::ExtendedValue
genProdOrSum(FN func, FD funcDim, mlir::Type resultType,
genReduction(FN func, FD funcDim, mlir::Type resultType,
fir::FirOpBuilder &builder, mlir::Location loc,
Fortran::lower::StatementContext *stmtCtx, llvm::StringRef errMsg,
llvm::ArrayRef<fir::ExtendedValue> args) {
@ -500,9 +500,11 @@ struct IntrinsicLibrary {
mlir::ArrayRef<mlir::Value> args);
void genGetCommandArgument(mlir::ArrayRef<fir::ExtendedValue> args);
void genGetEnvironmentVariable(llvm::ArrayRef<fir::ExtendedValue>);
fir::ExtendedValue genIall(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
/// Lowering for the IAND intrinsic. The IAND intrinsic expects two arguments
/// in the llvm::ArrayRef.
mlir::Value genIand(mlir::Type, llvm::ArrayRef<mlir::Value>);
fir::ExtendedValue genIany(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
mlir::Value genIbclr(mlir::Type, llvm::ArrayRef<mlir::Value>);
mlir::Value genIbits(mlir::Type, llvm::ArrayRef<mlir::Value>);
mlir::Value genIbset(mlir::Type, llvm::ArrayRef<mlir::Value>);
@ -514,6 +516,7 @@ struct IntrinsicLibrary {
mlir::Value genIeor(mlir::Type, llvm::ArrayRef<mlir::Value>);
fir::ExtendedValue genIndex(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
mlir::Value genIor(mlir::Type, llvm::ArrayRef<mlir::Value>);
fir::ExtendedValue genIparity(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
mlir::Value genIshft(mlir::Type, llvm::ArrayRef<mlir::Value>);
mlir::Value genIshftc(mlir::Type, llvm::ArrayRef<mlir::Value>);
fir::ExtendedValue genLbound(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
@ -802,7 +805,19 @@ static constexpr IntrinsicHandler handlers[]{
{"errmsg", asBox, handleDynamicOptional}}},
/*isElemental=*/false},
{"iachar", &I::genIchar},
{"iall",
&I::genIall,
{{{"array", asBox},
{"dim", asValue},
{"mask", asBox, handleDynamicOptional}}},
/*isElemental=*/false},
{"iand", &I::genIand},
{"iany",
&I::genIany,
{{{"array", asBox},
{"dim", asValue},
{"mask", asBox, handleDynamicOptional}}},
/*isElemental=*/false},
{"ibclr", &I::genIbclr},
{"ibits", &I::genIbits},
{"ibset", &I::genIbset},
@ -820,6 +835,12 @@ static constexpr IntrinsicHandler handlers[]{
{"back", asValue, handleDynamicOptional},
{"kind", asValue}}}},
{"ior", &I::genIor},
{"iparity",
&I::genIparity,
{{{"array", asBox},
{"dim", asValue},
{"mask", asBox, handleDynamicOptional}}},
/*isElemental=*/false},
{"ishft", &I::genIshft},
{"ishftc", &I::genIshftc},
{"lbound",
@ -3084,6 +3105,15 @@ void IntrinsicLibrary::genGetEnvironmentVariable(
}
}
// IALL
fir::ExtendedValue
IntrinsicLibrary::genIall(mlir::Type resultType,
llvm::ArrayRef<fir::ExtendedValue> args) {
return genReduction(fir::runtime::genIAll, fir::runtime::genIAllDim,
resultType, builder, loc, stmtCtx,
"unexpected result for IALL", args);
}
// IAND
mlir::Value IntrinsicLibrary::genIand(mlir::Type resultType,
llvm::ArrayRef<mlir::Value> args) {
@ -3093,6 +3123,15 @@ mlir::Value IntrinsicLibrary::genIand(mlir::Type resultType,
return builder.create<mlir::arith::AndIOp>(loc, arg0, arg1);
}
// IANY
fir::ExtendedValue
IntrinsicLibrary::genIany(mlir::Type resultType,
llvm::ArrayRef<fir::ExtendedValue> args) {
return genReduction(fir::runtime::genIAny, fir::runtime::genIAnyDim,
resultType, builder, loc, stmtCtx,
"unexpected result for IANY", args);
}
// IBCLR
mlir::Value IntrinsicLibrary::genIbclr(mlir::Type resultType,
llvm::ArrayRef<mlir::Value> args) {
@ -3317,6 +3356,15 @@ mlir::Value IntrinsicLibrary::genIor(mlir::Type resultType,
return builder.create<mlir::arith::OrIOp>(loc, args[0], args[1]);
}
// IPARITY
fir::ExtendedValue
IntrinsicLibrary::genIparity(mlir::Type resultType,
llvm::ArrayRef<fir::ExtendedValue> args) {
return genReduction(fir::runtime::genIParity, fir::runtime::genIParityDim,
resultType, builder, loc, stmtCtx,
"unexpected result for IPARITY", args);
}
// ISHFT
mlir::Value IntrinsicLibrary::genIshft(mlir::Type resultType,
llvm::ArrayRef<mlir::Value> args) {
@ -3824,7 +3872,7 @@ IntrinsicLibrary::genPresent(mlir::Type,
fir::ExtendedValue
IntrinsicLibrary::genProduct(mlir::Type resultType,
llvm::ArrayRef<fir::ExtendedValue> args) {
return genProdOrSum(fir::runtime::genProduct, fir::runtime::genProductDim,
return genReduction(fir::runtime::genProduct, fir::runtime::genProductDim,
resultType, builder, loc, stmtCtx,
"unexpected result for Product", args);
}
@ -4424,7 +4472,7 @@ IntrinsicLibrary::genSpread(mlir::Type resultType,
fir::ExtendedValue
IntrinsicLibrary::genSum(mlir::Type resultType,
llvm::ArrayRef<fir::ExtendedValue> args) {
return genProdOrSum(fir::runtime::genSum, fir::runtime::genSumDim, resultType,
return genReduction(fir::runtime::genSum, fir::runtime::genSumDim, resultType,
builder, loc, stmtCtx, "unexpected result for Sum", args);
}

View File

@ -17,6 +17,10 @@
using namespace Fortran::runtime;
#define STRINGIFY(S) #S
#define JOIN2(A, B) A##B
#define JOIN3(A, B, C) A##B##C
/// Placeholder for real*10 version of Maxval Intrinsic
struct ForcedMaxvalReal10 {
static constexpr const char *name = ExpandAndQuoteKey(RTNAME(MaxvalReal10));
@ -368,6 +372,54 @@ struct ForcedSumComplex16 {
}
};
/// Placeholder for integer(16) version of IAll Intrinsic
struct ForcedIAll16 {
static constexpr const char *name = EXPAND_AND_QUOTE_KEY(IAll16);
static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
return [](mlir::MLIRContext *ctx) {
auto ty = mlir::IntegerType::get(ctx, 128);
auto boxTy =
fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy},
{ty});
};
}
};
/// Placeholder for integer(16) version of IAny Intrinsic
struct ForcedIAny16 {
static constexpr const char *name = EXPAND_AND_QUOTE_KEY(IAny16);
static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
return [](mlir::MLIRContext *ctx) {
auto ty = mlir::IntegerType::get(ctx, 128);
auto boxTy =
fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy},
{ty});
};
}
};
/// Placeholder for integer(16) version of IParity Intrinsic
struct ForcedIParity16 {
static constexpr const char *name = EXPAND_AND_QUOTE_KEY(IParity16);
static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
return [](mlir::MLIRContext *ctx) {
auto ty = mlir::IntegerType::get(ctx, 128);
auto boxTy =
fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy},
{ty});
};
}
};
/// Generate call to specialized runtime function that takes a mask and
/// dim argument. The All, Any, and Count intrinsics use this pattern.
template <typename FN>
@ -942,3 +994,78 @@ mlir::Value fir::runtime::genSum(fir::FirOpBuilder &builder, mlir::Location loc,
return builder.create<fir::CallOp>(loc, func, args).getResult(0);
}
// The IAll, IAny and IParity intrinsics have essentially the same
// implementation. This macro will generate the function body given the
// instrinsic name.
#define GEN_IALL_IANY_IPARITY(F) \
mlir::Value fir::runtime::JOIN2(gen, F)( \
fir::FirOpBuilder & builder, mlir::Location loc, mlir::Value arrayBox, \
mlir::Value maskBox, mlir::Value resultBox) { \
mlir::func::FuncOp func; \
auto ty = arrayBox.getType(); \
auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty); \
auto eleTy = arrTy.cast<fir::SequenceType>().getEleTy(); \
auto dim = builder.createIntegerConstant(loc, builder.getIndexType(), 0); \
\
if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(1))) \
func = fir::runtime::getRuntimeFunc<mkRTKey(JOIN2(F, 1))>(loc, builder); \
else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(2))) \
func = fir::runtime::getRuntimeFunc<mkRTKey(JOIN2(F, 2))>(loc, builder); \
else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(4))) \
func = fir::runtime::getRuntimeFunc<mkRTKey(JOIN2(F, 4))>(loc, builder); \
else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(8))) \
func = fir::runtime::getRuntimeFunc<mkRTKey(JOIN2(F, 8))>(loc, builder); \
else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(16))) \
func = fir::runtime::getRuntimeFunc<JOIN3(Forced, F, 16)>(loc, builder); \
else \
fir::emitFatalError(loc, "invalid type in " STRINGIFY(F)); \
\
auto fTy = func.getFunctionType(); \
auto sourceFile = fir::factory::locationToFilename(builder, loc); \
auto sourceLine = \
fir::factory::locationToLineNo(builder, loc, fTy.getInput(2)); \
auto args = fir::runtime::createArguments( \
builder, loc, fTy, arrayBox, sourceFile, sourceLine, dim, maskBox); \
\
return builder.create<fir::CallOp>(loc, func, args).getResult(0); \
}
/// Generate call to `IAllDim` intrinsic runtime routine. This is the version
/// that handles any rank array with the dim argument specified.
void fir::runtime::genIAllDim(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value resultBox, mlir::Value arrayBox,
mlir::Value dim, mlir::Value maskBox) {
auto func = fir::runtime::getRuntimeFunc<mkRTKey(IAllDim)>(loc, builder);
genReduction3Args(func, builder, loc, resultBox, arrayBox, dim, maskBox);
}
/// Generate call to `IAll` intrinsic runtime routine. This is the version
/// that does not take a dim argument.
GEN_IALL_IANY_IPARITY(IAll)
/// Generate call to `IAnyDim` intrinsic runtime routine. This is the version
/// that handles any rank array with the dim argument specified.
void fir::runtime::genIAnyDim(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value resultBox, mlir::Value arrayBox,
mlir::Value dim, mlir::Value maskBox) {
auto func = fir::runtime::getRuntimeFunc<mkRTKey(IAnyDim)>(loc, builder);
genReduction3Args(func, builder, loc, resultBox, arrayBox, dim, maskBox);
}
/// Generate call to `IAny` intrinsic runtime routine. This is the version
/// that does not take a dim argument.
GEN_IALL_IANY_IPARITY(IAny)
/// Generate call to `IParityDim` intrinsic runtime routine. This is the version
/// that handles any rank array with the dim argument specified.
void fir::runtime::genIParityDim(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value resultBox, mlir::Value arrayBox,
mlir::Value dim, mlir::Value maskBox) {
auto func = fir::runtime::getRuntimeFunc<mkRTKey(IParityDim)>(loc, builder);
genReduction3Args(func, builder, loc, resultBox, arrayBox, dim, maskBox);
}
/// Generate call to `IParity` intrinsic runtime routine. This is the version
/// that does not take a dim argument.
GEN_IALL_IANY_IPARITY(IParity)

View File

@ -0,0 +1,156 @@
! RUN: bbc -emit-fir %s -o - | FileCheck %s
! CHECK-LABEL: func @_QPiall_test_1(
! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?xi8>>{{.*}}) -> i8 {
integer(1) function iall_test_1(a)
integer(1) :: a(:)
! CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index
! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box<i1>
! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?xi8>>) -> !fir.box<none>
! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32
! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box<i1>) -> !fir.box<none>
iall_test_1 = iall(a)
! CHECK: %{{.*}} = fir.call @_FortranAIAll1(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i8
end function
! CHECK-LABEL: func @_QPiall_test_2(
! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?xi16>>{{.*}}) -> i16 {
integer(2) function iall_test_2(a)
integer(2) :: a(:)
! CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index
! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box<i1>
! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?xi16>>) -> !fir.box<none>
! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32
! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box<i1>) -> !fir.box<none>
iall_test_2 = iall(a)
! CHECK: %{{.*}} = fir.call @_FortranAIAll2(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i16
end function
! CHECK-LABEL: func @_QPiall_test_4(
! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?xi32>>{{.*}}) -> i32 {
integer function iall_test_4(a)
integer :: a(:)
! CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index
! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box<i1>
! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?xi32>>) -> !fir.box<none>
! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32
! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box<i1>) -> !fir.box<none>
iall_test_4 = iall(a)
! CHECK: %{{.*}} = fir.call @_FortranAIAll4(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i32
end function
! CHECK-LABEL: func @_QPiall_test_8(
! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?xi64>>{{.*}}) -> i64 {
integer(8) function iall_test_8(a)
integer(8) :: a(:)
! CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index
! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box<i1>
! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?xi64>>) -> !fir.box<none>
! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32
! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box<i1>) -> !fir.box<none>
iall_test_8 = iall(a)
! CHECK: %{{.*}} = fir.call @_FortranAIAll8(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i64
end function
! CHECK-LABEL: func @_QPiall_test_16(
! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?xi128>>{{.*}}) -> i128 {
integer(16) function iall_test_16(a)
integer(16) :: a(:)
! CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index
! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box<i1>
! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?xi128>>) -> !fir.box<none>
! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32
! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box<i1>) -> !fir.box<none>
iall_test_16 = iall(a)
! CHECK: %{{.*}} = fir.call @_FortranAIAll16(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i128
end function
! CHECK-LABEL: func @_QPiall_test2(
! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?x?xi32>>{{.*}}, %[[arg1:.*]]: !fir.box<!fir.array<?xi32>>{{.*}}) {
subroutine iall_test2(a,r)
integer :: a(:,:)
integer :: r(:)
! CHECK-DAG: %[[c2_i32:.*]] = arith.constant 2 : i32
! CHECK-DAG: %[[a0:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>>
! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box<i1>
! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a0]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<none>>
! CHECK-DAG: %[[a7:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?x?xi32>>) -> !fir.box<none>
! CHECK-DAG: %[[a9:.*]] = fir.convert %[[a1]] : (!fir.box<i1>) -> !fir.box<none>
r = iall(a,dim=2)
! CHECK: %{{.*}} = fir.call @_FortranAIAllDim(%[[a6]], %[[a7]], %[[c2_i32]], %{{.*}}, %{{.*}}, %[[a9]]) : (!fir.ref<!fir.box<none>>, !fir.box<none>, i32, !fir.ref<i8>, i32, !fir.box<none>) -> none
! CHECK-DAG: %[[a11:.*]] = fir.load %[[a0]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
! CHECK-DAG: %[[a13:.*]] = fir.box_addr %[[a11]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
! CHECK-DAG: fir.freemem %[[a13]]
end subroutine
! CHECK-LABEL: func @_QPiall_test_optional(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?x!fir.logical<4>>>
integer function iall_test_optional(mask, x)
integer :: x(:)
logical, optional :: mask(:)
iall_test_optional = iall(x, mask=mask)
! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_0]] : (!fir.box<!fir.array<?x!fir.logical<4>>>) -> !fir.box<none>
! CHECK: fir.call @_FortranAIAll4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_9]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i32
end function
! CHECK-LABEL: func @_QPiall_test_optional_2(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>>
integer function iall_test_optional_2(mask, x)
integer :: x(:)
logical, pointer :: mask(:)
iall_test_optional_2 = iall(x, mask=mask)
! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>>
! CHECK: %[[VAL_5:.*]] = fir.box_addr %[[VAL_4]] : (!fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>) -> !fir.ptr<!fir.array<?x!fir.logical<4>>>
! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_5]] : (!fir.ptr<!fir.array<?x!fir.logical<4>>>) -> i64
! CHECK: %[[VAL_7:.*]] = arith.constant 0 : i64
! CHECK: %[[VAL_8:.*]] = arith.cmpi ne, %[[VAL_6]], %[[VAL_7]] : i64
! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>>
! CHECK: %[[VAL_10:.*]] = fir.absent !fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>
! CHECK: %[[VAL_11:.*]] = arith.select %[[VAL_8]], %[[VAL_9]], %[[VAL_10]] : !fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>
! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_11]] : (!fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>) -> !fir.box<none>
! CHECK: fir.call @_FortranAIAll4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_18]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i32
end function
! CHECK-LABEL: func @_QPiall_test_optional_3(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<10x!fir.logical<4>>>
integer function iall_test_optional_3(mask, x)
integer :: x(:)
logical, optional :: mask(10)
iall_test_optional_3 = iall(x, mask=mask)
! CHECK: %[[VAL_2:.*]] = arith.constant 10 : index
! CHECK: %[[VAL_5:.*]] = fir.is_present %[[VAL_0]] : (!fir.ref<!fir.array<10x!fir.logical<4>>>) -> i1
! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1>
! CHECK: %[[VAL_7:.*]] = fir.embox %[[VAL_0]](%[[VAL_6]]) : (!fir.ref<!fir.array<10x!fir.logical<4>>>, !fir.shape<1>) -> !fir.box<!fir.array<10x!fir.logical<4>>>
! CHECK: %[[VAL_8:.*]] = fir.absent !fir.box<!fir.array<10x!fir.logical<4>>>
! CHECK: %[[VAL_9:.*]] = arith.select %[[VAL_5]], %[[VAL_7]], %[[VAL_8]] : !fir.box<!fir.array<10x!fir.logical<4>>>
! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_9]] : (!fir.box<!fir.array<10x!fir.logical<4>>>) -> !fir.box<none>
! CHECK: fir.call @_FortranAIAll4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_18]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i32
end function
! CHECK-LABEL: func @_QPiall_test_optional_4(
integer function iall_test_optional_4(x, use_mask)
! Test that local allocatable tracked in local variables
! are dealt as optional argument correctly.
integer :: x(:)
logical :: use_mask
logical, allocatable :: mask(:)
if (use_mask) then
allocate(mask(size(x, 1)))
call set_mask(mask)
! CHECK: fir.call @_QPset_mask
end if
iall_test_optional_4 = iall(x, mask=mask)
! CHECK: %[[VAL_20:.*]] = fir.load %[[VAL_3:.*]] : !fir.ref<!fir.heap<!fir.array<?x!fir.logical<4>>>>
! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (!fir.heap<!fir.array<?x!fir.logical<4>>>) -> i64
! CHECK: %[[VAL_22:.*]] = arith.constant 0 : i64
! CHECK: %[[VAL_23:.*]] = arith.cmpi ne, %[[VAL_21]], %[[VAL_22]] : i64
! CHECK: %[[VAL_24:.*]] = fir.load %[[VAL_4:.*]] : !fir.ref<index>
! CHECK: %[[VAL_25:.*]] = fir.load %[[VAL_5:.*]] : !fir.ref<index>
! CHECK: %[[VAL_26:.*]] = fir.load %[[VAL_3]] : !fir.ref<!fir.heap<!fir.array<?x!fir.logical<4>>>>
! CHECK: %[[VAL_27:.*]] = fir.shape_shift %[[VAL_24]], %[[VAL_25]] : (index, index) -> !fir.shapeshift<1>
! CHECK: %[[VAL_28:.*]] = fir.embox %[[VAL_26]](%[[VAL_27]]) : (!fir.heap<!fir.array<?x!fir.logical<4>>>, !fir.shapeshift<1>) -> !fir.box<!fir.array<?x!fir.logical<4>>>
! CHECK: %[[VAL_29:.*]] = fir.absent !fir.box<!fir.array<?x!fir.logical<4>>>
! CHECK: %[[VAL_30:.*]] = arith.select %[[VAL_23]], %[[VAL_28]], %[[VAL_29]] : !fir.box<!fir.array<?x!fir.logical<4>>>
! CHECK: %[[VAL_37:.*]] = fir.convert %[[VAL_30]] : (!fir.box<!fir.array<?x!fir.logical<4>>>) -> !fir.box<none>
! CHECK: fir.call @_FortranAIAll4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_37]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i32
end function

View File

@ -0,0 +1,156 @@
! RUN: bbc -emit-fir %s -o - | FileCheck %s
! CHECK-LABEL: func @_QPiany_test_1(
! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?xi8>>{{.*}}) -> i8 {
integer(1) function iany_test_1(a)
integer(1) :: a(:)
! CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index
! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box<i1>
! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?xi8>>) -> !fir.box<none>
! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32
! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box<i1>) -> !fir.box<none>
iany_test_1 = iany(a)
! CHECK: %{{.*}} = fir.call @_FortranAIAny1(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i8
end function
! CHECK-LABEL: func @_QPiany_test_2(
! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?xi16>>{{.*}}) -> i16 {
integer(2) function iany_test_2(a)
integer(2) :: a(:)
! CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index
! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box<i1>
! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?xi16>>) -> !fir.box<none>
! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32
! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box<i1>) -> !fir.box<none>
iany_test_2 = iany(a)
! CHECK: %{{.*}} = fir.call @_FortranAIAny2(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i16
end function
! CHECK-LABEL: func @_QPiany_test_4(
! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?xi32>>{{.*}}) -> i32 {
integer function iany_test_4(a)
integer :: a(:)
! CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index
! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box<i1>
! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?xi32>>) -> !fir.box<none>
! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32
! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box<i1>) -> !fir.box<none>
iany_test_4 = iany(a)
! CHECK: %{{.*}} = fir.call @_FortranAIAny4(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i32
end function
! CHECK-LABEL: func @_QPiany_test_8(
! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?xi64>>{{.*}}) -> i64 {
integer(8) function iany_test_8(a)
integer(8) :: a(:)
! CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index
! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box<i1>
! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?xi64>>) -> !fir.box<none>
! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32
! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box<i1>) -> !fir.box<none>
iany_test_8 = iany(a)
! CHECK: %{{.*}} = fir.call @_FortranAIAny8(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i64
end function
! CHECK-LABEL: func @_QPiany_test_16(
! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?xi128>>{{.*}}) -> i128 {
integer(16) function iany_test_16(a)
integer(16) :: a(:)
! CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index
! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box<i1>
! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?xi128>>) -> !fir.box<none>
! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32
! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box<i1>) -> !fir.box<none>
iany_test_16 = iany(a)
! CHECK: %{{.*}} = fir.call @_FortranAIAny16(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i128
end function
! CHECK-LABEL: func @_QPiany_test2(
! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?x?xi32>>{{.*}}, %[[arg1:.*]]: !fir.box<!fir.array<?xi32>>{{.*}}) {
subroutine iany_test2(a,r)
integer :: a(:,:)
integer :: r(:)
! CHECK-DAG: %[[c2_i32:.*]] = arith.constant 2 : i32
! CHECK-DAG: %[[a0:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>>
! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box<i1>
! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a0]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<none>>
! CHECK-DAG: %[[a7:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?x?xi32>>) -> !fir.box<none>
! CHECK-DAG: %[[a9:.*]] = fir.convert %[[a1]] : (!fir.box<i1>) -> !fir.box<none>
r = iany(a,dim=2)
! CHECK: %{{.*}} = fir.call @_FortranAIAnyDim(%[[a6]], %[[a7]], %[[c2_i32]], %{{.*}}, %{{.*}}, %[[a9]]) : (!fir.ref<!fir.box<none>>, !fir.box<none>, i32, !fir.ref<i8>, i32, !fir.box<none>) -> none
! CHECK-DAG: %[[a11:.*]] = fir.load %[[a0]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
! CHECK-DAG: %[[a13:.*]] = fir.box_addr %[[a11]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
! CHECK-DAG: fir.freemem %[[a13]]
end subroutine
! CHECK-LABEL: func @_QPiany_test_optional(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?x!fir.logical<4>>>
integer function iany_test_optional(mask, x)
integer :: x(:)
logical, optional :: mask(:)
iany_test_optional = iany(x, mask=mask)
! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_0]] : (!fir.box<!fir.array<?x!fir.logical<4>>>) -> !fir.box<none>
! CHECK: fir.call @_FortranAIAny4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_9]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i32
end function
! CHECK-LABEL: func @_QPiany_test_optional_2(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>>
integer function iany_test_optional_2(mask, x)
integer :: x(:)
logical, pointer :: mask(:)
iany_test_optional_2 = iany(x, mask=mask)
! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>>
! CHECK: %[[VAL_5:.*]] = fir.box_addr %[[VAL_4]] : (!fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>) -> !fir.ptr<!fir.array<?x!fir.logical<4>>>
! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_5]] : (!fir.ptr<!fir.array<?x!fir.logical<4>>>) -> i64
! CHECK: %[[VAL_7:.*]] = arith.constant 0 : i64
! CHECK: %[[VAL_8:.*]] = arith.cmpi ne, %[[VAL_6]], %[[VAL_7]] : i64
! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>>
! CHECK: %[[VAL_10:.*]] = fir.absent !fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>
! CHECK: %[[VAL_11:.*]] = arith.select %[[VAL_8]], %[[VAL_9]], %[[VAL_10]] : !fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>
! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_11]] : (!fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>) -> !fir.box<none>
! CHECK: fir.call @_FortranAIAny4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_18]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i32
end function
! CHECK-LABEL: func @_QPiany_test_optional_3(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<10x!fir.logical<4>>>
integer function iany_test_optional_3(mask, x)
integer :: x(:)
logical, optional :: mask(10)
iany_test_optional_3 = iany(x, mask=mask)
! CHECK: %[[VAL_2:.*]] = arith.constant 10 : index
! CHECK: %[[VAL_5:.*]] = fir.is_present %[[VAL_0]] : (!fir.ref<!fir.array<10x!fir.logical<4>>>) -> i1
! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1>
! CHECK: %[[VAL_7:.*]] = fir.embox %[[VAL_0]](%[[VAL_6]]) : (!fir.ref<!fir.array<10x!fir.logical<4>>>, !fir.shape<1>) -> !fir.box<!fir.array<10x!fir.logical<4>>>
! CHECK: %[[VAL_8:.*]] = fir.absent !fir.box<!fir.array<10x!fir.logical<4>>>
! CHECK: %[[VAL_9:.*]] = arith.select %[[VAL_5]], %[[VAL_7]], %[[VAL_8]] : !fir.box<!fir.array<10x!fir.logical<4>>>
! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_9]] : (!fir.box<!fir.array<10x!fir.logical<4>>>) -> !fir.box<none>
! CHECK: fir.call @_FortranAIAny4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_18]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i32
end function
! CHECK-LABEL: func @_QPiany_test_optional_4(
integer function iany_test_optional_4(x, use_mask)
! Test that local allocatable tracked in local variables
! are dealt as optional argument correctly.
integer :: x(:)
logical :: use_mask
logical, allocatable :: mask(:)
if (use_mask) then
allocate(mask(size(x, 1)))
call set_mask(mask)
! CHECK: fir.call @_QPset_mask
end if
iany_test_optional_4 = iany(x, mask=mask)
! CHECK: %[[VAL_20:.*]] = fir.load %[[VAL_3:.*]] : !fir.ref<!fir.heap<!fir.array<?x!fir.logical<4>>>>
! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (!fir.heap<!fir.array<?x!fir.logical<4>>>) -> i64
! CHECK: %[[VAL_22:.*]] = arith.constant 0 : i64
! CHECK: %[[VAL_23:.*]] = arith.cmpi ne, %[[VAL_21]], %[[VAL_22]] : i64
! CHECK: %[[VAL_24:.*]] = fir.load %[[VAL_4:.*]] : !fir.ref<index>
! CHECK: %[[VAL_25:.*]] = fir.load %[[VAL_5:.*]] : !fir.ref<index>
! CHECK: %[[VAL_26:.*]] = fir.load %[[VAL_3]] : !fir.ref<!fir.heap<!fir.array<?x!fir.logical<4>>>>
! CHECK: %[[VAL_27:.*]] = fir.shape_shift %[[VAL_24]], %[[VAL_25]] : (index, index) -> !fir.shapeshift<1>
! CHECK: %[[VAL_28:.*]] = fir.embox %[[VAL_26]](%[[VAL_27]]) : (!fir.heap<!fir.array<?x!fir.logical<4>>>, !fir.shapeshift<1>) -> !fir.box<!fir.array<?x!fir.logical<4>>>
! CHECK: %[[VAL_29:.*]] = fir.absent !fir.box<!fir.array<?x!fir.logical<4>>>
! CHECK: %[[VAL_30:.*]] = arith.select %[[VAL_23]], %[[VAL_28]], %[[VAL_29]] : !fir.box<!fir.array<?x!fir.logical<4>>>
! CHECK: %[[VAL_37:.*]] = fir.convert %[[VAL_30]] : (!fir.box<!fir.array<?x!fir.logical<4>>>) -> !fir.box<none>
! CHECK: fir.call @_FortranAIAny4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_37]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i32
end function

View File

@ -0,0 +1,156 @@
! RUN: bbc -emit-fir %s -o - | FileCheck %s
! CHECK-LABEL: func @_QPiparity_test_1(
! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?xi8>>{{.*}}) -> i8 {
integer(1) function iparity_test_1(a)
integer(1) :: a(:)
! CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index
! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box<i1>
! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?xi8>>) -> !fir.box<none>
! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32
! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box<i1>) -> !fir.box<none>
iparity_test_1 = iparity(a)
! CHECK: %{{.*}} = fir.call @_FortranAIParity1(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i8
end function
! CHECK-LABEL: func @_QPiparity_test_2(
! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?xi16>>{{.*}}) -> i16 {
integer(2) function iparity_test_2(a)
integer(2) :: a(:)
! CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index
! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box<i1>
! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?xi16>>) -> !fir.box<none>
! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32
! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box<i1>) -> !fir.box<none>
iparity_test_2 = iparity(a)
! CHECK: %{{.*}} = fir.call @_FortranAIParity2(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i16
end function
! CHECK-LABEL: func @_QPiparity_test_4(
! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?xi32>>{{.*}}) -> i32 {
integer function iparity_test_4(a)
integer :: a(:)
! CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index
! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box<i1>
! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?xi32>>) -> !fir.box<none>
! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32
! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box<i1>) -> !fir.box<none>
iparity_test_4 = iparity(a)
! CHECK: %{{.*}} = fir.call @_FortranAIParity4(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i32
end function
! CHECK-LABEL: func @_QPiparity_test_8(
! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?xi64>>{{.*}}) -> i64 {
integer(8) function iparity_test_8(a)
integer(8) :: a(:)
! CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index
! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box<i1>
! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?xi64>>) -> !fir.box<none>
! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32
! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box<i1>) -> !fir.box<none>
iparity_test_8 = iparity(a)
! CHECK: %{{.*}} = fir.call @_FortranAIParity8(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i64
end function
! CHECK-LABEL: func @_QPiparity_test_16(
! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?xi128>>{{.*}}) -> i128 {
integer(16) function iparity_test_16(a)
integer(16) :: a(:)
! CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index
! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box<i1>
! CHECK-DAG: %[[a3:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?xi128>>) -> !fir.box<none>
! CHECK-DAG: %[[a5:.*]] = fir.convert %[[c0]] : (index) -> i32
! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a1]] : (!fir.box<i1>) -> !fir.box<none>
iparity_test_16 = iparity(a)
! CHECK: %{{.*}} = fir.call @_FortranAIParity16(%[[a3]], %{{.*}}, %{{.*}}, %[[a5]], %[[a6]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i128
end function
! CHECK-LABEL: func @_QPiparity_test2(
! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?x?xi32>>{{.*}}, %[[arg1:.*]]: !fir.box<!fir.array<?xi32>>{{.*}}) {
subroutine iparity_test2(a,r)
integer :: a(:,:)
integer :: r(:)
! CHECK-DAG: %[[c2_i32:.*]] = arith.constant 2 : i32
! CHECK-DAG: %[[a0:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>>
! CHECK-DAG: %[[a1:.*]] = fir.absent !fir.box<i1>
! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a0]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<none>>
! CHECK-DAG: %[[a7:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?x?xi32>>) -> !fir.box<none>
! CHECK-DAG: %[[a9:.*]] = fir.convert %[[a1]] : (!fir.box<i1>) -> !fir.box<none>
r = iparity(a,dim=2)
! CHECK: %{{.*}} = fir.call @_FortranAIParityDim(%[[a6]], %[[a7]], %[[c2_i32]], %{{.*}}, %{{.*}}, %[[a9]]) : (!fir.ref<!fir.box<none>>, !fir.box<none>, i32, !fir.ref<i8>, i32, !fir.box<none>) -> none
! CHECK-DAG: %[[a11:.*]] = fir.load %[[a0]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
! CHECK-DAG: %[[a13:.*]] = fir.box_addr %[[a11]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
! CHECK-DAG: fir.freemem %[[a13]]
end subroutine
! CHECK-LABEL: func @_QPiparity_test_optional(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?x!fir.logical<4>>>
integer function iparity_test_optional(mask, x)
integer :: x(:)
logical, optional :: mask(:)
iparity_test_optional = iparity(x, mask=mask)
! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_0]] : (!fir.box<!fir.array<?x!fir.logical<4>>>) -> !fir.box<none>
! CHECK: fir.call @_FortranAIParity4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_9]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i32
end function
! CHECK-LABEL: func @_QPiparity_test_optional_2(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>>
integer function iparity_test_optional_2(mask, x)
integer :: x(:)
logical, pointer :: mask(:)
iparity_test_optional_2 = iparity(x, mask=mask)
! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>>
! CHECK: %[[VAL_5:.*]] = fir.box_addr %[[VAL_4]] : (!fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>) -> !fir.ptr<!fir.array<?x!fir.logical<4>>>
! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_5]] : (!fir.ptr<!fir.array<?x!fir.logical<4>>>) -> i64
! CHECK: %[[VAL_7:.*]] = arith.constant 0 : i64
! CHECK: %[[VAL_8:.*]] = arith.cmpi ne, %[[VAL_6]], %[[VAL_7]] : i64
! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>>
! CHECK: %[[VAL_10:.*]] = fir.absent !fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>
! CHECK: %[[VAL_11:.*]] = arith.select %[[VAL_8]], %[[VAL_9]], %[[VAL_10]] : !fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>
! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_11]] : (!fir.box<!fir.ptr<!fir.array<?x!fir.logical<4>>>>) -> !fir.box<none>
! CHECK: fir.call @_FortranAIParity4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_18]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i32
end function
! CHECK-LABEL: func @_QPiparity_test_optional_3(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<10x!fir.logical<4>>>
integer function iparity_test_optional_3(mask, x)
integer :: x(:)
logical, optional :: mask(10)
iparity_test_optional_3 = iparity(x, mask=mask)
! CHECK: %[[VAL_2:.*]] = arith.constant 10 : index
! CHECK: %[[VAL_5:.*]] = fir.is_present %[[VAL_0]] : (!fir.ref<!fir.array<10x!fir.logical<4>>>) -> i1
! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1>
! CHECK: %[[VAL_7:.*]] = fir.embox %[[VAL_0]](%[[VAL_6]]) : (!fir.ref<!fir.array<10x!fir.logical<4>>>, !fir.shape<1>) -> !fir.box<!fir.array<10x!fir.logical<4>>>
! CHECK: %[[VAL_8:.*]] = fir.absent !fir.box<!fir.array<10x!fir.logical<4>>>
! CHECK: %[[VAL_9:.*]] = arith.select %[[VAL_5]], %[[VAL_7]], %[[VAL_8]] : !fir.box<!fir.array<10x!fir.logical<4>>>
! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_9]] : (!fir.box<!fir.array<10x!fir.logical<4>>>) -> !fir.box<none>
! CHECK: fir.call @_FortranAIParity4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_18]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i32
end function
! CHECK-LABEL: func @_QPiparity_test_optional_4(
integer function iparity_test_optional_4(x, use_mask)
! Test that local allocatable tracked in local variables
! are dealt as optional argument correctly.
integer :: x(:)
logical :: use_mask
logical, allocatable :: mask(:)
if (use_mask) then
allocate(mask(size(x, 1)))
call set_mask(mask)
! CHECK: fir.call @_QPset_mask
end if
iparity_test_optional_4 = iparity(x, mask=mask)
! CHECK: %[[VAL_20:.*]] = fir.load %[[VAL_3:.*]] : !fir.ref<!fir.heap<!fir.array<?x!fir.logical<4>>>>
! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (!fir.heap<!fir.array<?x!fir.logical<4>>>) -> i64
! CHECK: %[[VAL_22:.*]] = arith.constant 0 : i64
! CHECK: %[[VAL_23:.*]] = arith.cmpi ne, %[[VAL_21]], %[[VAL_22]] : i64
! CHECK: %[[VAL_24:.*]] = fir.load %[[VAL_4:.*]] : !fir.ref<index>
! CHECK: %[[VAL_25:.*]] = fir.load %[[VAL_5:.*]] : !fir.ref<index>
! CHECK: %[[VAL_26:.*]] = fir.load %[[VAL_3]] : !fir.ref<!fir.heap<!fir.array<?x!fir.logical<4>>>>
! CHECK: %[[VAL_27:.*]] = fir.shape_shift %[[VAL_24]], %[[VAL_25]] : (index, index) -> !fir.shapeshift<1>
! CHECK: %[[VAL_28:.*]] = fir.embox %[[VAL_26]](%[[VAL_27]]) : (!fir.heap<!fir.array<?x!fir.logical<4>>>, !fir.shapeshift<1>) -> !fir.box<!fir.array<?x!fir.logical<4>>>
! CHECK: %[[VAL_29:.*]] = fir.absent !fir.box<!fir.array<?x!fir.logical<4>>>
! CHECK: %[[VAL_30:.*]] = arith.select %[[VAL_23]], %[[VAL_28]], %[[VAL_29]] : !fir.box<!fir.array<?x!fir.logical<4>>>
! CHECK: %[[VAL_37:.*]] = fir.convert %[[VAL_30]] : (!fir.box<!fir.array<?x!fir.logical<4>>>) -> !fir.box<none>
! CHECK: fir.call @_FortranAIParity4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_37]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32, !fir.box<none>) -> i32
end function