Skip to content

Commit

Permalink
[clang] Better SysV bitfield access units (#65742)
Browse files Browse the repository at this point in the history
Reimplement bitfield access unit computation for SysV ABIs. Considers
expense of unaligned and non-power-of-2 accesses.
  • Loading branch information
urnathan committed Mar 29, 2024
1 parent 7df79ab commit 49839f9
Show file tree
Hide file tree
Showing 20 changed files with 1,141 additions and 1,681 deletions.
351 changes: 261 additions & 90 deletions clang/lib/CodeGen/CGRecordLayoutBuilder.cpp

Large diffs are not rendered by default.

38 changes: 19 additions & 19 deletions clang/test/CodeGen/aapcs-bitfield-access-unit.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ struct st2 {
short c : 7;
} st2;
// LAYOUT-LABEL: LLVMType:%struct.st2 =
// LAYOUT-SAME: type { i16, i8 }
// LAYOUT-SAME: type { i32 }
// LAYOUT: BitFields:[
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:10 IsSigned:1 StorageSize:16 StorageOffset:0
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:8 StorageOffset:2
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:10 IsSigned:1 StorageSize:32 StorageOffset:0
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:32 StorageOffset:0
// LAYOUT-NEXT: ]>

struct st3 {
Expand Down Expand Up @@ -60,10 +60,10 @@ struct st5 {
volatile char c : 5;
} st5;
// LAYOUT-LABEL: LLVMType:%struct.st5 =
// LAYOUT-SAME: type { i16, i8 }
// LAYOUT-SAME: type { i32 }
// LAYOUT: BitFields:[
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:12 IsSigned:1 StorageSize:16 StorageOffset:0
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:5 IsSigned:1 StorageSize:8 StorageOffset:2
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:12 IsSigned:1 StorageSize:32 StorageOffset:0
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:5 IsSigned:1 StorageSize:32 StorageOffset:0
// LAYOUT-NEXT: ]>

struct st6 {
Expand Down Expand Up @@ -141,7 +141,7 @@ struct st12{
int f : 16;
} st12;
// LAYOUT-LABEL: LLVMType:%struct.st12 =
// LAYOUT-SAME: type { i24 }
// LAYOUT-SAME: type { i32 }
// LAYOUT: BitFields:[
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:32 StorageOffset:0
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:32 StorageOffset:0
Expand All @@ -152,10 +152,10 @@ struct st13 {
int b : 32;
} __attribute__((packed)) st13;
// LAYOUT-LABEL: LLVMType:%struct.st13 =
// LAYOUT-SAME: type { [5 x i8] }
// LAYOUT-SAME: type <{ i8, i32 }>
// LAYOUT: BitFields:[
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:40 StorageOffset:0
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:32 IsSigned:1 StorageSize:40 StorageOffset:0
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:8 StorageOffset:0
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:32 IsSigned:1 StorageSize:32 StorageOffset:1
// LAYOUT-NEXT: ]>

struct st14 {
Expand Down Expand Up @@ -183,23 +183,23 @@ struct st16 {
int d : 16;
} st16;
// LAYOUT-LABEL: LLVMType:%struct.st16 =
// LAYOUT-SAME: type { i48, i48 }
// LAYOUT-SAME: type { i32, i16, i32, i16 }
// LAYOUT: BitFields:[
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:32 IsSigned:1 StorageSize:64 StorageOffset:0
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:64 StorageOffset:0
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:32 IsSigned:1 StorageSize:64 StorageOffset:8
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:64 StorageOffset:8
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:32 IsSigned:1 StorageSize:32 StorageOffset:0
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:16 StorageOffset:4
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:32 IsSigned:1 StorageSize:32 StorageOffset:8
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:16 StorageOffset:12
// LAYOUT-NEXT: ]>

struct st17 {
int b : 32;
char c : 8;
} __attribute__((packed)) st17;
// LAYOUT-LABEL: LLVMType:%struct.st17 =
// LAYOUT-SAME: type { [5 x i8] }
// LAYOUT-SAME: type <{ i32, i8 }>
// LAYOUT: BitFields:[
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:32 IsSigned:1 StorageSize:40 StorageOffset:0
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:40 StorageOffset:0
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:32 IsSigned:1 StorageSize:32 StorageOffset:0
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:8 StorageOffset:4
// LAYOUT-NEXT: ]>

struct zero_bitfield {
Expand All @@ -221,7 +221,7 @@ struct zero_bitfield_ok {
int b : 24;
} st19;
// LAYOUT-LABEL: LLVMType:%struct.zero_bitfield_ok =
// LAYOUT-SAME: type { i16, i24 }
// LAYOUT-SAME: type { i16, i32 }
// LAYOUT: BitFields:[
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:16 StorageOffset:0
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:16 StorageOffset:0
Expand Down
1,920 changes: 624 additions & 1,296 deletions clang/test/CodeGen/aapcs-bitfield.c

Large diffs are not rendered by default.

23 changes: 14 additions & 9 deletions clang/test/CodeGen/arm-bitfield-alignment.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -triple arm-none-eabi -fdump-record-layouts-simple -ffreestanding -emit-llvm -o %t %s | FileCheck %s -check-prefix=LAYOUT
// RUN: FileCheck %s -check-prefix=IR <%t
// RUN: %clang_cc1 -triple aarch64 -fdump-record-layouts-simple -ffreestanding -emit-llvm -o %t %s | FileCheck %s -check-prefix=LAYOUT
// RUN: FileCheck %s -check-prefix=IR <%t
// RUN: %clang_cc1 -triple arm-none-eabi -fdump-record-layouts-simple -ffreestanding -emit-llvm -o %t %s | FileCheck %s -check-prefixes=LAYOUT,LAYOUT-32
// RUN: FileCheck %s -check-prefixes=IR,IR-32 <%t
// RUN: %clang_cc1 -triple aarch64 -fdump-record-layouts-simple -ffreestanding -emit-llvm -o %t %s | FileCheck %s -check-prefixes=LAYOUT,LAYOUT-64
// RUN: FileCheck %s -check-prefixes=IR,IR-64 <%t

extern struct T {
int b0 : 8;
Expand All @@ -14,12 +14,17 @@ int func(void) {
}

// IR: @g = external global %struct.T, align 4
// IR: %{{.*}} = load i64, ptr @g, align 4
// IR-32: %{{.*}} = load i32, ptr @g, align 4
// IR-64: %{{.*}} = load i64, ptr @g, align 4

// LAYOUT-LABEL: LLVMType:%struct.T =
// LAYOUT-SAME: type { i40 }
// LAYOUT-32-SAME: type { i32, i8 }
// LAYOUT-64-SAME: type { i64 }
// LAYOUT: BitFields:[
// LAYOUT-NEXT: <CGBitFieldInfo Offset:0 Size:8 IsSigned:1 StorageSize:64 StorageOffset:0
// LAYOUT-NEXT: <CGBitFieldInfo Offset:8 Size:24 IsSigned:1 StorageSize:64 StorageOffset:0
// LAYOUT-NEXT: <CGBitFieldInfo Offset:32 Size:1 IsSigned:1 StorageSize:64 StorageOffset:0
// LAYOUT-32-NEXT: <CGBitFieldInfo Offset:0 Size:8 IsSigned:1 StorageSize:32 StorageOffset:0
// LAYOUT-32-NEXT: <CGBitFieldInfo Offset:8 Size:24 IsSigned:1 StorageSize:32 StorageOffset:0
// LAYOUT-32-NEXT: <CGBitFieldInfo Offset:0 Size:1 IsSigned:1 StorageSize:8 StorageOffset:4
// LAYOUT-64-NEXT: <CGBitFieldInfo Offset:0 Size:8 IsSigned:1 StorageSize:64 StorageOffset:0
// LAYOUT-64-NEXT: <CGBitFieldInfo Offset:8 Size:24 IsSigned:1 StorageSize:64 StorageOffset:0
// LAYOUT-64-NEXT: <CGBitFieldInfo Offset:32 Size:1 IsSigned:1 StorageSize:64 StorageOffset:0
// LAYOUT-NEXT: ]>
8 changes: 5 additions & 3 deletions clang/test/CodeGen/arm64-be-bitfield.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,18 @@ struct bt3 { signed b2:10; signed b3:10; } b16;
signed callee_b0f(struct bt3 bp11) {
// IR: callee_b0f(i64 [[ARG:%.*]])
// IR: [[BP11:%.*]] = alloca %struct.bt3, align 4
// IR: store i64 [[ARG]], ptr [[PTR:%.*]], align 8
// IR: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[BP11]], ptr align 8 [[PTR]], i64 4
// IR: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.bt3, ptr [[BP11]], i32 0, i32 0
// IR: [[COERCE_HIGHBITS:%.*]] = lshr i64 [[ARG]], 32
// IR: [[COERCE_VAL_II:%.*]] = trunc i64 [[COERCE_HIGHBITS]] to i32
// IR: store i32 [[COERCE_VAL_II]], ptr [[COERCE_DIVE]], align 4
// IR: [[BF_LOAD:%.*]] = load i32, ptr [[BP11]], align 4
// IR: [[BF_ASHR:%.*]] = ashr i32 [[BF_LOAD]], 22
// IR: ret i32 [[BF_ASHR]]
return bp11.b2;
}

// LAYOUT-LABEL: LLVMType:%struct.bt3 =
// LAYOUT-SAME: type { i24 }
// LAYOUT-SAME: type { i32 }
// LAYOUT: BitFields:[
// LAYOUT-NEXT: <CGBitFieldInfo Offset:22 Size:10 IsSigned:1 StorageSize:32 StorageOffset:0
// LAYOUT-NEXT: <CGBitFieldInfo Offset:12 Size:10 IsSigned:1 StorageSize:32 StorageOffset:0
Expand Down
6 changes: 3 additions & 3 deletions clang/test/CodeGen/bitfield-2.c
Original file line number Diff line number Diff line change
Expand Up @@ -271,11 +271,11 @@ _Bool test_6(void) {
// CHECK-RECORD: *** Dumping IRgen Record Layout
// CHECK-RECORD: Record: RecordDecl{{.*}}s7
// CHECK-RECORD: Layout: <CGRecordLayout
// CHECK-RECORD: LLVMType:%struct.s7 = type { i32, i32, i32, i8, i32, [12 x i8] }
// CHECK-RECORD: LLVMType:%struct.s7 = type <{ i32, i32, i32, i64, [12 x i8] }>
// CHECK-RECORD: IsZeroInitializable:1
// CHECK-RECORD: BitFields:[
// CHECK-RECORD: <CGBitFieldInfo Offset:0 Size:5 IsSigned:1 StorageSize:8 StorageOffset:12
// CHECK-RECORD: <CGBitFieldInfo Offset:0 Size:29 IsSigned:1 StorageSize:32 StorageOffset:16
// CHECK-RECORD: <CGBitFieldInfo Offset:0 Size:5 IsSigned:1 StorageSize:64 StorageOffset:12
// CHECK-RECORD: <CGBitFieldInfo Offset:32 Size:29 IsSigned:1 StorageSize:64 StorageOffset:12

struct __attribute__((aligned(16))) s7 {
int a, b, c;
Expand Down

0 comments on commit 49839f9

Please sign in to comment.