Xiangling_L updated this revision to Diff 269396.
Xiangling_L marked 2 inline comments as done.
Xiangling_L added a comment.

Simplify the code;
Add one more testcase related to [[no_unique_addr]];


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D79719

Files:
  clang/include/clang/AST/RecordLayout.h
  clang/include/clang/Basic/TargetInfo.h
  clang/lib/AST/ASTContext.cpp
  clang/lib/AST/RecordLayout.cpp
  clang/lib/AST/RecordLayoutBuilder.cpp
  clang/lib/Basic/Targets/OSTargets.h
  clang/lib/Basic/Targets/PPC.h
  clang/test/Layout/aix-double-struct-member.cpp
  clang/test/Layout/aix-no-unique-address-with-double.cpp
  clang/test/Layout/aix-virtual-function-and-base-with-double.cpp

Index: clang/test/Layout/aix-virtual-function-and-base-with-double.cpp
===================================================================
--- /dev/null
+++ clang/test/Layout/aix-virtual-function-and-base-with-double.cpp
@@ -0,0 +1,112 @@
+// RUN: %clang_cc1 -emit-llvm-only -triple powerpc-ibm-aix-xcoff \
+// RUN:     -fdump-record-layouts -fsyntax-only %s 2>/dev/null | \
+// RUN:   FileCheck --check-prefixes=CHECK,CHECK32 %s
+
+// RUN: %clang_cc1 -emit-llvm-only -triple powerpc64-ibm-aix-xcoff \
+// RUN:     -fdump-record-layouts -fsyntax-only %s 2>/dev/null | \
+// RUN:   FileCheck --check-prefixes=CHECK,CHECK64 %s
+
+namespace test1 {
+struct A {
+  double d1;
+  virtual void boo() {}
+};
+
+struct B {
+  double d2;
+  A a;
+};
+
+struct C : public A {
+  double d3;
+};
+
+int i = sizeof(B);
+int j = sizeof(C);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:            0 | struct test1::A
+// CHECK-NEXT:            0 |   (A vtable pointer)
+// CHECK32-NEXT:          4 |   double d1
+// CHECK32-NEXT:            | [sizeof=12, dsize=12, align=4, preferredalign=4,
+// CHECK32-NEXT:            |  nvsize=12, nvalign=4, preferrednvalign=4]
+// CHECK64-NEXT:          8 |   double d1
+// CHECK64-NEXT:            | [sizeof=16, dsize=16, align=8, preferredalign=8,
+// CHECK64-NEXT:            |  nvsize=16, nvalign=8, preferrednvalign=8]
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:            0 | struct test1::B
+// CHECK-NEXT:            0 |   double d2
+// CHECK-NEXT:            8 |   struct test1::A a
+// CHECK-NEXT:            8 |     (A vtable pointer)
+// CHECK32-NEXT:         12 |     double d1
+// CHECK32-NEXT:            | [sizeof=24, dsize=20, align=4, preferredalign=8,
+// CHECK32-NEXT:            |  nvsize=20, nvalign=4, preferrednvalign=8]
+// CHECK64-NEXT:         16 |     double d1
+// CHECK64-NEXT:            | [sizeof=24, dsize=24, align=8, preferredalign=8,
+// CHECK64-NEXT:            |  nvsize=24, nvalign=8, preferrednvalign=8]
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:            0 | struct test1::C
+// CHECK-NEXT:            0 |   struct test1::A (primary base)
+// CHECK-NEXT:            0 |     (A vtable pointer)
+// CHECK32-NEXT:          4 |     double d1
+// CHECK32-NEXT:         12 |   double d3
+// CHECK32-NEXT:            | [sizeof=20, dsize=20, align=4, preferredalign=4,
+// CHECK32-NEXT:            |  nvsize=20, nvalign=4, preferrednvalign=4]
+// CHECK64-NEXT:          8 |     double d1
+// CHECK64-NEXT:         16 |   double d3
+// CHECK64-NEXT:            | [sizeof=24, dsize=24, align=8, preferredalign=8,
+// CHECK64-NEXT:            |  nvsize=24, nvalign=8, preferrednvalign=8]
+
+}; // namespace test1
+
+namespace test2 {
+struct A {
+  long long l1;
+};
+
+struct B : public virtual A {
+  double d2;
+};
+
+#pragma pack(2)
+struct C : public virtual A {
+  double __attribute__((aligned(4))) d3;
+};
+
+int i = sizeof(B);
+int j = sizeof(C);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:            0 | struct test2::A
+// CHECK-NEXT:            0 |   long long l1
+// CHECK-NEXT:              | [sizeof=8, dsize=8, align=8, preferredalign=8,
+// CHECK-NEXT:              |  nvsize=8, nvalign=8, preferrednvalign=8]
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:            0 | struct test2::B
+// CHECK-NEXT:            0 |   (B vtable pointer)
+// CHECK32-NEXT:          4 |   double d2
+// CHECK64-NEXT:          8 |   double d2
+// CHECK-NEXT:           16 |   struct test2::A (virtual base)
+// CHECK-NEXT:           16 |     long long l1
+// CHECK-NEXT:              | [sizeof=24, dsize=24, align=8, preferredalign=8,
+// CHECK32-NEXT:            |  nvsize=12, nvalign=4, preferrednvalign=4]
+// CHECK64-NEXT:            |  nvsize=16, nvalign=8, preferrednvalign=8]
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:            0 | struct test2::C
+// CHECK-NEXT:            0 |   (C vtable pointer)
+// CHECK32-NEXT:          4 |   double d3
+// CHECK32-NEXT:         12 |   struct test2::A (virtual base)
+// CHECK32-NEXT:         12 |     long long l1
+// CHECK32-NEXT:            | [sizeof=20, dsize=20, align=2, preferredalign=2,
+// CHECK32-NEXT:            |  nvsize=12, nvalign=2, preferrednvalign=2]
+// CHECK64-NEXT:          8 |   double d3
+// CHECK64-NEXT:         16 |   struct test2::A (virtual base)
+// CHECK64-NEXT:         16 |     long long l1
+// CHECK64-NEXT:            | [sizeof=24, dsize=24, align=2, preferredalign=2,
+// CHECK64-NEXT:            |  nvsize=16, nvalign=2, preferrednvalign=2]
+
+}; // namespace test2
Index: clang/test/Layout/aix-no-unique-address-with-double.cpp
===================================================================
--- /dev/null
+++ clang/test/Layout/aix-no-unique-address-with-double.cpp
@@ -0,0 +1,144 @@
+// RUN: %clang_cc1 -emit-llvm-only -triple powerpc-ibm-aix-xcoff \
+// RUN:     -fdump-record-layouts -fsyntax-only %s 2>/dev/null | \
+// RUN:   FileCheck %s
+
+// RUN: %clang_cc1 -emit-llvm-only -triple powerpc64-ibm-aix-xcoff \
+// RUN:     -fdump-record-layouts -fsyntax-only %s 2>/dev/null | \
+// RUN:   FileCheck %s
+
+struct Empty {};
+
+struct A {
+  double d;
+};
+
+// CHECK:     *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct Empty (empty)
+// CHECK-NEXT:            | [sizeof=1, dsize=1, align=1, preferredalign=1,
+// CHECK-NEXT:            |  nvsize=1, nvalign=1, preferrednvalign=1]
+
+// CHECK:     *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct A
+// CHECK-NEXT:          0 |   double d
+// CHECK-NEXT:            | [sizeof=8, dsize=8, align=4, preferredalign=8,
+// CHECK-NEXT:            |  nvsize=8, nvalign=4, preferrednvalign=8]
+
+struct B {
+  ~B();
+
+  Empty emp;
+  A a;
+  char c;
+};
+
+struct B1 {
+  [[no_unique_address]] B b;
+  char ext[7];
+};
+
+// CHECK:     *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct B
+// CHECK-NEXT:          0 |   struct Empty emp (empty)
+// CHECK-NEXT:          4 |   struct A a
+// CHECK-NEXT:          4 |     double d
+// CHECK-NEXT:         12 |   char c
+// CHECK-NEXT:            | [sizeof=16, dsize=13, align=4, preferredalign=4,
+// CHECK-NEXT:            |  nvsize=13, nvalign=4, preferrednvalign=4]
+
+// CHECK:     *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct B1
+// CHECK-NEXT:          0 |   struct B b
+// CHECK-NEXT:          0 |     struct Empty emp (empty)
+// CHECK-NEXT:          4 |     struct A a
+// CHECK-NEXT:          4 |       double d
+// CHECK-NEXT:         12 |     char c
+// CHECK-NEXT:         13 |   char [7] ext
+// CHECK-NEXT:            | [sizeof=20, dsize=20, align=4, preferredalign=4,
+// CHECK-NEXT:            |  nvsize=20, nvalign=4, preferrednvalign=4]
+
+struct C {
+  ~C();
+
+  [[no_unique_address]] Empty emp;
+  A a;
+  char c;
+};
+
+struct C1 {
+  [[no_unique_address]] C c;
+  char ext[7];
+};
+
+// CHECK:     *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct C
+// CHECK-NEXT:          0 |   struct Empty emp (empty)
+// CHECK-NEXT:          0 |   struct A a
+// CHECK-NEXT:          0 |     double d
+// CHECK-NEXT:          8 |   char c
+// CHECK-NEXT:            | [sizeof=16, dsize=9, align=4, preferredalign=8,
+// CHECK-NEXT:            |  nvsize=9, nvalign=4, preferrednvalign=8]
+
+// CHECK:     *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct C1
+// CHECK-NEXT:          0 |   struct C c
+// CHECK-NEXT:          0 |     struct Empty emp (empty)
+// CHECK-NEXT:          0 |     struct A a
+// CHECK-NEXT:          0 |       double d
+// CHECK-NEXT:          8 |     char c
+// CHECK-NEXT:          9 |   char [7] ext
+// CHECK-NEXT:            | [sizeof=16, dsize=16, align=4, preferredalign=8,
+// CHECK-NEXT:            |  nvsize=16, nvalign=4, preferrednvalign=8]
+
+struct D {
+  ~D();
+
+  [[no_unique_address]] char notEmp;
+  A a;
+  char c;
+};
+
+struct D1 {
+  [[no_unique_address]] D d;
+  char ext[7];
+};
+
+// CHECK:     *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct D
+// CHECK-NEXT:          0 |   char notEmp
+// CHECK-NEXT:          4 |   struct A a
+// CHECK-NEXT:          4 |     double d
+// CHECK-NEXT:         12 |   char c
+// CHECK-NEXT:            | [sizeof=16, dsize=13, align=4, preferredalign=4,
+// CHECK-NEXT:            |  nvsize=13, nvalign=4, preferrednvalign=4]
+
+// CHECK:     *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct D1
+// CHECK-NEXT:          0 |   struct D d
+// CHECK-NEXT:          0 |     char notEmp
+// CHECK-NEXT:          4 |     struct A a
+// CHECK-NEXT:          4 |       double d
+// CHECK-NEXT:         12 |     char c
+// CHECK-NEXT:         13 |   char [7] ext
+// CHECK-NEXT:            | [sizeof=20, dsize=20, align=4, preferredalign=4,
+// CHECK-NEXT:            |  nvsize=20, nvalign=4, preferrednvalign=4]
+
+struct E {
+  [[no_unique_address]] Empty emp;
+  int : 0;
+  double d;
+};
+
+// CHECK:     *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct E
+// CHECK-NEXT:          0 |   struct Empty emp (empty)
+// CHECK-NEXT:        0:- |   int
+// CHECK-NEXT:          0 |   double d
+// CHECK-NEXT:            | [sizeof=8, dsize=8, align=4, preferredalign=4,
+// CHECK-NEXT:            |  nvsize=8, nvalign=4, preferrednvalign=4]
+
+int a = sizeof(Empty);
+int b = sizeof(A);
+int c = sizeof(B1);
+int d = sizeof(C1);
+int e = sizeof(D1);
+int f = sizeof(E);
Index: clang/test/Layout/aix-double-struct-member.cpp
===================================================================
--- /dev/null
+++ clang/test/Layout/aix-double-struct-member.cpp
@@ -0,0 +1,298 @@
+// RUN: %clang_cc1 -emit-llvm-only -triple powerpc-ibm-aix-xcoff \
+// RUN:     -fdump-record-layouts -fsyntax-only %s 2>/dev/null | \
+// RUN:   FileCheck %s
+
+// RUN: %clang_cc1 -emit-llvm-only -triple powerpc64-ibm-aix-xcoff \
+// RUN:     -fdump-record-layouts -fsyntax-only %s 2>/dev/null | \
+// RUN:   FileCheck %s
+
+namespace test1 {
+// Test double alignment when it is/is not the first struct member.
+struct D {
+  double d1;
+  int i1;
+};
+
+struct DoubleFirst {
+  struct D d2;
+  int i2;
+};
+
+struct IntFirst {
+  int i3;
+  struct D d3;
+};
+
+int a = sizeof(DoubleFirst);
+int b = sizeof(IntFirst);
+
+// CHECK:     *** Dumping AST Record Layout
+// CHECK-NEXT:         0 | struct test1::D
+// CHECK-NEXT:         0 |   double d1
+// CHECK-NEXT:         8 |   int i1
+// CHECK-NEXT:           | [sizeof=16, dsize=16, align=4, preferredalign=8,
+// CHECK-NEXT:           |  nvsize=16, nvalign=4, preferrednvalign=8]
+
+// CHECK:     *** Dumping AST Record Layout
+// CHECK-NEXT:         0 | struct test1::DoubleFirst
+// CHECK-NEXT:         0 |   struct test1::D d2
+// CHECK-NEXT:         0 |     double d1
+// CHECK-NEXT:         8 |     int i1
+// CHECK-NEXT:        16 |   int i2
+// CHECK-NEXT:           | [sizeof=24, dsize=24, align=4, preferredalign=8,
+// CHECK-NEXT:           |  nvsize=24, nvalign=4, preferrednvalign=8]
+
+// CHECK:     *** Dumping AST Record Layout
+// CHECK-NEXT:         0 | struct test1::IntFirst
+// CHECK-NEXT:         0 |   int i3
+// CHECK-NEXT:         4 |   struct test1::D d3
+// CHECK-NEXT:         4 |     double d1
+// CHECK-NEXT:        12 |     int i1
+// CHECK-NEXT:           | [sizeof=20, dsize=20, align=4, preferredalign=4,
+// CHECK-NEXT:           |  nvsize=20, nvalign=4, preferrednvalign=4]
+}; // namespace test1
+
+namespace test2 {
+// Test AIX layout for zero sized bitfield followed by double.
+struct Double {
+  int : 0;
+  double d;
+};
+
+int a = sizeof(Double);
+
+// CHECK:     *** Dumping AST Record Layout
+// CHECK-NEXT:         0 | struct test2::Double
+// CHECK-NEXT:       0:- |   int
+// CHECK-NEXT:         0 |   double d
+// CHECK-NEXT:           | [sizeof=8, dsize=8, align=4, preferredalign=4,
+// CHECK-NEXT:           |  nvsize=8, nvalign=4, preferrednvalign=4]
+}; // namespace test2
+
+namespace test3 {
+// Test the alignment of a double member in union.
+union A {
+  int b;
+  double d;
+};
+
+struct UnionStruct {
+  union A a;
+  int i;
+};
+
+int a = sizeof(UnionStruct);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | union test3::A
+// CHECK-NEXT:          0 |   int b
+// CHECK-NEXT:          0 |   double d
+// CHECK-NEXT:            | [sizeof=8, dsize=8, align=4, preferredalign=8,
+// CHECK-NEXT:            |  nvsize=8, nvalign=4, preferrednvalign=8]
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct test3::UnionStruct
+// CHECK-NEXT:          0 |   union test3::A a
+// CHECK-NEXT:          0 |     int b
+// CHECK-NEXT:          0 |     double d
+// CHECK-NEXT:          8 |   int i
+// CHECK-NEXT:            | [sizeof=16, dsize=16, align=4, preferredalign=8,
+// CHECK-NEXT:            |  nvsize=16, nvalign=4, preferrednvalign=8]
+
+}; // namespace test3
+
+namespace test4 {
+// Test the AIX Alignment rule when layout base class.
+struct A {
+  int a;
+};
+
+struct B {
+  double d;
+};
+
+class S : A, B {
+};
+
+int a = sizeof(S);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct test4::A
+// CHECK-NEXT:          0 |   int a
+// CHECK-NEXT:            | [sizeof=4, dsize=4, align=4, preferredalign=4,
+// CHECK-NEXT:            |  nvsize=4, nvalign=4, preferrednvalign=4]
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct test4::B
+// CHECK-NEXT:          0 |   double d
+// CHECK-NEXT:            | [sizeof=8, dsize=8, align=4, preferredalign=8,
+// CHECK-NEXT:            |  nvsize=8, nvalign=4, preferrednvalign=8]
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | class test4::S
+// CHECK-NEXT:          0 |   struct test4::A (base)
+// CHECK-NEXT:          0 |     int a
+// CHECK-NEXT:          4 |   struct test4::B (base)
+// CHECK-NEXT:          4 |     double d
+// CHECK-NEXT:            | [sizeof=12, dsize=12, align=4, preferredalign=4,
+// CHECK-NEXT:            |  nvsize=12, nvalign=4, preferrednvalign=4]
+}; // namespace test4
+
+namespace test5 {
+// Test the AIX alignment rule with basic inheritance.
+struct Empty {
+};
+
+struct EmptyDer : Empty {
+  double d;
+};
+
+struct NonEmpty {
+  int i;
+};
+
+struct NonEmptyDer : NonEmpty {
+  double d;
+};
+
+int a = sizeof(EmptyDer);
+int b = sizeof(NonEmptyDer);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct test5::Empty (empty)
+// CHECK-NEXT:            | [sizeof=1, dsize=1, align=1, preferredalign=1,
+// CHECK-NEXT:            |  nvsize=1, nvalign=1, preferrednvalign=1]
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct test5::EmptyDer
+// CHECK-NEXT:          0 |   struct test5::Empty (base) (empty)
+// CHECK-NEXT:          0 |   double d
+// CHECK-NEXT:            | [sizeof=8, dsize=8, align=4, preferredalign=8,
+// CHECK-NEXT:            |  nvsize=8, nvalign=4, preferrednvalign=8]
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct test5::NonEmpty
+// CHECK-NEXT:          0 |   int i
+// CHECK-NEXT:            | [sizeof=4, dsize=4, align=4, preferredalign=4,
+// CHECK-NEXT:            |  nvsize=4, nvalign=4, preferrednvalign=4]
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct test5::NonEmptyDer
+// CHECK-NEXT:          0 |   struct test5::NonEmpty (base)
+// CHECK-NEXT:          0 |     int i
+// CHECK-NEXT:          4 |   double d
+// CHECK-NEXT:            | [sizeof=12, dsize=12, align=4, preferredalign=4,
+// CHECK-NEXT:            |  nvsize=12, nvalign=4, preferrednvalign=4]
+}; // namespace test5
+
+namespace test6 {
+// Test how #pragma pack and align attribute interacts with AIX alignment.
+struct A {
+  char a;
+  double __attribute__((aligned(16))) d;
+  int i;
+};
+
+struct B {
+  double __attribute__((aligned(4))) d1;
+  char a;
+  double d2;
+};
+
+#pragma pack(2)
+struct C {
+  int i;
+  short j;
+  double k;
+};
+
+#pragma pack(2)
+struct D {
+  double d;
+  short j;
+  int i;
+};
+
+#pragma pack(8)
+struct E {
+  double __attribute__((aligned(4))) d;
+  short s;
+};
+
+#pragma pack(4)
+struct F : public D {
+  double d;
+};
+
+#pragma pack(2)
+struct G : public E {
+  int i;
+};
+
+int a = sizeof(A);
+int b = sizeof(B);
+int c = sizeof(C);
+int d = sizeof(D);
+int e = sizeof(E);
+int f = sizeof(F);
+int g = sizeof(G);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct test6::A
+// CHECK-NEXT:          0 |   char a
+// CHECK-NEXT:         16 |   double d
+// CHECK-NEXT:         24 |   int i
+// CHECK-NEXT:            | [sizeof=32, dsize=32, align=16, preferredalign=16,
+// CHECK-NEXT:            |  nvsize=32, nvalign=16, preferrednvalign=16]
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct test6::B
+// CHECK-NEXT:          0 |   double d1
+// CHECK-NEXT:          8 |   char a
+// CHECK-NEXT:         12 |   double d2
+// CHECK-NEXT:            | [sizeof=24, dsize=24, align=4, preferredalign=8,
+// CHECK-NEXT:            |  nvsize=24, nvalign=4, preferrednvalign=8]
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct test6::C
+// CHECK-NEXT:          0 |   int i
+// CHECK-NEXT:          4 |   short j
+// CHECK-NEXT:          6 |   double k
+// CHECK-NEXT:            | [sizeof=14, dsize=14, align=2, preferredalign=2,
+// CHECK-NEXT:            |  nvsize=14, nvalign=2, preferrednvalign=2]
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct test6::D
+// CHECK-NEXT:          0 |   double d
+// CHECK-NEXT:          8 |   short j
+// CHECK-NEXT:         10 |   int i
+// CHECK-NEXT:            | [sizeof=14, dsize=14, align=2, preferredalign=2,
+// CHECK-NEXT:            |  nvsize=14, nvalign=2, preferrednvalign=2]
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct test6::E
+// CHECK-NEXT:          0 |   double d
+// CHECK-NEXT:          8 |   short s
+// CHECK-NEXT:            | [sizeof=16, dsize=16, align=4, preferredalign=8,
+// CHECK-NEXT:            |  nvsize=16, nvalign=4, preferrednvalign=8]
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct test6::F
+// CHECK-NEXT:          0 |   struct test6::D (base)
+// CHECK-NEXT:          0 |     double d
+// CHECK-NEXT:          8 |     short j
+// CHECK-NEXT:         10 |     int i
+// CHECK-NEXT:         16 |   double d
+// CHECK-NEXT:            | [sizeof=24, dsize=24, align=4, preferredalign=4,
+// CHECK-NEXT:            |  nvsize=24, nvalign=4, preferrednvalign=4]
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct test6::G
+// CHECK-NEXT:          0 |   struct test6::E (base)
+// CHECK-NEXT:          0 |     double d
+// CHECK-NEXT:          8 |     short s
+// CHECK-NEXT:         16 |   int i
+// CHECK-NEXT:            | [sizeof=20, dsize=20, align=2, preferredalign=2,
+// CHECK-NEXT:            |  nvsize=20, nvalign=2, preferrednvalign=2]
+
+}; // namespace test6
Index: clang/lib/Basic/Targets/PPC.h
===================================================================
--- clang/lib/Basic/Targets/PPC.h
+++ clang/lib/Basic/Targets/PPC.h
@@ -368,11 +368,17 @@
     }
 
     if (Triple.isOSFreeBSD() || Triple.isOSNetBSD() || Triple.isOSOpenBSD() ||
-        Triple.getOS() == llvm::Triple::AIX || Triple.isMusl()) {
+        Triple.isMusl()) {
       LongDoubleWidth = LongDoubleAlign = 64;
       LongDoubleFormat = &llvm::APFloat::IEEEdouble();
     }
 
+    if (Triple.isOSAIX()) {
+      LongDoubleWidth = 64;
+      LongDoubleAlign = DoubleAlign = 32;
+      LongDoubleFormat = &llvm::APFloat::IEEEdouble();
+    }
+
     // PPC32 supports atomics up to 4 bytes.
     MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32;
   }
@@ -404,12 +410,17 @@
     if (Triple.getOS() == llvm::Triple::AIX)
       SuitableAlign = 64;
 
-    if (Triple.isOSFreeBSD() || Triple.getOS() == llvm::Triple::AIX ||
-        Triple.isMusl()) {
+    if (Triple.isOSFreeBSD() || Triple.isMusl()) {
       LongDoubleWidth = LongDoubleAlign = 64;
       LongDoubleFormat = &llvm::APFloat::IEEEdouble();
     }
 
+    if (Triple.isOSAIX()) {
+      LongDoubleWidth = 64;
+      LongDoubleAlign = DoubleAlign = 32;
+      LongDoubleFormat = &llvm::APFloat::IEEEdouble();
+    }
+
     // PPC64 supports atomics up to 8 bytes.
     MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
   }
Index: clang/lib/Basic/Targets/OSTargets.h
===================================================================
--- clang/lib/Basic/Targets/OSTargets.h
+++ clang/lib/Basic/Targets/OSTargets.h
@@ -719,6 +719,8 @@
   // AIX sets FLT_EVAL_METHOD to be 1.
   unsigned getFloatEvalMethod() const override { return 1; }
   bool hasInt128Type() const override { return false; }
+
+  bool supportsAIXPowerAlignment() const override { return true; }
 };
 
 void addWindowsDefines(const llvm::Triple &Triple, const LangOptions &Opts,
Index: clang/lib/AST/RecordLayoutBuilder.cpp
===================================================================
--- clang/lib/AST/RecordLayoutBuilder.cpp
+++ clang/lib/AST/RecordLayoutBuilder.cpp
@@ -6,7 +6,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "clang/AST/RecordLayout.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/ASTDiagnostic.h"
 #include "clang/AST/Attr.h"
@@ -15,6 +14,7 @@
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/Expr.h"
+#include "clang/AST/RecordLayout.h"
 #include "clang/Basic/TargetInfo.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/Support/Format.h"
@@ -588,6 +588,9 @@
   /// Alignment - The current alignment of the record layout.
   CharUnits Alignment;
 
+  /// PreferredAlignment - The preferred alignment of the record layout.
+  CharUnits PreferredAlignment;
+
   /// The alignment if attribute packed is not used.
   CharUnits UnpackedAlignment;
 
@@ -631,6 +634,7 @@
 
   CharUnits NonVirtualSize;
   CharUnits NonVirtualAlignment;
+  CharUnits PreferredNVAlignment;
 
   /// If we've laid out a field but not included its tail padding in Size yet,
   /// this is the size up to the end of that field.
@@ -651,6 +655,15 @@
   /// the flag of field offset changing due to packed attribute.
   bool HasPackedField;
 
+  /// FirstNonOverlappingEmptyFieldStatus - An auxiliary field used for AIX.
+  /// When there are OverlappingEmptyFields existing in the aggregate, the
+  /// status shows if a following non-overlappingEmptyField can be found.
+  enum {
+    Default,
+    FirstNonOverlappingEmptyFieldFound,
+    FirstNonOverlappingEmptyFieldHandled
+  } FirstNonOverlappingEmptyFieldStatus;
+
   typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
 
   /// Bases - base classes and their offsets in the record.
@@ -677,17 +690,19 @@
   ItaniumRecordLayoutBuilder(const ASTContext &Context,
                              EmptySubobjectMap *EmptySubobjects)
       : Context(Context), EmptySubobjects(EmptySubobjects), Size(0),
-        Alignment(CharUnits::One()), UnpackedAlignment(CharUnits::One()),
-        UnadjustedAlignment(CharUnits::One()),
-        UseExternalLayout(false), InferAlignment(false), Packed(false),
-        IsUnion(false), IsMac68kAlign(false), IsMsStruct(false),
-        UnfilledBitsInLastUnit(0), LastBitfieldTypeSize(0),
-        MaxFieldAlignment(CharUnits::Zero()), DataSize(0),
-        NonVirtualSize(CharUnits::Zero()),
+        Alignment(CharUnits::One()), PreferredAlignment(CharUnits::One()),
+        UnpackedAlignment(CharUnits::One()),
+        UnadjustedAlignment(CharUnits::One()), UseExternalLayout(false),
+        InferAlignment(false), Packed(false), IsUnion(false),
+        IsMac68kAlign(false), IsMsStruct(false), UnfilledBitsInLastUnit(0),
+        LastBitfieldTypeSize(0), MaxFieldAlignment(CharUnits::Zero()),
+        DataSize(0), NonVirtualSize(CharUnits::Zero()),
         NonVirtualAlignment(CharUnits::One()),
+        PreferredNVAlignment(CharUnits::One()),
         PaddedFieldSize(CharUnits::Zero()), PrimaryBase(nullptr),
-        PrimaryBaseIsVirtual(false), HasOwnVFPtr(false),
-        HasPackedField(false), FirstNearlyEmptyVBase(nullptr) {}
+        PrimaryBaseIsVirtual(false), HasOwnVFPtr(false), HasPackedField(false),
+        FirstNonOverlappingEmptyFieldStatus(Default),
+        FirstNearlyEmptyVBase(nullptr) {}
 
   void Layout(const RecordDecl *D);
   void Layout(const CXXRecordDecl *D);
@@ -762,9 +777,13 @@
   /// alignment.
   void FinishLayout(const NamedDecl *D);
 
-  void UpdateAlignment(CharUnits NewAlignment, CharUnits UnpackedNewAlignment);
+  void UpdateAlignment(CharUnits NewAlignment, CharUnits UnpackedNewAlignment,
+                       CharUnits PreferredAlignment);
+  void UpdateAlignment(CharUnits NewAlignment, CharUnits UnpackedNewAlignment) {
+    UpdateAlignment(NewAlignment, UnpackedNewAlignment, NewAlignment);
+  }
   void UpdateAlignment(CharUnits NewAlignment) {
-    UpdateAlignment(NewAlignment, NewAlignment);
+    UpdateAlignment(NewAlignment, NewAlignment, NewAlignment);
   }
 
   /// Retrieve the externally-supplied field offset for the given
@@ -806,6 +825,10 @@
 };
 } // end anonymous namespace
 
+static bool isAIXLayout(const ASTContext &Context) {
+  return Context.getTargetInfo().getTriple().getOS() == llvm::Triple::AIX;
+}
+
 void ItaniumRecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD) {
   for (const auto &I : RD->bases()) {
     assert(!I.getType()->isDependentType() &&
@@ -997,7 +1020,7 @@
   setSize(getSize().alignTo(BaseAlign));
 
   // Update the alignment.
-  UpdateAlignment(BaseAlign, UnpackedBaseAlign);
+  UpdateAlignment(BaseAlign, UnpackedBaseAlign, BaseAlign);
 }
 
 void ItaniumRecordLayoutBuilder::LayoutNonVirtualBases(
@@ -1179,8 +1202,6 @@
 CharUnits
 ItaniumRecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) {
   const ASTRecordLayout &Layout = Context.getASTRecordLayout(Base->Class);
-
-
   CharUnits Offset;
 
   // Query the external layout to see if it provides an offset.
@@ -1196,26 +1217,40 @@
   // Clang <= 6 incorrectly applied the 'packed' attribute to base classes.
   // Per GCC's documentation, it only applies to non-static data members.
   CharUnits UnpackedBaseAlign = Layout.getNonVirtualAlignment();
+  CharUnits UnpackedPreferredAlign = Layout.getPreferredNVAlignment();
   CharUnits BaseAlign =
       (Packed && ((Context.getLangOpts().getClangABICompat() <=
                    LangOptions::ClangABI::Ver6) ||
                   Context.getTargetInfo().getTriple().isPS4()))
           ? CharUnits::One()
           : UnpackedBaseAlign;
+  CharUnits PreferredAlign =
+      (Packed && ((Context.getLangOpts().getClangABICompat() <=
+                   LangOptions::ClangABI::Ver6) ||
+                  Context.getTargetInfo().getTriple().isPS4()))
+          ? CharUnits::One()
+          : UnpackedPreferredAlign;
 
   // If we have an empty base class, try to place it at offset 0.
   if (Base->Class->isEmpty() &&
       (!HasExternalLayout || Offset == CharUnits::Zero()) &&
       EmptySubobjects->CanPlaceBaseAtOffset(Base, CharUnits::Zero())) {
     setSize(std::max(getSize(), Layout.getSize()));
-    UpdateAlignment(BaseAlign, UnpackedBaseAlign);
+    UpdateAlignment(BaseAlign, UnpackedBaseAlign, PreferredAlign);
 
     return CharUnits::Zero();
   }
 
+  // Do not use AIX special alignment if current base is not the first member or
+  // the struct is not a union.
+  if (isAIXLayout(Context) && !(getDataSize().isZero() || IsUnion)) {
+    PreferredAlign = BaseAlign;
+  }
+
   // The maximum field alignment overrides base align.
   if (!MaxFieldAlignment.isZero()) {
     BaseAlign = std::min(BaseAlign, MaxFieldAlignment);
+    PreferredAlign = std::min(PreferredAlign, MaxFieldAlignment);
     UnpackedBaseAlign = std::min(UnpackedBaseAlign, MaxFieldAlignment);
   }
 
@@ -1248,7 +1283,7 @@
     setSize(std::max(getSize(), Offset + Layout.getSize()));
 
   // Remember max struct/class alignment.
-  UpdateAlignment(BaseAlign, UnpackedBaseAlign);
+  UpdateAlignment(BaseAlign, UnpackedBaseAlign, PreferredAlign);
 
   return Offset;
 }
@@ -1321,6 +1356,7 @@
   NonVirtualSize = Context.toCharUnitsFromBits(
       llvm::alignTo(getSizeInBits(), Context.getTargetInfo().getCharAlign()));
   NonVirtualAlignment = Alignment;
+  PreferredNVAlignment = PreferredAlignment;
 
   // Lay out the virtual bases and add the primary virtual base offsets.
   LayoutVirtualBases(RD, RD);
@@ -1733,25 +1769,34 @@
 
 void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D,
                                              bool InsertExtraPadding) {
+  auto *FieldClass = D->getType()->getAsCXXRecordDecl();
+  bool PotentiallyOverlapping = D->hasAttr<NoUniqueAddressAttr>() && FieldClass;
+  bool IsOverlappingEmptyField =
+      PotentiallyOverlapping && FieldClass->isEmpty();
+
+  if (isAIXLayout(Context) && FirstNonOverlappingEmptyFieldStatus == Default &&
+      !IsOverlappingEmptyField)
+    FirstNonOverlappingEmptyFieldStatus = FirstNonOverlappingEmptyFieldFound;
+
   if (D->isBitField()) {
+    if (FirstNonOverlappingEmptyFieldStatus ==
+        FirstNonOverlappingEmptyFieldFound)
+      FirstNonOverlappingEmptyFieldStatus =
+          FirstNonOverlappingEmptyFieldHandled;
     LayoutBitField(D);
     return;
   }
 
   uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
-
   // Reset the unfilled bits.
   UnfilledBitsInLastUnit = 0;
   LastBitfieldTypeSize = 0;
 
-  auto *FieldClass = D->getType()->getAsCXXRecordDecl();
-  bool PotentiallyOverlapping = D->hasAttr<NoUniqueAddressAttr>() && FieldClass;
-  bool IsOverlappingEmptyField = PotentiallyOverlapping && FieldClass->isEmpty();
   bool FieldPacked = Packed || D->hasAttr<PackedAttr>();
 
-  CharUnits FieldOffset = (IsUnion || IsOverlappingEmptyField)
-                              ? CharUnits::Zero()
-                              : getDataSize();
+  CharUnits FieldOffset =
+      (IsUnion || IsOverlappingEmptyField) ? CharUnits::Zero() : getDataSize();
+
   CharUnits FieldSize;
   CharUnits FieldAlign;
   // The amount of this class's dsize occupied by the field.
@@ -1829,21 +1874,52 @@
     }
   }
 
+  // AIX ABI has this special rule that in aggregates, the first member of
+  // floating point data type(or aggregate type contains floating point data
+  // type) is aligned according to its natural alignment value, subsequent
+  // of such data type members of the aggregate are aligned on 4-byte
+  // boundaries.
+  CharUnits PreferredAlign = FieldAlign;
+  if (isAIXLayout(Context) && FieldOffset == CharUnits::Zero() &&
+      ((D->getFieldIndex() == 0 && !IsOverlappingEmptyField) || IsUnion ||
+       (D->getFieldIndex() != 0 && FirstNonOverlappingEmptyFieldStatus ==
+                                       FirstNonOverlappingEmptyFieldFound))) {
+    FirstNonOverlappingEmptyFieldStatus = FirstNonOverlappingEmptyFieldHandled;
+
+    if (const BuiltinType *BTy =
+            Context.getBaseElementType(D->getType())->getAs<BuiltinType>()) {
+      if (BTy->isFloatingPoint()) {
+        PreferredAlign = FieldSize;
+      }
+    } else if (const RecordType *RT = D->getType()
+                                          ->getBaseElementTypeUnsafe()
+                                          ->getAs<RecordType>()) {
+      if (const RecordDecl *RD = RT->getDecl()) {
+        const ASTRecordLayout &FieldRecord = Context.getASTRecordLayout(RD);
+        PreferredAlign = FieldRecord.getPreferredAlignment();
+      }
+    }
+  }
+
   // The align if the field is not packed. This is to check if the attribute
   // was unnecessary (-Wpacked).
   CharUnits UnpackedFieldAlign = FieldAlign;
   CharUnits UnpackedFieldOffset = FieldOffset;
 
-  if (FieldPacked)
+  if (FieldPacked) {
     FieldAlign = CharUnits::One();
+    PreferredAlign = CharUnits::One();
+  }
   CharUnits MaxAlignmentInChars =
     Context.toCharUnitsFromBits(D->getMaxAlignment());
   FieldAlign = std::max(FieldAlign, MaxAlignmentInChars);
+  PreferredAlign = std::max(PreferredAlign, MaxAlignmentInChars);
   UnpackedFieldAlign = std::max(UnpackedFieldAlign, MaxAlignmentInChars);
 
   // The maximum field alignment overrides the aligned attribute.
   if (!MaxFieldAlignment.isZero()) {
     FieldAlign = std::min(FieldAlign, MaxFieldAlignment);
+    PreferredAlign = std::min(PreferredAlign, MaxFieldAlignment);
     UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignment);
   }
 
@@ -1910,7 +1986,7 @@
 
   // Remember max struct/class alignment.
   UnadjustedAlignment = std::max(UnadjustedAlignment, FieldAlign);
-  UpdateAlignment(FieldAlign, UnpackedFieldAlign);
+  UpdateAlignment(FieldAlign, UnpackedFieldAlign, PreferredAlign);
 }
 
 void ItaniumRecordLayoutBuilder::FinishLayout(const NamedDecl *D) {
@@ -1936,8 +2012,10 @@
   uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastUnit;
   uint64_t UnpackedSizeInBits =
       llvm::alignTo(getSizeInBits(), Context.toBits(UnpackedAlignment));
-  uint64_t RoundedSize =
-      llvm::alignTo(getSizeInBits(), Context.toBits(Alignment));
+
+  uint64_t RoundedSize = llvm::alignTo(
+      getSizeInBits(),
+      Context.toBits(!isAIXLayout(Context) ? Alignment : PreferredAlignment));
 
   if (UseExternalLayout) {
     // If we're inferring alignment, and the external size is smaller than
@@ -1981,7 +2059,8 @@
 }
 
 void ItaniumRecordLayoutBuilder::UpdateAlignment(
-    CharUnits NewAlignment, CharUnits UnpackedNewAlignment) {
+    CharUnits NewAlignment, CharUnits UnpackedNewAlignment,
+    CharUnits PreferredNewAlignment) {
   // The alignment is not modified when using 'mac68k' alignment or when
   // we have an externally-supplied layout that also provides overall alignment.
   if (IsMac68kAlign || (UseExternalLayout && !InferAlignment))
@@ -1998,6 +2077,12 @@
            "Alignment not a power of 2");
     UnpackedAlignment = UnpackedNewAlignment;
   }
+
+  if (PreferredNewAlignment > PreferredAlignment) {
+    assert(llvm::isPowerOf2_64(PreferredNewAlignment.getQuantity()) &&
+           "Alignment not a power of 2");
+    PreferredAlignment = PreferredNewAlignment;
+  }
 }
 
 uint64_t
@@ -3048,10 +3133,10 @@
       Builder.cxxLayout(RD);
       NewEntry = new (*this) ASTRecordLayout(
           *this, Builder.Size, Builder.Alignment, Builder.Alignment,
-          Builder.RequiredAlignment,
-          Builder.HasOwnVFPtr, Builder.HasOwnVFPtr || Builder.PrimaryBase,
-          Builder.VBPtrOffset, Builder.DataSize, Builder.FieldOffsets,
-          Builder.NonVirtualSize, Builder.Alignment, CharUnits::Zero(),
+          Builder.Alignment, Builder.RequiredAlignment, Builder.HasOwnVFPtr,
+          Builder.HasOwnVFPtr || Builder.PrimaryBase, Builder.VBPtrOffset,
+          Builder.DataSize, Builder.FieldOffsets, Builder.NonVirtualSize,
+          Builder.Alignment, Builder.Alignment, CharUnits::Zero(),
           Builder.PrimaryBase, false, Builder.SharedVBPtrBase,
           Builder.EndsWithZeroSizedObject, Builder.LeadsWithZeroSizedBase,
           Builder.Bases, Builder.VBases);
@@ -3059,8 +3144,8 @@
       Builder.layout(D);
       NewEntry = new (*this) ASTRecordLayout(
           *this, Builder.Size, Builder.Alignment, Builder.Alignment,
-          Builder.RequiredAlignment,
-          Builder.Size, Builder.FieldOffsets);
+          Builder.Alignment, Builder.RequiredAlignment, Builder.Size,
+          Builder.FieldOffsets);
     }
   } else {
     if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
@@ -3080,11 +3165,13 @@
       CharUnits NonVirtualSize =
           skipTailPadding ? DataSize : Builder.NonVirtualSize;
       NewEntry = new (*this) ASTRecordLayout(
-          *this, Builder.getSize(), Builder.Alignment, Builder.UnadjustedAlignment,
+          *this, Builder.getSize(), Builder.Alignment,
+          Builder.PreferredAlignment, Builder.UnadjustedAlignment,
           /*RequiredAlignment : used by MS-ABI)*/
           Builder.Alignment, Builder.HasOwnVFPtr, RD->isDynamicClass(),
           CharUnits::fromQuantity(-1), DataSize, Builder.FieldOffsets,
           NonVirtualSize, Builder.NonVirtualAlignment,
+          Builder.PreferredNVAlignment,
           EmptySubobjects.SizeOfLargestEmptySubobject, Builder.PrimaryBase,
           Builder.PrimaryBaseIsVirtual, nullptr, false, false, Builder.Bases,
           Builder.VBases);
@@ -3093,7 +3180,8 @@
       Builder.Layout(D);
 
       NewEntry = new (*this) ASTRecordLayout(
-          *this, Builder.getSize(), Builder.Alignment, Builder.UnadjustedAlignment,
+          *this, Builder.getSize(), Builder.Alignment,
+          Builder.PreferredAlignment, Builder.UnadjustedAlignment,
           /*RequiredAlignment : used by MS-ABI)*/
           Builder.Alignment, Builder.getSize(), Builder.FieldOffsets);
     }
@@ -3245,14 +3333,11 @@
   ItaniumRecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/nullptr);
   Builder.Layout(D);
 
-  const ASTRecordLayout *NewEntry =
-    new (*this) ASTRecordLayout(*this, Builder.getSize(),
-                                Builder.Alignment,
-                                Builder.UnadjustedAlignment,
-                                /*RequiredAlignment : used by MS-ABI)*/
-                                Builder.Alignment,
-                                Builder.getDataSize(),
-                                Builder.FieldOffsets);
+  const ASTRecordLayout *NewEntry = new (*this) ASTRecordLayout(
+      *this, Builder.getSize(), Builder.Alignment, Builder.PreferredAlignment,
+      Builder.UnadjustedAlignment,
+      /*RequiredAlignment : used by MS-ABI)*/
+      Builder.Alignment, Builder.getDataSize(), Builder.FieldOffsets);
 
   ObjCLayouts[Key] = NewEntry;
 
@@ -3415,22 +3500,26 @@
   if (CXXRD && !isMsLayout(C))
     OS << ", dsize=" << Layout.getDataSize().getQuantity();
   OS << ", align=" << Layout.getAlignment().getQuantity();
+  if (isAIXLayout(C))
+    OS << ", preferredalign=" << Layout.getPreferredAlignment().getQuantity();
 
   if (CXXRD) {
     OS << ",\n";
     PrintIndentNoOffset(OS, IndentLevel - 1);
     OS << " nvsize=" << Layout.getNonVirtualSize().getQuantity();
     OS << ", nvalign=" << Layout.getNonVirtualAlignment().getQuantity();
+    if (isAIXLayout(C))
+      OS << ", preferrednvalign="
+         << Layout.getPreferredNVAlignment().getQuantity();
   }
   OS << "]\n";
 }
 
-void ASTContext::DumpRecordLayout(const RecordDecl *RD,
-                                  raw_ostream &OS,
+void ASTContext::DumpRecordLayout(const RecordDecl *RD, raw_ostream &OS,
                                   bool Simple) const {
   if (!Simple) {
     ::DumpRecordLayout(OS, RD, *this, CharUnits(), 0, nullptr,
-                       /*PrintSizeInfo*/true,
+                       /*PrintSizeInfo*/ true,
                        /*IncludeVirtualBases=*/true);
     return;
   }
@@ -3450,9 +3539,13 @@
   if (!isMsLayout(*this))
     OS << "  DataSize:" << toBits(Info.getDataSize()) << "\n";
   OS << "  Alignment:" << toBits(Info.getAlignment()) << "\n";
+  if (isAIXLayout(*this))
+    OS << "  PreferredAlignment:" << toBits(Info.getPreferredAlignment())
+       << "\n";
   OS << "  FieldOffsets: [";
   for (unsigned i = 0, e = Info.getFieldCount(); i != e; ++i) {
-    if (i) OS << ", ";
+    if (i)
+      OS << ", ";
     OS << Info.getFieldOffset(i);
   }
   OS << "]>\n";
Index: clang/lib/AST/RecordLayout.cpp
===================================================================
--- clang/lib/AST/RecordLayout.cpp
+++ clang/lib/AST/RecordLayout.cpp
@@ -29,45 +29,42 @@
 
 ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx, CharUnits size,
                                  CharUnits alignment,
+                                 CharUnits preferredAlignment,
                                  CharUnits unadjustedAlignment,
                                  CharUnits requiredAlignment,
                                  CharUnits datasize,
                                  ArrayRef<uint64_t> fieldoffsets)
     : Size(size), DataSize(datasize), Alignment(alignment),
+      PreferredAlignment(preferredAlignment),
       UnadjustedAlignment(unadjustedAlignment),
       RequiredAlignment(requiredAlignment) {
   FieldOffsets.append(Ctx, fieldoffsets.begin(), fieldoffsets.end());
 }
 
 // Constructor for C++ records.
-ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx,
-                                 CharUnits size, CharUnits alignment,
-                                 CharUnits unadjustedAlignment,
-                                 CharUnits requiredAlignment,
-                                 bool hasOwnVFPtr, bool hasExtendableVFPtr,
-                                 CharUnits vbptroffset,
-                                 CharUnits datasize,
-                                 ArrayRef<uint64_t> fieldoffsets,
-                                 CharUnits nonvirtualsize,
-                                 CharUnits nonvirtualalignment,
-                                 CharUnits SizeOfLargestEmptySubobject,
-                                 const CXXRecordDecl *PrimaryBase,
-                                 bool IsPrimaryBaseVirtual,
-                                 const CXXRecordDecl *BaseSharingVBPtr,
-                                 bool EndsWithZeroSizedObject,
-                                 bool LeadsWithZeroSizedBase,
-                                 const BaseOffsetsMapTy& BaseOffsets,
-                                 const VBaseOffsetsMapTy& VBaseOffsets)
-  : Size(size), DataSize(datasize), Alignment(alignment),
-    UnadjustedAlignment(unadjustedAlignment),
-    RequiredAlignment(requiredAlignment), CXXInfo(new (Ctx) CXXRecordLayoutInfo)
-{
+ASTRecordLayout::ASTRecordLayout(
+    const ASTContext &Ctx, CharUnits size, CharUnits alignment,
+    CharUnits preferredAlignment, CharUnits unadjustedAlignment,
+    CharUnits requiredAlignment, bool hasOwnVFPtr, bool hasExtendableVFPtr,
+    CharUnits vbptroffset, CharUnits datasize, ArrayRef<uint64_t> fieldoffsets,
+    CharUnits nonvirtualsize, CharUnits nonvirtualalignment,
+    CharUnits preferrednvalignment, CharUnits SizeOfLargestEmptySubobject,
+    const CXXRecordDecl *PrimaryBase, bool IsPrimaryBaseVirtual,
+    const CXXRecordDecl *BaseSharingVBPtr, bool EndsWithZeroSizedObject,
+    bool LeadsWithZeroSizedBase, const BaseOffsetsMapTy &BaseOffsets,
+    const VBaseOffsetsMapTy &VBaseOffsets)
+    : Size(size), DataSize(datasize), Alignment(alignment),
+      PreferredAlignment(preferredAlignment),
+      UnadjustedAlignment(unadjustedAlignment),
+      RequiredAlignment(requiredAlignment),
+      CXXInfo(new (Ctx) CXXRecordLayoutInfo) {
   FieldOffsets.append(Ctx, fieldoffsets.begin(), fieldoffsets.end());
 
   CXXInfo->PrimaryBase.setPointer(PrimaryBase);
   CXXInfo->PrimaryBase.setInt(IsPrimaryBaseVirtual);
   CXXInfo->NonVirtualSize = nonvirtualsize;
   CXXInfo->NonVirtualAlignment = nonvirtualalignment;
+  CXXInfo->PreferredNVAlignment = preferrednvalignment;
   CXXInfo->SizeOfLargestEmptySubobject = SizeOfLargestEmptySubobject;
   CXXInfo->BaseOffsets = BaseOffsets;
   CXXInfo->VBaseOffsets = VBaseOffsets;
Index: clang/lib/AST/ASTContext.cpp
===================================================================
--- clang/lib/AST/ASTContext.cpp
+++ clang/lib/AST/ASTContext.cpp
@@ -2393,6 +2393,12 @@
   if (T->isMemberPointerType())
     return getPreferredTypeAlign(getPointerDiffType().getTypePtr());
 
+  if (const auto *RT = T->getAs<RecordType>()) {
+    const RecordDecl *RD = RT->getDecl();
+    return std::max(
+        ABIAlign, (unsigned)toBits(getASTRecordLayout(RD).PreferredAlignment));
+  }
+
   if (!Target->allowsLargerPreferedTypeAlignment())
     return ABIAlign;
 
@@ -2403,7 +2409,9 @@
     T = ET->getDecl()->getIntegerType().getTypePtr();
   if (T->isSpecificBuiltinType(BuiltinType::Double) ||
       T->isSpecificBuiltinType(BuiltinType::LongLong) ||
-      T->isSpecificBuiltinType(BuiltinType::ULongLong))
+      T->isSpecificBuiltinType(BuiltinType::ULongLong) ||
+      (T->isSpecificBuiltinType(BuiltinType::LongDouble) &&
+       Target->supportsAIXPowerAlignment()))
     // Don't increase the alignment if an alignment attribute was specified on a
     // typedef declaration.
     if (!TI.AlignIsRequired)
Index: clang/include/clang/Basic/TargetInfo.h
===================================================================
--- clang/include/clang/Basic/TargetInfo.h
+++ clang/include/clang/Basic/TargetInfo.h
@@ -1371,6 +1371,9 @@
   /// Whether target allows to overalign ABI-specified preferred alignment
   virtual bool allowsLargerPreferedTypeAlignment() const { return true; }
 
+  /// Whether target supports the special power alignment rules of AIX.
+  virtual bool supportsAIXPowerAlignment() const { return false; }
+
   /// Set supported OpenCL extensions and optional core features.
   virtual void setSupportedOpenCLOpts() {}
 
Index: clang/include/clang/AST/RecordLayout.h
===================================================================
--- clang/include/clang/AST/RecordLayout.h
+++ clang/include/clang/AST/RecordLayout.h
@@ -70,6 +70,11 @@
   // Alignment - Alignment of record in characters.
   CharUnits Alignment;
 
+  // PreferredAlignment - Preferred alignment of record in characters. This
+  // can be different than Alignment in cases where it is beneficial for
+  // performance.
+  CharUnits PreferredAlignment;
+
   // UnadjustedAlignment - Maximum of the alignments of the record members in
   // characters.
   CharUnits UnadjustedAlignment;
@@ -91,6 +96,11 @@
     /// which is the alignment of the object without virtual bases.
     CharUnits NonVirtualAlignment;
 
+    /// PreferredNVAlignment - The preferred non-virtual alignment (in chars) of
+    /// an object, which is the preferred alignment of the object without
+    /// virtual bases.
+    CharUnits PreferredNVAlignment;
+
     /// SizeOfLargestEmptySubobject - The size of the largest empty subobject
     /// (either a base or a member). Will be zero if the class doesn't contain
     /// any empty subobjects.
@@ -139,30 +149,26 @@
   CXXRecordLayoutInfo *CXXInfo = nullptr;
 
   ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment,
-                  CharUnits unadjustedAlignment,
+                  CharUnits preferredAlignment, CharUnits unadjustedAlignment,
                   CharUnits requiredAlignment, CharUnits datasize,
                   ArrayRef<uint64_t> fieldoffsets);
 
   using BaseOffsetsMapTy = CXXRecordLayoutInfo::BaseOffsetsMapTy;
 
   // Constructor for C++ records.
-  ASTRecordLayout(const ASTContext &Ctx,
-                  CharUnits size, CharUnits alignment,
-                  CharUnits unadjustedAlignment,
-                  CharUnits requiredAlignment,
-                  bool hasOwnVFPtr, bool hasExtendableVFPtr,
-                  CharUnits vbptroffset,
-                  CharUnits datasize,
-                  ArrayRef<uint64_t> fieldoffsets,
+  ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment,
+                  CharUnits preferredAlignment, CharUnits unadjustedAlignment,
+                  CharUnits requiredAlignment, bool hasOwnVFPtr,
+                  bool hasExtendableVFPtr, CharUnits vbptroffset,
+                  CharUnits datasize, ArrayRef<uint64_t> fieldoffsets,
                   CharUnits nonvirtualsize, CharUnits nonvirtualalignment,
+                  CharUnits preferrednvalignment,
                   CharUnits SizeOfLargestEmptySubobject,
-                  const CXXRecordDecl *PrimaryBase,
-                  bool IsPrimaryBaseVirtual,
+                  const CXXRecordDecl *PrimaryBase, bool IsPrimaryBaseVirtual,
                   const CXXRecordDecl *BaseSharingVBPtr,
-                  bool EndsWithZeroSizedObject,
-                  bool LeadsWithZeroSizedBase,
-                  const BaseOffsetsMapTy& BaseOffsets,
-                  const VBaseOffsetsMapTy& VBaseOffsets);
+                  bool EndsWithZeroSizedObject, bool LeadsWithZeroSizedBase,
+                  const BaseOffsetsMapTy &BaseOffsets,
+                  const VBaseOffsetsMapTy &VBaseOffsets);
 
   ~ASTRecordLayout() = default;
 
@@ -175,6 +181,10 @@
   /// getAlignment - Get the record alignment in characters.
   CharUnits getAlignment() const { return Alignment; }
 
+  /// getPreferredFieldAlignment - Get the record preferred alignment in
+  /// characters.
+  CharUnits getPreferredAlignment() const { return PreferredAlignment; }
+
   /// getUnadjustedAlignment - Get the record alignment in characters, before
   /// alignment adjustement.
   CharUnits getUnadjustedAlignment() const { return UnadjustedAlignment; }
@@ -193,9 +203,7 @@
 
   /// getDataSize() - Get the record data size, which is the record size
   /// without tail padding, in characters.
-  CharUnits getDataSize() const {
-    return DataSize;
-  }
+  CharUnits getDataSize() const { return DataSize; }
 
   /// getNonVirtualSize - Get the non-virtual size (in chars) of an object,
   /// which is the size of the object without virtual bases.
@@ -205,14 +213,23 @@
     return CXXInfo->NonVirtualSize;
   }
 
-  /// getNonVirtualSize - Get the non-virtual alignment (in chars) of an object,
-  /// which is the alignment of the object without virtual bases.
+  /// getNonVirtualAlignment - Get the non-virtual alignment (in chars) of an
+  /// object, which is the alignment of the object without virtual bases.
   CharUnits getNonVirtualAlignment() const {
     assert(CXXInfo && "Record layout does not have C++ specific info!");
 
     return CXXInfo->NonVirtualAlignment;
   }
 
+  /// getPreferredNVAlignment - Get the preferred non-virtual alignment (in
+  /// chars) of an object, which is the preferred alignment of the object
+  /// without virtual bases.
+  CharUnits getPreferredNVAlignment() const {
+    assert(CXXInfo && "Record layout does not have C++ specific info!");
+
+    return CXXInfo->PreferredNVAlignment;
+  }
+
   /// getPrimaryBase - Get the primary base for this record.
   const CXXRecordDecl *getPrimaryBase() const {
     assert(CXXInfo && "Record layout does not have C++ specific info!");
@@ -287,9 +304,7 @@
     return !CXXInfo->VBPtrOffset.isNegative();
   }
 
-  CharUnits getRequiredAlignment() const {
-    return RequiredAlignment;
-  }
+  CharUnits getRequiredAlignment() const { return RequiredAlignment; }
 
   bool endsWithZeroSizedObject() const {
     return CXXInfo && CXXInfo->EndsWithZeroSizedObject;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to