Index: lib/CodeGen/CGRecordLayoutBuilder.cpp =================================================================== --- lib/CodeGen/CGRecordLayoutBuilder.cpp +++ lib/CodeGen/CGRecordLayoutBuilder.cpp @@ -403,6 +403,22 @@ } return; } + + // Check if current Field is better to be a single field run. + // When current field has legal integer width, and its bitfield offset is + // naturally aligned, it is better to make the bitfield a separate storage + // component so as it can be accessed directly. + auto betterBeSingleFieldRun = [&](RecordDecl::field_iterator Field) { + if (!DataLayout.isLegalInteger(Field->getBitWidthValue(Context))) + return false; + // Make sure Field is natually aligned if it is treated as an IType integer. + llvm::Type *IType = getIntNType(Field->getBitWidthValue(Context)); + if (getFieldBitOffset(*Field) % Context.toBits(getAlignment(IType)) != 0) + return false; + return true; + }; + + bool SingleFieldRun = false; for (;;) { // Check to see if we need to start a new run. if (Run == FieldEnd) { @@ -414,16 +430,21 @@ Run = Field; StartBitOffset = getFieldBitOffset(*Field); Tail = StartBitOffset + Field->getBitWidthValue(Context); + SingleFieldRun = betterBeSingleFieldRun(Run); } ++Field; continue; } + // Add bitfields to the run as long as they qualify. - if (Field != FieldEnd && Field->getBitWidthValue(Context) != 0 && - Tail == getFieldBitOffset(*Field)) { - Tail += Field->getBitWidthValue(Context); - ++Field; - continue; + if (Field != FieldEnd && !SingleFieldRun) { + SingleFieldRun = betterBeSingleFieldRun(Field); + if (!SingleFieldRun && Field->getBitWidthValue(Context) != 0 && + Tail == getFieldBitOffset(*Field)) { + Tail += Field->getBitWidthValue(Context); + ++Field; + continue; + } } // We've hit a break-point in the run and need to emit a storage field. llvm::Type *Type = getIntNType(Tail - StartBitOffset); @@ -435,6 +456,7 @@ Members.push_back(MemberInfo(bitsToCharUnits(StartBitOffset), MemberInfo::Field, nullptr, *Run)); Run = FieldEnd; + SingleFieldRun = false; } } Index: test/CodeGen/2009-12-07-BitFieldAlignment.c =================================================================== --- test/CodeGen/2009-12-07-BitFieldAlignment.c +++ test/CodeGen/2009-12-07-BitFieldAlignment.c @@ -4,7 +4,7 @@ struct S { int a, b; void *c; - unsigned d : 8; + unsigned d : 7; unsigned e : 8; }; Index: test/CodeGenCXX/2009-12-23-MissingSext.cpp =================================================================== --- test/CodeGenCXX/2009-12-23-MissingSext.cpp +++ test/CodeGenCXX/2009-12-23-MissingSext.cpp @@ -3,7 +3,8 @@ // getting extended to 32 bits, so uninitialized // bits of the temporary were used. 7366161. struct foo { - char x:8; + char x1:3; + char x2:5; signed int y:24; }; int bar(struct foo p, int x) { Index: test/CodeGenCXX/bitfield.cpp =================================================================== --- test/CodeGenCXX/bitfield.cpp +++ test/CodeGenCXX/bitfield.cpp @@ -478,3 +478,42 @@ s->b = x; } } + +namespace N8 { + // If a bitfield has the width of legal integer type and it is natually aligned to such type, + // the bitfield will be accessed like a separate memory location. + struct S { + unsigned b1 : 6; + unsigned b2 : 10; + unsigned b3 : 16; + unsigned b4 : 4; + }; + unsigned read(S* s) { + // CHECK-X86-64-LABEL: define i32 @_ZN2N84readEPNS_1SE + // CHECK-X86-64: %[[gep:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %{{.*}}, i32 0, i32 1 + // CHECK-X86-64: %[[val:.*]] = load i16, i16* %[[gep]] + // CHECK-X86-64: %[[ext:.*]] = zext i16 %[[val]] to i32 + // CHECK-X86-64: ret i32 %[[ext]] + // CHECK-PPC64-LABEL: define zeroext i32 @_ZN2N84readEPNS_1SE + // CHECK-PPC64: %[[val:.*]] = load i64, i64* {{.*}} + // CHECK-PPC64: %[[shr:.*]] = lshr i64 %[[val]], 32 + // CHECK-PPC64: %[[and:.*]] = and i64 %[[shr]], 65535 + // CHECK-PPC64: %[[trunc:.*]] = trunc i64 %[[and]] to i32 + // CHECK-PPC64: ret i32 %[[trunc]] + return s->b3; + } + void write(S* s, unsigned x) { + // CHECK-X86-64-LABEL: define void @_ZN2N85writeEPNS_1SEj + // CHECK-X86-64: %[[gep:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %{{.*}}, i32 0, i32 1 + // CHECK-X86-64: %[[new:.*]] = trunc i32 %{{.*}} to i16 + // CHECK-X86-64: store i16 %[[new]], i16* %[[gep]] + // CHECK-PPC64-LABEL: define void @_ZN2N85writeEPNS_1SEj + // CHECK-PPC64: %[[load:.*]] = load i64, i64* {{.*}} + // CHECK-PPC64: %[[and1:.*]] = and i64 {{.*}}, 65535 + // CHECK-PPC64: %[[shl:.*]] = shl i64 %[[and1]], 32 + // CHECK-PPC64: %[[and2:.*]] = and i64 %[[load]], -281470681743361 + // CHECK-PPC64: %[[or:.*]] = or i64 %[[and2]], %[[shl]] + // CHECK-PPC64: store i64 %[[or]], i64* {{.*}} + s->b3 = x; + } +} Index: test/CodeGenCXX/pod-member-memcpys.cpp =================================================================== --- test/CodeGenCXX/pod-member-memcpys.cpp +++ test/CodeGenCXX/pod-member-memcpys.cpp @@ -69,7 +69,7 @@ struct BitfieldMember3 { virtual void f(); - int : 8; + int z : 8; int x : 1; int y; }; Index: test/OpenMP/atomic_capture_codegen.cpp =================================================================== --- test/OpenMP/atomic_capture_codegen.cpp +++ test/OpenMP/atomic_capture_codegen.cpp @@ -27,12 +27,14 @@ int4 int4x; struct BitFields { - int : 32; + int : 2; + int : 30; int a : 31; } bfx; struct BitFields_packed { - int : 32; + int : 2; + int : 30; int a : 31; } __attribute__ ((__packed__)) bfx_packed; @@ -57,13 +59,15 @@ } __attribute__ ((__packed__)) bfx3_packed; struct BitFields4 { - short : 16; + short : 6; + short : 10; int a: 1; long b : 7; } bfx4; struct BitFields4_packed { - short : 16; + short : 6; + short : 10; int a: 1; long b : 7; } __attribute__ ((__packed__)) bfx4_packed; Index: test/OpenMP/atomic_read_codegen.c =================================================================== --- test/OpenMP/atomic_read_codegen.c +++ test/OpenMP/atomic_read_codegen.c @@ -28,12 +28,14 @@ int4 int4x; struct BitFields { - int : 32; + int : 2; + int : 30; int a : 31; } bfx; struct BitFields_packed { - int : 32; + int : 2; + int : 30; int a : 31; } __attribute__ ((__packed__)) bfx_packed; @@ -58,13 +60,15 @@ } __attribute__ ((__packed__)) bfx3_packed; struct BitFields4 { - short : 16; + short : 6; + short : 10; int a: 1; long b : 7; } bfx4; struct BitFields4_packed { - short : 16; + short : 6; + short : 10; int a: 1; long b : 7; } __attribute__ ((__packed__)) bfx4_packed; Index: test/OpenMP/atomic_update_codegen.cpp =================================================================== --- test/OpenMP/atomic_update_codegen.cpp +++ test/OpenMP/atomic_update_codegen.cpp @@ -27,12 +27,14 @@ int4 int4x; struct BitFields { - int : 32; + int : 2; + int : 30; int a : 31; } bfx; struct BitFields_packed { - int : 32; + int : 2; + int : 30; int a : 31; } __attribute__ ((__packed__)) bfx_packed; @@ -57,13 +59,15 @@ } __attribute__ ((__packed__)) bfx3_packed; struct BitFields4 { - short : 16; + short : 6; + short : 10; int a: 1; long b : 7; } bfx4; struct BitFields4_packed { - short : 16; + short : 6; + short : 10; int a: 1; long b : 7; } __attribute__ ((__packed__)) bfx4_packed; Index: test/OpenMP/atomic_write_codegen.c =================================================================== --- test/OpenMP/atomic_write_codegen.c +++ test/OpenMP/atomic_write_codegen.c @@ -28,12 +28,14 @@ int4 int4x; struct BitFields { - int : 32; + int : 2; + int : 30; int a : 31; } bfx; struct BitFields_packed { - int : 32; + int : 2; + int : 30; int a : 31; } __attribute__ ((__packed__)) bfx_packed; @@ -58,13 +60,15 @@ } __attribute__ ((__packed__)) bfx3_packed; struct BitFields4 { - short : 16; + short : 6; + short : 10; int a: 1; long b : 7; } bfx4; struct BitFields4_packed { - short : 16; + short : 6; + short : 10; int a: 1; long b : 7; } __attribute__ ((__packed__)) bfx4_packed;