https://github.com/Michael137 updated 
https://github.com/llvm/llvm-project/pull/205813

>From 88a2a6036cae2a5437e43d1d270157fcce309971 Mon Sep 17 00:00:00 2001
From: Michael Buch <[email protected]>
Date: Thu, 25 Jun 2026 13:17:11 +0000
Subject: [PATCH] [clang][test] Add more tests for __builtin_clear_padding

Follow-up to https://github.com/llvm/llvm-project/pull/201102 which
fixed Clang's `__builtin_clear_padding` treatment of unnamed bitfields.

This patch adds some more test coverage (more layouts, and verifies IR).

Used Claude to generate the layouts. Manually ran
`llvm/utils/update_cc_test_checks.py` to generate the `CHECK`
directives and confirmed that the bit-masks in the IR match the expected
`__builtin_clear_padding` behaviour.

Assisted-by: claude
---
 .../CodeGen/builtin-clear-padding-codegen.c   | 249 ++++++++++++++++++
 .../builtin-clear-padding-codegen.cpp         | 249 ++++++++++++++++++
 2 files changed, 498 insertions(+)

diff --git a/clang/test/CodeGen/builtin-clear-padding-codegen.c 
b/clang/test/CodeGen/builtin-clear-padding-codegen.c
index 9d5e06c79fa94..c2602d8934bd7 100644
--- a/clang/test/CodeGen/builtin-clear-padding-codegen.c
+++ b/clang/test/CodeGen/builtin-clear-padding-codegen.c
@@ -991,3 +991,252 @@ void testAttributedLongDoubleType(LongDouble3Vec *v) {
   // long double elements occupy [0-9], [16-25], [32-41] on x86.
   __builtin_clear_padding(v);
 }
+
+struct UnnamedBitfieldSingleBit {
+  unsigned char a : 3;
+  unsigned char   : 1;
+  unsigned char b : 4;
+};
+
+// LINUX-LABEL: define dso_local void @testUnnamedBitfieldSingleBit(
+// LINUX-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// LINUX-NEXT:  [[ENTRY:.*:]]
+// LINUX-NEXT:    [[S_ADDR:%.*]] = alloca ptr, align 8
+// LINUX-NEXT:    store ptr [[S]], ptr [[S_ADDR]], align 8
+// LINUX-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
+// LINUX-NEXT:    [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
+// LINUX-NEXT:    [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 1
+// LINUX-NEXT:    [[TMP3:%.*]] = and i8 [[TMP2]], -9
+// LINUX-NEXT:    store i8 [[TMP3]], ptr [[TMP1]], align 1
+// LINUX-NEXT:    ret void
+//
+// WINDOWS-LABEL: define dso_local void @testUnnamedBitfieldSingleBit(
+// WINDOWS-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// WINDOWS-NEXT:  [[ENTRY:.*:]]
+// WINDOWS-NEXT:    [[S_ADDR:%.*]] = alloca ptr, align 8
+// WINDOWS-NEXT:    store ptr [[S]], ptr [[S_ADDR]], align 8
+// WINDOWS-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
+// WINDOWS-NEXT:    [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
+// WINDOWS-NEXT:    [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 1
+// WINDOWS-NEXT:    [[TMP3:%.*]] = and i8 [[TMP2]], -9
+// WINDOWS-NEXT:    store i8 [[TMP3]], ptr [[TMP1]], align 1
+// WINDOWS-NEXT:    ret void
+//
+void testUnnamedBitfieldSingleBit(struct UnnamedBitfieldSingleBit *s) {
+  // byte 0: a[bits 0-2], unnamed[bit 3], b[bits 4-7]
+  // bit 3 must be cleared
+  // Mask: 0b11110111 == -9
+  __builtin_clear_padding(s);
+}
+
+struct UnnamedBitfieldMiddle {
+  unsigned char a : 3;
+  unsigned char   : 2;
+  unsigned char b : 3;
+};
+
+// LINUX-LABEL: define dso_local void @testUnnamedBitfieldMiddle(
+// LINUX-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// LINUX-NEXT:  [[ENTRY:.*:]]
+// LINUX-NEXT:    [[S_ADDR:%.*]] = alloca ptr, align 8
+// LINUX-NEXT:    store ptr [[S]], ptr [[S_ADDR]], align 8
+// LINUX-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
+// LINUX-NEXT:    [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
+// LINUX-NEXT:    [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 1
+// LINUX-NEXT:    [[TMP3:%.*]] = and i8 [[TMP2]], -25
+// LINUX-NEXT:    store i8 [[TMP3]], ptr [[TMP1]], align 1
+// LINUX-NEXT:    ret void
+//
+// WINDOWS-LABEL: define dso_local void @testUnnamedBitfieldMiddle(
+// WINDOWS-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// WINDOWS-NEXT:  [[ENTRY:.*:]]
+// WINDOWS-NEXT:    [[S_ADDR:%.*]] = alloca ptr, align 8
+// WINDOWS-NEXT:    store ptr [[S]], ptr [[S_ADDR]], align 8
+// WINDOWS-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
+// WINDOWS-NEXT:    [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
+// WINDOWS-NEXT:    [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 1
+// WINDOWS-NEXT:    [[TMP3:%.*]] = and i8 [[TMP2]], -25
+// WINDOWS-NEXT:    store i8 [[TMP3]], ptr [[TMP1]], align 1
+// WINDOWS-NEXT:    ret void
+//
+void testUnnamedBitfieldMiddle(struct UnnamedBitfieldMiddle *s) {
+  // byte 0: a[0-2], unnamed[3-4], b[5-7]
+  // bits 3-4 must be cleared
+  // Mask: 0b11100111 == -25
+  __builtin_clear_padding(s);
+}
+
+struct UnnamedBitfieldSurrounding {
+  unsigned char   : 2;
+  unsigned char a : 4;
+  unsigned char   : 2;
+};
+
+// LINUX-LABEL: define dso_local void @testUnnamedBitfieldSurrounding(
+// LINUX-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// LINUX-NEXT:  [[ENTRY:.*:]]
+// LINUX-NEXT:    [[S_ADDR:%.*]] = alloca ptr, align 8
+// LINUX-NEXT:    store ptr [[S]], ptr [[S_ADDR]], align 8
+// LINUX-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
+// LINUX-NEXT:    [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
+// LINUX-NEXT:    [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 1
+// LINUX-NEXT:    [[TMP3:%.*]] = and i8 [[TMP2]], -4
+// LINUX-NEXT:    store i8 [[TMP3]], ptr [[TMP1]], align 1
+// LINUX-NEXT:    [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
+// LINUX-NEXT:    [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1
+// LINUX-NEXT:    [[TMP6:%.*]] = and i8 [[TMP5]], 63
+// LINUX-NEXT:    store i8 [[TMP6]], ptr [[TMP4]], align 1
+// LINUX-NEXT:    ret void
+//
+// WINDOWS-LABEL: define dso_local void @testUnnamedBitfieldSurrounding(
+// WINDOWS-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// WINDOWS-NEXT:  [[ENTRY:.*:]]
+// WINDOWS-NEXT:    [[S_ADDR:%.*]] = alloca ptr, align 8
+// WINDOWS-NEXT:    store ptr [[S]], ptr [[S_ADDR]], align 8
+// WINDOWS-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
+// WINDOWS-NEXT:    [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
+// WINDOWS-NEXT:    [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 1
+// WINDOWS-NEXT:    [[TMP3:%.*]] = and i8 [[TMP2]], -4
+// WINDOWS-NEXT:    store i8 [[TMP3]], ptr [[TMP1]], align 1
+// WINDOWS-NEXT:    [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
+// WINDOWS-NEXT:    [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1
+// WINDOWS-NEXT:    [[TMP6:%.*]] = and i8 [[TMP5]], 63
+// WINDOWS-NEXT:    store i8 [[TMP6]], ptr [[TMP4]], align 1
+// WINDOWS-NEXT:    ret void
+//
+void testUnnamedBitfieldSurrounding(struct UnnamedBitfieldSurrounding *s) {
+  // byte 0: unnamed[0-1], a[2-5], unnamed[6-7]
+  // bits 0-1 and 6-7 must be cleared
+  // Masks:
+  //   0b11111100 == -4
+  //   0b00111111 == 63
+  __builtin_clear_padding(s);
+}
+
+struct UnnamedZeroWidthBitfield {
+  unsigned char a : 4;
+  unsigned int  : 0;
+  unsigned int b : 4;
+};
+
+// LINUX-LABEL: define dso_local void @testUnnamedZeroWidthBitfield(
+// LINUX-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// LINUX-NEXT:  [[ENTRY:.*:]]
+// LINUX-NEXT:    [[S_ADDR:%.*]] = alloca ptr, align 8
+// LINUX-NEXT:    store ptr [[S]], ptr [[S_ADDR]], align 8
+// LINUX-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
+// LINUX-NEXT:    [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
+// LINUX-NEXT:    [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 4
+// LINUX-NEXT:    [[TMP3:%.*]] = and i8 [[TMP2]], 15
+// LINUX-NEXT:    store i8 [[TMP3]], ptr [[TMP1]], align 4
+// LINUX-NEXT:    [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// LINUX-NEXT:    store i8 0, ptr [[TMP4]], align 1
+// LINUX-NEXT:    [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
+// LINUX-NEXT:    store i8 0, ptr [[TMP5]], align 2
+// LINUX-NEXT:    [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
+// LINUX-NEXT:    store i8 0, ptr [[TMP6]], align 1
+// LINUX-NEXT:    [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 4
+// LINUX-NEXT:    [[TMP8:%.*]] = load i8, ptr [[TMP7]], align 4
+// LINUX-NEXT:    [[TMP9:%.*]] = and i8 [[TMP8]], 15
+// LINUX-NEXT:    store i8 [[TMP9]], ptr [[TMP7]], align 4
+// LINUX-NEXT:    [[TMP10:%.*]] = getelementptr i8, ptr [[TMP0]], i32 5
+// LINUX-NEXT:    store i8 0, ptr [[TMP10]], align 1
+// LINUX-NEXT:    [[TMP11:%.*]] = getelementptr i8, ptr [[TMP0]], i32 6
+// LINUX-NEXT:    store i8 0, ptr [[TMP11]], align 2
+// LINUX-NEXT:    [[TMP12:%.*]] = getelementptr i8, ptr [[TMP0]], i32 7
+// LINUX-NEXT:    store i8 0, ptr [[TMP12]], align 1
+// LINUX-NEXT:    ret void
+//
+// WINDOWS-LABEL: define dso_local void @testUnnamedZeroWidthBitfield(
+// WINDOWS-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// WINDOWS-NEXT:  [[ENTRY:.*:]]
+// WINDOWS-NEXT:    [[S_ADDR:%.*]] = alloca ptr, align 8
+// WINDOWS-NEXT:    store ptr [[S]], ptr [[S_ADDR]], align 8
+// WINDOWS-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
+// WINDOWS-NEXT:    [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
+// WINDOWS-NEXT:    [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 4
+// WINDOWS-NEXT:    [[TMP3:%.*]] = and i8 [[TMP2]], 15
+// WINDOWS-NEXT:    store i8 [[TMP3]], ptr [[TMP1]], align 4
+// WINDOWS-NEXT:    [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// WINDOWS-NEXT:    store i8 0, ptr [[TMP4]], align 1
+// WINDOWS-NEXT:    [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
+// WINDOWS-NEXT:    store i8 0, ptr [[TMP5]], align 2
+// WINDOWS-NEXT:    [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
+// WINDOWS-NEXT:    store i8 0, ptr [[TMP6]], align 1
+// WINDOWS-NEXT:    [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 4
+// WINDOWS-NEXT:    [[TMP8:%.*]] = load i8, ptr [[TMP7]], align 4
+// WINDOWS-NEXT:    [[TMP9:%.*]] = and i8 [[TMP8]], 15
+// WINDOWS-NEXT:    store i8 [[TMP9]], ptr [[TMP7]], align 4
+// WINDOWS-NEXT:    [[TMP10:%.*]] = getelementptr i8, ptr [[TMP0]], i32 5
+// WINDOWS-NEXT:    store i8 0, ptr [[TMP10]], align 1
+// WINDOWS-NEXT:    [[TMP11:%.*]] = getelementptr i8, ptr [[TMP0]], i32 6
+// WINDOWS-NEXT:    store i8 0, ptr [[TMP11]], align 2
+// WINDOWS-NEXT:    [[TMP12:%.*]] = getelementptr i8, ptr [[TMP0]], i32 7
+// WINDOWS-NEXT:    store i8 0, ptr [[TMP12]], align 1
+// WINDOWS-NEXT:    ret void
+//
+void testUnnamedZeroWidthBitfield(struct UnnamedZeroWidthBitfield *s) {
+  // byte 0: a[0-3], unnamed[4-7]
+  // bytes 1-3: struct padding
+  // bytes 4-7: b[bits 0-3], tail padding[bits 4-31]
+  //
+  // byte 0:   clear bits 4-7
+  //           mask: 0b00001111 == 15
+  //
+  // byte 1-3: clear all bits
+  //           3 x store i8 0
+  //
+  // byte 4-7: clear bits 4-31
+  //           mask: 0b00001111 == 15
+  //           3 x store i8 0
+  __builtin_clear_padding(s);
+}
+
+struct UnnamedBitfieldMultiByte {
+  unsigned short a : 4;
+  unsigned short   : 8;
+  unsigned short b : 4;
+};
+
+// LINUX-LABEL: define dso_local void @testUnnamedBitfieldMultiByte(
+// LINUX-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// LINUX-NEXT:  [[ENTRY:.*:]]
+// LINUX-NEXT:    [[S_ADDR:%.*]] = alloca ptr, align 8
+// LINUX-NEXT:    store ptr [[S]], ptr [[S_ADDR]], align 8
+// LINUX-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
+// LINUX-NEXT:    [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
+// LINUX-NEXT:    [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 2
+// LINUX-NEXT:    [[TMP3:%.*]] = and i8 [[TMP2]], 15
+// LINUX-NEXT:    store i8 [[TMP3]], ptr [[TMP1]], align 2
+// LINUX-NEXT:    [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// LINUX-NEXT:    [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1
+// LINUX-NEXT:    [[TMP6:%.*]] = and i8 [[TMP5]], -16
+// LINUX-NEXT:    store i8 [[TMP6]], ptr [[TMP4]], align 1
+// LINUX-NEXT:    ret void
+//
+// WINDOWS-LABEL: define dso_local void @testUnnamedBitfieldMultiByte(
+// WINDOWS-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// WINDOWS-NEXT:  [[ENTRY:.*:]]
+// WINDOWS-NEXT:    [[S_ADDR:%.*]] = alloca ptr, align 8
+// WINDOWS-NEXT:    store ptr [[S]], ptr [[S_ADDR]], align 8
+// WINDOWS-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
+// WINDOWS-NEXT:    [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
+// WINDOWS-NEXT:    [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 2
+// WINDOWS-NEXT:    [[TMP3:%.*]] = and i8 [[TMP2]], 15
+// WINDOWS-NEXT:    store i8 [[TMP3]], ptr [[TMP1]], align 2
+// WINDOWS-NEXT:    [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// WINDOWS-NEXT:    [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1
+// WINDOWS-NEXT:    [[TMP6:%.*]] = and i8 [[TMP5]], -16
+// WINDOWS-NEXT:    store i8 [[TMP6]], ptr [[TMP4]], align 1
+// WINDOWS-NEXT:    ret void
+//
+void testUnnamedBitfieldMultiByte(struct UnnamedBitfieldMultiByte *s) {
+  // 2 bytes: a[0-3], unnamed[4-11], b[12-15]
+  // byte 0: clear bits 4-7
+  // byte 1: clear bits 0-3
+  //
+  // Masks:
+  //   0b00001111 ==  15
+  //   0b11110000 == -16
+  __builtin_clear_padding(s);
+}
diff --git a/clang/test/CodeGenCXX/builtin-clear-padding-codegen.cpp 
b/clang/test/CodeGenCXX/builtin-clear-padding-codegen.cpp
index 05ea1265e75db..0705cc374ff09 100644
--- a/clang/test/CodeGenCXX/builtin-clear-padding-codegen.cpp
+++ b/clang/test/CodeGenCXX/builtin-clear-padding-codegen.cpp
@@ -1519,3 +1519,252 @@ void testAttributedLongDoubleType(LongDouble3Vec *v) {
   // long double elements occupy [0-9], [16-25], [32-41] on x86.
   __builtin_clear_padding(v);
 }
+
+struct UnnamedBitfieldSingleBit {
+  unsigned char a : 3;
+  unsigned char   : 1;
+  unsigned char b : 4;
+};
+
+// LINUX-LABEL: define dso_local void 
@_Z28testUnnamedBitfieldSingleBitP24UnnamedBitfieldSingleBit(
+// LINUX-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// LINUX-NEXT:  [[ENTRY:.*:]]
+// LINUX-NEXT:    [[S_ADDR:%.*]] = alloca ptr, align 8
+// LINUX-NEXT:    store ptr [[S]], ptr [[S_ADDR]], align 8
+// LINUX-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
+// LINUX-NEXT:    [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
+// LINUX-NEXT:    [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 1
+// LINUX-NEXT:    [[TMP3:%.*]] = and i8 [[TMP2]], -9
+// LINUX-NEXT:    store i8 [[TMP3]], ptr [[TMP1]], align 1
+// LINUX-NEXT:    ret void
+//
+// WINDOWS-LABEL: define dso_local void 
@_Z28testUnnamedBitfieldSingleBitP24UnnamedBitfieldSingleBit(
+// WINDOWS-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// WINDOWS-NEXT:  [[ENTRY:.*:]]
+// WINDOWS-NEXT:    [[S_ADDR:%.*]] = alloca ptr, align 8
+// WINDOWS-NEXT:    store ptr [[S]], ptr [[S_ADDR]], align 8
+// WINDOWS-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
+// WINDOWS-NEXT:    [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
+// WINDOWS-NEXT:    [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 1
+// WINDOWS-NEXT:    [[TMP3:%.*]] = and i8 [[TMP2]], -9
+// WINDOWS-NEXT:    store i8 [[TMP3]], ptr [[TMP1]], align 1
+// WINDOWS-NEXT:    ret void
+//
+void testUnnamedBitfieldSingleBit(struct UnnamedBitfieldSingleBit *s) {
+  // byte 0: a[bits 0-2], unnamed[bit 3], b[bits 4-7]
+  // bit 3 must be cleared
+  // Mask: 0b11110111 == -9
+  __builtin_clear_padding(s);
+}
+
+struct UnnamedBitfieldMiddle {
+  unsigned char a : 3;
+  unsigned char   : 2;
+  unsigned char b : 3;
+};
+
+// LINUX-LABEL: define dso_local void 
@_Z25testUnnamedBitfieldMiddleP21UnnamedBitfieldMiddle(
+// LINUX-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// LINUX-NEXT:  [[ENTRY:.*:]]
+// LINUX-NEXT:    [[S_ADDR:%.*]] = alloca ptr, align 8
+// LINUX-NEXT:    store ptr [[S]], ptr [[S_ADDR]], align 8
+// LINUX-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
+// LINUX-NEXT:    [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
+// LINUX-NEXT:    [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 1
+// LINUX-NEXT:    [[TMP3:%.*]] = and i8 [[TMP2]], -25
+// LINUX-NEXT:    store i8 [[TMP3]], ptr [[TMP1]], align 1
+// LINUX-NEXT:    ret void
+//
+// WINDOWS-LABEL: define dso_local void 
@_Z25testUnnamedBitfieldMiddleP21UnnamedBitfieldMiddle(
+// WINDOWS-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// WINDOWS-NEXT:  [[ENTRY:.*:]]
+// WINDOWS-NEXT:    [[S_ADDR:%.*]] = alloca ptr, align 8
+// WINDOWS-NEXT:    store ptr [[S]], ptr [[S_ADDR]], align 8
+// WINDOWS-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
+// WINDOWS-NEXT:    [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
+// WINDOWS-NEXT:    [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 1
+// WINDOWS-NEXT:    [[TMP3:%.*]] = and i8 [[TMP2]], -25
+// WINDOWS-NEXT:    store i8 [[TMP3]], ptr [[TMP1]], align 1
+// WINDOWS-NEXT:    ret void
+//
+void testUnnamedBitfieldMiddle(struct UnnamedBitfieldMiddle *s) {
+  // byte 0: a[0-2], unnamed[3-4], b[5-7]
+  // bits 3-4 must be cleared
+  // Mask: 0b11100111 == -25
+  __builtin_clear_padding(s);
+}
+
+struct UnnamedBitfieldSurrounding {
+  unsigned char   : 2;
+  unsigned char a : 4;
+  unsigned char   : 2;
+};
+
+// LINUX-LABEL: define dso_local void 
@_Z30testUnnamedBitfieldSurroundingP26UnnamedBitfieldSurrounding(
+// LINUX-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// LINUX-NEXT:  [[ENTRY:.*:]]
+// LINUX-NEXT:    [[S_ADDR:%.*]] = alloca ptr, align 8
+// LINUX-NEXT:    store ptr [[S]], ptr [[S_ADDR]], align 8
+// LINUX-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
+// LINUX-NEXT:    [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
+// LINUX-NEXT:    [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 1
+// LINUX-NEXT:    [[TMP3:%.*]] = and i8 [[TMP2]], -4
+// LINUX-NEXT:    store i8 [[TMP3]], ptr [[TMP1]], align 1
+// LINUX-NEXT:    [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
+// LINUX-NEXT:    [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1
+// LINUX-NEXT:    [[TMP6:%.*]] = and i8 [[TMP5]], 63
+// LINUX-NEXT:    store i8 [[TMP6]], ptr [[TMP4]], align 1
+// LINUX-NEXT:    ret void
+//
+// WINDOWS-LABEL: define dso_local void 
@_Z30testUnnamedBitfieldSurroundingP26UnnamedBitfieldSurrounding(
+// WINDOWS-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// WINDOWS-NEXT:  [[ENTRY:.*:]]
+// WINDOWS-NEXT:    [[S_ADDR:%.*]] = alloca ptr, align 8
+// WINDOWS-NEXT:    store ptr [[S]], ptr [[S_ADDR]], align 8
+// WINDOWS-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
+// WINDOWS-NEXT:    [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
+// WINDOWS-NEXT:    [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 1
+// WINDOWS-NEXT:    [[TMP3:%.*]] = and i8 [[TMP2]], -4
+// WINDOWS-NEXT:    store i8 [[TMP3]], ptr [[TMP1]], align 1
+// WINDOWS-NEXT:    [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
+// WINDOWS-NEXT:    [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1
+// WINDOWS-NEXT:    [[TMP6:%.*]] = and i8 [[TMP5]], 63
+// WINDOWS-NEXT:    store i8 [[TMP6]], ptr [[TMP4]], align 1
+// WINDOWS-NEXT:    ret void
+//
+void testUnnamedBitfieldSurrounding(struct UnnamedBitfieldSurrounding *s) {
+  // byte 0: unnamed[0-1], a[2-5], unnamed[6-7]
+  // bits 0-1 and 6-7 must be cleared
+  // Masks:
+  //   0b11111100 == -4
+  //   0b00111111 == 63
+  __builtin_clear_padding(s);
+}
+
+struct UnnamedZeroWidthBitfield {
+  unsigned char a : 4;
+  unsigned int  : 0;
+  unsigned int b : 4;
+};
+
+// LINUX-LABEL: define dso_local void 
@_Z28testUnnamedZeroWidthBitfieldP24UnnamedZeroWidthBitfield(
+// LINUX-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// LINUX-NEXT:  [[ENTRY:.*:]]
+// LINUX-NEXT:    [[S_ADDR:%.*]] = alloca ptr, align 8
+// LINUX-NEXT:    store ptr [[S]], ptr [[S_ADDR]], align 8
+// LINUX-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
+// LINUX-NEXT:    [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
+// LINUX-NEXT:    [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 4
+// LINUX-NEXT:    [[TMP3:%.*]] = and i8 [[TMP2]], 15
+// LINUX-NEXT:    store i8 [[TMP3]], ptr [[TMP1]], align 4
+// LINUX-NEXT:    [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// LINUX-NEXT:    store i8 0, ptr [[TMP4]], align 1
+// LINUX-NEXT:    [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
+// LINUX-NEXT:    store i8 0, ptr [[TMP5]], align 2
+// LINUX-NEXT:    [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
+// LINUX-NEXT:    store i8 0, ptr [[TMP6]], align 1
+// LINUX-NEXT:    [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 4
+// LINUX-NEXT:    [[TMP8:%.*]] = load i8, ptr [[TMP7]], align 4
+// LINUX-NEXT:    [[TMP9:%.*]] = and i8 [[TMP8]], 15
+// LINUX-NEXT:    store i8 [[TMP9]], ptr [[TMP7]], align 4
+// LINUX-NEXT:    [[TMP10:%.*]] = getelementptr i8, ptr [[TMP0]], i32 5
+// LINUX-NEXT:    store i8 0, ptr [[TMP10]], align 1
+// LINUX-NEXT:    [[TMP11:%.*]] = getelementptr i8, ptr [[TMP0]], i32 6
+// LINUX-NEXT:    store i8 0, ptr [[TMP11]], align 2
+// LINUX-NEXT:    [[TMP12:%.*]] = getelementptr i8, ptr [[TMP0]], i32 7
+// LINUX-NEXT:    store i8 0, ptr [[TMP12]], align 1
+// LINUX-NEXT:    ret void
+//
+// WINDOWS-LABEL: define dso_local void 
@_Z28testUnnamedZeroWidthBitfieldP24UnnamedZeroWidthBitfield(
+// WINDOWS-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// WINDOWS-NEXT:  [[ENTRY:.*:]]
+// WINDOWS-NEXT:    [[S_ADDR:%.*]] = alloca ptr, align 8
+// WINDOWS-NEXT:    store ptr [[S]], ptr [[S_ADDR]], align 8
+// WINDOWS-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
+// WINDOWS-NEXT:    [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
+// WINDOWS-NEXT:    [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 4
+// WINDOWS-NEXT:    [[TMP3:%.*]] = and i8 [[TMP2]], 15
+// WINDOWS-NEXT:    store i8 [[TMP3]], ptr [[TMP1]], align 4
+// WINDOWS-NEXT:    [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// WINDOWS-NEXT:    store i8 0, ptr [[TMP4]], align 1
+// WINDOWS-NEXT:    [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2
+// WINDOWS-NEXT:    store i8 0, ptr [[TMP5]], align 2
+// WINDOWS-NEXT:    [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3
+// WINDOWS-NEXT:    store i8 0, ptr [[TMP6]], align 1
+// WINDOWS-NEXT:    [[TMP7:%.*]] = getelementptr i8, ptr [[TMP0]], i32 4
+// WINDOWS-NEXT:    [[TMP8:%.*]] = load i8, ptr [[TMP7]], align 4
+// WINDOWS-NEXT:    [[TMP9:%.*]] = and i8 [[TMP8]], 15
+// WINDOWS-NEXT:    store i8 [[TMP9]], ptr [[TMP7]], align 4
+// WINDOWS-NEXT:    [[TMP10:%.*]] = getelementptr i8, ptr [[TMP0]], i32 5
+// WINDOWS-NEXT:    store i8 0, ptr [[TMP10]], align 1
+// WINDOWS-NEXT:    [[TMP11:%.*]] = getelementptr i8, ptr [[TMP0]], i32 6
+// WINDOWS-NEXT:    store i8 0, ptr [[TMP11]], align 2
+// WINDOWS-NEXT:    [[TMP12:%.*]] = getelementptr i8, ptr [[TMP0]], i32 7
+// WINDOWS-NEXT:    store i8 0, ptr [[TMP12]], align 1
+// WINDOWS-NEXT:    ret void
+//
+void testUnnamedZeroWidthBitfield(struct UnnamedZeroWidthBitfield *s) {
+  // byte 0: a[0-3], unnamed[4-7]
+  // bytes 1-3: struct padding
+  // bytes 4-7: b[bits 0-3], tail padding[bits 4-31]
+  //
+  // byte 0:   clear bits 4-7
+  //           mask: 0b00001111 == 15
+  //
+  // byte 1-3: clear all bits
+  //           3 x store i8 0
+  //
+  // byte 4-7: clear bits 4-31
+  //           mask: 0b00001111 == 15
+  //           3 x store i8 0
+  __builtin_clear_padding(s);
+}
+
+struct UnnamedBitfieldMultiByte {
+  unsigned short a : 4;
+  unsigned short   : 8;
+  unsigned short b : 4;
+};
+
+// LINUX-LABEL: define dso_local void 
@_Z28testUnnamedBitfieldMultiByteP24UnnamedBitfieldMultiByte(
+// LINUX-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// LINUX-NEXT:  [[ENTRY:.*:]]
+// LINUX-NEXT:    [[S_ADDR:%.*]] = alloca ptr, align 8
+// LINUX-NEXT:    store ptr [[S]], ptr [[S_ADDR]], align 8
+// LINUX-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
+// LINUX-NEXT:    [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
+// LINUX-NEXT:    [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 2
+// LINUX-NEXT:    [[TMP3:%.*]] = and i8 [[TMP2]], 15
+// LINUX-NEXT:    store i8 [[TMP3]], ptr [[TMP1]], align 2
+// LINUX-NEXT:    [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// LINUX-NEXT:    [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1
+// LINUX-NEXT:    [[TMP6:%.*]] = and i8 [[TMP5]], -16
+// LINUX-NEXT:    store i8 [[TMP6]], ptr [[TMP4]], align 1
+// LINUX-NEXT:    ret void
+//
+// WINDOWS-LABEL: define dso_local void 
@_Z28testUnnamedBitfieldMultiByteP24UnnamedBitfieldMultiByte(
+// WINDOWS-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] {
+// WINDOWS-NEXT:  [[ENTRY:.*:]]
+// WINDOWS-NEXT:    [[S_ADDR:%.*]] = alloca ptr, align 8
+// WINDOWS-NEXT:    store ptr [[S]], ptr [[S_ADDR]], align 8
+// WINDOWS-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
+// WINDOWS-NEXT:    [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0
+// WINDOWS-NEXT:    [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 2
+// WINDOWS-NEXT:    [[TMP3:%.*]] = and i8 [[TMP2]], 15
+// WINDOWS-NEXT:    store i8 [[TMP3]], ptr [[TMP1]], align 2
+// WINDOWS-NEXT:    [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1
+// WINDOWS-NEXT:    [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1
+// WINDOWS-NEXT:    [[TMP6:%.*]] = and i8 [[TMP5]], -16
+// WINDOWS-NEXT:    store i8 [[TMP6]], ptr [[TMP4]], align 1
+// WINDOWS-NEXT:    ret void
+//
+void testUnnamedBitfieldMultiByte(struct UnnamedBitfieldMultiByte *s) {
+  // 2 bytes: a[0-3], unnamed[4-11], b[12-15]
+  // byte 0: clear bits 4-7
+  // byte 1: clear bits 0-3
+  //
+  // Masks:
+  //   0b00001111 ==  15
+  //   0b11110000 == -16
+  __builtin_clear_padding(s);
+}

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

Reply via email to