summaryrefslogtreecommitdiff
path: root/flang/lib/Optimizer/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'flang/lib/Optimizer/CodeGen')
-rw-r--r--flang/lib/Optimizer/CodeGen/CodeGenOpenMP.cpp90
1 files changed, 88 insertions, 2 deletions
diff --git a/flang/lib/Optimizer/CodeGen/CodeGenOpenMP.cpp b/flang/lib/Optimizer/CodeGen/CodeGenOpenMP.cpp
index 97912bda79b0..381b2a29c517 100644
--- a/flang/lib/Optimizer/CodeGen/CodeGenOpenMP.cpp
+++ b/flang/lib/Optimizer/CodeGen/CodeGenOpenMP.cpp
@@ -60,6 +60,21 @@ struct MapInfoOpConversion
: public OpenMPFIROpConversion<mlir::omp::MapInfoOp> {
using OpenMPFIROpConversion::OpenMPFIROpConversion;
+ mlir::omp::MapBoundsOp
+ createBoundsForCharString(mlir::ConversionPatternRewriter &rewriter,
+ unsigned int len, mlir::Location loc) const {
+ mlir::Type i64Ty = rewriter.getIntegerType(64);
+ auto lBound = mlir::LLVM::ConstantOp::create(rewriter, loc, i64Ty, 0);
+ auto uBoundAndExt =
+ mlir::LLVM::ConstantOp::create(rewriter, loc, i64Ty, len - 1);
+ auto stride = mlir::LLVM::ConstantOp::create(rewriter, loc, i64Ty, 1);
+ auto baseLb = mlir::LLVM::ConstantOp::create(rewriter, loc, i64Ty, 1);
+ auto mapBoundType = rewriter.getType<mlir::omp::MapBoundsType>();
+ return mlir::omp::MapBoundsOp::create(rewriter, loc, mapBoundType, lBound,
+ uBoundAndExt, uBoundAndExt, stride,
+ /*strideInBytes*/ false, baseLb);
+ }
+
llvm::LogicalResult
matchAndRewrite(mlir::omp::MapInfoOp curOp, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const override {
@@ -69,13 +84,79 @@ struct MapInfoOpConversion
return mlir::failure();
llvm::SmallVector<mlir::NamedAttribute> newAttrs;
- mlir::omp::MapInfoOp newOp;
+ mlir::omp::MapBoundsOp mapBoundsOp;
for (mlir::NamedAttribute attr : curOp->getAttrs()) {
if (auto typeAttr = mlir::dyn_cast<mlir::TypeAttr>(attr.getValue())) {
mlir::Type newAttr;
if (fir::isTypeWithDescriptor(typeAttr.getValue())) {
newAttr = lowerTy().convertBoxTypeAsStruct(
mlir::cast<fir::BaseBoxType>(typeAttr.getValue()));
+ } else if (fir::isa_char_string(fir::unwrapSequenceType(
+ fir::unwrapPassByRefType(typeAttr.getValue()))) &&
+ !characterWithDynamicLen(
+ fir::unwrapPassByRefType(typeAttr.getValue()))) {
+ // Characters with a LEN param are represented as strings
+ // (array of characters), the lowering to LLVM dialect
+ // doesn't generate bounds for these (and this is not
+ // done at the initial lowering either) and there is
+ // minor inconsistencies in the variable types we
+ // create for the map without this step when converting
+ // to the LLVM dialect.
+ //
+ // For example, given the types:
+ //
+ // 1) CHARACTER(LEN=16), dimension(:,:), allocatable :: char_arr
+ // 2) CHARACTER(LEN=16), dimension(10,10) :: char_arr
+ //
+ // We get the FIR types (note for 1: we already peeled off the
+ // dynamic extents from the type at this stage, but the conversion
+ // to llvm dialect does that in any case, so the final result
+ // is the same):
+ //
+ // 1) !fir.char<1,16>
+ // 2) !fir.array<10x10x!fir.char<1,16>>
+ //
+ // Which are converted to the LLVM dialect types:
+ //
+ // 1) !llvm.array<16 x i8>
+ // 2) llvm.array<10 x array<10 x array<16 x i8>>
+ //
+ // And in both cases, we are missing the innermost bounds for
+ // the !fir.char<1,16> which is expanded into a 16 x i8 array
+ // in the conversion to LLVM dialect.
+ //
+ // The problem with this is that we would like to treat these
+ // cases identically and not have to create specialised
+ // lowerings for either of these in the lowering to LLVM-IR
+ // and treat them like any other array that passes through.
+ //
+ // To do so below, we generate an extra bound for the
+ // innermost array (the char type/string) using the LEN
+ // parameter of the character type. And we "canonicalize"
+ // the type, stripping it down to the base element type,
+ // which in this case is an i8. This effectively allows
+ // the lowering to treat this as a 1-D array with multiple
+ // bounds which it is capable of handling without any special
+ // casing.
+ // TODO: Handle dynamic LEN characters.
+ if (auto ct = mlir::dyn_cast_or_null<fir::CharacterType>(
+ fir::unwrapSequenceType(typeAttr.getValue()))) {
+ newAttr = converter->convertType(
+ fir::unwrapSequenceType(typeAttr.getValue()));
+ if (auto type = mlir::dyn_cast<mlir::LLVM::LLVMArrayType>(newAttr))
+ newAttr = type.getElementType();
+ // We do not generate MapBoundsOps for the device pass, as
+ // MapBoundsOps are not generated for the device pass, as
+ // they're unused in the device lowering.
+ auto offloadMod =
+ llvm::dyn_cast_or_null<mlir::omp::OffloadModuleInterface>(
+ *curOp->getParentOfType<mlir::ModuleOp>());
+ if (!offloadMod.getIsTargetDevice())
+ mapBoundsOp = createBoundsForCharString(rewriter, ct.getLen(),
+ curOp.getLoc());
+ } else {
+ newAttr = converter->convertType(typeAttr.getValue());
+ }
} else {
newAttr = converter->convertType(typeAttr.getValue());
}
@@ -85,8 +166,13 @@ struct MapInfoOpConversion
}
}
- rewriter.replaceOpWithNewOp<mlir::omp::MapInfoOp>(
+ auto newOp = rewriter.replaceOpWithNewOp<mlir::omp::MapInfoOp>(
curOp, resTypes, adaptor.getOperands(), newAttrs);
+ if (mapBoundsOp) {
+ rewriter.startOpModification(newOp);
+ newOp.getBoundsMutable().append(mlir::ValueRange{mapBoundsOp});
+ rewriter.finalizeOpModification(newOp);
+ }
return mlir::success();
}