Index: lib/AST/ASTContext.cpp =================================================================== --- lib/AST/ASTContext.cpp +++ lib/AST/ASTContext.cpp @@ -1958,10 +1958,16 @@ Width = Info.Width; Align = Info.Align; - // If the size of the type doesn't exceed the platform's max - // atomic promotion width, make the size and alignment more - // favorable to atomic operations: - if (Width != 0 && Width <= Target->getMaxAtomicPromoteWidth()) { + if (!Width) { + // An otherwise zero-sized type should still generate an + // atomic operation. + Width = Target->getCharWidth(); + Align = Target->getCharWidth(); + } else if (Width <= Target->getMaxAtomicPromoteWidth()) { + // If the size of the type doesn't exceed the platform's max + // atomic promotion width, make the size and alignment more + // favorable to atomic operations: + // Round the size up to a power of 2. if (!llvm::isPowerOf2_64(Width)) Width = llvm::NextPowerOf2(Width); Index: test/CodeGen/c11atomics-ios.c =================================================================== --- test/CodeGen/c11atomics-ios.c +++ test/CodeGen/c11atomics-ios.c @@ -319,3 +319,19 @@ return __c11_atomic_compare_exchange_strong(addr, desired, *new, 5, 5); } + +struct Empty {}; + +struct Empty testEmptyStructLoad(_Atomic(struct Empty)* empty) { + // CHECK-LABEL: @testEmptyStructLoad( + // CHECK-NOT: @__atomic_load + // CHECK: load atomic i8, i8* %{{.*}} seq_cst, align 1 + return *empty; +} + +void testEmptyStructStore(_Atomic(struct Empty)* empty, struct Empty value) { + // CHECK-LABEL: @testEmptyStructStore( + // CHECK-NOT: @__atomic_store + // CHECK: store atomic i8 %{{.*}}, i8* %{{.*}} seq_cst, align 1 + *empty = value; +} Index: test/CodeGen/c11atomics.c =================================================================== --- test/CodeGen/c11atomics.c +++ test/CodeGen/c11atomics.c @@ -474,3 +474,17 @@ // CHECK: ret i1 [[RES]] return __c11_atomic_compare_exchange_strong(addr, desired, *new, 5, 5); } + +struct Empty {}; + +struct Empty test_empty_struct_load(_Atomic(struct Empty)* empty) { + // CHECK-LABEL: @test_empty_struct_load( + // CHECK: call arm_aapcscc zeroext i8 @__atomic_load_1(i8* %{{.*}}, i32 5) + return __c11_atomic_load(empty, 5); +} + +void test_empty_struct_store(_Atomic(struct Empty)* empty, struct Empty value) { + // CHECK-LABEL: @test_empty_struct_store( + // CHECK: call arm_aapcscc void @__atomic_store_1(i8* %{{.*}}, i8 zeroext %{{.*}}, i32 5) + __c11_atomic_store(empty, value, 5); +}