[clang] [Clang] Fix oversized bit-field layout on big-endian targets (PR #225494)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Sep 30 00:00:15 PDT 2026
https://github.com/xiongzile updated https://github.com/llvm/llvm-project/pull/225494
>From aa4b747ea45d05e37ec6f8d30b3f0dd1821c7d39 Mon Sep 17 00:00:00 2001
From: Elio <xiongzile at bytedance.com>
Date: Wed, 23 Sep 2026 03:10:13 +0800
Subject: [PATCH 01/15] [Clang][CodeGen] Fix oversized bit-field placement on
big-endian
CodeGen treated the full declared width of an oversized bit-field as
value bits. On big-endian targets that stored the value at the low end
of the storage unit, so `unsigned char value : 16` initialized to 0xAB
landed in memory as 00 AB and was loaded from the second byte. Clamp
the value width to the declared type before the big-endian offset
adjustment, matching CGBitFieldInfo::MakeInfo.
---
clang/lib/CodeGen/CGRecordLayoutBuilder.cpp | 5 ++
.../aarch64-be-oversized-bitfield.cpp | 47 +++++++++++++++++++
2 files changed, 52 insertions(+)
create mode 100644 clang/test/CodeGenCXX/aarch64-be-oversized-bitfield.cpp
diff --git a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
index d98d7c0c96dc3d..56199dc18b7943 100644
--- a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
+++ b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
@@ -243,6 +243,11 @@ void CGRecordLowering::setBitFieldInfo(
Info.StorageOffset = StartOffset;
if (Info.Size > Info.StorageSize)
Info.Size = Info.StorageSize;
+ // CGBitFieldInfo::MakeInfo does the same clamp
+ llvm::Type *FieldType = Types.ConvertTypeForMem(FD->getType());
+ unsigned FieldTypeSize = DataLayout.getTypeAllocSizeInBits(FieldType);
+ if (Info.Size > FieldTypeSize)
+ Info.Size = FieldTypeSize;
// Reverse the bit offsets for big endian machines. Because we represent
// a bitfield as a single large integer load, we can imagine the bits
// counting from the most-significant-bit instead of the
diff --git a/clang/test/CodeGenCXX/aarch64-be-oversized-bitfield.cpp b/clang/test/CodeGenCXX/aarch64-be-oversized-bitfield.cpp
new file mode 100644
index 00000000000000..8dc72c55f984dd
--- /dev/null
+++ b/clang/test/CodeGenCXX/aarch64-be-oversized-bitfield.cpp
@@ -0,0 +1,47 @@
+// RUN: %clang_cc1 -triple aarch64_be-linux-gnu -std=c++17 -emit-llvm -O0 \
+// RUN: -fdump-record-layouts-simple -o %t.be.ll %s | FileCheck %s --check-prefix=LAYOUT-BE
+// RUN: FileCheck %s --check-prefix=BE <%t.be.ll
+// RUN: %clang_cc1 -triple aarch64-linux-gnu -std=c++17 -emit-llvm -O0 \
+// RUN: -fdump-record-layouts-simple -o %t.le.ll %s | FileCheck %s --check-prefix=LAYOUT-LE
+// RUN: FileCheck %s --check-prefix=LE <%t.le.ll
+
+// An oversized bit-field has a declared width larger than its type. Only the
+// type width is a value; the rest is padding, and the value bits come first.
+// On AArch64 big endian that places 0xAB in the high byte of the 16-bit
+// container (memory AB 00). A load therefore shifts the container right by 8.
+// Little endian keeps the value in the low byte (memory AB 00 as well, as the
+// integer 0x00AB).
+
+#pragma clang diagnostic ignored "-Wbitfield-width"
+
+struct S {
+ unsigned char value : 16;
+};
+
+// LAYOUT-BE: BitFields:[
+// LAYOUT-BE-NEXT: <CGBitFieldInfo Offset:8 Size:8 IsSigned:0 StorageSize:16 StorageOffset:0
+// LAYOUT-BE-NEXT: ]>
+// LAYOUT-LE: BitFields:[
+// LAYOUT-LE-NEXT: <CGBitFieldInfo Offset:0 Size:8 IsSigned:0 StorageSize:16 StorageOffset:0
+// LAYOUT-LE-NEXT: ]>
+
+// First byte is 0xAB. The padding byte is not the value.
+// BE: @global = global { i8, i8 } { i8 -85, i8 undef }, align 2
+// LE: @global = global { i8, i8 } { i8 -85, i8 undef }, align 2
+extern "C" S global = {0xAB};
+
+// BE-LABEL: define {{.*}} @get(
+// BE: [[P:%.*]] = load ptr, ptr %p.addr
+// BE: [[LOAD:%.*]] = load i16, ptr [[P]]
+// BE-NEXT: [[SHL:%.*]] = lshr i16 [[LOAD]], 8
+// BE-NEXT: trunc i16 [[SHL]] to i8
+//
+// LE-LABEL: define {{.*}} @get(
+// LE: [[P:%.*]] = load ptr, ptr %p.addr
+// LE: [[LOAD:%.*]] = load i16, ptr [[P]]
+// LE-NOT: lshr
+// LE: [[CLEAR:%.*]] = and i16 [[LOAD]], 255
+// LE-NEXT: trunc i16 [[CLEAR]] to i8
+extern "C" unsigned char get(const S *p) {
+ return p->value;
+}
>From 7c0868223ac0cdb79ee75007c2b13f0977ace40f Mon Sep 17 00:00:00 2001
From: Elio <xiongzile at bytedance.com>
Date: Wed, 23 Sep 2026 03:10:14 +0800
Subject: [PATCH 02/15] [Clang] Adjust padding calculation for corrected
oversized bit-fields
__builtin_clear_padding located occupied bits using the old big-endian
layout, which placed padding before the value of an oversized
bit-field. After the CodeGen fix, value bits come first. Size the value
container to the field type and keep only the low-order occupied bits
inside it, so clear_padding no longer zeroes the value.
---
clang/lib/AST/ASTContext.cpp | 27 +-
.../builtin-clear-padding-codegen.cpp | 395 ++++++------------
2 files changed, 152 insertions(+), 270 deletions(-)
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index e74423ca8c8a1b..f2d7ebcbd3c5ed 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -15917,13 +15917,15 @@ struct PaddingCalculator {
const uint64_t DeclaredSizeInBits = Field->getBitWidthValue();
- // Handle over-sized bitfields:
- // unsigned char a : 12;
- // In this case, DeclaredSizeInBits is 12, but the actually occupied bit
- // size is 8, while the remaining 4 bits are padding.
- const uint64_t OccupiedSizeInBits =
- std::min(DeclaredSizeInBits,
- static_cast<uint64_t>(Ctx.getIntWidth(Field->getType())));
+ // Oversized bit-fields (declared width larger than the field type) keep
+ // only the type's width as the value container. The extra declared bits
+ // are padding and follow that container (Itanium C++ ABI 2.4).
+ // getIntWidth may be narrower still (bool, _BitInt); those occupied bits
+ // are the low-order bits of the value container.
+ const uint64_t ValueFieldBits =
+ std::min(DeclaredSizeInBits, Ctx.getTypeSize(Field->getType()));
+ const uint64_t OccupiedSizeInBits = std::min(
+ ValueFieldBits, static_cast<uint64_t>(Ctx.getIntWidth(Field->getType())));
if (Ctx.getTargetInfo().isLittleEndian()) {
OccuppiedIntervals.push_back(
@@ -15941,14 +15943,11 @@ struct PaddingCalculator {
// the partially occupied bytes in either end, if present, their bit
// intervals need to be adjusted so that they count from the MSB instead.
//
- // FIXME: For over-sized bitfields in BE, Clang allocates padding bits
- // before the occupied bits. This violates the ABI rules, which say that
- // padding should be allocated after, regardless of endianness (Itanium C++
- // ABI §2.4, II.1(b)). The current code accommodates for Clang's current
- // behaviour though, and bumps Start forward to skip the leading padding
- // bits.
+ // Within the value container, occupied bits are its low-order bits, which
+ // are allocated last. Padding from an oversized declared width follows
+ // the container.
const uint64_t Start =
- StartBitOffset + DeclaredSizeInBits - OccupiedSizeInBits;
+ StartBitOffset + ValueFieldBits - OccupiedSizeInBits;
const uint64_t End = Start + OccupiedSizeInBits;
const uint64_t CharWidth = Ctx.getCharWidth();
diff --git a/clang/test/CodeGenCXX/builtin-clear-padding-codegen.cpp b/clang/test/CodeGenCXX/builtin-clear-padding-codegen.cpp
index 7de1b0bb59fc5f..599a8ba03c30df 100644
--- a/clang/test/CodeGenCXX/builtin-clear-padding-codegen.cpp
+++ b/clang/test/CodeGenCXX/builtin-clear-padding-codegen.cpp
@@ -1782,32 +1782,20 @@ struct OversizedBitfield {
// ARM-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
// ARM-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
// ARM-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
-// ARM-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
-// ARM-BE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 4
-// ARM-BE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 63
-// ARM-BE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 4
-// ARM-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// ARM-BE-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1
-// ARM-BE-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], -64
-// ARM-BE-NEXT: store i8 [[TMP6]], ptr [[TMP4]], align 1
-// ARM-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// ARM-BE-NEXT: store i8 0, ptr [[TMP7]], align 2
-// ARM-BE-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// ARM-BE-NEXT: store i8 0, ptr [[TMP8]], align 1
-// ARM-BE-NEXT: [[TMP9:%.*]] = getelementptr i8, ptr [[TMP0]], i32 8
-// ARM-BE-NEXT: [[TMP10:%.*]] = load i8, ptr [[TMP9]], align 4
-// ARM-BE-NEXT: [[TMP11:%.*]] = and i8 [[TMP10]], 31
-// ARM-BE-NEXT: store i8 [[TMP11]], ptr [[TMP9]], align 4
-// ARM-BE-NEXT: [[TMP12:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
-// ARM-BE-NEXT: [[TMP13:%.*]] = load i8, ptr [[TMP12]], align 4
-// ARM-BE-NEXT: [[TMP14:%.*]] = and i8 [[TMP13]], -32
-// ARM-BE-NEXT: store i8 [[TMP14]], ptr [[TMP12]], align 4
-// ARM-BE-NEXT: [[TMP15:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
-// ARM-BE-NEXT: store i8 0, ptr [[TMP15]], align 1
-// ARM-BE-NEXT: [[TMP16:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
-// ARM-BE-NEXT: store i8 0, ptr [[TMP16]], align 2
-// ARM-BE-NEXT: [[TMP17:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
-// ARM-BE-NEXT: store i8 0, ptr [[TMP17]], align 1
+// ARM-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// ARM-BE-NEXT: store i8 0, ptr [[TMP1]], align 1
+// ARM-BE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
+// ARM-BE-NEXT: store i8 0, ptr [[TMP2]], align 2
+// ARM-BE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
+// ARM-BE-NEXT: store i8 0, ptr [[TMP3]], align 1
+// ARM-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
+// ARM-BE-NEXT: store i8 0, ptr [[TMP4]], align 4
+// ARM-BE-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
+// ARM-BE-NEXT: store i8 0, ptr [[TMP5]], align 1
+// ARM-BE-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
+// ARM-BE-NEXT: store i8 0, ptr [[TMP6]], align 2
+// ARM-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
+// ARM-BE-NEXT: store i8 0, ptr [[TMP7]], align 1
// ARM-BE-NEXT: ret void
//
// AARCH64-BE-LABEL: define dso_local void @testOversizedBitfield(
@@ -1816,32 +1804,20 @@ struct OversizedBitfield {
// AARCH64-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
// AARCH64-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
// AARCH64-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
-// AARCH64-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
-// AARCH64-BE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 4
-// AARCH64-BE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 63
-// AARCH64-BE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 4
-// AARCH64-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// AARCH64-BE-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1
-// AARCH64-BE-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], -64
-// AARCH64-BE-NEXT: store i8 [[TMP6]], ptr [[TMP4]], align 1
-// AARCH64-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP7]], align 2
-// AARCH64-BE-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP8]], align 1
-// AARCH64-BE-NEXT: [[TMP9:%.*]] = getelementptr i8, ptr [[TMP0]], i32 8
-// AARCH64-BE-NEXT: [[TMP10:%.*]] = load i8, ptr [[TMP9]], align 4
-// AARCH64-BE-NEXT: [[TMP11:%.*]] = and i8 [[TMP10]], 31
-// AARCH64-BE-NEXT: store i8 [[TMP11]], ptr [[TMP9]], align 4
-// AARCH64-BE-NEXT: [[TMP12:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
-// AARCH64-BE-NEXT: [[TMP13:%.*]] = load i8, ptr [[TMP12]], align 4
-// AARCH64-BE-NEXT: [[TMP14:%.*]] = and i8 [[TMP13]], -32
-// AARCH64-BE-NEXT: store i8 [[TMP14]], ptr [[TMP12]], align 4
-// AARCH64-BE-NEXT: [[TMP15:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP15]], align 1
-// AARCH64-BE-NEXT: [[TMP16:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP16]], align 2
-// AARCH64-BE-NEXT: [[TMP17:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP17]], align 1
+// AARCH64-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP1]], align 1
+// AARCH64-BE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP2]], align 2
+// AARCH64-BE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP3]], align 1
+// AARCH64-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP4]], align 4
+// AARCH64-BE-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP5]], align 1
+// AARCH64-BE-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP6]], align 2
+// AARCH64-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP7]], align 1
// AARCH64-BE-NEXT: ret void
//
extern "C" void testOversizedBitfield(struct OversizedBitfield *s) {
@@ -1898,32 +1874,20 @@ extern "C" void testOversizedBitfield(struct OversizedBitfield *s) {
// ARM-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
// ARM-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
// ARM-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
-// ARM-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
-// ARM-BE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 4
-// ARM-BE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 63
-// ARM-BE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 4
-// ARM-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// ARM-BE-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1
-// ARM-BE-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], -64
-// ARM-BE-NEXT: store i8 [[TMP6]], ptr [[TMP4]], align 1
-// ARM-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// ARM-BE-NEXT: store i8 0, ptr [[TMP7]], align 2
-// ARM-BE-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// ARM-BE-NEXT: store i8 0, ptr [[TMP8]], align 1
-// ARM-BE-NEXT: [[TMP9:%.*]] = getelementptr i8, ptr [[TMP0]], i32 8
-// ARM-BE-NEXT: [[TMP10:%.*]] = load i8, ptr [[TMP9]], align 4
-// ARM-BE-NEXT: [[TMP11:%.*]] = and i8 [[TMP10]], 31
-// ARM-BE-NEXT: store i8 [[TMP11]], ptr [[TMP9]], align 4
-// ARM-BE-NEXT: [[TMP12:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
-// ARM-BE-NEXT: [[TMP13:%.*]] = load i8, ptr [[TMP12]], align 4
-// ARM-BE-NEXT: [[TMP14:%.*]] = and i8 [[TMP13]], -32
-// ARM-BE-NEXT: store i8 [[TMP14]], ptr [[TMP12]], align 4
-// ARM-BE-NEXT: [[TMP15:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
-// ARM-BE-NEXT: store i8 0, ptr [[TMP15]], align 1
-// ARM-BE-NEXT: [[TMP16:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
-// ARM-BE-NEXT: store i8 0, ptr [[TMP16]], align 2
-// ARM-BE-NEXT: [[TMP17:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
-// ARM-BE-NEXT: store i8 0, ptr [[TMP17]], align 1
+// ARM-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// ARM-BE-NEXT: store i8 0, ptr [[TMP1]], align 1
+// ARM-BE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
+// ARM-BE-NEXT: store i8 0, ptr [[TMP2]], align 2
+// ARM-BE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
+// ARM-BE-NEXT: store i8 0, ptr [[TMP3]], align 1
+// ARM-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
+// ARM-BE-NEXT: store i8 0, ptr [[TMP4]], align 4
+// ARM-BE-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
+// ARM-BE-NEXT: store i8 0, ptr [[TMP5]], align 1
+// ARM-BE-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
+// ARM-BE-NEXT: store i8 0, ptr [[TMP6]], align 2
+// ARM-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
+// ARM-BE-NEXT: store i8 0, ptr [[TMP7]], align 1
// ARM-BE-NEXT: ret void
//
// AARCH64-BE-LABEL: define dso_local void @testOversizedBitfieldVolatileStruct(
@@ -1932,32 +1896,20 @@ extern "C" void testOversizedBitfield(struct OversizedBitfield *s) {
// AARCH64-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
// AARCH64-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
// AARCH64-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
-// AARCH64-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
-// AARCH64-BE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 4
-// AARCH64-BE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 63
-// AARCH64-BE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 4
-// AARCH64-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// AARCH64-BE-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1
-// AARCH64-BE-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], -64
-// AARCH64-BE-NEXT: store i8 [[TMP6]], ptr [[TMP4]], align 1
-// AARCH64-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP7]], align 2
-// AARCH64-BE-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP8]], align 1
-// AARCH64-BE-NEXT: [[TMP9:%.*]] = getelementptr i8, ptr [[TMP0]], i32 8
-// AARCH64-BE-NEXT: [[TMP10:%.*]] = load i8, ptr [[TMP9]], align 4
-// AARCH64-BE-NEXT: [[TMP11:%.*]] = and i8 [[TMP10]], 31
-// AARCH64-BE-NEXT: store i8 [[TMP11]], ptr [[TMP9]], align 4
-// AARCH64-BE-NEXT: [[TMP12:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
-// AARCH64-BE-NEXT: [[TMP13:%.*]] = load i8, ptr [[TMP12]], align 4
-// AARCH64-BE-NEXT: [[TMP14:%.*]] = and i8 [[TMP13]], -32
-// AARCH64-BE-NEXT: store i8 [[TMP14]], ptr [[TMP12]], align 4
-// AARCH64-BE-NEXT: [[TMP15:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP15]], align 1
-// AARCH64-BE-NEXT: [[TMP16:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP16]], align 2
-// AARCH64-BE-NEXT: [[TMP17:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP17]], align 1
+// AARCH64-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP1]], align 1
+// AARCH64-BE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP2]], align 2
+// AARCH64-BE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP3]], align 1
+// AARCH64-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP4]], align 4
+// AARCH64-BE-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP5]], align 1
+// AARCH64-BE-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP6]], align 2
+// AARCH64-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP7]], align 1
// AARCH64-BE-NEXT: ret void
//
extern "C" void testOversizedBitfieldVolatileStruct(
@@ -2021,32 +1973,20 @@ struct VolatileOversizedBitfield {
// ARM-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
// ARM-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
// ARM-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
-// ARM-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
-// ARM-BE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 4
-// ARM-BE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 63
-// ARM-BE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 4
-// ARM-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// ARM-BE-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1
-// ARM-BE-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], -64
-// ARM-BE-NEXT: store i8 [[TMP6]], ptr [[TMP4]], align 1
-// ARM-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// ARM-BE-NEXT: store i8 0, ptr [[TMP7]], align 2
-// ARM-BE-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// ARM-BE-NEXT: store i8 0, ptr [[TMP8]], align 1
-// ARM-BE-NEXT: [[TMP9:%.*]] = getelementptr i8, ptr [[TMP0]], i32 8
-// ARM-BE-NEXT: [[TMP10:%.*]] = load i8, ptr [[TMP9]], align 4
-// ARM-BE-NEXT: [[TMP11:%.*]] = and i8 [[TMP10]], 31
-// ARM-BE-NEXT: store i8 [[TMP11]], ptr [[TMP9]], align 4
-// ARM-BE-NEXT: [[TMP12:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
-// ARM-BE-NEXT: [[TMP13:%.*]] = load i8, ptr [[TMP12]], align 4
-// ARM-BE-NEXT: [[TMP14:%.*]] = and i8 [[TMP13]], -32
-// ARM-BE-NEXT: store i8 [[TMP14]], ptr [[TMP12]], align 4
-// ARM-BE-NEXT: [[TMP15:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
-// ARM-BE-NEXT: store i8 0, ptr [[TMP15]], align 1
-// ARM-BE-NEXT: [[TMP16:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
-// ARM-BE-NEXT: store i8 0, ptr [[TMP16]], align 2
-// ARM-BE-NEXT: [[TMP17:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
-// ARM-BE-NEXT: store i8 0, ptr [[TMP17]], align 1
+// ARM-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// ARM-BE-NEXT: store i8 0, ptr [[TMP1]], align 1
+// ARM-BE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
+// ARM-BE-NEXT: store i8 0, ptr [[TMP2]], align 2
+// ARM-BE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
+// ARM-BE-NEXT: store i8 0, ptr [[TMP3]], align 1
+// ARM-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
+// ARM-BE-NEXT: store i8 0, ptr [[TMP4]], align 4
+// ARM-BE-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
+// ARM-BE-NEXT: store i8 0, ptr [[TMP5]], align 1
+// ARM-BE-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
+// ARM-BE-NEXT: store i8 0, ptr [[TMP6]], align 2
+// ARM-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
+// ARM-BE-NEXT: store i8 0, ptr [[TMP7]], align 1
// ARM-BE-NEXT: ret void
//
// AARCH64-BE-LABEL: define dso_local void @testVolatileOversizedBitfield(
@@ -2055,32 +1995,20 @@ struct VolatileOversizedBitfield {
// AARCH64-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
// AARCH64-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
// AARCH64-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
-// AARCH64-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
-// AARCH64-BE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 4
-// AARCH64-BE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 63
-// AARCH64-BE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 4
-// AARCH64-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// AARCH64-BE-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1
-// AARCH64-BE-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], -64
-// AARCH64-BE-NEXT: store i8 [[TMP6]], ptr [[TMP4]], align 1
-// AARCH64-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP7]], align 2
-// AARCH64-BE-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP8]], align 1
-// AARCH64-BE-NEXT: [[TMP9:%.*]] = getelementptr i8, ptr [[TMP0]], i32 8
-// AARCH64-BE-NEXT: [[TMP10:%.*]] = load i8, ptr [[TMP9]], align 4
-// AARCH64-BE-NEXT: [[TMP11:%.*]] = and i8 [[TMP10]], 31
-// AARCH64-BE-NEXT: store i8 [[TMP11]], ptr [[TMP9]], align 4
-// AARCH64-BE-NEXT: [[TMP12:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
-// AARCH64-BE-NEXT: [[TMP13:%.*]] = load i8, ptr [[TMP12]], align 4
-// AARCH64-BE-NEXT: [[TMP14:%.*]] = and i8 [[TMP13]], -32
-// AARCH64-BE-NEXT: store i8 [[TMP14]], ptr [[TMP12]], align 4
-// AARCH64-BE-NEXT: [[TMP15:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP15]], align 1
-// AARCH64-BE-NEXT: [[TMP16:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP16]], align 2
-// AARCH64-BE-NEXT: [[TMP17:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP17]], align 1
+// AARCH64-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP1]], align 1
+// AARCH64-BE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP2]], align 2
+// AARCH64-BE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP3]], align 1
+// AARCH64-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP4]], align 4
+// AARCH64-BE-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP5]], align 1
+// AARCH64-BE-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP6]], align 2
+// AARCH64-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP7]], align 1
// AARCH64-BE-NEXT: ret void
//
extern "C" void testVolatileOversizedBitfield(
@@ -2138,32 +2066,20 @@ extern "C" void testVolatileOversizedBitfield(
// ARM-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
// ARM-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
// ARM-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
-// ARM-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
-// ARM-BE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 4
-// ARM-BE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 63
-// ARM-BE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 4
-// ARM-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// ARM-BE-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1
-// ARM-BE-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], -64
-// ARM-BE-NEXT: store i8 [[TMP6]], ptr [[TMP4]], align 1
-// ARM-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// ARM-BE-NEXT: store i8 0, ptr [[TMP7]], align 2
-// ARM-BE-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// ARM-BE-NEXT: store i8 0, ptr [[TMP8]], align 1
-// ARM-BE-NEXT: [[TMP9:%.*]] = getelementptr i8, ptr [[TMP0]], i32 8
-// ARM-BE-NEXT: [[TMP10:%.*]] = load i8, ptr [[TMP9]], align 4
-// ARM-BE-NEXT: [[TMP11:%.*]] = and i8 [[TMP10]], 31
-// ARM-BE-NEXT: store i8 [[TMP11]], ptr [[TMP9]], align 4
-// ARM-BE-NEXT: [[TMP12:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
-// ARM-BE-NEXT: [[TMP13:%.*]] = load i8, ptr [[TMP12]], align 4
-// ARM-BE-NEXT: [[TMP14:%.*]] = and i8 [[TMP13]], -32
-// ARM-BE-NEXT: store i8 [[TMP14]], ptr [[TMP12]], align 4
-// ARM-BE-NEXT: [[TMP15:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
-// ARM-BE-NEXT: store i8 0, ptr [[TMP15]], align 1
-// ARM-BE-NEXT: [[TMP16:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
-// ARM-BE-NEXT: store i8 0, ptr [[TMP16]], align 2
-// ARM-BE-NEXT: [[TMP17:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
-// ARM-BE-NEXT: store i8 0, ptr [[TMP17]], align 1
+// ARM-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// ARM-BE-NEXT: store i8 0, ptr [[TMP1]], align 1
+// ARM-BE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
+// ARM-BE-NEXT: store i8 0, ptr [[TMP2]], align 2
+// ARM-BE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
+// ARM-BE-NEXT: store i8 0, ptr [[TMP3]], align 1
+// ARM-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
+// ARM-BE-NEXT: store i8 0, ptr [[TMP4]], align 4
+// ARM-BE-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
+// ARM-BE-NEXT: store i8 0, ptr [[TMP5]], align 1
+// ARM-BE-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
+// ARM-BE-NEXT: store i8 0, ptr [[TMP6]], align 2
+// ARM-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
+// ARM-BE-NEXT: store i8 0, ptr [[TMP7]], align 1
// ARM-BE-NEXT: ret void
//
// AARCH64-BE-LABEL: define dso_local void @testVolatileOversizedBitfieldVolatileStruct(
@@ -2172,32 +2088,20 @@ extern "C" void testVolatileOversizedBitfield(
// AARCH64-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
// AARCH64-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
// AARCH64-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
-// AARCH64-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
-// AARCH64-BE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 4
-// AARCH64-BE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 63
-// AARCH64-BE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 4
-// AARCH64-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// AARCH64-BE-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1
-// AARCH64-BE-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], -64
-// AARCH64-BE-NEXT: store i8 [[TMP6]], ptr [[TMP4]], align 1
-// AARCH64-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP7]], align 2
-// AARCH64-BE-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP8]], align 1
-// AARCH64-BE-NEXT: [[TMP9:%.*]] = getelementptr i8, ptr [[TMP0]], i32 8
-// AARCH64-BE-NEXT: [[TMP10:%.*]] = load i8, ptr [[TMP9]], align 4
-// AARCH64-BE-NEXT: [[TMP11:%.*]] = and i8 [[TMP10]], 31
-// AARCH64-BE-NEXT: store i8 [[TMP11]], ptr [[TMP9]], align 4
-// AARCH64-BE-NEXT: [[TMP12:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
-// AARCH64-BE-NEXT: [[TMP13:%.*]] = load i8, ptr [[TMP12]], align 4
-// AARCH64-BE-NEXT: [[TMP14:%.*]] = and i8 [[TMP13]], -32
-// AARCH64-BE-NEXT: store i8 [[TMP14]], ptr [[TMP12]], align 4
-// AARCH64-BE-NEXT: [[TMP15:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP15]], align 1
-// AARCH64-BE-NEXT: [[TMP16:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP16]], align 2
-// AARCH64-BE-NEXT: [[TMP17:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP17]], align 1
+// AARCH64-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP1]], align 1
+// AARCH64-BE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP2]], align 2
+// AARCH64-BE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP3]], align 1
+// AARCH64-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP4]], align 4
+// AARCH64-BE-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP5]], align 1
+// AARCH64-BE-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP6]], align 2
+// AARCH64-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP7]], align 1
// AARCH64-BE-NEXT: ret void
//
extern "C" void testVolatileOversizedBitfieldVolatileStruct(
@@ -4838,8 +4742,8 @@ extern "C" void testPackedBooleanVectorWithFullyPaddingBytes(bool33 *v) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wbitfield-width"
-// Match Clang's existing oversized-field representation. On big endian the
-// occupied byte is byte 1, so clearing padding must leave that byte intact.
+// Value bits occupy the first byte on both endians. The second byte is
+// padding and must be cleared.
struct BitfieldOversizedAligned {
unsigned char value : 16;
};
@@ -4870,8 +4774,8 @@ struct BitfieldOversizedAligned {
// ARM-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
// ARM-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
// ARM-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
-// ARM-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
-// ARM-BE-NEXT: store i8 0, ptr [[TMP1]], align 2
+// ARM-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// ARM-BE-NEXT: store i8 0, ptr [[TMP1]], align 1
// ARM-BE-NEXT: ret void
//
// AARCH64-BE-LABEL: define dso_local void @testBitfieldOversizedAligned(
@@ -4880,16 +4784,15 @@ struct BitfieldOversizedAligned {
// AARCH64-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
// AARCH64-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
// AARCH64-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
-// AARCH64-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP1]], align 2
+// AARCH64-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP1]], align 1
// AARCH64-BE-NEXT: ret void
//
extern "C" void testBitfieldOversizedAligned(BitfieldOversizedAligned *s) {
__builtin_clear_padding(s);
}
-// The occupied bits cross a byte boundary after more than one byte of leading
-// padding on big endian. The declared width also exceeds the allocation type.
+// Eight value bits occupy the first byte. The rest of the allocation is padding.
struct BitfieldOversizedBeyondBoundary {
unsigned char value : 17;
};
@@ -4928,18 +4831,12 @@ struct BitfieldOversizedBeyondBoundary {
// ARM-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
// ARM-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
// ARM-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
-// ARM-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
-// ARM-BE-NEXT: store i8 0, ptr [[TMP1]], align 2
-// ARM-BE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// ARM-BE-NEXT: [[TMP3:%.*]] = load i8, ptr [[TMP2]], align 1
-// ARM-BE-NEXT: [[TMP4:%.*]] = and i8 [[TMP3]], 127
-// ARM-BE-NEXT: store i8 [[TMP4]], ptr [[TMP2]], align 1
-// ARM-BE-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// ARM-BE-NEXT: [[TMP6:%.*]] = load i8, ptr [[TMP5]], align 2
-// ARM-BE-NEXT: [[TMP7:%.*]] = and i8 [[TMP6]], -128
-// ARM-BE-NEXT: store i8 [[TMP7]], ptr [[TMP5]], align 2
-// ARM-BE-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// ARM-BE-NEXT: store i8 0, ptr [[TMP8]], align 1
+// ARM-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// ARM-BE-NEXT: store i8 0, ptr [[TMP1]], align 1
+// ARM-BE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
+// ARM-BE-NEXT: store i8 0, ptr [[TMP2]], align 2
+// ARM-BE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
+// ARM-BE-NEXT: store i8 0, ptr [[TMP3]], align 1
// ARM-BE-NEXT: ret void
//
// AARCH64-BE-LABEL: define dso_local void @testBitfieldOversizedBeyondBoundary(
@@ -4948,18 +4845,12 @@ struct BitfieldOversizedBeyondBoundary {
// AARCH64-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
// AARCH64-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
// AARCH64-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
-// AARCH64-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP1]], align 2
-// AARCH64-BE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// AARCH64-BE-NEXT: [[TMP3:%.*]] = load i8, ptr [[TMP2]], align 1
-// AARCH64-BE-NEXT: [[TMP4:%.*]] = and i8 [[TMP3]], 127
-// AARCH64-BE-NEXT: store i8 [[TMP4]], ptr [[TMP2]], align 1
-// AARCH64-BE-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// AARCH64-BE-NEXT: [[TMP6:%.*]] = load i8, ptr [[TMP5]], align 2
-// AARCH64-BE-NEXT: [[TMP7:%.*]] = and i8 [[TMP6]], -128
-// AARCH64-BE-NEXT: store i8 [[TMP7]], ptr [[TMP5]], align 2
-// AARCH64-BE-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP8]], align 1
+// AARCH64-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP1]], align 1
+// AARCH64-BE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP2]], align 2
+// AARCH64-BE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP3]], align 1
// AARCH64-BE-NEXT: ret void
//
extern "C" void testBitfieldOversizedBeyondBoundary(
@@ -5030,14 +4921,10 @@ struct BitfieldOversizedValueTypes {
// ARM-BE-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 2
// ARM-BE-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], 63
// ARM-BE-NEXT: store i8 [[TMP6]], ptr [[TMP4]], align 2
-// ARM-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// ARM-BE-NEXT: [[TMP8:%.*]] = load i8, ptr [[TMP7]], align 1
-// ARM-BE-NEXT: [[TMP9:%.*]] = and i8 [[TMP8]], 15
-// ARM-BE-NEXT: store i8 [[TMP9]], ptr [[TMP7]], align 1
-// ARM-BE-NEXT: [[TMP10:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// ARM-BE-NEXT: [[TMP11:%.*]] = load i8, ptr [[TMP10]], align 2
-// ARM-BE-NEXT: [[TMP12:%.*]] = and i8 [[TMP11]], -15
-// ARM-BE-NEXT: store i8 [[TMP12]], ptr [[TMP10]], align 2
+// ARM-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
+// ARM-BE-NEXT: [[TMP8:%.*]] = load i8, ptr [[TMP7]], align 2
+// ARM-BE-NEXT: [[TMP9:%.*]] = and i8 [[TMP8]], 1
+// ARM-BE-NEXT: store i8 [[TMP9]], ptr [[TMP7]], align 2
// ARM-BE-NEXT: ret void
//
// AARCH64-BE-LABEL: define dso_local void @testBitfieldOversizedValueTypes(
@@ -5054,14 +4941,10 @@ struct BitfieldOversizedValueTypes {
// AARCH64-BE-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 2
// AARCH64-BE-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], 63
// AARCH64-BE-NEXT: store i8 [[TMP6]], ptr [[TMP4]], align 2
-// AARCH64-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// AARCH64-BE-NEXT: [[TMP8:%.*]] = load i8, ptr [[TMP7]], align 1
-// AARCH64-BE-NEXT: [[TMP9:%.*]] = and i8 [[TMP8]], 15
-// AARCH64-BE-NEXT: store i8 [[TMP9]], ptr [[TMP7]], align 1
-// AARCH64-BE-NEXT: [[TMP10:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// AARCH64-BE-NEXT: [[TMP11:%.*]] = load i8, ptr [[TMP10]], align 2
-// AARCH64-BE-NEXT: [[TMP12:%.*]] = and i8 [[TMP11]], -15
-// AARCH64-BE-NEXT: store i8 [[TMP12]], ptr [[TMP10]], align 2
+// AARCH64-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
+// AARCH64-BE-NEXT: [[TMP8:%.*]] = load i8, ptr [[TMP7]], align 2
+// AARCH64-BE-NEXT: [[TMP9:%.*]] = and i8 [[TMP8]], 1
+// AARCH64-BE-NEXT: store i8 [[TMP9]], ptr [[TMP7]], align 2
// AARCH64-BE-NEXT: ret void
//
extern "C" void testBitfieldOversizedValueTypes(
>From a57f09dfe74547b919b2423d5e93db1803a020b8 Mon Sep 17 00:00:00 2001
From: Zile Xiong <xiongzile at bytedance.com>
Date: Wed, 23 Sep 2026 11:09:43 +0800
Subject: [PATCH 03/15] clang-format
---
clang/lib/AST/ASTContext.cpp | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index f2d7ebcbd3c5ed..c6554fc58f1985 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -15924,8 +15924,9 @@ struct PaddingCalculator {
// are the low-order bits of the value container.
const uint64_t ValueFieldBits =
std::min(DeclaredSizeInBits, Ctx.getTypeSize(Field->getType()));
- const uint64_t OccupiedSizeInBits = std::min(
- ValueFieldBits, static_cast<uint64_t>(Ctx.getIntWidth(Field->getType())));
+ const uint64_t OccupiedSizeInBits =
+ std::min(ValueFieldBits,
+ static_cast<uint64_t>(Ctx.getIntWidth(Field->getType())));
if (Ctx.getTargetInfo().isLittleEndian()) {
OccuppiedIntervals.push_back(
@@ -15946,8 +15947,7 @@ struct PaddingCalculator {
// Within the value container, occupied bits are its low-order bits, which
// are allocated last. Padding from an oversized declared width follows
// the container.
- const uint64_t Start =
- StartBitOffset + ValueFieldBits - OccupiedSizeInBits;
+ const uint64_t Start = StartBitOffset + ValueFieldBits - OccupiedSizeInBits;
const uint64_t End = Start + OccupiedSizeInBits;
const uint64_t CharWidth = Ctx.getCharWidth();
>From 039a4270357f30a18875a287c80a497a77e90290 Mon Sep 17 00:00:00 2001
From: Zile Xiong <xiongzile at bytedance.com>
Date: Wed, 23 Sep 2026 11:23:18 +0800
Subject: [PATCH 04/15] add systemZ and powerPC tests
---
...ld.cpp => big-endian-oversized-bitfield.cpp} | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
rename clang/test/CodeGenCXX/{aarch64-be-oversized-bitfield.cpp => big-endian-oversized-bitfield.cpp} (63%)
diff --git a/clang/test/CodeGenCXX/aarch64-be-oversized-bitfield.cpp b/clang/test/CodeGenCXX/big-endian-oversized-bitfield.cpp
similarity index 63%
rename from clang/test/CodeGenCXX/aarch64-be-oversized-bitfield.cpp
rename to clang/test/CodeGenCXX/big-endian-oversized-bitfield.cpp
index 8dc72c55f984dd..0e37c714e853dc 100644
--- a/clang/test/CodeGenCXX/aarch64-be-oversized-bitfield.cpp
+++ b/clang/test/CodeGenCXX/big-endian-oversized-bitfield.cpp
@@ -4,13 +4,22 @@
// RUN: %clang_cc1 -triple aarch64-linux-gnu -std=c++17 -emit-llvm -O0 \
// RUN: -fdump-record-layouts-simple -o %t.le.ll %s | FileCheck %s --check-prefix=LAYOUT-LE
// RUN: FileCheck %s --check-prefix=LE <%t.le.ll
+// RUN: %clang_cc1 -triple s390x-linux-gnu -std=c++17 -emit-llvm -O0 \
+// RUN: -fdump-record-layouts-simple -o %t.s390x.ll %s | FileCheck %s --check-prefix=LAYOUT-BE
+// RUN: FileCheck %s --check-prefix=BE <%t.s390x.ll
+// RUN: %clang_cc1 -triple powerpc64-linux-gnu -std=c++17 -emit-llvm -O0 \
+// RUN: -fdump-record-layouts-simple -o %t.ppc64.ll %s | FileCheck %s --check-prefix=LAYOUT-BE
+// RUN: FileCheck %s --check-prefix=BE <%t.ppc64.ll
+// RUN: %clang_cc1 -triple powerpc64le-linux-gnu -std=c++17 -emit-llvm -O0 \
+// RUN: -fdump-record-layouts-simple -o %t.ppc64le.ll %s | FileCheck %s --check-prefix=LAYOUT-LE
+// RUN: FileCheck %s --check-prefix=LE <%t.ppc64le.ll
// An oversized bit-field has a declared width larger than its type. Only the
// type width is a value; the rest is padding, and the value bits come first.
-// On AArch64 big endian that places 0xAB in the high byte of the 16-bit
-// container (memory AB 00). A load therefore shifts the container right by 8.
-// Little endian keeps the value in the low byte (memory AB 00 as well, as the
-// integer 0x00AB).
+// Big endian (AArch64, SystemZ, PowerPC) places 0xAB in the high byte of the
+// 16-bit container (memory AB 00). A load therefore shifts the container right
+// by 8. Little endian keeps the value in the low byte (memory AB 00 as well,
+// as the integer 0x00AB) and masks instead of shifting.
#pragma clang diagnostic ignored "-Wbitfield-width"
>From 1389a5ca38412d6fb884dd283f8db6f4df7f8bf4 Mon Sep 17 00:00:00 2001
From: Zile Xiong <xiongzile at bytedance.com>
Date: Wed, 23 Sep 2026 12:40:09 +0800
Subject: [PATCH 05/15] remove le tests
---
.../big-endian-oversized-bitfield.cpp | 20 +------------------
1 file changed, 1 insertion(+), 19 deletions(-)
diff --git a/clang/test/CodeGenCXX/big-endian-oversized-bitfield.cpp b/clang/test/CodeGenCXX/big-endian-oversized-bitfield.cpp
index 0e37c714e853dc..cad72482c372ac 100644
--- a/clang/test/CodeGenCXX/big-endian-oversized-bitfield.cpp
+++ b/clang/test/CodeGenCXX/big-endian-oversized-bitfield.cpp
@@ -1,25 +1,18 @@
// RUN: %clang_cc1 -triple aarch64_be-linux-gnu -std=c++17 -emit-llvm -O0 \
// RUN: -fdump-record-layouts-simple -o %t.be.ll %s | FileCheck %s --check-prefix=LAYOUT-BE
// RUN: FileCheck %s --check-prefix=BE <%t.be.ll
-// RUN: %clang_cc1 -triple aarch64-linux-gnu -std=c++17 -emit-llvm -O0 \
-// RUN: -fdump-record-layouts-simple -o %t.le.ll %s | FileCheck %s --check-prefix=LAYOUT-LE
-// RUN: FileCheck %s --check-prefix=LE <%t.le.ll
// RUN: %clang_cc1 -triple s390x-linux-gnu -std=c++17 -emit-llvm -O0 \
// RUN: -fdump-record-layouts-simple -o %t.s390x.ll %s | FileCheck %s --check-prefix=LAYOUT-BE
// RUN: FileCheck %s --check-prefix=BE <%t.s390x.ll
// RUN: %clang_cc1 -triple powerpc64-linux-gnu -std=c++17 -emit-llvm -O0 \
// RUN: -fdump-record-layouts-simple -o %t.ppc64.ll %s | FileCheck %s --check-prefix=LAYOUT-BE
// RUN: FileCheck %s --check-prefix=BE <%t.ppc64.ll
-// RUN: %clang_cc1 -triple powerpc64le-linux-gnu -std=c++17 -emit-llvm -O0 \
-// RUN: -fdump-record-layouts-simple -o %t.ppc64le.ll %s | FileCheck %s --check-prefix=LAYOUT-LE
-// RUN: FileCheck %s --check-prefix=LE <%t.ppc64le.ll
// An oversized bit-field has a declared width larger than its type. Only the
// type width is a value; the rest is padding, and the value bits come first.
// Big endian (AArch64, SystemZ, PowerPC) places 0xAB in the high byte of the
// 16-bit container (memory AB 00). A load therefore shifts the container right
-// by 8. Little endian keeps the value in the low byte (memory AB 00 as well,
-// as the integer 0x00AB) and masks instead of shifting.
+// by 8.
#pragma clang diagnostic ignored "-Wbitfield-width"
@@ -30,13 +23,9 @@ struct S {
// LAYOUT-BE: BitFields:[
// LAYOUT-BE-NEXT: <CGBitFieldInfo Offset:8 Size:8 IsSigned:0 StorageSize:16 StorageOffset:0
// LAYOUT-BE-NEXT: ]>
-// LAYOUT-LE: BitFields:[
-// LAYOUT-LE-NEXT: <CGBitFieldInfo Offset:0 Size:8 IsSigned:0 StorageSize:16 StorageOffset:0
-// LAYOUT-LE-NEXT: ]>
// First byte is 0xAB. The padding byte is not the value.
// BE: @global = global { i8, i8 } { i8 -85, i8 undef }, align 2
-// LE: @global = global { i8, i8 } { i8 -85, i8 undef }, align 2
extern "C" S global = {0xAB};
// BE-LABEL: define {{.*}} @get(
@@ -44,13 +33,6 @@ extern "C" S global = {0xAB};
// BE: [[LOAD:%.*]] = load i16, ptr [[P]]
// BE-NEXT: [[SHL:%.*]] = lshr i16 [[LOAD]], 8
// BE-NEXT: trunc i16 [[SHL]] to i8
-//
-// LE-LABEL: define {{.*}} @get(
-// LE: [[P:%.*]] = load ptr, ptr %p.addr
-// LE: [[LOAD:%.*]] = load i16, ptr [[P]]
-// LE-NOT: lshr
-// LE: [[CLEAR:%.*]] = and i16 [[LOAD]], 255
-// LE-NEXT: trunc i16 [[CLEAR]] to i8
extern "C" unsigned char get(const S *p) {
return p->value;
}
>From a4ead86d3723bc5b24fc818ceab1f268ed788d66 Mon Sep 17 00:00:00 2001
From: Zile Xiong <xiongzile at bytedance.com>
Date: Thu, 24 Sep 2026 14:11:19 +0800
Subject: [PATCH 06/15] add set test
---
.../big-endian-oversized-bitfield.cpp | 23 +++++++++++++++----
1 file changed, 19 insertions(+), 4 deletions(-)
diff --git a/clang/test/CodeGenCXX/big-endian-oversized-bitfield.cpp b/clang/test/CodeGenCXX/big-endian-oversized-bitfield.cpp
index cad72482c372ac..0dda596725bed4 100644
--- a/clang/test/CodeGenCXX/big-endian-oversized-bitfield.cpp
+++ b/clang/test/CodeGenCXX/big-endian-oversized-bitfield.cpp
@@ -12,7 +12,7 @@
// type width is a value; the rest is padding, and the value bits come first.
// Big endian (AArch64, SystemZ, PowerPC) places 0xAB in the high byte of the
// 16-bit container (memory AB 00). A load therefore shifts the container right
-// by 8.
+// by 8. A store shifts the new value left by 8 and keeps the low byte.
#pragma clang diagnostic ignored "-Wbitfield-width"
@@ -26,13 +26,28 @@ struct S {
// First byte is 0xAB. The padding byte is not the value.
// BE: @global = global { i8, i8 } { i8 -85, i8 undef }, align 2
-extern "C" S global = {0xAB};
+S global = {0xAB};
-// BE-LABEL: define {{.*}} @get(
+// BE-LABEL: define {{.*}} @_Z3getPK1S(
// BE: [[P:%.*]] = load ptr, ptr %p.addr
// BE: [[LOAD:%.*]] = load i16, ptr [[P]]
// BE-NEXT: [[SHL:%.*]] = lshr i16 [[LOAD]], 8
// BE-NEXT: trunc i16 [[SHL]] to i8
-extern "C" unsigned char get(const S *p) {
+unsigned char get(const S *p) {
return p->value;
}
+
+// The value goes in the high byte. The low byte is padding and is preserved.
+// BE-LABEL: define {{.*}} @_Z3setP1Sh(
+// BE: [[V:%.*]] = load i8, ptr %v.addr
+// BE: [[PTR:%.*]] = load ptr, ptr %p.addr
+// BE: [[EXT:%.*]] = zext i8 [[V]] to i16
+// BE: [[OLD:%.*]] = load i16, ptr [[PTR]]
+// BE-NEXT: [[MASKED:%.*]] = and i16 [[EXT]], 255
+// BE-NEXT: [[SHIFTED:%.*]] = shl i16 [[MASKED]], 8
+// BE-NEXT: [[KEPT:%.*]] = and i16 [[OLD]], 255
+// BE-NEXT: [[MERGED:%.*]] = or i16 [[KEPT]], [[SHIFTED]]
+// BE-NEXT: store i16 [[MERGED]], ptr [[PTR]]
+void set(S *p, unsigned char v) {
+ p->value = v;
+}
>From a6ae7eefa2f96b7e9fe80ddd00edc0fdce00224c Mon Sep 17 00:00:00 2001
From: Zile Xiong <xiongzile at bytedance.com>
Date: Thu, 24 Sep 2026 14:28:06 +0800
Subject: [PATCH 07/15] chore
---
.../big-endian-oversized-bitfield.cpp | 53 +++++++++----------
1 file changed, 25 insertions(+), 28 deletions(-)
diff --git a/clang/test/CodeGenCXX/big-endian-oversized-bitfield.cpp b/clang/test/CodeGenCXX/big-endian-oversized-bitfield.cpp
index 0dda596725bed4..371f0a6b9fd7b0 100644
--- a/clang/test/CodeGenCXX/big-endian-oversized-bitfield.cpp
+++ b/clang/test/CodeGenCXX/big-endian-oversized-bitfield.cpp
@@ -1,12 +1,9 @@
-// RUN: %clang_cc1 -triple aarch64_be-linux-gnu -std=c++17 -emit-llvm -O0 \
-// RUN: -fdump-record-layouts-simple -o %t.be.ll %s | FileCheck %s --check-prefix=LAYOUT-BE
-// RUN: FileCheck %s --check-prefix=BE <%t.be.ll
-// RUN: %clang_cc1 -triple s390x-linux-gnu -std=c++17 -emit-llvm -O0 \
-// RUN: -fdump-record-layouts-simple -o %t.s390x.ll %s | FileCheck %s --check-prefix=LAYOUT-BE
-// RUN: FileCheck %s --check-prefix=BE <%t.s390x.ll
-// RUN: %clang_cc1 -triple powerpc64-linux-gnu -std=c++17 -emit-llvm -O0 \
-// RUN: -fdump-record-layouts-simple -o %t.ppc64.ll %s | FileCheck %s --check-prefix=LAYOUT-BE
-// RUN: FileCheck %s --check-prefix=BE <%t.ppc64.ll
+// RUN: %clang_cc1 -triple aarch64_be-linux-gnu -emit-llvm -fdump-record-layouts-simple -o %t.be.ll %s | FileCheck %s --check-prefix=LAYOUT
+// RUN: FileCheck %s --check-prefix=IR <%t.be.ll
+// RUN: %clang_cc1 -triple s390x-linux-gnu -emit-llvm -fdump-record-layouts-simple -o %t.s390x.ll %s | FileCheck %s --check-prefix=LAYOUT
+// RUN: FileCheck %s --check-prefix=IR <%t.s390x.ll
+// RUN: %clang_cc1 -triple powerpc64-linux-gnu -emit-llvm -fdump-record-layouts-simple -o %t.ppc64.ll %s | FileCheck %s --check-prefix=LAYOUT
+// RUN: FileCheck %s --check-prefix=IR <%t.ppc64.ll
// An oversized bit-field has a declared width larger than its type. Only the
// type width is a value; the rest is padding, and the value bits come first.
@@ -20,34 +17,34 @@ struct S {
unsigned char value : 16;
};
-// LAYOUT-BE: BitFields:[
-// LAYOUT-BE-NEXT: <CGBitFieldInfo Offset:8 Size:8 IsSigned:0 StorageSize:16 StorageOffset:0
-// LAYOUT-BE-NEXT: ]>
+// LAYOUT: BitFields:[
+// LAYOUT-NEXT: <CGBitFieldInfo Offset:8 Size:8 IsSigned:0 StorageSize:16 StorageOffset:0
+// LAYOUT-NEXT: ]>
// First byte is 0xAB. The padding byte is not the value.
-// BE: @global = global { i8, i8 } { i8 -85, i8 undef }, align 2
+// IR: @global = global { i8, i8 } { i8 -85, i8 undef }, align 2
S global = {0xAB};
-// BE-LABEL: define {{.*}} @_Z3getPK1S(
-// BE: [[P:%.*]] = load ptr, ptr %p.addr
-// BE: [[LOAD:%.*]] = load i16, ptr [[P]]
-// BE-NEXT: [[SHL:%.*]] = lshr i16 [[LOAD]], 8
-// BE-NEXT: trunc i16 [[SHL]] to i8
+// IR-LABEL: define {{.*}} @_Z3getPK1S(
+// IR: [[P:%.*]] = load ptr, ptr %p.addr
+// IR: [[LOAD:%.*]] = load i16, ptr [[P]]
+// IR-NEXT: [[SHL:%.*]] = lshr i16 [[LOAD]], 8
+// IR-NEXT: trunc i16 [[SHL]] to i8
unsigned char get(const S *p) {
return p->value;
}
// The value goes in the high byte. The low byte is padding and is preserved.
-// BE-LABEL: define {{.*}} @_Z3setP1Sh(
-// BE: [[V:%.*]] = load i8, ptr %v.addr
-// BE: [[PTR:%.*]] = load ptr, ptr %p.addr
-// BE: [[EXT:%.*]] = zext i8 [[V]] to i16
-// BE: [[OLD:%.*]] = load i16, ptr [[PTR]]
-// BE-NEXT: [[MASKED:%.*]] = and i16 [[EXT]], 255
-// BE-NEXT: [[SHIFTED:%.*]] = shl i16 [[MASKED]], 8
-// BE-NEXT: [[KEPT:%.*]] = and i16 [[OLD]], 255
-// BE-NEXT: [[MERGED:%.*]] = or i16 [[KEPT]], [[SHIFTED]]
-// BE-NEXT: store i16 [[MERGED]], ptr [[PTR]]
+// IR-LABEL: define {{.*}} @_Z3setP1Sh(
+// IR: [[V:%.*]] = load i8, ptr %v.addr
+// IR: [[PTR:%.*]] = load ptr, ptr %p.addr
+// IR: [[EXT:%.*]] = zext i8 [[V]] to i16
+// IR: [[OLD:%.*]] = load i16, ptr [[PTR]]
+// IR-NEXT: [[MASKED:%.*]] = and i16 [[EXT]], 255
+// IR-NEXT: [[SHIFTED:%.*]] = shl i16 [[MASKED]], 8
+// IR-NEXT: [[KEPT:%.*]] = and i16 [[OLD]], 255
+// IR-NEXT: [[MERGED:%.*]] = or i16 [[KEPT]], [[SHIFTED]]
+// IR-NEXT: store i16 [[MERGED]], ptr [[PTR]]
void set(S *p, unsigned char v) {
p->value = v;
}
>From 60a86471c85c4fa769cbe4e4b5fb14e042dc7789 Mon Sep 17 00:00:00 2001
From: Zile Xiong <xiongzile at bytedance.com>
Date: Fri, 25 Sep 2026 03:58:49 +0800
Subject: [PATCH 08/15] adjust some misleading description
---
clang/test/CodeGenCXX/big-endian-oversized-bitfield.cpp | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/clang/test/CodeGenCXX/big-endian-oversized-bitfield.cpp b/clang/test/CodeGenCXX/big-endian-oversized-bitfield.cpp
index 371f0a6b9fd7b0..d311357f3d4851 100644
--- a/clang/test/CodeGenCXX/big-endian-oversized-bitfield.cpp
+++ b/clang/test/CodeGenCXX/big-endian-oversized-bitfield.cpp
@@ -7,9 +7,10 @@
// An oversized bit-field has a declared width larger than its type. Only the
// type width is a value; the rest is padding, and the value bits come first.
-// Big endian (AArch64, SystemZ, PowerPC) places 0xAB in the high byte of the
-// 16-bit container (memory AB 00). A load therefore shifts the container right
-// by 8. A store shifts the new value left by 8 and keeps the low byte.
+// Big endian places 0xAB at the higher bits of the 16-bit storage type, although in memory it resides
+// at the low byte because of the reversed byte order. A load therefore
+// shifts the storage type (i16) right by 8. A store shifts the new value left by 8
+// and keeps the lower bits.
#pragma clang diagnostic ignored "-Wbitfield-width"
>From 9654b77c4b7c1e444897a5f2c1856039e7bf9aa0 Mon Sep 17 00:00:00 2001
From: Zile Xiong <xiongzile at bytedance.com>
Date: Mon, 28 Sep 2026 22:36:09 +0800
Subject: [PATCH 09/15] add tests for bool:16
---
.../big-endian-oversized-bitfield.cpp | 32 +++++++++
.../builtin-clear-padding-codegen.cpp | 68 +++++++++++++++++++
2 files changed, 100 insertions(+)
diff --git a/clang/test/CodeGenCXX/big-endian-oversized-bitfield.cpp b/clang/test/CodeGenCXX/big-endian-oversized-bitfield.cpp
index d311357f3d4851..da51f12b553ab9 100644
--- a/clang/test/CodeGenCXX/big-endian-oversized-bitfield.cpp
+++ b/clang/test/CodeGenCXX/big-endian-oversized-bitfield.cpp
@@ -26,6 +26,14 @@ struct S {
// IR: @global = global { i8, i8 } { i8 -85, i8 undef }, align 2
S global = {0xAB};
+// `bool : 16 = true` is 00000001 in the first byte. The value bit is the
+// low bit of that byte; the second byte is padding.
+// IR: @bglobal = global { i8, i8 } { i8 1, i8 undef }, align 2
+struct B {
+ bool value : 16;
+};
+B bglobal = {true};
+
// IR-LABEL: define {{.*}} @_Z3getPK1S(
// IR: [[P:%.*]] = load ptr, ptr %p.addr
// IR: [[LOAD:%.*]] = load i16, ptr [[P]]
@@ -49,3 +57,27 @@ unsigned char get(const S *p) {
void set(S *p, unsigned char v) {
p->value = v;
}
+
+// LAYOUT: BitFields:[
+// LAYOUT-NEXT: <CGBitFieldInfo Offset:8 Size:8 IsSigned:0 StorageSize:16 StorageOffset:0
+// LAYOUT-NEXT: ]>
+
+// IR-LABEL: define {{.*}} @_Z3getPK1B(
+// IR: [[BP:%.*]] = load ptr, ptr %p.addr
+// IR: [[BLOAD:%.*]] = load i16, ptr [[BP]]
+// IR-NEXT: [[BSHL:%.*]] = lshr i16 [[BLOAD]], 8
+// IR-NEXT: trunc i16 [[BSHL]] to i1
+bool get(const B *p) {
+ return p->value;
+}
+
+// IR-LABEL: define {{.*}} @_Z3setP1Bb(
+// IR: [[BEXT:%.*]] = zext i1 {{.*}} to i16
+// IR: [[BOLD:%.*]] = load i16, ptr %{{.*}}
+// IR-NEXT: [[BSHIFT:%.*]] = shl i16 [[BEXT]], 8
+// IR-NEXT: [[BKEPT:%.*]] = and i16 [[BOLD]], 255
+// IR-NEXT: [[BMERGED:%.*]] = or i16 [[BKEPT]], [[BSHIFT]]
+// IR-NEXT: store i16 [[BMERGED]], ptr %{{.*}}
+void set(B *p, bool v) {
+ p->value = v;
+}
diff --git a/clang/test/CodeGenCXX/builtin-clear-padding-codegen.cpp b/clang/test/CodeGenCXX/builtin-clear-padding-codegen.cpp
index 599a8ba03c30df..9d5d23fe7449e9 100644
--- a/clang/test/CodeGenCXX/builtin-clear-padding-codegen.cpp
+++ b/clang/test/CodeGenCXX/builtin-clear-padding-codegen.cpp
@@ -4792,6 +4792,74 @@ extern "C" void testBitfieldOversizedAligned(BitfieldOversizedAligned *s) {
__builtin_clear_padding(s);
}
+// `bool : 16` stores true as 00000001 in the first byte on both endians.
+// clear_padding treats only that value bit as occupied (getIntWidth == 1).
+// The other seven bits of the first byte, and the whole second byte, are
+// cleared.
+struct BitfieldOversizedBool {
+ bool value : 16;
+};
+
+// ITANIUM64-LE-LABEL: define dso_local void @testBitfieldOversizedBool(
+// ITANIUM64-LE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// ITANIUM64-LE-NEXT: [[ENTRY:.*:]]
+// ITANIUM64-LE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// ITANIUM64-LE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// ITANIUM64-LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
+// ITANIUM64-LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
+// ITANIUM64-LE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 2
+// ITANIUM64-LE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 1
+// ITANIUM64-LE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 2
+// ITANIUM64-LE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// ITANIUM64-LE-NEXT: store i8 0, ptr [[TMP4]], align 1
+// ITANIUM64-LE-NEXT: ret void
+//
+// ARM-LE-LABEL: define dso_local void @testBitfieldOversizedBool(
+// ARM-LE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// ARM-LE-NEXT: [[ENTRY:.*:]]
+// ARM-LE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// ARM-LE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// ARM-LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
+// ARM-LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
+// ARM-LE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 2
+// ARM-LE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 1
+// ARM-LE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 2
+// ARM-LE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// ARM-LE-NEXT: store i8 0, ptr [[TMP4]], align 1
+// ARM-LE-NEXT: ret void
+//
+// ARM-BE-LABEL: define dso_local void @testBitfieldOversizedBool(
+// ARM-BE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// ARM-BE-NEXT: [[ENTRY:.*:]]
+// ARM-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// ARM-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// ARM-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
+// ARM-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
+// ARM-BE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 2
+// ARM-BE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 1
+// ARM-BE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 2
+// ARM-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// ARM-BE-NEXT: store i8 0, ptr [[TMP4]], align 1
+// ARM-BE-NEXT: ret void
+//
+// AARCH64-BE-LABEL: define dso_local void @testBitfieldOversizedBool(
+// AARCH64-BE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// AARCH64-BE-NEXT: [[ENTRY:.*:]]
+// AARCH64-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// AARCH64-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// AARCH64-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
+// AARCH64-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
+// AARCH64-BE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 2
+// AARCH64-BE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 1
+// AARCH64-BE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 2
+// AARCH64-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// AARCH64-BE-NEXT: store i8 0, ptr [[TMP4]], align 1
+// AARCH64-BE-NEXT: ret void
+//
+extern "C" void testBitfieldOversizedBool(BitfieldOversizedBool *s) {
+ __builtin_clear_padding(s);
+}
+
// Eight value bits occupy the first byte. The rest of the allocation is padding.
struct BitfieldOversizedBeyondBoundary {
unsigned char value : 17;
>From 7cf18f240ea7a539ad74f2cba270cbf87925a981 Mon Sep 17 00:00:00 2001
From: Zile Xiong <xiongzile at bytedance.com>
Date: Tue, 29 Sep 2026 20:07:44 +0800
Subject: [PATCH 10/15] entire reference
---
clang/lib/AST/ASTContext.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index c6554fc58f1985..f36ab09fd878aa 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -15919,7 +15919,7 @@ struct PaddingCalculator {
// Oversized bit-fields (declared width larger than the field type) keep
// only the type's width as the value container. The extra declared bits
- // are padding and follow that container (Itanium C++ ABI 2.4).
+ // are padding and follow that container (Itanium C++ ABI §2.4, II.1(b)).
// getIntWidth may be narrower still (bool, _BitInt); those occupied bits
// are the low-order bits of the value container.
const uint64_t ValueFieldBits =
>From bc1f3e646dba11dd249723a2208cbf1d7631ef7f Mon Sep 17 00:00:00 2001
From: Zile Xiong <xiongzile at bytedance.com>
Date: Wed, 30 Sep 2026 12:35:48 +0800
Subject: [PATCH 11/15] ignore the wrong case on bool and _BitInt
---
clang/lib/AST/ASTContext.cpp | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index f36ab09fd878aa..7031f4242d65b7 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -15922,10 +15922,8 @@ struct PaddingCalculator {
// are padding and follow that container (Itanium C++ ABI §2.4, II.1(b)).
// getIntWidth may be narrower still (bool, _BitInt); those occupied bits
// are the low-order bits of the value container.
- const uint64_t ValueFieldBits =
- std::min(DeclaredSizeInBits, Ctx.getTypeSize(Field->getType()));
const uint64_t OccupiedSizeInBits =
- std::min(ValueFieldBits,
+ std::min(DeclaredSizeInBits,
static_cast<uint64_t>(Ctx.getIntWidth(Field->getType())));
if (Ctx.getTargetInfo().isLittleEndian()) {
@@ -15947,7 +15945,7 @@ struct PaddingCalculator {
// Within the value container, occupied bits are its low-order bits, which
// are allocated last. Padding from an oversized declared width follows
// the container.
- const uint64_t Start = StartBitOffset + ValueFieldBits - OccupiedSizeInBits;
+ const uint64_t Start = StartBitOffset;
const uint64_t End = Start + OccupiedSizeInBits;
const uint64_t CharWidth = Ctx.getCharWidth();
>From 8926c44c01d1f4a51bf6ba7d672d2725851974cb Mon Sep 17 00:00:00 2001
From: Zile Xiong <xiongzile at bytedance.com>
Date: Wed, 30 Sep 2026 12:42:50 +0800
Subject: [PATCH 12/15] fix bool issue(need more tests)
---
clang/lib/AST/ASTContext.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 7031f4242d65b7..c7579e3429cd4c 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -15924,7 +15924,7 @@ struct PaddingCalculator {
// are the low-order bits of the value container.
const uint64_t OccupiedSizeInBits =
std::min(DeclaredSizeInBits,
- static_cast<uint64_t>(Ctx.getIntWidth(Field->getType())));
+ static_cast<uint64_t>(Ctx.getTypeSize(Field->getType())));
if (Ctx.getTargetInfo().isLittleEndian()) {
OccuppiedIntervals.push_back(
>From 06dfc127e935ff7f62f82616ca0fea13bbb85669 Mon Sep 17 00:00:00 2001
From: Zile Xiong <xiongzile at bytedance.com>
Date: Wed, 30 Sep 2026 12:43:23 +0800
Subject: [PATCH 13/15] remove unused cast
---
clang/lib/AST/ASTContext.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index c7579e3429cd4c..7446251f8d1ab4 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -15923,8 +15923,7 @@ struct PaddingCalculator {
// getIntWidth may be narrower still (bool, _BitInt); those occupied bits
// are the low-order bits of the value container.
const uint64_t OccupiedSizeInBits =
- std::min(DeclaredSizeInBits,
- static_cast<uint64_t>(Ctx.getTypeSize(Field->getType())));
+ std::min(DeclaredSizeInBits,Ctx.getTypeSize(Field->getType()));
if (Ctx.getTargetInfo().isLittleEndian()) {
OccuppiedIntervals.push_back(
>From 0e5c74b72746ec2af07a764a21e4bbd70213c56e Mon Sep 17 00:00:00 2001
From: Zile Xiong <xiongzile at bytedance.com>
Date: Wed, 30 Sep 2026 12:49:01 +0800
Subject: [PATCH 14/15] add comments
---
clang/lib/AST/ASTContext.cpp | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 7446251f8d1ab4..3c8458478d4e6a 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -15920,8 +15920,9 @@ struct PaddingCalculator {
// Oversized bit-fields (declared width larger than the field type) keep
// only the type's width as the value container. The extra declared bits
// are padding and follow that container (Itanium C++ ABI §2.4, II.1(b)).
- // getIntWidth may be narrower still (bool, _BitInt); those occupied bits
- // are the low-order bits of the value container.
+ // We use getTypeSize instead of getIntWidth
+ // because getIntWidth may be narrower still (bool, _BitInt);
+ // those occupied bits are the low-order bits of the value container.
const uint64_t OccupiedSizeInBits =
std::min(DeclaredSizeInBits,Ctx.getTypeSize(Field->getType()));
>From 243ddbaa99a1a2d975bc7aa4c59345f01fb613b8 Mon Sep 17 00:00:00 2001
From: Zile Xiong <xiongzile at bytedance.com>
Date: Wed, 30 Sep 2026 14:59:40 +0800
Subject: [PATCH 15/15] handle bool type in a special way
---
clang/lib/AST/ASTContext.cpp | 21 +-
.../builtin-clear-padding-codegen.cpp | 829 +++++++-----------
2 files changed, 332 insertions(+), 518 deletions(-)
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 3c8458478d4e6a..7d3af397ca889f 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -15917,14 +15917,17 @@ struct PaddingCalculator {
const uint64_t DeclaredSizeInBits = Field->getBitWidthValue();
- // Oversized bit-fields (declared width larger than the field type) keep
- // only the type's width as the value container. The extra declared bits
- // are padding and follow that container (Itanium C++ ABI §2.4, II.1(b)).
- // We use getTypeSize instead of getIntWidth
- // because getIntWidth may be narrower still (bool, _BitInt);
- // those occupied bits are the low-order bits of the value container.
+ // Oversized bit-fields (declared width larger than the field type) occupy
+ // only the type's width. The extra declared bits are padding and follow
+ // the occupied bits (Itanium C++ ABI §2.4, II.1(b)).
+ // A bool bit-field occupies its whole declared width up to the size of
+ // bool, like GCC. _BitInt(N) occupies only its N value bits.
+ const QualType FieldTy = Field->getType();
const uint64_t OccupiedSizeInBits =
- std::min(DeclaredSizeInBits,Ctx.getTypeSize(Field->getType()));
+ std::min(DeclaredSizeInBits,
+ FieldTy->isBooleanType()
+ ? Ctx.getTypeSize(FieldTy)
+ : static_cast<uint64_t>(Ctx.getIntWidth(FieldTy)));
if (Ctx.getTargetInfo().isLittleEndian()) {
OccuppiedIntervals.push_back(
@@ -15942,9 +15945,7 @@ struct PaddingCalculator {
// the partially occupied bytes in either end, if present, their bit
// intervals need to be adjusted so that they count from the MSB instead.
//
- // Within the value container, occupied bits are its low-order bits, which
- // are allocated last. Padding from an oversized declared width follows
- // the container.
+ // Occupied bits are allocated first, and any padding follows them.
const uint64_t Start = StartBitOffset;
const uint64_t End = Start + OccupiedSizeInBits;
const uint64_t CharWidth = Ctx.getCharWidth();
diff --git a/clang/test/CodeGenCXX/builtin-clear-padding-codegen.cpp b/clang/test/CodeGenCXX/builtin-clear-padding-codegen.cpp
index 9d5d23fe7449e9..3d649af81eed01 100644
--- a/clang/test/CodeGenCXX/builtin-clear-padding-codegen.cpp
+++ b/clang/test/CodeGenCXX/builtin-clear-padding-codegen.cpp
@@ -1732,185 +1732,97 @@ struct OversizedBitfield {
int c : 35;
};
-// ITANIUM64-LE-LABEL: define dso_local void @testOversizedBitfield(
-// ITANIUM64-LE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
-// ITANIUM64-LE-NEXT: [[ENTRY:.*:]]
-// ITANIUM64-LE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
-// ITANIUM64-LE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
-// ITANIUM64-LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
-// ITANIUM64-LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// ITANIUM64-LE-NEXT: store i8 0, ptr [[TMP1]], align 1
-// ITANIUM64-LE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// ITANIUM64-LE-NEXT: store i8 0, ptr [[TMP2]], align 2
-// ITANIUM64-LE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// ITANIUM64-LE-NEXT: store i8 0, ptr [[TMP3]], align 1
-// ITANIUM64-LE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
-// ITANIUM64-LE-NEXT: store i8 0, ptr [[TMP4]], align 4
-// ITANIUM64-LE-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
-// ITANIUM64-LE-NEXT: store i8 0, ptr [[TMP5]], align 1
-// ITANIUM64-LE-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
-// ITANIUM64-LE-NEXT: store i8 0, ptr [[TMP6]], align 2
-// ITANIUM64-LE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
-// ITANIUM64-LE-NEXT: store i8 0, ptr [[TMP7]], align 1
-// ITANIUM64-LE-NEXT: ret void
-//
-// ARM-LE-LABEL: define dso_local void @testOversizedBitfield(
-// ARM-LE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
-// ARM-LE-NEXT: [[ENTRY:.*:]]
-// ARM-LE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
-// ARM-LE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
-// ARM-LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
-// ARM-LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// ARM-LE-NEXT: store i8 0, ptr [[TMP1]], align 1
-// ARM-LE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// ARM-LE-NEXT: store i8 0, ptr [[TMP2]], align 2
-// ARM-LE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// ARM-LE-NEXT: store i8 0, ptr [[TMP3]], align 1
-// ARM-LE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
-// ARM-LE-NEXT: store i8 0, ptr [[TMP4]], align 4
-// ARM-LE-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
-// ARM-LE-NEXT: store i8 0, ptr [[TMP5]], align 1
-// ARM-LE-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
-// ARM-LE-NEXT: store i8 0, ptr [[TMP6]], align 2
-// ARM-LE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
-// ARM-LE-NEXT: store i8 0, ptr [[TMP7]], align 1
-// ARM-LE-NEXT: ret void
-//
-// ARM-BE-LABEL: define dso_local void @testOversizedBitfield(
-// ARM-BE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
-// ARM-BE-NEXT: [[ENTRY:.*:]]
-// ARM-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
-// ARM-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
-// ARM-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
-// ARM-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// ARM-BE-NEXT: store i8 0, ptr [[TMP1]], align 1
-// ARM-BE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// ARM-BE-NEXT: store i8 0, ptr [[TMP2]], align 2
-// ARM-BE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// ARM-BE-NEXT: store i8 0, ptr [[TMP3]], align 1
-// ARM-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
-// ARM-BE-NEXT: store i8 0, ptr [[TMP4]], align 4
-// ARM-BE-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
-// ARM-BE-NEXT: store i8 0, ptr [[TMP5]], align 1
-// ARM-BE-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
-// ARM-BE-NEXT: store i8 0, ptr [[TMP6]], align 2
-// ARM-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
-// ARM-BE-NEXT: store i8 0, ptr [[TMP7]], align 1
-// ARM-BE-NEXT: ret void
+// ITANIUM64-LABEL: define dso_local void @testOversizedBitfield(
+// ITANIUM64-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// ITANIUM64-NEXT: [[ENTRY:.*:]]
+// ITANIUM64-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// ITANIUM64-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// ITANIUM64-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
+// ITANIUM64-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// ITANIUM64-NEXT: store i8 0, ptr [[TMP1]], align 1
+// ITANIUM64-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
+// ITANIUM64-NEXT: store i8 0, ptr [[TMP2]], align 2
+// ITANIUM64-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
+// ITANIUM64-NEXT: store i8 0, ptr [[TMP3]], align 1
+// ITANIUM64-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
+// ITANIUM64-NEXT: store i8 0, ptr [[TMP4]], align 4
+// ITANIUM64-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
+// ITANIUM64-NEXT: store i8 0, ptr [[TMP5]], align 1
+// ITANIUM64-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
+// ITANIUM64-NEXT: store i8 0, ptr [[TMP6]], align 2
+// ITANIUM64-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
+// ITANIUM64-NEXT: store i8 0, ptr [[TMP7]], align 1
+// ITANIUM64-NEXT: ret void
//
-// AARCH64-BE-LABEL: define dso_local void @testOversizedBitfield(
-// AARCH64-BE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
-// AARCH64-BE-NEXT: [[ENTRY:.*:]]
-// AARCH64-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
-// AARCH64-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
-// AARCH64-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
-// AARCH64-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP1]], align 1
-// AARCH64-BE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP2]], align 2
-// AARCH64-BE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP3]], align 1
-// AARCH64-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP4]], align 4
-// AARCH64-BE-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP5]], align 1
-// AARCH64-BE-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP6]], align 2
-// AARCH64-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP7]], align 1
-// AARCH64-BE-NEXT: ret void
+// ARM-LABEL: define dso_local void @testOversizedBitfield(
+// ARM-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// ARM-NEXT: [[ENTRY:.*:]]
+// ARM-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// ARM-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// ARM-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
+// ARM-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// ARM-NEXT: store i8 0, ptr [[TMP1]], align 1
+// ARM-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
+// ARM-NEXT: store i8 0, ptr [[TMP2]], align 2
+// ARM-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
+// ARM-NEXT: store i8 0, ptr [[TMP3]], align 1
+// ARM-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
+// ARM-NEXT: store i8 0, ptr [[TMP4]], align 4
+// ARM-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
+// ARM-NEXT: store i8 0, ptr [[TMP5]], align 1
+// ARM-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
+// ARM-NEXT: store i8 0, ptr [[TMP6]], align 2
+// ARM-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
+// ARM-NEXT: store i8 0, ptr [[TMP7]], align 1
+// ARM-NEXT: ret void
//
extern "C" void testOversizedBitfield(struct OversizedBitfield *s) {
__builtin_clear_padding(s);
}
-// ITANIUM64-LE-LABEL: define dso_local void @testOversizedBitfieldVolatileStruct(
-// ITANIUM64-LE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
-// ITANIUM64-LE-NEXT: [[ENTRY:.*:]]
-// ITANIUM64-LE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
-// ITANIUM64-LE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
-// ITANIUM64-LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
-// ITANIUM64-LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// ITANIUM64-LE-NEXT: store i8 0, ptr [[TMP1]], align 1
-// ITANIUM64-LE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// ITANIUM64-LE-NEXT: store i8 0, ptr [[TMP2]], align 2
-// ITANIUM64-LE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// ITANIUM64-LE-NEXT: store i8 0, ptr [[TMP3]], align 1
-// ITANIUM64-LE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
-// ITANIUM64-LE-NEXT: store i8 0, ptr [[TMP4]], align 4
-// ITANIUM64-LE-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
-// ITANIUM64-LE-NEXT: store i8 0, ptr [[TMP5]], align 1
-// ITANIUM64-LE-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
-// ITANIUM64-LE-NEXT: store i8 0, ptr [[TMP6]], align 2
-// ITANIUM64-LE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
-// ITANIUM64-LE-NEXT: store i8 0, ptr [[TMP7]], align 1
-// ITANIUM64-LE-NEXT: ret void
-//
-// ARM-LE-LABEL: define dso_local void @testOversizedBitfieldVolatileStruct(
-// ARM-LE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
-// ARM-LE-NEXT: [[ENTRY:.*:]]
-// ARM-LE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
-// ARM-LE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
-// ARM-LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
-// ARM-LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// ARM-LE-NEXT: store i8 0, ptr [[TMP1]], align 1
-// ARM-LE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// ARM-LE-NEXT: store i8 0, ptr [[TMP2]], align 2
-// ARM-LE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// ARM-LE-NEXT: store i8 0, ptr [[TMP3]], align 1
-// ARM-LE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
-// ARM-LE-NEXT: store i8 0, ptr [[TMP4]], align 4
-// ARM-LE-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
-// ARM-LE-NEXT: store i8 0, ptr [[TMP5]], align 1
-// ARM-LE-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
-// ARM-LE-NEXT: store i8 0, ptr [[TMP6]], align 2
-// ARM-LE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
-// ARM-LE-NEXT: store i8 0, ptr [[TMP7]], align 1
-// ARM-LE-NEXT: ret void
-//
-// ARM-BE-LABEL: define dso_local void @testOversizedBitfieldVolatileStruct(
-// ARM-BE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
-// ARM-BE-NEXT: [[ENTRY:.*:]]
-// ARM-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
-// ARM-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
-// ARM-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
-// ARM-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// ARM-BE-NEXT: store i8 0, ptr [[TMP1]], align 1
-// ARM-BE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// ARM-BE-NEXT: store i8 0, ptr [[TMP2]], align 2
-// ARM-BE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// ARM-BE-NEXT: store i8 0, ptr [[TMP3]], align 1
-// ARM-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
-// ARM-BE-NEXT: store i8 0, ptr [[TMP4]], align 4
-// ARM-BE-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
-// ARM-BE-NEXT: store i8 0, ptr [[TMP5]], align 1
-// ARM-BE-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
-// ARM-BE-NEXT: store i8 0, ptr [[TMP6]], align 2
-// ARM-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
-// ARM-BE-NEXT: store i8 0, ptr [[TMP7]], align 1
-// ARM-BE-NEXT: ret void
+// ITANIUM64-LABEL: define dso_local void @testOversizedBitfieldVolatileStruct(
+// ITANIUM64-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// ITANIUM64-NEXT: [[ENTRY:.*:]]
+// ITANIUM64-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// ITANIUM64-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// ITANIUM64-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
+// ITANIUM64-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// ITANIUM64-NEXT: store i8 0, ptr [[TMP1]], align 1
+// ITANIUM64-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
+// ITANIUM64-NEXT: store i8 0, ptr [[TMP2]], align 2
+// ITANIUM64-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
+// ITANIUM64-NEXT: store i8 0, ptr [[TMP3]], align 1
+// ITANIUM64-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
+// ITANIUM64-NEXT: store i8 0, ptr [[TMP4]], align 4
+// ITANIUM64-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
+// ITANIUM64-NEXT: store i8 0, ptr [[TMP5]], align 1
+// ITANIUM64-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
+// ITANIUM64-NEXT: store i8 0, ptr [[TMP6]], align 2
+// ITANIUM64-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
+// ITANIUM64-NEXT: store i8 0, ptr [[TMP7]], align 1
+// ITANIUM64-NEXT: ret void
//
-// AARCH64-BE-LABEL: define dso_local void @testOversizedBitfieldVolatileStruct(
-// AARCH64-BE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
-// AARCH64-BE-NEXT: [[ENTRY:.*:]]
-// AARCH64-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
-// AARCH64-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
-// AARCH64-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
-// AARCH64-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP1]], align 1
-// AARCH64-BE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP2]], align 2
-// AARCH64-BE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP3]], align 1
-// AARCH64-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP4]], align 4
-// AARCH64-BE-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP5]], align 1
-// AARCH64-BE-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP6]], align 2
-// AARCH64-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP7]], align 1
-// AARCH64-BE-NEXT: ret void
+// ARM-LABEL: define dso_local void @testOversizedBitfieldVolatileStruct(
+// ARM-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// ARM-NEXT: [[ENTRY:.*:]]
+// ARM-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// ARM-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// ARM-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
+// ARM-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// ARM-NEXT: store i8 0, ptr [[TMP1]], align 1
+// ARM-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
+// ARM-NEXT: store i8 0, ptr [[TMP2]], align 2
+// ARM-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
+// ARM-NEXT: store i8 0, ptr [[TMP3]], align 1
+// ARM-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
+// ARM-NEXT: store i8 0, ptr [[TMP4]], align 4
+// ARM-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
+// ARM-NEXT: store i8 0, ptr [[TMP5]], align 1
+// ARM-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
+// ARM-NEXT: store i8 0, ptr [[TMP6]], align 2
+// ARM-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
+// ARM-NEXT: store i8 0, ptr [[TMP7]], align 1
+// ARM-NEXT: ret void
//
extern "C" void testOversizedBitfieldVolatileStruct(
volatile struct OversizedBitfield *s) {
@@ -1923,186 +1835,98 @@ struct VolatileOversizedBitfield {
volatile int c : 35;
};
-// ITANIUM64-LE-LABEL: define dso_local void @testVolatileOversizedBitfield(
-// ITANIUM64-LE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
-// ITANIUM64-LE-NEXT: [[ENTRY:.*:]]
-// ITANIUM64-LE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
-// ITANIUM64-LE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
-// ITANIUM64-LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
-// ITANIUM64-LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// ITANIUM64-LE-NEXT: store i8 0, ptr [[TMP1]], align 1
-// ITANIUM64-LE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// ITANIUM64-LE-NEXT: store i8 0, ptr [[TMP2]], align 2
-// ITANIUM64-LE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// ITANIUM64-LE-NEXT: store i8 0, ptr [[TMP3]], align 1
-// ITANIUM64-LE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
-// ITANIUM64-LE-NEXT: store i8 0, ptr [[TMP4]], align 4
-// ITANIUM64-LE-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
-// ITANIUM64-LE-NEXT: store i8 0, ptr [[TMP5]], align 1
-// ITANIUM64-LE-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
-// ITANIUM64-LE-NEXT: store i8 0, ptr [[TMP6]], align 2
-// ITANIUM64-LE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
-// ITANIUM64-LE-NEXT: store i8 0, ptr [[TMP7]], align 1
-// ITANIUM64-LE-NEXT: ret void
-//
-// ARM-LE-LABEL: define dso_local void @testVolatileOversizedBitfield(
-// ARM-LE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
-// ARM-LE-NEXT: [[ENTRY:.*:]]
-// ARM-LE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
-// ARM-LE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
-// ARM-LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
-// ARM-LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// ARM-LE-NEXT: store i8 0, ptr [[TMP1]], align 1
-// ARM-LE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// ARM-LE-NEXT: store i8 0, ptr [[TMP2]], align 2
-// ARM-LE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// ARM-LE-NEXT: store i8 0, ptr [[TMP3]], align 1
-// ARM-LE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
-// ARM-LE-NEXT: store i8 0, ptr [[TMP4]], align 4
-// ARM-LE-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
-// ARM-LE-NEXT: store i8 0, ptr [[TMP5]], align 1
-// ARM-LE-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
-// ARM-LE-NEXT: store i8 0, ptr [[TMP6]], align 2
-// ARM-LE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
-// ARM-LE-NEXT: store i8 0, ptr [[TMP7]], align 1
-// ARM-LE-NEXT: ret void
-//
-// ARM-BE-LABEL: define dso_local void @testVolatileOversizedBitfield(
-// ARM-BE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
-// ARM-BE-NEXT: [[ENTRY:.*:]]
-// ARM-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
-// ARM-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
-// ARM-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
-// ARM-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// ARM-BE-NEXT: store i8 0, ptr [[TMP1]], align 1
-// ARM-BE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// ARM-BE-NEXT: store i8 0, ptr [[TMP2]], align 2
-// ARM-BE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// ARM-BE-NEXT: store i8 0, ptr [[TMP3]], align 1
-// ARM-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
-// ARM-BE-NEXT: store i8 0, ptr [[TMP4]], align 4
-// ARM-BE-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
-// ARM-BE-NEXT: store i8 0, ptr [[TMP5]], align 1
-// ARM-BE-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
-// ARM-BE-NEXT: store i8 0, ptr [[TMP6]], align 2
-// ARM-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
-// ARM-BE-NEXT: store i8 0, ptr [[TMP7]], align 1
-// ARM-BE-NEXT: ret void
+// ITANIUM64-LABEL: define dso_local void @testVolatileOversizedBitfield(
+// ITANIUM64-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// ITANIUM64-NEXT: [[ENTRY:.*:]]
+// ITANIUM64-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// ITANIUM64-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// ITANIUM64-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
+// ITANIUM64-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// ITANIUM64-NEXT: store i8 0, ptr [[TMP1]], align 1
+// ITANIUM64-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
+// ITANIUM64-NEXT: store i8 0, ptr [[TMP2]], align 2
+// ITANIUM64-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
+// ITANIUM64-NEXT: store i8 0, ptr [[TMP3]], align 1
+// ITANIUM64-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
+// ITANIUM64-NEXT: store i8 0, ptr [[TMP4]], align 4
+// ITANIUM64-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
+// ITANIUM64-NEXT: store i8 0, ptr [[TMP5]], align 1
+// ITANIUM64-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
+// ITANIUM64-NEXT: store i8 0, ptr [[TMP6]], align 2
+// ITANIUM64-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
+// ITANIUM64-NEXT: store i8 0, ptr [[TMP7]], align 1
+// ITANIUM64-NEXT: ret void
//
-// AARCH64-BE-LABEL: define dso_local void @testVolatileOversizedBitfield(
-// AARCH64-BE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
-// AARCH64-BE-NEXT: [[ENTRY:.*:]]
-// AARCH64-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
-// AARCH64-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
-// AARCH64-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
-// AARCH64-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP1]], align 1
-// AARCH64-BE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP2]], align 2
-// AARCH64-BE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP3]], align 1
-// AARCH64-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP4]], align 4
-// AARCH64-BE-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP5]], align 1
-// AARCH64-BE-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP6]], align 2
-// AARCH64-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP7]], align 1
-// AARCH64-BE-NEXT: ret void
+// ARM-LABEL: define dso_local void @testVolatileOversizedBitfield(
+// ARM-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// ARM-NEXT: [[ENTRY:.*:]]
+// ARM-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// ARM-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// ARM-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
+// ARM-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// ARM-NEXT: store i8 0, ptr [[TMP1]], align 1
+// ARM-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
+// ARM-NEXT: store i8 0, ptr [[TMP2]], align 2
+// ARM-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
+// ARM-NEXT: store i8 0, ptr [[TMP3]], align 1
+// ARM-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
+// ARM-NEXT: store i8 0, ptr [[TMP4]], align 4
+// ARM-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
+// ARM-NEXT: store i8 0, ptr [[TMP5]], align 1
+// ARM-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
+// ARM-NEXT: store i8 0, ptr [[TMP6]], align 2
+// ARM-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
+// ARM-NEXT: store i8 0, ptr [[TMP7]], align 1
+// ARM-NEXT: ret void
//
extern "C" void testVolatileOversizedBitfield(
struct VolatileOversizedBitfield *s) {
__builtin_clear_padding(s);
}
-// ITANIUM64-LE-LABEL: define dso_local void @testVolatileOversizedBitfieldVolatileStruct(
-// ITANIUM64-LE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
-// ITANIUM64-LE-NEXT: [[ENTRY:.*:]]
-// ITANIUM64-LE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
-// ITANIUM64-LE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
-// ITANIUM64-LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
-// ITANIUM64-LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// ITANIUM64-LE-NEXT: store i8 0, ptr [[TMP1]], align 1
-// ITANIUM64-LE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// ITANIUM64-LE-NEXT: store i8 0, ptr [[TMP2]], align 2
-// ITANIUM64-LE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// ITANIUM64-LE-NEXT: store i8 0, ptr [[TMP3]], align 1
-// ITANIUM64-LE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
-// ITANIUM64-LE-NEXT: store i8 0, ptr [[TMP4]], align 4
-// ITANIUM64-LE-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
-// ITANIUM64-LE-NEXT: store i8 0, ptr [[TMP5]], align 1
-// ITANIUM64-LE-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
-// ITANIUM64-LE-NEXT: store i8 0, ptr [[TMP6]], align 2
-// ITANIUM64-LE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
-// ITANIUM64-LE-NEXT: store i8 0, ptr [[TMP7]], align 1
-// ITANIUM64-LE-NEXT: ret void
-//
-// ARM-LE-LABEL: define dso_local void @testVolatileOversizedBitfieldVolatileStruct(
-// ARM-LE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
-// ARM-LE-NEXT: [[ENTRY:.*:]]
-// ARM-LE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
-// ARM-LE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
-// ARM-LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
-// ARM-LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// ARM-LE-NEXT: store i8 0, ptr [[TMP1]], align 1
-// ARM-LE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// ARM-LE-NEXT: store i8 0, ptr [[TMP2]], align 2
-// ARM-LE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// ARM-LE-NEXT: store i8 0, ptr [[TMP3]], align 1
-// ARM-LE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
-// ARM-LE-NEXT: store i8 0, ptr [[TMP4]], align 4
-// ARM-LE-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
-// ARM-LE-NEXT: store i8 0, ptr [[TMP5]], align 1
-// ARM-LE-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
-// ARM-LE-NEXT: store i8 0, ptr [[TMP6]], align 2
-// ARM-LE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
-// ARM-LE-NEXT: store i8 0, ptr [[TMP7]], align 1
-// ARM-LE-NEXT: ret void
-//
-// ARM-BE-LABEL: define dso_local void @testVolatileOversizedBitfieldVolatileStruct(
-// ARM-BE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
-// ARM-BE-NEXT: [[ENTRY:.*:]]
-// ARM-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
-// ARM-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
-// ARM-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
-// ARM-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// ARM-BE-NEXT: store i8 0, ptr [[TMP1]], align 1
-// ARM-BE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// ARM-BE-NEXT: store i8 0, ptr [[TMP2]], align 2
-// ARM-BE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// ARM-BE-NEXT: store i8 0, ptr [[TMP3]], align 1
-// ARM-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
-// ARM-BE-NEXT: store i8 0, ptr [[TMP4]], align 4
-// ARM-BE-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
-// ARM-BE-NEXT: store i8 0, ptr [[TMP5]], align 1
-// ARM-BE-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
-// ARM-BE-NEXT: store i8 0, ptr [[TMP6]], align 2
-// ARM-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
-// ARM-BE-NEXT: store i8 0, ptr [[TMP7]], align 1
-// ARM-BE-NEXT: ret void
+// ITANIUM64-LABEL: define dso_local void @testVolatileOversizedBitfieldVolatileStruct(
+// ITANIUM64-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// ITANIUM64-NEXT: [[ENTRY:.*:]]
+// ITANIUM64-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// ITANIUM64-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// ITANIUM64-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
+// ITANIUM64-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// ITANIUM64-NEXT: store i8 0, ptr [[TMP1]], align 1
+// ITANIUM64-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
+// ITANIUM64-NEXT: store i8 0, ptr [[TMP2]], align 2
+// ITANIUM64-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
+// ITANIUM64-NEXT: store i8 0, ptr [[TMP3]], align 1
+// ITANIUM64-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
+// ITANIUM64-NEXT: store i8 0, ptr [[TMP4]], align 4
+// ITANIUM64-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
+// ITANIUM64-NEXT: store i8 0, ptr [[TMP5]], align 1
+// ITANIUM64-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
+// ITANIUM64-NEXT: store i8 0, ptr [[TMP6]], align 2
+// ITANIUM64-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
+// ITANIUM64-NEXT: store i8 0, ptr [[TMP7]], align 1
+// ITANIUM64-NEXT: ret void
//
-// AARCH64-BE-LABEL: define dso_local void @testVolatileOversizedBitfieldVolatileStruct(
-// AARCH64-BE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
-// AARCH64-BE-NEXT: [[ENTRY:.*:]]
-// AARCH64-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
-// AARCH64-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
-// AARCH64-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
-// AARCH64-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP1]], align 1
-// AARCH64-BE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP2]], align 2
-// AARCH64-BE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP3]], align 1
-// AARCH64-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP4]], align 4
-// AARCH64-BE-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP5]], align 1
-// AARCH64-BE-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP6]], align 2
-// AARCH64-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP7]], align 1
-// AARCH64-BE-NEXT: ret void
+// ARM-LABEL: define dso_local void @testVolatileOversizedBitfieldVolatileStruct(
+// ARM-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// ARM-NEXT: [[ENTRY:.*:]]
+// ARM-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// ARM-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// ARM-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
+// ARM-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// ARM-NEXT: store i8 0, ptr [[TMP1]], align 1
+// ARM-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
+// ARM-NEXT: store i8 0, ptr [[TMP2]], align 2
+// ARM-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
+// ARM-NEXT: store i8 0, ptr [[TMP3]], align 1
+// ARM-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12
+// ARM-NEXT: store i8 0, ptr [[TMP4]], align 4
+// ARM-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13
+// ARM-NEXT: store i8 0, ptr [[TMP5]], align 1
+// ARM-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14
+// ARM-NEXT: store i8 0, ptr [[TMP6]], align 2
+// ARM-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15
+// ARM-NEXT: store i8 0, ptr [[TMP7]], align 1
+// ARM-NEXT: ret void
//
extern "C" void testVolatileOversizedBitfieldVolatileStruct(
volatile struct VolatileOversizedBitfield *s) {
@@ -4748,113 +4572,55 @@ struct BitfieldOversizedAligned {
unsigned char value : 16;
};
-// ITANIUM64-LE-LABEL: define dso_local void @testBitfieldOversizedAligned(
-// ITANIUM64-LE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
-// ITANIUM64-LE-NEXT: [[ENTRY:.*:]]
-// ITANIUM64-LE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
-// ITANIUM64-LE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
-// ITANIUM64-LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
-// ITANIUM64-LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// ITANIUM64-LE-NEXT: store i8 0, ptr [[TMP1]], align 1
-// ITANIUM64-LE-NEXT: ret void
-//
-// ARM-LE-LABEL: define dso_local void @testBitfieldOversizedAligned(
-// ARM-LE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
-// ARM-LE-NEXT: [[ENTRY:.*:]]
-// ARM-LE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
-// ARM-LE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
-// ARM-LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
-// ARM-LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// ARM-LE-NEXT: store i8 0, ptr [[TMP1]], align 1
-// ARM-LE-NEXT: ret void
-//
-// ARM-BE-LABEL: define dso_local void @testBitfieldOversizedAligned(
-// ARM-BE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
-// ARM-BE-NEXT: [[ENTRY:.*:]]
-// ARM-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
-// ARM-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
-// ARM-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
-// ARM-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// ARM-BE-NEXT: store i8 0, ptr [[TMP1]], align 1
-// ARM-BE-NEXT: ret void
+// ITANIUM64-LABEL: define dso_local void @testBitfieldOversizedAligned(
+// ITANIUM64-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// ITANIUM64-NEXT: [[ENTRY:.*:]]
+// ITANIUM64-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// ITANIUM64-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// ITANIUM64-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
+// ITANIUM64-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// ITANIUM64-NEXT: store i8 0, ptr [[TMP1]], align 1
+// ITANIUM64-NEXT: ret void
//
-// AARCH64-BE-LABEL: define dso_local void @testBitfieldOversizedAligned(
-// AARCH64-BE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
-// AARCH64-BE-NEXT: [[ENTRY:.*:]]
-// AARCH64-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
-// AARCH64-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
-// AARCH64-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
-// AARCH64-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP1]], align 1
-// AARCH64-BE-NEXT: ret void
+// ARM-LABEL: define dso_local void @testBitfieldOversizedAligned(
+// ARM-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// ARM-NEXT: [[ENTRY:.*:]]
+// ARM-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// ARM-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// ARM-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
+// ARM-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// ARM-NEXT: store i8 0, ptr [[TMP1]], align 1
+// ARM-NEXT: ret void
//
extern "C" void testBitfieldOversizedAligned(BitfieldOversizedAligned *s) {
__builtin_clear_padding(s);
}
-// `bool : 16` stores true as 00000001 in the first byte on both endians.
-// clear_padding treats only that value bit as occupied (getIntWidth == 1).
-// The other seven bits of the first byte, and the whole second byte, are
-// cleared.
+// `bool : 16` occupies the whole first byte on both endians, like GCC. Only
+// the second byte is padding.
struct BitfieldOversizedBool {
bool value : 16;
};
-// ITANIUM64-LE-LABEL: define dso_local void @testBitfieldOversizedBool(
-// ITANIUM64-LE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
-// ITANIUM64-LE-NEXT: [[ENTRY:.*:]]
-// ITANIUM64-LE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
-// ITANIUM64-LE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
-// ITANIUM64-LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
-// ITANIUM64-LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
-// ITANIUM64-LE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 2
-// ITANIUM64-LE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 1
-// ITANIUM64-LE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 2
-// ITANIUM64-LE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// ITANIUM64-LE-NEXT: store i8 0, ptr [[TMP4]], align 1
-// ITANIUM64-LE-NEXT: ret void
-//
-// ARM-LE-LABEL: define dso_local void @testBitfieldOversizedBool(
-// ARM-LE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
-// ARM-LE-NEXT: [[ENTRY:.*:]]
-// ARM-LE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
-// ARM-LE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
-// ARM-LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
-// ARM-LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
-// ARM-LE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 2
-// ARM-LE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 1
-// ARM-LE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 2
-// ARM-LE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// ARM-LE-NEXT: store i8 0, ptr [[TMP4]], align 1
-// ARM-LE-NEXT: ret void
-//
-// ARM-BE-LABEL: define dso_local void @testBitfieldOversizedBool(
-// ARM-BE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
-// ARM-BE-NEXT: [[ENTRY:.*:]]
-// ARM-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
-// ARM-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
-// ARM-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
-// ARM-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
-// ARM-BE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 2
-// ARM-BE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 1
-// ARM-BE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 2
-// ARM-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// ARM-BE-NEXT: store i8 0, ptr [[TMP4]], align 1
-// ARM-BE-NEXT: ret void
+// ITANIUM64-LABEL: define dso_local void @testBitfieldOversizedBool(
+// ITANIUM64-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// ITANIUM64-NEXT: [[ENTRY:.*:]]
+// ITANIUM64-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// ITANIUM64-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// ITANIUM64-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
+// ITANIUM64-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// ITANIUM64-NEXT: store i8 0, ptr [[TMP1]], align 1
+// ITANIUM64-NEXT: ret void
//
-// AARCH64-BE-LABEL: define dso_local void @testBitfieldOversizedBool(
-// AARCH64-BE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
-// AARCH64-BE-NEXT: [[ENTRY:.*:]]
-// AARCH64-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
-// AARCH64-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
-// AARCH64-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
-// AARCH64-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
-// AARCH64-BE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 2
-// AARCH64-BE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 1
-// AARCH64-BE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 2
-// AARCH64-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP4]], align 1
-// AARCH64-BE-NEXT: ret void
+// ARM-LABEL: define dso_local void @testBitfieldOversizedBool(
+// ARM-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// ARM-NEXT: [[ENTRY:.*:]]
+// ARM-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// ARM-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// ARM-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
+// ARM-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// ARM-NEXT: store i8 0, ptr [[TMP1]], align 1
+// ARM-NEXT: ret void
//
extern "C" void testBitfieldOversizedBool(BitfieldOversizedBool *s) {
__builtin_clear_padding(s);
@@ -4865,61 +4631,33 @@ struct BitfieldOversizedBeyondBoundary {
unsigned char value : 17;
};
-// ITANIUM64-LE-LABEL: define dso_local void @testBitfieldOversizedBeyondBoundary(
-// ITANIUM64-LE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
-// ITANIUM64-LE-NEXT: [[ENTRY:.*:]]
-// ITANIUM64-LE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
-// ITANIUM64-LE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
-// ITANIUM64-LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
-// ITANIUM64-LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// ITANIUM64-LE-NEXT: store i8 0, ptr [[TMP1]], align 1
-// ITANIUM64-LE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// ITANIUM64-LE-NEXT: store i8 0, ptr [[TMP2]], align 2
-// ITANIUM64-LE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// ITANIUM64-LE-NEXT: store i8 0, ptr [[TMP3]], align 1
-// ITANIUM64-LE-NEXT: ret void
-//
-// ARM-LE-LABEL: define dso_local void @testBitfieldOversizedBeyondBoundary(
-// ARM-LE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
-// ARM-LE-NEXT: [[ENTRY:.*:]]
-// ARM-LE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
-// ARM-LE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
-// ARM-LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
-// ARM-LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// ARM-LE-NEXT: store i8 0, ptr [[TMP1]], align 1
-// ARM-LE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// ARM-LE-NEXT: store i8 0, ptr [[TMP2]], align 2
-// ARM-LE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// ARM-LE-NEXT: store i8 0, ptr [[TMP3]], align 1
-// ARM-LE-NEXT: ret void
-//
-// ARM-BE-LABEL: define dso_local void @testBitfieldOversizedBeyondBoundary(
-// ARM-BE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
-// ARM-BE-NEXT: [[ENTRY:.*:]]
-// ARM-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
-// ARM-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
-// ARM-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
-// ARM-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// ARM-BE-NEXT: store i8 0, ptr [[TMP1]], align 1
-// ARM-BE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// ARM-BE-NEXT: store i8 0, ptr [[TMP2]], align 2
-// ARM-BE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// ARM-BE-NEXT: store i8 0, ptr [[TMP3]], align 1
-// ARM-BE-NEXT: ret void
+// ITANIUM64-LABEL: define dso_local void @testBitfieldOversizedBeyondBoundary(
+// ITANIUM64-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// ITANIUM64-NEXT: [[ENTRY:.*:]]
+// ITANIUM64-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// ITANIUM64-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// ITANIUM64-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
+// ITANIUM64-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// ITANIUM64-NEXT: store i8 0, ptr [[TMP1]], align 1
+// ITANIUM64-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
+// ITANIUM64-NEXT: store i8 0, ptr [[TMP2]], align 2
+// ITANIUM64-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
+// ITANIUM64-NEXT: store i8 0, ptr [[TMP3]], align 1
+// ITANIUM64-NEXT: ret void
//
-// AARCH64-BE-LABEL: define dso_local void @testBitfieldOversizedBeyondBoundary(
-// AARCH64-BE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
-// AARCH64-BE-NEXT: [[ENTRY:.*:]]
-// AARCH64-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
-// AARCH64-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
-// AARCH64-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
-// AARCH64-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP1]], align 1
-// AARCH64-BE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP2]], align 2
-// AARCH64-BE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// AARCH64-BE-NEXT: store i8 0, ptr [[TMP3]], align 1
-// AARCH64-BE-NEXT: ret void
+// ARM-LABEL: define dso_local void @testBitfieldOversizedBeyondBoundary(
+// ARM-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// ARM-NEXT: [[ENTRY:.*:]]
+// ARM-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// ARM-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// ARM-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
+// ARM-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// ARM-NEXT: store i8 0, ptr [[TMP1]], align 1
+// ARM-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
+// ARM-NEXT: store i8 0, ptr [[TMP2]], align 2
+// ARM-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
+// ARM-NEXT: store i8 0, ptr [[TMP3]], align 1
+// ARM-NEXT: ret void
//
extern "C" void testBitfieldOversizedBeyondBoundary(
BitfieldOversizedBeyondBoundary *s) {
@@ -4943,7 +4681,7 @@ struct BitfieldOversizedValueTypes {
// ITANIUM64-LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// ITANIUM64-LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
// ITANIUM64-LE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 2
-// ITANIUM64-LE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 1
+// ITANIUM64-LE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 7
// ITANIUM64-LE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 2
// ITANIUM64-LE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
// ITANIUM64-LE-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 2
@@ -4963,7 +4701,7 @@ struct BitfieldOversizedValueTypes {
// ARM-LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// ARM-LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
// ARM-LE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 2
-// ARM-LE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 1
+// ARM-LE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 7
// ARM-LE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 2
// ARM-LE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
// ARM-LE-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 2
@@ -4985,14 +4723,14 @@ struct BitfieldOversizedValueTypes {
// ARM-BE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 2
// ARM-BE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], -32
// ARM-BE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 2
-// ARM-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
+// ARM-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
// ARM-BE-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 2
-// ARM-BE-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], 63
+// ARM-BE-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], 15
// ARM-BE-NEXT: store i8 [[TMP6]], ptr [[TMP4]], align 2
-// ARM-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// ARM-BE-NEXT: [[TMP8:%.*]] = load i8, ptr [[TMP7]], align 2
-// ARM-BE-NEXT: [[TMP9:%.*]] = and i8 [[TMP8]], 1
-// ARM-BE-NEXT: store i8 [[TMP9]], ptr [[TMP7]], align 2
+// ARM-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
+// ARM-BE-NEXT: [[TMP8:%.*]] = load i8, ptr [[TMP7]], align 1
+// ARM-BE-NEXT: [[TMP9:%.*]] = and i8 [[TMP8]], -8
+// ARM-BE-NEXT: store i8 [[TMP9]], ptr [[TMP7]], align 1
// ARM-BE-NEXT: ret void
//
// AARCH64-BE-LABEL: define dso_local void @testBitfieldOversizedValueTypes(
@@ -5005,14 +4743,14 @@ struct BitfieldOversizedValueTypes {
// AARCH64-BE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 2
// AARCH64-BE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], -32
// AARCH64-BE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 2
-// AARCH64-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
+// AARCH64-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
// AARCH64-BE-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 2
-// AARCH64-BE-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], 63
+// AARCH64-BE-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], 15
// AARCH64-BE-NEXT: store i8 [[TMP6]], ptr [[TMP4]], align 2
-// AARCH64-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
-// AARCH64-BE-NEXT: [[TMP8:%.*]] = load i8, ptr [[TMP7]], align 2
-// AARCH64-BE-NEXT: [[TMP9:%.*]] = and i8 [[TMP8]], 1
-// AARCH64-BE-NEXT: store i8 [[TMP9]], ptr [[TMP7]], align 2
+// AARCH64-BE-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
+// AARCH64-BE-NEXT: [[TMP8:%.*]] = load i8, ptr [[TMP7]], align 1
+// AARCH64-BE-NEXT: [[TMP9:%.*]] = and i8 [[TMP8]], -8
+// AARCH64-BE-NEXT: store i8 [[TMP9]], ptr [[TMP7]], align 1
// AARCH64-BE-NEXT: ret void
//
extern "C" void testBitfieldOversizedValueTypes(
@@ -5020,6 +4758,81 @@ extern "C" void testBitfieldOversizedValueTypes(
__builtin_clear_padding(s);
}
+// Within a single byte, padding follows the occupied bits: it is in the high
+// bits on little endian and in the low bits on big endian.
+struct BitfieldOversizedSubByte {
+ _BitInt(5) precise : 6;
+ bool flag : 6;
+};
+
+// ITANIUM64-LE-LABEL: define dso_local void @testBitfieldOversizedSubByte(
+// ITANIUM64-LE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// ITANIUM64-LE-NEXT: [[ENTRY:.*:]]
+// ITANIUM64-LE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// ITANIUM64-LE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// ITANIUM64-LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
+// ITANIUM64-LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
+// ITANIUM64-LE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 1
+// ITANIUM64-LE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 31
+// ITANIUM64-LE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 1
+// ITANIUM64-LE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// ITANIUM64-LE-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1
+// ITANIUM64-LE-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], 63
+// ITANIUM64-LE-NEXT: store i8 [[TMP6]], ptr [[TMP4]], align 1
+// ITANIUM64-LE-NEXT: ret void
+//
+// ARM-LE-LABEL: define dso_local void @testBitfieldOversizedSubByte(
+// ARM-LE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// ARM-LE-NEXT: [[ENTRY:.*:]]
+// ARM-LE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// ARM-LE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// ARM-LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
+// ARM-LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
+// ARM-LE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 1
+// ARM-LE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 31
+// ARM-LE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 1
+// ARM-LE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// ARM-LE-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1
+// ARM-LE-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], 63
+// ARM-LE-NEXT: store i8 [[TMP6]], ptr [[TMP4]], align 1
+// ARM-LE-NEXT: ret void
+//
+// ARM-BE-LABEL: define dso_local void @testBitfieldOversizedSubByte(
+// ARM-BE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// ARM-BE-NEXT: [[ENTRY:.*:]]
+// ARM-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// ARM-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// ARM-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
+// ARM-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
+// ARM-BE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 1
+// ARM-BE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], -8
+// ARM-BE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 1
+// ARM-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// ARM-BE-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1
+// ARM-BE-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], -4
+// ARM-BE-NEXT: store i8 [[TMP6]], ptr [[TMP4]], align 1
+// ARM-BE-NEXT: ret void
+//
+// AARCH64-BE-LABEL: define dso_local void @testBitfieldOversizedSubByte(
+// AARCH64-BE-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// AARCH64-BE-NEXT: [[ENTRY:.*:]]
+// AARCH64-BE-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// AARCH64-BE-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// AARCH64-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
+// AARCH64-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
+// AARCH64-BE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 1
+// AARCH64-BE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], -8
+// AARCH64-BE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 1
+// AARCH64-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// AARCH64-BE-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1
+// AARCH64-BE-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], -4
+// AARCH64-BE-NEXT: store i8 [[TMP6]], ptr [[TMP4]], align 1
+// AARCH64-BE-NEXT: ret void
+//
+extern "C" void testBitfieldOversizedSubByte(BitfieldOversizedSubByte *s) {
+ __builtin_clear_padding(s);
+}
+
#pragma clang diagnostic pop
#endif
More information about the cfe-commits
mailing list