[Openmp-commits] [openmp] [Flang][OpenMP][MLIR] Initial array section mapping MLIR -> LLVM-IR lowering utilising omp.bounds (PR #68689)
Kiran Chandramohan via Openmp-commits
openmp-commits at lists.llvm.org
Fri Oct 27 09:07:59 PDT 2023
================
@@ -1642,13 +1635,154 @@ getRefPtrIfDeclareTarget(mlir::Value value,
return nullptr;
}
+// A small helper structure to contain data gathered
+// for map lowering and coalese it into one area and
+// avoiding extra computations such as searches in the
+// llvm module for lowered mapped varibles or checking
+// if something is declare target (and retrieving the
+// value) more than neccessary.
+struct MapInfoData : llvm::OpenMPIRBuilder::MapInfosTy {
+ llvm::SmallVector<bool, 4> IsDeclareTarget;
+ llvm::SmallVector<mlir::Operation *, 4> MapClause;
+ llvm::SmallVector<llvm::Value *, 4> OriginalValue;
+ // Stripped off array/pointer to get the underlying
+ // element type
+ llvm::SmallVector<llvm::Type *, 4> BaseType;
+
+ /// Append arrays in \a CurInfo.
+ void append(MapInfoData &CurInfo) {
+ IsDeclareTarget.append(CurInfo.IsDeclareTarget.begin(),
+ CurInfo.IsDeclareTarget.end());
+ MapClause.append(CurInfo.MapClause.begin(), CurInfo.MapClause.end());
+ OriginalValue.append(CurInfo.OriginalValue.begin(),
+ CurInfo.OriginalValue.end());
+ BaseType.append(CurInfo.BaseType.begin(), CurInfo.BaseType.end());
+ llvm::OpenMPIRBuilder::MapInfosTy::append(CurInfo);
+ }
+};
+
+uint64_t getArrayElementSizeInBits(LLVM::LLVMArrayType arrTy, DataLayout &dl) {
+ if (auto nestedArrTy = llvm::dyn_cast_if_present<LLVM::LLVMArrayType>(
+ arrTy.getElementType()))
+ return getArrayElementSizeInBits(nestedArrTy, dl);
+ return dl.getTypeSizeInBits(arrTy.getElementType());
+}
+
+// This function calculates the size to be offloaded for a specified type, given
+// its associated map clause (which can contain bounds information which affects
+// the total size), this size is calculated based on the underlying element type
+// e.g. given a 1-D array of ints, we will calculate the size from the integer
+// type * number of elements in the array. This size can be used in other
+// calculations but is ultimately used as an argument to the OpenMP runtimes
+// kernel argument structure which is generated through the combinedInfo data
+// structures.
+// This function is somewhat equivalent to Clang's getExprTypeSize inside of
+// CGOpenMPRuntime.cpp.
+llvm::Value *getSizeInBytes(DataLayout &dl, const mlir::Type &type,
+ Operation *clauseOp, llvm::IRBuilderBase &builder,
+ LLVM::ModuleTranslation &moduleTranslation) {
+ // utilising getTypeSizeInBits instead of getTypeSize as getTypeSize gives
+ // the size in inconsistent byte or bit format.
+ uint64_t underlyingTypeSzInBits = dl.getTypeSizeInBits(type);
+ if (auto arrTy = llvm::dyn_cast_if_present<LLVM::LLVMArrayType>(type)) {
+ underlyingTypeSzInBits = getArrayElementSizeInBits(arrTy, dl);
+ }
+
+ if (auto memberClause =
+ mlir::dyn_cast_if_present<mlir::omp::MapInfoOp>(clauseOp)) {
+ // This calculates the size to transfer based on bounds and the underlying
+ // element type, provided bounds have been specified (Fortran
+ // pointers/allocatables/target and arrays that have sections specified fall
+ // into this as well).
+ if (!memberClause.getBounds().empty()) {
+ llvm::Value *elementCount = builder.getInt64(1);
+ for (auto bounds : memberClause.getBounds()) {
+ if (auto boundOp = mlir::dyn_cast_if_present<mlir::omp::DataBoundsOp>(
+ bounds.getDefiningOp())) {
+ // The below calculation for the size to be mapped calculated from the
+ // map_info's bounds is: (elemCount * [UB - LB] + 1), later we
+ // multiply by the underlying element types byte size to get the full
+ // size to be offloaded based on the bounds
+ elementCount = builder.CreateMul(
+ elementCount,
+ builder.CreateAdd(
+ builder.CreateSub(
+ moduleTranslation.lookupValue(boundOp.getUpperBound()),
+ moduleTranslation.lookupValue(boundOp.getLowerBound())),
+ builder.getInt64(1)));
+ }
+ }
+
+ // The size in bytes x number of elements, the sizeInBytes stored is
+ // the underyling types size, e.g. if ptr<i32>, it'll be the i32's
+ // size, so we do some on the fly runtime math to get the size in
+ // bytes from the extent (ub - lb) * sizeInBytes. NOTE: This may need
+ // some adjustment for members with more complex types.
+ return builder.CreateMul(elementCount,
+ builder.getInt64(underlyingTypeSzInBits / 8));
+ }
+ }
+
+ return builder.getInt64(underlyingTypeSzInBits / 8);
+}
+
+// Get the underlying LLVM type, this will bypass the pointer and
+// access the underlying type. Which bypasses llvm's opaque pointers
+// to get the underlying type via MLIR.
+llvm::Type *getLLVMIRType(mlir::Type inputType,
+ LLVM::ModuleTranslation &moduleTranslation) {
+ llvm::Type *type = moduleTranslation.convertType(inputType);
+ if (auto pointerType =
+ llvm::dyn_cast<mlir::omp::PointerLikeType>(inputType)) {
+ if (auto eleType = pointerType.getElementType()) {
+ type = moduleTranslation.convertType(eleType);
+ }
+ }
+ return type;
+}
+
+void collectMapDataFromMapOperands(MapInfoData &mapData,
+ llvm::SmallVectorImpl<Value> &mapOperands,
+ LLVM::ModuleTranslation &moduleTranslation,
+ DataLayout &dl,
+ llvm::IRBuilderBase &builder) {
+ for (mlir::Value mapValue : mapOperands) {
+ if (auto mapOp = mlir::dyn_cast_if_present<mlir::omp::MapInfoOp>(
----------------
kiranchandramohan wrote:
Should all `mapOperands` be `MapInfoOp`s now? If so, this should be an assertion followed by a cast.
https://github.com/llvm/llvm-project/pull/68689
More information about the Openmp-commits
mailing list