351 changes: 261 additions & 90 deletions clang/lib/CodeGen/CGRecordLayoutBuilder.cpp

Large diffs are not rendered by default.

231 changes: 231 additions & 0 deletions clang/test/CodeGen/aapcs-bitfield-access-unit.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
// RUN: %clang_cc1 -triple armv8-none-linux-eabi -fno-aapcs-bitfield-width -fdump-record-layouts-simple -emit-llvm -o /dev/null %s | FileCheck %s -check-prefixes=LAYOUT
// RUN: %clang_cc1 -triple armebv8-none-linux-eabi -fno-aapcs-bitfield-width -fdump-record-layouts-simple -emit-llvm -o /dev/null %s | FileCheck %s -check-prefixes=LAYOUT

// RUN: %clang_cc1 -triple armv8-none-linux-eabi -faapcs-bitfield-width -fdump-record-layouts-simple -emit-llvm -o /dev/null %s | FileCheck %s -check-prefixes=LAYOUT
// RUN: %clang_cc1 -triple armebv8-none-linux-eabi -faapcs-bitfield-width -fdump-record-layouts-simple -emit-llvm -o /dev/null %s | FileCheck %s -check-prefixes=LAYOUT

struct st0 {
short c : 7;
} st0;
// LAYOUT-LABEL: LLVMType:%struct.st0 =
// LAYOUT-SAME: type { i8, i8 }
// LAYOUT: BitFields:[
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:8 StorageOffset:0
// LAYOUT-NEXT: ]>

struct st1 {
int a : 10;
short c : 6;
} st1;
// LAYOUT-LABEL: LLVMType:%struct.st1 =
// LAYOUT-SAME: type { i16, [2 x i8] }
// LAYOUT: BitFields:[
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:10 IsSigned:1 StorageSize:16 StorageOffset:0
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:6 IsSigned:1 StorageSize:16 StorageOffset:0
// LAYOUT-NEXT: ]>

struct st2 {
int a : 10;
short c : 7;
} st2;
// LAYOUT-LABEL: LLVMType:%struct.st2 =
// LAYOUT-SAME: type { i32 }
// LAYOUT: BitFields:[
// 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 {
volatile short c : 7;
} st3;
// LAYOUT-LABEL: LLVMType:%struct.st3 =
// LAYOUT-SAME: type { i8, i8 }
// LAYOUT: BitFields:[
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:8 StorageOffset:0
// LAYOUT-NEXT: ]>

struct st4 {
int b : 9;
volatile char c : 5;
} st4;
// LAYOUT-LABEL: LLVMType:%struct.st4 =
// LAYOUT-SAME: type { i16, [2 x i8] }
// LAYOUT: BitFields:[
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:9 IsSigned:1 StorageSize:16 StorageOffset:0
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:5 IsSigned:1 StorageSize:16 StorageOffset:0
// LAYOUT-NEXT: ]>

struct st5 {
int a : 12;
volatile char c : 5;
} st5;
// LAYOUT-LABEL: LLVMType:%struct.st5 =
// LAYOUT-SAME: type { i32 }
// LAYOUT: BitFields:[
// 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 {
int a : 12;
char b;
int c : 5;
} st6;
// LAYOUT-LABEL: LLVMType:%struct.st6 =
// LAYOUT-SAME: type { i16, i8, i8 }
// 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:3
// LAYOUT-NEXT: ]>

struct st7a {
char a;
int b : 5;
} st7a;
// LAYOUT-LABEL: LLVMType:%struct.st7a =
// LAYOUT-SAME: type { i8, i8, [2 x i8] }
// LAYOUT: BitFields:[
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:5 IsSigned:1 StorageSize:8 StorageOffset:1
// LAYOUT-NEXT: ]>

struct st7b {
char x;
volatile struct st7a y;
} st7b;
// LAYOUT-LABEL: LLVMType:%struct.st7b =
// LAYOUT-SAME: type { i8, [3 x i8], %struct.st7a }
// LAYOUT: BitFields:[
// LAYOUT-NEXT: ]>

struct st8 {
unsigned f : 16;
} st8;
// LAYOUT-LABEL: LLVMType:%struct.st8 =
// LAYOUT-SAME: type { i16, [2 x i8] }
// LAYOUT: BitFields:[
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:0 StorageSize:16 StorageOffset:0
// LAYOUT-NEXT: ]>

struct st9{
int f : 8;
} st9;
// LAYOUT-LABEL: LLVMType:%struct.st9 =
// LAYOUT-SAME: type { i8, [3 x i8] }
// LAYOUT: BitFields:[
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:8 StorageOffset:0
// LAYOUT-NEXT: ]>

struct st10{
int e : 1;
int f : 8;
} st10;
// LAYOUT-LABEL: LLVMType:%struct.st10 =
// LAYOUT-SAME: type { i16, [2 x i8] }
// LAYOUT: BitFields:[
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:1 IsSigned:1 StorageSize:16 StorageOffset:0
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:16 StorageOffset:0
// LAYOUT-NEXT: ]>

struct st11{
char e;
int f : 16;
} st11;
// LAYOUT-LABEL: LLVMType:%struct.st11 =
// LAYOUT-SAME: type <{ i8, i16, i8 }>
// LAYOUT: BitFields:[
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:16 StorageOffset:1
// LAYOUT-NEXT: ]>

struct st12{
int e : 8;
int f : 16;
} st12;
// LAYOUT-LABEL: LLVMType:%struct.st12 =
// 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
// LAYOUT-NEXT: ]>

struct st13 {
char a : 8;
int b : 32;
} __attribute__((packed)) st13;
// LAYOUT-LABEL: LLVMType:%struct.st13 =
// LAYOUT-SAME: type <{ i8, i32 }>
// LAYOUT: BitFields:[
// 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 {
char a : 8;
} __attribute__((packed)) st14;
// LAYOUT-LABEL: LLVMType:%struct.st14 =
// LAYOUT-SAME: type { i8 }
// LAYOUT: BitFields:[
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:8 StorageOffset:0
// LAYOUT-NEXT: ]>

struct st15 {
short a : 8;
} __attribute__((packed)) st15;
// LAYOUT-LABEL: LLVMType:%struct.st15 =
// LAYOUT-SAME: type { i8 }
// LAYOUT: BitFields:[
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:8 StorageOffset:0
// LAYOUT-NEXT: ]>

struct st16 {
int a : 32;
int b : 16;
int c : 32;
int d : 16;
} st16;
// LAYOUT-LABEL: LLVMType:%struct.st16 =
// LAYOUT-SAME: type { i32, i16, i32, i16 }
// LAYOUT: BitFields:[
// 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 <{ i32, i8 }>
// LAYOUT: BitFields:[
// 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 {
int a : 8;
char : 0;
int b : 8;
} st18;
// LAYOUT-LABEL: LLVMType:%struct.zero_bitfield =
// LAYOUT-SAME: type { i8, i8, [2 x i8] }
// LAYOUT: BitFields:[
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:8 StorageOffset:0
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:8 StorageOffset:1
// LAYOUT-NEXT: ]>

struct zero_bitfield_ok {
short a : 8;
char a1 : 8;
long : 0;
int b : 24;
} st19;
// LAYOUT-LABEL: LLVMType:%struct.zero_bitfield_ok =
// 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
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:24 IsSigned:1 StorageSize:32 StorageOffset:4
// LAYOUT-NEXT: ]>


1,920 changes: 624 additions & 1,296 deletions clang/test/CodeGen/aapcs-bitfield.c

Large diffs are not rendered by default.

23 changes: 19 additions & 4 deletions clang/test/CodeGen/arm-bitfield-alignment.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -triple arm-none-eabi -ffreestanding -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -triple aarch64 -ffreestanding -emit-llvm -o - %s | FileCheck %s
// 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 @@ -11,5 +13,18 @@ int func(void) {
return g.b1;
}

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

// LAYOUT-LABEL: LLVMType:%struct.T =
// LAYOUT-32-SAME: type { i32, i8 }
// LAYOUT-64-SAME: type { i64 }
// LAYOUT: BitFields:[
// 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: ]>
20 changes: 17 additions & 3 deletions clang/test/CodeGen/arm64-be-bitfield.c
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
// RUN: %clang_cc1 -triple aarch64_be-linux-gnu -ffreestanding -emit-llvm -O0 -o - %s | FileCheck --check-prefix IR %s
// RUN: %clang_cc1 -triple aarch64_be-linux-gnu -ffreestanding -emit-llvm -O0 -o %t -fdump-record-layouts-simple %s | FileCheck %s --check-prefix=LAYOUT
// RUN: FileCheck %s --check-prefix=IR <%t

struct bt3 { signed b2:10; signed b3:10; } b16;

// Get the high 32-bits and then shift appropriately for big-endian.
signed callee_b0f(struct bt3 bp11) {
// IR: callee_b0f(i64 [[ARG:%.*]])
// IR: store i64 [[ARG]], ptr [[PTR:%.*]], align 8
// IR: call void @llvm.memcpy.p0.p0.i64(ptr {{.*}}, ptr align 8 [[PTR]], i64 4
// IR: [[BP11:%.*]] = alloca %struct.bt3, align 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 { 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
// LAYOUT-NEXT: ]>
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
396 changes: 396 additions & 0 deletions clang/test/CodeGen/bitfield-access-pad.c

Large diffs are not rendered by default.

302 changes: 302 additions & 0 deletions clang/test/CodeGen/bitfield-access-unit.c

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions clang/test/CodeGen/debug-info-bitfield-0-struct.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,10 @@ struct None_B {
int y : 4;
};

struct None_C {
// BOTH-DAG: ![[NONE_C:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "None_C", file: !{{[0-9]+}}, line: {{[0-9]+}}, size: 32, elements: ![[NONE_C_ELEMENTS:[0-9]+]])
// AMDGCN does not do unaligned access cheaply, so the bitfield access units
// would remain single bytes, without the aligned attribure
struct __attribute__((aligned(4))) None_C {
// BOTH-DAG: ![[NONE_C:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "None_C", file: !{{[0-9]+}}, line: {{[0-9]+}}, size: 32, align: 32, elements: ![[NONE_C_ELEMENTS:[0-9]+]])
// BOTH-DAG: ![[NONE_C_ELEMENTS]] = !{![[NONE_C_X:[0-9]+]], ![[NONE_C_Y:[0-9]+]], ![[NONE_C_A:[0-9]+]], ![[NONE_C_B:[0-9]+]]}
// BOTH-DAG: ![[NONE_C_X]] = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: ![[NONE_C]], file: !{{[0-9]+}}, line: {{[0-9]+}}, baseType: !{{[0-9]+}}, size: 8, flags: DIFlagBitField, extraData: i64 0)
// BOTH-DAG: ![[NONE_C_Y]] = !DIDerivedType(tag: DW_TAG_member, name: "y", scope: ![[NONE_C]], file: !{{[0-9]+}}, line: {{[0-9]+}}, baseType: !{{[0-9]+}}, size: 8, offset: 8, flags: DIFlagBitField, extraData: i64 0)
Expand Down
10 changes: 9 additions & 1 deletion clang/test/CodeGen/no-bitfield-type-align.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin -fno-bitfield-type-align -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -triple x86_64-apple-darwin -fno-bitfield-type-align -fdump-record-layouts-simple -emit-llvm -o %t %s | FileCheck %s -check-prefix=LAYOUT
// RUN: FileCheck %s <%t

struct S {
unsigned short: 0;
Expand All @@ -7,6 +8,13 @@ struct S {
unsigned short f2:15;
};

// LAYOUT-LABEL: LLVMType:%struct.S =
// LAYOUT-SAME: type { i32 }
// LAYOUT: BitFields:[
// LAYOUT-NEXT: <CGBitFieldInfo Offset:0 Size:15 IsSigned:0 StorageSize:32 StorageOffset:0
// LAYOUT-NEXT: <CGBitFieldInfo Offset:15 Size:15 IsSigned:0 StorageSize:32 StorageOffset:0
// LAYOUT-NEXT: ]>

// CHECK: define{{.*}} void @test_zero_width_bitfield(ptr noundef %[[A:.*]])
// CHECK: %[[BF_LOAD:.*]] = load i32, ptr %[[V1:.*]], align 1
// CHECK: %[[BF_CLEAR:.*]] = and i32 %[[BF_LOAD]], 32767
Expand Down
69 changes: 57 additions & 12 deletions clang/test/CodeGen/struct-x86-darwin.c
Original file line number Diff line number Diff line change
@@ -1,25 +1,70 @@
// RUN: %clang_cc1 %s -emit-llvm -triple=i686-apple-darwin9 -o - | FileCheck %s
// CHECK: STest1 = type { i32, [4 x i16], double }
// CHECK: STest2 = type { i16, i16, i32, i32 }
// CHECK: STest3 = type { i8, i16, i32 }
// CHECK: STestB1 = type { i8, i8 }
// CHECK: STestB2 = type { i8, i8, i8 }
// CHECK: STestB3 = type { i8, i8 }
// CHECK: STestB4 = type { i8, i8, i8, i8 }
// CHECK: STestB5 = type { i8, i16, i8 }
// CHECK: STestB6 = type { i8, i8, i16 }
// RUN: %clang_cc1 %s -emit-llvm -o /dev/null -triple=i686-apple-darwin9 -fdump-record-layouts-simple | FileCheck %s

// Test struct layout for x86-darwin target

struct STest1 {int x; short y[4]; double z; } st1;
struct STest2 {short a,b; int c,d; } st2;
struct STest3 {char a; short b; int c; } st3;

// Bitfields
// Bitfields
struct STestB1 {char a; char b:2; } stb1;
struct STestB2 {char a; char b:5; char c:4; } stb2;
struct STestB3 {char a; char b:2; } stb3;
struct STestB4 {char a; short b:2; char c; } stb4;
struct STestB5 {char a; short b:10; char c; } stb5;
struct STestB6 {int a:1; char b; int c:13 } stb6;
struct STestB6 {int a:1; char b; int c:13; } stb6;

// Packed struct STestP1 {char a; short b; int c; } __attribute__((__packed__)) stp1;

// CHECK-LABEL: LLVMType:%struct.STest1 =
// CHECK-SAME: type { i32, [4 x i16], double }
// CHECK: BitFields:[
// CHECK-NEXT: ]>

// CHECK-LABEL: LLVMType:%struct.STest2 =
// CHECK-SAME: type { i16, i16, i32, i32 }
// CHECK: BitFields:[
// CHECK-NEXT: ]>

// CHECK-LABEL: LLVMType:%struct.STest3 =
// CHECK-SAME: type { i8, i16, i32 }
// CHECK: BitFields:[
// CHECK-NEXT: ]>

// CHECK-LABEL: LLVMType:%struct.STestB1 =
// CHECK-SAME: type { i8, i8 }
// CHECK: BitFields:[
// CHECK-NEXT: <CGBitFieldInfo Offset:0 Size:2 IsSigned:1 StorageSize:8 StorageOffset:1
// CHECK-NEXT: ]>

// CHECK-LABEL: LLVMType:%struct.STestB2 =
// CHECK-SAME: type <{ i8, i16 }>
// CHECK: BitFields:[
// CHECK-NEXT: <CGBitFieldInfo Offset:0 Size:5 IsSigned:1 StorageSize:16 StorageOffset:1
// CHECK-NEXT: <CGBitFieldInfo Offset:8 Size:4 IsSigned:1 StorageSize:16 StorageOffset:1
// CHECK-NEXT: ]>

// CHECK-LABEL: LLVMType:%struct.STestB3 =
// CHECK-SAME: type { i8, i8 }
// CHECK: BitFields:[
// CHECK-NEXT: <CGBitFieldInfo Offset:0 Size:2 IsSigned:1 StorageSize:8 StorageOffset:1
// CHECK-NEXT: ]>

// CHECK-LABEL: LLVMType:%struct.STestB4 =
// CHECK-SAME: type { i8, i8, i8, i8 }
// CHECK: BitFields:[
// CHECK-NEXT: <CGBitFieldInfo Offset:0 Size:2 IsSigned:1 StorageSize:8 StorageOffset:1
// CHECK-NEXT: ]>

// CHECK-LABEL: LLVMType:%struct.STestB5 =
// CHECK-SAME: type { i8, i16, i8 }
// CHECK: BitFields:[
// CHECK-NEXT: <CGBitFieldInfo Offset:0 Size:10 IsSigned:1 StorageSize:16 StorageOffset:2
// CHECK-NEXT: ]>

// CHECK-LABEL: LLVMType:%struct.STestB6 =
// CHECK-SAME: type { i8, i8, i16 }
// CHECK: BitFields:[
// CHECK-NEXT: <CGBitFieldInfo Offset:0 Size:1 IsSigned:1 StorageSize:8 StorageOffset:0
// CHECK-NEXT: <CGBitFieldInfo Offset:0 Size:13 IsSigned:1 StorageSize:16 StorageOffset:2
// CHECK-NEXT: ]>
2 changes: 1 addition & 1 deletion clang/test/CodeGen/tbaa-struct.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ void copy12(UnionMember2 *a1, UnionMember2 *a2) {
// CHECK-OLD: [[TS6]] = !{i64 0, i64 2, [[TAG_CHAR]], i64 2, i64 1, [[TAG_CHAR]], i64 8, i64 8, [[TAG_DOUBLE:!.+]]}
// CHECK-OLD: [[TAG_DOUBLE]] = !{[[DOUBLE:!.+]], [[DOUBLE]], i64 0}
// CHECK-OLD [[DOUBLE]] = !{!"double", [[CHAR]], i64 0}
// CHECK-OLD: [[TS7]] = !{i64 0, i64 1, [[TAG_CHAR]], i64 1, i64 1, [[TAG_CHAR]], i64 2, i64 1, [[TAG_CHAR]], i64 3, i64 1, [[TAG_CHAR]], i64 4, i64 1, [[TAG_CHAR]], i64 8, i64 8, [[TAG_DOUBLE]], i64 16, i64 1, [[TAG_CHAR]]}
// CHECK-OLD: [[TS7]] = !{i64 0, i64 1, [[TAG_CHAR]], i64 1, i64 1, [[TAG_CHAR]], i64 2, i64 1, [[TAG_CHAR]], i64 3, i64 2, [[TAG_CHAR]], i64 8, i64 8, [[TAG_DOUBLE]], i64 16, i64 1, [[TAG_CHAR]]}
// CHECK-OLD: [[TS8]] = !{i64 0, i64 4, [[TAG_CHAR]], i64 8, i64 8, [[TAG_DOUBLE]]}
// CHECK-OLD: [[TS9]] = !{i64 0, i64 8, [[TAG_CHAR]], i64 8, i64 4, [[TAG_INT]]}
// CHECK-OLD: [[TS10]] = !{i64 0, i64 4, [[TAG_INT]], i64 8, i64 8, [[TAG_CHAR]]}
Expand Down
150 changes: 150 additions & 0 deletions clang/test/CodeGenCXX/bitfield-access-empty.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
// Check if we can merge bitfields across empty members

// Configs that have cheap unaligned access
// Little Endian
// RUN: %clang_cc1 -triple=aarch64-apple-darwin %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=aarch64-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=arm-apple-darwin %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT-DWN32 %s
// RUN: %clang_cc1 -triple=arm-none-eabi %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=i686-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=loongarch64-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=powerpcle-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=ve-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=wasm32 %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=wasm64 %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=x86_64-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s

// Big Endian
// RUN: %clang_cc1 -triple=powerpc-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=powerpc64-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=systemz %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s

// Configs that have expensive unaligned access
// Little Endian
// RUN: %clang_cc1 -triple=amdgcn-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=arc-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=bpf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=csky %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=hexagon-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=le64-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=loongarch32-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=nvptx-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=riscv32 %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=riscv64 %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=spir-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=xcore-none-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s

// Big endian
// RUN: %clang_cc1 -triple=lanai-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=m68k-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=mips-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=mips64-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=sparc-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=tce-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s

struct Empty {};

struct P1 {
unsigned a : 16;
[[no_unique_address]] Empty e;
unsigned b : 16;
} p1;
// CHECK-LABEL: LLVMType:%struct.P1 =
// LAYOUT-SAME: type { i16, i16 }
// LAYOUT-DWN32-SAME: type { i16, i16 }
// CHECK-NEXT: NonVirtualBaseLLVMType:%struct.P1 =
// CHECK: BitFields:[
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:0 StorageSize:16 StorageOffset:0
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:0 StorageSize:16 StorageOffset:2

// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:0 StorageSize:16 StorageOffset:0
// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:0 StorageSize:16 StorageOffset:2
// CHECK-NEXT: ]>

struct P2 {
unsigned a : 15;
[[no_unique_address]] Empty e;
unsigned b : 15;
} p2;
// CHECK-LABEL: LLVMType:%struct.P2 =
// LAYOUT-SAME: type { i16, i16 }
// LAYOUT-DWN32-SAME: type { i16, i16 }
// CHECK-NEXT: NonVirtualBaseLLVMType:%struct.P2 =
// CHECK: BitFields:[
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:15 IsSigned:0 StorageSize:16 StorageOffset:0
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:15 IsSigned:0 StorageSize:16 StorageOffset:2

// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:15 IsSigned:0 StorageSize:16 StorageOffset:0
// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:15 IsSigned:0 StorageSize:16 StorageOffset:2
// CHECK-NEXT: ]>

struct P3 {
unsigned a : 16;
Empty e;
unsigned b : 16;
} p3;
// CHECK-LABEL: LLVMType:%struct.P3 =
// LAYOUT-SAME: type { i16, %struct.Empty, i16, [2 x i8] }
// LAYOUT-DWN32-SAME: type <{ i16, %struct.Empty, i16 }>
// CHECK-NEXT: NonVirtualBaseLLVMType:%struct.P3 =
// CHECK: BitFields:[
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:0 StorageSize:16 StorageOffset:0
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:0 StorageSize:16 StorageOffset:4

// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:0 StorageSize:16 StorageOffset:0
// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:0 StorageSize:16 StorageOffset:3
// CHECK-NEXT: ]>

struct P4 {
unsigned : 0;
} p4;
// CHECK-LABEL: LLVMType:%struct.P4 =
// LAYOUT-SAME: type { {{.+}} }
// CHECK-NEXT: NonVirtualBaseLLVMType:%struct.P4 =
// CHECK: BitFields:[
// CHECK-NEXT: ]>

struct P5 {
~P5();
unsigned : 0;
} p5;
// CHECK-LABEL: LLVMType:%struct.P5 =
// CHECK-NEXT: NonVirtualBaseLLVMType:%struct.P5.base = type {}
// CHECK: BitFields:[
// CHECK-NEXT: ]>

struct P6 {
unsigned a : 16;
unsigned b : 8;
[[no_unique_address]] Empty e;
unsigned c;
} p6;
// CHECK-LABEL: LLVMType:%struct.P6 =
// LAYOUT-SAME: type { i32, i32 }
// LAYOUT-DWN32-SAME: type { i32, i32 }
// CHECK-NEXT: NonVirtualBaseLLVMType:%struct.P6 =
// CHECK: BitFields:[
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:0 StorageSize:32 StorageOffset:0
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:32 StorageOffset:0

// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:0 StorageSize:32 StorageOffset:0
// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:32 StorageOffset:0
// CHECK-NEXT: ]>

struct P7 {
unsigned a : 16;
unsigned b : 8;
Empty e;
unsigned c;
} p7;
// CHECK-LABEL: LLVMType:%struct.P7 =
// LAYOUT-SAME: type { i16, i8, %struct.Empty, i32 }
// LAYOUT-DWN32-SAME: type { i16, i8, %struct.Empty, i32 }
// CHECK-NEXT: NonVirtualBaseLLVMType:%struct.P7 =
// CHECK: BitFields:[
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:0 StorageSize:16 StorageOffset:0
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:2

// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:0 StorageSize:16 StorageOffset:0
// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:2
// CHECK-NEXT: ]>
115 changes: 115 additions & 0 deletions clang/test/CodeGenCXX/bitfield-access-tail.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// Check we use tail padding if it is known to be safe

// Configs that have cheap unaligned access
// Little Endian
// RUN: %clang_cc1 -triple=aarch64-apple-darwin %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=aarch64-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=arm-apple-darwin %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT-DWN32 %s
// RUN: %clang_cc1 -triple=arm-none-eabi %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=i686-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=loongarch64-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=powerpcle-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=ve-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=wasm32 %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=wasm64 %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=x86_64-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s

// Big Endian
// RUN: %clang_cc1 -triple=powerpc-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=powerpc64-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=systemz %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s

// Configs that have expensive unaligned access
// Little Endian
// RUN: %clang_cc1 -triple=amdgcn-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=arc-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=bpf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=csky %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=hexagon-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=le64-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=loongarch32-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=nvptx-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=riscv32 %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=riscv64 %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=spir-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=xcore-none-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s

// Big endian
// RUN: %clang_cc1 -triple=lanai-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=m68k-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=mips-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=mips64-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=sparc-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=tce-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s

// Can use tail padding
struct Pod {
int a : 16;
int b : 8;
} P;
// CHECK-LABEL: LLVMType:%struct.Pod =
// LAYOUT-SAME: type { i32 }
// LAYOUT-DWN32-SAME: type <{ i16, i8 }>
// CHECK-NEXT: NonVirtualBaseLLVMType:%struct.Pod =
// CHECK: BitFields:[
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:32 StorageOffset:0
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:32 StorageOffset:0

// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:16 StorageOffset:0
// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:8 StorageOffset:2
// CHECK-NEXT: ]>

// No tail padding
struct __attribute__((packed)) PPod {
int a : 16;
int b : 8;
} PP;
// CHECK-LABEL: LLVMType:%struct.PPod =
// LAYOUT-SAME: type <{ i16, i8 }>
// LAYOUT-DWN32-SAME: type <{ i16, i8 }>
// CHECK-NEXT: NonVirtualBaseLLVMType:%struct.PPod =
// CHECK: BitFields:[
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:16 StorageOffset:0
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:8 StorageOffset:2

// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:16 StorageOffset:0
// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:8 StorageOffset:2
// CHECK-NEXT: ]>

// Cannot use tail padding
struct NonPod {
~NonPod();
int a : 16;
int b : 8;
} NP;
// CHECK-LABEL: LLVMType:%struct.NonPod =
// LAYOUT-SAME: type <{ i16, i8, i8 }>
// LAYOUT-DWN32-SAME: type <{ i16, i8 }>
// CHECK-NEXT: NonVirtualBaseLLVMType:%struct.
// LAYOUT-SAME: NonPod.base = type <{ i16, i8 }>
// LAYOUT-DWN32-SAME: NonPod = type <{ i16, i8 }>
// CHECK: BitFields:[
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:16 StorageOffset:0
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:8 StorageOffset:2

// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:16 StorageOffset:0
// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:8 StorageOffset:2
// CHECK-NEXT: ]>

// No tail padding
struct __attribute__((packed)) PNonPod {
~PNonPod();
int a : 16;
int b : 8;
} PNP;
// CHECK-LABEL: LLVMType:%struct.PNonPod =
// LAYOUT-SAME: type <{ i16, i8 }>
// LAYOUT-DWN32-SAME: type <{ i16, i8 }>
// CHECK-NEXT: NonVirtualBaseLLVMType:%struct.PNonPod =
// CHECK: BitFields:[
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:16 StorageOffset:0
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:8 StorageOffset:2

// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:16 StorageOffset:0
// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:8 StorageOffset:2
// CHECK-NEXT: ]>
101 changes: 101 additions & 0 deletions clang/test/CodeGenCXX/bitfield-ir.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 2
// RUN: %clang_cc1 -triple x86_64-linux-gnu -O2 -emit-llvm -o - %s | FileCheck %s

struct Tail {
~Tail();
int a : 16;
int b : 8;
};

struct Char {
int a : 16;
int b : 8;
char c;
};

struct Int {
int a : 16;
int b : 8;
int c;
};


// CHECK-LABEL: define dso_local void @_Z1AP4Tail
// CHECK-SAME: (ptr nocapture noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[BF_LOAD:%.*]] = load i16, ptr [[P]], align 4
// CHECK-NEXT: [[INC:%.*]] = add i16 [[BF_LOAD]], 1
// CHECK-NEXT: store i16 [[INC]], ptr [[P]], align 4
// CHECK-NEXT: ret void
//
void A (Tail *p) {
p->a++;
}

// CHECK-LABEL: define dso_local void @_Z1BP4Tail
// CHECK-SAME: (ptr nocapture noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[B:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 2
// CHECK-NEXT: [[BF_LOAD:%.*]] = load i8, ptr [[B]], align 2
// CHECK-NEXT: [[INC:%.*]] = add i8 [[BF_LOAD]], 1
// CHECK-NEXT: store i8 [[INC]], ptr [[B]], align 2
// CHECK-NEXT: ret void
//
void B (Tail *p) {
p->b++;
}

// CHECK-LABEL: define dso_local void @_Z1AP4Char
// CHECK-SAME: (ptr nocapture noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[BF_LOAD:%.*]] = load i16, ptr [[P]], align 4
// CHECK-NEXT: [[INC:%.*]] = add i16 [[BF_LOAD]], 1
// CHECK-NEXT: store i16 [[INC]], ptr [[P]], align 4
// CHECK-NEXT: ret void
//
void A (Char *p) {
p->a++;
}

// CHECK-LABEL: define dso_local void @_Z1BP4Char
// CHECK-SAME: (ptr nocapture noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[B:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 2
// CHECK-NEXT: [[BF_LOAD:%.*]] = load i8, ptr [[B]], align 2
// CHECK-NEXT: [[INC:%.*]] = add i8 [[BF_LOAD]], 1
// CHECK-NEXT: store i8 [[INC]], ptr [[B]], align 2
// CHECK-NEXT: ret void
//
void B (Char *p) {
p->b++;
}

// CHECK-LABEL: define dso_local void @_Z1AP3Int
// CHECK-SAME: (ptr nocapture noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[P]], align 4
// CHECK-NEXT: [[INC:%.*]] = add i32 [[BF_LOAD]], 1
// CHECK-NEXT: [[BF_VALUE:%.*]] = and i32 [[INC]], 65535
// CHECK-NEXT: [[BF_CLEAR:%.*]] = and i32 [[BF_LOAD]], -65536
// CHECK-NEXT: [[BF_SET:%.*]] = or disjoint i32 [[BF_VALUE]], [[BF_CLEAR]]
// CHECK-NEXT: store i32 [[BF_SET]], ptr [[P]], align 4
// CHECK-NEXT: ret void
//
void A (Int *p) {
p->a++;
}

// CHECK-LABEL: define dso_local void @_Z1BP3Int
// CHECK-SAME: (ptr nocapture noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[P]], align 4
// CHECK-NEXT: [[BF_VALUE:%.*]] = add i32 [[BF_LOAD]], 65536
// CHECK-NEXT: [[BF_SHL2:%.*]] = and i32 [[BF_VALUE]], 16711680
// CHECK-NEXT: [[BF_CLEAR:%.*]] = and i32 [[BF_LOAD]], -16711681
// CHECK-NEXT: [[BF_SET:%.*]] = or disjoint i32 [[BF_SHL2]], [[BF_CLEAR]]
// CHECK-NEXT: store i32 [[BF_SET]], ptr [[P]], align 4
// CHECK-NEXT: ret void
//
void B (Int *p) {
p->b++;
}
101 changes: 97 additions & 4 deletions clang/test/CodeGenCXX/bitfield.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s \
// RUN: | FileCheck -check-prefix=CHECK-X86-64 %s
// RUN: %clang_cc1 -triple powerpc64-unknown-unknown -emit-llvm -o - %s \
// RUN: | FileCheck -check-prefix=CHECK-PPC64 %s
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fdump-record-layouts-simple \
// RUN: -emit-llvm -o %t %s | FileCheck -check-prefixes=LAYOUT,LAYOUT-X86-64 %s
// RUN: FileCheck -check-prefix=CHECK-X86-64 %s <%t
// RUN: %clang_cc1 -triple powerpc64-unknown-unknown -fdump-record-layouts-simple\
// RUN: -emit-llvm -o %t %s | FileCheck -check-prefixes=LAYOUT,LAYOUT-PPC64 %s
// RUN: FileCheck -check-prefix=CHECK-PPC64 %s <%t
//
// Tests for bitfield access patterns in C++ with special attention to
// conformance to C++11 memory model requirements.
Expand All @@ -19,6 +21,27 @@ namespace N0 {
unsigned b70 : 6;
unsigned b71 : 2;
};
// LAYOUT-LABEL: LLVMType:%"struct.N0::S" =
// LAYOUT-SAME: type { i64 }
// LAYOUT: BitFields:[
// LAYOUT-X86-64-NEXT: <CGBitFieldInfo Offset:0 Size:14 IsSigned:0 StorageSize:64 StorageOffset:0
// LAYOUT-X86-64-NEXT: <CGBitFieldInfo Offset:14 Size:2 IsSigned:0 StorageSize:64 StorageOffset:0
// LAYOUT-X86-64-NEXT: <CGBitFieldInfo Offset:16 Size:6 IsSigned:0 StorageSize:64 StorageOffset:0
// LAYOUT-X86-64-NEXT: <CGBitFieldInfo Offset:22 Size:2 IsSigned:0 StorageSize:64 StorageOffset:0
// LAYOUT-X86-64-NEXT: <CGBitFieldInfo Offset:24 Size:30 IsSigned:0 StorageSize:64 StorageOffset:0
// LAYOUT-X86-64-NEXT: <CGBitFieldInfo Offset:54 Size:2 IsSigned:0 StorageSize:64 StorageOffset:0
// LAYOUT-X86-64-NEXT: <CGBitFieldInfo Offset:56 Size:6 IsSigned:0 StorageSize:64 StorageOffset:0
// LAYOUT-X86-64-NEXT: <CGBitFieldInfo Offset:62 Size:2 IsSigned:0 StorageSize:64 StorageOffset:0
// LAYOUT-PPC64-NEXT: <CGBitFieldInfo Offset:50 Size:14 IsSigned:0 StorageSize:64 StorageOffset:0
// LAYOUT-PPC64-NEXT: <CGBitFieldInfo Offset:48 Size:2 IsSigned:0 StorageSize:64 StorageOffset:0
// LAYOUT-PPC64-NEXT: <CGBitFieldInfo Offset:42 Size:6 IsSigned:0 StorageSize:64 StorageOffset:0
// LAYOUT-PPC64-NEXT: <CGBitFieldInfo Offset:40 Size:2 IsSigned:0 StorageSize:64 StorageOffset:0
// LAYOUT-PPC64-NEXT: <CGBitFieldInfo Offset:10 Size:30 IsSigned:0 StorageSize:64 StorageOffset:0
// LAYOUT-PPC64-NEXT: <CGBitFieldInfo Offset:8 Size:2 IsSigned:0 StorageSize:64 StorageOffset:0
// LAYOUT-PPC64-NEXT: <CGBitFieldInfo Offset:2 Size:6 IsSigned:0 StorageSize:64 StorageOffset:0
// LAYOUT-PPC64-NEXT: <CGBitFieldInfo Offset:0 Size:2 IsSigned:0 StorageSize:64 StorageOffset:0
// LAYOUT-NEXT: ]>

unsigned read00(S* s) {
// CHECK-X86-64-LABEL: define{{.*}} i32 @_ZN2N06read00
// CHECK-X86-64: %[[val:.*]] = load i64, ptr %{{.*}}
Expand Down Expand Up @@ -149,6 +172,13 @@ namespace N1 {
unsigned b : 1;
char c;
};
// LAYOUT-LABEL: LLVMType:%"struct.N1::S" =
// LAYOUT-SAME: type { i8, i8, i8, i8 }
// LAYOUT: BitFields:[
// LAYOUT-X86-64-NEXT: <CGBitFieldInfo Offset:0 Size:1 IsSigned:0 StorageSize:8 StorageOffset:1
// LAYOUT-PPC64-NEXT: <CGBitFieldInfo Offset:7 Size:1 IsSigned:0 StorageSize:8 StorageOffset:1
// LAYOUT-NEXT: ]>

unsigned read(S* s) {
// CHECK-X86-64-LABEL: define{{.*}} i32 @_ZN2N14read
// CHECK-X86-64: %[[ptr:.*]] = getelementptr inbounds %{{.*}}, ptr %{{.*}}, i32 0, i32 1
Expand Down Expand Up @@ -193,6 +223,13 @@ namespace N2 {
unsigned b : 24;
void *p;
};
// LAYOUT-LABEL: LLVMType:%"struct.N2::S" =
// LAYOUT-SAME: type { i32, ptr }
// LAYOUT: BitFields:[
// LAYOUT-X86-64-NEXT: <CGBitFieldInfo Offset:0 Size:24 IsSigned:0 StorageSize:32 StorageOffset:0
// LAYOUT-PPC64-NEXT: <CGBitFieldInfo Offset:8 Size:24 IsSigned:0 StorageSize:32 StorageOffset:0
// LAYOUT-NEXT: ]>

unsigned read(S* s) {
// CHECK-X86-64-LABEL: define{{.*}} i32 @_ZN2N24read
// CHECK-X86-64: %[[val:.*]] = load i32, ptr %{{.*}}
Expand Down Expand Up @@ -230,6 +267,13 @@ namespace N3 {
struct S {
unsigned b : 24;
};
// LAYOUT-LABEL: LLVMType:%"struct.N3::S" =
// LAYOUT-SAME: type { i32 }
// LAYOUT: BitFields:[
// LAYOUT-X86-64-NEXT: <CGBitFieldInfo Offset:0 Size:24 IsSigned:0 StorageSize:32 StorageOffset:0
// LAYOUT-PPC64-NEXT: <CGBitFieldInfo Offset:8 Size:24 IsSigned:0 StorageSize:32 StorageOffset:0
// LAYOUT-NEXT: ]>

unsigned read(S* s) {
// CHECK-X86-64-LABEL: define{{.*}} i32 @_ZN2N34read
// CHECK-X86-64: %[[val:.*]] = load i32, ptr %{{.*}}
Expand Down Expand Up @@ -276,6 +320,14 @@ namespace N4 {
char c;
};
#endif
// LAYOUT-LABEL: LLVMType:%"struct.N4::Base" =
// LAYOUT-SAME: type <{ ptr, [3 x i8], [5 x i8] }>
// LAYOUT-NEXT: NonVirtualBaseLLVMType:%"struct.N4::Base.base" = type <{ ptr, [3 x i8] }>
// LAYOUT: BitFields:[
// LAYOUT-X86-64-NEXT: <CGBitFieldInfo Offset:0 Size:24 IsSigned:0 StorageSize:24 StorageOffset:8
// LAYOUT-PPC64-NEXT: <CGBitFieldInfo Offset:0 Size:24 IsSigned:0 StorageSize:24 StorageOffset:8
// LAYOUT-NEXT: ]>

unsigned read(Base* s) {
// FIXME: We should widen this load as long as the function isn't being
// instrumented by ThreadSanitizer.
Expand Down Expand Up @@ -317,6 +369,22 @@ namespace N5 {
struct X { unsigned b : 24; char c; } x;
struct Y { unsigned b : 24; } y;
};
// LAYOUT-LABEL: LLVMType:%"struct.N5::U::X" =
// LAYOUT-SAME: type { [3 x i8], i8 }
// LAYOUT-NEXT: NonVirtualBaseLLVMType:%"struct.N5::U::X" =
// LAYOUT: BitFields:[
// LAYOUT-X86-64-NEXT: <CGBitFieldInfo Offset:0 Size:24 IsSigned:0 StorageSize:24 StorageOffset:0
// LAYOUT-PPC64-NEXT: <CGBitFieldInfo Offset:0 Size:24 IsSigned:0 StorageSize:24 StorageOffset:0
// LAYOUT-NEXT: ]>

// LAYOUT-LABEL: LLVMType:%"struct.N5::U::Y" =
// LAYOUT-SAME: type { i32 }
// LAYOUT-NEXT: NonVirtualBaseLLVMType:%"struct.N5::U::Y" =
// LAYOUT: BitFields:[
// LAYOUT-X86-64-NEXT: <CGBitFieldInfo Offset:0 Size:24 IsSigned:0 StorageSize:32 StorageOffset:0
// LAYOUT-PPC64-NEXT: <CGBitFieldInfo Offset:8 Size:24 IsSigned:0 StorageSize:32 StorageOffset:0
// LAYOUT-NEXT: ]>

unsigned read(U* u) {
// CHECK-X86-64-LABEL: define{{.*}} i32 @_ZN2N54read
// CHECK-X86-64: %[[val:.*]] = load i32, ptr %{{.*}}
Expand Down Expand Up @@ -360,6 +428,15 @@ namespace N6 {
unsigned char : 0;
unsigned char b2 : 8;
};
// LAYOUT-LABEL: LLVMType:%"struct.N6::S" =
// LAYOUT-SAME: type { [3 x i8], i8 }
// LAYOUT: BitFields:[
// LAYOUT-X86-64-NEXT: <CGBitFieldInfo Offset:0 Size:24 IsSigned:0 StorageSize:24 StorageOffset:0
// LAYOUT-X86-64-NEXT: <CGBitFieldInfo Offset:0 Size:8 IsSigned:0 StorageSize:8 StorageOffset:3
// LAYOUT-PPC64-NEXT: <CGBitFieldInfo Offset:0 Size:24 IsSigned:0 StorageSize:24 StorageOffset:0
// LAYOUT-PPC64-NEXT: <CGBitFieldInfo Offset:0 Size:8 IsSigned:0 StorageSize:8 StorageOffset:3
// LAYOUT-NEXT: ]>

unsigned read(S* s) {
// CHECK-X86-64-LABEL: define{{.*}} i32 @_ZN2N64read
// CHECK-X86-64: %[[val1:.*]] = load i24, ptr %{{.*}}
Expand Down Expand Up @@ -416,6 +493,22 @@ namespace N7 {
char c;
};
#endif
// LAYOUT-LABEL: LLVMType:%"struct.N7::B1" =
// LAYOUT-SAME: type <{ ptr, [3 x i8], [5 x i8] }>
// LAYOUT-NEXT: NonVirtualBaseLLVMType:%"struct.N7::B1.base" = type <{ ptr, [3 x i8] }>
// LAYOUT: BitFields:[
// LAYOUT-X86-64-NEXT: <CGBitFieldInfo Offset:0 Size:24 IsSigned:0 StorageSize:24 StorageOffset:8
// LAYOUT-PPC64-NEXT: <CGBitFieldInfo Offset:0 Size:24 IsSigned:0 StorageSize:24 StorageOffset:8
// LAYOUT-NEXT: ]>

// LAYOUT-LABEL: LLVMType:%"struct.N7::B2" =
// LAYOUT-SAME: type <{ ptr, [3 x i8], [5 x i8], %"struct.N7::B1.base", [5 x i8] }>
// LAYOUT-NEXT: NonVirtualBaseLLVMType:%"struct.N7::B2.base" = type <{ ptr, [3 x i8] }>
// LAYOUT: BitFields:[
// LAYOUT-X86-64-NEXT: <CGBitFieldInfo Offset:0 Size:24 IsSigned:0 StorageSize:24 StorageOffset:8
// LAYOUT-PPC64-NEXT: <CGBitFieldInfo Offset:0 Size:24 IsSigned:0 StorageSize:24 StorageOffset:8
// LAYOUT-NEXT: ]>

unsigned read(B2* s) {
// FIXME: We should widen this load as long as the function isn't being
// instrumented by ThreadSanitizer.
Expand Down
8 changes: 4 additions & 4 deletions clang/test/OpenMP/atomic_capture_codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -811,7 +811,7 @@ int main(void) {
#pragma omp atomic relaxed capture
iv = bfx4.a = bfx4.a * ldv;
// CHECK: [[EXPR:%.+]] = load x86_fp80, ptr @{{.+}}
// CHECK: [[PREV_VALUE:%.+]] = load atomic i8, ptr getelementptr (i8, ptr @{{.+}}, i64 2) monotonic, align 1
// CHECK: [[PREV_VALUE:%.+]] = load atomic i8, ptr getelementptr inbounds (%struct.BitFields4_packed, ptr @{{.+}}, i32 0, i32 1) monotonic, align 1
// CHECK: br label %[[CONT:.+]]
// CHECK: [[CONT]]
// CHECK: [[OLD_BF_VALUE:%.+]] = phi i8 [ [[PREV_VALUE]], %{{.+}} ], [ [[FAILED_OLD_VAL:%.+]], %[[CONT]] ]
Expand All @@ -831,7 +831,7 @@ int main(void) {
// CHECK: or i8 [[BF_CLEAR]], [[BF_VALUE]]
// CHECK: store i8 %{{.+}}, ptr [[BITCAST1]]
// CHECK: [[NEW_BF_VALUE:%.+]] = load i8, ptr [[BITCAST1]]
// CHECK: [[RES:%.+]] = cmpxchg ptr getelementptr (i8, ptr @{{.+}}, i64 2), i8 [[OLD_BF_VALUE]], i8 [[NEW_BF_VALUE]] monotonic monotonic, align 1
// CHECK: [[RES:%.+]] = cmpxchg ptr getelementptr inbounds (%struct.BitFields4_packed, ptr @{{.+}}, i32 0, i32 1), i8 [[OLD_BF_VALUE]], i8 [[NEW_BF_VALUE]] monotonic monotonic, align 1
// CHECK: [[FAILED_OLD_VAL]] = extractvalue { i8, i1 } [[RES]], 0
// CHECK: [[FAIL_SUCCESS:%.+]] = extractvalue { i8, i1 } [[RES]], 1
// CHECK: br i1 [[FAIL_SUCCESS]], label %[[EXIT:.+]], label %[[CONT]]
Expand Down Expand Up @@ -870,7 +870,7 @@ int main(void) {
#pragma omp atomic capture release
{bfx4.b /= ldv; iv = bfx4.b;}
// CHECK: [[EXPR:%.+]] = load x86_fp80, ptr @{{.+}}
// CHECK: [[PREV_VALUE:%.+]] = load atomic i8, ptr getelementptr (i8, ptr @{{.+}}, i64 2) acquire, align 1
// CHECK: [[PREV_VALUE:%.+]] = load atomic i8, ptr getelementptr inbounds (%struct.BitFields4_packed, ptr @{{.+}}, i32 0, i32 1) acquire, align 1
// CHECK: br label %[[CONT:.+]]
// CHECK: [[CONT]]
// CHECK: [[OLD_BF_VALUE:%.+]] = phi i8 [ [[PREV_VALUE]], %[[EXIT]] ], [ [[FAILED_OLD_VAL:%.+]], %[[CONT]] ]
Expand All @@ -890,7 +890,7 @@ int main(void) {
// CHECK: or i8 [[BF_CLEAR]], [[BF_VALUE]]
// CHECK: store i8 %{{.+}}, ptr [[BITCAST1]]
// CHECK: [[NEW_BF_VALUE:%.+]] = load i8, ptr [[BITCAST1]]
// CHECK: [[RES:%.+]] = cmpxchg ptr getelementptr (i8, ptr @{{.+}}, i64 2), i8 [[OLD_BF_VALUE]], i8 [[NEW_BF_VALUE]] acquire acquire, align 1
// CHECK: [[RES:%.+]] = cmpxchg ptr getelementptr inbounds (%struct.BitFields4_packed, ptr @{{.+}}, i32 0, i32 1), i8 [[OLD_BF_VALUE]], i8 [[NEW_BF_VALUE]] acquire acquire, align 1
// CHECK: [[FAILED_OLD_VAL]] = extractvalue { i8, i1 } [[RES]], 0
// CHECK: [[FAIL_SUCCESS:%.+]] = extractvalue { i8, i1 } [[RES]], 1
// CHECK: br i1 [[FAIL_SUCCESS]], label %[[EXIT:.+]], label %[[CONT]]
Expand Down
4 changes: 2 additions & 2 deletions clang/test/OpenMP/atomic_read_codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ int main(void) {
// CHECK: store x86_fp80
#pragma omp atomic read
ldv = bfx4.a;
// CHECK: [[LD:%.+]] = load atomic i8, ptr getelementptr (i8, ptr @bfx4_packed, i64 2) monotonic, align 1
// CHECK: [[LD:%.+]] = load atomic i8, ptr getelementptr inbounds (%struct.BitFields4_packed, ptr @bfx4_packed, i32 0, i32 1) monotonic, align 1
// CHECK: store i8 [[LD]], ptr [[LDTEMP:%.+]]
// CHECK: [[LD:%.+]] = load i8, ptr [[LDTEMP]]
// CHECK: [[SHL:%.+]] = shl i8 [[LD]], 7
Expand All @@ -309,7 +309,7 @@ int main(void) {
// CHECK: store x86_fp80
#pragma omp atomic read relaxed
ldv = bfx4.b;
// CHECK: [[LD:%.+]] = load atomic i8, ptr getelementptr (i8, ptr @bfx4_packed, i64 2) acquire, align 1
// CHECK: [[LD:%.+]] = load atomic i8, ptr getelementptr inbounds (%struct.BitFields4_packed, ptr @bfx4_packed, i32 0, i32 1) acquire, align 1
// CHECK: store i8 [[LD]], ptr [[LDTEMP:%.+]]
// CHECK: [[LD:%.+]] = load i8, ptr [[LDTEMP]]
// CHECK: [[ASHR:%.+]] = ashr i8 [[LD]], 1
Expand Down
8 changes: 4 additions & 4 deletions clang/test/OpenMP/atomic_update_codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -737,7 +737,7 @@ int main(void) {
#pragma omp atomic
bfx4.a = bfx4.a * ldv;
// CHECK: [[EXPR:%.+]] = load x86_fp80, ptr @{{.+}}
// CHECK: [[PREV_VALUE:%.+]] = load atomic i8, ptr getelementptr (i8, ptr @{{.+}}, i64 2) monotonic, align 1
// CHECK: [[PREV_VALUE:%.+]] = load atomic i8, ptr getelementptr inbounds (%struct.BitFields4_packed, ptr @{{.+}}, i32 0, i32 1) monotonic, align 1
// CHECK: br label %[[CONT:.+]]
// CHECK: [[CONT]]
// CHECK: [[OLD_BF_VALUE:%.+]] = phi i8 [ [[PREV_VALUE]], %{{.+}} ], [ [[FAILED_OLD_VAL:%.+]], %[[CONT]] ]
Expand All @@ -757,7 +757,7 @@ int main(void) {
// CHECK: or i8 [[BF_CLEAR]], [[BF_VALUE]]
// CHECK: store i8 %{{.+}}, ptr [[BITCAST1]]
// CHECK: [[NEW_BF_VALUE:%.+]] = load i8, ptr [[BITCAST1]]
// CHECK: [[RES:%.+]] = cmpxchg ptr getelementptr (i8, ptr @{{.+}}, i64 2), i8 [[OLD_BF_VALUE]], i8 [[NEW_BF_VALUE]] monotonic monotonic, align 1
// CHECK: [[RES:%.+]] = cmpxchg ptr getelementptr inbounds (%struct.BitFields4_packed, ptr @{{.+}}, i32 0, i32 1), i8 [[OLD_BF_VALUE]], i8 [[NEW_BF_VALUE]] monotonic monotonic, align 1
// CHECK: [[FAILED_OLD_VAL]] = extractvalue { i8, i1 } [[RES]], 0
// CHECK: [[FAIL_SUCCESS:%.+]] = extractvalue { i8, i1 } [[RES]], 1
// CHECK: br i1 [[FAIL_SUCCESS]], label %[[EXIT:.+]], label %[[CONT]]
Expand Down Expand Up @@ -792,7 +792,7 @@ int main(void) {
#pragma omp atomic
bfx4.b /= ldv;
// CHECK: [[EXPR:%.+]] = load x86_fp80, ptr @{{.+}}
// CHECK: [[PREV_VALUE:%.+]] = load atomic i8, ptr getelementptr (i8, ptr @{{.+}}, i64 2) monotonic, align 1
// CHECK: [[PREV_VALUE:%.+]] = load atomic i8, ptr getelementptr inbounds (%struct.BitFields4_packed, ptr @{{.+}}, i32 0, i32 1) monotonic, align 1
// CHECK: br label %[[CONT:.+]]
// CHECK: [[CONT]]
// CHECK: [[OLD_BF_VALUE:%.+]] = phi i8 [ [[PREV_VALUE]], %[[EXIT]] ], [ [[FAILED_OLD_VAL:%.+]], %[[CONT]] ]
Expand All @@ -812,7 +812,7 @@ int main(void) {
// CHECK: or i8 [[BF_CLEAR]], [[BF_VALUE]]
// CHECK: store i8 %{{.+}}, ptr [[BITCAST1]]
// CHECK: [[NEW_BF_VALUE:%.+]] = load i8, ptr [[BITCAST1]]
// CHECK: [[RES:%.+]] = cmpxchg ptr getelementptr (i8, ptr @{{.+}}, i64 2), i8 [[OLD_BF_VALUE]], i8 [[NEW_BF_VALUE]] monotonic monotonic, align 1
// CHECK: [[RES:%.+]] = cmpxchg ptr getelementptr inbounds (%struct.BitFields4_packed, ptr @{{.+}}, i32 0, i32 1), i8 [[OLD_BF_VALUE]], i8 [[NEW_BF_VALUE]] monotonic monotonic, align 1
// CHECK: [[FAILED_OLD_VAL]] = extractvalue { i8, i1 } [[RES]], 0
// CHECK: [[FAIL_SUCCESS:%.+]] = extractvalue { i8, i1 } [[RES]], 1
// CHECK: br i1 [[FAIL_SUCCESS]], label %[[EXIT:.+]], label %[[CONT]]
Expand Down
8 changes: 4 additions & 4 deletions clang/test/OpenMP/atomic_write_codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ int main(void) {
bfx4.a = ldv;
// CHECK: load x86_fp80, ptr @{{.+}}
// CHECK: [[NEW_VAL:%.+]] = fptosi x86_fp80 %{{.+}} to i32
// CHECK: [[PREV_VALUE:%.+]] = load atomic i8, ptr getelementptr (i8, ptr @{{.+}}, i64 2) monotonic, align 1
// CHECK: [[PREV_VALUE:%.+]] = load atomic i8, ptr getelementptr inbounds (%struct.BitFields4_packed, ptr @{{.+}}, i32 0, i32 1) monotonic, align 1
// CHECK: br label %[[CONT:.+]]
// CHECK: [[CONT]]
// CHECK: [[OLD_BF_VALUE:%.+]] = phi i8 [ [[PREV_VALUE]], %[[EXIT]] ], [ [[FAILED_OLD_VAL:%.+]], %[[CONT]] ]
Expand All @@ -423,7 +423,7 @@ int main(void) {
// CHECK: or i8 [[BF_CLEAR]], [[BF_VALUE]]
// CHECK: store i8 %{{.+}}, ptr [[LDTEMP:%.+]]
// CHECK: [[NEW_BF_VALUE:%.+]] = load i8, ptr [[LDTEMP]]
// CHECK: [[RES:%.+]] = cmpxchg ptr getelementptr (i8, ptr @{{.+}}, i64 2), i8 [[OLD_BF_VALUE]], i8 [[NEW_BF_VALUE]] monotonic monotonic, align 1
// CHECK: [[RES:%.+]] = cmpxchg ptr getelementptr inbounds (%struct.BitFields4_packed, ptr @{{.+}}, i32 0, i32 1), i8 [[OLD_BF_VALUE]], i8 [[NEW_BF_VALUE]] monotonic monotonic, align 1
// CHECK: [[FAILED_OLD_VAL]] = extractvalue { i8, i1 } [[RES]], 0
// CHECK: [[FAIL_SUCCESS:%.+]] = extractvalue { i8, i1 } [[RES]], 1
// CHECK: br i1 [[FAIL_SUCCESS]], label %[[EXIT:.+]], label %[[CONT]]
Expand Down Expand Up @@ -451,7 +451,7 @@ int main(void) {
bfx4.b = ldv;
// CHECK: load x86_fp80, ptr @{{.+}}
// CHECK: [[NEW_VAL:%.+]] = fptosi x86_fp80 %{{.+}} to i64
// CHECK: [[PREV_VALUE:%.+]] = load atomic i8, ptr getelementptr (i8, ptr @{{.+}}, i64 2) monotonic, align 1
// CHECK: [[PREV_VALUE:%.+]] = load atomic i8, ptr getelementptr inbounds (%struct.BitFields4_packed, ptr @{{.+}}, i32 0, i32 1) monotonic, align 1
// CHECK: br label %[[CONT:.+]]
// CHECK: [[CONT]]
// CHECK: [[OLD_BF_VALUE:%.+]] = phi i8 [ [[PREV_VALUE]], %[[EXIT]] ], [ [[FAILED_OLD_VAL:%.+]], %[[CONT]] ]
Expand All @@ -462,7 +462,7 @@ int main(void) {
// CHECK: or i8 [[BF_CLEAR]], [[BF_VALUE]]
// CHECK: store i8 %{{.+}}, ptr [[LDTEMP:%.+]]
// CHECK: [[NEW_BF_VALUE:%.+]] = load i8, ptr [[LDTEMP]]
// CHECK: [[RES:%.+]] = cmpxchg ptr getelementptr (i8, ptr @{{.+}}, i64 2), i8 [[OLD_BF_VALUE]], i8 [[NEW_BF_VALUE]] monotonic monotonic, align 1
// CHECK: [[RES:%.+]] = cmpxchg ptr getelementptr inbounds (%struct.BitFields4_packed, ptr @{{.+}}, i32 0, i32 1), i8 [[OLD_BF_VALUE]], i8 [[NEW_BF_VALUE]] monotonic monotonic, align 1
// CHECK: [[FAILED_OLD_VAL]] = extractvalue { i8, i1 } [[RES]], 0
// CHECK: [[FAIL_SUCCESS:%.+]] = extractvalue { i8, i1 } [[RES]], 1
// CHECK: br i1 [[FAIL_SUCCESS]], label %[[EXIT:.+]], label %[[CONT]]
Expand Down