Skip to content

Commit 0adf900

Browse files
committed
[flang][FIR] add fir.assumed_size_extent to abstract assumed-size extent encoding
1 parent 00092f9 commit 0adf900

File tree

16 files changed

+165
-18
lines changed

16 files changed

+165
-18
lines changed

flang/include/flang/Optimizer/Dialect/FIROps.td

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1249,6 +1249,41 @@ def fir_IsAssumedSizeOp : fir_SimpleOp<"is_assumed_size", [NoMemoryEffect]> {
12491249
let results = (outs BoolLike);
12501250
}
12511251

1252+
def fir_AssumedSizeExtentOp : fir_SimpleOneResultOp<"assumed_size_extent", [NoMemoryEffect]> {
1253+
let summary = "get the assumed-size last extent sentinel";
1254+
1255+
let description = [{
1256+
Returns the special extent value representing the last dimension of an
1257+
assumed-size array. This is used to model the semantics in FIR without
1258+
directly materializing the sentinel value. The concrete encoding is
1259+
introduced during FIR to LLVM lowering.
1260+
1261+
```
1262+
%e = fir.assumed_size_extent : index
1263+
```
1264+
}];
1265+
1266+
let results = (outs Index);
1267+
let assemblyFormat = "attr-dict `:` type(results)";
1268+
}
1269+
1270+
def fir_IsAssumedSizeExtentOp : fir_SimpleOp<"is_assumed_size_extent", [NoMemoryEffect]> {
1271+
let summary = "is value the assumed-size last extent sentinel";
1272+
1273+
let description = [{
1274+
Returns true iff the given integer equals the assumed-size extent sentinel.
1275+
1276+
```
1277+
%t = fir.is_assumed_size_extent %v : (index) -> i1
1278+
%c = fir.is_assumed_size_extent %x : (i32) -> i1
1279+
```
1280+
}];
1281+
1282+
let arguments = (ins AnyIntegerLike:$val);
1283+
let results = (outs BoolLike);
1284+
let hasCanonicalizer = 1;
1285+
}
1286+
12521287
def fir_BoxIsPtrOp : fir_SimpleOp<"box_isptr", [NoMemoryEffect]> {
12531288
let summary = "is the boxed value a POINTER?";
12541289

flang/lib/Lower/Bridge.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4010,8 +4010,8 @@ class FirConverter : public Fortran::lower::AbstractConverter {
40104010
// parameters and dynamic type. The selector cannot be a
40114011
// POINTER/ALLOCATBLE as per F'2023 C1160.
40124012
fir::ExtendedValue newExv;
4013-
llvm::SmallVector assumeSizeExtents{
4014-
builder->createMinusOneInteger(loc, builder->getIndexType())};
4013+
llvm::SmallVector<mlir::Value> assumeSizeExtents{
4014+
builder->create<fir::AssumedSizeExtentOp>(loc)};
40154015
mlir::Value baseAddr =
40164016
hlfir::genVariableRawAddress(loc, *builder, selector);
40174017
const bool isVolatile = fir::isa_volatile_type(selector.getType());

flang/lib/Lower/ConvertVariable.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1711,7 +1711,7 @@ static void lowerExplicitLowerBounds(
17111711
/// CFI_desc_t requirements in 18.5.3 point 5.).
17121712
static mlir::Value getAssumedSizeExtent(mlir::Location loc,
17131713
fir::FirOpBuilder &builder) {
1714-
return builder.createMinusOneInteger(loc, builder.getIndexType());
1714+
return builder.create<fir::AssumedSizeExtentOp>(loc);
17151715
}
17161716

17171717
/// Lower explicit extents into \p result if this is an explicit-shape or

flang/lib/Optimizer/CodeGen/CodeGen.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -749,6 +749,44 @@ struct VolatileCastOpConversion
749749
}
750750
};
751751

752+
/// Lower `fir.assumed_size_extent` to constant -1 of index type.
753+
struct AssumedSizeExtentOpConversion
754+
: public fir::FIROpConversion<fir::AssumedSizeExtentOp> {
755+
using FIROpConversion::FIROpConversion;
756+
757+
llvm::LogicalResult
758+
matchAndRewrite(fir::AssumedSizeExtentOp op, OpAdaptor,
759+
mlir::ConversionPatternRewriter &rewriter) const override {
760+
mlir::Location loc = op.getLoc();
761+
mlir::Type ity = lowerTy().indexType();
762+
auto cst = fir::genConstantIndex(loc, ity, rewriter, -1);
763+
rewriter.replaceOp(op, cst.getResult());
764+
return mlir::success();
765+
}
766+
};
767+
768+
/// Lower `fir.is_assumed_size_extent` to integer equality with -1.
769+
struct IsAssumedSizeExtentOpConversion
770+
: public fir::FIROpConversion<fir::IsAssumedSizeExtentOp> {
771+
using FIROpConversion::FIROpConversion;
772+
773+
llvm::LogicalResult
774+
matchAndRewrite(fir::IsAssumedSizeExtentOp op, OpAdaptor adaptor,
775+
mlir::ConversionPatternRewriter &rewriter) const override {
776+
mlir::Location loc = op.getLoc();
777+
mlir::Value val = adaptor.getVal();
778+
mlir::Type valTy = val.getType();
779+
// Create constant -1 of the operand type.
780+
auto negOneAttr = rewriter.getIntegerAttr(valTy, -1);
781+
auto negOne =
782+
mlir::LLVM::ConstantOp::create(rewriter, loc, valTy, negOneAttr);
783+
auto cmp = mlir::LLVM::ICmpOp::create(
784+
rewriter, loc, mlir::LLVM::ICmpPredicate::eq, val, negOne);
785+
rewriter.replaceOp(op, cmp.getResult());
786+
return mlir::success();
787+
}
788+
};
789+
752790
/// convert value of from-type to value of to-type
753791
struct ConvertOpConversion : public fir::FIROpConversion<fir::ConvertOp> {
754792
using FIROpConversion::FIROpConversion;
@@ -4360,6 +4398,7 @@ void fir::populateFIRToLLVMConversionPatterns(
43604398
AllocaOpConversion, AllocMemOpConversion, BoxAddrOpConversion,
43614399
BoxCharLenOpConversion, BoxDimsOpConversion, BoxEleSizeOpConversion,
43624400
BoxIsAllocOpConversion, BoxIsArrayOpConversion, BoxIsPtrOpConversion,
4401+
AssumedSizeExtentOpConversion, IsAssumedSizeExtentOpConversion,
43634402
BoxOffsetOpConversion, BoxProcHostOpConversion, BoxRankOpConversion,
43644403
BoxTypeCodeOpConversion, BoxTypeDescOpConversion, CallOpConversion,
43654404
CmpcOpConversion, VolatileCastOpConversion, ConvertOpConversion,

flang/lib/Optimizer/Dialect/FIROps.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5142,6 +5142,34 @@ void fir::BoxTotalElementsOp::getCanonicalizationPatterns(
51425142
patterns.add<SimplifyBoxTotalElementsOp>(context);
51435143
}
51445144

5145+
//===----------------------------------------------------------------------===//
5146+
// IsAssumedSizeExtentOp and AssumedSizeExtentOp
5147+
//===----------------------------------------------------------------------===//
5148+
5149+
namespace {
5150+
struct FoldIsAssumedSizeExtentOnCtor
5151+
: public mlir::OpRewritePattern<fir::IsAssumedSizeExtentOp> {
5152+
using mlir::OpRewritePattern<fir::IsAssumedSizeExtentOp>::OpRewritePattern;
5153+
mlir::LogicalResult
5154+
matchAndRewrite(fir::IsAssumedSizeExtentOp op,
5155+
mlir::PatternRewriter &rewriter) const override {
5156+
if (llvm::isa_and_nonnull<fir::AssumedSizeExtentOp>(
5157+
op.getVal().getDefiningOp())) {
5158+
mlir::Type i1 = rewriter.getI1Type();
5159+
rewriter.replaceOpWithNewOp<mlir::arith::ConstantOp>(
5160+
op, i1, rewriter.getIntegerAttr(i1, 1));
5161+
return mlir::success();
5162+
}
5163+
return mlir::failure();
5164+
}
5165+
};
5166+
} // namespace
5167+
5168+
void fir::IsAssumedSizeExtentOp::getCanonicalizationPatterns(
5169+
mlir::RewritePatternSet &patterns, mlir::MLIRContext *context) {
5170+
patterns.add<FoldIsAssumedSizeExtentOnCtor>(context);
5171+
}
5172+
51455173
//===----------------------------------------------------------------------===//
51465174
// LocalitySpecifierOp
51475175
//===----------------------------------------------------------------------===//

flang/lib/Optimizer/Transforms/ArrayValueCopy.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -832,8 +832,8 @@ static mlir::Type getEleTy(mlir::Type ty) {
832832
static bool isAssumedSize(llvm::SmallVectorImpl<mlir::Value> &extents) {
833833
if (extents.empty())
834834
return false;
835-
auto cstLen = fir::getIntIfConstant(extents.back());
836-
return cstLen.has_value() && *cstLen == -1;
835+
return llvm::isa_and_nonnull<fir::AssumedSizeExtentOp>(
836+
extents.back().getDefiningOp());
837837
}
838838

839839
// Extract extents from the ShapeOp/ShapeShiftOp into the result vector.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: fir-opt --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" %s | FileCheck %s
2+
3+
// CHECK-LABEL: @assumed_size_extent(
4+
// CHECK: %[[CNEG1:.*]] = llvm.mlir.constant(-1 : i64)
5+
// CHECK: llvm.return %[[CNEG1]] : i64
6+
func.func @assumed_size_extent() -> index {
7+
%e = fir.assumed_size_extent : index
8+
return %e : index
9+
}
10+
11+
// CHECK-LABEL: @is_assumed_size_extent(
12+
// CHECK: %[[NEG1:.*]] = llvm.mlir.constant(-1 : i64)
13+
// CHECK: %[[CMP:.*]] = llvm.icmp "eq"
14+
// CHECK: llvm.return %[[CMP]] : i1
15+
func.func @is_assumed_size_extent(%x: index) -> i1 {
16+
%c = fir.is_assumed_size_extent %x : (index) -> i1
17+
return %c : i1
18+
}
19+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: fir-opt --canonicalize %s | FileCheck %s
2+
3+
// Verify: fir.is_assumed_size_extent(fir.assumed_size_extent) folds to i1 true.
4+
5+
// CHECK-LABEL: func.func @fold(
6+
func.func @fold() -> i1 {
7+
%e = fir.assumed_size_extent : index
8+
// CHECK: %[[C:.*]] = arith.constant true
9+
%t = fir.is_assumed_size_extent %e : (index) -> i1
10+
return %t : i1
11+
}
12+
13+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: fir-opt %s | fir-opt | FileCheck %s
2+
3+
func.func @roundtrip() {
4+
// CHECK: %[[E:.*]] = fir.assumed_size_extent : index
5+
%e = fir.assumed_size_extent : index
6+
7+
// CHECK: %[[T:.*]] = fir.is_assumed_size_extent %[[E]] : (index) -> i1
8+
%t = fir.is_assumed_size_extent %e : (index) -> i1
9+
10+
return
11+
}
12+
13+

flang/test/HLFIR/assumed-type-actual-args.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ subroutine s5b(x)
113113
! CHECK-LABEL: func.func @_QPtest2(
114114
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<?xnone>> {fir.bindc_name = "x"}) {
115115
! CHECK: %[[DSCOPE:.*]] = fir.dummy_scope : !fir.dscope
116-
! CHECK: %[[VAL_1:.*]] = arith.constant -1 : index
116+
! CHECK: %[[VAL_1:.*]] = fir.assumed_size_extent : index
117117
! CHECK: %[[VAL_2:.*]] = fir.shape %[[VAL_1]] : (index) -> !fir.shape<1>
118118
! 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>>)
119119
! CHECK: fir.call @_QPs2(%[[VAL_3]]#1) fastmath<contract> : (!fir.ref<!fir.array<?xnone>>) -> ()

0 commit comments

Comments
 (0)