Author: Elio
Date: 2026-10-09T12:05:53+01:00
New Revision: f3c93acd6ecef3324c39af67a8a563b3a8dc6020

URL: 
https://github.com/llvm/llvm-project/commit/f3c93acd6ecef3324c39af67a8a563b3a8dc6020
DIFF: 
https://github.com/llvm/llvm-project/commit/f3c93acd6ecef3324c39af67a8a563b3a8dc6020.diff

LOG: [Clang] Fix oversized bit-field layout on big-endian targets (#225494)

Fixes #225361.

This patch fixes two issues related to bit-fields:

- **Big-endian CodeGen:** Clang incorrectly places the value bits of
oversized bit-fields after the padding bits, contrary to the Itanium C++
ABI (§2.4). Fix the layout so that value bits precede padding bits.
- **`__builtin_clear_padding` (LE and BE):** Correct the occupied-bit
calculation for bit-fields, including `bool` and `_BitInt`, by using
`min(declared width, type size)`. This preserves bits that should not be
treated as padding.

Added: 
    clang/test/CodeGenCXX/big-endian-oversized-bitfield.cpp

Modified: 
    clang/lib/AST/ASTContext.cpp
    clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
    clang/test/CodeGenCXX/builtin-clear-padding-codegen.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 58a761f11925c0..d2774b03151b2c 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -15972,13 +15972,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.
+    // 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)).
+    // In case where the bitfield can only have values with a range smaller 
than
+    // the one declared, e.g. bool a : 5 or _BitInt(5) b : 6, the remaining 
bits
+    // within the bitfield are for sign or zero extension. These are considered
+    // occupied as well.
     const uint64_t OccupiedSizeInBits =
-        std::min(DeclaredSizeInBits,
-                 static_cast<uint64_t>(Ctx.getIntWidth(Field->getType())));
+        std::min(DeclaredSizeInBits, Ctx.getTypeSize(Field->getType()));
 
     if (Ctx.getTargetInfo().isLittleEndian()) {
       OccuppiedIntervals.push_back(
@@ -15996,14 +15998,8 @@ 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.
-    const uint64_t Start =
-        StartBitOffset + DeclaredSizeInBits - OccupiedSizeInBits;
+    // 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/lib/CodeGen/CGRecordLayoutBuilder.cpp 
b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
index 6e7df1395350c8..0a5fd222b7d80b 100644
--- a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
+++ b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
@@ -223,6 +223,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/big-endian-oversized-bitfield.cpp 
b/clang/test/CodeGenCXX/big-endian-oversized-bitfield.cpp
new file mode 100644
index 00000000000000..da51f12b553ab9
--- /dev/null
+++ b/clang/test/CodeGenCXX/big-endian-oversized-bitfield.cpp
@@ -0,0 +1,83 @@
+// 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.
+// 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"
+
+struct S {
+  unsigned char value : 16;
+};
+
+// 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.
+// 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]]
+// 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.
+// 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;
+}
+
+// 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 7de1b0bb59fc5f..8b495d4336ea97 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,65 @@ 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.
+// `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 1
+// ITANIUM64-LE-NEXT:    store i8 0, ptr [[TMP1]], 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 1
+// ARM-LE-NEXT:    store i8 0, ptr [[TMP1]], 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 1
+// ARM-BE-NEXT:    store i8 0, ptr [[TMP1]], 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 1
+// AARCH64-BE-NEXT:    store i8 0, ptr [[TMP1]], 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;
 };
@@ -4928,18 +4881,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 +4895,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(
@@ -4984,16 +4925,12 @@ 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
 // ITANIUM64-LE-NEXT:    [[TMP6:%.*]] = and i8 [[TMP5]], -16
 // ITANIUM64-LE-NEXT:    store i8 [[TMP6]], ptr [[TMP4]], align 2
-// ITANIUM64-LE-NEXT:    [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// ITANIUM64-LE-NEXT:    [[TMP8:%.*]] = load i8, ptr [[TMP7]], align 1
-// ITANIUM64-LE-NEXT:    [[TMP9:%.*]] = and i8 [[TMP8]], 31
-// ITANIUM64-LE-NEXT:    store i8 [[TMP9]], ptr [[TMP7]], align 1
 // ITANIUM64-LE-NEXT:    ret void
 //
 // ARM-LE-LABEL: define dso_local void @testBitfieldOversizedValueTypes(
@@ -5004,16 +4941,12 @@ 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
 // ARM-LE-NEXT:    [[TMP6:%.*]] = and i8 [[TMP5]], -16
 // ARM-LE-NEXT:    store i8 [[TMP6]], ptr [[TMP4]], align 2
-// ARM-LE-NEXT:    [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
-// ARM-LE-NEXT:    [[TMP8:%.*]] = load i8, ptr [[TMP7]], align 1
-// ARM-LE-NEXT:    [[TMP9:%.*]] = and i8 [[TMP8]], 31
-// ARM-LE-NEXT:    store i8 [[TMP9]], ptr [[TMP7]], align 1
 // ARM-LE-NEXT:    ret void
 //
 // ARM-BE-LABEL: define dso_local void @testBitfieldOversizedValueTypes(
@@ -5026,18 +4959,10 @@ 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 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:    ret void
 //
 // AARCH64-BE-LABEL: define dso_local void @testBitfieldOversizedValueTypes(
@@ -5050,18 +4975,10 @@ 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 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:    ret void
 //
 extern "C" void testBitfieldOversizedValueTypes(
@@ -5069,6 +4986,82 @@ 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. The _BitInt(5)
+// field is kept up to the storage size of _BitInt(5), i.e. all 6 bits.
+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]], 63
+// 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]], 63
+// 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]], -4
+// 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]], -4
+// 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
 


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

Reply via email to