Xiangling_L updated this revision to Diff 292207.
Xiangling_L added a comment.

Use default argument;


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

https://reviews.llvm.org/D86790

Files:
  clang/include/clang/AST/ASTContext.h
  clang/lib/AST/ASTContext.cpp
  clang/lib/CodeGen/CGExprCXX.cpp
  clang/lib/CodeGen/ItaniumCXXABI.cpp
  clang/lib/CodeGen/TargetInfo.cpp
  clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
  clang/test/CodeGen/aix-alignment.c
  clang/test/CodeGenCXX/aix-alignment.cpp

Index: clang/test/CodeGenCXX/aix-alignment.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGenCXX/aix-alignment.cpp
@@ -0,0 +1,30 @@
+// REQUIRES: powerpc-registered-target
+// RUN: %clang_cc1 -triple powerpc-unknown-aix \
+// RUN:     -emit-llvm -o - -x c++ %s | \
+// RUN:   FileCheck %s --check-prefixes=AIX,AIX32
+// RUN: %clang_cc1 -triple powerpc64-unknown-aix \
+// RUN:     -emit-llvm -o - %s -x c++| \
+// RUN:   FileCheck %s --check-prefixes=AIX,AIX64
+
+struct B {
+  double d;
+  ~B() {}
+};
+
+// AIX32: %call = call noalias nonnull i8* @_Znam(i32 8)
+// AIX64: %call = call noalias nonnull i8* @_Znam(i64 8)
+B *allocBp() { return new B[0]; }
+
+typedef struct D {
+  double d;
+  int i;
+
+  ~D(){};
+} D;
+
+// AIX: define void @_Z3foo1D(%struct.D* noalias sret align 4 %agg.result, %struct.D* %x)
+// AIX:   %1 = bitcast %struct.D* %agg.result to i8*
+// AIX:   %2 = bitcast %struct.D* %x to i8*
+// AIX32  call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %1, i8* align 4 %2, i32 16, i1 false)
+// AIX64: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %1, i8* align 4 %2, i64 16, i1 false)
+D foo(D x) { return x; }
Index: clang/test/CodeGen/aix-alignment.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/aix-alignment.c
@@ -0,0 +1,41 @@
+// REQUIRES: powerpc-registered-target
+// RUN: %clang_cc1 -triple powerpc-unknown-aix -emit-llvm -o - %s | \
+// RUN:   FileCheck %s --check-prefixes=AIX,AIX32
+// RUN: %clang_cc1 -triple powerpc64-unknown-aix -emit-llvm -o - %s | \
+// RUN:   FileCheck %s --check-prefixes=AIX,AIX64
+
+// AIX: @d = global double 0.000000e+00, align 8
+double d;
+
+typedef struct {
+  double d;
+  int i;
+} StructDouble;
+
+// AIX: @d1 = global %struct.StructDouble zeroinitializer, align 8
+StructDouble d1;
+
+// AIX: double @retDouble(double %x)
+// AIX: %x.addr = alloca double, align 8
+// AIX: store double %x, double* %x.addr, align 8
+// AIX: load double, double* %x.addr, align 8
+// AIX: ret double %0
+double retDouble(double x) { return x; }
+
+// AIX32: define void @bar(%struct.StructDouble* noalias sret align 4 %agg.result, %struct.StructDouble* byval(%struct.StructDouble) align 4 %x)
+// AIX64: define void @bar(%struct.StructDouble* noalias sret align 4 %agg.result, %struct.StructDouble* byval(%struct.StructDouble) align 8 %x)
+// AIX:     %0 = bitcast %struct.StructDouble* %agg.result to i8*
+// AIX:     %1 = bitcast %struct.StructDouble* %x to i8*
+// AIX32:   call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %0, i8* align 4 %1, i32 16, i1 false)
+// AIX64:   call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %0, i8* align 8 %1, i64 16, i1 false)
+StructDouble bar(StructDouble x) { return x; }
+
+// AIX:   define void @foo(double* %out, double* %in)
+// AIX32:   %0 = load double*, double** %in.addr, align 4
+// AIX64:   %0 = load double*, double** %in.addr, align 8
+// AIX:     %1 = load double, double* %0, align 4
+// AIX:     %mul = fmul double %1, 2.000000e+00
+// AIX32:   %2 = load double*, double** %out.addr, align 4
+// AIX64:   %2 = load double*, double** %out.addr, align 8
+// AIX:     store double %mul, double* %2, align 4
+void foo(double *out, double *in) { *out = *in * 2; }
Index: clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
@@ -248,8 +248,8 @@
       FieldInfo RetVal;
       RetVal.Field = FD;
       auto &Ctx = FD->getASTContext();
-      std::tie(RetVal.Size, RetVal.Align) =
-          Ctx.getTypeInfoInChars(FD->getType());
+      std::tie(RetVal.Size, RetVal.Align) = Ctx.getTypeInfoInChars(
+          FD->getType(), true /* NeedsPreferredAlignment */);
       assert(llvm::isPowerOf2_64(RetVal.Align.getQuantity()));
       if (auto Max = FD->getMaxAlignment())
         RetVal.Align = std::max(Ctx.toCharUnitsFromBits(Max), RetVal.Align);
Index: clang/lib/CodeGen/TargetInfo.cpp
===================================================================
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -349,7 +349,8 @@
 ///
 /// \param IsIndirect - Values of this type are passed indirectly.
 /// \param ValueInfo - The size and alignment of this type, generally
-///   computed with getContext().getTypeInfoInChars(ValueTy).
+///   computed with getContext().getTypeInfoInChars(ValueTy,
+///   NeedsPreferredAlignment).
 /// \param SlotSizeAndAlign - The size and alignment of a stack slot.
 ///   Each argument will be allocated to a multiple of this number of
 ///   slots, and all the slots will be aligned to this value.
@@ -4512,8 +4513,6 @@
   if (RetTy->isVoidType())
     return ABIArgInfo::getIgnore();
 
-  // TODO:  Evaluate if AIX power alignment rule would have an impact on the
-  // alignment here.
   if (isAggregateTypeForABI(RetTy))
     return getNaturalAlignIndirect(RetTy);
 
@@ -4530,8 +4529,6 @@
   if (Ty->isVectorType())
     llvm::report_fatal_error("vector type is not supported on AIX yet");
 
-  // TODO:  Evaluate if AIX power alignment rule would have an impact on the
-  // alignment here.
   if (isAggregateTypeForABI(Ty)) {
     // Records with non-trivial destructors/copy-constructors should not be
     // passed by value.
Index: clang/lib/CodeGen/ItaniumCXXABI.cpp
===================================================================
--- clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -2111,7 +2111,8 @@
   // The array cookie is a size_t; pad that up to the element alignment.
   // The cookie is actually right-justified in that space.
   return std::max(CharUnits::fromQuantity(CGM.SizeSizeInBytes),
-                  CGM.getContext().getTypeAlignInChars(elementType));
+                  CGM.getContext().getTypeAlignInChars(
+                      elementType, true /* NeedsPreferredAlignment */));
 }
 
 Address ItaniumCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
@@ -2127,8 +2128,9 @@
   CharUnits SizeSize = CGF.getSizeSize();
 
   // The size of the cookie.
-  CharUnits CookieSize =
-    std::max(SizeSize, Ctx.getTypeAlignInChars(ElementType));
+  CharUnits CookieSize = std::max(
+      SizeSize,
+      Ctx.getTypeAlignInChars(ElementType, true /* NeedsPreferredAlignment */));
   assert(CookieSize == getArrayCookieSizeImpl(ElementType));
 
   // Compute an offset to the cookie.
Index: clang/lib/CodeGen/CGExprCXX.cpp
===================================================================
--- clang/lib/CodeGen/CGExprCXX.cpp
+++ clang/lib/CodeGen/CGExprCXX.cpp
@@ -1570,7 +1570,8 @@
   llvm::Value *allocSize =
     EmitCXXNewAllocSize(*this, E, minElements, numElements,
                         allocSizeWithoutCookie);
-  CharUnits allocAlign = getContext().getTypeAlignInChars(allocType);
+  CharUnits allocAlign = getContext().getTypeAlignInChars(
+      allocType, true /* NeedsPreferredAlignment */);
 
   // Emit the allocation call.  If the allocator is a global placement
   // operator, just "inline" it directly.
@@ -1820,8 +1821,9 @@
   // Pass the alignment if the delete function has an align_val_t parameter.
   if (Params.Alignment) {
     QualType AlignValType = *ParamTypeIt++;
-    CharUnits DeleteTypeAlign = getContext().toCharUnitsFromBits(
-        getContext().getTypeAlignIfKnown(DeleteTy));
+    CharUnits DeleteTypeAlign =
+        getContext().toCharUnitsFromBits(getContext().getTypeAlignIfKnown(
+            DeleteTy, true /* NeedsPreferredAlignment */));
     llvm::Value *Align = llvm::ConstantInt::get(ConvertType(AlignValType),
                                                 DeleteTypeAlign.getQuantity());
     DeleteArgs.add(RValue::get(Align), AlignValType);
Index: clang/lib/AST/ASTContext.cpp
===================================================================
--- clang/lib/AST/ASTContext.cpp
+++ clang/lib/AST/ASTContext.cpp
@@ -1796,11 +1796,11 @@
 
 /// getConstantArrayInfoInChars - Performing the computation in CharUnits
 /// instead of in bits prevents overflowing the uint64_t for some large arrays.
-std::pair<CharUnits, CharUnits>
-static getConstantArrayInfoInChars(const ASTContext &Context,
-                                   const ConstantArrayType *CAT) {
-  std::pair<CharUnits, CharUnits> EltInfo =
-      Context.getTypeInfoInChars(CAT->getElementType());
+std::pair<CharUnits, CharUnits> static getConstantArrayInfoInChars(
+    const ASTContext &Context, const ConstantArrayType *CAT,
+    bool NeedsPreferredAlignment) {
+  std::pair<CharUnits, CharUnits> EltInfo = Context.getTypeInfoInChars(
+      CAT->getElementType(), NeedsPreferredAlignment);
   uint64_t Size = CAT->getSize().getZExtValue();
   assert((Size == 0 || static_cast<uint64_t>(EltInfo.first.getQuantity()) <=
               (uint64_t)(-1)/Size) &&
@@ -1815,17 +1815,18 @@
 }
 
 std::pair<CharUnits, CharUnits>
-ASTContext::getTypeInfoInChars(const Type *T) const {
+ASTContext::getTypeInfoInChars(const Type *T,
+                               bool NeedsPreferredAlignment) const {
   if (const auto *CAT = dyn_cast<ConstantArrayType>(T))
-    return getConstantArrayInfoInChars(*this, CAT);
-  TypeInfo Info = getTypeInfo(T);
+    return getConstantArrayInfoInChars(*this, CAT, NeedsPreferredAlignment);
+  TypeInfo Info = getTypeInfo(T, NeedsPreferredAlignment);
   return std::make_pair(toCharUnitsFromBits(Info.Width),
                         toCharUnitsFromBits(Info.Align));
 }
 
 std::pair<CharUnits, CharUnits>
-ASTContext::getTypeInfoInChars(QualType T) const {
-  return getTypeInfoInChars(T.getTypePtr());
+ASTContext::getTypeInfoInChars(QualType T, bool NeedsPreferredAlignment) const {
+  return getTypeInfoInChars(T.getTypePtr(), NeedsPreferredAlignment);
 }
 
 bool ASTContext::isAlignmentRequired(const Type *T) const {
@@ -1836,7 +1837,8 @@
   return isAlignmentRequired(T.getTypePtr());
 }
 
-unsigned ASTContext::getTypeAlignIfKnown(QualType T) const {
+unsigned ASTContext::getTypeAlignIfKnown(QualType T,
+                                         bool NeedsPreferredAlignment) const {
   // An alignment on a typedef overrides anything else.
   if (const auto *TT = T->getAs<TypedefType>())
     if (unsigned Align = TT->getDecl()->getMaxAlignment())
@@ -1845,7 +1847,7 @@
   // If we have an (array of) complete type, we're done.
   T = getBaseElementType(T);
   if (!T->isIncompleteType())
-    return getTypeAlign(T);
+    return getTypeAlign(T, NeedsPreferredAlignment);
 
   // If we had an array type, its element type might be a typedef
   // type with an alignment attribute.
@@ -1860,28 +1862,44 @@
   return 0;
 }
 
-TypeInfo ASTContext::getTypeInfo(const Type *T) const {
-  TypeInfoMap::iterator I = MemoizedTypeInfo.find(T);
-  if (I != MemoizedTypeInfo.end())
-    return I->second;
+TypeInfo ASTContext::getTypeInfo(const Type *T,
+                                 bool NeedsPreferredAlignment) const {
+  auto getTypeInfo = [&](auto &TIMap) {
+    TypeInfoMap::iterator I = TIMap.find(T);
+    if (I != TIMap.end())
+      return I->second;
 
-  // This call can invalidate MemoizedTypeInfo[T], so we need a second lookup.
-  TypeInfo TI = getTypeInfoImpl(T);
-  MemoizedTypeInfo[T] = TI;
-  return TI;
+    // This call can invalidate MemoizedTypeInfo[T], so we need a second lookup.
+    TypeInfo TI = getTypeInfoImpl(T, NeedsPreferredAlignment);
+    TIMap[T] = TI;
+    return TI;
+  };
+
+  return NeedsPreferredAlignment ? getTypeInfo(MemoizedPreferredTypeInfo)
+                                 : getTypeInfo(MemoizedTypeInfo);
 }
 
 /// getTypeInfoImpl - Return the size of the specified type, in bits.  This
 /// method does not work on incomplete types.
 ///
+/// Set "NeedsPreferredAlignment" as true only when allocating memory for a
+/// variable on the stack or in global/thread local memory. The preferred
+/// alignment applies only to a complete object.
+///
 /// FIXME: Pointers into different addr spaces could have different sizes and
 /// alignment requirements: getPointerInfo should take an AddrSpace, this
 /// should take a QualType, &c.
-TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
+TypeInfo ASTContext::getTypeInfoImpl(const Type *T,
+                                     bool NeedsPreferredAlignment) const {
   uint64_t Width = 0;
   unsigned Align = 8;
   bool AlignIsRequired = false;
   unsigned AS = 0;
+
+  auto setAlign = [&](unsigned PreferredAlignment, unsigned Alignment) {
+    Align = NeedsPreferredAlignment ? PreferredAlignment : Alignment;
+  };
+
   switch (T->getTypeClass()) {
 #define TYPE(Class, Base)
 #define ABSTRACT_TYPE(Class, Base)
@@ -1889,8 +1907,9 @@
 #define DEPENDENT_TYPE(Class, Base) case Type::Class:
 #define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base)                       \
   case Type::Class:                                                            \
-  assert(!T->isDependentType() && "should not see dependent types here");      \
-  return getTypeInfo(cast<Class##Type>(T)->desugar().getTypePtr());
+    assert(!T->isDependentType() && "should not see dependent types here");    \
+    return getTypeInfo(cast<Class##Type>(T)->desugar().getTypePtr(),           \
+                       NeedsPreferredAlignment);
 #include "clang/AST/TypeNodes.inc"
     llvm_unreachable("Should not see dependent types");
 
@@ -1909,7 +1928,8 @@
     if (const auto *CAT = dyn_cast<ConstantArrayType>(T))
       Size = CAT->getSize().getZExtValue();
 
-    TypeInfo EltInfo = getTypeInfo(cast<ArrayType>(T)->getElementType());
+    TypeInfo EltInfo = getTypeInfo(cast<ArrayType>(T)->getElementType(),
+                                   NeedsPreferredAlignment);
     assert((Size == 0 || EltInfo.Width <= (uint64_t)(-1) / Size) &&
            "Overflow in array type bit size evaluation");
     Width = EltInfo.Width * Size;
@@ -1924,7 +1944,8 @@
   case Type::ExtVector:
   case Type::Vector: {
     const auto *VT = cast<VectorType>(T);
-    TypeInfo EltInfo = getTypeInfo(VT->getElementType());
+    TypeInfo EltInfo =
+        getTypeInfo(VT->getElementType(), NeedsPreferredAlignment);
     Width = EltInfo.Width * VT->getNumElements();
     Align = Width;
     // If the alignment is not a power of 2, round up to the next power of 2.
@@ -1949,7 +1970,8 @@
 
   case Type::ConstantMatrix: {
     const auto *MT = cast<ConstantMatrixType>(T);
-    TypeInfo ElementInfo = getTypeInfo(MT->getElementType());
+    TypeInfo ElementInfo =
+        getTypeInfo(MT->getElementType(), NeedsPreferredAlignment);
     // The internal layout of a matrix value is implementation defined.
     // Initially be ABI compatible with arrays with respect to alignment and
     // size.
@@ -2081,17 +2103,17 @@
       break;
     case BuiltinType::Double:
       Width = Target->getDoubleWidth();
-      Align = Target->getDoubleAlign();
+      setAlign(Width, Target->getDoubleAlign());
       break;
     case BuiltinType::LongDouble:
       if (getLangOpts().OpenMP && getLangOpts().OpenMPIsDevice &&
           (Target->getLongDoubleWidth() != AuxTarget->getLongDoubleWidth() ||
            Target->getLongDoubleAlign() != AuxTarget->getLongDoubleAlign())) {
         Width = AuxTarget->getLongDoubleWidth();
-        Align = AuxTarget->getLongDoubleAlign();
+        setAlign(Width, AuxTarget->getLongDoubleAlign());
       } else {
         Width = Target->getLongDoubleWidth();
-        Align = Target->getLongDoubleAlign();
+        setAlign(Width, Target->getLongDoubleAlign());
       }
       break;
     case BuiltinType::Float128:
@@ -2186,16 +2208,19 @@
   case Type::Complex: {
     // Complex types have the same alignment as their elements, but twice the
     // size.
-    TypeInfo EltInfo = getTypeInfo(cast<ComplexType>(T)->getElementType());
+    TypeInfo EltInfo = getTypeInfo(cast<ComplexType>(T)->getElementType(),
+                                   NeedsPreferredAlignment);
     Width = EltInfo.Width * 2;
     Align = EltInfo.Align;
     break;
   }
   case Type::ObjCObject:
-    return getTypeInfo(cast<ObjCObjectType>(T)->getBaseType().getTypePtr());
+    return getTypeInfo(cast<ObjCObjectType>(T)->getBaseType().getTypePtr(),
+                       NeedsPreferredAlignment);
   case Type::Adjusted:
   case Type::Decayed:
-    return getTypeInfo(cast<AdjustedType>(T)->getAdjustedType().getTypePtr());
+    return getTypeInfo(cast<AdjustedType>(T)->getAdjustedType().getTypePtr(),
+                       NeedsPreferredAlignment);
   case Type::ObjCInterface: {
     const auto *ObjCI = cast<ObjCInterfaceType>(T);
     if (ObjCI->getDecl()->isInvalidDecl()) {
@@ -2230,7 +2255,8 @@
     if (const auto *ET = dyn_cast<EnumType>(TT)) {
       const EnumDecl *ED = ET->getDecl();
       TypeInfo Info =
-          getTypeInfo(ED->getIntegerType()->getUnqualifiedDesugaredType());
+          getTypeInfo(ED->getIntegerType()->getUnqualifiedDesugaredType(),
+                      NeedsPreferredAlignment);
       if (unsigned AttrAlign = ED->getMaxAlignment()) {
         Info.Align = AttrAlign;
         Info.AlignIsRequired = true;
@@ -2242,36 +2268,43 @@
     const RecordDecl *RD = RT->getDecl();
     const ASTRecordLayout &Layout = getASTRecordLayout(RD);
     Width = toBits(Layout.getSize());
-    Align = toBits(Layout.getAlignment());
+    setAlign(toBits(Layout.getPreferredAlignment()),
+             toBits(Layout.getAlignment()));
     AlignIsRequired = RD->hasAttr<AlignedAttr>();
     break;
   }
 
   case Type::SubstTemplateTypeParm:
-    return getTypeInfo(cast<SubstTemplateTypeParmType>(T)->
-                       getReplacementType().getTypePtr());
+    return getTypeInfo(
+        cast<SubstTemplateTypeParmType>(T)->getReplacementType().getTypePtr(),
+        NeedsPreferredAlignment);
 
   case Type::Auto:
   case Type::DeducedTemplateSpecialization: {
     const auto *A = cast<DeducedType>(T);
     assert(!A->getDeducedType().isNull() &&
            "cannot request the size of an undeduced or dependent auto type");
-    return getTypeInfo(A->getDeducedType().getTypePtr());
+    return getTypeInfo(A->getDeducedType().getTypePtr(),
+                       NeedsPreferredAlignment);
   }
 
   case Type::Paren:
-    return getTypeInfo(cast<ParenType>(T)->getInnerType().getTypePtr());
+    return getTypeInfo(cast<ParenType>(T)->getInnerType().getTypePtr(),
+                       NeedsPreferredAlignment);
 
   case Type::MacroQualified:
     return getTypeInfo(
-        cast<MacroQualifiedType>(T)->getUnderlyingType().getTypePtr());
+        cast<MacroQualifiedType>(T)->getUnderlyingType().getTypePtr(),
+        NeedsPreferredAlignment);
 
   case Type::ObjCTypeParam:
-    return getTypeInfo(cast<ObjCTypeParamType>(T)->desugar().getTypePtr());
+    return getTypeInfo(cast<ObjCTypeParamType>(T)->desugar().getTypePtr(),
+                       NeedsPreferredAlignment);
 
   case Type::Typedef: {
     const TypedefNameDecl *Typedef = cast<TypedefType>(T)->getDecl();
-    TypeInfo Info = getTypeInfo(Typedef->getUnderlyingType().getTypePtr());
+    TypeInfo Info = getTypeInfo(Typedef->getUnderlyingType().getTypePtr(),
+                                NeedsPreferredAlignment);
     // If the typedef has an aligned attribute on it, it overrides any computed
     // alignment we have.  This violates the GCC documentation (which says that
     // attribute(aligned) can only round up) but matches its implementation.
@@ -2287,15 +2320,18 @@
   }
 
   case Type::Elaborated:
-    return getTypeInfo(cast<ElaboratedType>(T)->getNamedType().getTypePtr());
+    return getTypeInfo(cast<ElaboratedType>(T)->getNamedType().getTypePtr(),
+                       NeedsPreferredAlignment);
 
   case Type::Attributed:
     return getTypeInfo(
-                  cast<AttributedType>(T)->getEquivalentType().getTypePtr());
+        cast<AttributedType>(T)->getEquivalentType().getTypePtr(),
+        NeedsPreferredAlignment);
 
   case Type::Atomic: {
     // Start with the base type information.
-    TypeInfo Info = getTypeInfo(cast<AtomicType>(T)->getValueType());
+    TypeInfo Info = getTypeInfo(cast<AtomicType>(T)->getValueType(),
+                                NeedsPreferredAlignment);
     Width = Info.Width;
     Align = Info.Align;
 
@@ -2380,13 +2416,17 @@
   return getTypeInfoInChars(T).first;
 }
 
-/// getTypeAlignInChars - Return the ABI-specified alignment of a type, in
-/// characters. This method does not work on incomplete types.
-CharUnits ASTContext::getTypeAlignInChars(QualType T) const {
-  return toCharUnitsFromBits(getTypeAlign(T));
+/// getTypeAlignInChars - Set "NeedsPreferredAlignment" as true to return the
+/// preferred alignment of a complete type \p T only when allocating memory for
+/// a variable on the the stack or in global/thread local memory. Otherwise,
+/// return the ABI-specified alignment of a (complete) type \p T, in characters.
+CharUnits ASTContext::getTypeAlignInChars(QualType T,
+                                          bool NeedsPreferredAlignment) const {
+  return toCharUnitsFromBits(getTypeAlign(T, NeedsPreferredAlignment));
 }
-CharUnits ASTContext::getTypeAlignInChars(const Type *T) const {
-  return toCharUnitsFromBits(getTypeAlign(T));
+CharUnits ASTContext::getTypeAlignInChars(const Type *T,
+                                          bool NeedsPreferredAlignment) const {
+  return toCharUnitsFromBits(getTypeAlign(T, NeedsPreferredAlignment));
 }
 
 /// getTypeUnadjustedAlignInChars - Return the ABI-specified alignment of a
@@ -2458,7 +2498,8 @@
 /// to a global variable of the specified type.
 unsigned ASTContext::getAlignOfGlobalVar(QualType T) const {
   uint64_t TypeSize = getTypeSize(T.getTypePtr());
-  return std::max(getTypeAlign(T), getTargetInfo().getMinGlobalAlign(TypeSize));
+  return std::max(getTypeAlign(T, true /* NeedsPreferredAlignment */),
+                  getTargetInfo().getMinGlobalAlign(TypeSize));
 }
 
 /// getAlignOfGlobalVarInChars - Return the alignment in characters that
Index: clang/include/clang/AST/ASTContext.h
===================================================================
--- clang/include/clang/AST/ASTContext.h
+++ clang/include/clang/AST/ASTContext.h
@@ -253,9 +253,11 @@
   mutable llvm::DenseMap<const ObjCContainerDecl*, const ASTRecordLayout*>
     ObjCLayouts;
 
-  /// A cache from types to size and alignment information.
   using TypeInfoMap = llvm::DenseMap<const Type *, struct TypeInfo>;
+  /// A cache from types to size and ABI-specified alignment information.
   mutable TypeInfoMap MemoizedTypeInfo;
+  /// /// A cache from types to size and preferred alignment information.
+  mutable TypeInfoMap MemoizedPreferredTypeInfo;
 
   /// A cache from types to unadjusted alignment information. Only ARM and
   /// AArch64 targets need this information, keeping it separate prevents
@@ -2040,7 +2042,8 @@
 
 private:
   CanQualType getFromTargetType(unsigned Type) const;
-  TypeInfo getTypeInfoImpl(const Type *T) const;
+  TypeInfo getTypeInfoImpl(const Type *T,
+                           bool NeedsPreferredAlignment = false) const;
 
   //===--------------------------------------------------------------------===//
   //                         Type Predicates.
@@ -2083,8 +2086,14 @@
   const llvm::fltSemantics &getFloatTypeSemantics(QualType T) const;
 
   /// Get the size and alignment of the specified complete type in bits.
-  TypeInfo getTypeInfo(const Type *T) const;
-  TypeInfo getTypeInfo(QualType T) const { return getTypeInfo(T.getTypePtr()); }
+  /// Set "NeedsPreferredAlignment" as true to return the preferred alignment
+  /// when allocating memory for a variable on the stack or in global/thread
+  /// local memory. Otherwise, return the ABI-specified alignment.
+  TypeInfo getTypeInfo(const Type *T,
+                       bool NeedsPreferredAlignment = false) const;
+  TypeInfo getTypeInfo(QualType T, bool NeedsPreferredAlignment = false) const {
+    return getTypeInfo(T.getTypePtr(), NeedsPreferredAlignment);
+  }
 
   /// Get default simd alignment of the specified complete type in bits.
   unsigned getOpenMPDefaultSimdAlign(QualType T) const;
@@ -2119,10 +2128,23 @@
     return getTypeSizeInCharsIfKnown(QualType(Ty, 0));
   }
 
-  /// Return the ABI-specified alignment of a (complete) type \p T, in
-  /// bits.
-  unsigned getTypeAlign(QualType T) const { return getTypeInfo(T).Align; }
-  unsigned getTypeAlign(const Type *T) const { return getTypeInfo(T).Align; }
+  /// Returns the bitwidth of \p T, an SVE type attributed with
+  /// 'arm_sve_vector_bits'. Should only be called if T->isVLST().
+  unsigned getBitwidthForAttributedSveType(const Type *T) const;
+
+  /// Set "NeedsPreferredAlignment" as true to return the preferred alignment
+  /// of a complete type \p T only when allocating memory for a variable on the
+  /// the stack or in global/thread local memory.
+  /// Otherwise, return the ABI-specified alignment of a (complete) type \p T,
+  /// in bits.
+  unsigned getTypeAlign(QualType T,
+                        bool NeedsPreferredAlignment = false) const {
+    return getTypeInfo(T, NeedsPreferredAlignment).Align;
+  }
+  unsigned getTypeAlign(const Type *T,
+                        bool NeedsPreferredAlignment = false) const {
+    return getTypeInfo(T, NeedsPreferredAlignment).Align;
+  }
 
   /// Return the ABI-specified natural alignment of a (complete) type \p T,
   /// before alignment adjustments, in bits.
@@ -2134,15 +2156,24 @@
   }
   unsigned getTypeUnadjustedAlign(const Type *T) const;
 
-  /// Return the ABI-specified alignment of a type, in bits, or 0 if
-  /// the type is incomplete and we cannot determine the alignment (for
-  /// example, from alignment attributes).
-  unsigned getTypeAlignIfKnown(QualType T) const;
-
-  /// Return the ABI-specified alignment of a (complete) type \p T, in
-  /// characters.
-  CharUnits getTypeAlignInChars(QualType T) const;
-  CharUnits getTypeAlignInChars(const Type *T) const;
+  /// Set "NeedsPreferredAlignment" as true to return the preferred alignment
+  /// of a complete type \p T only when allocating memory for a variable on the
+  /// the stack or in global/thread local memory. Otherwise, return the
+  /// ABI-specified alignment of a (complete) type \p T, in bits. Return 0 if
+  /// the type is incomplete and we cannot determine the alignment (for example,
+  /// from alignment attributes).
+  unsigned getTypeAlignIfKnown(QualType T,
+                               bool NeedsPreferredAlignment = false) const;
+
+  /// Set "NeedsPreferredAlignment" as true to return the preferred alignment
+  /// of a complete type \p T only when allocating memory for a variable on the
+  /// the stack or in global/thread local memory.
+  /// Otherwise, return the ABI-specified alignment of a (complete) type \p T,
+  /// in characters.
+  CharUnits getTypeAlignInChars(QualType T,
+                                bool NeedsPreferredAlignment = false) const;
+  CharUnits getTypeAlignInChars(const Type *T,
+                                bool NeedsPreferredAlignment = false) const;
 
   /// getTypeUnadjustedAlignInChars - Return the ABI-specified alignment of a type,
   /// in characters, before alignment adjustments. This method does not work on
@@ -2154,8 +2185,14 @@
   // type is a record, its data size is returned.
   std::pair<CharUnits, CharUnits> getTypeInfoDataSizeInChars(QualType T) const;
 
-  std::pair<CharUnits, CharUnits> getTypeInfoInChars(const Type *T) const;
-  std::pair<CharUnits, CharUnits> getTypeInfoInChars(QualType T) const;
+  /// Get the size and alignment of the specified complete type in characters.
+  /// Set "NeedsPreferredAlignment" as true to return the preferred alignment
+  /// when allocating memory for a variable on the stack or in global/thread
+  /// local memory. Otherwise, return the ABI-specified alignment.
+  std::pair<CharUnits, CharUnits>
+  getTypeInfoInChars(const Type *T, bool NeedsPreferredAlignment = false) const;
+  std::pair<CharUnits, CharUnits>
+  getTypeInfoInChars(QualType T, bool NeedsPreferredAlignment = false) const;
 
   /// Determine if the alignment the type has was required using an
   /// alignment attribute.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to