Skip to content

Commit 7782e08

Browse files
committed
[Coroutines] Only do symmetric transfer if optimization is on
Symmetric transfer is not a part of C++ standards. So the vendors is not forced to implement it any way. Given the symmetric transfer nowadays is an optimization. It makes more sense to enable it only if the optimization is enabled. It is also helpful for the compilation speed in O0.
1 parent 8b68da2 commit 7782e08

20 files changed

+38
-35
lines changed

llvm/include/llvm/Transforms/Coroutines/CoroSplit.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@
2222
namespace llvm {
2323

2424
struct CoroSplitPass : PassInfoMixin<CoroSplitPass> {
25-
CoroSplitPass(bool OptimizeFrame = false) : OptimizeFrame(OptimizeFrame) {}
25+
CoroSplitPass(bool Optimizing = false) : Optimizing(Optimizing) {}
2626

2727
PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
2828
LazyCallGraph &CG, CGSCCUpdateResult &UR);
2929
static bool isRequired() { return true; }
3030

3131
// Would be true if the Optimization level isn't O0.
32-
bool OptimizeFrame;
32+
bool Optimizing;
3333
};
3434
} // end namespace llvm
3535

llvm/lib/Passes/PassBuilder.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -601,7 +601,7 @@ Expected<bool> parseInlinerPassOptions(StringRef Params) {
601601
}
602602

603603
Expected<bool> parseCoroSplitPassOptions(StringRef Params) {
604-
return parseSinglePassOption(Params, "reuse-storage", "CoroSplitPass");
604+
return parseSinglePassOption(Params, "optimizing", "CoroSplitPass");
605605
}
606606

607607
Expected<bool> parseEarlyCSEPassOptions(StringRef Params) {

llvm/lib/Passes/PassRegistry.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ CGSCC_PASS_WITH_PARAMS("coro-split",
192192
return CoroSplitPass(OptimizeFrame);
193193
},
194194
parseCoroSplitPassOptions,
195-
"reuse-storage")
195+
"optimizing")
196196
#undef CGSCC_PASS_WITH_PARAMS
197197

198198
#ifndef FUNCTION_ANALYSIS

llvm/lib/Transforms/Coroutines/CoroFrame.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -612,7 +612,7 @@ void FrameTypeBuilder::addFieldForAllocas(const Function &F,
612612
}
613613
});
614614

615-
if (!Shape.OptimizeFrame) {
615+
if (!Shape.Optimizing) {
616616
for (const auto &A : FrameData.Allocas) {
617617
AllocaInst *Alloca = A.Alloca;
618618
NonOverlapedAllocas.emplace_back(AllocaSetType(1, Alloca));
@@ -1696,14 +1696,14 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) {
16961696
&*Builder.GetInsertPoint());
16971697
// This dbg.declare is for the main function entry point. It
16981698
// will be deleted in all coro-split functions.
1699-
coro::salvageDebugInfo(DbgPtrAllocaCache, DDI, Shape.OptimizeFrame);
1699+
coro::salvageDebugInfo(DbgPtrAllocaCache, DDI, Shape.Optimizing);
17001700
}
17011701
}
17021702

17031703
// Salvage debug info on any dbg.addr that we see. We do not insert them
17041704
// into each block where we have a use though.
17051705
if (auto *DI = dyn_cast<DbgAddrIntrinsic>(U)) {
1706-
coro::salvageDebugInfo(DbgPtrAllocaCache, DI, Shape.OptimizeFrame);
1706+
coro::salvageDebugInfo(DbgPtrAllocaCache, DI, Shape.Optimizing);
17071707
}
17081708

17091709
// If we have a single edge PHINode, remove it and replace it with a
@@ -2552,7 +2552,7 @@ static void collectFrameAllocas(Function &F, coro::Shape &Shape,
25522552

25532553
void coro::salvageDebugInfo(
25542554
SmallDenseMap<llvm::Value *, llvm::AllocaInst *, 4> &DbgPtrAllocaCache,
2555-
DbgVariableIntrinsic *DVI, bool OptimizeFrame) {
2555+
DbgVariableIntrinsic *DVI, bool Optimizing) {
25562556
Function *F = DVI->getFunction();
25572557
IRBuilder<> Builder(F->getContext());
25582558
auto InsertPt = F->getEntryBlock().getFirstInsertionPt();
@@ -2605,7 +2605,7 @@ void coro::salvageDebugInfo(
26052605
//
26062606
// Avoid to create the alloca would be eliminated by optimization
26072607
// passes and the corresponding dbg.declares would be invalid.
2608-
if (!OptimizeFrame)
2608+
if (!Optimizing)
26092609
if (auto *Arg = dyn_cast<llvm::Argument>(Storage)) {
26102610
auto &Cached = DbgPtrAllocaCache[Storage];
26112611
if (!Cached) {

llvm/lib/Transforms/Coroutines/CoroInternal.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ void replaceCoroFree(CoroIdInst *CoroId, bool Elide);
3131
/// holding a pointer to the coroutine frame.
3232
void salvageDebugInfo(
3333
SmallDenseMap<llvm::Value *, llvm::AllocaInst *, 4> &DbgPtrAllocaCache,
34-
DbgVariableIntrinsic *DVI, bool OptimizeFrame);
34+
DbgVariableIntrinsic *DVI, bool Optimizing);
3535

3636
// Keeps data and helper functions for lowering coroutine intrinsics.
3737
struct LowererBase {
@@ -104,7 +104,7 @@ struct LLVM_LIBRARY_VISIBILITY Shape {
104104
BasicBlock *AllocaSpillBlock;
105105

106106
/// This would only be true if optimization are enabled.
107-
bool OptimizeFrame;
107+
bool Optimizing;
108108

109109
struct SwitchLoweringStorage {
110110
SwitchInst *ResumeSwitch;
@@ -255,8 +255,8 @@ struct LLVM_LIBRARY_VISIBILITY Shape {
255255
void emitDealloc(IRBuilder<> &Builder, Value *Ptr, CallGraph *CG) const;
256256

257257
Shape() = default;
258-
explicit Shape(Function &F, bool OptimizeFrame = false)
259-
: OptimizeFrame(OptimizeFrame) {
258+
explicit Shape(Function &F, bool Optimizing = false)
259+
: Optimizing(Optimizing) {
260260
buildFrom(F);
261261
}
262262
void buildFrom(Function &F);

llvm/lib/Transforms/Coroutines/CoroSplit.cpp

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -683,7 +683,7 @@ void CoroCloner::salvageDebugInfo() {
683683
if (auto *DVI = dyn_cast<DbgVariableIntrinsic>(&I))
684684
Worklist.push_back(DVI);
685685
for (DbgVariableIntrinsic *DVI : Worklist)
686-
coro::salvageDebugInfo(DbgPtrAllocaCache, DVI, Shape.OptimizeFrame);
686+
coro::salvageDebugInfo(DbgPtrAllocaCache, DVI, Shape.Optimizing);
687687

688688
// Remove all salvaged dbg.declare intrinsics that became
689689
// either unreachable or stale due to the CoroSplit transformation.
@@ -1351,8 +1351,8 @@ static bool shouldBeMustTail(const CallInst &CI, const Function &F) {
13511351
}
13521352

13531353
// Add musttail to any resume instructions that is immediately followed by a
1354-
// suspend (i.e. ret). We do this even in -O0 to support guaranteed tail call
1355-
// for symmetrical coroutine control transfer (C++ Coroutines TS extension).
1354+
// suspend (i.e. ret) to implement symmetric transfer. We wouldn't do this in
1355+
// O0 since symmetric transfer is not part of standard now.
13561356
// This transformation is done only in the resume part of the coroutine that has
13571357
// identical signature and calling convention as the coro.resume call.
13581358
static void addMustTailToCoroResumes(Function &F) {
@@ -1580,7 +1580,10 @@ static void splitSwitchCoroutine(Function &F, coro::Shape &Shape,
15801580
postSplitCleanup(*DestroyClone);
15811581
postSplitCleanup(*CleanupClone);
15821582

1583-
addMustTailToCoroResumes(*ResumeClone);
1583+
// Prepare to do symmetric transfer. We only do this if optimization is
1584+
// enabled since the symmetric transfer is not part of the C++ standard now.
1585+
if (Shape.Optimizing)
1586+
addMustTailToCoroResumes(*ResumeClone);
15841587

15851588
// Store addresses resume/destroy/cleanup functions in the coroutine frame.
15861589
updateCoroFrame(Shape, ResumeClone, DestroyClone, CleanupClone);
@@ -1885,14 +1888,14 @@ namespace {
18851888

18861889
static coro::Shape splitCoroutine(Function &F,
18871890
SmallVectorImpl<Function *> &Clones,
1888-
bool OptimizeFrame) {
1891+
bool Optimizing) {
18891892
PrettyStackTraceFunction prettyStackTrace(F);
18901893

18911894
// The suspend-crossing algorithm in buildCoroutineFrame get tripped
18921895
// up by uses in unreachable blocks, so remove them as a first pass.
18931896
removeUnreachableBlocks(F);
18941897

1895-
coro::Shape Shape(F, OptimizeFrame);
1898+
coro::Shape Shape(F, Optimizing);
18961899
if (!Shape.CoroBegin)
18971900
return Shape;
18981901

@@ -1941,7 +1944,7 @@ static coro::Shape splitCoroutine(Function &F,
19411944
}
19421945
}
19431946
for (auto *DDI : Worklist)
1944-
coro::salvageDebugInfo(DbgPtrAllocaCache, DDI, Shape.OptimizeFrame);
1947+
coro::salvageDebugInfo(DbgPtrAllocaCache, DDI, Shape.Optimizing);
19451948

19461949
return Shape;
19471950
}
@@ -2084,7 +2087,7 @@ PreservedAnalyses CoroSplitPass::run(LazyCallGraph::SCC &C,
20842087
F.setSplittedCoroutine();
20852088

20862089
SmallVector<Function *, 4> Clones;
2087-
const coro::Shape Shape = splitCoroutine(F, Clones, OptimizeFrame);
2090+
const coro::Shape Shape = splitCoroutine(F, Clones, Optimizing);
20882091
updateCallGraphAfterCoroutineSplit(*N, Shape, Clones, C, CG, AM, UR, FAM);
20892092

20902093
if (!Shape.CoroSuspends.empty()) {

llvm/test/Transforms/Coroutines/coro-debug-O2.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
; RUN: opt < %s -passes='module(coro-early),cgscc(coro-split<reuse-storage>),function(sroa)' -S | FileCheck %s
1+
; RUN: opt < %s -passes='module(coro-early),cgscc(coro-split<optimizing>),function(sroa)' -S | FileCheck %s
22

33
; Checks whether the dbg.declare for `__promise` remains valid under O2.
44

llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-00.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; Check that we can handle spills of array allocas
2-
; RUN: opt < %s -passes='cgscc(coro-split<reuse-storage>),simplifycfg,early-cse' -S | FileCheck %s
2+
; RUN: opt < %s -passes='cgscc(coro-split<optimizing>),simplifycfg,early-cse' -S | FileCheck %s
33

44
%struct.big_structure = type { [500 x i8] }
55
declare void @consume(%struct.big_structure*)

llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-01.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
; Tests that variables in a Corotuine whose lifetime range is not overlapping each other
22
; re-use the same slot in Coroutine frame.
3-
; RUN: opt < %s -passes='cgscc(coro-split<reuse-storage>),simplifycfg,early-cse' -S | FileCheck %s
3+
; RUN: opt < %s -passes='cgscc(coro-split<optimizing>),simplifycfg,early-cse' -S | FileCheck %s
44
%"struct.task::promise_type" = type { i8 }
55
%struct.awaitable = type { i8 }
66
%struct.big_structure = type { [500 x i8] }

llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-02.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
; Tests that variables of different type in a Corotuine whose lifetime range is not overlapping each other
22
; re-use the same slot in Coroutine frame.
3-
; RUN: opt < %s -passes='cgscc(coro-split<reuse-storage>),simplifycfg,early-cse' -S | FileCheck %s
3+
; RUN: opt < %s -passes='cgscc(coro-split<optimizing>),simplifycfg,early-cse' -S | FileCheck %s
44
%"struct.task::promise_type" = type { i8 }
55
%struct.awaitable = type { i8 }
66
%struct.big_structure = type { [500 x i8] }

llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-04.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
; Tests that variables of different type with incompatible alignment in a Corotuine whose lifetime
22
; range is not overlapping each other should not re-use the same slot in Coroutine frame.
3-
; RUN: opt < %s -passes='cgscc(coro-split<reuse-storage>),simplifycfg,early-cse' -S | FileCheck %s
3+
; RUN: opt < %s -passes='cgscc(coro-split<optimizing>),simplifycfg,early-cse' -S | FileCheck %s
44
%"struct.task::promise_type" = type { i8 }
55
%struct.awaitable = type { i8 }
66
%struct.big_structure = type { [500 x i8] }

llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-05.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
; Tests that variables of different type with incompatible alignment in a Corotuine whose
22
; lifetime range is not overlapping each other re-use the same slot in CorotuineFrame.
3-
; RUN: opt < %s -passes='cgscc(coro-split<reuse-storage>),simplifycfg,early-cse' -S | FileCheck %s
3+
; RUN: opt < %s -passes='cgscc(coro-split<optimizing>),simplifycfg,early-cse' -S | FileCheck %s
44
%"struct.task::promise_type" = type { i8 }
55
%struct.awaitable = type { i8 }
66
%struct.big_structure = type { [500 x i8] }

llvm/test/Transforms/Coroutines/coro-split-musttail.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
; Tests that coro-split will convert coro.resume followed by a suspend to a
22
; musttail call.
3-
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
3+
; RUN: opt < %s -passes='cgscc(coro-split<optimizing>),simplifycfg,early-cse' -S | FileCheck %s
44

55
define void @f() #0 {
66
entry:

llvm/test/Transforms/Coroutines/coro-split-musttail1.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
; Tests that coro-split will convert coro.resume followed by a suspend to a
22
; musttail call.
3-
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
3+
; RUN: opt < %s -passes='cgscc(coro-split<optimizing>),simplifycfg,early-cse' -S | FileCheck %s
44

55
define void @f() #0 {
66
entry:

llvm/test/Transforms/Coroutines/coro-split-musttail2.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
; Tests that coro-split will convert coro.resume followed by a suspend to a
22
; musttail call.
3-
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
3+
; RUN: opt < %s -passes='cgscc(coro-split<optimizing>),simplifycfg,early-cse' -S | FileCheck %s
44

55
define void @fakeresume1(i8*) {
66
entry:

llvm/test/Transforms/Coroutines/coro-split-musttail3.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
; Tests that coro-split will convert coro.resume followed by a suspend to a
22
; musttail call.
3-
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
3+
; RUN: opt < %s -passes='cgscc(coro-split<optimizing>),simplifycfg,early-cse' -S | FileCheck %s
44

55
define void @f() #0 {
66
entry:

llvm/test/Transforms/Coroutines/coro-split-musttail4.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
; Tests that coro-split will convert a call before coro.suspend to a musttail call
22
; while the user of the coro.suspend is a icmpinst.
3-
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
3+
; RUN: opt < %s -passes='cgscc(coro-split<optimizing>),simplifycfg,early-cse' -S | FileCheck %s
44

55
define void @fakeresume1(i8*) {
66
entry:

llvm/test/Transforms/Coroutines/coro-split-musttail5.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
; Tests that sinked lifetime markers wouldn't provent optimization
22
; to convert a resuming call to a musttail call.
3-
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
3+
; RUN: opt < %s -passes='cgscc(coro-split<optimizing>),simplifycfg,early-cse' -S | FileCheck %s
44

55
declare void @fakeresume1(i64* align 8)
66

llvm/test/Transforms/Coroutines/coro-split-musttail6.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
; The difference between this and coro-split-musttail5.ll is that there is
44
; an extra bitcast instruction in the path, which makes it harder to
55
; optimize.
6-
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
6+
; RUN: opt < %s -passes='cgscc(coro-split<optimizing>),simplifycfg,early-cse' -S | FileCheck %s
77

88
declare void @fakeresume1(i64* align 8)
99

llvm/test/Transforms/Coroutines/coro-split-musttail7.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
; The difference between this and coro-split-musttail5.ll and coro-split-musttail5.ll
44
; is that this contains dead instruction generated during the transformation,
55
; which makes the optimization harder.
6-
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
6+
; RUN: opt < %s -passes='cgscc(coro-split<optimizing>),simplifycfg,early-cse' -S | FileCheck %s
77

88
declare void @fakeresume1(i64* align 8)
99

0 commit comments

Comments
 (0)