diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 056caf64525a5..a67b0d8a91afb 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -3929,9 +3929,9 @@ llvm::Value *CodeGenFunction::EmitCMSEClearRecord(llvm::Value *Src, return R; } -void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI, - bool EmitRetDbgLoc, - SourceLocation EndLoc) { +void CodeGenFunction::EmitFunctionEpilog( + const CGFunctionInfo &FI, bool EmitRetDbgLoc, SourceLocation EndLoc, + uint64_t RetKeyInstructionsSourceAtom) { if (FI.isNoReturn()) { // Noreturn functions don't return. EmitUnreachable(EndLoc); @@ -3946,7 +3946,11 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI, // Functions with no result always return void. if (!ReturnValue.isValid()) { - Builder.CreateRetVoid(); + auto *I = Builder.CreateRetVoid(); + if (RetKeyInstructionsSourceAtom) + addInstToSpecificSourceAtom(I, nullptr, RetKeyInstructionsSourceAtom); + else + addInstToNewSourceAtom(I, nullptr); return; } @@ -4126,6 +4130,12 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI, if (RetDbgLoc) Ret->setDebugLoc(std::move(RetDbgLoc)); + + llvm::Value *Backup = RV ? Ret->getOperand(0) : nullptr; + if (RetKeyInstructionsSourceAtom) + addInstToSpecificSourceAtom(Ret, Backup, RetKeyInstructionsSourceAtom); + else + addInstToNewSourceAtom(Ret, Backup); } void CodeGenFunction::EmitReturnValueCheck(llvm::Value *RV) { diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 205a57cbab31a..7643cd7357938 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -1589,6 +1589,7 @@ static bool isSwiftAsyncCallee(const CallExpr *CE) { /// if the function returns void, or may be missing one if the function returns /// non-void. Fun stuff :). void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) { + ApplyAtomGroup Grp(getDebugInfo()); if (requiresReturnValueCheck()) { llvm::Constant *SLoc = EmitCheckSourceLocation(S.getBeginLoc()); auto *SLocPtr = @@ -1664,16 +1665,19 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) { // If this function returns a reference, take the address of the expression // rather than the value. RValue Result = EmitReferenceBindingToExpr(RV); - Builder.CreateStore(Result.getScalarVal(), ReturnValue); + auto *I = Builder.CreateStore(Result.getScalarVal(), ReturnValue); + addInstToCurrentSourceAtom(I, I->getValueOperand()); } else { switch (getEvaluationKind(RV->getType())) { case TEK_Scalar: { llvm::Value *Ret = EmitScalarExpr(RV); - if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect) + if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect) { EmitStoreOfScalar(Ret, MakeAddrLValue(ReturnValue, RV->getType()), /*isInit*/ true); - else - Builder.CreateStore(Ret, ReturnValue); + } else { + auto *I = Builder.CreateStore(Ret, ReturnValue); + addInstToCurrentSourceAtom(I, I->getValueOperand()); + } break; } case TEK_Complex: diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 0388c67d0100d..2ac7e9d498044 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -444,8 +444,10 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) { // Reset the debug location to that of the simple 'return' expression, if any // rather than that of the end of the function's scope '}'. + uint64_t RetKeyInstructionsAtomGroup = Loc ? Loc->getAtomGroup() : 0; ApplyDebugLocation AL(*this, Loc); - EmitFunctionEpilog(*CurFnInfo, EmitRetDbgLoc, EndLoc); + EmitFunctionEpilog(*CurFnInfo, EmitRetDbgLoc, EndLoc, + RetKeyInstructionsAtomGroup); EmitEndEHSpec(CurCodeDecl); assert(EHStack.empty() && diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index f0f051a1d26f5..cecc8c0ade729 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -2551,9 +2551,12 @@ class CodeGenFunction : public CodeGenTypeCache { const FunctionArgList &Args); /// EmitFunctionEpilog - Emit the target specific LLVM code to return the - /// given temporary. + /// given temporary. Specify the source location atom group (Key Instructions + /// debug info feature) for the `ret` using \p RetKeyInstructionsSourceAtom. + /// If it's 0, the `ret` will get added to a new source atom group. void EmitFunctionEpilog(const CGFunctionInfo &FI, bool EmitRetDbgLoc, - SourceLocation EndLoc); + SourceLocation EndLoc, + uint64_t RetKeyInstructionsSourceAtom); /// Emit a test that checks if the return value \p RV is nonnull. void EmitReturnValueCheck(llvm::Value *RV); diff --git a/clang/test/DebugInfo/KeyInstructions/agg.c b/clang/test/DebugInfo/KeyInstructions/agg.c index 33b3a0141a0f1..58d923d1d9328 100644 --- a/clang/test/DebugInfo/KeyInstructions/agg.c +++ b/clang/test/DebugInfo/KeyInstructions/agg.c @@ -24,6 +24,8 @@ void fun(Struct a) { // CHECK: %matins = insertelement <25 x float> %3, float 0.000000e+00, i64 0, !dbg [[G4R2:!.*]] // CHECK: store <25 x float> %matins, ptr @m{{.*}}, !dbg [[G4R1:!.*]] m[0][0] = 0; + +// CHECK: ret{{.*}}, !dbg [[RET:!.*]] } // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1) @@ -32,3 +34,4 @@ void fun(Struct a) { // CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1) // CHECK: [[G4R2]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 2) // CHECK: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1) +// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 1) diff --git a/clang/test/DebugInfo/KeyInstructions/assign-scalar.c b/clang/test/DebugInfo/KeyInstructions/assign-scalar.c index afb0ed8ebdfd7..0bba1830e42a3 100644 --- a/clang/test/DebugInfo/KeyInstructions/assign-scalar.c +++ b/clang/test/DebugInfo/KeyInstructions/assign-scalar.c @@ -58,6 +58,7 @@ void fun() { // CHECK-NEXT: %inc4 = add i64 %7, 1, !dbg [[G11R2:!.*]] // CHECK-NEXT: store i64 %inc4, ptr @i{{.*}}, !dbg [[G11R1:!.*]] g = ++h, ++i; +// CHECK: ret{{.*}}, !dbg [[RET:!.*]] } // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1) @@ -83,3 +84,4 @@ void fun() { // CHECK: [[load_i_loc]] = !DILocation(line: [[#]], column: [[#]], scope: ![[#]]) // CHECK: [[G11R2]] = !DILocation({{.*}}, atomGroup: 11, atomRank: 2) // CHECK: [[G11R1]] = !DILocation({{.*}}, atomGroup: 11, atomRank: 1) +// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 12, atomRank: 1) diff --git a/clang/test/DebugInfo/KeyInstructions/bitfield.cpp b/clang/test/DebugInfo/KeyInstructions/bitfield.cpp index a14b4fbaf5854..e1d4c264a426a 100644 --- a/clang/test/DebugInfo/KeyInstructions/bitfield.cpp +++ b/clang/test/DebugInfo/KeyInstructions/bitfield.cpp @@ -10,7 +10,10 @@ void foo(int x, S s) { // CHECK: %bf.set = or i8 %bf.clear, %bf.value, !dbg [[G1R2:!.*]] // CHECK: store i8 %bf.set, ptr %s, align 4, !dbg [[G1R1:!.*]] s.a = x; + +// CHECK: ret{{.*}}, !dbg [[RET:!.*]] } // CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2) // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1) +// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1) diff --git a/clang/test/DebugInfo/KeyInstructions/builtin.c b/clang/test/DebugInfo/KeyInstructions/builtin.c index 359d52ca3862e..ce8c6124fe923 100644 --- a/clang/test/DebugInfo/KeyInstructions/builtin.c +++ b/clang/test/DebugInfo/KeyInstructions/builtin.c @@ -64,6 +64,7 @@ void fun() { // CHECK-NEXT: %4 = trunc i32 %3 to i8, !dbg [[G15R2:!.*]] // CHECK-NEXT: call void @llvm.memset{{.*}}, !dbg [[G15R1:!.*]] __builtin_memset(f4, v, sizeof(float) * 4); +// CHECK: ret{{.*}}, !dbg [[RET:!.*]] } // CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2) @@ -86,3 +87,4 @@ void fun() { // CHECK: [[G15R3]] = !DILocation({{.*}}, atomGroup: 15, atomRank: 3) // CHECK: [[G15R2]] = !DILocation({{.*}}, atomGroup: 15, atomRank: 2) // CHECK: [[G15R1]] = !DILocation({{.*}}, atomGroup: 15, atomRank: 1) +// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 16, atomRank: 1) diff --git a/clang/test/DebugInfo/KeyInstructions/cast.c b/clang/test/DebugInfo/KeyInstructions/cast.c index 927a1f2a704c7..62f2c3d1d3e51 100644 --- a/clang/test/DebugInfo/KeyInstructions/cast.c +++ b/clang/test/DebugInfo/KeyInstructions/cast.c @@ -13,8 +13,10 @@ void a() { // CHECK: %conv = fptosi float %0 to i32{{.*}}, !dbg [[G1R2:!.*]] // CHECK: store i32 %conv, ptr %a{{.*}}, !dbg [[G1R1:!.*]] int a = g; +// CHECK: ret{{.*}}, !dbg [[RET:!.*]] } // CHECK: [[G1R3]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 3) // CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2) // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1) +// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1) diff --git a/clang/test/DebugInfo/KeyInstructions/coerced-packed.c b/clang/test/DebugInfo/KeyInstructions/coerced-packed.c index 90ec8420b0d8c..1bd2760149705 100644 --- a/clang/test/DebugInfo/KeyInstructions/coerced-packed.c +++ b/clang/test/DebugInfo/KeyInstructions/coerced-packed.c @@ -14,7 +14,9 @@ void f() { // CHECK: [[call:%.*]] = call i40{{.*}}getS{{.*}}, !dbg [[G1R2:!.*]] // CHECK: store i40 [[call]], ptr %s, align 1, !dbg [[G1R1:!.*]] S s = getS(); +// CHECK: ret{{.*}}, !dbg [[RET:!.*]] } // CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2) // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1) +// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1) diff --git a/clang/test/DebugInfo/KeyInstructions/coerced-ptr.c b/clang/test/DebugInfo/KeyInstructions/coerced-ptr.c index 0002e9051220b..1205b312e43c4 100644 --- a/clang/test/DebugInfo/KeyInstructions/coerced-ptr.c +++ b/clang/test/DebugInfo/KeyInstructions/coerced-ptr.c @@ -12,8 +12,10 @@ void f() { // CHECK: [[i2p:%.*]] = inttoptr i64 %call to ptr, !dbg [[G1R2:!.*]] // CHECK: store ptr [[i2p]], ptr [[gep]], align 8, !dbg [[G1R1:!.*]] Ptr p = getPtr(); +// CHECK: ret{{.*}}, !dbg [[RET:!.*]] } // CHECK: [[G1R3]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 3) // CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2) // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1) +// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1) diff --git a/clang/test/DebugInfo/KeyInstructions/coerced-through-memory.c b/clang/test/DebugInfo/KeyInstructions/coerced-through-memory.c index 98361aa9806ef..f8667b73b111b 100644 --- a/clang/test/DebugInfo/KeyInstructions/coerced-through-memory.c +++ b/clang/test/DebugInfo/KeyInstructions/coerced-through-memory.c @@ -18,7 +18,9 @@ void f() { // CHECK: store [2 x i64] %call, ptr %tmp.coerce, align 8 // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %s, ptr align 8 %tmp.coerce, i64 12, i1 false), !dbg [[G1R1:!.*]] S s = getS(); +// CHECK: ret{{.*}}, !dbg [[RET:!.*]] } // CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2) // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1) +// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1) diff --git a/clang/test/DebugInfo/KeyInstructions/coerced.c b/clang/test/DebugInfo/KeyInstructions/coerced.c index b5a254fb641c9..036f6d66fa670 100644 --- a/clang/test/DebugInfo/KeyInstructions/coerced.c +++ b/clang/test/DebugInfo/KeyInstructions/coerced.c @@ -16,6 +16,7 @@ void test() { // CHECK: %3 = extractvalue { ptr, ptr } %call, 1, !dbg [[G1R2]] // CHECK: store ptr %3, ptr {{.*}}, !dbg [[G1R1:!.*]] Struct s = get(); +// CHECK: ret{{.*}}, !dbg [[RET:!.*]] } typedef struct { int i; } Int; @@ -27,10 +28,13 @@ void test2() { // CHECK: %call = call i32 @{{(_Z6)?}}getInt{{v?}}(), !dbg [[T2_G1R2:!.*]] // CHECK: [[gep:%.*]] = getelementptr inbounds nuw %struct.Int, ptr %i, i32 0, i32 0 // CHECK: store i32 %call, ptr [[gep]]{{.*}}, !dbg [[T2_G1R1:!.*]] +// CHECK: ret{{.*}}, !dbg [[T2_RET:!.*]] Int i = getInt(); } // CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2) // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1) +// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1) // CHECK: [[T2_G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2) // CHECK: [[T2_G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1) +// CHECK: [[T2_RET]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1) diff --git a/clang/test/DebugInfo/KeyInstructions/complex.c b/clang/test/DebugInfo/KeyInstructions/complex.c index 9647d0e4009ee..d5cb67fed99d6 100644 --- a/clang/test/DebugInfo/KeyInstructions/complex.c +++ b/clang/test/DebugInfo/KeyInstructions/complex.c @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -triple x86_64-linux-gnu -gkey-instructions -x c++ %s -debug-info-kind=line-tables-only -emit-llvm -o - \ -// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank +// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank --check-prefixes=CHECK,CHECK-CXX // RUN: %clang_cc1 -triple x86_64-linux-gnu -gkey-instructions -x c %s -debug-info-kind=line-tables-only -emit-llvm -o - \ // RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank --check-prefixes=CHECK,CHECK-C @@ -71,6 +71,7 @@ void test() { // CHECK-C: store float %mul.rl, ptr @f, align 4, !dbg [[G11R1:!.*]] f *= ci; #endif +// CHECK: ret{{.*}}, !dbg [[RET:!.*]] } // CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2) @@ -95,3 +96,5 @@ void test() { // CHECK-C: [[G10R1]] = !DILocation({{.*}}, atomGroup: 10, atomRank: 1) // CHECK-C: [[G11R2]] = !DILocation({{.*}}, atomGroup: 11, atomRank: 2) // CHECK-C: [[G11R1]] = !DILocation({{.*}}, atomGroup: 11, atomRank: 1) +// CHECK-C: [[RET]] = !DILocation({{.*}}, atomGroup: 12, atomRank: 1) +// CHECK-CXX: [[RET]] = !DILocation({{.*}}, atomGroup: 8, atomRank: 1) diff --git a/clang/test/DebugInfo/KeyInstructions/do.c b/clang/test/DebugInfo/KeyInstructions/do.c index 4f0d388f94047..cc3749e6e56c5 100644 --- a/clang/test/DebugInfo/KeyInstructions/do.c +++ b/clang/test/DebugInfo/KeyInstructions/do.c @@ -25,9 +25,12 @@ void a(int A) { // CHECK: %tobool = icmp ne i32 %dec, 0, !dbg [[G2R1:!.*]] // CHECK: br i1 %tobool, label %do.body, label %do.end, !dbg [[G3R1:!.*]], !llvm.loop do { } while (--A); + +// CHECK: ret{{.*}}, !dbg [[RET:!.*]] } // CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2) // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1) // CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1) // CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1) +// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1) diff --git a/clang/test/DebugInfo/KeyInstructions/for.c b/clang/test/DebugInfo/KeyInstructions/for.c index 89345db9fb85f..e7c1567c14d60 100644 --- a/clang/test/DebugInfo/KeyInstructions/for.c +++ b/clang/test/DebugInfo/KeyInstructions/for.c @@ -27,6 +27,7 @@ void a(int A) { // CHECK: store i32 %inc, ptr %i{{.*}}, !dbg [[G4R1:!.*]] for (int i = 0; i < A; ++i) { } +// CHECK: ret{{.*}}, !dbg [[RET:!.*]] } void b(int A) { @@ -55,6 +56,7 @@ void b(int A) { if (A > 1) ; } +// CHECK: ret{{.*}}, !dbg [[bRET:!.*]] } void c(int A) { @@ -111,6 +113,7 @@ void e() { // CHECK-NEXT: br label %for.inc, !dbg [[eG4R1:!.*]] for (; i < 3; ee()) x = i; +// CHECK: ret{{.*}}, !dbg [[eRET:!.*]] } @@ -138,6 +141,7 @@ void g() { { break; } +// CHECK: ret{{.*}}, !dbg [[gRET:!.*]] } // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1) @@ -146,30 +150,34 @@ void g() { // CHECK: [[G5R1]] = !DILocation(line: 29,{{.*}} atomGroup: 5, atomRank: 1) // CHECK: [[G4R2]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 2) // CHECK: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1) +// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 6, atomRank: 1) // CHECK: [[bG1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1) // CHECK: [[bG2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1) // CHECK: [[bG3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1) // CHECK: [[bG4R2]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 2) // CHECK: [[bG4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1) -// CHECK: [[bG6R1]] = !DILocation(line: 57,{{.*}} atomGroup: 6, atomRank: 1) +// CHECK: [[bG6R1]] = !DILocation(line: 58,{{.*}} atomGroup: 6, atomRank: 1) // CHECK: [[bG5R2]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 2) // CHECK: [[bG5R1]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 1) +// CHECK: [[bRET]] = !DILocation({{.*}}, atomGroup: 7, atomRank: 1) // CHECK: [[cG1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2) // CHECK: [[cG1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1) -// CHECK: [[cG3R1]] = !DILocation(line: 81,{{.*}} atomGroup: 3, atomRank: 1) +// CHECK: [[cG3R1]] = !DILocation(line: 83,{{.*}} atomGroup: 3, atomRank: 1) // CHECK: [[cG2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2) // CHECK: [[cG2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1) -// CHECK: [[dG1R1]] = !DILocation(line: 91, column: 3, scope: ![[#]], atomGroup: 1, atomRank: 1) +// CHECK: [[dG1R1]] = !DILocation(line: 93, column: 3, scope: ![[#]], atomGroup: 1, atomRank: 1) // CHECK: [[eG1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1) // CHECK: [[eG2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1) // CHECK: [[eG3R2]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 2) // CHECK: [[eG3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1) -// CHECK: [[eG4R1]] = !DILocation(line: 113, column: 5, scope: ![[#]], atomGroup: 4, atomRank: 1) +// CHECK: [[eG4R1]] = !DILocation(line: 115, column: 5, scope: ![[#]], atomGroup: 4, atomRank: 1) +// CHECK: [[eRET]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 1) -// CHECK: [[fG1R1]] = !DILocation(line: 126, column: 5, scope: ![[#]], atomGroup: 1, atomRank: 1) +// CHECK: [[fG1R1]] = !DILocation(line: 129, column: 5, scope: ![[#]], atomGroup: 1, atomRank: 1) -// CHECK: [[gG1R1]] = !DILocation(line: 139, column: 5, scope: ![[#]], atomGroup: 1, atomRank: 1) +// CHECK: [[gG1R1]] = !DILocation(line: 142, column: 5, scope: ![[#]], atomGroup: 1, atomRank: 1) +// CHECK: [[gRET]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1) diff --git a/clang/test/DebugInfo/KeyInstructions/if.c b/clang/test/DebugInfo/KeyInstructions/if.c index b16dec7b91c4f..edadd04cf0e18 100644 --- a/clang/test/DebugInfo/KeyInstructions/if.c +++ b/clang/test/DebugInfo/KeyInstructions/if.c @@ -2,7 +2,7 @@ // RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank --check-prefixes=CHECK,CHECK-CXX // RUN: %clang_cc1 -triple x86_64-linux-gnu -gkey-instructions -x c %s -debug-info-kind=line-tables-only -emit-llvm -o - \ -// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank +// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank --check-prefixes=CHECK,CHECK-C int g; void a(int A) { @@ -32,6 +32,8 @@ void a(int A) { if (int B = A; B) ; #endif + +// CHECK: ret{{.*}}, !dbg [[RET:!.*]] } // CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2) @@ -44,3 +46,5 @@ void a(int A) { // CHECK-CXX: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1) // CHECK-CXX: [[G5R2]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 2) // CHECK-CXX: [[G5R1]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 1) +// CHECK-CXX: [[RET]] = !DILocation({{.*}}, atomGroup: 6, atomRank: 1) +// CHECK-C: [[RET]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1) diff --git a/clang/test/DebugInfo/KeyInstructions/init-agg.c b/clang/test/DebugInfo/KeyInstructions/init-agg.c index 1021490bd75b4..711d8ad3de57f 100644 --- a/clang/test/DebugInfo/KeyInstructions/init-agg.c +++ b/clang/test/DebugInfo/KeyInstructions/init-agg.c @@ -37,6 +37,8 @@ void a() { // CHECK: store i8 {{.*}}, ptr %uninit{{.*}}, !dbg [[G5R1:!.*]], !annotation char uninit; // -ftrivial-auto-var-init=pattern + +// CHECK: ret{{.*}}, !dbg [[RET:!.*]] } // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1) @@ -47,3 +49,4 @@ void a() { // CHECK: [[big_LINE]] = !DILocation(line: 33, scope: ![[#]]) // CHECK: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1) // CHECK: [[G5R1]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 1) +// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 6, atomRank: 1) diff --git a/clang/test/DebugInfo/KeyInstructions/init-member.cpp b/clang/test/DebugInfo/KeyInstructions/init-member.cpp index 4d8e1b9dace3f..0c45c07886d4f 100644 --- a/clang/test/DebugInfo/KeyInstructions/init-member.cpp +++ b/clang/test/DebugInfo/KeyInstructions/init-member.cpp @@ -17,6 +17,8 @@ void fun() { // CHECK: store i32 1, ptr %x{{.*}}, !dbg [[G1R1:!.*]] // CHECK: store float 5.000000e+00, ptr %y{{.*}}, !dbg [[G2R1:!.*]] +// CHECK: ret{{.*}}, !dbg [[RET:!.*]] // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1) // CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1) +// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1) diff --git a/clang/test/DebugInfo/KeyInstructions/init-scalar.c b/clang/test/DebugInfo/KeyInstructions/init-scalar.c index d4802a709b89a..217a2496c6751 100644 --- a/clang/test/DebugInfo/KeyInstructions/init-scalar.c +++ b/clang/test/DebugInfo/KeyInstructions/init-scalar.c @@ -10,8 +10,10 @@ void a() { // CHECK: %add = add {{.*}}, !dbg [[G2R2:!.*]] // CHECK: store i32 %add, ptr %B, align 4, !dbg [[G2R1:!.*]] int B = 2 * A + 1; +// CHECK: ret{{.*}}, !dbg [[RET:!.*]] } // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1) // CHECK: [[G2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2) // CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1) +// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1) diff --git a/clang/test/DebugInfo/KeyInstructions/init-static.cpp b/clang/test/DebugInfo/KeyInstructions/init-static.cpp index 2cac57e1d9fff..ee73275edb761 100644 --- a/clang/test/DebugInfo/KeyInstructions/init-static.cpp +++ b/clang/test/DebugInfo/KeyInstructions/init-static.cpp @@ -4,10 +4,12 @@ // CHECK: [[b_addr:@.*]] = {{.*}}global ptr void g(int *a) { - // CHECK: [[v:%.*]] = load ptr, ptr %a.addr{{.*}}, !dbg [[G1R2:!.*]] - // CHECK: store ptr [[v]], ptr [[b_addr]]{{.*}}, !dbg [[G1R1:!.*]] +// CHECK: [[v:%.*]] = load ptr, ptr %a.addr{{.*}}, !dbg [[G1R2:!.*]] +// CHECK: store ptr [[v]], ptr [[b_addr]]{{.*}}, !dbg [[G1R1:!.*]] static int &b = *a; +// CHECK: ret{{.*}}, !dbg [[RET:!.*]] } // CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2) // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1) +// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1) diff --git a/clang/test/DebugInfo/KeyInstructions/multi-func.c b/clang/test/DebugInfo/KeyInstructions/multi-func.c index 6e225eed81de8..ce311bad00d16 100644 --- a/clang/test/DebugInfo/KeyInstructions/multi-func.c +++ b/clang/test/DebugInfo/KeyInstructions/multi-func.c @@ -8,12 +8,17 @@ int g; // CHECK: store{{.*}}, !dbg [[AG:!.*]] +// CHECK: ret{{.*}}, !dbg [[ARET:!.*]] void a() { g = 0; } // CHECK: store{{.*}}, !dbg [[BG:!.*]] +// CHECK: ret{{.*}}, !dbg [[BRET:!.*]] void b() { g = 0; } // CHECK: [[A:!.*]] = distinct !DISubprogram(name: "a", -// CHECK: [[AG]] = !DILocation(line: 11, scope: [[A]], atomGroup: 1, atomRank: 1) +// CHECK: [[AG]] = !DILocation(line: 12, scope: [[A]], atomGroup: 1, atomRank: 1) +// CHECK: [[ARET]] = !DILocation(line: 12, scope: [[A]], atomGroup: 2, atomRank: 1) + // CHECK: [[B:!.*]] = distinct !DISubprogram(name: "b", -// CHECK: [[BG]] = !DILocation(line: 14, scope: [[B]], atomGroup: 1, atomRank: 1) +// CHECK: [[BG]] = !DILocation(line: 16, scope: [[B]], atomGroup: 1, atomRank: 1) +// CHECK: [[BRET]] = !DILocation(line: 16, scope: [[B]], atomGroup: 2, atomRank: 1) diff --git a/clang/test/DebugInfo/KeyInstructions/new.cpp b/clang/test/DebugInfo/KeyInstructions/new.cpp index 5ac2cf31d1380..f939e784a4575 100644 --- a/clang/test/DebugInfo/KeyInstructions/new.cpp +++ b/clang/test/DebugInfo/KeyInstructions/new.cpp @@ -18,6 +18,7 @@ void f(int x) { // CHECK: %3 = load ptr, ptr %n // CHECK: store i32 %2, ptr %3{{.*}}, !dbg [[G3R1:!.*]] *n = x; +// CHECK: ret{{.*}}, !dbg [[RET:!.*]] } // CHECK: [[G1R2_C12]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2) @@ -32,3 +33,5 @@ void f(int x) { // CHECK: [[G3R2]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 2) // CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1) + +// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1) diff --git a/clang/test/DebugInfo/KeyInstructions/return-va-arg.c b/clang/test/DebugInfo/KeyInstructions/return-va-arg.c new file mode 100644 index 0000000000000..0773bf5353177 --- /dev/null +++ b/clang/test/DebugInfo/KeyInstructions/return-va-arg.c @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -triple x86_64-linux-gnu -gkey-instructions -gno-column-info -x c++ %s -debug-info-kind=line-tables-only -emit-llvm -o - \ +// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank + +// RUN: %clang_cc1 -triple x86_64-linux-gnu -gkey-instructions -gno-column-info -x c %s -debug-info-kind=line-tables-only -emit-llvm -o - \ +// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank + +typedef struct { + struct{} a; + double b; +} s1; + +s1 f(int z, ...) { + __builtin_va_list list; + __builtin_va_start(list, z); +// CHECK: vaarg.end: +// CHECK-NEXT: %vaarg.addr = phi ptr +// CHECK-NEXT: call void @llvm.memcpy{{.*}}, !dbg [[G1R1:!.*]] +// CHECK-NEXT: {{.*}} = getelementptr{{.*}} +// CHECK-NEXT: [[LOAD:%.*]] = load double{{.*}}, !dbg [[G1R2:!.*]] +// CHECK-NEXT: ret double [[LOAD]], !dbg [[G1R1]] + return __builtin_va_arg(list, s1); +} + +// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1) +// CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2) diff --git a/clang/test/DebugInfo/KeyInstructions/return.c b/clang/test/DebugInfo/KeyInstructions/return.c new file mode 100644 index 0000000000000..c79e9d930f317 --- /dev/null +++ b/clang/test/DebugInfo/KeyInstructions/return.c @@ -0,0 +1,101 @@ +// RUN: %clang_cc1 -triple x86_64-linux-gnu -gkey-instructions -gno-column-info -x c++ %s -debug-info-kind=line-tables-only -emit-llvm -o - \ +// RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-CXX + +// RUN: %clang_cc1 -triple x86_64-linux-gnu -gkey-instructions -gno-column-info -x c %s -debug-info-kind=line-tables-only -emit-llvm -o - \ +// RUN: | FileCheck %s + +// Check the stores to `retval` allocas and branches to `return` block are 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). + +// Also check that 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. + +#ifdef __cplusplus +#define nomangle extern "C" +#else +#define nomangle +#endif + +int g; +nomangle float a() { +// CHECK: float @a() + if (g) +// CHECK: if.then: +// CHECK-NEXT: %1 = load i32, ptr @g{{.*}}, !dbg [[G2R3:!.*]] +// CHECK-NEXT: %conv = sitofp i32 %1 to float{{.*}}, !dbg [[G2R2:!.*]] +// CHECK-NEXT: store float %conv, ptr %retval{{.*}}, !dbg [[G2R1:!.*]] +// CHECK-NEXT: br label %return{{.*}}, !dbg [[G2R1]] + return g; +// CHECK: if.end: +// CHECK-NEXT: store float 1.000000e+00, ptr %retval{{.*}}, !dbg [[G3R1:!.*]] +// CHECK-NEXT: br label %return, !dbg [[G3R1]] + +// CHECK: return: +// CHECK-NEXT: %2 = load float, ptr %retval{{.*}}, !dbg [[G4R2:!.*]] +// CHECK-NEXT: ret float %2{{.*}}, !dbg [[G4R1:!.*]] + return 1; +} + +// CHECK: void @b() +// CHECK: ret void{{.*}}, !dbg [[B_G1R1:!.*]] +nomangle void b() { return; } + +// CHECK: i32 @c() +// CHECK: %add = add{{.*}}, !dbg [[C_G1R2:!.*]] +// CHECK: ret i32 %add{{.*}}, !dbg [[C_G1R1:!.*]] +nomangle int c() { return g + 1; } + +// NOTE: (return) (g = 1) are two separate atoms. +// CHECK: i32 @d() +// CHECK: store{{.*}}, !dbg [[D_G2R1:!.*]] +// CHECK: ret i32 1{{.*}}, !dbg [[D_G1R1:!.*]] +nomangle int d() { return g = 1; } + +// The implicit return here get the line number of the closing brace; make it +// key to match existing behaviour. +// CHECK: void @e() +// CHECK: ret void, !dbg [[E_G1R1:!.*]] +nomangle void e() {} + +#ifdef __cplusplus +// CHECK-CXX: ptr @_Z1fRi +int &f(int &r) { +// Include ctrl-flow to stop ret value store being elided. + if (r) +// CHECK-CXX: if.then: +// CHECK-CXX-NEXT: %2 = load ptr, ptr %r.addr{{.*}}, !dbg [[F_G2R2:!.*]], !nonnull +// CHECK-CXX-NEXT: store ptr %2, ptr %retval{{.*}}, !dbg [[F_G2R1:!.*]] +// CHECK-CXX-NEXT: br label %return, !dbg [[F_G2R1:!.*]] + return r; + +// CHECK-CXX: if.end: +// CHECK-CXX-NEXT: store ptr @g, ptr %retval{{.*}}, !dbg [[F_G3R1:!.*]] +// CHECK-CXX-NEXT: br label %return, !dbg [[F_G3R1:!.*]] +// CHECK-CXX: return: +// CHECK-CXX-NEXT: %3 = load ptr, ptr %retval{{.*}}, !dbg [[F_G4R2:!.*]] +// CHECK-CXX-NEXT: ret ptr %3, !dbg [[F_G4R1:!.*]] + return g; +} +#endif + +// CHECK: [[G2R3]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 3) +// CHECK: [[G2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2) +// CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1) +// CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1) +// CHECK: [[G4R2]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 2) +// CHECK: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1) +// CHECK: [[B_G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1) +// CHECK: [[C_G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2) +// CHECK: [[C_G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1) +// CHECK: [[D_G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1) +// CHECK: [[D_G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1) +// CHECK: [[E_G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1) +// CHECK-CXX: [[F_G2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2) +// CHECK-CXX: [[F_G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1) +// CHECK-CXX: [[F_G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1) +// CHECK-CXX: [[F_G4R2]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 2) +// CHECK-CXX: [[F_G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1) diff --git a/clang/test/DebugInfo/KeyInstructions/switch.c b/clang/test/DebugInfo/KeyInstructions/switch.c index 96b18592621d5..cd8fced67eed9 100644 --- a/clang/test/DebugInfo/KeyInstructions/switch.c +++ b/clang/test/DebugInfo/KeyInstructions/switch.c @@ -2,7 +2,7 @@ // RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank --check-prefixes=CHECK,CHECK-CXX // RUN: %clang_cc1 -triple x86_64-linux-gnu -gkey-instructions -x c %s -debug-info-kind=line-tables-only -emit-llvm -o - \ -// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank +// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank --check-prefixes=CHECK,CHECK-C int g; void a(int A, int B) { @@ -40,6 +40,7 @@ void a(int A, int B) { } }; } +// CHECK: ret{{.*}}, !dbg [[RET:!.*]] } // CHECK: [[G2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2) @@ -49,3 +50,5 @@ void a(int A, int B) { // CHECK: [[G4R2]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 2) // CHECK: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1) // CHECK-CXX: [[G5R1]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 1) +// CHECK-CXX: [[RET]] = !DILocation({{.*}}, atomGroup: 6, atomRank: 1) +// CHECK-C: [[RET]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 1) diff --git a/clang/test/DebugInfo/KeyInstructions/try-catch.cpp b/clang/test/DebugInfo/KeyInstructions/try-catch.cpp index 918eb4c97db9a..c1887bc525187 100644 --- a/clang/test/DebugInfo/KeyInstructions/try-catch.cpp +++ b/clang/test/DebugInfo/KeyInstructions/try-catch.cpp @@ -14,7 +14,10 @@ void attempt() { // CHECK: store i32 %5, ptr %e{{.*}}, !dbg [[G1R1:!.*]] // CHECK: call void @__cxa_end_catch() catch (int e) { } + +// CHECK: ret{{.*}}, !dbg [[RET:!.*]] } // CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2) // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1) +// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1) diff --git a/clang/test/DebugInfo/KeyInstructions/while.c b/clang/test/DebugInfo/KeyInstructions/while.c index 38cdb8433dd27..9c9eab399f345 100644 --- a/clang/test/DebugInfo/KeyInstructions/while.c +++ b/clang/test/DebugInfo/KeyInstructions/while.c @@ -26,9 +26,12 @@ void a(int A) { // CHECK: %tobool = icmp ne i32 %dec, 0, !dbg [[G2R1:!.*]] // CHECK: br i1 %tobool, label %while.body, label %while.end, !dbg [[G3R1:!.*]] while (--A) { }; + +// CHECK: ret{{.*}}, !dbg [[RET:!.*]] } // CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2) // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1) // CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1) // CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1) +// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1)