diff options
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 3 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGAtomic.cpp | 16 | ||||
| -rw-r--r-- | clang/test/CodeGen/atomics-sema-alignment.c | 27 | 
3 files changed, 40 insertions, 6 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index d2a484c415f..152879cac39 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -7111,6 +7111,9 @@ def warn_atomic_op_has_invalid_memory_order : Warning<    InGroup<DiagGroup<"atomic-memory-ordering">>;  def err_atomic_op_has_invalid_synch_scope : Error<    "synchronization scope argument to atomic operation is invalid">; +def warn_atomic_op_misaligned : Warning< +  "misaligned or large atomic operation may incur significant performance penalty">, +  InGroup<DiagGroup<"atomic-alignment">>;  def err_overflow_builtin_must_be_int : Error<    "operand argument to overflow builtin must be an integer (%0 invalid)">; diff --git a/clang/lib/CodeGen/CGAtomic.cpp b/clang/lib/CodeGen/CGAtomic.cpp index efc708988ab..47a82b602a0 100644 --- a/clang/lib/CodeGen/CGAtomic.cpp +++ b/clang/lib/CodeGen/CGAtomic.cpp @@ -18,6 +18,7 @@  #include "TargetInfo.h"  #include "clang/AST/ASTContext.h"  #include "clang/CodeGen/CGFunctionInfo.h" +#include "clang/Sema/SemaDiagnostic.h"  #include "llvm/ADT/DenseMap.h"  #include "llvm/IR/DataLayout.h"  #include "llvm/IR/Intrinsics.h" @@ -751,6 +752,13 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {    Address Dest = Address::invalid();    Address Ptr = EmitPointerWithAlignment(E->getPtr()); +  if (E->getOp() == AtomicExpr::AO__c11_atomic_init || +      E->getOp() == AtomicExpr::AO__opencl_atomic_init) { +    LValue lvalue = MakeAddrLValue(Ptr, AtomicTy); +    EmitAtomicInit(E->getVal1(), lvalue); +    return RValue::get(nullptr); +  } +    CharUnits sizeChars, alignChars;    std::tie(sizeChars, alignChars) = getContext().getTypeInfoInChars(AtomicTy);    uint64_t Size = sizeChars.getQuantity(); @@ -758,12 +766,8 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {    bool UseLibcall = ((Ptr.getAlignment() % sizeChars) != 0 ||                       getContext().toBits(sizeChars) > MaxInlineWidthInBits); -  if (E->getOp() == AtomicExpr::AO__c11_atomic_init || -      E->getOp() == AtomicExpr::AO__opencl_atomic_init) { -    LValue lvalue = MakeAddrLValue(Ptr, AtomicTy); -    EmitAtomicInit(E->getVal1(), lvalue); -    return RValue::get(nullptr); -  } +  if (UseLibcall) +    CGM.getDiags().Report(E->getLocStart(), diag::warn_atomic_op_misaligned);    llvm::Value *Order = EmitScalarExpr(E->getOrder());    llvm::Value *Scope = diff --git a/clang/test/CodeGen/atomics-sema-alignment.c b/clang/test/CodeGen/atomics-sema-alignment.c new file mode 100644 index 00000000000..364743dd53f --- /dev/null +++ b/clang/test/CodeGen/atomics-sema-alignment.c @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -triple aarch64-linux-gnu %s -emit-llvm -o /dev/null -verify + +typedef struct { +  int a, b; +} IntPair; + +typedef struct { +  long long a; +} LongStruct; + +typedef int __attribute__((aligned(1))) unaligned_int; + +void func(IntPair *p) { +  IntPair res; +  __atomic_load(p, &res, 0); // expected-warning {{misaligned or large atomic operation may incur significant performance penalty}} +  __atomic_store(p, &res, 0); // expected-warning {{misaligned or large atomic operation may incur significant performance penalty}} +  __atomic_fetch_add((unaligned_int *)p, 1, 2); // expected-warning {{misaligned or large atomic operation may incur significant performance penalty}} +  __atomic_fetch_sub((unaligned_int *)p, 1, 3); // expected-warning {{misaligned or large atomic operation may incur significant performance penalty}} +} + +void func1(LongStruct *p) { +  LongStruct res; +  __atomic_load(p, &res, 0); +  __atomic_store(p, &res, 0); +  __atomic_fetch_add((int *)p, 1, 2); +  __atomic_fetch_sub((int *)p, 1, 3); +}  | 

