Skip to content

Commit ddecfa6

Browse files
authored
[KeyInstr][Clang] Atomic ops atoms (#141624)
This patch is part of a stack that teaches Clang to generate Key Instructions metadata for C and C++. The feature is only functional in LLVM if LLVM is built with CMake flag LLVM_EXPERIMENTAL_KEY_INSTRUCTIONs. Eventually that flag will be removed. RFC: https://discourse.llvm.org/t/rfc-improving-is-stmt-placement-for-better-interactive-debugging/82668
1 parent fa5d7c9 commit ddecfa6

File tree

2 files changed

+175
-4
lines changed

2 files changed

+175
-4
lines changed

clang/lib/CodeGen/CGAtomic.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,9 @@ static void emitAtomicCmpXchg(CodeGenFunction &CGF, AtomicExpr *E, bool IsWeak,
411411

412412
CGF.Builder.SetInsertPoint(StoreExpectedBB);
413413
// Update the memory at Expected with Old's value.
414-
CGF.Builder.CreateStore(Old, Val1);
414+
auto *I = CGF.Builder.CreateStore(Old, Val1);
415+
CGF.addInstToCurrentSourceAtom(I, Old);
416+
415417
// Finally, branch to the exit point.
416418
CGF.Builder.CreateBr(ContinueBB);
417419

@@ -591,7 +593,8 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
591593
Load->setAtomic(Order, Scope);
592594
Load->setVolatile(E->isVolatile());
593595
CGF.maybeAttachRangeForLoad(Load, E->getValueType(), E->getExprLoc());
594-
CGF.Builder.CreateStore(Load, Dest);
596+
auto *I = CGF.Builder.CreateStore(Load, Dest);
597+
CGF.addInstToCurrentSourceAtom(I, Load);
595598
return;
596599
}
597600

@@ -606,6 +609,7 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
606609
llvm::StoreInst *Store = CGF.Builder.CreateStore(LoadVal1, Ptr);
607610
Store->setAtomic(Order, Scope);
608611
Store->setVolatile(E->isVolatile());
612+
CGF.addInstToCurrentSourceAtom(Store, LoadVal1);
609613
return;
610614
}
611615

@@ -731,7 +735,8 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
731735
CGF.Builder.getInt8(1), Order, Scope, E);
732736
RMWI->setVolatile(E->isVolatile());
733737
llvm::Value *Result = CGF.Builder.CreateIsNotNull(RMWI, "tobool");
734-
CGF.Builder.CreateStore(Result, Dest);
738+
auto *I = CGF.Builder.CreateStore(Result, Dest);
739+
CGF.addInstToCurrentSourceAtom(I, Result);
735740
return;
736741
}
737742

@@ -740,6 +745,7 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
740745
CGF.Builder.CreateStore(CGF.Builder.getInt8(0), Ptr);
741746
Store->setAtomic(Order, Scope);
742747
Store->setVolatile(E->isVolatile());
748+
CGF.addInstToCurrentSourceAtom(Store, nullptr);
743749
return;
744750
}
745751
}
@@ -762,7 +768,8 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
762768
if (E->getOp() == AtomicExpr::AO__atomic_nand_fetch ||
763769
E->getOp() == AtomicExpr::AO__scoped_atomic_nand_fetch)
764770
Result = CGF.Builder.CreateNot(Result);
765-
CGF.Builder.CreateStore(Result, Dest);
771+
auto *I = CGF.Builder.CreateStore(Result, Dest);
772+
CGF.addInstToCurrentSourceAtom(I, Result);
766773
}
767774

768775
// This function emits any expression (scalar, complex, or aggregate)
@@ -845,6 +852,8 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *Expr, Address Dest,
845852
}
846853

847854
RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
855+
ApplyAtomGroup Grp(getDebugInfo());
856+
848857
QualType AtomicTy = E->getPtr()->getType()->getPointeeType();
849858
QualType MemTy = AtomicTy;
850859
if (const AtomicType *AT = AtomicTy->getAs<AtomicType>())
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
// RUN: %clang_cc1 -triple x86_64-linux-gnu -gkey-instructions -x c++ -std=c++17 %s -debug-info-kind=line-tables-only -emit-llvm -o - -gno-column-info \
2+
// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
3+
// RUN: %clang_cc1 -triple x86_64-linux-gnu -gkey-instructions -x c %s -debug-info-kind=line-tables-only -emit-llvm -o - -gno-column-info \
4+
// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
5+
6+
// Check that atomic handling code gets Key Instruction annotations.
7+
8+
_Atomic(unsigned int) x;
9+
unsigned int y;
10+
void fun() {
11+
unsigned int r1 = __c11_atomic_fetch_add(&x,- 1, __ATOMIC_RELAXED);
12+
// CHECK: store i32 -1, ptr %.atomictmp, align 4, !dbg [[LINE11_G2R1:!.*]]
13+
// CHECK-NEXT: %0 = load i32, ptr %.atomictmp, align 4, !dbg [[LINE11:!.*]]
14+
// CHECK-NEXT: %1 = atomicrmw add ptr @x, i32 %0 monotonic, align 4, !dbg [[LINE11_G2R2:!.*]]
15+
// CHECK-NEXT: store i32 %1, ptr %atomic-temp, align 4, !dbg [[LINE11_G2R1]]
16+
// CHECK-NEXT: %2 = load i32, ptr %atomic-temp, align 4, !dbg [[LINE11_G1R2:!.*]]
17+
// CHECK-NEXT: store i32 %2, ptr %r1, align 4, !dbg [[LINE11_G1R1:!.*]]
18+
19+
unsigned int r2 = __c11_atomic_load(&x, __ATOMIC_RELAXED);
20+
// CHECK-NEXT: %3 = load atomic i32, ptr @x monotonic, align 4, !dbg [[LINE19_G4R2:!.*]]
21+
// CHECK-NEXT: store i32 %3, ptr %atomic-temp1, align 4, !dbg [[LINE19_G4R1:!.*]]
22+
// CHECK-NEXT: %4 = load i32, ptr %atomic-temp1, align 4, !dbg [[LINE19_G3R2:!.*]]
23+
// CHECK-NEXT: store i32 %4, ptr %r2, align 4, !dbg [[LINE19_G3R1:!.*]]
24+
25+
__c11_atomic_store(&x, 2, __ATOMIC_RELAXED);
26+
// CHECK-NEXT: store i32 2, ptr %.atomictmp2, align 4, !dbg [[LINE25_G5R1:!.*]]
27+
// CHECK-NEXT: %5 = load i32, ptr %.atomictmp2, align 4, !dbg [[LINE25_G5R2:!.*]]
28+
// CHECK-NEXT: store atomic i32 %5, ptr @x monotonic, align 4, !dbg [[LINE25_G5R1:!.*]]
29+
30+
int r3 = __atomic_test_and_set(&x, __ATOMIC_RELAXED);
31+
// CHECK-NEXT: %6 = atomicrmw xchg ptr @x, i8 1 monotonic, align 4, !dbg [[LINE30:!.*]]
32+
// CHECK-NEXT: %tobool = icmp ne i8 %6, 0, !dbg [[LINE30_G7R2:!.*]]
33+
// CHECK-NEXT: store i1 %tobool, ptr %atomic-temp3, align 1, !dbg [[LINE30_G7R1:!.*]]
34+
// CHECK-NEXT: %7 = load i8, ptr %atomic-temp3, align 1, !dbg [[LINE30_G6R4:!.*]]
35+
// CHECK-NEXT: %loadedv = trunc i8 %7 to i1, !dbg [[LINE30_G6R3:!.*]]
36+
// CHECK-NEXT: %conv = zext i1 %loadedv to i32, !dbg [[LINE30_G6R2:!.*]]
37+
// CHECK-NEXT: store i32 %conv, ptr %r3, align 4, !dbg [[LINE30_G6R1:!.*]]
38+
39+
__atomic_clear(&x, __ATOMIC_RELAXED);
40+
// CHECK-NEXT: store atomic i8 0, ptr @x monotonic, align 4, !dbg [[LINE39_G8R1:!.*]]
41+
42+
int r4 = __c11_atomic_exchange(&x, 2,__ATOMIC_RELAXED);
43+
// CHECK-NEXT: store i32 2, ptr %.atomictmp4, align 4, !dbg [[LINE42_G10R1:!.*]]
44+
// CHECK-NEXT: %8 = load i32, ptr %.atomictmp4, align 4, !dbg [[LINE42:!.*]]
45+
// CHECK-NEXT: %9 = atomicrmw xchg ptr @x, i32 %8 monotonic, align 4, !dbg [[LINE42_G10R2:!.*]]
46+
// CHECK-NEXT: store i32 %9, ptr %atomic-temp5, align 4, !dbg [[LINE42_G10R1:!.*]]
47+
// CHECK-NEXT: %10 = load i32, ptr %atomic-temp5, align 4, !dbg [[LINE42_G9R2:!.*]]
48+
// CHECK-NEXT: store i32 %10, ptr %r4, align 4, !dbg [[LINE42_G9R1:!.*]]
49+
50+
int r5 = __atomic_compare_exchange(&y, &y, &y, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
51+
// CHECK-NEXT: %11 = load i32, ptr @y, align 4, !dbg [[LINE50:!.*]]
52+
// CHECK-NEXT: %12 = load i32, ptr @y, align 4, !dbg [[LINE50]]
53+
// CHECK-NEXT: %13 = cmpxchg ptr @y, i32 %11, i32 %12 monotonic monotonic, align 4, !dbg [[LINE50]]
54+
// CHECK-NEXT: %14 = extractvalue { i32, i1 } %13, 0, !dbg [[LINE50_G12R2:!.*]]
55+
// CHECK-NEXT: %15 = extractvalue { i32, i1 } %13, 1, !dbg [[LINE50_G12R3:!.*]]
56+
// CHECK-NEXT: br i1 %15, label %cmpxchg.continue, label %cmpxchg.store_expected, !dbg [[LINE50]]
57+
// CHECK: cmpxchg.store_expected:
58+
// CHECK-NEXT: store i32 %14, ptr @y, align 4, !dbg [[LINE50_G12R1:!.*]]
59+
// CHECK-NEXT: br label %cmpxchg.continue, !dbg [[LINE50]]
60+
// CHECK: cmpxchg.continue:
61+
// CHECK-NEXT: %storedv = zext i1 %15 to i8, !dbg [[LINE50_G12R2]]
62+
// CHECK-NEXT: store i8 %storedv, ptr %cmpxchg.bool, align 1, !dbg [[LINE50_G12R1]]
63+
// CHECK-NEXT: %16 = load i8, ptr %cmpxchg.bool, align 1, !dbg [[LINE50_G11R4:!.*]]
64+
// CHECK-NEXT: %loadedv6 = trunc i8 %16 to i1, !dbg [[LINE50_G11R3:!.*]]
65+
// CHECK-NEXT: %conv7 = zext i1 %loadedv6 to i32, !dbg [[LINE50_G11R2:!.*]]
66+
// CHECK-NEXT: store i32 %conv7, ptr %r5, align 4, !dbg [[LINE50_G11R1:!.*]]
67+
68+
int r6 = __c11_atomic_compare_exchange_strong(&x, &y, 42, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
69+
// CHECK-NEXT: store i32 42, ptr %.atomictmp8, align 4, !dbg [[LINE68_G14R1:!.*]]
70+
// CHECK-NEXT: %17 = load i32, ptr @y, align 4, !dbg [[LINE68:!.*]]
71+
// CHECK-NEXT: %18 = load i32, ptr %.atomictmp8, align 4, !dbg [[LINE68]]
72+
// CHECK-NEXT: %19 = cmpxchg ptr @x, i32 %17, i32 %18 monotonic monotonic, align 4, !dbg [[LINE68]]
73+
// CHECK-NEXT: %20 = extractvalue { i32, i1 } %19, 0, !dbg [[LINE68_G14R2:!.*]]
74+
// CHECK-NEXT: %21 = extractvalue { i32, i1 } %19, 1, !dbg [[LINE68_G14R3:!.*]]
75+
// CHECK-NEXT: br i1 %21, label %cmpxchg.continue11, label %cmpxchg.store_expected10, !dbg [[LINE68]]
76+
// CHECK: cmpxchg.store_expected10:
77+
// CHECK-NEXT: store i32 %20, ptr @y, align 4, !dbg [[LINE68_G14R1:!.*]]
78+
// CHECK-NEXT: br label %cmpxchg.continue11, !dbg [[LINE68]]
79+
// CHECK: cmpxchg.continue11:
80+
// CHECK-NEXT: %storedv12 = zext i1 %21 to i8, !dbg [[LINE68_G14R2]]
81+
// CHECK-NEXT: store i8 %storedv12, ptr %cmpxchg.bool9, align 1, !dbg [[LINE68_G14R1:!.*]]
82+
// CHECK-NEXT: %22 = load i8, ptr %cmpxchg.bool9, align 1, !dbg [[LINE68_G13R4:!.*]]
83+
// CHECK-NEXT: %loadedv13 = trunc i8 %22 to i1, !dbg [[LINE68_G13R3:!.*]]
84+
// CHECK-NEXT: %conv14 = zext i1 %loadedv13 to i32, !dbg [[LINE68_G13R2:!.*]]
85+
// CHECK-NEXT: store i32 %conv14, ptr %r6, align 4, !dbg [[LINE68_G13R1:!.*]]
86+
87+
int r7 = __c11_atomic_compare_exchange_weak(&x, &y, 43, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
88+
// CHECK-NEXT: store i32 43, ptr %.atomictmp15, align 4, !dbg [[LINE87_G16R1:!.*]]
89+
// CHECK-NEXT: %23 = load i32, ptr @y, align 4, !dbg [[LINE87:!.*]]
90+
// CHECK-NEXT: %24 = load i32, ptr %.atomictmp15, align 4, !dbg [[LINE87]]
91+
// CHECK-NEXT: %25 = cmpxchg weak ptr @x, i32 %23, i32 %24 monotonic monotonic, align 4, !dbg [[LINE87]]
92+
// CHECK-NEXT: %26 = extractvalue { i32, i1 } %25, 0, !dbg [[LINE87_G16R2:!.*]]
93+
// CHECK-NEXT: %27 = extractvalue { i32, i1 } %25, 1, !dbg [[LINE87_G16R3:!.*]]
94+
// CHECK-NEXT: br i1 %27, label %cmpxchg.continue18, label %cmpxchg.store_expected17, !dbg [[LINE87]]
95+
// CHECK: cmpxchg.store_expected17:
96+
// CHECK-NEXT: store i32 %26, ptr @y, align 4, !dbg [[LINE87_G16R1]]
97+
// CHECK-NEXT: br label %cmpxchg.continue18, !dbg [[LINE87]]
98+
// CHECK: cmpxchg.continue18:
99+
// CHECK-NEXT: %storedv19 = zext i1 %27 to i8, !dbg [[LINE87_G16R2]]
100+
// CHECK-NEXT: store i8 %storedv19, ptr %cmpxchg.bool16, align 1, !dbg [[LINE87_G16R1]]
101+
// CHECK-NEXT: %28 = load i8, ptr %cmpxchg.bool16, align 1, !dbg [[LINE87_G15R4:!.*]]
102+
// CHECK-NEXT: %loadedv20 = trunc i8 %28 to i1, !dbg [[LINE87_G15R3:!.*]]
103+
// CHECK-NEXT: %conv21 = zext i1 %loadedv20 to i32, !dbg [[LINE87_G15R2:!.*]]
104+
// CHECK-NEXT: store i32 %conv21, ptr %r7, align 4, !dbg [[LINE87_G15R1:!.*]]
105+
}
106+
107+
// CHECK: [[LINE11_G2R1]] = !DILocation(line: 11, scope: ![[#]], atomGroup: 2, atomRank: 1)
108+
// CHECK: [[LINE11]] = !DILocation(line: 11, scope: ![[#]])
109+
// CHECK: [[LINE11_G2R2]] = !DILocation(line: 11, scope: ![[#]], atomGroup: 2, atomRank: 2)
110+
// CHECK: [[LINE11_G1R2]] = !DILocation(line: 11, scope: ![[#]], atomGroup: 1, atomRank: 2)
111+
// CHECK: [[LINE11_G1R1]] = !DILocation(line: 11, scope: ![[#]], atomGroup: 1, atomRank: 1)
112+
113+
// CHECK: [[LINE19_G4R2]] = !DILocation(line: 19, scope: ![[#]], atomGroup: 4, atomRank: 2)
114+
// CHECK: [[LINE19_G4R1]] = !DILocation(line: 19, scope: ![[#]], atomGroup: 4, atomRank: 1)
115+
// CHECK: [[LINE19_G3R2]] = !DILocation(line: 19, scope: ![[#]], atomGroup: 3, atomRank: 2)
116+
// CHECK: [[LINE19_G3R1]] = !DILocation(line: 19, scope: ![[#]], atomGroup: 3, atomRank: 1)
117+
118+
// CHECK: [[LINE25_G5R1]] = !DILocation(line: 25, scope: ![[#]], atomGroup: 5, atomRank: 1)
119+
// CHECK: [[LINE25_G5R2]] = !DILocation(line: 25, scope: ![[#]], atomGroup: 5, atomRank: 2)
120+
121+
// CHECK: [[LINE30]] = !DILocation(line: 30, scope: ![[#]])
122+
// CHECK: [[LINE30_G7R2]] = !DILocation(line: 30, scope: ![[#]], atomGroup: 7, atomRank: 2)
123+
// CHECK: [[LINE30_G7R1]] = !DILocation(line: 30, scope: ![[#]], atomGroup: 7, atomRank: 1)
124+
// CHECK: [[LINE30_G6R4]] = !DILocation(line: 30, scope: ![[#]], atomGroup: 6, atomRank: 4)
125+
// CHECK: [[LINE30_G6R3]] = !DILocation(line: 30, scope: ![[#]], atomGroup: 6, atomRank: 3)
126+
// CHECK: [[LINE30_G6R2]] = !DILocation(line: 30, scope: ![[#]], atomGroup: 6, atomRank: 2)
127+
// CHECK: [[LINE30_G6R1]] = !DILocation(line: 30, scope: ![[#]], atomGroup: 6, atomRank: 1)
128+
129+
// CHECK: [[LINE39_G8R1]] = !DILocation(line: 39, scope: ![[#]], atomGroup: 8, atomRank: 1)
130+
131+
// CHECK: [[LINE42_G10R1]] = !DILocation(line: 42, scope: ![[#]], atomGroup: 10, atomRank: 1)
132+
// CHECK: [[LINE42]] = !DILocation(line: 42, scope: ![[#]])
133+
// CHECK: [[LINE42_G10R2]] = !DILocation(line: 42, scope: ![[#]], atomGroup: 10, atomRank: 2)
134+
// CHECK: [[LINE42_G9R2]] = !DILocation(line: 42, scope: ![[#]], atomGroup: 9, atomRank: 2)
135+
// CHECK: [[LINE42_G9R1]] = !DILocation(line: 42, scope: ![[#]], atomGroup: 9, atomRank: 1)
136+
137+
// CHECK: [[LINE50]] = !DILocation(line: 50, scope: ![[#]])
138+
// CHECK: [[LINE50_G12R2]] = !DILocation(line: 50, scope: ![[#]], atomGroup: 12, atomRank: 2)
139+
// CHECK: [[LINE50_G12R3]] = !DILocation(line: 50, scope: ![[#]], atomGroup: 12, atomRank: 3)
140+
// CHECK: [[LINE50_G12R1]] = !DILocation(line: 50, scope: ![[#]], atomGroup: 12, atomRank: 1)
141+
// CHECK: [[LINE50_G11R4]] = !DILocation(line: 50, scope: ![[#]], atomGroup: 11, atomRank: 4)
142+
// CHECK: [[LINE50_G11R3]] = !DILocation(line: 50, scope: ![[#]], atomGroup: 11, atomRank: 3)
143+
// CHECK: [[LINE50_G11R2]] = !DILocation(line: 50, scope: ![[#]], atomGroup: 11, atomRank: 2)
144+
// CHECK: [[LINE50_G11R1]] = !DILocation(line: 50, scope: ![[#]], atomGroup: 11, atomRank: 1)
145+
146+
// CHECK: [[LINE68_G14R1]] = !DILocation(line: 68, scope: ![[#]], atomGroup: 14, atomRank: 1)
147+
// CHECK: [[LINE68]] = !DILocation(line: 68, scope: ![[#]])
148+
// CHECK: [[LINE68_G14R2]] = !DILocation(line: 68, scope: ![[#]], atomGroup: 14, atomRank: 2)
149+
// CHECK: [[LINE68_G14R3]] = !DILocation(line: 68, scope: ![[#]], atomGroup: 14, atomRank: 3)
150+
// CHECK: [[LINE68_G13R4]] = !DILocation(line: 68, scope: ![[#]], atomGroup: 13, atomRank: 4)
151+
// CHECK: [[LINE68_G13R3]] = !DILocation(line: 68, scope: ![[#]], atomGroup: 13, atomRank: 3)
152+
// CHECK: [[LINE68_G13R2]] = !DILocation(line: 68, scope: ![[#]], atomGroup: 13, atomRank: 2)
153+
// CHECK: [[LINE68_G13R1]] = !DILocation(line: 68, scope: ![[#]], atomGroup: 13, atomRank: 1)
154+
155+
// CHECK: [[LINE87_G16R1]] = !DILocation(line: 87, scope: ![[#]], atomGroup: 16, atomRank: 1)
156+
// CHECK: [[LINE87]] = !DILocation(line: 87, scope: ![[#]])
157+
// CHECK: [[LINE87_G16R2]] = !DILocation(line: 87, scope: ![[#]], atomGroup: 16, atomRank: 2)
158+
// CHECK: [[LINE87_G16R3]] = !DILocation(line: 87, scope: ![[#]], atomGroup: 16, atomRank: 3)
159+
// CHECK: [[LINE87_G15R4]] = !DILocation(line: 87, scope: ![[#]], atomGroup: 15, atomRank: 4)
160+
// CHECK: [[LINE87_G15R3]] = !DILocation(line: 87, scope: ![[#]], atomGroup: 15, atomRank: 3)
161+
// CHECK: [[LINE87_G15R2]] = !DILocation(line: 87, scope: ![[#]], atomGroup: 15, atomRank: 2)
162+
// CHECK: [[LINE87_G15R1]] = !DILocation(line: 87, scope: ![[#]], atomGroup: 15, atomRank: 1)

0 commit comments

Comments
 (0)