[PATCH] D141350: Fix runtime problem for base class member data used in target region.

2023-01-10 Thread Jennifer Yu via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGfe29a1695a6c: This is to fix runtime problem for member data 
used in target region. (authored by jyu2).

Changed prior to commit:
  https://reviews.llvm.org/D141350?vs=487845&id=488041#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D141350/new/

https://reviews.llvm.org/D141350

Files:
  clang/lib/CodeGen/CGOpenMPRuntime.cpp
  clang/test/OpenMP/target_map_member_expr_codegen.cpp
  openmp/libomptarget/test/mapping/target_map_for_member_data.cpp

Index: openmp/libomptarget/test/mapping/target_map_for_member_data.cpp
===
--- /dev/null
+++ openmp/libomptarget/test/mapping/target_map_for_member_data.cpp
@@ -0,0 +1,68 @@
+// RUN: %libomptarget-compile-generic -fopenmp-version=51
+// RUN: %libomptarget-run-generic 2>&1 \
+// RUN: | %fcheck-generic
+
+extern "C" int printf(const char *, ...);
+template  class A {
+protected:
+  T X;
+  T Y;
+
+public:
+  A(T x, T y) : X{x}, Y{y} {};
+};
+
+template  class B : public A {
+  using A::X;
+  using A::Y;
+
+public:
+  T res;
+
+  B(T x, T y) : A(x, y), res{0} {};
+
+  void run(void) {
+#pragma omp target map(res)
+{ res = X + Y; }
+  }
+};
+
+class X {
+protected:
+  int A;
+
+public:
+  X(int a) : A{a} {};
+};
+class Y : public X {
+  using X::A;
+
+protected:
+  int B;
+
+public:
+  Y(int a, int b) : X(a), B{b} {};
+};
+class Z : public Y {
+  using X::A;
+  using Y::B;
+
+public:
+  int res;
+  Z(int a, int b) : Y(a, b), res{0} {};
+  void run(void) {
+#pragma omp target map(res)
+{ res = A + B; }
+  }
+};
+
+int main(int argc, char *argv[]) {
+  B b(2, 3);
+  b.run();
+  // CHECK: 5
+  printf("b.res = %d \n", b.res);
+  Z c(2, 3);
+  c.run();
+  // CHECK: 5
+  printf("c.res = %d \n", c.res);
+}
Index: clang/test/OpenMP/target_map_member_expr_codegen.cpp
===
--- /dev/null
+++ clang/test/OpenMP/target_map_member_expr_codegen.cpp
@@ -0,0 +1,122 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-targets=x86_64-pc-linux-gnu  \
+// RUN:  -x c++ -triple x86_64-unknown-linux-gnu -emit-llvm %s -o - \
+// RUN:   | FileCheck %s
+
+// expected-no-diagnostics
+
+// CHECK: @.offload_sizes = private unnamed_addr constant [4 x i64] [i64 12, i64 4, i64 4, i64 4]
+// CHECK-NOT: @.offload_sizes = private unnamed_addr constant [4 x i64] [i64 0, i64 4, i64 4, i64 4]
+
+// CHECK-LABEL: define {{[^@]+}}@_Z3foov(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[B:%.*]] = alloca [[CLASS_B:%.*]], align 4
+// CHECK-NEXT:call void @_ZN1BC1Eii(ptr noundef nonnull align 4 dereferenceable(12) [[B]], i32 noundef 2, i32 noundef 3)
+// CHECK-NEXT:call void @_ZN1B3runEv(ptr noundef nonnull align 4 dereferenceable(12) [[B]])
+// CHECK-NEXT:ret void
+//
+class A {
+protected:
+  int X;
+  int Y;
+
+public:
+  A (int x, int y) : X { x }, Y { y } { };
+};
+
+class B : public A {
+  using A::X;
+  using A::Y;
+public:
+  int res;
+// CHECK-LABEL: define {{[^@]+}}@_ZN1BC1Eii(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK-NEXT:[[X_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[Y_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8
+// CHECK-NEXT:store i32 [[X:%.*]], ptr [[X_ADDR]], align 4
+// CHECK-NEXT:store i32 [[Y:%.*]], ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:[[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK-NEXT:[[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// CHECK-NEXT:[[TMP1:%.*]] = load i32, ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:call void @_ZN1BC2Eii(ptr noundef nonnull align 4 dereferenceable(12) [[THIS1]], i32 noundef [[TMP0]], i32 noundef [[TMP1]])
+// CHECK-NEXT:ret void
+//
+  B (int x, int y) : A(x,y), res{0} {}
+// CHECK-LABEL: define {{[^@]+}}@_ZN1B3runEv(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK-NEXT:[[DOTOFFLOAD_BASEPTRS:%.*]] = alloca [4 x ptr], align 8
+// CHECK-NEXT:[[DOTOFFLOAD_PTRS:%.*]] = alloca [4 x ptr], align 8
+// CHECK-NEXT:[[DOTOFFLOAD_MAPPERS:%.*]] = alloca [4 x ptr], align 8
+// CHECK-NEXT:store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8
+// CHECK-NEXT:[[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK-NOT: sdiv exact i64 {{.*}}, ptrtoint
+// CHECK-NEXT:[[RES:%.*]] = getelementptr inbounds [[CLASS_B:%.*]], ptr [[THIS1]], i32 0, i32 1
+// CHECK-NEXT:[[X:%.*]] = getelementptr inbounds [[CLASS_A:%.*]], ptr [[THIS1]], i32 0, i32 0
+// CHECK-NEXT:[[Y:%.*]] = getelementptr inbounds [[CLASS_A]], ptr [[THIS1]], i32 0, i32 1
+// CHECK-NEXT:[[TMP0:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]]

[PATCH] D141350: Fix runtime problem for base class member data used in target region.

2023-01-10 Thread Alexey Bataev via Phabricator via cfe-commits
ABataev accepted this revision.
ABataev added a comment.
This revision is now accepted and ready to land.

LG


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D141350/new/

https://reviews.llvm.org/D141350

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D141350: Fix runtime problem for base class member data used in target region.

2023-01-10 Thread Jennifer Yu via Phabricator via cfe-commits
jyu2 added inline comments.



Comment at: clang/lib/CodeGen/CGOpenMPRuntime.cpp:8490
+if (MD)
+  if (const CXXRecordDecl *RD = dyn_cast(MD->getParent()))
+HasBaseClass = RD->getNumBases() > 0;

ABataev wrote:
> `const auto *RD = dyn_cast(MD->getParent())`. Also, can we use 
> `MD->getParent()->getAsCXXRecordDecl()`?
Thank!  Changed.



Comment at: clang/lib/CodeGen/CGOpenMPRuntime.cpp:8493
 // There should not be a mapper for a combined entry.
+if (MD && HasBaseClass) {
+  // OpenMP 5.2 148:21:

ABataev wrote:
> MD is true if HasBaseClass is true
Sorry, changed.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D141350/new/

https://reviews.llvm.org/D141350

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D141350: Fix runtime problem for base class member data used in target region.

2023-01-10 Thread Jennifer Yu via Phabricator via cfe-commits
jyu2 updated this revision to Diff 487845.
jyu2 added a comment.

Thanks Alexey for code review.  This is to address his comments.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D141350/new/

https://reviews.llvm.org/D141350

Files:
  clang/lib/CodeGen/CGOpenMPRuntime.cpp
  clang/test/OpenMP/target_map_member_expr_codegen.cpp
  openmp/libomptarget/test/mapping/target_map_for_member_data.cpp

Index: openmp/libomptarget/test/mapping/target_map_for_member_data.cpp
===
--- /dev/null
+++ openmp/libomptarget/test/mapping/target_map_for_member_data.cpp
@@ -0,0 +1,64 @@
+// RUN: %libomptarget-compile-generic -fopenmp-version=51
+// RUN: %libomptarget-run-generic 2>&1 \
+// RUN: | %fcheck-generic
+
+extern "C" int printf(const char *, ...);
+template  class A {
+protected:
+  T X;
+  T Y;
+
+public:
+  A(T x, T y) : X{x}, Y{y} {};
+};
+
+template  class B : public A {
+  using A::X;
+  using A::Y;
+
+public:
+  T res;
+
+  B(T x, T y) : A(x, y), res{0} {};
+
+  void run(void) {
+#pragma omp target map(res)
+{ res = X + Y; }
+  }
+};
+
+class X {
+protected:
+  int A;
+public:
+  X (int a) : A {a} {};
+};
+class Y : public X {
+  using X::A;
+protected:
+  int B;
+public:
+  Y (int a, int b) : X(a), B{b} {};
+};
+class Z : public Y {
+  using X::A;
+  using Y::B;
+public:
+  int res;
+  Z(int a, int b): Y(a,b), res{0} {};
+  void run(void) {
+#pragma omp target map(res)
+{ res = A + B; }
+  }
+};
+
+int main(int argc, char *argv[]) {
+  B b(2, 3);
+  b.run();
+  // CHECK: 5
+  printf("b.res = %d \n", b.res);
+  Z c(2,3);
+  c.run();
+  // CHECK: 5
+  printf("c.res = %d \n", c.res);
+}
Index: clang/test/OpenMP/target_map_member_expr_codegen.cpp
===
--- /dev/null
+++ clang/test/OpenMP/target_map_member_expr_codegen.cpp
@@ -0,0 +1,122 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-targets=x86_64-pc-linux-gnu  \
+// RUN:  -x c++ -triple x86_64-unknown-linux-gnu -emit-llvm %s -o - \
+// RUN:   | FileCheck %s
+
+// expected-no-diagnostics
+
+// CHECK: @.offload_sizes = private unnamed_addr constant [4 x i64] [i64 12, i64 4, i64 4, i64 4]
+// CHECK-NOT: @.offload_sizes = private unnamed_addr constant [4 x i64] [i64 0, i64 4, i64 4, i64 4]
+
+// CHECK-LABEL: define {{[^@]+}}@_Z3foov(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[B:%.*]] = alloca [[CLASS_B:%.*]], align 4
+// CHECK-NEXT:call void @_ZN1BC1Eii(ptr noundef nonnull align 4 dereferenceable(12) [[B]], i32 noundef 2, i32 noundef 3)
+// CHECK-NEXT:call void @_ZN1B3runEv(ptr noundef nonnull align 4 dereferenceable(12) [[B]])
+// CHECK-NEXT:ret void
+//
+class A {
+protected:
+  int X;
+  int Y;
+
+public:
+  A (int x, int y) : X { x }, Y { y } { };
+};
+
+class B : public A {
+  using A::X;
+  using A::Y;
+public:
+  int res;
+// CHECK-LABEL: define {{[^@]+}}@_ZN1BC1Eii(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK-NEXT:[[X_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[Y_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8
+// CHECK-NEXT:store i32 [[X:%.*]], ptr [[X_ADDR]], align 4
+// CHECK-NEXT:store i32 [[Y:%.*]], ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:[[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK-NEXT:[[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// CHECK-NEXT:[[TMP1:%.*]] = load i32, ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:call void @_ZN1BC2Eii(ptr noundef nonnull align 4 dereferenceable(12) [[THIS1]], i32 noundef [[TMP0]], i32 noundef [[TMP1]])
+// CHECK-NEXT:ret void
+//
+  B (int x, int y) : A(x,y), res{0} {}
+// CHECK-LABEL: define {{[^@]+}}@_ZN1B3runEv(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK-NEXT:[[DOTOFFLOAD_BASEPTRS:%.*]] = alloca [4 x ptr], align 8
+// CHECK-NEXT:[[DOTOFFLOAD_PTRS:%.*]] = alloca [4 x ptr], align 8
+// CHECK-NEXT:[[DOTOFFLOAD_MAPPERS:%.*]] = alloca [4 x ptr], align 8
+// CHECK-NEXT:store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8
+// CHECK-NEXT:[[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK-NOT: sdiv exact i64 {{.*}}, ptrtoint
+// CHECK-NEXT:[[RES:%.*]] = getelementptr inbounds [[CLASS_B:%.*]], ptr [[THIS1]], i32 0, i32 1
+// CHECK-NEXT:[[X:%.*]] = getelementptr inbounds [[CLASS_A:%.*]], ptr [[THIS1]], i32 0, i32 0
+// CHECK-NEXT:[[Y:%.*]] = getelementptr inbounds [[CLASS_A]], ptr [[THIS1]], i32 0, i32 1
+// CHECK-NEXT:[[TMP0:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK-NEXT:store ptr [[THIS1]], ptr [[TMP0]], align 8
+// CHECK-NEXT:[[TMP1:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK-NEXT:store ptr [[T

[PATCH] D141350: Fix runtime problem for base class member data used in target region.

2023-01-10 Thread Alexey Bataev via Phabricator via cfe-commits
ABataev added inline comments.



Comment at: clang/lib/CodeGen/CGOpenMPRuntime.cpp:8490
+if (MD)
+  if (const CXXRecordDecl *RD = dyn_cast(MD->getParent()))
+HasBaseClass = RD->getNumBases() > 0;

`const auto *RD = dyn_cast(MD->getParent())`. Also, can we use 
`MD->getParent()->getAsCXXRecordDecl()`?



Comment at: clang/lib/CodeGen/CGOpenMPRuntime.cpp:8493
 // There should not be a mapper for a combined entry.
+if (MD && HasBaseClass) {
+  // OpenMP 5.2 148:21:

MD is true if HasBaseClass is true


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D141350/new/

https://reviews.llvm.org/D141350

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D141350: Fix runtime problem for base class member data used in target region.

2023-01-09 Thread Jennifer Yu via Phabricator via cfe-commits
jyu2 added a comment.

In D141350#4038619 , @ye-luo wrote:

> Does this patch work when there are more than one level of inheritance? For 
> example `class B: public A; class C: public B`

Yes, that works.  For that we emit this[:1] instead.   I can add more test that.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D141350/new/

https://reviews.llvm.org/D141350

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D141350: Fix runtime problem for base class member data used in target region.

2023-01-09 Thread Ye Luo via Phabricator via cfe-commits
ye-luo added a comment.

Does this patch work when there are more than one level of inheritance? For 
example `class B: public A; class C: public B`


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D141350/new/

https://reviews.llvm.org/D141350

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D141350: Fix runtime problem for base class member data used in target region.

2023-01-09 Thread Jennifer Yu via Phabricator via cfe-commits
jyu2 created this revision.
jyu2 added reviewers: ABataev, jdoerfert, mikerice.
jyu2 added a project: OpenMP.
Herald added a project: All.
jyu2 requested review of this revision.
Herald added subscribers: openmp-commits, cfe-commits, sstefan1.
Herald added a project: clang.

The problem is happened when base class member field is used in target
region , the size is wrong, cause runtime to fail. Currently the size of
calculation is depended on index of field, since field is in base class,
the calculation is wrong.

According OpenMP 5.2 148:21:
If the target construct is within a class non-static member function,
and a variable is an accessible data member of the object for which the
non-static data member function is invoked, the variable is treated as
if the this[:1] expression had appeared in a map clause with a map-type
of tofrom.

One way to fix this is emitting code to generate this[:1] instead only
when class has any base class.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D141350

Files:
  clang/lib/CodeGen/CGOpenMPRuntime.cpp
  clang/test/OpenMP/target_map_member_expr_codegen.cpp
  openmp/libomptarget/test/mapping/target_map_for_member_data.cpp

Index: openmp/libomptarget/test/mapping/target_map_for_member_data.cpp
===
--- /dev/null
+++ openmp/libomptarget/test/mapping/target_map_for_member_data.cpp
@@ -0,0 +1,35 @@
+// RUN: %libomptarget-compile-generic -fopenmp-version=51
+// RUN: %libomptarget-run-generic 2>&1 \
+// RUN: | %fcheck-generic
+
+extern "C" int printf(const char *, ...);
+template  class A {
+protected:
+  T X;
+  T Y;
+
+public:
+  A(T x, T y) : X{x}, Y{y} {};
+};
+
+template  class B : public A {
+  using A::X;
+  using A::Y;
+
+public:
+  T res;
+
+  B(T x, T y) : A(x, y), res{0} {};
+
+  void run(void) {
+#pragma omp target map(res)
+{ res = X + Y; }
+  }
+};
+
+int main(int argc, char *argv[]) {
+  B b(2, 3);
+  b.run();
+  // CHECK: 5
+  printf("b.res = %d \n", b.res);
+}
Index: clang/test/OpenMP/target_map_member_expr_codegen.cpp
===
--- /dev/null
+++ clang/test/OpenMP/target_map_member_expr_codegen.cpp
@@ -0,0 +1,122 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-targets=x86_64-pc-linux-gnu  \
+// RUN:  -x c++ -triple x86_64-unknown-linux-gnu -emit-llvm %s -o - \
+// RUN:   | FileCheck %s
+
+// expected-no-diagnostics
+
+// CHECK: @.offload_sizes = private unnamed_addr constant [4 x i64] [i64 12, i64 4, i64 4, i64 4]
+// CHECK-NOT: @.offload_sizes = private unnamed_addr constant [4 x i64] [i64 0, i64 4, i64 4, i64 4]
+
+// CHECK-LABEL: define {{[^@]+}}@_Z3foov(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[B:%.*]] = alloca [[CLASS_B:%.*]], align 4
+// CHECK-NEXT:call void @_ZN1BC1Eii(ptr noundef nonnull align 4 dereferenceable(12) [[B]], i32 noundef 2, i32 noundef 3)
+// CHECK-NEXT:call void @_ZN1B3runEv(ptr noundef nonnull align 4 dereferenceable(12) [[B]])
+// CHECK-NEXT:ret void
+//
+class A {
+protected:
+  int X;
+  int Y;
+
+public:
+  A (int x, int y) : X { x }, Y { y } { };
+};
+
+class B : public A {
+  using A::X;
+  using A::Y;
+public:
+  int res;
+// CHECK-LABEL: define {{[^@]+}}@_ZN1BC1Eii(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK-NEXT:[[X_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[Y_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8
+// CHECK-NEXT:store i32 [[X:%.*]], ptr [[X_ADDR]], align 4
+// CHECK-NEXT:store i32 [[Y:%.*]], ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:[[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK-NEXT:[[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// CHECK-NEXT:[[TMP1:%.*]] = load i32, ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:call void @_ZN1BC2Eii(ptr noundef nonnull align 4 dereferenceable(12) [[THIS1]], i32 noundef [[TMP0]], i32 noundef [[TMP1]])
+// CHECK-NEXT:ret void
+//
+  B (int x, int y) : A(x,y), res{0} {}
+// CHECK-LABEL: define {{[^@]+}}@_ZN1B3runEv(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK-NEXT:[[DOTOFFLOAD_BASEPTRS:%.*]] = alloca [4 x ptr], align 8
+// CHECK-NEXT:[[DOTOFFLOAD_PTRS:%.*]] = alloca [4 x ptr], align 8
+// CHECK-NEXT:[[DOTOFFLOAD_MAPPERS:%.*]] = alloca [4 x ptr], align 8
+// CHECK-NEXT:store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8
+// CHECK-NEXT:[[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK-NOT: sdiv exact i64 {{.*}}, ptrtoint
+// CHECK-NEXT:[[RES:%.*]] = getelementptr inbounds [[CLASS_B:%.*]], ptr [[THIS1]], i32 0, i32 1
+// CHECK-NEXT:[[X:%.*]] = getelementptr inbounds [[CLASS_A:%.*]], ptr [[THIS1]], i32 0, i32 0
+// CHECK-NEXT:[[Y:%.*]] = getelementptr inbounds [[CLASS_A]], ptr [[THIS1]], i32 0, i32 1
+// CHECK