[clang] [llvm] [profcheck][coro] Adding Branch weights PGO in Coroutines Passes (PR #184466)
Jin Huang via cfe-commits
cfe-commits at lists.llvm.org
Sun Jul 12 23:40:26 PDT 2026
https://github.com/jinhuang1102 updated https://github.com/llvm/llvm-project/pull/184466
>From e873648fe0e3aeadea23217befb7dadbbaa59a2a Mon Sep 17 00:00:00 2001
From: Jin Huang <jingold at google.com>
Date: Wed, 4 Mar 2026 00:19:01 +0000
Subject: [PATCH] [profcheck][coro] Adding Branch weights PGO in CoroSplit and
CoroFrame Passes
---
.../coro-destructor-of-final_suspend.cpp | 2 +-
.../llvm/Transforms/Coroutines/CoroShape.h | 16 +
.../lib/Transforms/Coroutines/CoroCleanup.cpp | 5 +
llvm/lib/Transforms/Coroutines/CoroFrame.cpp | 20 ++
llvm/lib/Transforms/Coroutines/CoroSplit.cpp | 109 ++++++-
.../coro-await-suspend-lower-invoke.ll | 31 +-
.../Transforms/Coroutines/coro-byval-param.ll | 30 +-
.../Coroutines/coro-catchswitch-cleanuppad.ll | 7 +-
.../Transforms/Coroutines/coro-noop-pacbti.ll | 24 +-
llvm/test/Transforms/Coroutines/coro-noop.ll | 35 ++-
.../Coroutines/coro-split-dbg-labels.ll | 296 ++++++++++++++++--
11 files changed, 518 insertions(+), 57 deletions(-)
diff --git a/clang/test/CodeGenCoroutines/coro-destructor-of-final_suspend.cpp b/clang/test/CodeGenCoroutines/coro-destructor-of-final_suspend.cpp
index bbc16a196d305..087085ba69c3b 100644
--- a/clang/test/CodeGenCoroutines/coro-destructor-of-final_suspend.cpp
+++ b/clang/test/CodeGenCoroutines/coro-destructor-of-final_suspend.cpp
@@ -61,7 +61,7 @@ gen maybe_throwing(bool x) {
// CHECK: define{{.*}}@_Z14maybe_throwingb.destroy
// CHECK: %[[INDEX:.+]] = load i1, ptr %index.addr, align 1
-// CHECK: br i1 %[[INDEX]], label %[[AFTERSUSPEND:.+]], label %[[CORO_FREE:.+]]
+// CHECK: br i1 %[[INDEX]], label %[[AFTERSUSPEND:.+]], label %[[CORO_FREE:.+]], !prof
// CHECK: [[AFTERSUSPEND]]:
// CHECK: call{{.*}}_ZN3gen12promise_type13final_awaiterD1Ev(
// CHECK: [[CORO_FREE]]:
diff --git a/llvm/include/llvm/Transforms/Coroutines/CoroShape.h b/llvm/include/llvm/Transforms/Coroutines/CoroShape.h
index 28931e3260e68..88c44e1e1a361 100644
--- a/llvm/include/llvm/Transforms/Coroutines/CoroShape.h
+++ b/llvm/include/llvm/Transforms/Coroutines/CoroShape.h
@@ -12,6 +12,7 @@
#ifndef LLVM_TRANSFORMS_COROUTINES_COROSHAPE_H
#define LLVM_TRANSFORMS_COROUTINES_COROSHAPE_H
+#include "llvm/ADT/DenseMap.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Support/Compiler.h"
@@ -57,6 +58,11 @@ struct Shape {
SmallVector<CoroSizeInst *, 2> CoroSizes;
SmallVector<CoroAlignInst *, 2> CoroAligns;
SmallVector<AnyCoroSuspendInst *, 4> CoroSuspends;
+ // Map from suspend instructions to their execution frequency, used for branch
+ // weights in the resume function.
+ SmallDenseMap<AnyCoroSuspendInst *, uint64_t, 4> SuspendFreqs;
+ // Estimated profile execution count for the resume function if available.
+ std::optional<uint64_t> ResumeEntryCount;
SmallVector<CoroAwaitSuspendInst *, 4> CoroAwaitSuspends;
SmallVector<CallInst *, 2> SymmetricTransfers;
@@ -70,6 +76,8 @@ struct Shape {
CoroSizes.clear();
CoroAligns.clear();
CoroSuspends.clear();
+ SuspendFreqs.clear();
+ ResumeEntryCount = std::nullopt;
CoroAwaitSuspends.clear();
SymmetricTransfers.clear();
@@ -77,6 +85,7 @@ struct Shape {
FramePtr = nullptr;
AllocaSpillBlock = nullptr;
+ SwitchSuspendProfileWeights.clear();
}
// Scan the function and collect the above intrinsics for later processing
@@ -101,6 +110,13 @@ struct Shape {
Value *FramePtr = nullptr;
BasicBlock *AllocaSpillBlock = nullptr;
+ struct SwitchSuspendWeights {
+ uint32_t Resume = 0;
+ uint32_t Destroy = 0;
+ bool HasProfile = false;
+ };
+ SmallVector<SwitchSuspendWeights, 4> SwitchSuspendProfileWeights;
+
struct SwitchLoweringStorage {
SwitchInst *ResumeSwitch;
AllocaInst *PromiseAlloca;
diff --git a/llvm/lib/Transforms/Coroutines/CoroCleanup.cpp b/llvm/lib/Transforms/Coroutines/CoroCleanup.cpp
index fc8a6277893a3..20de75d0ade60 100644
--- a/llvm/lib/Transforms/Coroutines/CoroCleanup.cpp
+++ b/llvm/lib/Transforms/Coroutines/CoroCleanup.cpp
@@ -15,6 +15,7 @@
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
+#include "llvm/IR/ProfDataUtils.h"
#include "llvm/Transforms/Scalar/SimplifyCFG.h"
#include "llvm/Transforms/Utils/Local.h"
@@ -185,6 +186,10 @@ void Lowerer::lowerCoroNoop(IntrinsicInst *II) {
FnTy, GlobalValue::LinkageTypes::InternalLinkage,
M.getDataLayout().getProgramAddressSpace(), "__NoopCoro_ResumeDestroy",
&M);
+
+ // Mark this synthetic function's entry count as explicitly unknown.
+ setExplicitlyUnknownFunctionEntryCount(*NoopFn, DEBUG_TYPE);
+
buildDebugInfoForNoopResumeDestroyFunc(NoopFn);
auto *Entry = BasicBlock::Create(C, "entry", NoopFn);
ReturnInst::Create(C, Entry);
diff --git a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
index 3e3960ea24e88..b2722c46fea64 100644
--- a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
+++ b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
@@ -25,8 +25,10 @@
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/ProfDataUtils.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/OptimizedStructLayout.h"
@@ -43,6 +45,10 @@
using namespace llvm;
+namespace llvm {
+extern cl::opt<bool> ProfcheckDisableMetadataFixes;
+}
+
#define DEBUG_TYPE "coro-frame"
namespace {
@@ -1364,6 +1370,20 @@ static void rewritePHIsForCleanupPad(BasicBlock *CleanupPadBB,
SwitchOnDispatch->addCase(SwitchConstant, CaseBB);
SwitchIndex++;
}
+
+ if (!ProfcheckDisableMetadataFixes) {
+ // Add branch weights to SwitchOnDispatch, where branches are unreachable by
+ // default. We mark all branches as having equal weights because they are
+ // mutually exclusive.
+ MDBuilder MDB(CleanupPadBB->getContext());
+ SmallVector<uint32_t> Weights;
+ Weights.push_back(0);
+ for (int i = 0; i < SwitchIndex; ++i) {
+ Weights.push_back(llvm::MDBuilder::kUnlikelyBranchWeight);
+ }
+ SwitchOnDispatch->setMetadata(LLVMContext::MD_prof,
+ MDB.createBranchWeights(Weights));
+ }
}
static void cleanupSinglePredPHIs(Function &F) {
diff --git a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp
index 7915fbf4cce05..7a21856b46b52 100644
--- a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp
+++ b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp
@@ -29,6 +29,7 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/Analysis/BlockFrequencyInfo.h"
#include "llvm/Analysis/CFG.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Analysis/ConstantFolding.h"
@@ -55,7 +56,9 @@
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/ProfDataUtils.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Value.h"
#include "llvm/IR/Verifier.h"
@@ -69,11 +72,13 @@
#include "llvm/Transforms/Utils/CallGraphUpdater.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/Local.h"
+#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <initializer_list>
#include <iterator>
+#include <limits>
using namespace llvm;
@@ -411,7 +416,11 @@ void coro::BaseCloner::handleFinalSuspend() {
auto *Switch = cast<SwitchInst>(VMap[Shape.SwitchLowering.ResumeSwitch]);
auto FinalCaseIt = std::prev(Switch->case_end());
BasicBlock *ResumeBB = FinalCaseIt->getCaseSuccessor();
- Switch->removeCase(FinalCaseIt);
+
+ // Use SwitchInstProfUpdateWrapper to remove the case, keeping the profile
+ // branch weights in sync with the switch successors.
+ SwitchInstProfUpdateWrapper SwitchWrapper(*Switch);
+ SwitchWrapper.removeCase(FinalCaseIt);
if (isSwitchDestroyFunction()) {
BasicBlock *OldSwitchBB = Switch->getParent();
auto *NewSwitchBB = OldSwitchBB->splitBasicBlock(Switch, "Switch");
@@ -426,7 +435,11 @@ void coro::BaseCloner::handleFinalSuspend() {
auto *Load =
Builder.CreateLoad(Shape.getSwitchResumePointerType(), NewFramePtr);
auto *Cond = Builder.CreateIsNull(Load);
- Builder.CreateCondBr(Cond, ResumeBB, NewSwitchBB);
+ auto *Br = Builder.CreateCondBr(Cond, ResumeBB, NewSwitchBB);
+ applyProfMetadataIfEnabled(Br, [&](Instruction *Inst) {
+ setExplicitlyUnknownBranchWeightsIfProfiled(*Inst, DEBUG_TYPE,
+ Inst->getFunction());
+ });
}
OldSwitchBB->getTerminator()->eraseFromParent();
}
@@ -623,8 +636,7 @@ static void replaceSwiftErrorOps(Function &F, coro::Shape &Shape,
}
/// Returns all debug records in F.
-static SmallVector<DbgVariableRecord *>
-collectDbgVariableRecords(Function &F) {
+static SmallVector<DbgVariableRecord *> collectDbgVariableRecords(Function &F) {
SmallVector<DbgVariableRecord *> DbgVariableRecords;
for (auto &I : instructions(F)) {
for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange()))
@@ -1099,9 +1111,52 @@ void coro::SwitchCloner::create() {
// Clone the function
coro::BaseCloner::create();
+ // Override EntryCount for the cloned resume function with the true sum of
+ // all suspension points profile counts.
+ if (FKind == coro::CloneKind::SwitchResume && OrigF.hasProfileData() &&
+ Shape.ResumeEntryCount.has_value()) {
+ NewF->setEntryCount(Shape.ResumeEntryCount.value());
+ }
+
// Replacing coro.free with 'null' in cleanup to suppress deallocation code.
if (FKind == coro::CloneKind::SwitchCleanup)
elideCoroFree(NewFramePtr);
+
+ // Update branch weights of the cloned resume switch if we have profile data.
+ if (auto *ClonedSwitch = cast_if_present<SwitchInst>(
+ VMap[Shape.SwitchLowering.ResumeSwitch])) {
+ bool IsDestroy = isSwitchDestroyFunction();
+ bool HasAnyProfile = false;
+ for (auto &W : Shape.SwitchSuspendProfileWeights) {
+ if (W.HasProfile) {
+ HasAnyProfile = true;
+ break;
+ }
+ }
+
+ if (HasAnyProfile) {
+ SmallVector<uint32_t, 4> ClonedWeights;
+ // Default destination (unreachable) weight.
+ ClonedWeights.push_back(0);
+
+ for (auto &Case : ClonedSwitch->cases()) {
+ auto *Val = Case.getCaseValue();
+ uint64_t SuspendIndex = Val->getZExtValue();
+ uint32_t Weight = 0;
+ if (SuspendIndex < Shape.SwitchSuspendProfileWeights.size()) {
+ auto &W = Shape.SwitchSuspendProfileWeights[SuspendIndex];
+ if (W.HasProfile) {
+ Weight = IsDestroy ? W.Destroy : W.Resume;
+ }
+ }
+ ClonedWeights.push_back(Weight);
+ }
+
+ MDBuilder MDB(NewF->getContext());
+ ClonedSwitch->setMetadata(LLVMContext::MD_prof,
+ MDB.createBranchWeights(ClonedWeights));
+ }
+ }
}
static void updateAsyncFuncPointerContextSize(coro::Shape &Shape) {
@@ -1505,6 +1560,10 @@ struct SwitchCoroutineSplitter {
// Split all coro.suspend calls
size_t SuspendIndex = 0;
+ SmallVector<uint64_t, 8> SwitchWeights64;
+ // Default destination (unreachable) has weight 0
+ SwitchWeights64.push_back(0);
+
for (auto *AnyS : Shape.CoroSuspends) {
auto *S = cast<CoroSuspendInst>(AnyS);
ConstantInt *IndexVal = Shape.getIndex(SuspendIndex);
@@ -1557,6 +1616,14 @@ struct SwitchCoroutineSplitter {
S->getNextNode(), ResumeBB->getName() + Twine(".landing"));
Switch->addCase(IndexVal, ResumeBB);
+ // Get pre-split frequency for this suspend point
+ uint64_t Weight = 1; // Default fallback weight
+ auto It = Shape.SuspendFreqs.find(AnyS);
+ if (It != Shape.SuspendFreqs.end()) {
+ Weight = It->second;
+ }
+ SwitchWeights64.push_back(Weight);
+
cast<UncondBrInst>(SuspendBB->getTerminator())->setSuccessor(LandingBB);
auto *PN = PHINode::Create(Builder.getInt8Ty(), 2, "");
PN->insertBefore(LandingBB->begin());
@@ -1590,6 +1657,13 @@ struct SwitchCoroutineSplitter {
++SuspendIndex;
}
+ if (!Shape.SuspendFreqs.empty()) {
+ auto SwitchWeights32 = llvm::fitWeights(SwitchWeights64);
+ MDBuilder MDB(C);
+ Switch->setMetadata(LLVMContext::MD_prof,
+ MDB.createBranchWeights(SwitchWeights32));
+ }
+
Builder.SetInsertPoint(UnreachBB);
Builder.CreateUnreachable();
DBuilder.finalize();
@@ -1614,6 +1688,10 @@ struct SwitchCoroutineSplitter {
// If there is a CoroAlloc and it returns false (meaning we elide the
// allocation, use CleanupFn instead of DestroyFn).
DestroyOrCleanupFn = Builder.CreateSelect(CA, DestroyFn, CleanupFn);
+ applyProfMetadataIfEnabled(DestroyOrCleanupFn, [&](Instruction *Inst) {
+ setExplicitlyUnknownBranchWeightsIfProfiled(*Inst, DEBUG_TYPE,
+ CoroId->getFunction());
+ });
}
// Destroy function pointer
@@ -2248,6 +2326,29 @@ PreservedAnalyses CoroSplitPass::run(LazyCallGraph::SCC &C,
F.setSplittedCoroutine();
+ // Query BFI and populate SuspendFreqs right before splitting.
+ auto &BFI = FAM.getResult<BlockFrequencyAnalysis>(F);
+ for (auto *AnyS : Shape.CoroSuspends) {
+ BasicBlock *BB = AnyS->getParent();
+ uint64_t Freq = BFI.getBlockFreq(BB).getFrequency();
+ Shape.SuspendFreqs[AnyS] = Freq;
+
+ // Query BFI to get the actual estimated execution profile count of the
+ // basic block where this suspension point resides.
+ std::optional<uint64_t> Count =
+ BFI.getBlockProfileCount(BB, /*AllowSynthetic=*/true);
+ if (Count.has_value()) {
+ if (!Shape.ResumeEntryCount.has_value()) {
+ // For the first suspend point visited, initialize the total sum.
+ Shape.ResumeEntryCount = Count.value();
+ } else {
+ // Accumulate the absolute execution count of each subsequent suspend
+ // point into the total sum.
+ Shape.ResumeEntryCount.value() += Count.value();
+ }
+ }
+ }
+
std::unique_ptr<coro::BaseABI> ABI = CreateAndInitABI(F, Shape);
SmallVector<Function *, 4> Clones;
diff --git a/llvm/test/Transforms/Coroutines/coro-await-suspend-lower-invoke.ll b/llvm/test/Transforms/Coroutines/coro-await-suspend-lower-invoke.ll
index 20acaed0abe0d..c2c03542cb95d 100644
--- a/llvm/test/Transforms/Coroutines/coro-await-suspend-lower-invoke.ll
+++ b/llvm/test/Transforms/Coroutines/coro-await-suspend-lower-invoke.ll
@@ -1,10 +1,10 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 6
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --include-generated-funcs --version 6
; Tests that invoke <type> @llvm.coro.await.suspend lowers to invoke @helper
; RUN: opt < %s -passes='module(coro-early),cgscc(coro-split),simplifycfg' -S | FileCheck %s
%Awaiter = type {}
-define void @f() presplitcoroutine personality i32 0 {
+define void @f() presplitcoroutine personality i32 0 !prof !0 {
entry:
%awaiter = alloca %Awaiter
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
@@ -103,7 +103,13 @@ declare void @__cxa_end_catch()
declare noalias ptr @malloc(i32)
declare void @free(ptr)
-; CHECK-LABEL: define void @f() personality i32 0 {
+
+!0 = !{!"function_entry_count", i64 1000}
+;.
+; CHECK: @f.resumers = private constant [3 x ptr] [ptr @f.resume, ptr @f.destroy, ptr @f.cleanup]
+;.
+; CHECK-LABEL: define void @f(
+; CHECK-SAME: ) personality i32 0 !prof [[PROF0:![0-9]+]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr @f, ptr @f.resumers)
; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 24)
@@ -118,7 +124,7 @@ declare void @free(ptr)
;
;
; CHECK-LABEL: define internal void @f.resume(
-; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[HDL:%.*]]) personality i32 0 {
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[HDL:%.*]]) personality i32 0 !prof [[PROF1:![0-9]+]] {
; CHECK-NEXT: [[ENTRY_RESUME:.*]]:
; CHECK-NEXT: [[AWAITER_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 0
; CHECK-NEXT: [[INDEX_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
@@ -128,7 +134,7 @@ declare void @free(ptr)
; CHECK-NEXT: i2 1, label %[[AFTERCOROSUSPEND3:.*]]
; CHECK-NEXT: i2 -2, label %[[AFTERCOROSUSPEND7:.*]]
; CHECK-NEXT: i2 -1, label %[[CLEANUP:.*]]
-; CHECK-NEXT: ]
+; CHECK-NEXT: ], !prof [[PROF2:![0-9]+]]
; CHECK: [[COROSAVE1]]:
; CHECK-NEXT: [[INDEX_ADDR13:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
; CHECK-NEXT: store i2 1, ptr [[INDEX_ADDR13]], align 1
@@ -176,7 +182,7 @@ declare void @free(ptr)
;
;
; CHECK-LABEL: define internal void @f.destroy(
-; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[HDL:%.*]]) personality i32 0 {
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[HDL:%.*]]) personality i32 0 !prof [[PROF0]] {
; CHECK-NEXT: [[ENTRY_DESTROY:.*:]]
; CHECK-NEXT: [[AWAITER_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 0
; CHECK-NEXT: [[MEM:%.*]] = call ptr @llvm.coro.free(token poison, ptr [[HDL]])
@@ -185,9 +191,20 @@ declare void @free(ptr)
;
;
; CHECK-LABEL: define internal void @f.cleanup(
-; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[HDL:%.*]]) personality i32 0 {
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[HDL:%.*]]) personality i32 0 !prof [[PROF0]] {
; CHECK-NEXT: [[ENTRY_CLEANUP:.*:]]
; CHECK-NEXT: [[AWAITER_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 0
; CHECK-NEXT: call void @free(ptr null)
; CHECK-NEXT: ret void
;
+;.
+; CHECK: attributes #[[ATTR0:[0-9]+]] = { nounwind memory(argmem: read) }
+; CHECK: attributes #[[ATTR1:[0-9]+]] = { nounwind memory(none) }
+; CHECK: attributes #[[ATTR2:[0-9]+]] = { nounwind }
+; CHECK: attributes #[[ATTR3:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(argmem: read) }
+; CHECK: attributes #[[ATTR4:[0-9]+]] = { nomerge nounwind }
+;.
+; CHECK: [[PROF0]] = !{!"function_entry_count", i64 1000}
+; CHECK: [[PROF1]] = !{!"function_entry_count", i64 1463}
+; CHECK: [[PROF2]] = !{!"branch_weights", i32 0, i32 -2147483648, i32 715827200, i32 119304419, i32 159072407}
+;.
diff --git a/llvm/test/Transforms/Coroutines/coro-byval-param.ll b/llvm/test/Transforms/Coroutines/coro-byval-param.ll
index db1f151b59bc5..44204de99ea66 100644
--- a/llvm/test/Transforms/Coroutines/coro-byval-param.ll
+++ b/llvm/test/Transforms/Coroutines/coro-byval-param.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --version 6
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
target datalayout = "e-m:e-p:64:64-i64:64-f80:128-n8:16:32:64-S128"
@@ -10,21 +10,24 @@ target datalayout = "e-m:e-p:64:64-i64:64-f80:128-n8:16:32:64-S128"
; struct pointer, and that the alignment is taken into account.
; Function Attrs: noinline ssp uwtable mustprogress
-define ptr @foo(ptr nocapture readonly byval(%struct.A) align 8 %a1) #0 {
+;.
+; CHECK: @foo.resumers = private constant [3 x ptr] [ptr @foo.resume, ptr @foo.destroy, ptr @foo.cleanup]
+;.
+define ptr @foo(ptr nocapture readonly byval(%struct.A) align 8 %a1) #0 !prof !0 {
; CHECK-LABEL: define ptr @foo(
-; CHECK-SAME: ptr readonly byval([[STRUCT_A:%.*]]) align 8 [[A1:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-SAME: ptr readonly byval([[STRUCT_A:%.*]]) align 8 [[A1:%.*]]) #[[ATTR0:[0-9]+]] !prof [[PROF0:![0-9]+]] {
; CHECK-NEXT: [[ENTRY:.*]]:
; CHECK-NEXT: [[TMP0:%.*]] = call token @llvm.coro.id(i32 16, ptr nonnull null, ptr @foo, ptr @foo.resumers)
; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.coro.alloc(token [[TMP0]])
; CHECK-NEXT: br i1 [[TMP1]], label %[[CORO_ALLOC:.*]], label %[[CORO_INIT:.*]]
; CHECK: [[CORO_ALLOC]]:
-; CHECK-NEXT: [[CALL:%.*]] = call noalias nonnull ptr @_Znwm(i64 48) #[[ATTR11:[0-9]+]]
+; CHECK-NEXT: [[CALL:%.*]] = call noalias nonnull ptr @_Znwm(i64 48) #[[ATTR10:[0-9]+]]
; CHECK-NEXT: br label %[[CORO_INIT]]
; CHECK: [[CORO_INIT]]:
; CHECK-NEXT: [[TMP2:%.*]] = phi ptr [ [[CALL]], %[[CORO_ALLOC]] ], [ null, %[[ENTRY]] ]
; CHECK-NEXT: [[TMP3:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[TMP0]], ptr [[TMP2]])
; CHECK-NEXT: store ptr @foo.resume, ptr [[TMP3]], align 8
-; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP1]], ptr @foo.destroy, ptr @foo.cleanup
+; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP1]], ptr @foo.destroy, ptr @foo.cleanup, !prof [[PROF1:![0-9]+]]
; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[TMP3]], i64 8
; CHECK-NEXT: store ptr [[TMP4]], ptr [[DESTROY_ADDR]], align 8
; CHECK-NEXT: [[__PROMISE_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[TMP3]], i64 16
@@ -152,3 +155,20 @@ attributes #8 = { nobuiltin nounwind "frame-pointer"="all" "no-trapping-math"="t
attributes #9 = { allocsize(0) }
attributes #10 = { noduplicate }
+!0 = !{!"function_entry_count", i64 1000}
+;.
+; CHECK: attributes #[[ATTR0]] = { mustprogress noinline ssp uwtable "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+cx8,+fxsr,+mmx,+sahf,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "tune-cpu"="generic" }
+; CHECK: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(argmem: read) }
+; CHECK: attributes #[[ATTR2]] = { nounwind }
+; CHECK: attributes #[[ATTR3:[0-9]+]] = { nobuiltin nofree allocsize(0) "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+cx8,+fxsr,+mmx,+sahf,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "tune-cpu"="generic" }
+; CHECK: attributes #[[ATTR4:[0-9]+]] = { nounwind memory(none) }
+; CHECK: attributes #[[ATTR5:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
+; CHECK: attributes #[[ATTR6:[0-9]+]] = { mustprogress noinline nounwind ssp willreturn uwtable "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+cx8,+fxsr,+mmx,+sahf,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "tune-cpu"="generic" }
+; CHECK: attributes #[[ATTR7:[0-9]+]] = { nomerge nounwind }
+; CHECK: attributes #[[ATTR8:[0-9]+]] = { nobuiltin nounwind "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+cx8,+fxsr,+mmx,+sahf,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "tune-cpu"="generic" }
+; CHECK: attributes #[[ATTR9:[0-9]+]] = { nounwind memory(argmem: read) }
+; CHECK: attributes #[[ATTR10]] = { allocsize(0) }
+;.
+; CHECK: [[PROF0]] = !{!"function_entry_count", i64 1000}
+; CHECK: [[PROF1]] = !{!"unknown", !"coro-split"}
+;.
diff --git a/llvm/test/Transforms/Coroutines/coro-catchswitch-cleanuppad.ll b/llvm/test/Transforms/Coroutines/coro-catchswitch-cleanuppad.ll
index 99f9a3a5e77c8..945b364cbad70 100644
--- a/llvm/test/Transforms/Coroutines/coro-catchswitch-cleanuppad.ll
+++ b/llvm/test/Transforms/Coroutines/coro-catchswitch-cleanuppad.ll
@@ -3,7 +3,7 @@
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg<switch-range-to-icmp>,early-cse' -S | FileCheck %s
declare i32 @__CxxFrameHandler3(...)
-define ptr @f2(i1 %val) presplitcoroutine personality ptr @__CxxFrameHandler3 {
+define ptr @f2(i1 %val) presplitcoroutine personality ptr @__CxxFrameHandler3 !prof !0 {
entry:
%id = call token @llvm.coro.id(i32 0, ptr null, ptr @f2, ptr null)
%valueA = call i32 @f();
@@ -81,7 +81,7 @@ cleanup2:
; CHECK: %1 = phi i8 [ 0, %handler2 ], [ 1, %catch.dispatch.2 ]
; CHECK: %2 = cleanuppad within %h1 []
; CHECK: %3 = icmp eq i8 %1, 0
-; CHECK: br i1 %3, label %cleanup2.from.handler2, label %cleanup2.from.catch.dispatch.2
+; CHECK: br i1 %3, label %cleanup2.from.handler2, label %cleanup2.from.catch.dispatch.2, !prof [[PROF1:![0-9]+]]
; CHECK: cleanup2.from.handler2:
; CHECK: %valueB.reload = load i32, ptr %valueB.spill.addr, align 4
@@ -113,3 +113,6 @@ declare void @print(i32)
declare void @free(ptr)
declare i32 @f()
+
+!0 = !{!"function_entry_count", i64 1000}
+; CHECK: [[PROF1]] = !{!"branch_weights", i32 1, i32 1}
diff --git a/llvm/test/Transforms/Coroutines/coro-noop-pacbti.ll b/llvm/test/Transforms/Coroutines/coro-noop-pacbti.ll
index 6fb8312f97bdf..8d5899e4d3061 100644
--- a/llvm/test/Transforms/Coroutines/coro-noop-pacbti.ll
+++ b/llvm/test/Transforms/Coroutines/coro-noop-pacbti.ll
@@ -1,14 +1,17 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --version 6
-; RUN: opt < %s -S -passes=coro-cleanup | FileCheck %s
+; RUN: opt < %s -S -passes=coro-early | FileCheck %s
-; CHECK: define internal void @__NoopCoro_ResumeDestroy(ptr %0) #1 {
-; CHECK-NEXT: entry:
-; CHECK-NEXT: ret void
-; CHECK-NEXT: }
; CHECK: attributes #1 = { "branch-target-enforcement" "sign-return-address"="all" "sign-return-address-key"="a_key" }
-define ptr @noop() {
+define ptr @noop() !prof !3 {
+; CHECK-LABEL: define ptr @noop(
+; CHECK-SAME: ) !prof [[PROF3:![0-9]+]] {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[N:%.*]] = call ptr @llvm.coro.noop()
+; CHECK-NEXT: ret ptr [[N]]
+;
entry:
%n = call ptr @llvm.coro.noop()
ret ptr %n
@@ -21,3 +24,12 @@ declare ptr @llvm.coro.noop()
!0 = !{i32 8, !"branch-target-enforcement", i32 1}
!1 = !{i32 8, !"sign-return-address", i32 1}
!2 = !{i32 8, !"sign-return-address-all", i32 1}
+!3 = !{!"function_entry_count", i64 1000}
+;.
+; CHECK: attributes #[[ATTR0:[0-9]+]] = { nounwind memory(none) }
+;.
+; CHECK: [[META0:![0-9]+]] = !{i32 8, !"branch-target-enforcement", i32 1}
+; CHECK: [[META1:![0-9]+]] = !{i32 8, !"sign-return-address", i32 1}
+; CHECK: [[META2:![0-9]+]] = !{i32 8, !"sign-return-address-all", i32 1}
+; CHECK: [[PROF3]] = !{!"function_entry_count", i64 1000}
+;.
diff --git a/llvm/test/Transforms/Coroutines/coro-noop.ll b/llvm/test/Transforms/Coroutines/coro-noop.ll
index 3736d3f1762f5..4319ec2b05cca 100644
--- a/llvm/test/Transforms/Coroutines/coro-noop.ll
+++ b/llvm/test/Transforms/Coroutines/coro-noop.ll
@@ -1,14 +1,18 @@
-; Tests that CoroCleanup pass correctly lowers coro.noop
-; RUN: opt < %s -S -passes=coro-cleanup | FileCheck %s
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --version 6
+; Tests that CoroEarly pass correctly lowers coro.noop
+; RUN: opt < %s -S -passes=coro-early | FileCheck %s
-; CHECK: @NoopCoro.Frame.Const = private constant %NoopCoro.Frame { ptr @__NoopCoro_ResumeDestroy, ptr @__NoopCoro_ResumeDestroy }
+; CHECK: %NoopCoro.Frame = type { ptr, ptr }
-; CHECK-LABEL: @noop(
define ptr @noop() {
-; CHECK-NEXT: entry
+; CHECK-LABEL: define ptr @noop(
+; CHECK-SAME: ) !prof [[PROF5:![0-9]+]] {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[N:%.*]] = call ptr @llvm.coro.noop()
+; CHECK-NEXT: ret ptr [[N]]
+;
entry:
-; CHECK-NEXT: ret ptr @NoopCoro.Frame.Const
%n = call ptr @llvm.coro.noop()
ret ptr %n
}
@@ -23,10 +27,15 @@ declare ptr @llvm.coro.noop()
!2 = !{}
!3 = !{i32 2, !"Dwarf Version", i32 4}
!4 = !{i32 2, !"Debug Info Version", i32 3}
-
-
-; CHECK: define internal void @__NoopCoro_ResumeDestroy(ptr %0) !dbg ![[RESUME:[0-9]+]] {
-; CHECK-NEXT: entry
-; CHECK-NEXT: ret void
-
-; CHECK: ![[RESUME]] = distinct !DISubprogram(name: "__NoopCoro_ResumeDestroy", linkageName: "__NoopCoro_ResumeDestroy", {{.*}} flags: DIFlagArtificial,
+!5 = !{!"function_entry_count", i64 1000}
+
+;.
+; CHECK: attributes #[[ATTR0:[0-9]+]] = { nounwind memory(none) }
+;.
+; CHECK: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C99, file: [[META1:![0-9]+]], producer: "hand-written", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: [[META2:![0-9]+]])
+; CHECK: [[META1]] = !DIFile(filename: "{{.*}}<stdin>", directory: {{.*}})
+; CHECK: [[META2]] = !{}
+; CHECK: [[META3:![0-9]+]] = !{i32 2, !"Dwarf Version", i32 4}
+; CHECK: [[META4:![0-9]+]] = !{i32 2, !"Debug Info Version", i32 3}
+; CHECK: [[PROF5]] = !{!"function_entry_count", i64 1000}
+;.
diff --git a/llvm/test/Transforms/Coroutines/coro-split-dbg-labels.ll b/llvm/test/Transforms/Coroutines/coro-split-dbg-labels.ll
index c3b13c89fdede..60303bad7c30c 100644
--- a/llvm/test/Transforms/Coroutines/coro-split-dbg-labels.ll
+++ b/llvm/test/Transforms/Coroutines/coro-split-dbg-labels.ll
@@ -1,3 +1,4 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --version 6
; Tests that we add DILabels for the suspend points.
;
; Check the generated LLVM:
@@ -32,7 +33,126 @@ declare void @baz(...) local_unnamed_addr #0
; }
; Function Attrs: nounwind uwtable
-define ptr @f() #2 !dbg !16 {
+;.
+; CHECK: @f.resumers = private constant [3 x ptr] [ptr @f.resume, ptr @f.destroy, ptr @f.cleanup]
+;.
+; LINE-TABLE: @f.resumers = private constant [3 x ptr] [ptr @f.resume, ptr @f.destroy, ptr @f.cleanup]
+;.
+define ptr @f() #2 !dbg !16 !prof !42 {
+; CHECK-LABEL: define ptr @f(
+; CHECK-SAME: ) #[[ATTR1:[0-9]+]] !dbg [[DBG6:![0-9]+]] !prof [[PROF16:![0-9]+]] {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[TMP0:%.*]] = tail call token @llvm.coro.id(i32 0, ptr null, ptr @f, ptr @f.resumers), !dbg [[DBG17:![0-9]+]]
+; CHECK-NEXT: [[FRAME:%.*]] = tail call ptr @malloc(i64 24), !dbg [[DBG17]]
+; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias nonnull ptr @llvm.coro.begin(token [[TMP0]], ptr [[FRAME]]), !dbg [[DBG17]]
+; CHECK-NEXT: store ptr @f.resume, ptr [[TMP1]], align 8, !dbg [[DBG18:![0-9]+]]
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 8, !dbg [[DBG18]]
+; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8, !dbg [[DBG18]]
+; CHECK-NEXT: br label %[[ALLOCASPILLBB:.*]], !dbg [[DBG18]]
+; CHECK: [[ALLOCASPILLBB]]:
+; CHECK-NEXT: br label %[[POSTSPILL:.*]], !dbg [[DBG18]]
+; CHECK: [[POSTSPILL]]:
+; CHECK-NEXT: br label %[[LOOP1:.*]], !dbg [[DBG18]]
+; CHECK: [[LOOP1]]:
+; CHECK-NEXT: tail call void (...) @bar() #[[ATTR0:[0-9]+]], !dbg [[DBG19:![0-9]+]]
+; CHECK-NEXT: br label %[[COROSAVE:.*]], !dbg [[DBG20:![0-9]+]]
+; CHECK: [[COROSAVE]]:
+; CHECK-NEXT: [[INDEX_ADDR4:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 16, !dbg [[DBG20]]
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR4]], align 1, !dbg [[DBG20]]
+; CHECK-NEXT: br label %[[COROSUSPEND:.*]], !dbg [[DBG20]]
+; CHECK: [[COROSUSPEND]]:
+; CHECK-NEXT: br label %[[RESUME_0_LANDING:.*]], !dbg [[DBG20]]
+; CHECK: [[RESUME_0_LANDING]]:
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND:.*]], !dbg [[DBG20]]
+; CHECK: [[AFTERCOROSUSPEND]]:
+; CHECK-NEXT: switch i8 -1, label %[[CORO_SUSPEND:.*]] [
+; CHECK-NEXT: i8 0, label %[[LOOP2:.*]]
+; CHECK-NEXT: i8 1, label %[[CORO_CLEANUP:.*]]
+; CHECK-NEXT: ], !dbg [[DBG20]], !prof [[PROF21:![0-9]+]]
+; CHECK: [[LOOP2]]:
+; CHECK-NEXT: tail call void (...) @baz() #[[ATTR0]], !dbg [[DBG22:![0-9]+]]
+; CHECK-NEXT: br label %[[COROSAVE1:.*]], !dbg [[DBG23:![0-9]+]]
+; CHECK: [[COROSAVE1]]:
+; CHECK-NEXT: [[INDEX_ADDR5:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 16, !dbg [[DBG23]]
+; CHECK-NEXT: store i1 true, ptr [[INDEX_ADDR5]], align 1, !dbg [[DBG23]]
+; CHECK-NEXT: br label %[[COROSUSPEND2:.*]], !dbg [[DBG23]]
+; CHECK: [[COROSUSPEND2]]:
+; CHECK-NEXT: br label %[[RESUME_1_LANDING:.*]], !dbg [[DBG23]]
+; CHECK: [[RESUME_1_LANDING]]:
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND3:.*]], !dbg [[DBG23]]
+; CHECK: [[AFTERCOROSUSPEND3]]:
+; CHECK-NEXT: switch i8 -1, label %[[CORO_SUSPEND]] [
+; CHECK-NEXT: i8 0, label %[[LOOP1]]
+; CHECK-NEXT: i8 1, label %[[CORO_CLEANUP]]
+; CHECK-NEXT: ], !dbg [[DBG23]], !prof [[PROF21]]
+; CHECK: [[CORO_CLEANUP]]:
+; CHECK-NEXT: [[TMP2:%.*]] = tail call ptr @llvm.coro.free(token [[TMP0]], ptr [[TMP1]]), !dbg [[DBG24:![0-9]+]]
+; CHECK-NEXT: tail call void @free(ptr nonnull [[TMP2]]), !dbg [[DBG24]]
+; CHECK-NEXT: br label %[[CORO_SUSPEND]], !dbg [[DBG24]]
+; CHECK: [[CORO_SUSPEND]]:
+; CHECK-NEXT: br label %[[COROEND:.*]], !dbg [[DBG24]]
+; CHECK: [[COROEND]]:
+; CHECK-NEXT: br label %[[AFTERCOROEND:.*]], !dbg [[DBG25:![0-9]+]]
+; CHECK: [[AFTERCOROEND]]:
+; CHECK-NEXT: ret ptr [[TMP1]], !dbg [[DBG25]]
+;
+; LINE-TABLE-LABEL: define ptr @f(
+; LINE-TABLE-SAME: ) #[[ATTR1:[0-9]+]] !dbg [[DBG6:![0-9]+]] !prof [[PROF16:![0-9]+]] {
+; LINE-TABLE-NEXT: [[ENTRY:.*:]]
+; LINE-TABLE-NEXT: [[TMP0:%.*]] = tail call token @llvm.coro.id(i32 0, ptr null, ptr @f, ptr @f.resumers), !dbg [[DBG17:![0-9]+]]
+; LINE-TABLE-NEXT: [[FRAME:%.*]] = tail call ptr @malloc(i64 24), !dbg [[DBG17]]
+; LINE-TABLE-NEXT: [[TMP1:%.*]] = tail call noalias nonnull ptr @llvm.coro.begin(token [[TMP0]], ptr [[FRAME]]), !dbg [[DBG17]]
+; LINE-TABLE-NEXT: store ptr @f.resume, ptr [[TMP1]], align 8, !dbg [[DBG18:![0-9]+]]
+; LINE-TABLE-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 8, !dbg [[DBG18]]
+; LINE-TABLE-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8, !dbg [[DBG18]]
+; LINE-TABLE-NEXT: br label %[[ALLOCASPILLBB:.*]], !dbg [[DBG18]]
+; LINE-TABLE: [[ALLOCASPILLBB]]:
+; LINE-TABLE-NEXT: br label %[[POSTSPILL:.*]], !dbg [[DBG18]]
+; LINE-TABLE: [[POSTSPILL]]:
+; LINE-TABLE-NEXT: br label %[[LOOP1:.*]], !dbg [[DBG18]]
+; LINE-TABLE: [[LOOP1]]:
+; LINE-TABLE-NEXT: tail call void (...) @bar() #[[ATTR0:[0-9]+]], !dbg [[DBG19:![0-9]+]]
+; LINE-TABLE-NEXT: br label %[[COROSAVE:.*]], !dbg [[DBG20:![0-9]+]]
+; LINE-TABLE: [[COROSAVE]]:
+; LINE-TABLE-NEXT: [[INDEX_ADDR4:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 16, !dbg [[DBG20]]
+; LINE-TABLE-NEXT: store i1 false, ptr [[INDEX_ADDR4]], align 1, !dbg [[DBG20]]
+; LINE-TABLE-NEXT: br label %[[COROSUSPEND:.*]], !dbg [[DBG20]]
+; LINE-TABLE: [[COROSUSPEND]]:
+; LINE-TABLE-NEXT: br label %[[RESUME_0_LANDING:.*]], !dbg [[DBG20]]
+; LINE-TABLE: [[RESUME_0_LANDING]]:
+; LINE-TABLE-NEXT: br label %[[AFTERCOROSUSPEND:.*]], !dbg [[DBG20]]
+; LINE-TABLE: [[AFTERCOROSUSPEND]]:
+; LINE-TABLE-NEXT: switch i8 -1, label %[[CORO_SUSPEND:.*]] [
+; LINE-TABLE-NEXT: i8 0, label %[[LOOP2:.*]]
+; LINE-TABLE-NEXT: i8 1, label %[[CORO_CLEANUP:.*]]
+; LINE-TABLE-NEXT: ], !dbg [[DBG20]], !prof [[PROF21:![0-9]+]]
+; LINE-TABLE: [[LOOP2]]:
+; LINE-TABLE-NEXT: tail call void (...) @baz() #[[ATTR0]], !dbg [[DBG22:![0-9]+]]
+; LINE-TABLE-NEXT: br label %[[COROSAVE1:.*]], !dbg [[DBG23:![0-9]+]]
+; LINE-TABLE: [[COROSAVE1]]:
+; LINE-TABLE-NEXT: [[INDEX_ADDR5:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 16, !dbg [[DBG23]]
+; LINE-TABLE-NEXT: store i1 true, ptr [[INDEX_ADDR5]], align 1, !dbg [[DBG23]]
+; LINE-TABLE-NEXT: br label %[[COROSUSPEND2:.*]], !dbg [[DBG23]]
+; LINE-TABLE: [[COROSUSPEND2]]:
+; LINE-TABLE-NEXT: br label %[[RESUME_1_LANDING:.*]], !dbg [[DBG23]]
+; LINE-TABLE: [[RESUME_1_LANDING]]:
+; LINE-TABLE-NEXT: br label %[[AFTERCOROSUSPEND3:.*]], !dbg [[DBG23]]
+; LINE-TABLE: [[AFTERCOROSUSPEND3]]:
+; LINE-TABLE-NEXT: switch i8 -1, label %[[CORO_SUSPEND]] [
+; LINE-TABLE-NEXT: i8 0, label %[[LOOP1]]
+; LINE-TABLE-NEXT: i8 1, label %[[CORO_CLEANUP]]
+; LINE-TABLE-NEXT: ], !dbg [[DBG23]], !prof [[PROF21]]
+; LINE-TABLE: [[CORO_CLEANUP]]:
+; LINE-TABLE-NEXT: [[TMP2:%.*]] = tail call ptr @llvm.coro.free(token [[TMP0]], ptr [[TMP1]]), !dbg [[DBG24:![0-9]+]]
+; LINE-TABLE-NEXT: tail call void @free(ptr nonnull [[TMP2]]), !dbg [[DBG24]]
+; LINE-TABLE-NEXT: br label %[[CORO_SUSPEND]], !dbg [[DBG24]]
+; LINE-TABLE: [[CORO_SUSPEND]]:
+; LINE-TABLE-NEXT: br label %[[COROEND:.*]], !dbg [[DBG24]]
+; LINE-TABLE: [[COROEND]]:
+; LINE-TABLE-NEXT: br label %[[AFTERCOROEND:.*]], !dbg [[DBG25:![0-9]+]]
+; LINE-TABLE: [[AFTERCOROEND]]:
+; LINE-TABLE-NEXT: ret ptr [[TMP1]], !dbg [[DBG25]]
+;
entry:
%0 = tail call token @llvm.coro.id(i32 0, ptr null, ptr @f, ptr null), !dbg !26
%1 = tail call i64 @llvm.coro.size.i64(), !dbg !26
@@ -45,8 +165,8 @@ loop1: ; preds = %for.cond, %entry
%3 = tail call token @llvm.coro.save(ptr null), !dbg !34
%4 = tail call i8 @llvm.coro.suspend(token %3, i1 false), !dbg !34
switch i8 %4, label %coro_Suspend [
- i8 0, label %loop2
- i8 1, label %coro_Cleanup
+ i8 0, label %loop2
+ i8 1, label %coro_Cleanup
], !dbg !34
loop2: ; preds = %for.cond, %entry
@@ -54,8 +174,8 @@ loop2: ; preds = %for.cond, %entry
%5 = tail call token @llvm.coro.save(ptr null), !dbg !36
%6 = tail call i8 @llvm.coro.suspend(token %5, i1 false), !dbg !36
switch i8 %6, label %coro_Suspend [
- i8 0, label %loop1
- i8 1, label %coro_Cleanup
+ i8 0, label %loop1
+ i8 1, label %coro_Cleanup
], !dbg !36
coro_Cleanup: ; preds = %for.cond
@@ -69,24 +189,10 @@ coro_Suspend: ; preds = %for.cond, %if.then,
}
; Check that the resume function contains the `#dbg_label` instructions.
-; CHECK-LABEL: define ptr @f() #1 !dbg !6 {
-; CHECK: resume.0: ; preds = %resume.entry
-; CHECK-NEXT: #dbg_label(![[RESUME_0:[0-9]+]], !{{[0-9]+}})
-; CHECK: resume.1: ; preds = %resume.entry
-; CHECK-NEXT: #dbg_label(![[RESUME_1:[0-9]+]], !{{[0-9]+}})
; Check that the destroy function contains the `#dbg_label` instructions.
-; CHECK-LABEL: define internal void @f.destroy({{.*}}) #1 !dbg !38 {
-; CHECK: resume.0: ; preds = %resume.entry
-; CHECK-NEXT: #dbg_label(![[DESTROY_0:[0-9]+]], !{{[0-9]+}})
-; CHECK: resume.1: ; preds = %resume.entry
-; CHECK-NEXT: #dbg_label(![[DESTROY_1:[0-9]+]], !{{[0-9]+}})
; Check that the DILabels are correct.
-; CHECK: ![[RESUME_0]] = !DILabel(scope: !{{[0-9]+}}, name: "__coro_resume_0", file: !{{[0-9]*}}, line: 12, column: 6, isArtificial: true, coroSuspendIdx: 0)
-; CHECK: ![[RESUME_1]] = !DILabel(scope: !{{[0-9]+}}, name: "__coro_resume_1", file: !{{[0-9]*}}, line: 14, column: 6, isArtificial: true, coroSuspendIdx: 1)
-; CHECK: ![[DESTROY_0]] = !DILabel(scope: !{{[0-9]+}}, name: "__coro_resume_0", file: !{{[0-9]*}}, line: 12, column: 6, isArtificial: true, coroSuspendIdx: 0)
-; CHECK: ![[DESTROY_1]] = !DILabel(scope: !{{[0-9]+}}, name: "__coro_resume_1", file: !{{[0-9]*}}, line: 14, column: 6, isArtificial: true, coroSuspendIdx: 1)
; Check the we do not emit any DILabels in LineTablesOnly mode.
; The DWARF emitter cannot handle this and would run into an assertion.
@@ -152,3 +258,155 @@ attributes #4 = { argmemonly nounwind readonly }
!37 = !DILocation(line: 16, column: 3, scope: !16)
!40 = !DILocation(line: 16, column: 3, scope: !16)
!41 = !DILocation(line: 17, column: 1, scope: !16)
+!42 = !{!"function_entry_count", i64 1000}
+;.
+; CHECK: attributes #[[ATTR0]] = { nounwind }
+; CHECK: attributes #[[ATTR1]] = { nounwind uwtable }
+; CHECK: attributes #[[ATTR2:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(argmem: read) }
+; CHECK: attributes #[[ATTR3:[0-9]+]] = { nounwind memory(none) }
+; CHECK: attributes #[[ATTR4:[0-9]+]] = { nomerge nounwind }
+; CHECK: attributes #[[ATTR5:[0-9]+]] = { nounwind memory(argmem: read) }
+;.
+; LINE-TABLE: attributes #[[ATTR0]] = { nounwind }
+; LINE-TABLE: attributes #[[ATTR1]] = { nounwind uwtable }
+; LINE-TABLE: attributes #[[ATTR2:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(argmem: read) }
+; LINE-TABLE: attributes #[[ATTR3:[0-9]+]] = { nounwind memory(none) }
+; LINE-TABLE: attributes #[[ATTR4:[0-9]+]] = { nomerge nounwind }
+; LINE-TABLE: attributes #[[ATTR5:[0-9]+]] = { nounwind memory(argmem: read) }
+;.
+; CHECK: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C99, file: [[META1:![0-9]+]], producer: "{{.*}}clang version {{.*}} - manually edited", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: [[META2:![0-9]+]])
+; CHECK: [[META1]] = !DIFile(filename: "{{.*}}coro.c", directory: {{.*}})
+; CHECK: [[META2]] = !{}
+; CHECK: [[META3:![0-9]+]] = !{i32 2, !"Dwarf Version", i32 4}
+; CHECK: [[META4:![0-9]+]] = !{i32 2, !"Debug Info Version", i32 3}
+; CHECK: [[META5:![0-9]+]] = !{!"{{.*}}clang version {{.*}} - manually edited"}
+; CHECK: [[DBG6]] = distinct !DISubprogram(name: "f", scope: [[META1]], file: [[META1]], line: 8, type: [[META7:![0-9]+]], scopeLine: 8, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]], retainedNodes: [[META10:![0-9]+]])
+; CHECK: [[META7]] = !DISubroutineType(types: [[META8:![0-9]+]])
+; CHECK: [[META8]] = !{[[META9:![0-9]+]]}
+; CHECK: [[META9]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64, align: 64)
+; CHECK: [[META10]] = !{[[META11:![0-9]+]], [[META12:![0-9]+]], [[META15:![0-9]+]]}
+; CHECK: [[META11]] = !DILocalVariable(name: "coro_hdl", scope: [[DBG6]], file: [[META1]], line: 9, type: [[META9]])
+; CHECK: [[META12]] = !DILocalVariable(name: "i", scope: [[META13:![0-9]+]], file: [[META1]], line: 11, type: [[META14:![0-9]+]])
+; CHECK: [[META13]] = distinct !DILexicalBlock(scope: [[DBG6]], file: [[META1]], line: 11, column: 3)
+; CHECK: [[META14]] = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
+; CHECK: [[META15]] = !DILocalVariable(name: "coro_mem", scope: [[DBG6]], file: [[META1]], line: 16, type: [[META9]])
+; CHECK: [[PROF16]] = !{!"function_entry_count", i64 1000}
+; CHECK: [[DBG17]] = !DILocation(line: 9, column: 3, scope: [[DBG6]])
+; CHECK: [[DBG18]] = !DILocation(line: 10, column: 8, scope: [[META13]])
+; CHECK: [[DBG19]] = !DILocation(line: 11, column: 6, scope: [[META13]])
+; CHECK: [[DBG20]] = !DILocation(line: 12, column: 6, scope: [[META13]])
+; CHECK: [[PROF21]] = !{!"branch_weights", i32 32537631, i32 1008666562, i32 32537631}
+; CHECK: [[DBG22]] = !DILocation(line: 13, column: 6, scope: [[META13]])
+; CHECK: [[DBG23]] = !DILocation(line: 14, column: 6, scope: [[META13]])
+; CHECK: [[DBG24]] = !DILocation(line: 16, column: 3, scope: [[DBG6]])
+; CHECK: [[DBG25]] = !DILocation(line: 17, column: 1, scope: [[DBG6]])
+; CHECK: [[META26:![0-9]+]] = distinct !DISubprogram(name: "f", linkageName: "f.resume", scope: [[META1]], file: [[META1]], line: 8, type: [[META7]], scopeLine: 8, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]], retainedNodes: [[META27:![0-9]+]])
+; CHECK: [[META27]] = !{[[META28:![0-9]+]], [[META29:![0-9]+]], [[META31:![0-9]+]]}
+; CHECK: [[META28]] = !DILocalVariable(name: "coro_hdl", scope: [[META26]], file: [[META1]], line: 9, type: [[META9]])
+; CHECK: [[META29]] = !DILocalVariable(name: "i", scope: [[META30:![0-9]+]], file: [[META1]], line: 11, type: [[META14]])
+; CHECK: [[META30]] = distinct !DILexicalBlock(scope: [[META26]], file: [[META1]], line: 11, column: 3)
+; CHECK: [[META31]] = !DILocalVariable(name: "coro_mem", scope: [[META26]], file: [[META1]], line: 16, type: [[META9]])
+; CHECK: [[META32:![0-9]+]] = !{!"function_entry_count", i64 16500}
+; CHECK: [[META33:![0-9]+]] = !DILocation(line: 10, column: 8, scope: [[META30]])
+; CHECK: [[META34:![0-9]+]] = !{!"branch_weights", i32 0, i32 -2147483648, i32 2017333124}
+; CHECK: [[META35:![0-9]+]] = !DILocation(line: 11, column: 6, scope: [[META30]])
+; CHECK: [[META36:![0-9]+]] = !DILocation(line: 12, column: 6, scope: [[META30]])
+; CHECK: [[META37:![0-9]+]] = !DILabel(scope: [[META26]], name: "__coro_resume_0", file: [[META1]], line: 12, column: 6, isArtificial: true, coroSuspendIdx: 0)
+; CHECK: [[META38:![0-9]+]] = !DILocation(line: 13, column: 6, scope: [[META30]])
+; CHECK: [[META39:![0-9]+]] = !DILocation(line: 14, column: 6, scope: [[META30]])
+; CHECK: [[META40:![0-9]+]] = !DILabel(scope: [[META26]], name: "__coro_resume_1", file: [[META1]], line: 14, column: 6, isArtificial: true, coroSuspendIdx: 1)
+; CHECK: [[META41:![0-9]+]] = !DILocation(line: 16, column: 3, scope: [[META26]])
+; CHECK: [[META42:![0-9]+]] = distinct !DISubprogram(name: "f", linkageName: "f.destroy", scope: [[META1]], file: [[META1]], line: 8, type: [[META7]], scopeLine: 8, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]], retainedNodes: [[META43:![0-9]+]])
+; CHECK: [[META43]] = !{[[META44:![0-9]+]], [[META45:![0-9]+]], [[META47:![0-9]+]]}
+; CHECK: [[META44]] = !DILocalVariable(name: "coro_hdl", scope: [[META42]], file: [[META1]], line: 9, type: [[META9]])
+; CHECK: [[META45]] = !DILocalVariable(name: "i", scope: [[META46:![0-9]+]], file: [[META1]], line: 11, type: [[META14]])
+; CHECK: [[META46]] = distinct !DILexicalBlock(scope: [[META42]], file: [[META1]], line: 11, column: 3)
+; CHECK: [[META47]] = !DILocalVariable(name: "coro_mem", scope: [[META42]], file: [[META1]], line: 16, type: [[META9]])
+; CHECK: [[META48:![0-9]+]] = !DILocation(line: 10, column: 8, scope: [[META46]])
+; CHECK: [[META49:![0-9]+]] = !DILocation(line: 11, column: 6, scope: [[META46]])
+; CHECK: [[META50:![0-9]+]] = !DILocation(line: 12, column: 6, scope: [[META46]])
+; CHECK: [[META51:![0-9]+]] = !DILabel(scope: [[META42]], name: "__coro_resume_0", file: [[META1]], line: 12, column: 6, isArtificial: true, coroSuspendIdx: 0)
+; CHECK: [[META52:![0-9]+]] = !DILocation(line: 13, column: 6, scope: [[META46]])
+; CHECK: [[META53:![0-9]+]] = !DILocation(line: 14, column: 6, scope: [[META46]])
+; CHECK: [[META54:![0-9]+]] = !DILabel(scope: [[META42]], name: "__coro_resume_1", file: [[META1]], line: 14, column: 6, isArtificial: true, coroSuspendIdx: 1)
+; CHECK: [[META55:![0-9]+]] = !DILocation(line: 16, column: 3, scope: [[META42]])
+; CHECK: [[META56:![0-9]+]] = distinct !DISubprogram(name: "f", linkageName: "f.cleanup", scope: [[META1]], file: [[META1]], line: 8, type: [[META7]], scopeLine: 8, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]], retainedNodes: [[META57:![0-9]+]])
+; CHECK: [[META57]] = !{[[META58:![0-9]+]], [[META59:![0-9]+]], [[META61:![0-9]+]]}
+; CHECK: [[META58]] = !DILocalVariable(name: "coro_hdl", scope: [[META56]], file: [[META1]], line: 9, type: [[META9]])
+; CHECK: [[META59]] = !DILocalVariable(name: "i", scope: [[META60:![0-9]+]], file: [[META1]], line: 11, type: [[META14]])
+; CHECK: [[META60]] = distinct !DILexicalBlock(scope: [[META56]], file: [[META1]], line: 11, column: 3)
+; CHECK: [[META61]] = !DILocalVariable(name: "coro_mem", scope: [[META56]], file: [[META1]], line: 16, type: [[META9]])
+; CHECK: [[META62:![0-9]+]] = !DILocation(line: 10, column: 8, scope: [[META60]])
+; CHECK: [[META63:![0-9]+]] = !DILocation(line: 11, column: 6, scope: [[META60]])
+; CHECK: [[META64:![0-9]+]] = !DILocation(line: 12, column: 6, scope: [[META60]])
+; CHECK: [[META65:![0-9]+]] = !DILabel(scope: [[META56]], name: "__coro_resume_0", file: [[META1]], line: 12, column: 6, isArtificial: true, coroSuspendIdx: 0)
+; CHECK: [[META66:![0-9]+]] = !DILocation(line: 13, column: 6, scope: [[META60]])
+; CHECK: [[META67:![0-9]+]] = !DILocation(line: 14, column: 6, scope: [[META60]])
+; CHECK: [[META68:![0-9]+]] = !DILabel(scope: [[META56]], name: "__coro_resume_1", file: [[META1]], line: 14, column: 6, isArtificial: true, coroSuspendIdx: 1)
+; CHECK: [[META69:![0-9]+]] = !DILocation(line: 16, column: 3, scope: [[META56]])
+;.
+; LINE-TABLE: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C99, file: [[META1:![0-9]+]], producer: "{{.*}}clang version {{.*}} - manually edited", isOptimized: true, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: [[META2:![0-9]+]])
+; LINE-TABLE: [[META1]] = !DIFile(filename: "{{.*}}coro.c", directory: {{.*}})
+; LINE-TABLE: [[META2]] = !{}
+; LINE-TABLE: [[META3:![0-9]+]] = !{i32 2, !"Dwarf Version", i32 4}
+; LINE-TABLE: [[META4:![0-9]+]] = !{i32 2, !"Debug Info Version", i32 3}
+; LINE-TABLE: [[META5:![0-9]+]] = !{!"{{.*}}clang version {{.*}} - manually edited"}
+; LINE-TABLE: [[DBG6]] = distinct !DISubprogram(name: "f", scope: [[META1]], file: [[META1]], line: 8, type: [[META7:![0-9]+]], scopeLine: 8, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]], retainedNodes: [[META10:![0-9]+]])
+; LINE-TABLE: [[META7]] = !DISubroutineType(types: [[META8:![0-9]+]])
+; LINE-TABLE: [[META8]] = !{[[META9:![0-9]+]]}
+; LINE-TABLE: [[META9]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64, align: 64)
+; LINE-TABLE: [[META10]] = !{[[META11:![0-9]+]], [[META12:![0-9]+]], [[META15:![0-9]+]]}
+; LINE-TABLE: [[META11]] = !DILocalVariable(name: "coro_hdl", scope: [[DBG6]], file: [[META1]], line: 9, type: [[META9]])
+; LINE-TABLE: [[META12]] = !DILocalVariable(name: "i", scope: [[META13:![0-9]+]], file: [[META1]], line: 11, type: [[META14:![0-9]+]])
+; LINE-TABLE: [[META13]] = distinct !DILexicalBlock(scope: [[DBG6]], file: [[META1]], line: 11, column: 3)
+; LINE-TABLE: [[META14]] = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
+; LINE-TABLE: [[META15]] = !DILocalVariable(name: "coro_mem", scope: [[DBG6]], file: [[META1]], line: 16, type: [[META9]])
+; LINE-TABLE: [[PROF16]] = !{!"function_entry_count", i64 1000}
+; LINE-TABLE: [[DBG17]] = !DILocation(line: 9, column: 3, scope: [[DBG6]])
+; LINE-TABLE: [[DBG18]] = !DILocation(line: 10, column: 8, scope: [[META13]])
+; LINE-TABLE: [[DBG19]] = !DILocation(line: 11, column: 6, scope: [[META13]])
+; LINE-TABLE: [[DBG20]] = !DILocation(line: 12, column: 6, scope: [[META13]])
+; LINE-TABLE: [[PROF21]] = !{!"branch_weights", i32 32537631, i32 1008666562, i32 32537631}
+; LINE-TABLE: [[DBG22]] = !DILocation(line: 13, column: 6, scope: [[META13]])
+; LINE-TABLE: [[DBG23]] = !DILocation(line: 14, column: 6, scope: [[META13]])
+; LINE-TABLE: [[DBG24]] = !DILocation(line: 16, column: 3, scope: [[DBG6]])
+; LINE-TABLE: [[DBG25]] = !DILocation(line: 17, column: 1, scope: [[DBG6]])
+; LINE-TABLE: [[META26:![0-9]+]] = distinct !DISubprogram(name: "f", linkageName: "f.resume", scope: [[META1]], file: [[META1]], line: 8, type: [[META7]], scopeLine: 8, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]], retainedNodes: [[META27:![0-9]+]])
+; LINE-TABLE: [[META27]] = !{[[META28:![0-9]+]], [[META29:![0-9]+]], [[META31:![0-9]+]]}
+; LINE-TABLE: [[META28]] = !DILocalVariable(name: "coro_hdl", scope: [[META26]], file: [[META1]], line: 9, type: [[META9]])
+; LINE-TABLE: [[META29]] = !DILocalVariable(name: "i", scope: [[META30:![0-9]+]], file: [[META1]], line: 11, type: [[META14]])
+; LINE-TABLE: [[META30]] = distinct !DILexicalBlock(scope: [[META26]], file: [[META1]], line: 11, column: 3)
+; LINE-TABLE: [[META31]] = !DILocalVariable(name: "coro_mem", scope: [[META26]], file: [[META1]], line: 16, type: [[META9]])
+; LINE-TABLE: [[META32:![0-9]+]] = !{!"function_entry_count", i64 16500}
+; LINE-TABLE: [[META33:![0-9]+]] = !DILocation(line: 10, column: 8, scope: [[META30]])
+; LINE-TABLE: [[META34:![0-9]+]] = !{!"branch_weights", i32 0, i32 -2147483648, i32 2017333124}
+; LINE-TABLE: [[META35:![0-9]+]] = !DILocation(line: 11, column: 6, scope: [[META30]])
+; LINE-TABLE: [[META36:![0-9]+]] = !DILocation(line: 12, column: 6, scope: [[META30]])
+; LINE-TABLE: [[META37:![0-9]+]] = !DILocation(line: 13, column: 6, scope: [[META30]])
+; LINE-TABLE: [[META38:![0-9]+]] = !DILocation(line: 14, column: 6, scope: [[META30]])
+; LINE-TABLE: [[META39:![0-9]+]] = !DILocation(line: 16, column: 3, scope: [[META26]])
+; LINE-TABLE: [[META40:![0-9]+]] = distinct !DISubprogram(name: "f", linkageName: "f.destroy", scope: [[META1]], file: [[META1]], line: 8, type: [[META7]], scopeLine: 8, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]], retainedNodes: [[META41:![0-9]+]])
+; LINE-TABLE: [[META41]] = !{[[META42:![0-9]+]], [[META43:![0-9]+]], [[META45:![0-9]+]]}
+; LINE-TABLE: [[META42]] = !DILocalVariable(name: "coro_hdl", scope: [[META40]], file: [[META1]], line: 9, type: [[META9]])
+; LINE-TABLE: [[META43]] = !DILocalVariable(name: "i", scope: [[META44:![0-9]+]], file: [[META1]], line: 11, type: [[META14]])
+; LINE-TABLE: [[META44]] = distinct !DILexicalBlock(scope: [[META40]], file: [[META1]], line: 11, column: 3)
+; LINE-TABLE: [[META45]] = !DILocalVariable(name: "coro_mem", scope: [[META40]], file: [[META1]], line: 16, type: [[META9]])
+; LINE-TABLE: [[META46:![0-9]+]] = !DILocation(line: 10, column: 8, scope: [[META44]])
+; LINE-TABLE: [[META47:![0-9]+]] = !DILocation(line: 11, column: 6, scope: [[META44]])
+; LINE-TABLE: [[META48:![0-9]+]] = !DILocation(line: 12, column: 6, scope: [[META44]])
+; LINE-TABLE: [[META49:![0-9]+]] = !DILocation(line: 13, column: 6, scope: [[META44]])
+; LINE-TABLE: [[META50:![0-9]+]] = !DILocation(line: 14, column: 6, scope: [[META44]])
+; LINE-TABLE: [[META51:![0-9]+]] = !DILocation(line: 16, column: 3, scope: [[META40]])
+; LINE-TABLE: [[META52:![0-9]+]] = distinct !DISubprogram(name: "f", linkageName: "f.cleanup", scope: [[META1]], file: [[META1]], line: 8, type: [[META7]], scopeLine: 8, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]], retainedNodes: [[META53:![0-9]+]])
+; LINE-TABLE: [[META53]] = !{[[META54:![0-9]+]], [[META55:![0-9]+]], [[META57:![0-9]+]]}
+; LINE-TABLE: [[META54]] = !DILocalVariable(name: "coro_hdl", scope: [[META52]], file: [[META1]], line: 9, type: [[META9]])
+; LINE-TABLE: [[META55]] = !DILocalVariable(name: "i", scope: [[META56:![0-9]+]], file: [[META1]], line: 11, type: [[META14]])
+; LINE-TABLE: [[META56]] = distinct !DILexicalBlock(scope: [[META52]], file: [[META1]], line: 11, column: 3)
+; LINE-TABLE: [[META57]] = !DILocalVariable(name: "coro_mem", scope: [[META52]], file: [[META1]], line: 16, type: [[META9]])
+; LINE-TABLE: [[META58:![0-9]+]] = !DILocation(line: 10, column: 8, scope: [[META56]])
+; LINE-TABLE: [[META59:![0-9]+]] = !DILocation(line: 11, column: 6, scope: [[META56]])
+; LINE-TABLE: [[META60:![0-9]+]] = !DILocation(line: 12, column: 6, scope: [[META56]])
+; LINE-TABLE: [[META61:![0-9]+]] = !DILocation(line: 13, column: 6, scope: [[META56]])
+; LINE-TABLE: [[META62:![0-9]+]] = !DILocation(line: 14, column: 6, scope: [[META56]])
+; LINE-TABLE: [[META63:![0-9]+]] = !DILocation(line: 16, column: 3, scope: [[META52]])
+;.
More information about the cfe-commits
mailing list