-
Notifications
You must be signed in to change notification settings - Fork 15k
[flang][FIR] add fir.assumed_size_extent to abstract assumed-size extent encoding #164452
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
@llvm/pr-subscribers-flang-fir-hlfir @llvm/pr-subscribers-flang-codegen Author: None (jeanPerier) ChangesFollow-up on discussions #163505 (comment) The purpose of this patch is to allow converting FIR array representation to memref when possible without hitting memref verifier issue. The issue was that FIR arrays may be assumed size, in which case the last dimension will not be known at runtime. Flang uses -1 to encode this to fulfill Fortran 2023 standard requirements in 18.5.3 point 5 about CFI_desc_t. When arrays are converted to memeref, if this Patch is 20.62 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/164452.diff 16 Files Affected:
diff --git a/flang/include/flang/Optimizer/Dialect/FIROps.td b/flang/include/flang/Optimizer/Dialect/FIROps.td
index fc6eedc6ed4c6..86502c6271d23 100644
--- a/flang/include/flang/Optimizer/Dialect/FIROps.td
+++ b/flang/include/flang/Optimizer/Dialect/FIROps.td
@@ -1249,6 +1249,41 @@ def fir_IsAssumedSizeOp : fir_SimpleOp<"is_assumed_size", [NoMemoryEffect]> {
let results = (outs BoolLike);
}
+def fir_AssumedSizeExtentOp : fir_SimpleOneResultOp<"assumed_size_extent", [NoMemoryEffect]> {
+ let summary = "get the assumed-size last extent sentinel";
+
+ let description = [{
+ Returns the special extent value representing the last dimension of an
+ assumed-size array. This is used to model the semantics in FIR without
+ directly materializing the sentinel value. The concrete encoding is
+ introduced during FIR to LLVM lowering.
+
+ ```
+ %e = fir.assumed_size_extent : index
+ ```
+ }];
+
+ let results = (outs Index);
+ let assemblyFormat = "attr-dict `:` type(results)";
+}
+
+def fir_IsAssumedSizeExtentOp : fir_SimpleOp<"is_assumed_size_extent", [NoMemoryEffect]> {
+ let summary = "is value the assumed-size last extent sentinel";
+
+ let description = [{
+ Returns true iff the given integer equals the assumed-size extent sentinel.
+
+ ```
+ %t = fir.is_assumed_size_extent %v : (index) -> i1
+ %c = fir.is_assumed_size_extent %x : (i32) -> i1
+ ```
+ }];
+
+ let arguments = (ins AnyIntegerLike:$val);
+ let results = (outs BoolLike);
+ let hasCanonicalizer = 1;
+}
+
def fir_BoxIsPtrOp : fir_SimpleOp<"box_isptr", [NoMemoryEffect]> {
let summary = "is the boxed value a POINTER?";
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 3b711ccbe786a..579e0b673955c 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -4010,8 +4010,8 @@ class FirConverter : public Fortran::lower::AbstractConverter {
// parameters and dynamic type. The selector cannot be a
// POINTER/ALLOCATBLE as per F'2023 C1160.
fir::ExtendedValue newExv;
- llvm::SmallVector assumeSizeExtents{
- builder->createMinusOneInteger(loc, builder->getIndexType())};
+ llvm::SmallVector<mlir::Value> assumeSizeExtents{
+ builder->create<fir::AssumedSizeExtentOp>(loc)};
mlir::Value baseAddr =
hlfir::genVariableRawAddress(loc, *builder, selector);
const bool isVolatile = fir::isa_volatile_type(selector.getType());
diff --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp
index 00ec1b51e5400..dcee64f6a614d 100644
--- a/flang/lib/Lower/ConvertVariable.cpp
+++ b/flang/lib/Lower/ConvertVariable.cpp
@@ -1711,7 +1711,7 @@ static void lowerExplicitLowerBounds(
/// CFI_desc_t requirements in 18.5.3 point 5.).
static mlir::Value getAssumedSizeExtent(mlir::Location loc,
fir::FirOpBuilder &builder) {
- return builder.createMinusOneInteger(loc, builder.getIndexType());
+ return builder.create<fir::AssumedSizeExtentOp>(loc);
}
/// Lower explicit extents into \p result if this is an explicit-shape or
diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
index 70bb43a2510ba..e71f4e3cee49c 100644
--- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp
+++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
@@ -749,6 +749,44 @@ struct VolatileCastOpConversion
}
};
+/// Lower `fir.assumed_size_extent` to constant -1 of index type.
+struct AssumedSizeExtentOpConversion
+ : public fir::FIROpConversion<fir::AssumedSizeExtentOp> {
+ using FIROpConversion::FIROpConversion;
+
+ llvm::LogicalResult
+ matchAndRewrite(fir::AssumedSizeExtentOp op, OpAdaptor,
+ mlir::ConversionPatternRewriter &rewriter) const override {
+ mlir::Location loc = op.getLoc();
+ mlir::Type ity = lowerTy().indexType();
+ auto cst = fir::genConstantIndex(loc, ity, rewriter, -1);
+ rewriter.replaceOp(op, cst.getResult());
+ return mlir::success();
+ }
+};
+
+/// Lower `fir.is_assumed_size_extent` to integer equality with -1.
+struct IsAssumedSizeExtentOpConversion
+ : public fir::FIROpConversion<fir::IsAssumedSizeExtentOp> {
+ using FIROpConversion::FIROpConversion;
+
+ llvm::LogicalResult
+ matchAndRewrite(fir::IsAssumedSizeExtentOp op, OpAdaptor adaptor,
+ mlir::ConversionPatternRewriter &rewriter) const override {
+ mlir::Location loc = op.getLoc();
+ mlir::Value val = adaptor.getVal();
+ mlir::Type valTy = val.getType();
+ // Create constant -1 of the operand type.
+ auto negOneAttr = rewriter.getIntegerAttr(valTy, -1);
+ auto negOne =
+ mlir::LLVM::ConstantOp::create(rewriter, loc, valTy, negOneAttr);
+ auto cmp = mlir::LLVM::ICmpOp::create(
+ rewriter, loc, mlir::LLVM::ICmpPredicate::eq, val, negOne);
+ rewriter.replaceOp(op, cmp.getResult());
+ return mlir::success();
+ }
+};
+
/// convert value of from-type to value of to-type
struct ConvertOpConversion : public fir::FIROpConversion<fir::ConvertOp> {
using FIROpConversion::FIROpConversion;
@@ -4360,6 +4398,7 @@ void fir::populateFIRToLLVMConversionPatterns(
AllocaOpConversion, AllocMemOpConversion, BoxAddrOpConversion,
BoxCharLenOpConversion, BoxDimsOpConversion, BoxEleSizeOpConversion,
BoxIsAllocOpConversion, BoxIsArrayOpConversion, BoxIsPtrOpConversion,
+ AssumedSizeExtentOpConversion, IsAssumedSizeExtentOpConversion,
BoxOffsetOpConversion, BoxProcHostOpConversion, BoxRankOpConversion,
BoxTypeCodeOpConversion, BoxTypeDescOpConversion, CallOpConversion,
CmpcOpConversion, VolatileCastOpConversion, ConvertOpConversion,
diff --git a/flang/lib/Optimizer/Dialect/FIROps.cpp b/flang/lib/Optimizer/Dialect/FIROps.cpp
index 1712af1d1eba7..d0164f32d9b6a 100644
--- a/flang/lib/Optimizer/Dialect/FIROps.cpp
+++ b/flang/lib/Optimizer/Dialect/FIROps.cpp
@@ -5142,6 +5142,34 @@ void fir::BoxTotalElementsOp::getCanonicalizationPatterns(
patterns.add<SimplifyBoxTotalElementsOp>(context);
}
+//===----------------------------------------------------------------------===//
+// IsAssumedSizeExtentOp and AssumedSizeExtentOp
+//===----------------------------------------------------------------------===//
+
+namespace {
+struct FoldIsAssumedSizeExtentOnCtor
+ : public mlir::OpRewritePattern<fir::IsAssumedSizeExtentOp> {
+ using mlir::OpRewritePattern<fir::IsAssumedSizeExtentOp>::OpRewritePattern;
+ mlir::LogicalResult
+ matchAndRewrite(fir::IsAssumedSizeExtentOp op,
+ mlir::PatternRewriter &rewriter) const override {
+ if (llvm::isa_and_nonnull<fir::AssumedSizeExtentOp>(
+ op.getVal().getDefiningOp())) {
+ mlir::Type i1 = rewriter.getI1Type();
+ rewriter.replaceOpWithNewOp<mlir::arith::ConstantOp>(
+ op, i1, rewriter.getIntegerAttr(i1, 1));
+ return mlir::success();
+ }
+ return mlir::failure();
+ }
+};
+} // namespace
+
+void fir::IsAssumedSizeExtentOp::getCanonicalizationPatterns(
+ mlir::RewritePatternSet &patterns, mlir::MLIRContext *context) {
+ patterns.add<FoldIsAssumedSizeExtentOnCtor>(context);
+}
+
//===----------------------------------------------------------------------===//
// LocalitySpecifierOp
//===----------------------------------------------------------------------===//
diff --git a/flang/lib/Optimizer/Transforms/ArrayValueCopy.cpp b/flang/lib/Optimizer/Transforms/ArrayValueCopy.cpp
index ed9a2ae11f0d9..5bf783db92bf3 100644
--- a/flang/lib/Optimizer/Transforms/ArrayValueCopy.cpp
+++ b/flang/lib/Optimizer/Transforms/ArrayValueCopy.cpp
@@ -832,8 +832,8 @@ static mlir::Type getEleTy(mlir::Type ty) {
static bool isAssumedSize(llvm::SmallVectorImpl<mlir::Value> &extents) {
if (extents.empty())
return false;
- auto cstLen = fir::getIntIfConstant(extents.back());
- return cstLen.has_value() && *cstLen == -1;
+ return llvm::isa_and_nonnull<fir::AssumedSizeExtentOp>(
+ extents.back().getDefiningOp());
}
// Extract extents from the ShapeOp/ShapeShiftOp into the result vector.
diff --git a/flang/test/Fir/assumed-size-ops-codegen.fir b/flang/test/Fir/assumed-size-ops-codegen.fir
new file mode 100644
index 0000000000000..54e9b3c8f30f4
--- /dev/null
+++ b/flang/test/Fir/assumed-size-ops-codegen.fir
@@ -0,0 +1,19 @@
+// RUN: fir-opt --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" %s | FileCheck %s
+
+// CHECK-LABEL: @assumed_size_extent(
+// CHECK: %[[CNEG1:.*]] = llvm.mlir.constant(-1 : i64)
+// CHECK: llvm.return %[[CNEG1]] : i64
+func.func @assumed_size_extent() -> index {
+ %e = fir.assumed_size_extent : index
+ return %e : index
+}
+
+// CHECK-LABEL: @is_assumed_size_extent(
+// CHECK: %[[NEG1:.*]] = llvm.mlir.constant(-1 : i64)
+// CHECK: %[[CMP:.*]] = llvm.icmp "eq"
+// CHECK: llvm.return %[[CMP]] : i1
+func.func @is_assumed_size_extent(%x: index) -> i1 {
+ %c = fir.is_assumed_size_extent %x : (index) -> i1
+ return %c : i1
+}
+
diff --git a/flang/test/Fir/assumed-size-ops-folding.fir b/flang/test/Fir/assumed-size-ops-folding.fir
new file mode 100644
index 0000000000000..9fd5fabb7290b
--- /dev/null
+++ b/flang/test/Fir/assumed-size-ops-folding.fir
@@ -0,0 +1,13 @@
+// RUN: fir-opt --canonicalize %s | FileCheck %s
+
+// Verify: fir.is_assumed_size_extent(fir.assumed_size_extent) folds to i1 true.
+
+// CHECK-LABEL: func.func @fold(
+func.func @fold() -> i1 {
+ %e = fir.assumed_size_extent : index
+ // CHECK: %[[C:.*]] = arith.constant true
+ %t = fir.is_assumed_size_extent %e : (index) -> i1
+ return %t : i1
+}
+
+
diff --git a/flang/test/Fir/assumed-size-ops-roundtrip.fir b/flang/test/Fir/assumed-size-ops-roundtrip.fir
new file mode 100644
index 0000000000000..c3c1883a2b7c0
--- /dev/null
+++ b/flang/test/Fir/assumed-size-ops-roundtrip.fir
@@ -0,0 +1,13 @@
+// RUN: fir-opt %s | fir-opt | FileCheck %s
+
+func.func @roundtrip() {
+ // CHECK: %[[E:.*]] = fir.assumed_size_extent : index
+ %e = fir.assumed_size_extent : index
+
+ // CHECK: %[[T:.*]] = fir.is_assumed_size_extent %[[E]] : (index) -> i1
+ %t = fir.is_assumed_size_extent %e : (index) -> i1
+
+ return
+}
+
+
diff --git a/flang/test/HLFIR/assumed-type-actual-args.f90 b/flang/test/HLFIR/assumed-type-actual-args.f90
index 42e9ed27340e7..aaac98ba3c79d 100644
--- a/flang/test/HLFIR/assumed-type-actual-args.f90
+++ b/flang/test/HLFIR/assumed-type-actual-args.f90
@@ -113,7 +113,7 @@ subroutine s5b(x)
! CHECK-LABEL: func.func @_QPtest2(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<?xnone>> {fir.bindc_name = "x"}) {
! CHECK: %[[DSCOPE:.*]] = fir.dummy_scope : !fir.dscope
-! CHECK: %[[VAL_1:.*]] = arith.constant -1 : index
+! CHECK: %[[VAL_1:.*]] = fir.assumed_size_extent : index
! CHECK: %[[VAL_2:.*]] = fir.shape %[[VAL_1]] : (index) -> !fir.shape<1>
! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_2]]) dummy_scope %[[DSCOPE]] {uniq_name = "_QFtest2Ex"} : (!fir.ref<!fir.array<?xnone>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xnone>>, !fir.ref<!fir.array<?xnone>>)
! CHECK: fir.call @_QPs2(%[[VAL_3]]#1) fastmath<contract> : (!fir.ref<!fir.array<?xnone>>) -> ()
diff --git a/flang/test/Lower/HLFIR/assumed-rank-iface.f90 b/flang/test/Lower/HLFIR/assumed-rank-iface.f90
index 9ecbb7c9e5b94..ffb36fa4b7003 100644
--- a/flang/test/Lower/HLFIR/assumed-rank-iface.f90
+++ b/flang/test/Lower/HLFIR/assumed-rank-iface.f90
@@ -145,7 +145,7 @@ subroutine int_r2_assumed_size_to_assumed_rank(x)
! CHECK: %[[VAL_3:.*]] = arith.constant 0 : index
! CHECK: %[[VAL_4:.*]] = arith.cmpi sgt, %[[VAL_2]], %[[VAL_3]] : index
! CHECK: %[[VAL_5:.*]] = arith.select %[[VAL_4]], %[[VAL_2]], %[[VAL_3]] : index
-! CHECK: %[[VAL_6:.*]] = arith.constant -1 : index
+! CHECK: %[[VAL_6:.*]] = fir.assumed_size_extent : index
! CHECK: %[[VAL_7:.*]] = fir.shape %[[VAL_5]], %[[VAL_6]] : (index, index) -> !fir.shape<2>
! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_7]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFint_r2_assumed_size_to_assumed_rankEx"} : (!fir.ref<!fir.array<10x?xi32>>, !fir.shape<2>, !fir.dscope) -> (!fir.box<!fir.array<10x?xi32>>, !fir.ref<!fir.array<10x?xi32>>)
! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]]#0 : (!fir.box<!fir.array<10x?xi32>>) -> !fir.box<!fir.array<*:i32>>
diff --git a/flang/test/Lower/HLFIR/select-rank.f90 b/flang/test/Lower/HLFIR/select-rank.f90
index 0f80c723e468f..f1f968decd412 100644
--- a/flang/test/Lower/HLFIR/select-rank.f90
+++ b/flang/test/Lower/HLFIR/select-rank.f90
@@ -371,7 +371,7 @@ subroutine test_branching(x)
! CHECK: fir.call @_QPr1(%[[VAL_11]]#0) fastmath<contract> : (!fir.box<!fir.array<?xf32>>) -> ()
! CHECK: cf.br ^bb6
! CHECK: ^bb5:
-! CHECK: %[[VAL_12:.*]] = arith.constant -1 : index
+! CHECK: %[[VAL_12:.*]] = fir.assumed_size_extent : index
! CHECK: %[[VAL_13:.*]] = fir.box_addr %[[VAL_2]]#1 : (!fir.box<!fir.array<*:f32>>) -> !fir.ref<!fir.array<*:f32>>
! CHECK: %[[VAL_14:.*]] = fir.convert %[[VAL_13]] : (!fir.ref<!fir.array<*:f32>>) -> !fir.ref<!fir.array<?xf32>>
! CHECK: %[[VAL_15:.*]] = fir.shape %[[VAL_12]] : (index) -> !fir.shape<1>
@@ -435,7 +435,7 @@ subroutine test_branching(x)
! CHECK: fir.call @_QPrdefault(%[[VAL_8]]#0) fastmath<contract> : (!fir.box<!fir.array<*:f32>>) -> ()
! CHECK: cf.br ^bb5
! CHECK: ^bb4:
-! CHECK: %[[VAL_9:.*]] = arith.constant -1 : index
+! CHECK: %[[VAL_9:.*]] = fir.assumed_size_extent : index
! CHECK: %[[VAL_10:.*]] = fir.box_addr %[[VAL_2]]#1 : (!fir.box<!fir.array<*:f32>>) -> !fir.ref<!fir.array<*:f32>>
! CHECK: %[[VAL_11:.*]] = fir.convert %[[VAL_10]] : (!fir.ref<!fir.array<*:f32>>) -> !fir.ref<!fir.array<?xf32>>
! CHECK: %[[VAL_12:.*]] = fir.shape %[[VAL_9]] : (index) -> !fir.shape<1>
@@ -482,7 +482,7 @@ subroutine test_branching(x)
! CHECK: fir.call @_QPr1_implicit(%[[VAL_21]]#1) fastmath<contract> : (!fir.ref<!fir.array<?xf32>>) -> ()
! CHECK: cf.br ^bb6
! CHECK: ^bb5:
-! CHECK: %[[VAL_22:.*]] = arith.constant -1 : index
+! CHECK: %[[VAL_22:.*]] = fir.assumed_size_extent : index
! CHECK: %[[VAL_23:.*]] = fir.box_addr %[[VAL_2]]#1 : (!fir.box<!fir.array<*:f32>>) -> !fir.ref<!fir.array<*:f32>>
! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_23]] : (!fir.ref<!fir.array<*:f32>>) -> !fir.ref<!fir.array<?xf32>>
! CHECK: %[[VAL_25:.*]] = fir.shape %[[VAL_22]] : (index) -> !fir.shape<1>
@@ -534,7 +534,7 @@ subroutine test_branching(x)
! CHECK: fir.call @_QPrc1_implicit(%[[VAL_26]]) fastmath<contract> : (!fir.boxchar<1>) -> ()
! CHECK: cf.br ^bb6
! CHECK: ^bb5:
-! CHECK: %[[VAL_27:.*]] = arith.constant -1 : index
+! CHECK: %[[VAL_27:.*]] = fir.assumed_size_extent : index
! CHECK: %[[VAL_28:.*]] = fir.box_addr %[[VAL_8]]#1 : (!fir.box<!fir.array<*:!fir.char<1,?>>>) -> !fir.ref<!fir.array<*:!fir.char<1,?>>>
! CHECK: %[[VAL_29:.*]] = fir.convert %[[VAL_28]] : (!fir.ref<!fir.array<*:!fir.char<1,?>>>) -> !fir.ref<!fir.array<?x!fir.char<1,?>>>
! CHECK: %[[VAL_30:.*]] = fir.shape %[[VAL_27]] : (index) -> !fir.shape<1>
diff --git a/flang/test/Lower/Intrinsics/lbound.f90 b/flang/test/Lower/Intrinsics/lbound.f90
index a5ca2d39a5ee4..75c11ff8bc95f 100644
--- a/flang/test/Lower/Intrinsics/lbound.f90
+++ b/flang/test/Lower/Intrinsics/lbound.f90
@@ -40,7 +40,7 @@ subroutine lbound_test_2(a, dim, res)
subroutine lbound_test_3(a, dim, res)
real, dimension(2:10, 3:*) :: a
integer(8):: dim, res
-! CHECK: %[[VAL_0:.*]] = arith.constant -1 : index
+! CHECK: %[[VAL_0:.*]] = fir.assumed_size_extent : index
! CHECK: %[[VAL_1:.*]] = fir.load %arg1 : !fir.ref<i64>
! CHECK: %[[VAL_2:.*]] = fir.shape_shift %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_0]] : (index, index, index, index) -> !fir.shapeshift<2>
! CHECK: %[[VAL_3:.*]] = fir.embox %arg0(%[[VAL_2]]) : (!fir.ref<!fir.array<9x?xf32>>, !fir.shapeshift<2>) -> !fir.box<!fir.array<9x?xf32>>
diff --git a/flang/test/Lower/Intrinsics/ubound.f90 b/flang/test/Lower/Intrinsics/ubound.f90
index dae21acda170d..bc8cff8982542 100644
--- a/flang/test/Lower/Intrinsics/ubound.f90
+++ b/flang/test/Lower/Intrinsics/ubound.f90
@@ -48,7 +48,7 @@ subroutine ubound_test_2(a, dim, res)
subroutine ubound_test_3(a, dim, res)
real, dimension(10, 20, *) :: a
integer(8):: dim, res
-! CHECK: %[[VAL_0:.*]] = arith.constant -1 : index
+! CHECK: %[[VAL_0:.*]] = fir.assumed_size_extent : index
! CHECK: %[[VAL_1:.*]] = fir.shape %{{.*}}, %{{.*}}, %[[VAL_0]] : (index, index, index) -> !fir.shape<3>
! CHECK: %[[VAL_2:.*]] = fir.embox %{{.*}}(%[[VAL_1]]) : (!fir.ref<!fir.array<10x20x?xf32>>, !fir.shape<3>) -> !fir.box<!fir.array<10x20x?xf32>>
! CHECK: %[[VAL_3:.*]] = fir.load %{{.*}} : !fir.ref<i64>
diff --git a/flang/test/Lower/array-expression-assumed-size.f90 b/flang/test/Lower/array-expression-assumed-size.f90
index 2fbf315aff114..a498148d07fc7 100644
--- a/flang/test/Lower/array-expression-assumed-size.f90
+++ b/flang/test/Lower/array-expression-assumed-size.f90
@@ -19,7 +19,7 @@ end subroutine assumed_size_forall_test
! CHECK: %[[VAL_1A:.*]] = fir.convert %c10{{.*}} : (i64) -> index
! CHECK: %[[VAL_1B:.*]] = arith.cmpi sgt, %[[VAL_1A]], %c0{{.*}} : index
! CHECK: %[[VAL_1:.*]] = arith.select %[[VAL_1B]], %[[VAL_1A]], %c0{{.*}} : index
-! CHECK: %[[VAL_2:.*]] = arith.constant -1 : index
+! CHECK: %[[VAL_2:.*]] = fir.assumed_size_extent : index
! CHECK: %[[VAL_3:.*]] = arith.constant 1 : index
! CHECK: %[[VAL_4:.*]] = arith.constant 1 : i64
! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (i64) -> index
@@ -82,7 +82,7 @@ end subroutine assumed_size_forall_test
! CHECK: %[[VAL_2A:.*]] = fir.convert %c10{{.*}} : (i64) -> index
! CHECK: %[[VAL_2B:.*]] = arith.cmpi sgt, %[[VAL_2A]], %c0{{.*}} : index
! CHECK: %[[VAL_2:.*]] = arith.select %[[VAL_2B]], %[[VAL_2A]], %c0{{.*}} : index
-! CHECK: %[[VAL_3:.*]] = arith.constant -1 : index
+! CHECK: %[[VAL_3:.*]] = fir.assumed_size_extent : index
! CHECK: %[[VAL_4:.*]] = arith.constant 2 : i32
! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (i32) -> index
! CHECK: %[[VAL_6:.*]] = arith.constant 6 : i32
@@ -149,7 +149,7 @@ end subroutine assumed_size_forall_test
! PostOpt-DAG: %[[VAL_4:.*]] = arith.constant 0 : index
! PostOpt-DAG: %[[VAL_5:.*]] = arith.constant 3 : index
! PostOpt-DAG: %[[VAL_6:.*]] = arith.constant 4 : index
-! PostOpt-DAG: %[[VAL_7:.*]] = arith.constant -1 : index
+! PostOpt-DAG: %[[VAL_7:.*]] = fir.assumed_size_extent : index
! PostOpt: %[[VAL_8:.*]] = fir.shape %[[VAL_1]], %[[VAL_7]] : (index, index) -> !fir.shape<2>
! PostOpt: %[[VAL_9:.*]] = fir.slice %[[VAL_2]], %[[VAL_1]], %[[VAL_2]], %[[VAL_2]], %[[VAL_3]], %[[VAL_2]] : (index, index, index, index, index, index) -> !fir.slice<2>
! PostOpt: %[[VAL_10:.*]] = fir.allocmem !fir.array<10x?xi32>, %[[VAL_3]]
@@ -227,8 +227,8 @@ end subroutine assumed_size_forall_test
! PostOpt-DAG: %[[VAL_4:.*]] = arith.constant 1 : index
! PostOpt-DAG: %[[VAL_5:.*]] = arith.constant 0 : index
! PostOpt-DAG: %[[VAL_6:.*]] = arith.constant 5 : index
-! PostOpt-DAG: %[[VAL_8:.*]] = arith.constant -1 : index
! PostOpt: %[[VAL_7:.*]] = fir.alloca i32 {adapt.valuebyref, bindc_name = "i"}
+! PostOpt: %[[VAL_8:.*]] = fir.assumed_size_extent : index
! PostOpt: %[[VAL_9:.*]] = fir.shape %[[VAL_2]], %[[VAL_8]] : (index, index) -> !fir.shape<2>
! PostOpt: %[[VAL_10:.*]] = fir.allocmem !fir.array<10x?xi32>, %[[VAL_4]]
! PostOpt: br ^bb1(%[[VAL_5]], %[[VAL_4]] : index, index)
diff --git a/flang/test/Lower/entry-statement.f90 b/flang/test/Lower/entry-statement.f90
index 83d2d324aed87..f1e535a2bd3a1 100644
--- a/flang/test/Lower/entry-statement.f90
+++ b/flang/test/Lower/entry-statement.f90
@@ -491,7 +491,7 @@ subroutine assumed_size()
! CHECK-LABEL: func.func @_QPentry_with_assumed_size(
! CHECK-SAME: ...
[truncated]
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Thanks for looking at this Jean!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Follow-up on discussions #163505 (comment)
The purpose of this patch is to allow converting FIR array representation to memref when possible without hitting memref verifier issue.
The issue was that FIR arrays may be assumed size, in which case the last dimension will not be known at runtime. Flang uses -1 to encode this to fulfill Fortran 2023 standard requirements in 18.5.3 point 5 about CFI_desc_t.
When arrays are converted to memeref, if this
-1reaches memeref operations, it triggers verifier errors (even if the conversion happened in code that guards the code to be entered at runtime if the array is assumed-size because folders/verifiers do not take into account reachability).