forked from OSchip/llvm-project
[flang] Lower F08 parity intrinsic
Lower F08 parity intrinsic. This largely follows the implementation of the ANY and ALL intrinsics which are related. Differential Revision: https://reviews.llvm.org/D129788
This commit is contained in:
parent
ba57828e11
commit
5259528fc8
|
@ -39,6 +39,13 @@ void genAnyDescriptor(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||||
mlir::Value resultBox, mlir::Value maskBox,
|
mlir::Value resultBox, mlir::Value maskBox,
|
||||||
mlir::Value dim);
|
mlir::Value dim);
|
||||||
|
|
||||||
|
/// Generate call to `ParityDim` runtime routine.
|
||||||
|
/// This calls the descriptor based runtime call implementation of the `parity`
|
||||||
|
/// intrinsic.
|
||||||
|
void genParityDescriptor(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||||
|
mlir::Value resultBox, mlir::Value maskBox,
|
||||||
|
mlir::Value dim);
|
||||||
|
|
||||||
/// Generate call to `All` runtime routine. This version of `all` is specialized
|
/// Generate call to `All` runtime routine. This version of `all` is specialized
|
||||||
/// for rank 1 mask arguments.
|
/// for rank 1 mask arguments.
|
||||||
/// This calls the version that returns a scalar logical value.
|
/// This calls the version that returns a scalar logical value.
|
||||||
|
@ -128,6 +135,12 @@ void genMinvalDim(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||||
mlir::Value resultBox, mlir::Value arrayBox, mlir::Value dim,
|
mlir::Value resultBox, mlir::Value arrayBox, mlir::Value dim,
|
||||||
mlir::Value maskBox);
|
mlir::Value maskBox);
|
||||||
|
|
||||||
|
/// Generate call to `Parity` runtime routine. This version of `parity` is
|
||||||
|
/// specialized for rank 1 mask arguments.
|
||||||
|
/// This calls the version that returns a scalar logical value.
|
||||||
|
mlir::Value genParity(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||||
|
mlir::Value maskBox, mlir::Value dim);
|
||||||
|
|
||||||
/// Generate call to `Product` intrinsic runtime routine. This is the version
|
/// Generate call to `Product` intrinsic runtime routine. This is the version
|
||||||
/// that does not take a dim argument.
|
/// that does not take a dim argument.
|
||||||
mlir::Value genProduct(fir::FirOpBuilder &builder, mlir::Location loc,
|
mlir::Value genProduct(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||||
|
|
|
@ -535,6 +535,7 @@ struct IntrinsicLibrary {
|
||||||
mlir::Value genNot(mlir::Type, llvm::ArrayRef<mlir::Value>);
|
mlir::Value genNot(mlir::Type, llvm::ArrayRef<mlir::Value>);
|
||||||
fir::ExtendedValue genNull(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
|
fir::ExtendedValue genNull(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
|
||||||
fir::ExtendedValue genPack(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
|
fir::ExtendedValue genPack(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
|
||||||
|
fir::ExtendedValue genParity(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
|
||||||
mlir::Value genPopcnt(mlir::Type, llvm::ArrayRef<mlir::Value>);
|
mlir::Value genPopcnt(mlir::Type, llvm::ArrayRef<mlir::Value>);
|
||||||
mlir::Value genPoppar(mlir::Type, llvm::ArrayRef<mlir::Value>);
|
mlir::Value genPoppar(mlir::Type, llvm::ArrayRef<mlir::Value>);
|
||||||
fir::ExtendedValue genPresent(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
|
fir::ExtendedValue genPresent(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
|
||||||
|
@ -882,6 +883,10 @@ static constexpr IntrinsicHandler handlers[]{
|
||||||
{"mask", asBox},
|
{"mask", asBox},
|
||||||
{"vector", asBox, handleDynamicOptional}}},
|
{"vector", asBox, handleDynamicOptional}}},
|
||||||
/*isElemental=*/false},
|
/*isElemental=*/false},
|
||||||
|
{"parity",
|
||||||
|
&I::genParity,
|
||||||
|
{{{"mask", asBox}, {"dim", asValue}}},
|
||||||
|
/*isElemental=*/false},
|
||||||
{"popcnt", &I::genPopcnt},
|
{"popcnt", &I::genPopcnt},
|
||||||
{"poppar", &I::genPoppar},
|
{"poppar", &I::genPoppar},
|
||||||
{"present",
|
{"present",
|
||||||
|
@ -3631,6 +3636,52 @@ IntrinsicLibrary::genPack(mlir::Type resultType,
|
||||||
"unexpected result for PACK");
|
"unexpected result for PACK");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PARITY
|
||||||
|
fir::ExtendedValue
|
||||||
|
IntrinsicLibrary::genParity(mlir::Type resultType,
|
||||||
|
llvm::ArrayRef<fir::ExtendedValue> args) {
|
||||||
|
|
||||||
|
assert(args.size() == 2);
|
||||||
|
// Handle required mask argument
|
||||||
|
mlir::Value mask = builder.createBox(loc, args[0]);
|
||||||
|
|
||||||
|
fir::BoxValue maskArry = builder.createBox(loc, args[0]);
|
||||||
|
int rank = maskArry.rank();
|
||||||
|
assert(rank >= 1);
|
||||||
|
|
||||||
|
// Handle optional dim argument
|
||||||
|
bool absentDim = isStaticallyAbsent(args[1]);
|
||||||
|
mlir::Value dim =
|
||||||
|
absentDim ? builder.createIntegerConstant(loc, builder.getIndexType(), 1)
|
||||||
|
: fir::getBase(args[1]);
|
||||||
|
|
||||||
|
if (rank == 1 || absentDim)
|
||||||
|
return builder.createConvert(
|
||||||
|
loc, resultType, fir::runtime::genParity(builder, loc, mask, dim));
|
||||||
|
|
||||||
|
// else use the result descriptor ParityDim() intrinsic
|
||||||
|
|
||||||
|
// Create mutable fir.box to be passed to the runtime for the result.
|
||||||
|
|
||||||
|
mlir::Type resultArrayType = builder.getVarLenSeqTy(resultType, rank - 1);
|
||||||
|
fir::MutableBoxValue resultMutableBox =
|
||||||
|
fir::factory::createTempMutableBox(builder, loc, resultArrayType);
|
||||||
|
mlir::Value resultIrBox =
|
||||||
|
fir::factory::getMutableIRBox(builder, loc, resultMutableBox);
|
||||||
|
|
||||||
|
// Call runtime. The runtime is allocating the result.
|
||||||
|
fir::runtime::genParityDescriptor(builder, loc, resultIrBox, mask, dim);
|
||||||
|
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, "Invalid result for PARITY");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// POPCNT
|
// POPCNT
|
||||||
mlir::Value IntrinsicLibrary::genPopcnt(mlir::Type resultType,
|
mlir::Value IntrinsicLibrary::genPopcnt(mlir::Type resultType,
|
||||||
llvm::ArrayRef<mlir::Value> args) {
|
llvm::ArrayRef<mlir::Value> args) {
|
||||||
|
|
|
@ -471,6 +471,18 @@ void fir::runtime::genAnyDescriptor(fir::FirOpBuilder &builder,
|
||||||
genReduction2Args(anyFunc, builder, loc, resultBox, maskBox, dim);
|
genReduction2Args(anyFunc, builder, loc, resultBox, maskBox, dim);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Generate call to `ParityDim` runtime routine.
|
||||||
|
/// This calls the descriptor based runtime call implementation of the `parity`
|
||||||
|
/// intrinsic.
|
||||||
|
void fir::runtime::genParityDescriptor(fir::FirOpBuilder &builder,
|
||||||
|
mlir::Location loc,
|
||||||
|
mlir::Value resultBox,
|
||||||
|
mlir::Value maskBox, mlir::Value dim) {
|
||||||
|
auto parityFunc =
|
||||||
|
fir::runtime::getRuntimeFunc<mkRTKey(ParityDim)>(loc, builder);
|
||||||
|
genReduction2Args(parityFunc, builder, loc, resultBox, maskBox, dim);
|
||||||
|
}
|
||||||
|
|
||||||
/// Generate call to `All` intrinsic runtime routine. This routine is
|
/// Generate call to `All` intrinsic runtime routine. This routine is
|
||||||
/// specialized for mask arguments with rank == 1.
|
/// specialized for mask arguments with rank == 1.
|
||||||
mlir::Value fir::runtime::genAll(fir::FirOpBuilder &builder, mlir::Location loc,
|
mlir::Value fir::runtime::genAll(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||||
|
@ -694,6 +706,15 @@ mlir::Value fir::runtime::genMinval(fir::FirOpBuilder &builder,
|
||||||
return builder.create<fir::CallOp>(loc, func, args).getResult(0);
|
return builder.create<fir::CallOp>(loc, func, args).getResult(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Generate call to `Parity` intrinsic runtime routine. This routine is
|
||||||
|
/// specialized for mask arguments with rank == 1.
|
||||||
|
mlir::Value fir::runtime::genParity(fir::FirOpBuilder &builder,
|
||||||
|
mlir::Location loc, mlir::Value maskBox,
|
||||||
|
mlir::Value dim) {
|
||||||
|
auto parityFunc = fir::runtime::getRuntimeFunc<mkRTKey(Parity)>(loc, builder);
|
||||||
|
return genSpecial2Args(parityFunc, builder, loc, maskBox, dim);
|
||||||
|
}
|
||||||
|
|
||||||
/// Generate call to `ProductDim` intrinsic runtime routine. This is the version
|
/// Generate call to `ProductDim` intrinsic runtime routine. This is the version
|
||||||
/// that handles any rank array with the dim argument specified.
|
/// that handles any rank array with the dim argument specified.
|
||||||
void fir::runtime::genProductDim(fir::FirOpBuilder &builder, mlir::Location loc,
|
void fir::runtime::genProductDim(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
! RUN: bbc -emit-fir %s -o - | FileCheck %s
|
||||||
|
! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s
|
||||||
|
|
||||||
|
! CHECK-LABEL: parity_test
|
||||||
|
! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?x!fir.logical<4>>>{{.*}}) -> !fir.logical<4>
|
||||||
|
logical function parity_test(mask)
|
||||||
|
logical :: mask(:)
|
||||||
|
! CHECK: %[[c1:.*]] = arith.constant 1 : index
|
||||||
|
! CHECK: %[[a1:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?x!fir.logical<4>>>) -> !fir.box<none>
|
||||||
|
! CHECK: %[[a2:.*]] = fir.convert %[[c1]] : (index) -> i32
|
||||||
|
parity_test = parity(mask)
|
||||||
|
! CHECK: %[[a3:.*]] = fir.call @_FortranAParity(%[[a1]], %{{.*}}, %{{.*}}, %[[a2]]) : (!fir.box<none>, !fir.ref<i8>, i32, i32) -> i1
|
||||||
|
end function parity_test
|
||||||
|
|
||||||
|
! CHECK-LABEL: parity_test2
|
||||||
|
! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?x?x!fir.logical<4>>>
|
||||||
|
! CHECK-SAME: %[[arg1:.*]]: !fir.ref<i32>
|
||||||
|
! CHECK-SAME: %[[arg2:.*]]: !fir.box<!fir.array<?x!fir.logical<4>>>
|
||||||
|
subroutine parity_test2(mask, d, rslt)
|
||||||
|
logical :: mask(:,:)
|
||||||
|
integer :: d
|
||||||
|
logical :: rslt(:)
|
||||||
|
! CHECK-DAG: %[[a0:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>
|
||||||
|
! CHECK-DAG: %[[a1:.*]] = fir.load %[[arg1:.*]] : !fir.ref<i32>
|
||||||
|
! CHECK-DAG: %[[a6:.*]] = fir.convert %[[a0:.*]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>>) -> !fir.ref<!fir.box<none>>
|
||||||
|
! CHECK-DAG: %[[a7:.*]] = fir.convert %[[arg0:.*]]: (!fir.box<!fir.array<?x?x!fir.logical<4>>>) -> !fir.box<none>
|
||||||
|
rslt = parity(mask, d)
|
||||||
|
! CHECK: %[[r1:.*]] = fir.call @_FortranAParityDim(%[[a6:.*]], %[[a7:.*]], %[[a1:.*]], %{{.*}}, %{{.*}}) : (!fir.ref<!fir.box<none>>, !fir.box<none>, i32, !fir.ref<i8>, i32) -> none
|
||||||
|
! CHECK-DAG: %[[a10:.*]] = fir.load %[[a0:.*]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>>
|
||||||
|
! CHECK-DAG: %[[a12:.*]] = fir.box_addr %[[a10:.*]] : (!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>) -> !fir.heap<!fir.array<?x!fir.logical<4>>>
|
||||||
|
! CHECK-DAG fir.freemem %[[a12:.*]]
|
||||||
|
end subroutine parity_test2
|
|
@ -112,6 +112,23 @@ TEST_F(RuntimeCallTest, genMinValTest) {
|
||||||
testGenMinVal(*firBuilder, i128Ty, "_FortranAMinvalInteger16");
|
testGenMinVal(*firBuilder, i128Ty, "_FortranAMinvalInteger16");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(RuntimeCallTest, genParityTest) {
|
||||||
|
mlir::Location loc = firBuilder->getUnknownLoc();
|
||||||
|
mlir::Value undef = firBuilder->create<fir::UndefOp>(loc, seqTy10);
|
||||||
|
mlir::Value dim = firBuilder->createIntegerConstant(loc, i32Ty, 1);
|
||||||
|
mlir::Value parity = fir::runtime::genParity(*firBuilder, loc, undef, dim);
|
||||||
|
checkCallOp(parity.getDefiningOp(), "_FortranAParity", 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(RuntimeCallTest, genParityDescriptorTest) {
|
||||||
|
mlir::Location loc = firBuilder->getUnknownLoc();
|
||||||
|
mlir::Value result = firBuilder->create<fir::UndefOp>(loc, seqTy10);
|
||||||
|
mlir::Value mask = firBuilder->create<fir::UndefOp>(loc, seqTy10);
|
||||||
|
mlir::Value dim = firBuilder->createIntegerConstant(loc, i32Ty, 1);
|
||||||
|
fir::runtime::genParityDescriptor(*firBuilder, loc, result, mask, dim);
|
||||||
|
checkCallOpFromResultBox(result, "_FortranAParityDim", 3);
|
||||||
|
}
|
||||||
|
|
||||||
void testGenSum(
|
void testGenSum(
|
||||||
fir::FirOpBuilder &builder, mlir::Type eleTy, llvm::StringRef fctName) {
|
fir::FirOpBuilder &builder, mlir::Type eleTy, llvm::StringRef fctName) {
|
||||||
mlir::Location loc = builder.getUnknownLoc();
|
mlir::Location loc = builder.getUnknownLoc();
|
||||||
|
|
Loading…
Reference in New Issue