@@ -87,6 +87,14 @@ static inline mlir::Type getI8Type(mlir::MLIRContext *context) {
8787 return mlir::IntegerType::get (context, 8 );
8888}
8989
90+ static mlir::LLVM::ConstantOp
91+ genConstantIndex (mlir::Location loc, mlir::Type ity,
92+ mlir::ConversionPatternRewriter &rewriter,
93+ std::int64_t offset) {
94+ auto cattr = rewriter.getI64IntegerAttr (offset);
95+ return mlir::LLVM::ConstantOp::create (rewriter, loc, ity, cattr);
96+ }
97+
9098static mlir::Block *createBlock (mlir::ConversionPatternRewriter &rewriter,
9199 mlir::Block *insertBefore) {
92100 assert (insertBefore && " expected valid insertion block" );
@@ -200,6 +208,39 @@ getDependentTypeMemSizeFn(fir::RecordType recTy, fir::AllocaOp op,
200208 TODO (op.getLoc (), " did not find allocation function" );
201209}
202210
211+ // Compute the alloc scale size (constant factors encoded in the array type).
212+ // We do this for arrays without a constant interior or arrays of character with
213+ // dynamic length arrays, since those are the only ones that get decayed to a
214+ // pointer to the element type.
215+ template <typename OP>
216+ static mlir::Value
217+ genAllocationScaleSize (OP op, mlir::Type ity,
218+ mlir::ConversionPatternRewriter &rewriter) {
219+ mlir::Location loc = op.getLoc ();
220+ mlir::Type dataTy = op.getInType ();
221+ auto seqTy = mlir::dyn_cast<fir::SequenceType>(dataTy);
222+ fir::SequenceType::Extent constSize = 1 ;
223+ if (seqTy) {
224+ int constRows = seqTy.getConstantRows ();
225+ const fir::SequenceType::ShapeRef &shape = seqTy.getShape ();
226+ if (constRows != static_cast <int >(shape.size ())) {
227+ for (auto extent : shape) {
228+ if (constRows-- > 0 )
229+ continue ;
230+ if (extent != fir::SequenceType::getUnknownExtent ())
231+ constSize *= extent;
232+ }
233+ }
234+ }
235+
236+ if (constSize != 1 ) {
237+ mlir::Value constVal{
238+ genConstantIndex (loc, ity, rewriter, constSize).getResult ()};
239+ return constVal;
240+ }
241+ return nullptr ;
242+ }
243+
203244namespace {
204245struct DeclareOpConversion : public fir ::FIROpConversion<fir::cg::XDeclareOp> {
205246public:
@@ -234,7 +275,7 @@ struct AllocaOpConversion : public fir::FIROpConversion<fir::AllocaOp> {
234275 auto loc = alloc.getLoc ();
235276 mlir::Type ity = lowerTy ().indexType ();
236277 unsigned i = 0 ;
237- mlir::Value size = fir:: genConstantIndex (loc, ity, rewriter, 1 ).getResult ();
278+ mlir::Value size = genConstantIndex (loc, ity, rewriter, 1 ).getResult ();
238279 mlir::Type firObjType = fir::unwrapRefType (alloc.getType ());
239280 mlir::Type llvmObjectType = convertObjectType (firObjType);
240281 if (alloc.hasLenParams ()) {
@@ -266,8 +307,7 @@ struct AllocaOpConversion : public fir::FIROpConversion<fir::AllocaOp> {
266307 << scalarType << " with type parameters" ;
267308 }
268309 }
269- if (auto scaleSize = fir::genAllocationScaleSize (
270- alloc.getLoc (), alloc.getInType (), ity, rewriter))
310+ if (auto scaleSize = genAllocationScaleSize (alloc, ity, rewriter))
271311 size =
272312 rewriter.createOrFold <mlir::LLVM::MulOp>(loc, ity, size, scaleSize);
273313 if (alloc.hasShapeOperands ()) {
@@ -444,7 +484,7 @@ struct BoxIsArrayOpConversion : public fir::FIROpConversion<fir::BoxIsArrayOp> {
444484 auto loc = boxisarray.getLoc ();
445485 TypePair boxTyPair = getBoxTypePair (boxisarray.getVal ().getType ());
446486 mlir::Value rank = getRankFromBox (loc, boxTyPair, a, rewriter);
447- mlir::Value c0 = fir:: genConstantIndex (loc, rank.getType (), rewriter, 0 );
487+ mlir::Value c0 = genConstantIndex (loc, rank.getType (), rewriter, 0 );
448488 rewriter.replaceOpWithNewOp <mlir::LLVM::ICmpOp>(
449489 boxisarray, mlir::LLVM::ICmpPredicate::ne, rank, c0);
450490 return mlir::success ();
@@ -780,7 +820,7 @@ struct ConvertOpConversion : public fir::FIROpConversion<fir::ConvertOp> {
780820 // Do folding for constant inputs.
781821 if (auto constVal = fir::getIntIfConstant (op0)) {
782822 mlir::Value normVal =
783- fir:: genConstantIndex (loc, toTy, rewriter, *constVal ? 1 : 0 );
823+ genConstantIndex (loc, toTy, rewriter, *constVal ? 1 : 0 );
784824 rewriter.replaceOp (convert, normVal);
785825 return mlir::success ();
786826 }
@@ -793,7 +833,7 @@ struct ConvertOpConversion : public fir::FIROpConversion<fir::ConvertOp> {
793833 }
794834
795835 // Compare the input with zero.
796- mlir::Value zero = fir:: genConstantIndex (loc, fromTy, rewriter, 0 );
836+ mlir::Value zero = genConstantIndex (loc, fromTy, rewriter, 0 );
797837 auto isTrue = mlir::LLVM::ICmpOp::create (
798838 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, op0, zero);
799839
@@ -1042,6 +1082,21 @@ static mlir::SymbolRefAttr getMalloc(fir::AllocMemOp op,
10421082 return getMallocInModule (mod, op, rewriter, indexType);
10431083}
10441084
1085+ // / Helper function for generating the LLVM IR that computes the distance
1086+ // / in bytes between adjacent elements pointed to by a pointer
1087+ // / of type \p ptrTy. The result is returned as a value of \p idxTy integer
1088+ // / type.
1089+ static mlir::Value
1090+ computeElementDistance (mlir::Location loc, mlir::Type llvmObjectType,
1091+ mlir::Type idxTy,
1092+ mlir::ConversionPatternRewriter &rewriter,
1093+ const mlir::DataLayout &dataLayout) {
1094+ llvm::TypeSize size = dataLayout.getTypeSize (llvmObjectType);
1095+ unsigned short alignment = dataLayout.getTypeABIAlignment (llvmObjectType);
1096+ std::int64_t distance = llvm::alignTo (size, alignment);
1097+ return genConstantIndex (loc, idxTy, rewriter, distance);
1098+ }
1099+
10451100// / Return value of the stride in bytes between adjacent elements
10461101// / of LLVM type \p llTy. The result is returned as a value of
10471102// / \p idxTy integer type.
@@ -1050,7 +1105,7 @@ genTypeStrideInBytes(mlir::Location loc, mlir::Type idxTy,
10501105 mlir::ConversionPatternRewriter &rewriter, mlir::Type llTy,
10511106 const mlir::DataLayout &dataLayout) {
10521107 // Create a pointer type and use computeElementDistance().
1053- return fir:: computeElementDistance (loc, llTy, idxTy, rewriter, dataLayout);
1108+ return computeElementDistance (loc, llTy, idxTy, rewriter, dataLayout);
10541109}
10551110
10561111namespace {
@@ -1069,18 +1124,17 @@ struct AllocMemOpConversion : public fir::FIROpConversion<fir::AllocMemOp> {
10691124 if (fir::isRecordWithTypeParameters (fir::unwrapSequenceType (dataTy)))
10701125 TODO (loc, " fir.allocmem codegen of derived type with length parameters" );
10711126 mlir::Value size = genTypeSizeInBytes (loc, ity, rewriter, llvmObjectTy);
1072- if (auto scaleSize =
1073- fir::genAllocationScaleSize (loc, heap.getInType (), ity, rewriter))
1074- size = rewriter.create <mlir::LLVM::MulOp>(loc, ity, size, scaleSize);
1127+ if (auto scaleSize = genAllocationScaleSize (heap, ity, rewriter))
1128+ size = mlir::LLVM::MulOp::create (rewriter, loc, ity, size, scaleSize);
10751129 for (mlir::Value opnd : adaptor.getOperands ())
10761130 size = mlir::LLVM::MulOp::create (rewriter, loc, ity, size,
10771131 integerCast (loc, rewriter, ity, opnd));
10781132
10791133 // As the return value of malloc(0) is implementation defined, allocate one
10801134 // byte to ensure the allocation status being true. This behavior aligns to
10811135 // what the runtime has.
1082- mlir::Value zero = fir:: genConstantIndex (loc, ity, rewriter, 0 );
1083- mlir::Value one = fir:: genConstantIndex (loc, ity, rewriter, 1 );
1136+ mlir::Value zero = genConstantIndex (loc, ity, rewriter, 0 );
1137+ mlir::Value one = genConstantIndex (loc, ity, rewriter, 1 );
10841138 mlir::Value cmp = mlir::LLVM::ICmpOp::create (
10851139 rewriter, loc, mlir::LLVM::ICmpPredicate::sgt, size, zero);
10861140 size = mlir::LLVM::SelectOp::create (rewriter, loc, cmp, size, one);
@@ -1103,8 +1157,7 @@ struct AllocMemOpConversion : public fir::FIROpConversion<fir::AllocMemOp> {
11031157 mlir::Value genTypeSizeInBytes (mlir::Location loc, mlir::Type idxTy,
11041158 mlir::ConversionPatternRewriter &rewriter,
11051159 mlir::Type llTy) const {
1106- return fir::computeElementDistance (loc, llTy, idxTy, rewriter,
1107- getDataLayout ());
1160+ return computeElementDistance (loc, llTy, idxTy, rewriter, getDataLayout ());
11081161 }
11091162};
11101163} // namespace
@@ -1291,7 +1344,7 @@ genCUFAllocDescriptor(mlir::Location loc,
12911344 mlir::Type structTy = typeConverter.convertBoxTypeAsStruct (boxTy);
12921345 std::size_t boxSize = dl->getTypeSizeInBits (structTy) / 8 ;
12931346 mlir::Value sizeInBytes =
1294- fir:: genConstantIndex (loc, llvmIntPtrType, rewriter, boxSize);
1347+ genConstantIndex (loc, llvmIntPtrType, rewriter, boxSize);
12951348 llvm::SmallVector args = {sizeInBytes, sourceFile, sourceLine};
12961349 return mlir::LLVM::CallOp::create (rewriter, loc, fctTy,
12971350 RTNAME_STRING (CUFAllocDescriptor), args)
@@ -1546,7 +1599,7 @@ struct EmboxCommonConversion : public fir::FIROpConversion<OP> {
15461599 // representation of derived types with pointer/allocatable components.
15471600 // This has been seen in hashing algorithms using TRANSFER.
15481601 mlir::Value zero =
1549- fir:: genConstantIndex (loc, rewriter.getI64Type (), rewriter, 0 );
1602+ genConstantIndex (loc, rewriter.getI64Type (), rewriter, 0 );
15501603 descriptor = insertField (rewriter, loc, descriptor,
15511604 {getLenParamFieldId (boxTy), 0 }, zero);
15521605 }
@@ -1891,8 +1944,8 @@ struct XEmboxOpConversion : public EmboxCommonConversion<fir::cg::XEmboxOp> {
18911944 bool hasSlice = !xbox.getSlice ().empty ();
18921945 unsigned sliceOffset = xbox.getSliceOperandIndex ();
18931946 mlir::Location loc = xbox.getLoc ();
1894- mlir::Value zero = fir:: genConstantIndex (loc, i64Ty, rewriter, 0 );
1895- mlir::Value one = fir:: genConstantIndex (loc, i64Ty, rewriter, 1 );
1947+ mlir::Value zero = genConstantIndex (loc, i64Ty, rewriter, 0 );
1948+ mlir::Value one = genConstantIndex (loc, i64Ty, rewriter, 1 );
18961949 mlir::Value prevPtrOff = one;
18971950 mlir::Type eleTy = boxTy.getEleTy ();
18981951 const unsigned rank = xbox.getRank ();
@@ -1941,7 +1994,7 @@ struct XEmboxOpConversion : public EmboxCommonConversion<fir::cg::XEmboxOp> {
19411994 prevDimByteStride =
19421995 getCharacterByteSize (loc, rewriter, charTy, adaptor.getLenParams ());
19431996 } else {
1944- prevDimByteStride = fir:: genConstantIndex (
1997+ prevDimByteStride = genConstantIndex (
19451998 loc, i64Ty, rewriter,
19461999 charTy.getLen () * lowerTy ().characterBitsize (charTy) / 8 );
19472000 }
@@ -2099,7 +2152,7 @@ struct XReboxOpConversion : public EmboxCommonConversion<fir::cg::XReboxOp> {
20992152 if (auto charTy = mlir::dyn_cast<fir::CharacterType>(inputEleTy)) {
21002153 if (charTy.hasConstantLen ()) {
21012154 mlir::Value len =
2102- fir:: genConstantIndex (loc, idxTy, rewriter, charTy.getLen ());
2155+ genConstantIndex (loc, idxTy, rewriter, charTy.getLen ());
21032156 lenParams.emplace_back (len);
21042157 } else {
21052158 mlir::Value len = getElementSizeFromBox (loc, idxTy, inputBoxTyPair,
@@ -2108,7 +2161,7 @@ struct XReboxOpConversion : public EmboxCommonConversion<fir::cg::XReboxOp> {
21082161 assert (!isInGlobalOp (rewriter) &&
21092162 " character target in global op must have constant length" );
21102163 mlir::Value width =
2111- fir:: genConstantIndex (loc, idxTy, rewriter, charTy.getFKind ());
2164+ genConstantIndex (loc, idxTy, rewriter, charTy.getFKind ());
21122165 len = mlir::LLVM::SDivOp::create (rewriter, loc, idxTy, len, width);
21132166 }
21142167 lenParams.emplace_back (len);
@@ -2162,9 +2215,8 @@ struct XReboxOpConversion : public EmboxCommonConversion<fir::cg::XReboxOp> {
21622215 mlir::ConversionPatternRewriter &rewriter) const {
21632216 mlir::Location loc = rebox.getLoc ();
21642217 mlir::Value zero =
2165- fir::genConstantIndex (loc, lowerTy ().indexType (), rewriter, 0 );
2166- mlir::Value one =
2167- fir::genConstantIndex (loc, lowerTy ().indexType (), rewriter, 1 );
2218+ genConstantIndex (loc, lowerTy ().indexType (), rewriter, 0 );
2219+ mlir::Value one = genConstantIndex (loc, lowerTy ().indexType (), rewriter, 1 );
21682220 for (auto iter : llvm::enumerate (llvm::zip (extents, strides))) {
21692221 mlir::Value extent = std::get<0 >(iter.value ());
21702222 unsigned dim = iter.index ();
@@ -2197,7 +2249,7 @@ struct XReboxOpConversion : public EmboxCommonConversion<fir::cg::XReboxOp> {
21972249 mlir::Location loc = rebox.getLoc ();
21982250 mlir::Type byteTy = ::getI8Type (rebox.getContext ());
21992251 mlir::Type idxTy = lowerTy ().indexType ();
2200- mlir::Value zero = fir:: genConstantIndex (loc, idxTy, rewriter, 0 );
2252+ mlir::Value zero = genConstantIndex (loc, idxTy, rewriter, 0 );
22012253 // Apply subcomponent and substring shift on base address.
22022254 if (!rebox.getSubcomponent ().empty () || !rebox.getSubstr ().empty ()) {
22032255 // Cast to inputEleTy* so that a GEP can be used.
@@ -2225,7 +2277,7 @@ struct XReboxOpConversion : public EmboxCommonConversion<fir::cg::XReboxOp> {
22252277 // and strides.
22262278 llvm::SmallVector<mlir::Value> slicedExtents;
22272279 llvm::SmallVector<mlir::Value> slicedStrides;
2228- mlir::Value one = fir:: genConstantIndex (loc, idxTy, rewriter, 1 );
2280+ mlir::Value one = genConstantIndex (loc, idxTy, rewriter, 1 );
22292281 const bool sliceHasOrigins = !rebox.getShift ().empty ();
22302282 unsigned sliceOps = rebox.getSliceOperandIndex ();
22312283 unsigned shiftOps = rebox.getShiftOperandIndex ();
@@ -2298,7 +2350,7 @@ struct XReboxOpConversion : public EmboxCommonConversion<fir::cg::XReboxOp> {
22982350 // which may be OK if all new extents are ones, the stride does not
22992351 // matter, use one.
23002352 mlir::Value stride = inputStrides.empty ()
2301- ? fir:: genConstantIndex (loc, idxTy, rewriter, 1 )
2353+ ? genConstantIndex (loc, idxTy, rewriter, 1 )
23022354 : inputStrides[0 ];
23032355 for (unsigned i = 0 ; i < rebox.getShape ().size (); ++i) {
23042356 mlir::Value rawExtent = operands[rebox.getShapeOperandIndex () + i];
@@ -2533,9 +2585,9 @@ struct XArrayCoorOpConversion
25332585 unsigned shiftOffset = coor.getShiftOperandIndex ();
25342586 unsigned sliceOffset = coor.getSliceOperandIndex ();
25352587 auto sliceOps = coor.getSlice ().begin ();
2536- mlir::Value one = fir:: genConstantIndex (loc, idxTy, rewriter, 1 );
2588+ mlir::Value one = genConstantIndex (loc, idxTy, rewriter, 1 );
25372589 mlir::Value prevExt = one;
2538- mlir::Value offset = fir:: genConstantIndex (loc, idxTy, rewriter, 0 );
2590+ mlir::Value offset = genConstantIndex (loc, idxTy, rewriter, 0 );
25392591 const bool isShifted = !coor.getShift ().empty ();
25402592 const bool isSliced = !coor.getSlice ().empty ();
25412593 const bool baseIsBoxed =
@@ -2866,7 +2918,7 @@ struct CoordinateOpConversion
28662918 // of lower bound aspects. This both accounts for dynamically sized
28672919 // types and non contiguous arrays.
28682920 auto idxTy = lowerTy ().indexType ();
2869- mlir::Value off = fir:: genConstantIndex (loc, idxTy, rewriter, 0 );
2921+ mlir::Value off = genConstantIndex (loc, idxTy, rewriter, 0 );
28702922 unsigned arrayDim = arrTy.getDimension ();
28712923 for (unsigned dim = 0 ; dim < arrayDim && it != end; ++dim, ++it) {
28722924 mlir::Value stride =
@@ -3794,7 +3846,7 @@ struct IsPresentOpConversion : public fir::FIROpConversion<fir::IsPresentOp> {
37943846 ptr = mlir::LLVM::ExtractValueOp::create (rewriter, loc, ptr, 0 );
37953847 }
37963848 mlir::LLVM::ConstantOp c0 =
3797- fir:: genConstantIndex (isPresent.getLoc (), idxTy, rewriter, 0 );
3849+ genConstantIndex (isPresent.getLoc (), idxTy, rewriter, 0 );
37983850 auto addr = mlir::LLVM::PtrToIntOp::create (rewriter, loc, idxTy, ptr);
37993851 rewriter.replaceOpWithNewOp <mlir::LLVM::ICmpOp>(
38003852 isPresent, mlir::LLVM::ICmpPredicate::ne, addr, c0);
0 commit comments