Skip to content

Commit 0555594

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

File tree

2 files changed

+163
-1
lines changed

2 files changed

+163
-1
lines changed

clang/lib/CodeGen/CGStmt.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1365,7 +1365,14 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S,
13651365
BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
13661366
BoolCondVal, Stmt::getLikelihood(S.getBody()));
13671367

1368-
Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
1368+
auto *I = Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
1369+
// Key Instructions: Emit the condition and branch as separate atoms to
1370+
// match existing loop stepping behaviour. FIXME: We could have the branch
1371+
// as the backup location for the condition, which would probably be a
1372+
// better experience (no jumping to the brace).
1373+
if (auto *CondI = dyn_cast<llvm::Instruction>(BoolCondVal))
1374+
addInstToNewSourceAtom(CondI, nullptr);
1375+
addInstToNewSourceAtom(I, nullptr);
13691376

13701377
if (ExitBlock != LoopExit.getBlock()) {
13711378
EmitBlock(ExitBlock);
@@ -1390,6 +1397,10 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S,
13901397
EmitStmt(S.getBody());
13911398
}
13921399

1400+
// The last block in the loop's body (which unconditionally branches to the
1401+
// `inc` block if there is one).
1402+
auto *FinalBodyBB = Builder.GetInsertBlock();
1403+
13931404
// If there is an increment, emit it next.
13941405
if (S.getInc()) {
13951406
EmitBlock(Continue.getBlock());
@@ -1419,6 +1430,12 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S,
14191430

14201431
if (CGM.shouldEmitConvergenceTokens())
14211432
ConvergenceTokenStack.pop_back();
1433+
1434+
if (FinalBodyBB) {
1435+
// Key Instructions: We want the for closing brace to be step-able on to
1436+
// match existing behaviour.
1437+
addInstToNewSourceAtom(FinalBodyBB->getTerminator(), nullptr);
1438+
}
14221439
}
14231440

14241441
void
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
// RUN: %clang_cc1 -triple x86_64-linux-gnu -gkey-instructions -x c++ %s -debug-info-kind=line-tables-only -emit-llvm -o - \
2+
// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
3+
4+
// RUN: %clang_cc1 -triple x86_64-linux-gnu -gkey-instructions -x c %s -debug-info-kind=line-tables-only -emit-llvm -o - \
5+
// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
6+
7+
// Perennial question: should the inc be its own source atom or not
8+
// (currently it is).
9+
10+
// TODO: See do.c and while.c regarding cmp and cond br groups.
11+
12+
void a(int A) {
13+
// CHECK: entry:
14+
// CHECK: store i32 0, ptr %i{{.*}}, !dbg [[G1R1:!.*]]
15+
// CHECK: for.cond:
16+
// CHECK: %cmp = icmp slt i32 %0, %1, !dbg [[G2R1:!.*]]
17+
// CHECK: br i1 %cmp, label %for.body, label %for.end, !dbg [[G3R1:!.*]]
18+
19+
// TODO: The unconditional br is given an atom group here which is useful for
20+
// O0. Since we're no longer targeting O0 we should reevaluate whether this
21+
// adds any value.
22+
// CHECK: for.body:
23+
// CHECK-NEXT: br label %for.inc, !dbg [[G5R1:!.*]]
24+
25+
// CHECK: for.inc:
26+
// CHECK: %inc = add{{.*}}, !dbg [[G4R2:!.*]]
27+
// CHECK: store i32 %inc, ptr %i{{.*}}, !dbg [[G4R1:!.*]]
28+
for (int i = 0; i < A; ++i) {
29+
}
30+
}
31+
32+
void b(int A) {
33+
// CHECK: entry:
34+
// CHECK: store i32 0, ptr %i{{.*}}, !dbg [[bG1R1:!.*]]
35+
// CHECK: for.cond:
36+
// CHECK: %cmp = icmp slt i32 %0, %1, !dbg [[bG2R1:!.*]]
37+
// CHECK: br i1 %cmp, label %for.body, label %for.end, !dbg [[bG3R1:!.*]]
38+
39+
// CHECK: for.body:
40+
// CHECK-NEXT: %2 = load i32, ptr %A.addr
41+
// - If stmt atom:
42+
// CHECK-NEXT: %cmp1 = icmp sgt i32 %2, 1, !dbg [[bG4R2:!.*]]
43+
// CHECK-NEXT: br i1 %cmp1, label %if.then, label %if.end, !dbg [[bG4R1:!.*]]
44+
// CHECK: if.then:
45+
// CHECK-NEXT: br label %if.end
46+
47+
// - For closing brace.
48+
// CHECK: if.end:
49+
// CHECK-NEXT: br label %for.inc, !dbg [[bG6R1:!.*]]
50+
51+
// CHECK: for.inc:
52+
// CHECK: %inc = add{{.*}}, !dbg [[bG5R2:!.*]]
53+
// CHECK: store i32 %inc, ptr %i{{.*}}, !dbg [[bG5R1:!.*]]
54+
for (int i = 0; i < A; ++i) {
55+
if (A > 1)
56+
;
57+
}
58+
}
59+
60+
void c(int A) {
61+
// CHECK: entry:
62+
// CHECK: for.cond:
63+
// CHECK-NEXT: %0 = load i32, ptr %A.addr
64+
// - If stmt atom:
65+
// CHECK-NEXT: %cmp = icmp sgt i32 %0, 1, !dbg [[cG1R2:!.*]]
66+
// CHECK-NEXT: br i1 %cmp, label %if.then, label %if.end, !dbg [[cG1R1:!.*]]
67+
// CHECK: if.then:
68+
// CHECK-NEXT: br label %if.end
69+
70+
// - For closing brace.
71+
// CHECK: if.end:
72+
// CHECK-NEXT: br label %for.inc, !dbg [[cG3R1:!.*]]
73+
74+
// CHECK: for.inc:
75+
// CHECK-NEXT: %1 = load i32, ptr %A.addr
76+
// CHECK-NEXT: %inc = add{{.*}}, !dbg [[cG2R2:!.*]]
77+
// CHECK-NEXT: store i32 %inc, ptr %A.addr{{.*}}, !dbg [[cG2R1:!.*]]
78+
for (; /*no cond*/ ; ++A) {
79+
if (A > 1)
80+
;
81+
}
82+
}
83+
84+
void d() {
85+
// - Check the `for` keyword gets an atom group.
86+
// CHECK: entry:
87+
// CHECK-NEXT: br label %for.cond
88+
89+
// CHECK: for.cond:
90+
// CHECK: br label %for.cond, !dbg [[dG1R1:!.*]], !llvm.loop
91+
for ( ; ; )
92+
{
93+
}
94+
}
95+
96+
int x, i;
97+
void ee();
98+
void e() {
99+
// - Check we assign an atom group to `for.body`s `br`, even without braces.
100+
// - TODO: Investigate whether this is needed.
101+
// CHECK: entry:
102+
103+
// CHECK: for.cond:
104+
// CHECK-NEXT: %0 = load i32, ptr @i
105+
// CHECK-NEXT: %cmp = icmp slt i32 %0, 3, !dbg [[eG1R1:!.*]]
106+
// CHECK-NEXT: br i1 %cmp, label %for.body, label %for.end, !dbg [[eG2R1:!.*]]
107+
108+
// CHECK: for.body:
109+
// CHECK-NEXT: %1 = load i32, ptr @i{{.*}}, !dbg [[eG3R2:!.*]]
110+
// CHECK-NEXT: store i32 %1, ptr @x{{.*}}, !dbg [[eG3R1:!.*]]
111+
// CHECK-NEXT: br label %for.inc, !dbg [[eG4R1:!.*]]
112+
for (; i < 3; ee())
113+
x = i;
114+
}
115+
116+
117+
// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
118+
// CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
119+
// CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
120+
// CHECK: [[G5R1]] = !DILocation(line: 29,{{.*}} atomGroup: 5, atomRank: 1)
121+
// CHECK: [[G4R2]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 2)
122+
// CHECK: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1)
123+
124+
// CHECK: [[bG1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
125+
// CHECK: [[bG2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
126+
// CHECK: [[bG3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
127+
// CHECK: [[bG4R2]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 2)
128+
// CHECK: [[bG4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1)
129+
// CHECK: [[bG6R1]] = !DILocation(line: 57,{{.*}} atomGroup: 6, atomRank: 1)
130+
// CHECK: [[bG5R2]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 2)
131+
// CHECK: [[bG5R1]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 1)
132+
133+
// CHECK: [[cG1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
134+
// CHECK: [[cG1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
135+
// CHECK: [[cG3R1]] = !DILocation(line: 81,{{.*}} atomGroup: 3, atomRank: 1)
136+
// CHECK: [[cG2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2)
137+
// CHECK: [[cG2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
138+
139+
// CHECK: [[dG1R1]] = !DILocation(line: 91, column: 3, scope: ![[#]], atomGroup: 1, atomRank: 1)
140+
141+
// CHECK: [[eG1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
142+
// CHECK: [[eG2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
143+
// CHECK: [[eG3R2]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 2)
144+
// CHECK: [[eG3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
145+
// CHECK: [[eG4R1]] = !DILocation(line: 113, column: 5, scope: ![[#]], atomGroup: 4, atomRank: 1)

0 commit comments

Comments
 (0)