Skip to content

Commit 54d544b

Browse files
authored
[KeyInstr][Clang] Ret atom (#134652)
This patch is part of a stack that teaches Clang to generate Key Instructions metadata for C and C++. When returning a value, stores to the `retval` allocas and branches to `return` block are put in the same atom group. They are both rank 1, which could in theory introduce an extra step in some optimized code. This low risk currently feels an acceptable for keeping the code a bit simpler (as opposed to adding scaffolding to make the store rank 2). In the case of a single return (no control flow) the return instruction inherits the atom group of the branch to the return block when the blocks get folded togather. 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 a7f0b29 commit 54d544b

28 files changed

+235
-24
lines changed

clang/lib/CodeGen/CGCall.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3929,9 +3929,9 @@ llvm::Value *CodeGenFunction::EmitCMSEClearRecord(llvm::Value *Src,
39293929
return R;
39303930
}
39313931

3932-
void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
3933-
bool EmitRetDbgLoc,
3934-
SourceLocation EndLoc) {
3932+
void CodeGenFunction::EmitFunctionEpilog(
3933+
const CGFunctionInfo &FI, bool EmitRetDbgLoc, SourceLocation EndLoc,
3934+
uint64_t RetKeyInstructionsSourceAtom) {
39353935
if (FI.isNoReturn()) {
39363936
// Noreturn functions don't return.
39373937
EmitUnreachable(EndLoc);
@@ -3946,7 +3946,11 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
39463946

39473947
// Functions with no result always return void.
39483948
if (!ReturnValue.isValid()) {
3949-
Builder.CreateRetVoid();
3949+
auto *I = Builder.CreateRetVoid();
3950+
if (RetKeyInstructionsSourceAtom)
3951+
addInstToSpecificSourceAtom(I, nullptr, RetKeyInstructionsSourceAtom);
3952+
else
3953+
addInstToNewSourceAtom(I, nullptr);
39503954
return;
39513955
}
39523956

@@ -4126,6 +4130,12 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
41264130

41274131
if (RetDbgLoc)
41284132
Ret->setDebugLoc(std::move(RetDbgLoc));
4133+
4134+
llvm::Value *Backup = RV ? Ret->getOperand(0) : nullptr;
4135+
if (RetKeyInstructionsSourceAtom)
4136+
addInstToSpecificSourceAtom(Ret, Backup, RetKeyInstructionsSourceAtom);
4137+
else
4138+
addInstToNewSourceAtom(Ret, Backup);
41294139
}
41304140

41314141
void CodeGenFunction::EmitReturnValueCheck(llvm::Value *RV) {

clang/lib/CodeGen/CGStmt.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1605,6 +1605,7 @@ static bool isSwiftAsyncCallee(const CallExpr *CE) {
16051605
/// if the function returns void, or may be missing one if the function returns
16061606
/// non-void. Fun stuff :).
16071607
void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
1608+
ApplyAtomGroup Grp(getDebugInfo());
16081609
if (requiresReturnValueCheck()) {
16091610
llvm::Constant *SLoc = EmitCheckSourceLocation(S.getBeginLoc());
16101611
auto *SLocPtr =
@@ -1680,16 +1681,19 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
16801681
// If this function returns a reference, take the address of the expression
16811682
// rather than the value.
16821683
RValue Result = EmitReferenceBindingToExpr(RV);
1683-
Builder.CreateStore(Result.getScalarVal(), ReturnValue);
1684+
auto *I = Builder.CreateStore(Result.getScalarVal(), ReturnValue);
1685+
addInstToCurrentSourceAtom(I, I->getValueOperand());
16841686
} else {
16851687
switch (getEvaluationKind(RV->getType())) {
16861688
case TEK_Scalar: {
16871689
llvm::Value *Ret = EmitScalarExpr(RV);
1688-
if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect)
1690+
if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect) {
16891691
EmitStoreOfScalar(Ret, MakeAddrLValue(ReturnValue, RV->getType()),
16901692
/*isInit*/ true);
1691-
else
1692-
Builder.CreateStore(Ret, ReturnValue);
1693+
} else {
1694+
auto *I = Builder.CreateStore(Ret, ReturnValue);
1695+
addInstToCurrentSourceAtom(I, I->getValueOperand());
1696+
}
16931697
break;
16941698
}
16951699
case TEK_Complex:

clang/lib/CodeGen/CodeGenFunction.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -444,8 +444,10 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
444444

445445
// Reset the debug location to that of the simple 'return' expression, if any
446446
// rather than that of the end of the function's scope '}'.
447+
uint64_t RetKeyInstructionsAtomGroup = Loc ? Loc->getAtomGroup() : 0;
447448
ApplyDebugLocation AL(*this, Loc);
448-
EmitFunctionEpilog(*CurFnInfo, EmitRetDbgLoc, EndLoc);
449+
EmitFunctionEpilog(*CurFnInfo, EmitRetDbgLoc, EndLoc,
450+
RetKeyInstructionsAtomGroup);
449451
EmitEndEHSpec(CurCodeDecl);
450452

451453
assert(EHStack.empty() &&

clang/lib/CodeGen/CodeGenFunction.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2551,9 +2551,12 @@ class CodeGenFunction : public CodeGenTypeCache {
25512551
const FunctionArgList &Args);
25522552

25532553
/// EmitFunctionEpilog - Emit the target specific LLVM code to return the
2554-
/// given temporary.
2554+
/// given temporary. Specify the source location atom group (Key Instructions
2555+
/// debug info feature) for the `ret` using \p RetKeyInstructionsSourceAtom.
2556+
/// If it's 0, the `ret` will get added to a new source atom group.
25552557
void EmitFunctionEpilog(const CGFunctionInfo &FI, bool EmitRetDbgLoc,
2556-
SourceLocation EndLoc);
2558+
SourceLocation EndLoc,
2559+
uint64_t RetKeyInstructionsSourceAtom);
25572560

25582561
/// Emit a test that checks if the return value \p RV is nonnull.
25592562
void EmitReturnValueCheck(llvm::Value *RV);

clang/test/DebugInfo/KeyInstructions/agg.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ void fun(Struct a) {
2424
// CHECK: %matins = insertelement <25 x float> %3, float 0.000000e+00, i64 0, !dbg [[G4R2:!.*]]
2525
// CHECK: store <25 x float> %matins, ptr @m{{.*}}, !dbg [[G4R1:!.*]]
2626
m[0][0] = 0;
27+
28+
// CHECK: ret{{.*}}, !dbg [[RET:!.*]]
2729
}
2830

2931
// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
@@ -32,3 +34,4 @@ void fun(Struct a) {
3234
// CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
3335
// CHECK: [[G4R2]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 2)
3436
// CHECK: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1)
37+
// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 1)

clang/test/DebugInfo/KeyInstructions/assign-scalar.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ void fun() {
5858
// CHECK-NEXT: %inc4 = add i64 %7, 1, !dbg [[G11R2:!.*]]
5959
// CHECK-NEXT: store i64 %inc4, ptr @i{{.*}}, !dbg [[G11R1:!.*]]
6060
g = ++h, ++i;
61+
// CHECK: ret{{.*}}, !dbg [[RET:!.*]]
6162
}
6263

6364
// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
@@ -83,3 +84,4 @@ void fun() {
8384
// CHECK: [[load_i_loc]] = !DILocation(line: [[#]], column: [[#]], scope: ![[#]])
8485
// CHECK: [[G11R2]] = !DILocation({{.*}}, atomGroup: 11, atomRank: 2)
8586
// CHECK: [[G11R1]] = !DILocation({{.*}}, atomGroup: 11, atomRank: 1)
87+
// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 12, atomRank: 1)

clang/test/DebugInfo/KeyInstructions/bitfield.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ void foo(int x, S s) {
1010
// CHECK: %bf.set = or i8 %bf.clear, %bf.value, !dbg [[G1R2:!.*]]
1111
// CHECK: store i8 %bf.set, ptr %s, align 4, !dbg [[G1R1:!.*]]
1212
s.a = x;
13+
14+
// CHECK: ret{{.*}}, !dbg [[RET:!.*]]
1315
}
1416

1517
// CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
1618
// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
19+
// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)

clang/test/DebugInfo/KeyInstructions/builtin.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ void fun() {
6464
// CHECK-NEXT: %4 = trunc i32 %3 to i8, !dbg [[G15R2:!.*]]
6565
// CHECK-NEXT: call void @llvm.memset{{.*}}, !dbg [[G15R1:!.*]]
6666
__builtin_memset(f4, v, sizeof(float) * 4);
67+
// CHECK: ret{{.*}}, !dbg [[RET:!.*]]
6768
}
6869

6970
// CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
@@ -86,3 +87,4 @@ void fun() {
8687
// CHECK: [[G15R3]] = !DILocation({{.*}}, atomGroup: 15, atomRank: 3)
8788
// CHECK: [[G15R2]] = !DILocation({{.*}}, atomGroup: 15, atomRank: 2)
8889
// CHECK: [[G15R1]] = !DILocation({{.*}}, atomGroup: 15, atomRank: 1)
90+
// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 16, atomRank: 1)

clang/test/DebugInfo/KeyInstructions/cast.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ void a() {
1313
// CHECK: %conv = fptosi float %0 to i32{{.*}}, !dbg [[G1R2:!.*]]
1414
// CHECK: store i32 %conv, ptr %a{{.*}}, !dbg [[G1R1:!.*]]
1515
int a = g;
16+
// CHECK: ret{{.*}}, !dbg [[RET:!.*]]
1617
}
1718

1819
// CHECK: [[G1R3]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 3)
1920
// CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
2021
// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
22+
// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)

clang/test/DebugInfo/KeyInstructions/coerced-packed.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ void f() {
1414
// CHECK: [[call:%.*]] = call i40{{.*}}getS{{.*}}, !dbg [[G1R2:!.*]]
1515
// CHECK: store i40 [[call]], ptr %s, align 1, !dbg [[G1R1:!.*]]
1616
S s = getS();
17+
// CHECK: ret{{.*}}, !dbg [[RET:!.*]]
1718
}
1819

1920
// CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
2021
// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
22+
// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)

0 commit comments

Comments
 (0)