[flang-commits] [flang] 25db7cb - [flang][hlfir] Implement hlfir.declare optional codegen
Jean Perier via flang-commits
flang-commits at lists.llvm.org
Wed Mar 1 01:44:25 PST 2023
Author: Jean Perier
Date: 2023-03-01T10:43:56+01:00
New Revision: 25db7cb70c312b956240b3d65c3bc72020ac9409
URL: https://github.com/llvm/llvm-project/commit/25db7cb70c312b956240b3d65c3bc72020ac9409
DIFF: https://github.com/llvm/llvm-project/commit/25db7cb70c312b956240b3d65c3bc72020ac9409.diff
LOG: [flang][hlfir] Implement hlfir.declare optional codegen
The hlfir fir.box with the local lower bounds and type parameters
must be generated conditionally when the entity is optional.
Differential Revision: https://reviews.llvm.org/D144962
Added:
Modified:
flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp
flang/test/HLFIR/declare-codegen.fir
Removed:
################################################################################
diff --git a/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp b/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp
index ce09ef07115dc..160a77c7b9464 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp
+++ b/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp
@@ -286,26 +286,52 @@ class DeclareOpConversion : public mlir::OpRewritePattern<hlfir::DeclareOp> {
mlir::Value hlfirBase;
mlir::Type hlfirBaseType = declareOp.getBase().getType();
if (hlfirBaseType.isa<fir::BaseBoxType>()) {
- // Need to conditionally rebox/embox for optional.
- if (mlir::cast<fir::FortranVariableOpInterface>(declareOp.getOperation())
- .isOptional())
- TODO(loc, "converting hlfir declare of optional box to fir");
- if (!firBase.getType().isa<fir::BaseBoxType>()) {
- llvm::SmallVector<mlir::Value> typeParams;
- auto maybeCharType =
- fir::unwrapSequenceType(fir::unwrapPassByRefType(hlfirBaseType))
- .dyn_cast<fir::CharacterType>();
- if (!maybeCharType || maybeCharType.hasDynamicLen())
- typeParams.append(declareOp.getTypeparams().begin(),
- declareOp.getTypeparams().end());
- hlfirBase = rewriter.create<fir::EmboxOp>(
- loc, hlfirBaseType, firBase, declareOp.getShape(),
- /*slice=*/mlir::Value{}, typeParams);
+ auto module = declareOp->getParentOfType<mlir::ModuleOp>();
+ fir::FirOpBuilder builder(rewriter, fir::getKindMapping(module));
+ // Helper to generate the hlfir fir.box with the local lower bounds and
+ // type parameters.
+ auto genHlfirBox = [&]() -> mlir::Value {
+ if (!firBase.getType().isa<fir::BaseBoxType>()) {
+ llvm::SmallVector<mlir::Value> typeParams;
+ auto maybeCharType =
+ fir::unwrapSequenceType(fir::unwrapPassByRefType(hlfirBaseType))
+ .dyn_cast<fir::CharacterType>();
+ if (!maybeCharType || maybeCharType.hasDynamicLen())
+ typeParams.append(declareOp.getTypeparams().begin(),
+ declareOp.getTypeparams().end());
+ return builder.create<fir::EmboxOp>(
+ loc, hlfirBaseType, firBase, declareOp.getShape(),
+ /*slice=*/mlir::Value{}, typeParams);
+ } else {
+ // Rebox so that lower bounds are correct.
+ return builder.create<fir::ReboxOp>(loc, hlfirBaseType, firBase,
+ declareOp.getShape(),
+ /*slice=*/mlir::Value{});
+ }
+ };
+ if (!mlir::cast<fir::FortranVariableOpInterface>(declareOp.getOperation())
+ .isOptional()) {
+ hlfirBase = genHlfirBox();
} else {
- // Rebox so that lower bounds are correct.
- hlfirBase = rewriter.create<fir::ReboxOp>(loc, hlfirBaseType, firBase,
- declareOp.getShape(),
- /*slice=*/mlir::Value{});
+ // Need to conditionally rebox/embox the optional: the input fir.box
+ // may be null and the rebox would be illegal. It is also important to
+ // preserve the optional aspect: the hlfir fir.box should be null if
+ // the entity is absent so that later fir.is_present on the hlfir base
+ // are valid.
+ mlir::Value isPresent =
+ builder.create<fir::IsPresentOp>(loc, builder.getI1Type(), firBase);
+ hlfirBase = builder
+ .genIfOp(loc, {hlfirBaseType}, isPresent,
+ /*withElseRegion=*/true)
+ .genThen([&] {
+ builder.create<fir::ResultOp>(loc, genHlfirBox());
+ })
+ .genElse([&]() {
+ mlir::Value absent =
+ builder.create<fir::AbsentOp>(loc, hlfirBaseType);
+ builder.create<fir::ResultOp>(loc, absent);
+ })
+ .getResults()[0];
}
} else if (hlfirBaseType.isa<fir::BoxCharType>()) {
assert(declareOp.getTypeparams().size() == 1 &&
diff --git a/flang/test/HLFIR/declare-codegen.fir b/flang/test/HLFIR/declare-codegen.fir
index 601ad4cdc2da1..3e80a52be4524 100644
--- a/flang/test/HLFIR/declare-codegen.fir
+++ b/flang/test/HLFIR/declare-codegen.fir
@@ -178,3 +178,25 @@ func.func @array_declare_unlimited_polymorphic_boxaddr(%arg0: !fir.ref<!fir.clas
// CHECK-LABEL: func.func @array_declare_unlimited_polymorphic_boxaddr(
// CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.class<!fir.ptr<!fir.array<?x?xnone>>>>) {
// CHECK: %[[VAL_1:.*]] = fir.declare %[[VAL_0]] {uniq_name = "x"} : (!fir.ref<!fir.class<!fir.ptr<!fir.array<?x?xnone>>>>) -> !fir.ref<!fir.class<!fir.ptr<!fir.array<?x?xnone>>>>
+
+
+func.func @test_optional_declare(%arg0: !fir.box<!fir.array<?xi32>>) {
+ %c42 = arith.constant 42 : index
+ %0 = fir.shift %c42 : (index) -> !fir.shift<1>
+ %1:2 = hlfir.declare %arg0(%0) {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "x"} : (!fir.box<!fir.array<?xi32>>, !fir.shift<1>) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>)
+ return
+}
+
+// CHECK-LABEL: func.func @test_optional_declare(
+// CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xi32>>) {
+// CHECK: %[[VAL_1:.*]] = arith.constant 42 : index
+// CHECK: %[[VAL_2:.*]] = fir.shift %[[VAL_1]] : (index) -> !fir.shift<1>
+// CHECK: %[[VAL_3:.*]] = fir.declare %[[VAL_0]](%[[VAL_2]]) {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "x"} : (!fir.box<!fir.array<?xi32>>, !fir.shift<1>) -> !fir.box<!fir.array<?xi32>>
+// CHECK: %[[VAL_4:.*]] = fir.is_present %[[VAL_3]] : (!fir.box<!fir.array<?xi32>>) -> i1
+// CHECK: %[[VAL_5:.*]] = fir.if %[[VAL_4]] -> (!fir.box<!fir.array<?xi32>>) {
+// CHECK: %[[VAL_6:.*]] = fir.rebox %[[VAL_3]](%[[VAL_2]]) : (!fir.box<!fir.array<?xi32>>, !fir.shift<1>) -> !fir.box<!fir.array<?xi32>>
+// CHECK: fir.result %[[VAL_6]] : !fir.box<!fir.array<?xi32>>
+// CHECK: } else {
+// CHECK: %[[VAL_7:.*]] = fir.absent !fir.box<!fir.array<?xi32>>
+// CHECK: fir.result %[[VAL_7]] : !fir.box<!fir.array<?xi32>>
+// CHECK: }
More information about the flang-commits
mailing list