https://github.com/xiongzile updated 
https://github.com/llvm/llvm-project/pull/225494

>From aa4b747ea45d05e37ec6f8d30b3f0dd1821c7d39 Mon Sep 17 00:00:00 2001
From: Elio <[email protected]>
Date: Wed, 23 Sep 2026 03:10:13 +0800
Subject: [PATCH 1/6] [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 d98d7c0c96dc3..56199dc18b794 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 0000000000000..8dc72c55f984d
--- /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 <[email protected]>
Date: Wed, 23 Sep 2026 03:10:14 +0800
Subject: [PATCH 2/6] [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 e74423ca8c8a1..f2d7ebcbd3c5e 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 7de1b0bb59fc5..599a8ba03c30d 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 <[email protected]>
Date: Wed, 23 Sep 2026 11:09:43 +0800
Subject: [PATCH 3/6] 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 f2d7ebcbd3c5e..c6554fc58f198 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 <[email protected]>
Date: Wed, 23 Sep 2026 11:23:18 +0800
Subject: [PATCH 4/6] 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 8dc72c55f984d..0e37c714e853d 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 <[email protected]>
Date: Wed, 23 Sep 2026 12:40:09 +0800
Subject: [PATCH 5/6] 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 0e37c714e853d..cad72482c372a 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 <[email protected]>
Date: Thu, 24 Sep 2026 14:11:19 +0800
Subject: [PATCH 6/6] 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 cad72482c372a..0dda596725bed 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;
+}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to