Index: lib/CodeGen/CGExpr.cpp =================================================================== --- lib/CodeGen/CGExpr.cpp +++ lib/CodeGen/CGExpr.cpp @@ -1356,6 +1356,9 @@ RValue CodeGenFunction::EmitLoadOfBitfieldLValue(LValue LV) { const CGBitFieldInfo &Info = LV.getBitFieldInfo(); + int64_t Align = Info.StorageAlignment; + if (!LV.getAlignment().isZero()) + Align = std::min(Align, LV.getAlignment().getQuantity()); // Get the output type. llvm::Type *ResLTy = ConvertType(LV.getType()); @@ -1363,7 +1366,7 @@ llvm::Value *Ptr = LV.getBitFieldAddr(); llvm::Value *Val = Builder.CreateLoad(Ptr, LV.isVolatileQualified(), "bf.load"); - cast(Val)->setAlignment(Info.StorageAlignment); + cast(Val)->setAlignment(Align); if (Info.IsSigned) { assert(static_cast(Info.Offset + Info.Size) <= Info.StorageSize); @@ -1559,6 +1562,9 @@ void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst, llvm::Value **Result) { const CGBitFieldInfo &Info = Dst.getBitFieldInfo(); + int64_t Align = Info.StorageAlignment; + if (!Dst.getAlignment().isZero()) + Align = std::min(Align, Dst.getAlignment().getQuantity()); llvm::Type *ResLTy = ConvertTypeForMem(Dst.getType()); llvm::Value *Ptr = Dst.getBitFieldAddr(); @@ -1577,7 +1583,7 @@ assert(Info.StorageSize > Info.Size && "Invalid bitfield size."); llvm::Value *Val = Builder.CreateLoad(Ptr, Dst.isVolatileQualified(), "bf.load"); - cast(Val)->setAlignment(Info.StorageAlignment); + cast(Val)->setAlignment(Align); // Mask the source value as needed. if (!hasBooleanRepresentation(Dst.getType())) @@ -1605,7 +1611,7 @@ // Write the new value back out. llvm::StoreInst *Store = Builder.CreateStore(SrcVal, Ptr, Dst.isVolatileQualified()); - Store->setAlignment(Info.StorageAlignment); + Store->setAlignment(Align); // Return the new value of the bit-field, if requested. if (Result) { Index: test/CodeGen/packed-nest-unpacked.c =================================================================== --- test/CodeGen/packed-nest-unpacked.c +++ test/CodeGen/packed-nest-unpacked.c @@ -60,6 +60,35 @@ unsigned test7() { // CHECK: @test7 - // CHECK: load i32, i32* getelementptr inbounds (%struct.YBitfield, %struct.YBitfield* @gbitfield, i32 0, i32 1, i32 0), align 4 + // CHECK: load i32, i32* getelementptr inbounds (%struct.YBitfield, %struct.YBitfield* @gbitfield, i32 0, i32 1, i32 0), align 1 return gbitfield.y.b2; } + +void test8(unsigned x) { + // CHECK: @test8 + // CHECK: load i32, i32* getelementptr inbounds (%struct.YBitfield, %struct.YBitfield* @gbitfield, i32 0, i32 1, i32 0), align 1 + // CHECK: store i32 {{.*}}, i32* getelementptr inbounds (%struct.YBitfield, %struct.YBitfield* @gbitfield, i32 0, i32 1, i32 0), align 1 + gbitfield.y.b2 = x; +} + +struct TBitfield +{ + long a; + char b; + unsigned c:15; +}; +struct TBitfield tbitfield; + +unsigned test9() { + // CHECK: @test9 + // CHECK: load i16, i16* getelementptr inbounds (%struct.TBitfield, %struct.TBitfield* @tbitfield, i32 0, i32 2), align 1 + return tbitfield.c; +} + +void test10(unsigned x) { + // CHECK: @test10 + // CHECK: load i16, i16* getelementptr inbounds (%struct.TBitfield, %struct.TBitfield* @tbitfield, i32 0, i32 2), align 1 + // CHECK: store i16 {{.*}}, i16* getelementptr inbounds (%struct.TBitfield, %struct.TBitfield* @tbitfield, i32 0, i32 2), align 1 + tbitfield.c = x; +} +