Index: lib/CodeGen/CGAtomic.cpp =================================================================== --- lib/CodeGen/CGAtomic.cpp +++ lib/CodeGen/CGAtomic.cpp @@ -665,6 +665,20 @@ MemTy = AT->getValueType(); CharUnits sizeChars, alignChars; std::tie(sizeChars, alignChars) = getContext().getTypeInfoInChars(AtomicTy); + + // Get alignment from declaration. + if (const auto *UO = dyn_cast(E->getPtr())) + if (UO->getOpcode() == UO_AddrOf) { + CharUnits alignDecl; + if (const auto *DRE = dyn_cast(UO->getSubExpr())) + alignDecl = + getContext().toCharUnitsFromBits(DRE->getDecl()->getMaxAlignment()); + else if (const auto *ME = dyn_cast(UO->getSubExpr())) + alignDecl = getContext().toCharUnitsFromBits( + ME->getMemberDecl()->getMaxAlignment()); + alignChars = std::max(alignChars, alignDecl); + } + uint64_t Size = sizeChars.getQuantity(); unsigned MaxInlineWidthInBits = getTarget().getMaxAtomicInlineWidth(); bool UseLibcall = (sizeChars != alignChars || Index: test/CodeGenCXX/atomic-align.cpp =================================================================== --- test/CodeGenCXX/atomic-align.cpp +++ test/CodeGenCXX/atomic-align.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 %s -std=c++11 -emit-llvm -o - -triple=x86_64-linux-gnu | FileCheck %s + +struct AM { + int f1, f2; +}; +alignas(8) AM m; +AM load1() { + AM am; + // m is declared to align to 8bytes, so generate load atomic instead + // of libcall. + // CHECK-LABEL: @_Z5load1v + // CHECK: load atomic {{.*}} monotonic + __atomic_load(&m, &am, 0); + return am; +} + +struct BM { + int f1; + alignas(8) AM f2; +}; +BM bm; +AM load2() { + AM am; + // BM::f2 is declared to align to 8bytes, so generate load atomic instead + // of libcall. + // CHECK-LABEL: @_Z5load2v + // CHECK: load atomic {{.*}} monotonic + __atomic_load(&bm.f2, &am, 0); + return am; +}