Skip to content

Commit 9ba4432

Browse files
tschuettmemfrob
authored andcommitted
[clang] improve diagnostics for misaligned and large atomics
"Listing the alignment and access size (== expected alignment) in the warning seems like a good idea." solves PR 46947 struct Foo { struct Bar { void * a; void * b; }; Bar bar; }; struct ThirtyTwo { struct Large { void * a; void * b; void * c; void * d; }; Large bar; }; void braz(Foo *foo, ThirtyTwo *braz) { Foo::Bar bar; __atomic_load(&foo->bar, &bar, __ATOMIC_RELAXED); ThirtyTwo::Large foobar; __atomic_load(&braz->bar, &foobar, __ATOMIC_RELAXED); } repro.cpp:21:3: warning: misaligned atomic operation may incur significant performance penalty; the expected (16 bytes) exceeds the actual alignment (8 bytes) [-Watomic-alignment] __atomic_load(&foo->bar, &bar, __ATOMIC_RELAXED); ^ repro.cpp:24:3: warning: misaligned atomic operation may incur significant performance penalty; the expected (32 bytes) exceeds the actual alignment (8 bytes) [-Watomic-alignment] __atomic_load(&braz->bar, &foobar, __ATOMIC_RELAXED); ^ repro.cpp:24:3: warning: large atomic operation may incur significant performance penalty; the access size (32 bytes) exceeds the max lock-free size (16 bytes) [-Watomic-alignment] 3 warnings generated. Differential Revision: https://reviews.llvm.org/D85102
1 parent cb65e6f commit 9ba4432

File tree

4 files changed

+49
-9
lines changed

4 files changed

+49
-9
lines changed

clang/include/clang/Basic/DiagnosticFrontendKinds.td

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -270,8 +270,16 @@ def err_ifunc_resolver_return : Error<
270270
"ifunc resolver function must return a pointer">;
271271

272272
def warn_atomic_op_misaligned : Warning<
273-
"%select{large|misaligned}0 atomic operation may incur "
274-
"significant performance penalty">, InGroup<DiagGroup<"atomic-alignment">>;
273+
"misaligned atomic operation may incur "
274+
"significant performance penalty"
275+
"; the expected alignment (%0 bytes) exceeds the actual alignment (%1 bytes)">,
276+
InGroup<AtomicAlignment>;
277+
278+
def warn_atomic_op_oversized : Warning<
279+
"large atomic operation may incur "
280+
"significant performance penalty"
281+
"; the access size (%0 bytes) exceeds the max lock-free size (%1 bytes)">,
282+
InGroup<AtomicAlignment>;
275283

276284
def warn_alias_with_section : Warning<
277285
"%select{alias|ifunc}1 will not be in section '%0' but in the same section "

clang/include/clang/Basic/DiagnosticGroups.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,7 @@ def ReorderInitList : DiagGroup<"reorder-init-list">;
699699
def Reorder : DiagGroup<"reorder", [ReorderCtor, ReorderInitList]>;
700700
def UndeclaredSelector : DiagGroup<"undeclared-selector">;
701701
def ImplicitAtomic : DiagGroup<"implicit-atomic-properties">;
702+
def AtomicAlignment : DiagGroup<"atomic-alignment">;
702703
def CustomAtomic : DiagGroup<"custom-atomic-properties">;
703704
def AtomicProperties : DiagGroup<"atomic-properties",
704705
[ImplicitAtomic, CustomAtomic]>;

clang/lib/CodeGen/CGAtomic.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -807,10 +807,20 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
807807
bool Oversized = getContext().toBits(sizeChars) > MaxInlineWidthInBits;
808808
bool Misaligned = (Ptr.getAlignment() % sizeChars) != 0;
809809
bool UseLibcall = Misaligned | Oversized;
810+
CharUnits MaxInlineWidth =
811+
getContext().toCharUnitsFromBits(MaxInlineWidthInBits);
810812

811-
if (UseLibcall) {
812-
CGM.getDiags().Report(E->getBeginLoc(), diag::warn_atomic_op_misaligned)
813-
<< !Oversized;
813+
DiagnosticsEngine &Diags = CGM.getDiags();
814+
815+
if (Misaligned) {
816+
Diags.Report(E->getBeginLoc(), diag::warn_atomic_op_misaligned)
817+
<< (int)sizeChars.getQuantity()
818+
<< (int)Ptr.getAlignment().getQuantity();
819+
}
820+
821+
if (Oversized) {
822+
Diags.Report(E->getBeginLoc(), diag::warn_atomic_op_oversized)
823+
<< (int)sizeChars.getQuantity() << (int)MaxInlineWidth.getQuantity();
814824
}
815825

816826
llvm::Value *Order = EmitScalarExpr(E->getOrder());

clang/test/CodeGen/atomics-sema-alignment.c

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ typedef int __attribute__((aligned(1))) unaligned_int;
1212

1313
void func(IntPair *p) {
1414
IntPair res;
15-
__atomic_load(p, &res, 0); // expected-warning {{misaligned atomic operation may incur significant performance penalty}}
16-
__atomic_store(p, &res, 0); // expected-warning {{misaligned atomic operation may incur significant performance penalty}}
17-
__atomic_fetch_add((unaligned_int *)p, 1, 2); // expected-warning {{misaligned atomic operation may incur significant performance penalty}}
18-
__atomic_fetch_sub((unaligned_int *)p, 1, 3); // expected-warning {{misaligned atomic operation may incur significant performance penalty}}
15+
__atomic_load(p, &res, 0); // expected-warning {{misaligned atomic operation may incur significant performance penalty; the expected alignment (8 bytes) exceeds the actual alignment (4 bytes)}}
16+
__atomic_store(p, &res, 0); // expected-warning {{misaligned atomic operation may incur significant performance penalty; the expected alignment (8 bytes) exceeds the actual alignment (4 bytes)}}
17+
__atomic_fetch_add((unaligned_int *)p, 1, 2); // expected-warning {{misaligned atomic operation may incur significant performance penalty; the expected alignment (4 bytes) exceeds the actual alignment (1 bytes)}}
18+
__atomic_fetch_sub((unaligned_int *)p, 1, 3); // expected-warning {{misaligned atomic operation may incur significant performance penalty; the expected alignment (4 bytes) exceeds the actual alignment (1 bytes)}}
1919
}
2020

2121
void func1(LongStruct *p) {
@@ -25,3 +25,24 @@ void func1(LongStruct *p) {
2525
__atomic_fetch_add((int *)p, 1, 2);
2626
__atomic_fetch_sub((int *)p, 1, 3);
2727
}
28+
29+
typedef struct {
30+
void *a;
31+
void *b;
32+
} Foo;
33+
34+
typedef struct {
35+
void *a;
36+
void *b;
37+
void *c;
38+
void *d;
39+
} __attribute__((aligned(32))) ThirtyTwo;
40+
41+
void braz(Foo *foo, ThirtyTwo *braz) {
42+
Foo bar;
43+
__atomic_load(foo, &bar, __ATOMIC_RELAXED); // expected-warning {{misaligned atomic operation may incur significant performance penalty; the expected alignment (16 bytes) exceeds the actual alignment (8 bytes)}}
44+
45+
ThirtyTwo thirtyTwo1;
46+
ThirtyTwo thirtyTwo2;
47+
__atomic_load(&thirtyTwo1, &thirtyTwo2, __ATOMIC_RELAXED); // expected-warning {{large atomic operation may incur significant performance penalty; the access size (32 bytes) exceeds the max lock-free size (16 bytes)}}
48+
}

0 commit comments

Comments
 (0)