diff options
Diffstat (limited to 'flang/lib/Optimizer/CodeGen/CodeGenOpenMP.cpp')
| -rw-r--r-- | flang/lib/Optimizer/CodeGen/CodeGenOpenMP.cpp | 90 |
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(); } |
