llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-codegen @llvm/pr-subscribers-clang Author: Victor Campos (vhscampos) <details> <summary>Changes</summary> This patch fixes the padding clearing logic for bitfields. The padding clearing logic for bitfields is wrong for these cases: - Over-sized bitfields don't have their padding bits recognised as such. - In big endian mode, the occupied bits are wrongly determined because the different byte order is dismissed. Assisted-by: Codex. Used to help debugging. --- Patch is 311.48 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/216063.diff 3 Files Affected: - (modified) clang/lib/CodeGen/CGBuiltin.cpp (+66-4) - (modified) clang/test/CodeGen/builtin-clear-padding-codegen.c (+1909-58) - (modified) clang/test/CodeGenCXX/builtin-clear-padding-codegen.cpp (+2941-74) ``````````diff diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 13aff2ef13eb9..24b2987923e26 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -2672,6 +2672,69 @@ struct PaddingClearer { return CGF.getContext().getTypeSize(Ty); } + /// Compute the occupied bit intervals for a bitfield. + /// + /// In the case of little endian, the occupied bits are always contiguous so a + /// single interval is sufficient; whereas in big endian mode, the occupied + /// bits are not necessarily contiguous since the byte order is reversed. Care + /// is also taken if the bitfield is volatile because the field size and + /// offset can be different in this case. + SmallVector<BitInterval> + computeBitfieldOccupiedIntervals(const RecordDecl *RD, const FieldDecl *Field, + uint64_t StartBitOffset) const { + const CGRecordLayout &Layout = CGF.CGM.getTypes().getCGRecordLayout(RD); + const CGBitFieldInfo &Info = Layout.getBitFieldInfo(Field); + bool IsLittleEndian = CGF.getTarget().isLittleEndian(); + bool IsVolatile = Field->getType().isVolatileQualified() && + Info.VolatileStorageSize != 0 && + CGF.CGM.getTarget().getABI().starts_with("aapcs"); + + uint64_t DeclaredTySizeInBits = + getScalarOccupiedSizeInBits(Field->getType()); + // In case of over-sized bitfields, the number of bits actually occupied + // with values is smaller than the declared bitfield width (Info.Size). + uint64_t ValueSizeInBits = + std::min(static_cast<uint64_t>(Info.Size), DeclaredTySizeInBits); + + const uint64_t Offset = IsVolatile ? Info.VolatileOffset : Info.Offset; + + // This calculation looks different between volatile and non-volatile + // because StorageOffset is in bytes, whereas VolatileStorageOffset is in + // VolatileStorageSize units. + const uint64_t StorageOffset = + IsVolatile ? Info.VolatileStorageOffset.getQuantity() * + Info.VolatileStorageSize + : CGF.getContext().toBits(Info.StorageOffset); + + if (IsLittleEndian) + return {BitInterval{StartBitOffset + StorageOffset + Offset, + StartBitOffset + StorageOffset + Offset + + ValueSizeInBits}}; + + const uint64_t StorageSize = + IsVolatile ? Info.VolatileStorageSize : Info.StorageSize; + const uint64_t BitsInByte = CGF.getContext().getCharWidth(); + + SmallVector<BitInterval> Intervals; + + for (uint64_t Start = Offset, End = Start + ValueSizeInBits; Start < End; + Start = (Start + BitsInByte) & (~0UL << 3)) { + uint64_t ByteBoundaryStart = Start & (~0UL << 3); + uint64_t ByteBoundaryEnd = ByteBoundaryStart + BitsInByte; + uint64_t OffsetWithinByte = Start - ByteBoundaryStart; + uint64_t SizeWithinByte = + std::min(End - Start, BitsInByte - OffsetWithinByte); + uint64_t ByteOffset = StorageSize - ByteBoundaryEnd; + + BitInterval BI{StartBitOffset + StorageOffset + ByteOffset + + OffsetWithinByte, + StartBitOffset + StorageOffset + ByteOffset + + OffsetWithinByte + SizeWithinByte}; + Intervals.push_back(std::move(BI)); + } + return Intervals; + } + /// Compute the occupied bit intervals for a BitInt. /// /// In the case of little endian, the occupied bits are always contiguous so a @@ -2816,12 +2879,11 @@ struct PaddingClearer { if (Field->isUnnamedBitField()) continue; - auto FieldOffset = ASTLayout.getFieldOffset(Field->getFieldIndex()); if (Field->isBitField()) { - OccuppiedIntervals.push_back(BitInterval{ - StartBitOffset + FieldOffset, - StartBitOffset + FieldOffset + Field->getBitWidthValue()}); + OccuppiedIntervals.append( + computeBitfieldOccupiedIntervals(R, Field, StartBitOffset)); } else { + auto FieldOffset = ASTLayout.getFieldOffset(Field->getFieldIndex()); Stack.push_back(Data{StartBitOffset + FieldOffset, Field->getType(), /*VisitVirtualBase*/ true}); } diff --git a/clang/test/CodeGen/builtin-clear-padding-codegen.c b/clang/test/CodeGen/builtin-clear-padding-codegen.c index fceb7b623ba6d..7e709f4fcbf98 100644 --- a/clang/test/CodeGen/builtin-clear-padding-codegen.c +++ b/clang/test/CodeGen/builtin-clear-padding-codegen.c @@ -3,8 +3,8 @@ // RUN: %clang_cc1 -std=c11 -triple=x86_64-pc-windows-msvc -emit-llvm -o - %s | FileCheck %s --check-prefix=WINDOWS // RUN: %clang_cc1 -std=c11 -triple=armv7a-none-eabi -emit-llvm -o - %s | FileCheck %s --check-prefix=ARM-LE // RUN: %clang_cc1 -std=c11 -triple=armebv7a-none-eabi -emit-llvm -o - %s | FileCheck %s --check-prefix=ARM-BE -// RUN: %clang_cc1 -std=c11 -triple=aarch64-none-eabi -emit-llvm -o - %s | FileCheck %s --check-prefix=ARM-LE -// RUN: %clang_cc1 -std=c11 -triple=aarch64_be-none-eabi -emit-llvm -o - %s | FileCheck %s --check-prefix=ARM-BE +// RUN: %clang_cc1 -std=c11 -triple=aarch64-none-eabi -emit-llvm -o - %s | FileCheck %s --check-prefix=AARCH64-LE +// RUN: %clang_cc1 -std=c11 -triple=aarch64_be-none-eabi -emit-llvm -o - %s | FileCheck %s --check-prefix=AARCH64-BE struct Empty {}; @@ -31,6 +31,38 @@ struct Empty {}; // WINDOWS-NEXT: store i8 0, ptr %4, align 1 // WINDOWS-NEXT: ret void // +// ARM-LE-LABEL: define dso_local void @testEmpty( +// ARM-LE-SAME: ptr noundef [[E:%.*]]) #[[ATTR0:[0-9]+]] { +// ARM-LE-NEXT: [[ENTRY:.*:]] +// ARM-LE-NEXT: [[E_ADDR:%.*]] = alloca ptr, align 4 +// ARM-LE-NEXT: store ptr [[E]], ptr [[E_ADDR]], align 4 +// ARM-LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[E_ADDR]], align 4 +// ARM-LE-NEXT: ret void +// +// ARM-BE-LABEL: define dso_local void @testEmpty( +// ARM-BE-SAME: ptr noundef [[E:%.*]]) #[[ATTR0:[0-9]+]] { +// ARM-BE-NEXT: [[ENTRY:.*:]] +// ARM-BE-NEXT: [[E_ADDR:%.*]] = alloca ptr, align 4 +// ARM-BE-NEXT: store ptr [[E]], ptr [[E_ADDR]], align 4 +// ARM-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[E_ADDR]], align 4 +// ARM-BE-NEXT: ret void +// +// AARCH64-LE-LABEL: define dso_local void @testEmpty( +// AARCH64-LE-SAME: ptr noundef [[E:%.*]]) #[[ATTR0:[0-9]+]] { +// AARCH64-LE-NEXT: [[ENTRY:.*:]] +// AARCH64-LE-NEXT: [[E_ADDR:%.*]] = alloca ptr, align 8 +// AARCH64-LE-NEXT: store ptr [[E]], ptr [[E_ADDR]], align 8 +// AARCH64-LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[E_ADDR]], align 8 +// AARCH64-LE-NEXT: ret void +// +// AARCH64-BE-LABEL: define dso_local void @testEmpty( +// AARCH64-BE-SAME: ptr noundef [[E:%.*]]) #[[ATTR0:[0-9]+]] { +// AARCH64-BE-NEXT: [[ENTRY:.*:]] +// AARCH64-BE-NEXT: [[E_ADDR:%.*]] = alloca ptr, align 8 +// AARCH64-BE-NEXT: store ptr [[E]], ptr [[E_ADDR]], align 8 +// AARCH64-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[E_ADDR]], align 8 +// AARCH64-BE-NEXT: ret void +// void testEmpty(struct Empty *e) { // Emtpy struct is empty in C in Itanium ABI, no padding // Emtpy struct has 4 bytes in C in clang's MSVC ABI @@ -53,6 +85,38 @@ void testEmpty(struct Empty *e) { // WINDOWS-NEXT: %0 = load ptr, ptr %i.addr, align 8 // WINDOWS-NEXT: ret void // +// ARM-LE-LABEL: define dso_local void @testPrimitiveNoPadding( +// ARM-LE-SAME: ptr noundef [[I:%.*]]) #[[ATTR0]] { +// ARM-LE-NEXT: [[ENTRY:.*:]] +// ARM-LE-NEXT: [[I_ADDR:%.*]] = alloca ptr, align 4 +// ARM-LE-NEXT: store ptr [[I]], ptr [[I_ADDR]], align 4 +// ARM-LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[I_ADDR]], align 4 +// ARM-LE-NEXT: ret void +// +// ARM-BE-LABEL: define dso_local void @testPrimitiveNoPadding( +// ARM-BE-SAME: ptr noundef [[I:%.*]]) #[[ATTR0]] { +// ARM-BE-NEXT: [[ENTRY:.*:]] +// ARM-BE-NEXT: [[I_ADDR:%.*]] = alloca ptr, align 4 +// ARM-BE-NEXT: store ptr [[I]], ptr [[I_ADDR]], align 4 +// ARM-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[I_ADDR]], align 4 +// ARM-BE-NEXT: ret void +// +// AARCH64-LE-LABEL: define dso_local void @testPrimitiveNoPadding( +// AARCH64-LE-SAME: ptr noundef [[I:%.*]]) #[[ATTR0]] { +// AARCH64-LE-NEXT: [[ENTRY:.*:]] +// AARCH64-LE-NEXT: [[I_ADDR:%.*]] = alloca ptr, align 8 +// AARCH64-LE-NEXT: store ptr [[I]], ptr [[I_ADDR]], align 8 +// AARCH64-LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[I_ADDR]], align 8 +// AARCH64-LE-NEXT: ret void +// +// AARCH64-BE-LABEL: define dso_local void @testPrimitiveNoPadding( +// AARCH64-BE-SAME: ptr noundef [[I:%.*]]) #[[ATTR0]] { +// AARCH64-BE-NEXT: [[ENTRY:.*:]] +// AARCH64-BE-NEXT: [[I_ADDR:%.*]] = alloca ptr, align 8 +// AARCH64-BE-NEXT: store ptr [[I]], ptr [[I_ADDR]], align 8 +// AARCH64-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[I_ADDR]], align 8 +// AARCH64-BE-NEXT: ret void +// void testPrimitiveNoPadding(int *i) { // This should not clear any padding, since int has no padding. __builtin_clear_padding(i); @@ -86,6 +150,38 @@ void testPrimitiveNoPadding(int *i) { // WINDOWS-NEXT: %0 = load ptr, ptr %ld.addr, align 8 // WINDOWS-NEXT: ret void // +// ARM-LE-LABEL: define dso_local void @testPrimitiveLongDouble( +// ARM-LE-SAME: ptr noundef [[LD:%.*]]) #[[ATTR0]] { +// ARM-LE-NEXT: [[ENTRY:.*:]] +// ARM-LE-NEXT: [[LD_ADDR:%.*]] = alloca ptr, align 4 +// ARM-LE-NEXT: store ptr [[LD]], ptr [[LD_ADDR]], align 4 +// ARM-LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[LD_ADDR]], align 4 +// ARM-LE-NEXT: ret void +// +// ARM-BE-LABEL: define dso_local void @testPrimitiveLongDouble( +// ARM-BE-SAME: ptr noundef [[LD:%.*]]) #[[ATTR0]] { +// ARM-BE-NEXT: [[ENTRY:.*:]] +// ARM-BE-NEXT: [[LD_ADDR:%.*]] = alloca ptr, align 4 +// ARM-BE-NEXT: store ptr [[LD]], ptr [[LD_ADDR]], align 4 +// ARM-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[LD_ADDR]], align 4 +// ARM-BE-NEXT: ret void +// +// AARCH64-LE-LABEL: define dso_local void @testPrimitiveLongDouble( +// AARCH64-LE-SAME: ptr noundef [[LD:%.*]]) #[[ATTR0]] { +// AARCH64-LE-NEXT: [[ENTRY:.*:]] +// AARCH64-LE-NEXT: [[LD_ADDR:%.*]] = alloca ptr, align 8 +// AARCH64-LE-NEXT: store ptr [[LD]], ptr [[LD_ADDR]], align 8 +// AARCH64-LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[LD_ADDR]], align 8 +// AARCH64-LE-NEXT: ret void +// +// AARCH64-BE-LABEL: define dso_local void @testPrimitiveLongDouble( +// AARCH64-BE-SAME: ptr noundef [[LD:%.*]]) #[[ATTR0]] { +// AARCH64-BE-NEXT: [[ENTRY:.*:]] +// AARCH64-BE-NEXT: [[LD_ADDR:%.*]] = alloca ptr, align 8 +// AARCH64-BE-NEXT: store ptr [[LD]], ptr [[LD_ADDR]], align 8 +// AARCH64-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[LD_ADDR]], align 8 +// AARCH64-BE-NEXT: ret void +// void testPrimitiveLongDouble(long double *ld) { // padding [10, 15] on x86 __builtin_clear_padding(ld); @@ -127,82 +223,254 @@ void testPrimitiveLongDouble(long double *ld) { // WINDOWS-NEXT: ret void // // ARM-LE-LABEL: define dso_local void @testBitInt( -// ARM-LE: [[OBJ:%.*]] = load ptr, ptr {{.*}}, align {{[0-9]+}} -// ARM-LE-NEXT: [[BYTE12:%.*]] = getelementptr i8, ptr [[OBJ]], i32 12 -// ARM-LE-NEXT: [[VALUE:%.*]] = load i8, ptr [[BYTE12]], align 4 -// ARM-LE-NEXT: [[MASKED:%.*]] = and i8 [[VALUE]], 1 -// ARM-LE-NEXT: store i8 [[MASKED]], ptr [[BYTE12]], align 4 -// ARM-LE-NEXT: [[BYTE13:%.*]] = getelementptr i8, ptr [[OBJ]], i32 13 -// ARM-LE-NEXT: store i8 0, ptr [[BYTE13]], align 1 -// ARM-LE-NEXT: [[BYTE14:%.*]] = getelementptr i8, ptr [[OBJ]], i32 14 -// ARM-LE-NEXT: store i8 0, ptr [[BYTE14]], align 2 -// ARM-LE-NEXT: [[BYTE15:%.*]] = getelementptr i8, ptr [[OBJ]], i32 15 -// ARM-LE-NEXT: store i8 0, ptr [[BYTE15]], align 1 -// ARM-LE-NEXT: ret void +// ARM-LE-SAME: ptr noundef [[BI:%.*]]) #[[ATTR0]] { +// ARM-LE-NEXT: [[ENTRY:.*:]] +// ARM-LE-NEXT: [[BI_ADDR:%.*]] = alloca ptr, align 4 +// ARM-LE-NEXT: store ptr [[BI]], ptr [[BI_ADDR]], align 4 +// ARM-LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BI_ADDR]], align 4 +// ARM-LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12 +// ARM-LE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 4 +// ARM-LE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 1 +// ARM-LE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 4 +// ARM-LE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13 +// ARM-LE-NEXT: store i8 0, ptr [[TMP4]], align 1 +// ARM-LE-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14 +// ARM-LE-NEXT: store i8 0, ptr [[TMP5]], align 2 +// ARM-LE-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15 +// ARM-LE-NEXT: store i8 0, ptr [[TMP6]], align 1 +// ARM-LE-NEXT: ret void // // ARM-BE-LABEL: define dso_local void @testBitInt( -// ARM-BE: [[OBJ:%.*]] = load ptr, ptr {{.*}}, align {{[0-9]+}} -// ARM-BE-NEXT: [[BYTE0:%.*]] = getelementptr i8, ptr [[OBJ]], i32 0 -// ARM-BE-NEXT: store i8 0, ptr [[BYTE0]], align {{[0-9]+}} -// ARM-BE-NEXT: [[BYTE1:%.*]] = getelementptr i8, ptr [[OBJ]], i32 1 -// ARM-BE-NEXT: store i8 0, ptr [[BYTE1]], align 1 -// ARM-BE-NEXT: [[BYTE2:%.*]] = getelementptr i8, ptr [[OBJ]], i32 2 -// ARM-BE-NEXT: store i8 0, ptr [[BYTE2]], align 2 -// ARM-BE-NEXT: [[BYTE3:%.*]] = getelementptr i8, ptr [[OBJ]], i32 3 -// ARM-BE-NEXT: [[VALUE:%.*]] = load i8, ptr [[BYTE3]], align 1 -// ARM-BE-NEXT: [[MASKED:%.*]] = and i8 [[VALUE]], 1 -// ARM-BE-NEXT: store i8 [[MASKED]], ptr [[BYTE3]], align 1 -// ARM-BE-NEXT: ret void +// ARM-BE-SAME: ptr noundef [[BI:%.*]]) #[[ATTR0]] { +// ARM-BE-NEXT: [[ENTRY:.*:]] +// ARM-BE-NEXT: [[BI_ADDR:%.*]] = alloca ptr, align 4 +// ARM-BE-NEXT: store ptr [[BI]], ptr [[BI_ADDR]], align 4 +// ARM-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BI_ADDR]], align 4 +// ARM-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0 +// ARM-BE-NEXT: store i8 0, ptr [[TMP1]], align 8 +// ARM-BE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1 +// ARM-BE-NEXT: store i8 0, ptr [[TMP2]], align 1 +// ARM-BE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2 +// ARM-BE-NEXT: store i8 0, ptr [[TMP3]], align 2 +// ARM-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3 +// ARM-BE-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1 +// ARM-BE-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], 1 +// ARM-BE-NEXT: store i8 [[TMP6]], ptr [[TMP4]], align 1 +// ARM-BE-NEXT: ret void +// +// AARCH64-LE-LABEL: define dso_local void @testBitInt( +// AARCH64-LE-SAME: ptr noundef [[BI:%.*]]) #[[ATTR0]] { +// AARCH64-LE-NEXT: [[ENTRY:.*:]] +// AARCH64-LE-NEXT: [[BI_ADDR:%.*]] = alloca ptr, align 8 +// AARCH64-LE-NEXT: store ptr [[BI]], ptr [[BI_ADDR]], align 8 +// AARCH64-LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BI_ADDR]], align 8 +// AARCH64-LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 12 +// AARCH64-LE-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 4 +// AARCH64-LE-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 1 +// AARCH64-LE-NEXT: store i8 [[TMP3]], ptr [[TMP1]], align 4 +// AARCH64-LE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 13 +// AARCH64-LE-NEXT: store i8 0, ptr [[TMP4]], align 1 +// AARCH64-LE-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP0]], i32 14 +// AARCH64-LE-NEXT: store i8 0, ptr [[TMP5]], align 2 +// AARCH64-LE-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i32 15 +// AARCH64-LE-NEXT: store i8 0, ptr [[TMP6]], align 1 +// AARCH64-LE-NEXT: ret void +// +// AARCH64-BE-LABEL: define dso_local void @testBitInt( +// AARCH64-BE-SAME: ptr noundef [[BI:%.*]]) #[[ATTR0]] { +// AARCH64-BE-NEXT: [[ENTRY:.*:]] +// AARCH64-BE-NEXT: [[BI_ADDR:%.*]] = alloca ptr, align 8 +// AARCH64-BE-NEXT: store ptr [[BI]], ptr [[BI_ADDR]], align 8 +// AARCH64-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BI_ADDR]], align 8 +// AARCH64-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0 +// AARCH64-BE-NEXT: store i8 0, ptr [[TMP1]], align 16 +// AARCH64-BE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP0]], i32 1 +// AARCH64-BE-NEXT: store i8 0, ptr [[TMP2]], align 1 +// AARCH64-BE-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP0]], i32 2 +// AARCH64-BE-NEXT: store i8 0, ptr [[TMP3]], align 2 +// AARCH64-BE-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3 +// AARCH64-BE-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1 +// AARCH64-BE-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], 1 +// AARCH64-BE-NEXT: store i8 [[TMP6]], ptr [[TMP4]], align 1 +// AARCH64-BE-NEXT: ret void // void testBitInt(_BitInt(97) *bi) { // Storage is widened to 128 bits; clear bits [97, 128). __builtin_clear_padding(bi); } +// LINUX-LABEL: define dso_local void @testBitIntByteAligned( +// LINUX-SAME: ptr noundef [[BI:%.*]]) #[[ATTR0]] { +// LINUX-NEXT: [[ENTRY:.*:]] +// LINUX-NEXT: [[BI_ADDR:%.*]] = alloca ptr, align 8 +// LINUX-NEXT: store ptr [[BI]], ptr [[BI_ADDR]], align 8 +// LINUX-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BI_ADDR]], align 8 +// LINUX-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3 +// LINUX-NEXT: store i8 0, ptr [[TMP1]], align 1 +// LINUX-NEXT: ret void +// +// WINDOWS-LABEL: define dso_local void @testBitIntByteAligned( +// WINDOWS-SAME: ptr noundef [[BI:%.*]]) #[[ATTR0]] { +// WINDOWS-NEXT: [[ENTRY:.*:]] +// WINDOWS-NEXT: [[BI_ADDR:%.*]] = alloca ptr, align 8 +// WINDOWS-NEXT: store ptr [[BI]], ptr [[BI_ADDR]], align 8 +// WINDOWS-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BI_ADDR]], align 8 +// WINDOWS-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3 +// WINDOWS-NEXT: store i8 0, ptr [[TMP1]], align 1 +// WINDOWS-NEXT: ret void +// // ARM-LE-LABEL: define dso_local void @testBitIntByteAligned( -// ARM-LE: [[OBJ:%.*]] = load ptr, ptr {{.*}}, align {{[0-9]+}} -// ARM-LE-NEXT: [[BYTE3:%.*]] = getelementptr i8, ptr [[OBJ]], i32 3 -// ARM-LE-NEXT: store i8 0, ptr [[BYTE3]], align 1 -// ARM-LE-NEXT: ret void +// ARM-LE-SAME: ptr noundef [[BI:%.*]]) #[[ATTR0]] { +// ARM-LE-NEXT: [[ENTRY:.*:]] +// ARM-LE-NEXT: [[BI_ADDR:%.*]] = alloca ptr, align 4 +// ARM-LE-NEXT: store ptr [[BI]], ptr [[BI_ADDR]], align 4 +// ARM-LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BI_ADDR]], align 4 +// ARM-LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3 +// ARM-LE-NEXT: store i8 0, ptr [[TMP1]], align 1 +// ARM-LE-NEXT: ret void // // ARM-BE-LABEL: define dso_local void @testBitIntByteAligned( -// ARM-BE: [[OBJ:%.*]] = load ptr, ptr {{.*}}, align {{[0-9]+}} -// ARM-BE-NEXT: [[BYTE0:%.*]] = getelementptr i8, ptr [[OBJ]], i32 0 -// ARM-BE-NEXT: store i8 0, ptr [[BYTE0]], align 4 -// ARM-BE-NEXT: ret void +// ARM-BE-SAME: ptr noundef [[BI:%.*]]) #[[ATTR0]] { +// ARM-BE-NEXT: [[ENTRY:.*:]] +// ARM-BE-NEXT: [[BI_ADDR:%.*]] = alloca ptr, align 4 +// ARM-BE-NEXT: store ptr [[BI]], ptr [[BI_ADDR]], align 4 +// ARM-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BI_ADDR]], align 4 +// ARM-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0 +// ARM-BE-NEXT: store i8 0, ptr [[TMP1]], align 4 +// ARM-BE-NEXT: ret void +// +// AARCH64-LE-LABEL: define dso_local void @testBitIntByteAligned( +// AARCH64-LE-SAME: ptr noundef [[BI:%.*]]) #[[ATTR0]] { +// AARCH64-LE-NEXT: [[ENTRY:.*:]] +// AARCH64-LE-NEXT: [[BI_ADDR:%.*]] = alloca ptr, align 8 +// AARCH64-LE-NEXT: store ptr [[BI]], ptr [[BI_ADDR]], align 8 +// AARCH64-LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BI_ADDR]], align 8 +// AARCH64-LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 3 +// AARCH64-LE-NEXT: store i8 0, ptr [[TMP1]], align 1 +// AARCH64-LE-NEXT: ret void +// +// AARCH64-BE-LABEL: define dso_local void @testBitIntByteAligned( +// AARCH64-BE-SAME: ptr noundef [[BI:%.*]]) #[[ATTR0]] { +// AARCH64-BE-NEXT: [[ENTRY:.*:]] +// AARCH64-BE-NEXT: [[BI_ADDR:%.*]] = alloca ptr, align 8 +// AARCH64-BE-NEXT: store ptr [[BI]], ptr [[BI_ADDR]], align 8 +// AARCH64-BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BI_ADDR]], align 8 +// AARCH64-BE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 0 +// AARCH64-BE-NEXT: store i8 0, ptr [[TMP1]], align 4 +// AARCH64-BE-NEXT: ret void // void testBitIntByteAligned(_BitInt(24) *bi) { // Storage is widened to 32 bits; clear the leading or trailing byte. __builtin_clear_padding(bi); } +// LINUX-LABEL: define dso_local void @testVolatileBitInt( +// LINUX-SAME: ptr noundef [[BI:%.*]]) #[[ATTR0]] { +// LINUX-NEXT: [[ENTRY:.*:]] +// LINUX-NEXT: [[BI_ADDR:%.*]] = alloca ptr, align 8 +// LI... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/216063 _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
