diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index 3ced2e7397a75..8a6511b9ced83 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -97,6 +97,10 @@ struct TransferrableTargetInfo { unsigned char LongLongWidth, LongLongAlign; unsigned char Int128Align; + // This is an optional parameter for targets that + // don't use 'LongLongAlign' for '_BitInt' max alignment + std::optional BitIntMaxAlign; + // Fixed point bit widths unsigned char ShortAccumWidth, ShortAccumAlign; unsigned char AccumWidth, AccumAlign; @@ -518,6 +522,22 @@ class TargetInfo : public TransferrableTargetInfo, /// getInt128Align() - Returns the alignment of Int128. unsigned getInt128Align() const { return Int128Align; } + /// getBitIntMaxAlign() - Returns the maximum possible alignment of + /// '_BitInt' and 'unsigned _BitInt'. + unsigned getBitIntMaxAlign() const { + return BitIntMaxAlign.value_or(LongLongAlign); + } + + /// getBitIntAlign/Width - Return aligned size of '_BitInt' and + /// 'unsigned _BitInt' for this target, in bits. + unsigned getBitIntWidth(unsigned NumBits) const { + return llvm::alignTo(NumBits, getBitIntAlign(NumBits)); + } + unsigned getBitIntAlign(unsigned NumBits) const { + return std::clamp(llvm::PowerOf2Ceil(NumBits), getCharWidth(), + getBitIntMaxAlign()); + } + /// getShortAccumWidth/Align - Return the size of 'signed short _Accum' and /// 'unsigned short _Accum' for this target, in bits. unsigned getShortAccumWidth() const { return ShortAccumWidth; } diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 91e7a5f67a93d..4475f399a120b 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -2258,9 +2258,8 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { } case Type::BitInt: { const auto *EIT = cast(T); - Align = std::clamp(llvm::PowerOf2Ceil(EIT->getNumBits()), - getCharWidth(), Target->getLongLongAlign()); - Width = llvm::alignTo(EIT->getNumBits(), Align); + Align = Target->getBitIntAlign(EIT->getNumBits()); + Width = Target->getBitIntWidth(EIT->getNumBits()); break; } case Type::Record: diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp index 1a02520d7bd1f..4b1545339f694 100644 --- a/clang/lib/Basic/Targets/AArch64.cpp +++ b/clang/lib/Basic/Targets/AArch64.cpp @@ -154,6 +154,7 @@ AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple, else LongWidth = LongAlign = PointerWidth = PointerAlign = 32; + BitIntMaxAlign = 128; MaxVectorAlign = 128; MaxAtomicInlineWidth = 128; MaxAtomicPromoteWidth = 128; diff --git a/clang/test/CodeGen/aapcs64-align.cpp b/clang/test/CodeGen/aapcs64-align.cpp index de231f2123b97..7a8151022852e 100644 --- a/clang/test/CodeGen/aapcs64-align.cpp +++ b/clang/test/CodeGen/aapcs64-align.cpp @@ -1,7 +1,7 @@ // REQUIRES: arm-registered-target // RUN: %clang_cc1 -triple aarch64-none-elf \ // RUN: -O2 \ -// RUN: -emit-llvm -o - %s | FileCheck %s +// RUN: -emit-llvm -fexperimental-max-bitint-width=1024 -o - %s | FileCheck %s extern "C" { @@ -100,4 +100,66 @@ void f5m(int, int, int, int, int, P16); // CHECK: declare void @f5(i32 noundef, [2 x i64]) // CHECK: declare void @f5m(i32 noundef, i32 noundef, i32 noundef, i32 noundef, i32 noundef, [2 x i64]) +//BitInt alignment +struct BITINT129 { + char ch; + unsigned _BitInt(129) v; +}; + +int test_bitint129(){ + return __builtin_offsetof(struct BITINT129, v); } +// CHECK: ret i32 16 + +struct BITINT127 { + char ch; + _BitInt(127) v; +}; + +int test_bitint127(){ + return __builtin_offsetof(struct BITINT127, v); +} +// CHECK: ret i32 16 + +struct BITINT63 { + char ch; + _BitInt(63) v; +}; + +int test_bitint63(){ + return __builtin_offsetof(struct BITINT63, v); +} +// CHECK: ret i32 8 + +struct BITINT32 { + char ch; + unsigned _BitInt(32) v; +}; + +int test_bitint32(){ + return __builtin_offsetof(struct BITINT32, v); +} +// CHECK: ret i32 4 + +struct BITINT9 { + char ch; + unsigned _BitInt(9) v; +}; + +int test_bitint9(){ + return __builtin_offsetof(struct BITINT9, v); +} +// CHECK: ret i32 2 + +struct BITINT8 { + char ch; + unsigned _BitInt(8) v; +}; + +int test_bitint8(){ + return __builtin_offsetof(struct BITINT8, v); +} +// CHECK: ret i32 1 + +} +