[flang-commits] [flang] [mlir] [Flang][OpenMP] Fix OpenMP data-mapping stride calculation (PR #225653)

via flang-commits flang-commits at lists.llvm.org
Wed Sep 23 02:19:19 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mlir-openmp

Author: Michael Klemm (mjklemm)

<details>
<summary>Changes</summary>

The calculation of strides when mapping individual sub-arrays from multi-dimensional array, the calcuation of the stride was missing such that when mapping all of the multi-dim array only a fraction was actually mapped.

---
Full diff: https://github.com/llvm/llvm-project/pull/225653.diff


5 Files Affected:

- (modified) flang/test/Integration/OpenMP/map-types-and-sizes.f90 (+14-10) 
- (modified) mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp (+69-29) 
- (added) mlir/test/Target/LLVMIR/omptarget-array-section-single-element-host.mlir (+40) 
- (modified) mlir/test/Target/LLVMIR/omptarget-nested-ptr-record-type-mapping-host.mlir (+1-1) 
- (modified) mlir/test/Target/LLVMIR/omptarget-record-type-with-ptr-member-host.mlir (+6-2) 


``````````diff
diff --git a/flang/test/Integration/OpenMP/map-types-and-sizes.f90 b/flang/test/Integration/OpenMP/map-types-and-sizes.f90
index 1a86c7186a1f5..242ac1cfa72de 100644
--- a/flang/test/Integration/OpenMP/map-types-and-sizes.f90
+++ b/flang/test/Integration/OpenMP/map-types-and-sizes.f90
@@ -560,10 +560,14 @@ end subroutine mapType_common_block_members
 !CHECK: %[[RESTORE_OFFSET:.*]] = add i64 %[[CALCULATE_DIM_SIZE]], 1
 !CHECK: %[[MEMBER_BASE_ADDR_SIZE:.*]] = mul i64 1, %[[RESTORE_OFFSET]]
 !CHECK: %[[DESC_BASE_ADDR_DATA_SIZE:.*]] = mul i64 %[[MEMBER_BASE_ADDR_SIZE]], 4
+!CHECK: %[[ADDR_DATA_OFF1:.*]] = mul i64 0, %{{.*}}
+!CHECK: %[[ADDR_DATA_OFF:.*]] = add i64 0, %[[ADDR_DATA_OFF1]]
 !CHECK: %[[LOAD_ADDR_DATA:.*]] = load ptr, ptr %[[MEMBER_DESCRIPTOR_BASE_ADDR]], align 8
-!CHECK: %[[GEP_ADDR_DATA:.*]] = getelementptr inbounds i32, ptr %[[LOAD_ADDR_DATA]], i64 0
+!CHECK: %[[GEP_ADDR_DATA:.*]] = getelementptr inbounds i8, ptr %[[LOAD_ADDR_DATA]], i64 %[[ADDR_DATA_OFF]]
+!CHECK: %[[ADDR_DATA2_OFF1:.*]] = mul i64 0, %{{.*}}
+!CHECK: %[[ADDR_DATA2_OFF:.*]] = add i64 0, %[[ADDR_DATA2_OFF1]]
 !CHECK: %[[LOAD_ADDR_DATA2:.*]] = load ptr, ptr %[[MEMBER_DESCRIPTOR_BASE_ADDR]], align 8
-!CHECK: %[[GEP_ADDR_DATA2:.*]] = getelementptr inbounds i32, ptr %[[LOAD_ADDR_DATA2]], i64 0
+!CHECK: %[[GEP_ADDR_DATA2:.*]] = getelementptr inbounds i8, ptr %[[LOAD_ADDR_DATA2]], i64 %[[ADDR_DATA2_OFF]]
 !CHECK: %[[MEMBER_ACCESS_ADDR_END:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %[[MEMBER_ACCESS]], i64 1
 !CHECK: %[[MEMBER_ACCESS_ADDR_INT:.*]] = ptrtoaddr ptr %[[MEMBER_ACCESS_ADDR_END]] to i64
 !CHECK: %[[MEMBER_ACCESS_ADDR_BEGIN:.*]] = ptrtoaddr ptr %[[MEMBER_ACCESS]] to i64
@@ -620,7 +624,7 @@ end subroutine mapType_common_block_members
 !CHECK: %[[DTYPE_BASE_ADDR_LOAD_3:.*]] = load ptr, ptr %[[DTYPE_BASE_ADDR_ACCESS_3]], align 8
 !CHECK: %[[DTYPE_BASE_ADDR_LOAD_3_1:.*]] = load ptr, ptr %[[DTYPE_BASE_ADDR_ACCESS_3]], align 8
 !CHECK: %[[LOAD_DTYPE_DESC_MEMBER:.*]] = load ptr, ptr %[[DTYPE_ALLOCA_MEMBER_BASE_ADDR_ACCESS]], align 8
-!CHECK: %[[MEMBER_ARRAY_OFFSET:.*]] = getelementptr inbounds i32, ptr %[[LOAD_DTYPE_DESC_MEMBER]], i64 0
+!CHECK: %[[MEMBER_ARRAY_OFFSET:.*]] = getelementptr inbounds i8, ptr %[[LOAD_DTYPE_DESC_MEMBER]], i64 %{{.*}}
 !CHECK: %[[SIZE_CALC_1:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr %[[DTYPE_DESC_ALLOCA_3]], i32 1
 !CHECK: %[[SIZE_CALC_2:.*]] = ptrtoaddr ptr %[[SIZE_CALC_1]] to i64
 !CHECK: %[[SIZE_CALC_3:.*]] = ptrtoaddr ptr %[[DTYPE_DESC_ALLOCA_3]] to i64
@@ -670,7 +674,7 @@ end subroutine mapType_common_block_members
 !CHECK: %[[LOAD_BASE_ADDR:.*]] = load ptr, ptr %[[DTYPE_DESC_BASE_ADDR]], align 8
 !CHECK: %[[LOAD_BASE_ADDR2:.*]] = load ptr, ptr %[[DTYPE_DESC_BASE_ADDR]], align 8
 !CHECK: %[[LOAD_DESC_MEMBER_BASE_ADDR:.*]] = load ptr, ptr %[[MAPPED_MEMBER_BASE_ADDR_ACCESS]], align 8
-!CHECK: %[[ARRAY_OFFSET:.*]] = getelementptr inbounds i32, ptr %[[LOAD_DESC_MEMBER_BASE_ADDR]], i64 0
+!CHECK: %[[ARRAY_OFFSET:.*]] = getelementptr inbounds i8, ptr %[[LOAD_DESC_MEMBER_BASE_ADDR]], i64 %{{.*}}
 !CHECK: %[[NULL_CMP:.*]] = icmp eq ptr %[[LOAD_BASE_ADDR2]], null
 !CHECK: %[[SEL_SZ:.*]] = select i1 %[[NULL_CMP]], i64 0, i64 240
 !CHECK: %[[NULL_CMP2:.*]] = icmp eq ptr %[[ARRAY_OFFSET]], null
@@ -707,9 +711,9 @@ end subroutine mapType_common_block_members
 !CHECK: %[[SIZE_ZERO_CMP:.*]] = icmp eq i64 %[[ALLOCATABLE_MEMBER_SIZE_CALC_5]], 0
 !CHECK: %[[SIZE_ADJUSTED:.*]] = select i1 %[[SIZE_ZERO_CMP]], i64 1, i64 %[[ALLOCATABLE_MEMBER_SIZE_CALC_5]]
 !CHECK: %[[LOAD_BASE_ADDR:.*]] = load ptr, ptr %[[NESTED_MEMBER_BASE_ADDR_ACCESS]], align 8
-!CHECK: %[[ARR_OFFS:.*]] = getelementptr inbounds i32, ptr %[[LOAD_BASE_ADDR]], i64 0
+!CHECK: %[[ARR_OFFS:.*]] = getelementptr inbounds i8, ptr %[[LOAD_BASE_ADDR]], i64 %{{.*}}
 !CHECK: %[[LOAD_BASE_ADDR:.*]] = load ptr, ptr %[[NESTED_MEMBER_BASE_ADDR_ACCESS]], align 8
-!CHECK: %[[ARR_OFFS2:.*]] = getelementptr inbounds i32, ptr %[[LOAD_BASE_ADDR]], i64 0
+!CHECK: %[[ARR_OFFS2:.*]] = getelementptr inbounds i8, ptr %[[LOAD_BASE_ADDR]], i64 %{{.*}}
 !CHECK: %[[NESTED_MEMBER_BASE_ADDR_ACCESS_2:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %[[NESTED_MEMBER_ACCESS]], i64 1
 !CHECK: %[[DTYPE_SEGMENT_SIZE_CALC_1:.*]] = ptrtoaddr ptr %[[NESTED_MEMBER_BASE_ADDR_ACCESS_2]] to i64
 !CHECK: %[[DTYPE_SEGMENT_SIZE_CALC_2:.*]] = ptrtoaddr ptr %[[NESTED_MEMBER_ACCESS]] to i64
@@ -777,13 +781,13 @@ end subroutine mapType_common_block_members
 !CHECK: %[[SIZE_ZERO_CMP_2:.*]] = icmp eq i64 %[[SZ_CALC_4_2]], 0
 !CHECK: %[[SIZE_ADJUSTED_2:.*]] = select i1 %[[SIZE_ZERO_CMP_2]], i64 1, i64 %[[SZ_CALC_4_2]]
 !CHECK: %[[LOAD_OFF_PTR:.*]] = load ptr, ptr %[[OFF_PTR_2]], align 8
-!CHECK: %[[ARR_OFFS:.*]] = getelementptr inbounds %_QFmaptype_nested_derived_type_member_idxTvertexes, ptr %[[LOAD_OFF_PTR]], i64 0
+!CHECK: %[[ARR_OFFS:.*]] = getelementptr inbounds i8, ptr %[[LOAD_OFF_PTR]], i64 %{{.*}}
 !CHECK: %[[LOAD_ARR_OFFS:.*]] = load ptr, ptr %[[OFF_PTR_4]], align 8
-!CHECK: %[[ARR_OFFS_1:.*]] = getelementptr inbounds i32, ptr %[[LOAD_ARR_OFFS]], i64 0
+!CHECK: %[[ARR_OFFS_1:.*]] = getelementptr inbounds i8, ptr %[[LOAD_ARR_OFFS]], i64 %{{.*}}
 !CHECK: %[[LOAD_OFF_PTR:.*]] = load ptr, ptr %[[OFF_PTR_2]], align 8
-!CHECK: %[[ARR_OFFS_2:.*]] = getelementptr inbounds %_QFmaptype_nested_derived_type_member_idxTvertexes, ptr %[[LOAD_OFF_PTR]], i64 0
+!CHECK: %[[ARR_OFFS_2:.*]] = getelementptr inbounds i8, ptr %[[LOAD_OFF_PTR]], i64 %{{.*}}
 !CHECK: %[[LOAD_ARR_OFFS:.*]] = load ptr, ptr %[[OFF_PTR_4]], align 8
-!CHECK: %[[ARR_OFFS_3:.*]] = getelementptr inbounds i32, ptr %[[LOAD_ARR_OFFS]], i64 0
+!CHECK: %[[ARR_OFFS_3:.*]] = getelementptr inbounds i8, ptr %[[LOAD_ARR_OFFS]], i64 %{{.*}}
 !CHECK: %[[SZ_CALC_1:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }, ptr %[[OFF_PTR_1]], i64 1
 !CHECK: %[[SZ_CALC_2:.*]] = ptrtoaddr ptr %[[SZ_CALC_1]] to i64
 !CHECK: %[[SZ_CALC_3:.*]] = ptrtoaddr ptr %[[OFF_PTR_1]] to i64
diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
index e5e3e0cc6d944..bc1c768d891dc 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
@@ -7643,8 +7643,9 @@ static omp::MapInfoOp getFirstOrLastMappedMemberPtr(omp::MapInfoOp mapInfo,
 static std::vector<llvm::Value *>
 calculateBoundsOffset(LLVM::ModuleTranslation &moduleTranslation,
                       llvm::IRBuilderBase &builder, bool isArrayTy,
-                      OperandRange bounds) {
+                      OperandRange bounds, bool &isByteOffset) {
   std::vector<llvm::Value *> idx;
+  isByteOffset = false;
   // There's no bounds to calculate an offset from, we can safely
   // ignore and return no indices.
   if (bounds.empty())
@@ -7663,31 +7664,68 @@ calculateBoundsOffset(LLVM::ModuleTranslation &moduleTranslation,
       }
     }
   } else {
-    // If we do not have an array type, but we have bounds, then we're dealing
-    // with a pointer that's being treated like an array and we have the
-    // underlying type e.g. an i32, or f64 etc, e.g. a fortran descriptor base
-    // address (pointer pointing to the actual data) so we must caclulate the
-    // offset using a single index which the following loop attempts to
-    // compute using the standard column-major algorithm e.g for a 3D array:
-    //
-    // ((((c_idx * b_len) + b_idx) * a_len) + a_idx)
-    //
-    // It is of note that it's doing column-major rather than row-major at the
-    // moment, but having a way for the frontend to indicate which major format
-    // to use or standardizing/canonicalizing the order of the bounds to compute
-    // the offset may be useful in the future when there's other frontends with
-    // different formats.
-    for (int i = bounds.size() - 1; i >= 0; --i) {
-      if (auto boundOp = dyn_cast_if_present<omp::MapBoundsOp>(
-              bounds[i].getDefiningOp())) {
-        if (i == ((int)bounds.size() - 1))
-          idx.emplace_back(
-              moduleTranslation.lookupValue(boundOp.getLowerBound()));
-        else
-          idx.back() = builder.CreateAdd(
-              builder.CreateMul(idx.back(), moduleTranslation.lookupValue(
-                                                boundOp.getExtent())),
-              moduleTranslation.lookupValue(boundOp.getLowerBound()));
+    // Check if Fortran descriptors provide strides in bytes
+    llvm::Value *offset = builder.getInt64(0);
+    for (Value bound : bounds) {
+      auto boundOp =
+          dyn_cast_if_present<omp::MapBoundsOp>(bound.getDefiningOp());
+      if (!boundOp || !boundOp.getStride())
+        continue;
+      // Fortran descriptors provide strides in bytes; when that's the case the
+      // accumulated offset is a byte offset and must be consumed with a byte
+      // (i8) GEP at the call site to avoid double-scaling by the element size.
+      isByteOffset = boundOp.getStrideInBytes();
+    }
+    if (isByteOffset) {
+      for (Value bound : bounds) {
+        auto boundOp =
+            dyn_cast_if_present<omp::MapBoundsOp>(bound.getDefiningOp());
+        if (!boundOp || !boundOp.getStride())
+          continue;
+        // If we do not have an array type, but we have bounds, then we're
+        // dealing with a pointer that's being treated like an array
+        // and we have the underlying type e.g. an i32, or f64 etc,
+        // e.g. a fortran descriptor base address (pointer pointing to
+        // the actual data) and we know that the offset stride is expressed
+        // in bytes, so we must calculate the offset to the first mapped
+        // element as a single linear index into that data.
+        //
+        // Each bound carries the stride between consecutive elements along its
+        // dimension, so the linear offset to the section's origin is:
+        //
+        //   offset += lower_bound[d] * stride[d]
+        llvm::Value *lb =
+            moduleTranslation.lookupValue(boundOp.getLowerBound());
+        llvm::Value *stride =
+            moduleTranslation.lookupValue(boundOp.getStride());
+        offset = builder.CreateAdd(offset, builder.CreateMul(lb, stride));
+      }
+      idx.push_back(offset);
+    } else {
+      for (int i = bounds.size() - 1; i >= 0; --i) {
+        if (auto boundOp = dyn_cast_if_present<omp::MapBoundsOp>(
+                bounds[i].getDefiningOp())) {
+          // If the stride in bytes is unknown, so we must calculate the
+          // offset using a single index which the following loop attempts to
+          // compute using the standard column-major algorithm e.g for a 3D
+          // array:
+          //
+          // ((((c_idx * b_len) + b_idx) * a_len) + a_idx)
+          //
+          // It is of note that it's doing column-major rather than row-major at
+          // the moment, but having a way for the frontend to indicate which
+          // major format to use or standardizing/canonicalizing the order of
+          // the bounds to compute the offset may be useful in the future when
+          // there's other frontends with different formats.
+          if (i == ((int)bounds.size() - 1))
+            idx.emplace_back(
+                moduleTranslation.lookupValue(boundOp.getLowerBound()));
+          else
+            idx.back() = builder.CreateAdd(
+                builder.CreateMul(idx.back(), moduleTranslation.lookupValue(
+                                                  boundOp.getExtent())),
+                moduleTranslation.lookupValue(boundOp.getLowerBound()));
+        }
       }
     }
   }
@@ -8222,15 +8260,17 @@ createAlteredByCaptureMap(MapInfoData &mapData,
       switch (captureKind) {
       case omp::VariableCaptureKind::ByRef: {
         llvm::Value *newV = mapData.Pointers[i];
+        bool isByteOffset = false;
         std::vector<llvm::Value *> offsetIdx = calculateBoundsOffset(
             moduleTranslation, builder, mapData.BaseType[i]->isArrayTy(),
-            mapOp.getBounds());
+            mapOp.getBounds(), isByteOffset);
         if (isPtrTy)
           newV = builder.CreateLoad(builder.getPtrTy(), newV);
 
         if (!offsetIdx.empty())
-          newV = builder.CreateInBoundsGEP(mapData.BaseType[i], newV, offsetIdx,
-                                           "array_offset");
+          newV = builder.CreateInBoundsGEP(isByteOffset ? builder.getInt8Ty()
+                                                        : mapData.BaseType[i],
+                                           newV, offsetIdx, "array_offset");
         mapData.Pointers[i] = newV;
       } break;
       case omp::VariableCaptureKind::ByCopy: {
diff --git a/mlir/test/Target/LLVMIR/omptarget-array-section-single-element-host.mlir b/mlir/test/Target/LLVMIR/omptarget-array-section-single-element-host.mlir
new file mode 100644
index 0000000000000..4bb188c846480
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/omptarget-array-section-single-element-host.mlir
@@ -0,0 +1,40 @@
+// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
+
+// This test checks that the begin-pointer offset for a map of a single element
+// of a multi-dimensional Fortran array (accessed through a descriptor, so the
+// map has a non-array base type and carries per-dimension bounds) is linearized
+// using the per-dimension strides carried on the omp.map.bounds operations,
+// rather than the section extents. For a single-element section all extents are
+// 1, so an extent-based fold would collapse every element onto the same begin
+// pointer. The offset must instead be:
+//
+//   sum_d lower_bound[d] * stride[d]
+//
+// Here the strides are provided in bytes (stride_in_bytes(true)) with distinct
+// values 8 and 256, so the offset is lb0*8 + lb1*256 applied through a byte
+// (i8) GEP.
+
+module attributes {omp.is_target_device = false, omp.target_triples = ["amdgcn-amd-amdhsa"]} {
+  llvm.func @single_element_2d_map(%arg0: !llvm.ptr, %lb0: i64, %lb1: i64) {
+    %c1 = llvm.mlir.constant(1 : i64) : i64
+    %stride0 = llvm.mlir.constant(8 : i64) : i64
+    %stride1 = llvm.mlir.constant(256 : i64) : i64
+    %baddr = llvm.getelementptr %arg0[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<2 x array<3 x i64>>)>
+    %b0 = omp.map.bounds lower_bound(%lb0 : i64) upper_bound(%lb0 : i64) extent(%c1 : i64) stride(%stride0 : i64) start_idx(%c1 : i64) stride_in_bytes(true)
+    %b1 = omp.map.bounds lower_bound(%lb1 : i64) upper_bound(%lb1 : i64) extent(%c1 : i64) stride(%stride1 : i64) start_idx(%c1 : i64) stride_in_bytes(true)
+    %m0 = omp.map.info var_ptr(%arg0 : !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<2 x array<3 x i64>>)>) map_clauses(tofrom) capture(ByRef) var_ptr_ptr(%baddr : !llvm.ptr, f64) bounds(%b0, %b1) name("arr(i,j)") -> !llvm.ptr
+    %m1 = omp.map.info var_ptr(%arg0 : !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<2 x array<3 x i64>>)>) map_clauses(tofrom) capture(ByRef) members(%m0 : [0] : !llvm.ptr) name("arr(i,j)") -> !llvm.ptr
+    omp.target kernel_type(generic) map_entries(%m0 -> %a0, %m1 -> %a1 : !llvm.ptr, !llvm.ptr) {
+      omp.terminator
+    }
+    llvm.return
+  }
+}
+
+// CHECK: define void @single_element_2d_map(ptr %[[ARG0:.*]], i64 %[[LB0:.*]], i64 %[[LB1:.*]])
+// CHECK: %[[T0:.*]] = mul i64 %[[LB0]], 8
+// CHECK: %[[OFF0:.*]] = add i64 0, %[[T0]]
+// CHECK: %[[T1:.*]] = mul i64 %[[LB1]], 256
+// CHECK: %[[OFF:.*]] = add i64 %[[OFF0]], %[[T1]]
+// CHECK: %[[BASE:.*]] = load ptr, ptr %{{.*}}, align 8
+// CHECK: %[[ARR_OFFSET:.*]] = getelementptr inbounds i8, ptr %[[BASE]], i64 %[[OFF]]
\ No newline at end of file
diff --git a/mlir/test/Target/LLVMIR/omptarget-nested-ptr-record-type-mapping-host.mlir b/mlir/test/Target/LLVMIR/omptarget-nested-ptr-record-type-mapping-host.mlir
index 82ed7872e29b0..3552f9226453a 100644
--- a/mlir/test/Target/LLVMIR/omptarget-nested-ptr-record-type-mapping-host.mlir
+++ b/mlir/test/Target/LLVMIR/omptarget-nested-ptr-record-type-mapping-host.mlir
@@ -36,7 +36,7 @@ module attributes {omp.is_target_device = false, omp.target_triples = ["amdgcn-a
 // CHECK: %[[NESTED_STRUCT_PTR_MEMBER_GEP:.*]] = getelementptr { float, [10 x i32], { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, i32 }, ptr %[[NESTED_DTYPE_MEMBER_GEP]], i32 0, i32 2
 // CHECK: %[[NESTED_STRUCT_PTR_MEMBER_BADDR_GEP:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %[[NESTED_STRUCT_PTR_MEMBER_GEP]], i32 0, i32 0
 // CHECK: %[[NESTED_STRUCT_PTR_MEMBER_BADDR_LOAD:.*]] = load ptr, ptr %[[NESTED_STRUCT_PTR_MEMBER_BADDR_GEP]], align 8
-// CHECK: %[[ARR_OFFSET:.*]] = getelementptr inbounds i32, ptr %[[NESTED_STRUCT_PTR_MEMBER_BADDR_LOAD]], i64 0
+// CHECK: %[[ARR_OFFSET:.*]] = getelementptr inbounds i8, ptr %[[NESTED_STRUCT_PTR_MEMBER_BADDR_LOAD]], i64 0
 // CHECK: %[[DTYPE_SIZE_SEGMENT_CALC_1:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %[[NESTED_STRUCT_PTR_MEMBER_GEP]], i64 1
 // CHECK: %[[DTYPE_SIZE_SEGMENT_CALC_2:.*]] = ptrtoaddr ptr %[[DTYPE_SIZE_SEGMENT_CALC_1]] to i64
 // CHECK: %[[DTYPE_SIZE_SEGMENT_CALC_3:.*]] = ptrtoaddr ptr %[[NESTED_STRUCT_PTR_MEMBER_GEP]] to i64
diff --git a/mlir/test/Target/LLVMIR/omptarget-record-type-with-ptr-member-host.mlir b/mlir/test/Target/LLVMIR/omptarget-record-type-with-ptr-member-host.mlir
index c338761da3989..059715cd1c37d 100644
--- a/mlir/test/Target/LLVMIR/omptarget-record-type-with-ptr-member-host.mlir
+++ b/mlir/test/Target/LLVMIR/omptarget-record-type-with-ptr-member-host.mlir
@@ -81,10 +81,14 @@ module attributes {omp.is_target_device = false, omp.target_triples = ["amdgcn-a
 // CHECK: %[[ARR_SECT_SIZE:.*]] = mul i64 %[[ARR_SECT_SIZE1]], 4
 // CHECK: %[[ARR_SECT_SIZE_ZERO_CMP:.*]] = icmp eq i64 %[[ARR_SECT_SIZE]], 0
 // CHECK: %[[ARR_SECT_SIZE_ADJUSTED:.*]] = select i1 %[[ARR_SECT_SIZE_ZERO_CMP]], i64 1, i64 %[[ARR_SECT_SIZE]]
+// CHECK: %[[FULL_ARR_OFFSET1:.*]] = mul i64 0, %{{.*}}
+// CHECK: %[[FULL_ARR_OFFSET:.*]] = add i64 0, %[[FULL_ARR_OFFSET1]]
 // CHECK: %[[LFULL_ARR:.*]] = load ptr, ptr @full_arr, align 8
-// CHECK: %[[FULL_ARR_PTR:.*]] = getelementptr inbounds float, ptr %[[LFULL_ARR]], i64 0
+// CHECK: %[[FULL_ARR_PTR:.*]] = getelementptr inbounds i8, ptr %[[LFULL_ARR]], i64 %[[FULL_ARR_OFFSET]]
+// CHECK: %[[ARR_SECT_OFFSET1:.*]] = mul i64 %[[ARR_SECT_OFFSET2]], %{{.*}}
+// CHECK: %[[ARR_SECT_OFFSET:.*]] = add i64 0, %[[ARR_SECT_OFFSET1]]
 // CHECK: %[[LARR_SECT:.*]] = load ptr, ptr @sect_arr, align 8
-// CHECK: %[[ARR_SECT_PTR:.*]] = getelementptr inbounds i32, ptr %[[LARR_SECT]], i64 %[[ARR_SECT_OFFSET2]]
+// CHECK: %[[ARR_SECT_PTR:.*]] = getelementptr inbounds i8, ptr %[[LARR_SECT]], i64 %[[ARR_SECT_OFFSET]]
 // CHECK: %[[SCALAR_PTR_LOAD:.*]] = load ptr, ptr %[[SCALAR_BASE]], align 8
 // CHECK: %[[NULL_CMP:.*]] = icmp eq ptr %[[FULL_ARR_PTR]], null
 // CHECK: %[[IS_NULL:.*]] = select i1 %[[NULL_CMP]], i64 0, i64 %[[FULL_ARR_SIZE_ADJUSTED]]

``````````

</details>


https://github.com/llvm/llvm-project/pull/225653


More information about the flang-commits mailing list