Skip to content

Commit d2f5af3

Browse files
jeanPeriermahesh-attarde
authored andcommitted
[flang] add helper to create descriptor with new base address (llvm#161347)
There is currently no helper to create a descriptor for a copy of a Fortran entity based on the descriptor of the original entity and the base address of the copy (most places that are doing this currently are also doing allocation of the copy at the same time or using the runtime). Add a helper for this with a unit test.
1 parent d408875 commit d2f5af3

File tree

3 files changed

+78
-0
lines changed

3 files changed

+78
-0
lines changed

flang/include/flang/Optimizer/Builder/FIRBuilder.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -959,6 +959,15 @@ mlir::Value genLifetimeStart(mlir::OpBuilder &builder, mlir::Location loc,
959959
void genLifetimeEnd(mlir::OpBuilder &builder, mlir::Location loc,
960960
mlir::Value mem);
961961

962+
/// Given a fir.box or fir.class \p box describing an entity and a raw address
963+
/// \p newAddr for an entity with the same Fortran properties (rank, dynamic
964+
/// type, length parameters and bounds) and attributes (POINTER or ALLOCATABLE),
965+
/// create a box for \p newAddr with the same type as \p box. This assumes \p
966+
/// newAddr is for contiguous storage (\p box does not have to be contiguous).
967+
mlir::Value getDescriptorWithNewBaseAddress(fir::FirOpBuilder &builder,
968+
mlir::Location loc, mlir::Value box,
969+
mlir::Value newAddr);
970+
962971
} // namespace fir::factory
963972

964973
#endif // FORTRAN_OPTIMIZER_BUILDER_FIRBUILDER_H

flang/lib/Optimizer/Builder/FIRBuilder.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1974,3 +1974,25 @@ void fir::factory::genLifetimeEnd(mlir::OpBuilder &builder, mlir::Location loc,
19741974
mlir::Value cast) {
19751975
mlir::LLVM::LifetimeEndOp::create(builder, loc, cast);
19761976
}
1977+
1978+
mlir::Value fir::factory::getDescriptorWithNewBaseAddress(
1979+
fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value box,
1980+
mlir::Value newAddr) {
1981+
auto boxType = llvm::dyn_cast<fir::BaseBoxType>(box.getType());
1982+
assert(boxType &&
1983+
"expected a box type input in getDescriptorWithNewBaseAddress");
1984+
if (boxType.isAssumedRank())
1985+
TODO(loc, "changing descriptor base address for an assumed rank entity");
1986+
llvm::SmallVector<mlir::Value> lbounds;
1987+
fir::factory::genDimInfoFromBox(builder, loc, box, &lbounds,
1988+
/*extents=*/nullptr, /*strides=*/nullptr);
1989+
fir::BoxValue inputBoxValue(box, lbounds, /*explicitParams=*/{});
1990+
fir::ExtendedValue openedInput =
1991+
fir::factory::readBoxValue(builder, loc, inputBoxValue);
1992+
mlir::Value shape = fir::isArray(openedInput)
1993+
? builder.createShape(loc, openedInput)
1994+
: mlir::Value{};
1995+
mlir::Value typeMold = fir::isPolymorphicType(boxType) ? box : mlir::Value{};
1996+
return builder.createBox(loc, boxType, newAddr, shape, /*slice=*/{},
1997+
fir::getTypeParams(openedInput), typeMold);
1998+
}

flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -644,3 +644,50 @@ TEST_F(FIRBuilderTest, genArithIntegerOverflow) {
644644
auto op4_ioff = op4_iofi.getOverflowAttr().getValue();
645645
EXPECT_EQ(op4_ioff, nsw);
646646
}
647+
648+
TEST_F(FIRBuilderTest, getDescriptorWithNewBaseAddress) {
649+
auto builder = getBuilder();
650+
auto loc = builder.getUnknownLoc();
651+
652+
// Build an input fir.box for a 1-D array of i64 with constant extent 10.
653+
auto i64Ty = builder.getI64Type();
654+
auto seqTy = fir::SequenceType::get({10}, i64Ty);
655+
auto refArrTy = fir::ReferenceType::get(seqTy);
656+
auto ptrTy = fir::PointerType::get(seqTy);
657+
auto boxTy = fir::BoxType::get(ptrTy);
658+
// Create an undef box descriptor value (descriptor contents are unspecified).
659+
mlir::Value inputBox = fir::UndefOp::create(builder, loc, boxTy);
660+
661+
// New base address (same element type and properties).
662+
mlir::Value addr2 = fir::UndefOp::create(builder, loc, refArrTy);
663+
664+
mlir::Value newBox = fir::factory::getDescriptorWithNewBaseAddress(
665+
builder, loc, inputBox, addr2);
666+
667+
// The returned descriptor must have the same type as the input box.
668+
EXPECT_EQ(newBox.getType(), inputBox.getType());
669+
670+
// It must be constructed by an embox using the new base address.
671+
ASSERT_TRUE(llvm::isa_and_nonnull<fir::EmboxOp>(newBox.getDefiningOp()));
672+
auto embox = llvm::dyn_cast<fir::EmboxOp>(newBox.getDefiningOp());
673+
EXPECT_EQ(embox.getMemref(), addr2);
674+
675+
// The shape should be derived from the input box; expect a fir.shape with one
676+
// extent that comes from a fir.box_dims reading from the original input box.
677+
mlir::Value shape = embox.getShape();
678+
ASSERT_TRUE(shape);
679+
ASSERT_TRUE(llvm::isa_and_nonnull<fir::ShapeShiftOp>(shape.getDefiningOp()));
680+
auto shapeOp = llvm::dyn_cast<fir::ShapeShiftOp>(shape.getDefiningOp());
681+
ASSERT_EQ(shapeOp.getExtents().size(), 1u);
682+
mlir::Value extent0 = shapeOp.getExtents()[0];
683+
ASSERT_TRUE(llvm::isa_and_nonnull<fir::BoxDimsOp>(extent0.getDefiningOp()));
684+
auto dimOp = llvm::dyn_cast<fir::BoxDimsOp>(extent0.getDefiningOp());
685+
EXPECT_EQ(dimOp.getVal(), inputBox);
686+
687+
// Also verify the origin comes from a BoxDims on the same input box.
688+
ASSERT_EQ(shapeOp.getOrigins().size(), 1u);
689+
mlir::Value origin0 = shapeOp.getOrigins()[0];
690+
ASSERT_TRUE(llvm::isa_and_nonnull<fir::BoxDimsOp>(origin0.getDefiningOp()));
691+
auto lbOp = llvm::dyn_cast<fir::BoxDimsOp>(origin0.getDefiningOp());
692+
EXPECT_EQ(lbOp.getVal(), inputBox);
693+
}

0 commit comments

Comments
 (0)