@@ -6071,33 +6071,80 @@ mlir::Value IntrinsicLibrary::genSetExponent(mlir::Type resultType,
6071
6071
fir::getBase (args[1 ])));
6072
6072
}
6073
6073
6074
+ // / Create a fir.box to be passed to the LBOUND/UBOUND runtime.
6075
+ // / This ensure that local lower bounds of assumed shape are propagated and that
6076
+ // / a fir.box with equivalent LBOUNDs.
6077
+ static mlir::Value
6078
+ createBoxForRuntimeBoundInquiry (mlir::Location loc, fir::FirOpBuilder &builder,
6079
+ const fir::ExtendedValue &array) {
6080
+ // Assumed-rank descriptor must always carry accurate lower bound information
6081
+ // in lowering since they cannot be tracked on the side in a vector at compile
6082
+ // time.
6083
+ if (array.hasAssumedRank ())
6084
+ return builder.createBox (loc, array);
6085
+
6086
+ return array.match (
6087
+ [&](const fir::BoxValue &boxValue) -> mlir::Value {
6088
+ // This entity is mapped to a fir.box that may not contain the local
6089
+ // lower bound information if it is a dummy. Rebox it with the local
6090
+ // shape information.
6091
+ mlir::Value localShape = builder.createShape (loc, array);
6092
+ mlir::Value oldBox = boxValue.getAddr ();
6093
+ return builder.create <fir::ReboxOp>(loc, oldBox.getType (), oldBox,
6094
+ localShape,
6095
+ /* slice=*/ mlir::Value{});
6096
+ },
6097
+ [&](const auto &) -> mlir::Value {
6098
+ // This is a pointer/allocatable, or an entity not yet tracked with a
6099
+ // fir.box. For pointer/allocatable, createBox will forward the
6100
+ // descriptor that contains the correct lower bound information. For
6101
+ // other entities, a new fir.box will be made with the local lower
6102
+ // bounds.
6103
+ return builder.createBox (loc, array);
6104
+ });
6105
+ }
6106
+
6074
6107
// / Generate runtime call to inquire about all the bounds/extents of an
6075
- // / assumed-rank array .
6108
+ // / array (or an assumed-rank) .
6076
6109
template <typename Func>
6077
- static fir::ExtendedValue genAssumedRankBoundInquiry (
6078
- fir::FirOpBuilder &builder, mlir::Location loc, mlir::Type resultType,
6079
- llvm::ArrayRef<fir::ExtendedValue> args, int kindPos, Func genRtCall) {
6110
+ static fir::ExtendedValue
6111
+ genBoundInquiry (fir::FirOpBuilder &builder, mlir::Location loc,
6112
+ mlir::Type resultType, llvm::ArrayRef<fir::ExtendedValue> args,
6113
+ int kindPos, Func genRtCall, bool needAccurateLowerBound) {
6080
6114
const fir::ExtendedValue &array = args[0 ];
6081
- // Allocate an array with the maximum rank, that is big enough to hold the
6082
- // result but still "small" (15 elements). Static size alloca make stack
6083
- // analysis/manipulation easier.
6115
+ const bool hasAssumedRank = array.hasAssumedRank ();
6084
6116
mlir::Type resultElementType = fir::unwrapSequenceType (resultType);
6085
- mlir::Type allocSeqType =
6086
- fir::SequenceType::get ({Fortran::common::maxRank}, resultElementType);
6117
+ // For assumed-rank arrays, allocate an array with the maximum rank, that is
6118
+ // big enough to hold the result but still "small" (15 elements). Static size
6119
+ // alloca make stack analysis/manipulation easier.
6120
+ int rank = hasAssumedRank ? Fortran::common::maxRank : array.rank ();
6121
+ mlir::Type allocSeqType = fir::SequenceType::get (rank, resultElementType);
6087
6122
mlir::Value resultStorage = builder.createTemporary (loc, allocSeqType);
6088
- mlir::Value arrayBox = builder.createBox (loc, array);
6123
+ mlir::Value arrayBox =
6124
+ needAccurateLowerBound
6125
+ ? createBoxForRuntimeBoundInquiry (loc, builder, array)
6126
+ : builder.createBox (loc, array);
6089
6127
mlir::Value kind = isStaticallyAbsent (args, kindPos)
6090
6128
? builder.createIntegerConstant (
6091
6129
loc, builder.getI32Type (),
6092
6130
builder.getKindMap ().defaultIntegerKind ())
6093
6131
: fir::getBase (args[kindPos]);
6094
6132
genRtCall (builder, loc, resultStorage, arrayBox, kind);
6095
- mlir::Type baseType =
6096
- fir::ReferenceType::get (builder.getVarLenSeqTy (resultElementType));
6097
- mlir::Value resultBase = builder.createConvert (loc, baseType, resultStorage);
6098
- mlir::Value rank =
6099
- builder.create <fir::BoxRankOp>(loc, builder.getIndexType (), arrayBox);
6100
- return fir::ArrayBoxValue{resultBase, {rank}};
6133
+ if (hasAssumedRank) {
6134
+ // Cast to fir.ref<array<?xik>> since the result extent is not a compile
6135
+ // time constant.
6136
+ mlir::Type baseType =
6137
+ fir::ReferenceType::get (builder.getVarLenSeqTy (resultElementType));
6138
+ mlir::Value resultBase =
6139
+ builder.createConvert (loc, baseType, resultStorage);
6140
+ mlir::Value rankValue =
6141
+ builder.create <fir::BoxRankOp>(loc, builder.getIndexType (), arrayBox);
6142
+ return fir::ArrayBoxValue{resultBase, {rankValue}};
6143
+ }
6144
+ // Result extent is a compile time constant in the other cases.
6145
+ mlir::Value rankValue =
6146
+ builder.createIntegerConstant (loc, builder.getIndexType (), rank);
6147
+ return fir::ArrayBoxValue{resultStorage, {rankValue}};
6101
6148
}
6102
6149
6103
6150
// SHAPE
@@ -6107,8 +6154,9 @@ IntrinsicLibrary::genShape(mlir::Type resultType,
6107
6154
assert (args.size () >= 1 );
6108
6155
const fir::ExtendedValue &array = args[0 ];
6109
6156
if (array.hasAssumedRank ())
6110
- return genAssumedRankBoundInquiry (builder, loc, resultType, args,
6111
- /* kindPos=*/ 1 , fir::runtime::genShape);
6157
+ return genBoundInquiry (builder, loc, resultType, args,
6158
+ /* kindPos=*/ 1 , fir::runtime::genShape,
6159
+ /* needAccurateLowerBound=*/ false );
6112
6160
int rank = array.rank ();
6113
6161
mlir::Type indexType = builder.getIndexType ();
6114
6162
mlir::Type extentType = fir::unwrapSequenceType (resultType);
@@ -6344,33 +6392,6 @@ static mlir::Value computeLBOUND(fir::FirOpBuilder &builder, mlir::Location loc,
6344
6392
return builder.create <mlir::arith::SelectOp>(loc, dimIsEmpty, one, lb);
6345
6393
}
6346
6394
6347
- // / Create a fir.box to be passed to the LBOUND/UBOUND runtime.
6348
- // / This ensure that local lower bounds of assumed shape are propagated and that
6349
- // / a fir.box with equivalent LBOUNDs.
6350
- static mlir::Value
6351
- createBoxForRuntimeBoundInquiry (mlir::Location loc, fir::FirOpBuilder &builder,
6352
- const fir::ExtendedValue &array) {
6353
- return array.match (
6354
- [&](const fir::BoxValue &boxValue) -> mlir::Value {
6355
- // This entity is mapped to a fir.box that may not contain the local
6356
- // lower bound information if it is a dummy. Rebox it with the local
6357
- // shape information.
6358
- mlir::Value localShape = builder.createShape (loc, array);
6359
- mlir::Value oldBox = boxValue.getAddr ();
6360
- return builder.create <fir::ReboxOp>(loc, oldBox.getType (), oldBox,
6361
- localShape,
6362
- /* slice=*/ mlir::Value{});
6363
- },
6364
- [&](const auto &) -> mlir::Value {
6365
- // This is a pointer/allocatable, or an entity not yet tracked with a
6366
- // fir.box. For pointer/allocatable, createBox will forward the
6367
- // descriptor that contains the correct lower bound information. For
6368
- // other entities, a new fir.box will be made with the local lower
6369
- // bounds.
6370
- return builder.createBox (loc, array);
6371
- });
6372
- }
6373
-
6374
6395
// LBOUND
6375
6396
fir::ExtendedValue
6376
6397
IntrinsicLibrary::genLbound (mlir::Type resultType,
@@ -6380,9 +6401,12 @@ IntrinsicLibrary::genLbound(mlir::Type resultType,
6380
6401
// Semantics builds signatures for LBOUND calls as either
6381
6402
// LBOUND(array, dim, [kind]) or LBOUND(array, [kind]).
6382
6403
const bool dimIsAbsent = args.size () == 2 || isStaticallyAbsent (args, 1 );
6383
- if (array.hasAssumedRank () && dimIsAbsent)
6384
- return genAssumedRankBoundInquiry (builder, loc, resultType, args,
6385
- /* kindPos=*/ 1 , fir::runtime::genLbound);
6404
+ if (array.hasAssumedRank () && dimIsAbsent) {
6405
+ int kindPos = args.size () == 2 ? 1 : 2 ;
6406
+ return genBoundInquiry (builder, loc, resultType, args, kindPos,
6407
+ fir::runtime::genLbound,
6408
+ /* needAccurateLowerBound=*/ true );
6409
+ }
6386
6410
6387
6411
mlir::Type indexType = builder.getIndexType ();
6388
6412
@@ -6434,36 +6458,21 @@ fir::ExtendedValue
6434
6458
IntrinsicLibrary::genUbound (mlir::Type resultType,
6435
6459
llvm::ArrayRef<fir::ExtendedValue> args) {
6436
6460
assert (args.size () == 3 || args.size () == 2 );
6437
- if (args.size () == 3 ) {
6461
+ const bool dimIsAbsent = args.size () == 2 || isStaticallyAbsent (args, 1 );
6462
+ if (!dimIsAbsent) {
6438
6463
// Handle calls to UBOUND with the DIM argument, which return a scalar
6439
6464
mlir::Value extent = fir::getBase (genSize (resultType, args));
6440
6465
mlir::Value lbound = fir::getBase (genLbound (resultType, args));
6441
6466
6442
6467
mlir::Value one = builder.createIntegerConstant (loc, resultType, 1 );
6443
6468
mlir::Value ubound = builder.create <mlir::arith::SubIOp>(loc, lbound, one);
6444
6469
return builder.create <mlir::arith::AddIOp>(loc, ubound, extent);
6445
- } else {
6446
- // Handle calls to UBOUND without the DIM argument, which return an array
6447
- mlir::Value kind = isStaticallyAbsent (args[1 ])
6448
- ? builder.createIntegerConstant (
6449
- loc, builder.getIndexType (),
6450
- builder.getKindMap ().defaultIntegerKind ())
6451
- : fir::getBase (args[1 ]);
6452
-
6453
- // Create mutable fir.box to be passed to the runtime for the result.
6454
- mlir::Type type = builder.getVarLenSeqTy (resultType, /* rank=*/ 1 );
6455
- fir::MutableBoxValue resultMutableBox =
6456
- fir::factory::createTempMutableBox (builder, loc, type);
6457
- mlir::Value resultIrBox =
6458
- fir::factory::getMutableIRBox (builder, loc, resultMutableBox);
6459
-
6460
- fir::ExtendedValue box =
6461
- createBoxForRuntimeBoundInquiry (loc, builder, args[0 ]);
6462
- fir::runtime::genUbound (builder, loc, resultIrBox, fir::getBase (box), kind);
6463
-
6464
- return readAndAddCleanUp (resultMutableBox, resultType, " UBOUND" );
6465
6470
}
6466
- return mlir::Value ();
6471
+ // Handle calls to UBOUND without the DIM argument, which return an array
6472
+ int kindPos = args.size () == 2 ? 1 : 2 ;
6473
+ return genBoundInquiry (builder, loc, resultType, args, kindPos,
6474
+ fir::runtime::genUbound,
6475
+ /* needAccurateLowerBound=*/ true );
6467
6476
}
6468
6477
6469
6478
// SPACING
0 commit comments