LLVM: lib/Transforms/Coroutines/CoroSplit.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
72#include
73#include
74#include
75#include <initializer_list>
76#include
77
78using namespace llvm;
79
80#define DEBUG_TYPE "coro-split"
81
82
83
84
85
91
92 Builder.SetInsertPoint(CB);
93
95
96
97
98 AttributeList NewAttributes =
100
102 auto WrapperInvoke =
103 Builder.CreateInvoke(Wrapper, Invoke->getNormalDest(),
104 Invoke->getUnwindDest(), {Awaiter, FramePtr});
105
106 WrapperInvoke->setCallingConv(Invoke->getCallingConv());
107 std::copy(Invoke->bundle_op_info_begin(), Invoke->bundle_op_info_end(),
108 WrapperInvoke->bundle_op_info_begin());
109 WrapperInvoke->setAttributes(NewAttributes);
110 WrapperInvoke->setDebugLoc(Invoke->getDebugLoc());
111 NewCall = WrapperInvoke;
113 auto WrapperCall = Builder.CreateCall(Wrapper, {Awaiter, FramePtr});
114
115 WrapperCall->setAttributes(NewAttributes);
116 WrapperCall->setDebugLoc(Call->getDebugLoc());
117 NewCall = WrapperCall;
118 } else {
119 llvm_unreachable("Unexpected coro_await_suspend invocation method");
120 }
121
123 Intrinsic::coro_await_suspend_handle) {
124
125
127
128 Builder.SetInsertPoint(Invoke->getNormalDest()->getFirstInsertionPt());
129 }
130
133 &*Builder.GetInsertPoint());
134
138 auto *ResumeCall = Builder.CreateCall(ResumeTy, ResumeAddr, {NewCall});
140
141
142
144
145 NewCall = ResumeCall;
146 }
147
150}
151
157
167
168
169
170
173
175 if (!EndAsync) {
176 Builder.CreateRetVoid();
177 return true ;
178 }
179
180 auto *MustTailCallFunc = EndAsync->getMustTailCallFunction();
181 if (!MustTailCallFunc) {
182 Builder.CreateRetVoid();
183 return true ;
184 }
185
186
187 auto *CoroEndBlock = End->getParent();
188 auto *MustTailCallFuncBlock = CoroEndBlock->getSinglePredecessor();
189 assert(MustTailCallFuncBlock && "Must have a single predecessor block");
190 auto It = MustTailCallFuncBlock->getTerminator()->getIterator();
191 auto *MustTailCall = cast(&*std::prev(It));
192 CoroEndBlock->splice(End->getIterator(), MustTailCallFuncBlock,
193 MustTailCall->getIterator());
194
195
196 Builder.SetInsertPoint(End);
197 Builder.CreateRetVoid();
199
200
202 BB->splitBasicBlock(End);
203 BB->getTerminator()->eraseFromParent();
204
205 auto InlineRes = InlineFunction(*MustTailCall, FnInfo);
206 assert(InlineRes.isSuccess() && "Expected inlining to succeed");
207 (void)InlineRes;
208
209
210 return false;
211}
212
213
217
219
220
221 switch (Shape.ABI) {
222
225 "switch coroutine should not return any values");
226
227
228 if (InRamp)
229 return;
230 Builder.CreateRetVoid();
231 break;
232
233
236 if (!CoroEndBlockNeedsCleanup)
237 return;
238 break;
239 }
240
241
242
247
248 if (!CoroEnd->hasResults()) {
249 assert(RetTy->isVoidTy());
250 Builder.CreateRetVoid();
251 break;
252 }
253
254 auto *CoroResults = CoroEnd->getResults();
255 unsigned NumReturns = CoroResults->numReturns();
256
258 assert(RetStructTy->getNumElements() == NumReturns &&
259 "numbers of returns should match resume function singature");
261 unsigned Idx = 0;
262 for (Value *RetValEl : CoroResults->return_values())
263 ReturnValue = Builder.CreateInsertValue(ReturnValue, RetValEl, Idx++);
264 Builder.CreateRet(ReturnValue);
265 } else if (NumReturns == 0) {
266 assert(RetTy->isVoidTy());
267 Builder.CreateRetVoid();
268 } else {
269 assert(NumReturns == 1);
270 Builder.CreateRet(*CoroResults->retval_begin());
271 }
272 CoroResults->replaceAllUsesWith(
274 CoroResults->eraseFromParent();
275 break;
276 }
277
278
279
282 "retcon coroutine should not return any values");
287 cast(RetStructTy ? RetStructTy->getElementType(0) : RetTy);
288
290 if (RetStructTy) {
291 ReturnValue = Builder.CreateInsertValue(PoisonValue::get(RetStructTy),
292 ReturnValue, 0);
293 }
294 Builder.CreateRet(ReturnValue);
295 break;
296 }
297 }
298
299
301 BB->splitBasicBlock(End);
302 BB->getTerminator()->eraseFromParent();
303}
304
305
306
307
308
309
310
311
312
317 "markCoroutineAsDone is only supported for Switch-Resumed ABI for now.");
318 auto *GepIndex = Builder.CreateStructGEP(
320 "ResumeFn.addr");
323 Builder.CreateStore(NullPtr, GepIndex);
324
325
326
327
328
329
330
331
332
336 "The final suspend should only live in the last position of "
337 "CoroSuspends.");
339 auto *FinalIndex = Builder.CreateStructGEP(
341
342 Builder.CreateStore(IndexVal, FinalIndex);
343 }
344}
345
346
350
351 switch (Shape.ABI) {
352
354
355
356
357
358
359
361 if (InRamp)
362 return;
363 break;
364 }
365
367 break;
368
372 break;
373 }
374
375
378 auto *CleanupRet = Builder.CreateCleanupRet(FromPad, nullptr);
379 End->getParent()->splitBasicBlock(End);
380 CleanupRet->getParent()->getTerminator()->eraseFromParent();
381 }
382}
383
392
393
394
395
396
397
398
399
400
401
404 Shape.SwitchLowering.HasFinalSuspend);
405
407 return;
408
410 auto FinalCaseIt = std::prev(Switch->case_end());
411 BasicBlock *ResumeBB = FinalCaseIt->getCaseSuccessor();
412 Switch->removeCase(FinalCaseIt);
417
418 if (NewF->isCoroOnlyDestroyWhenComplete()) {
419
420
421 Builder.CreateBr(ResumeBB);
422 } else {
423 auto *GepIndex = Builder.CreateStructGEP(
425 "ResumeFn.addr");
426 auto *Load =
427 Builder.CreateLoad(Shape.getSwitchResumePointerType(), GepIndex);
429 Builder.CreateCondBr(Cond, ResumeBB, NewSwitchBB);
430 }
432 }
433}
434
439 auto &Context = Suspend->getParent()->getParent()->getContext();
442}
443
445 const Twine &Suffix,
452
455 OrigF.getName() + Suffix);
456
457 M->getFunctionList().insert(InsertBefore, NewF);
458
459 return NewF;
460}
461
462
463
464
465
469
471 if (NewS->use_empty())
472 return;
473
474
475
477
479 for (auto I = IsAsyncABI ? NewF->arg_begin() : std::next(NewF->arg_begin()),
480 E = NewF->arg_end();
482 Args.push_back(&*I);
483
484
485
487 assert(Args.size() == 1);
488 NewS->replaceAllUsesWith(Args.front());
489 return;
490 }
491
492
495 if (!EVI || EVI->getNumIndices() != 1)
496 continue;
497
498 EVI->replaceAllUsesWith(Args[EVI->getIndices().front()]);
499 EVI->eraseFromParent();
500 }
501
502
503 if (NewS->use_empty())
504 return;
505
506
509 Aggr = Builder.CreateInsertValue(Aggr, Arg, Idx);
510
511 NewS->replaceAllUsesWith(Aggr);
512}
513
515 Value *SuspendResult;
516
517 switch (Shape.ABI) {
518
519
520
521
522
523
526 break;
527
528
530 return;
531
532
533
534
537 return;
538 }
539
541
543 continue;
544
546 MappedCS->replaceAllUsesWith(SuspendResult);
547 MappedCS->eraseFromParent();
548 }
549}
550
559
561 auto &Ctx = OrigF.getContext();
562 for (auto *II : Shape.CoroIsInRampInsts) {
565 NewII->eraseFromParent();
566 }
567}
568
572 return;
573 Value *CachedSlot = nullptr;
574 auto getSwiftErrorSlot = [&](Type *ValueTy) -> Value * {
575 if (CachedSlot)
576 return CachedSlot;
577
578
579 for (auto &Arg : F.args()) {
580 if (Arg.isSwiftError()) {
581 CachedSlot = &Arg;
582 return &Arg;
583 }
584 }
585
586
588 F.getEntryBlock().getFirstNonPHIOrDbg());
589 auto Alloca = Builder.CreateAlloca(ValueTy);
590 Alloca->setSwiftError(true);
591
592 CachedSlot = Alloca;
593 return Alloca;
594 };
595
599
600
601 Value *MappedResult;
602 if (Op->arg_empty()) {
603 auto ValueTy = Op->getType();
604 auto Slot = getSwiftErrorSlot(ValueTy);
605 MappedResult = Builder.CreateLoad(ValueTy, Slot);
606 } else {
608 auto Value = MappedOp->getArgOperand(0);
610 auto Slot = getSwiftErrorSlot(ValueTy);
611 Builder.CreateStore(Value, Slot);
612 MappedResult = Slot;
613 }
614
616 MappedOp->eraseFromParent();
617 }
618
619
620 if (VMap == nullptr) {
622 }
623}
624
625
631 DbgVariableRecords.push_back(&DVR);
632 }
633 return DbgVariableRecords;
634}
635
639
643
644
645 bool UseEntryValue = OrigF.getParent()->getTargetTriple().isArch64Bit();
648
649
650
652 auto IsUnreachableBlock = [&](BasicBlock *BB) {
654 &DomTree);
655 };
657 if (IsUnreachableBlock(DVI->getParent()))
658 DVI->eraseFromParent();
660
661 unsigned Uses = 0;
662 for (auto *User : DVI->getVariableLocationOp(0)->users())
667 DVI->eraseFromParent();
668 }
669 };
670 for_each(DbgVariableRecords, RemoveOne);
671}
672
674
675
676
677
678
680 auto *OldEntry = &NewF->getEntryBlock();
681 Entry->setName("entry" + Suffix);
682 Entry->moveBefore(OldEntry);
683 Entry->getTerminator()->eraseFromParent();
684
685
686
687
688 assert(Entry->hasOneUse());
690 assert(BranchToEntry->isUnconditional());
691 Builder.SetInsertPoint(BranchToEntry);
692 Builder.CreateUnreachable();
693 BranchToEntry->eraseFromParent();
694
695
696 Builder.SetInsertPoint(Entry);
697 switch (Shape.ABI) {
699
700
701 auto *SwitchBB =
703 Builder.CreateBr(SwitchBB);
704 SwitchBB->moveAfter(Entry);
705 break;
706 }
710
711
712
720 assert(Branch->isUnconditional());
721 Builder.CreateBr(Branch->getSuccessor(0));
722 break;
723 }
724 }
725
726
727
728 Function *F = OldEntry->getParent();
732 if (!Alloca || I.use_empty())
733 continue;
736 continue;
737 I.moveBefore(*Entry, Entry->getFirstInsertionPt());
738 }
739}
740
741
743
744
745 switch (Shape.ABI) {
746
748 return &*NewF->arg_begin();
749
750
751
752
753
756 auto ContextIdx = ActiveAsyncSuspend->getStorageArgumentIndex() & 0xff;
757 auto *CalleeContext = NewF->getArg(ContextIdx);
758 auto *ProjectionFunc =
759 ActiveAsyncSuspend->getAsyncContextProjectionFunction();
760 auto DbgLoc =
762
763 auto *CallerContext = Builder.CreateCall(ProjectionFunc->getFunctionType(),
764 ProjectionFunc, CalleeContext);
765 CallerContext->setCallingConv(ProjectionFunc->getCallingConv());
766 CallerContext->setDebugLoc(DbgLoc);
767
768 auto &Context = Builder.getContext();
769 auto *FramePtrAddr = Builder.CreateConstInBoundsGEP1_32(
771 Shape.AsyncLowering.FrameOffset, "async.ctx.frameptr");
772
775 assert(InlineRes.isSuccess());
776 (void)InlineRes;
777 return FramePtrAddr;
778 }
779
784
785
786 if (Shape.RetconLowering.IsFrameInlineInStorage)
787 return NewStorage;
788
789
790 return Builder.CreateLoad(FramePtrTy, NewStorage);
791 }
792 }
794}
795
796
797
798
799
800
801
804 if (!ActiveSuspend)
805 return;
806
807
810 if (SPToUpdate.getFile() == DL->getFile())
811 SPToUpdate.setScopeLine(DL->getLine());
812 return;
813 }
814
816
817
819 Branch && Branch->isUnconditional())
820 Successor = Branch->getSuccessor(0)->getFirstNonPHIOrDbg();
821
822
823
828 if ( || DL.getLine() == 0)
829 continue;
830
831 if (SPToUpdate.getFile() == DL->getFile()) {
832 SPToUpdate.setScopeLine(DL.getLine());
833 return;
834 }
835
836 break;
837 }
838
839
841 if (SPToUpdate.getFile() == DL->getFile())
842 SPToUpdate.setScopeLine(DL->getLine());
843}
844
847 Align Alignment, bool NoAlias) {
848 AttrBuilder ParamAttrs(Context);
849 ParamAttrs.addAttribute(Attribute::NonNull);
850 ParamAttrs.addAttribute(Attribute::NoUndef);
851
852 if (NoAlias)
853 ParamAttrs.addAttribute(Attribute::NoAlias);
854
855 ParamAttrs.addAlignmentAttr(Alignment);
856 ParamAttrs.addDereferenceableAttr(Size);
857 Attrs = Attrs.addParamAttributes(Context, ParamIndex, ParamAttrs);
858}
859
861 unsigned ParamIndex) {
862 AttrBuilder ParamAttrs(Context);
863 ParamAttrs.addAttribute(Attribute::SwiftAsync);
864 Attrs = Attrs.addParamAttributes(Context, ParamIndex, ParamAttrs);
865}
866
868 unsigned ParamIndex) {
869 AttrBuilder ParamAttrs(Context);
870 ParamAttrs.addAttribute(Attribute::SwiftSelf);
871 Attrs = Attrs.addParamAttributes(Context, ParamIndex, ParamAttrs);
872}
873
874
875
878
879
880
881
882
883
888 }
889
891
892
893
894 auto savedVisibility = NewF->getVisibility();
895 auto savedUnnamedAddr = NewF->getUnnamedAddr();
896 auto savedDLLStorageClass = NewF->getDLLStorageClass();
897
898
899
900
901 auto savedLinkage = NewF->getLinkage();
903
906
907 auto &Context = NewF->getContext();
908
910 assert(SP != OrigF.getSubprogram() && SP->isDistinct());
912
913
914
916 SP->replaceLinkageName(NewLinkageName);
917 if (DISubprogram *Decl = SP->getDeclaration()) {
918 TempDISubprogram NewDecl = Decl->clone();
919 NewDecl->replaceLinkageName(NewLinkageName);
921 }
922 }
923
924 NewF->setLinkage(savedLinkage);
925 NewF->setVisibility(savedVisibility);
926 NewF->setUnnamedAddr(savedUnnamedAddr);
927 NewF->setDLLStorageClass(savedDLLStorageClass);
928
929
930
932 NewF->hasMetadata(LLVMContext::MD_func_sanitize))
933 NewF->eraseMetadata(LLVMContext::MD_func_sanitize);
934
935
936 auto OrigAttrs = NewF->getAttributes();
937 auto NewAttrs = AttributeList();
938
939 switch (Shape.ABI) {
941
942
943 NewAttrs = NewAttrs.addFnAttributes(
944 Context, AttrBuilder(Context, OrigAttrs.getFnAttrs()));
945
947 Shape.FrameAlign, false);
948 break;
951 if (OrigF.hasParamAttribute(Shape.AsyncLowering.ContextArgNo,
952 Attribute::SwiftAsync)) {
953 uint32_t ArgAttributeIndices =
954 ActiveAsyncSuspend->getStorageArgumentIndex();
955 auto ContextArgIndex = ArgAttributeIndices & 0xff;
957
958
959
960 auto SwiftSelfIndex = ArgAttributeIndices >> 8;
961 if (SwiftSelfIndex)
963 }
964
965
966 auto FnAttrs = OrigF.getAttributes().getFnAttrs();
967 NewAttrs = NewAttrs.addFnAttributes(Context, AttrBuilder(Context, FnAttrs));
968 break;
969 }
972
973
974 NewAttrs = Shape.RetconLowering.ResumePrototype->getAttributes();
975
976
978 Shape.getRetconCoroId()->getStorageSize(),
979 Shape.getRetconCoroId()->getStorageAlignment(),
980 true);
981
982 break;
983 }
984
985 switch (Shape.ABI) {
986
987
988
989
992
995 break;
996
997
998
999
1001 break;
1002
1003
1004
1005
1007 break;
1008 }
1009
1010 NewF->setAttributes(NewAttrs);
1011 NewF->setCallingConv(Shape.getResumeFunctionCC());
1012
1013
1015
1016
1017 for (CallInst *ResumeCall : Shape.SymmetricTransfers) {
1019 if (TTI.supportsTailCallFor(ResumeCall)) {
1020
1021
1023 }
1024
1025
1026
1030 Builder.CreateRetVoid();
1032 }
1033
1034 Builder.SetInsertPoint(&NewF->getEntryBlock().front());
1036
1037
1041
1042
1043 auto *NewVFrame = Builder.CreateBitCast(
1046 if (OldVFrame != NewVFrame)
1048
1049
1050
1051 for (Instruction *DummyArg : DummyArgs) {
1052 DummyArg->replaceAllUsesWith(PoisonValue::get(DummyArg->getType()));
1053 DummyArg->deleteValue();
1054 }
1055
1056 switch (Shape.ABI) {
1058
1059
1060
1061 if (Shape.SwitchLowering.HasFinalSuspend)
1063 break;
1067
1068
1070 "no active suspend when lowering a continuation-style coroutine");
1072 break;
1073 }
1074
1075
1077
1078
1080
1081
1083
1085
1086
1088}
1089
1091
1094
1095
1097
1098
1099
1102}
1103
1106
1109 auto *OrigRelativeFunOffset = FuncPtrStruct->getOperand(0);
1110 auto *OrigContextSize = FuncPtrStruct->getOperand(1);
1111 auto *NewContextSize = ConstantInt::get(OrigContextSize->getType(),
1114 FuncPtrStruct->getType(), OrigRelativeFunOffset, NewContextSize);
1115
1117}
1118
1120
1121 auto *SizeIntrin = Shape.CoroSizes.back();
1122 Module *M = SizeIntrin->getModule();
1124 return DL.getTypeAllocSize(Shape.FrameTy);
1125}
1126
1130
1135 }
1136
1138 return;
1139
1140
1141 auto *SizeIntrin = Shape.CoroSizes.back();
1142 auto *SizeConstant =
1144
1148 }
1149}
1150
1153
1154#ifndef NDEBUG
1155
1156
1157
1160#endif
1161}
1162
1163
1164
1166 auto *CoroBegin = Shape.CoroBegin;
1167 switch (Shape.ABI) {
1172 if (AllocInst) {
1174 auto *Frame = Builder.CreateAlloca(Shape.FrameTy);
1175 Frame->setAlignment(Shape.FrameAlign);
1176 AllocInst->replaceAllUsesWith(Builder.getFalse());
1177 AllocInst->eraseFromParent();
1178 CoroBegin->replaceAllUsesWith(Frame);
1179 } else {
1180 CoroBegin->replaceAllUsesWith(CoroBegin->getMem());
1181 }
1182
1183 break;
1184 }
1188 CoroBegin->replaceAllUsesWith(PoisonValue::get(CoroBegin->getType()));
1189 break;
1190 }
1191
1194}
1195
1196
1197
1198
1201
1203 continue;
1204
1206 return true;
1207 }
1208 return false;
1209}
1210
1214
1215 Set.insert(SaveBB);
1217
1218
1219
1220
1221 while (!Worklist.empty()) {
1223 Set.insert(BB);
1225 if (!Set.contains(Pred))
1227 }
1228
1229
1230 Set.erase(SaveBB);
1231 Set.erase(ResDesBB);
1232
1233 for (auto *BB : Set)
1235 return true;
1236
1237 return false;
1238}
1239
1241 auto *SaveBB = Save->getParent();
1242 auto *ResumeOrDestroyBB = ResumeOrDestroy->getParent();
1245
1246 if (SaveBB == ResumeOrDestroyBB)
1248
1249
1251 return true;
1252
1253
1255 {ResumeOrDestroyBB->getFirstNonPHIIt(), ResumeOrDestroyIt}))
1256 return true;
1257
1258
1260 return true;
1261
1262 return false;
1263}
1264
1265
1266
1270 if (!Prev) {
1271 auto *Pred = Suspend->getParent()->getSinglePredecessor();
1272 if (!Pred)
1273 return false;
1274 Prev = Pred->getTerminator();
1275 }
1276
1278 if (!CB)
1279 return false;
1280
1282
1283
1285 if (!SubFn)
1286 return false;
1287
1288
1289 if (SubFn->getFrame() != CoroBegin)
1290 return false;
1291
1292
1293
1294
1297 return false;
1298
1299
1300
1303 Save->eraseFromParent();
1304
1305
1308 }
1309
1310
1313
1314
1315 if (CalledValue != SubFn && CalledValue->user_empty())
1317 I->eraseFromParent();
1318
1319
1320 if (SubFn->user_empty())
1321 SubFn->eraseFromParent();
1322
1323 return true;
1324}
1325
1326
1328
1330 return;
1331
1333 size_t I = 0, N = S.size();
1334 if (N == 0)
1335 return;
1336
1337 size_t ChangedFinalIndex = std::numeric_limits<size_t>::max();
1338 while (true) {
1340
1341
1344 break;
1345
1347
1350 ChangedFinalIndex = I;
1351 }
1352
1353 continue;
1354 }
1356 break;
1357 }
1358 S.resize(N);
1359
1360
1361
1362 if (ChangedFinalIndex < N) {
1364 std::swap(S[ChangedFinalIndex], S.back());
1365 }
1366}
1367
1368namespace {
1369
1370struct SwitchCoroutineSplitter {
1371 static void split(Function &F, coro::Shape &Shape,
1372 SmallVectorImpl<Function *> &Clones,
1373 TargetTransformInfo &TTI) {
1374 assert(Shape.ABI == coro::ABI::Switch);
1375
1376
1377
1378
1379 createResumeEntryBlock(F, Shape);
1381 F, ".resume", Shape, coro::CloneKind::SwitchResume, TTI);
1383 F, ".destroy", Shape, coro::CloneKind::SwitchUnwind, TTI);
1385 F, ".cleanup", Shape, coro::CloneKind::SwitchCleanup, TTI);
1386
1390
1391
1392 updateCoroFrame(Shape, ResumeClone, DestroyClone, CleanupClone);
1393
1398
1399
1400
1401
1402 setCoroInfo(F, Shape, Clones);
1403 }
1404
1405
1406
1407
1408
1409
1410
1411
1412 static Function *createNoAllocVariant(Function &F, coro::Shape &Shape,
1413 SmallVectorImpl<Function *> &Clones) {
1414 assert(Shape.ABI == coro::ABI::Switch);
1415 auto *OrigFnTy = F.getFunctionType();
1416 auto OldParams = OrigFnTy->params();
1417
1419 NewParams.reserve(OldParams.size() + 1);
1420 NewParams.append(OldParams.begin(), OldParams.end());
1422
1423 auto *NewFnTy = FunctionType::get(OrigFnTy->getReturnType(), NewParams,
1424 OrigFnTy->isVarArg());
1426 Function::Create(NewFnTy, F.getLinkage(), F.getName() + ".noalloc");
1427
1429 unsigned int Idx = 0;
1430 for (const auto &I : F.args()) {
1431 VMap[&I] = NoAllocF->getArg(Idx++);
1432 }
1433
1434
1435 auto FrameIdx = NoAllocF->arg_size() - 1;
1438 CloneFunctionChangeType::LocalChangesOnly, Returns);
1439
1441 auto *NewCoroBegin =
1446 NewCoroBegin->replaceAllUsesWith(NoAllocF->getArg(FrameIdx));
1447 NewCoroBegin->eraseFromParent();
1448 }
1449
1451 M->getFunctionList().insert(M->end(), NoAllocF);
1452
1455
1456
1459 false);
1460
1462
1464
1465
1466 setCoroInfo(F, Shape, Clones);
1467
1468
1469
1471 return NoAllocF;
1472 }
1473
1474private:
1475
1476
1477 static void createResumeEntryBlock(Function &F, coro::Shape &Shape) {
1479
1480 DIBuilder DBuilder(*F.getParent(), false);
1481 DISubprogram *DIS = F.getSubprogram();
1482
1483
1484
1485 bool AddDebugLabels = DIS && DIS->getUnit() &&
1486 (DIS->getUnit()->getEmissionKind() ==
1487 DICompileUnit::DebugEmissionKind::FullDebug);
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1500
1503 auto *FrameTy = Shape.FrameTy;
1504 auto *GepIndex = Builder.CreateStructGEP(
1506 auto *Index = Builder.CreateLoad(Shape.getIndexType(), GepIndex, "index");
1508 Builder.CreateSwitch(Index, UnreachBB, Shape.CoroSuspends.size());
1510
1511
1512 size_t SuspendIndex = 0;
1515 ConstantInt *IndexVal = Shape.getIndex(SuspendIndex);
1516
1517
1518
1519
1520 auto *Save = S->getCoroSave();
1521 Builder.SetInsertPoint(Save);
1522 if (S->isFinal()) {
1523
1524
1526 } else {
1527 auto *GepIndex = Builder.CreateStructGEP(
1529 Builder.CreateStore(IndexVal, GepIndex);
1530 }
1531
1533 Save->eraseFromParent();
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559 auto *SuspendBB = S->getParent();
1560 auto *ResumeBB =
1561 SuspendBB->splitBasicBlock(S, "resume." + Twine(SuspendIndex));
1562 auto *LandingBB = ResumeBB->splitBasicBlock(
1563 S->getNextNode(), ResumeBB->getName() + Twine(".landing"));
1564 Switch->addCase(IndexVal, ResumeBB);
1565
1566 cast(SuspendBB->getTerminator())->setSuccessor(0, LandingBB);
1568 PN->insertBefore(LandingBB->begin());
1569 S->replaceAllUsesWith(PN);
1570 PN->addIncoming(Builder.getInt8(-1), SuspendBB);
1571 PN->addIncoming(S, ResumeBB);
1572
1573 if (AddDebugLabels) {
1574 if (DebugLoc SuspendLoc = S->getDebugLoc()) {
1575 std::string LabelName =
1576 ("__coro_resume_" + Twine(SuspendIndex)).str();
1577
1578
1579
1580
1581
1582 DILocation *DILoc = SuspendLoc;
1583 while (DILocation *InlinedAt = DILoc->getInlinedAt())
1584 DILoc = InlinedAt;
1585
1586 DILabel *ResumeLabel =
1587 DBuilder.createLabel(DIS, LabelName, DILoc->getFile(),
1588 SuspendLoc.getLine(), SuspendLoc.getCol(),
1589 true,
1590 SuspendIndex,
1591 false);
1592 DBuilder.insertLabel(ResumeLabel, DILoc, ResumeBB->begin());
1593 }
1594 }
1595
1596 ++SuspendIndex;
1597 }
1598
1599 Builder.SetInsertPoint(UnreachBB);
1600 Builder.CreateUnreachable();
1601 DBuilder.finalize();
1602
1604 }
1605
1606
1607 static void updateCoroFrame(coro::Shape &Shape, Function *ResumeFn,
1608 Function *DestroyFn, Function *CleanupFn) {
1610
1611 auto *ResumeAddr = Builder.CreateStructGEP(
1613 "resume.addr");
1614 Builder.CreateStore(ResumeFn, ResumeAddr);
1615
1616 Value *DestroyOrCleanupFn = DestroyFn;
1617
1619 if (CoroAllocInst *CA = CoroId->getCoroAlloc()) {
1620
1621
1622 DestroyOrCleanupFn = Builder.CreateSelect(CA, DestroyFn, CleanupFn);
1623 }
1624
1625 auto *DestroyAddr = Builder.CreateStructGEP(
1627 "destroy.addr");
1628 Builder.CreateStore(DestroyOrCleanupFn, DestroyAddr);
1629 }
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644 static void setCoroInfo(Function &F, coro::Shape &Shape,
1646
1647
1652 auto *ArrTy = ArrayType::get(Part->getType(), Args.size());
1653
1655 auto *GV = new GlobalVariable(*M, ConstVal->getType(), true,
1656 GlobalVariable::PrivateLinkage, ConstVal,
1657 F.getName() + Twine(".resumers"));
1658
1659
1660 LLVMContext &C = F.getContext();
1663 }
1664};
1665
1666}
1667
1671 auto &Context = Suspend->getParent()->getParent()->getContext();
1673
1675 auto *Val = Builder.CreateBitOrPointerCast(Continuation, Int8PtrTy);
1676 ResumeIntrinsic->replaceAllUsesWith(Val);
1677 ResumeIntrinsic->eraseFromParent();
1680}
1681
1682
1686 size_t ArgIdx = 0;
1687 for (auto *paramTy : FnTy->params()) {
1689 if (paramTy != FnArgs[ArgIdx]->getType())
1691 Builder.CreateBitOrPointerCast(FnArgs[ArgIdx], paramTy));
1692 else
1693 CallArgs.push_back(FnArgs[ArgIdx]);
1694 ++ArgIdx;
1695 }
1696}
1697
1703
1704
1707
1708 auto *TailCall = Builder.CreateCall(FnTy, MustTailCallFn, CallArgs);
1709
1710 if (TTI.supportsTailCallFor(TailCall)) {
1712 }
1713 TailCall->setDebugLoc(Loc);
1714 TailCall->setCallingConv(MustTailCallFn->getCallingConv());
1715 return TailCall;
1716}
1717
1723
1724
1725 F.removeFnAttr(Attribute::NoReturn);
1726 F.removeRetAttr(Attribute::NoAlias);
1727 F.removeRetAttr(Attribute::NonNull);
1728
1729 auto &Context = F.getContext();
1731
1732 auto *Id = Shape.getAsyncCoroId();
1734
1735 auto *FramePtr = Id->getStorage();
1736 FramePtr = Builder.CreateBitOrPointerCast(FramePtr, Int8PtrTy);
1737 FramePtr = Builder.CreateConstInBoundsGEP1_32(
1739 "async.ctx.frameptr");
1740
1741
1742 {
1743
1747 }
1748
1749
1750 auto NextF = std::next(F.getIterator());
1751
1752
1756
1757
1758 auto ResumeNameSuffix = ".resume.";
1759 auto ProjectionFunctionName =
1760 Suspend->getAsyncContextProjectionFunction()->getName();
1761 bool UseSwiftMangling = false;
1762 if (ProjectionFunctionName == "__swift_async_resume_project_context") {
1763 ResumeNameSuffix = "TQ";
1764 UseSwiftMangling = true;
1765 } else if (ProjectionFunctionName == "__swift_async_resume_get_context") {
1766 ResumeNameSuffix = "TY";
1767 UseSwiftMangling = true;
1768 }
1771 UseSwiftMangling ? ResumeNameSuffix + Twine(Idx) + "_"
1772 : ResumeNameSuffix + Twine(Idx),
1773 NextF, Suspend);
1775
1776
1777
1778 auto *SuspendBB = Suspend->getParent();
1779 auto *NewSuspendBB = SuspendBB->splitBasicBlock(Suspend);
1780 auto *Branch = cast(SuspendBB->getTerminator());
1781
1782
1783 auto *ReturnBB =
1785 Branch->setSuccessor(0, ReturnBB);
1786
1788
1789
1790 auto *Fn = Suspend->getMustTailCallFunction();
1795 FnArgs, Builder);
1796 Builder.CreateRetVoid();
1799
1800
1802 }
1803
1805
1807 auto *Suspend = CS;
1808 auto *Clone = Clones[Idx];
1809
1811 Suspend, TTI);
1812 }
1813}
1814
1820
1821
1822
1823 F.removeFnAttr(Attribute::NoReturn);
1824 F.removeRetAttr(Attribute::NoAlias);
1825 F.removeRetAttr(Attribute::NonNull);
1826
1827
1828 auto *Id = Shape.getRetconCoroId();
1829 Value *RawFramePtr;
1830 if (Shape.RetconLowering.IsFrameInlineInStorage) {
1831 RawFramePtr = Id->getStorage();
1832 } else {
1834
1835
1837 auto Size = DL.getTypeAllocSize(Shape.FrameTy);
1838
1839
1840
1841
1842 RawFramePtr = Shape.emitAlloc(Builder, Builder.getInt64(Size), nullptr);
1843 RawFramePtr =
1844 Builder.CreateBitCast(RawFramePtr, Shape.CoroBegin->getType());
1845
1846
1847 Builder.CreateStore(RawFramePtr, Id->getStorage());
1848 }
1849
1850
1851 {
1852
1854 Shape.CoroBegin->replaceAllUsesWith(RawFramePtr);
1856 }
1857
1858
1860 PHINode *ContinuationPhi = nullptr;
1862
1863
1864 auto NextF = std::next(F.getIterator());
1865
1866
1870
1871
1873 F, Shape, ".resume." + Twine(Idx), NextF, nullptr);
1875
1876
1877
1878 auto SuspendBB = Suspend->getParent();
1879 auto NewSuspendBB = SuspendBB->splitBasicBlock(Suspend);
1881
1882
1883 if (!ReturnBB) {
1884
1885 ReturnBB =
1887 Shape.RetconLowering.ReturnBlock = ReturnBB;
1888
1890
1891
1892 ContinuationPhi =
1893 Builder.CreatePHI(Continuation->getType(), Shape.CoroSuspends.size());
1894
1895
1897
1898
1899 for (auto *ResultTy : Shape.getRetconResultTypes())
1901 Builder.CreatePHI(ResultTy, Shape.CoroSuspends.size()));
1902
1903
1904 auto RetTy = F.getReturnType();
1905
1906
1907
1908
1909 auto CastedContinuationTy =
1910 (ReturnPHIs.empty() ? RetTy : RetTy->getStructElementType(0));
1911 auto *CastedContinuation =
1912 Builder.CreateBitCast(ContinuationPhi, CastedContinuationTy);
1913
1914 Value *RetV = CastedContinuation;
1915 if (!ReturnPHIs.empty()) {
1916 auto ValueIdx = 0;
1918 RetV = Builder.CreateInsertValue(RetV, CastedContinuation, ValueIdx++);
1919
1920 for (auto Phi : ReturnPHIs)
1921 RetV = Builder.CreateInsertValue(RetV, Phi, ValueIdx++);
1922 }
1923
1924 Builder.CreateRet(RetV);
1925 }
1926
1927
1928 Branch->setSuccessor(0, ReturnBB);
1929 assert(ContinuationPhi);
1931 for (auto [Phi, VUse] :
1933 Phi->addIncoming(VUse, SuspendBB);
1934 }
1935
1937
1939 auto Suspend = CS;
1940 auto Clone = Clones[Idx];
1941
1943 Suspend, TTI);
1944 }
1945}
1946
1947namespace {
1950
1951public:
1952 PrettyStackTraceFunction(Function &F) : F(F) {}
1954 OS << "While splitting coroutine ";
1955 F.printAsOperand(OS, false, F.getParent());
1956 OS << "\n";
1957 }
1958};
1959}
1960
1961
1964 for (auto *End : Shape.CoroEnds) {
1966 }
1967 } else {
1970 }
1971}
1972
1975 auto &Ctx = II->getContext();
1977 II->eraseFromParent();
1978 }
1979}
1980
1982 for (auto *U : F.users()) {
1984 auto *Caller = CB->getFunction();
1985 if (Caller && Caller->isPresplitCoroutine() &&
1986 CB->hasFnAttr(llvm::Attribute::CoroElideSafe))
1987 return true;
1988 }
1989 }
1990 return false;
1991}
1992
1996 SwitchCoroutineSplitter::split(F, Shape, Clones, TTI);
1997}
1998
2001 bool OptimizeFrame) {
2002 PrettyStackTraceFunction prettyStackTrace(F);
2003
2004 auto &Shape = ABI.Shape;
2006
2008
2010
2012 ABI.buildCoroutineFrame(OptimizeFrame);
2014
2015 bool isNoSuspendCoroutine = Shape.CoroSuspends.empty();
2016
2017 bool shouldCreateNoAllocVariant =
2020
2021
2022
2023 if (isNoSuspendCoroutine) {
2025 } else {
2026 ABI.splitCoroutine(F, Shape, Clones, TTI);
2027 }
2028
2029
2030
2032
2033
2034
2035
2040
2043
2044 if (shouldCreateNoAllocVariant)
2045 SwitchCoroutineSplitter::createNoAllocVariant(F, Shape, Clones);
2046}
2047
2053
2054 auto *CurrentSCC = &C;
2055 if (!Clones.empty()) {
2056 switch (Shape.ABI) {
2058
2059
2060 for (Function *Clone : Clones)
2062 break;
2066
2067
2068 if (!Clones.empty())
2070 break;
2071 }
2072
2073
2075 UR, FAM);
2076 }
2077
2078
2079
2082 AM, UR, FAM);
2083 return *CurrentSCC;
2084}
2085
2086
2089 auto CastFn = Prepare->getArgOperand(0);
2091
2092
2093
2094
2095
2096
2097
2099
2101 if (!Cast || Cast->getType() != Fn->getType())
2102 continue;
2103
2104
2105 Cast->replaceAllUsesWith(Fn);
2106 Cast->eraseFromParent();
2107 }
2108
2109
2110
2113
2114
2116 if (!Cast->use_empty())
2117 break;
2118 CastFn = Cast->getOperand(0);
2119 Cast->eraseFromParent();
2120 }
2121}
2122
2135
2139 auto *PrepareFn = M.getFunction(Name);
2140 if (PrepareFn && !PrepareFn->use_empty())
2142}
2143
2144static std::unique_ptrcoro::BaseABI
2146 std::function<bool(Instruction &)> IsMatCallback,
2150 if (CustomABI >= GenCustomABIs.size())
2151 llvm_unreachable("Custom ABI not found amoung those specified");
2152 return GenCustomABIs[CustomABI](F, S);
2153 }
2154
2155 switch (S.ABI) {
2157 return std::make_uniquecoro::SwitchABI(F, S, IsMatCallback);
2159 return std::make_uniquecoro::AsyncABI(F, S, IsMatCallback);
2161 return std::make_uniquecoro::AnyRetconABI(F, S, IsMatCallback);
2163 return std::make_uniquecoro::AnyRetconABI(F, S, IsMatCallback);
2164 }
2166}
2167
2170 std::unique_ptrcoro::BaseABI ABI =
2172 ABI->init();
2173 return ABI;
2174 }),
2175 OptimizeFrame(OptimizeFrame) {}
2176
2180 std::unique_ptrcoro::BaseABI ABI =
2182 ABI->init();
2183 return ABI;
2184 }),
2185 OptimizeFrame(OptimizeFrame) {}
2186
2187
2188
2192 std::unique_ptrcoro::BaseABI ABI =
2194 ABI->init();
2195 return ABI;
2196 }),
2197 OptimizeFrame(OptimizeFrame) {}
2198
2199
2200
2202 std::function<bool(Instruction &)> IsMatCallback,
2205 std::unique_ptrcoro::BaseABI ABI =
2206 CreateNewABI(F, S, IsMatCallback, GenCustomABIs);
2207 ABI->init();
2208 return ABI;
2209 }),
2210 OptimizeFrame(OptimizeFrame) {}
2211
2215
2216
2217
2218 Module &M = *C.begin()->getFunction().getParent();
2219 auto &FAM =
2221
2222
2226
2227
2230 if (N.getFunction().isPresplitCoroutine())
2232
2233 if (Coroutines.empty() && PrepareFns.empty())
2235
2236 auto *CurrentSCC = &C;
2237
2240 LLVM_DEBUG(dbgs() << "CoroSplit: Processing coroutine '" << F.getName()
2241 << "\n");
2242
2243
2244
2245
2247
2250 continue;
2251
2252 F.setSplittedCoroutine();
2253
2254 std::unique_ptrcoro::BaseABI ABI = CreateAndInitABI(F, Shape);
2255
2260 *N, Shape, Clones, *CurrentSCC, CG, AM, UR, FAM);
2261
2263 ORE.emit([&]() {
2265 << "Split '" << ore::NV("function", F.getName())
2266 << "' (frame_size=" << ore::NV("frame_size", Shape.FrameSize)
2268 });
2269
2271
2272 UR.CWorklist.insert(CurrentSCC);
2273 for (Function *Clone : Clones)
2276
2277
2279 }
2280 }
2281
2282 for (auto *PrepareFn : PrepareFns) {
2284 }
2285
2287}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
amdgpu aa AMDGPU Address space based Alias Analysis Wrapper
AMDGPU Lower Kernel Arguments
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
Expand Atomic instructions
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
This file provides interfaces used to manipulate a call graph, regardless if it is a "old style" Call...
This file provides interfaces used to build and manipulate a call graph, which is a very useful tool ...
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static void addSwiftSelfAttrs(AttributeList &Attrs, LLVMContext &Context, unsigned ParamIndex)
Definition CoroSplit.cpp:867
static bool hasCallsBetween(Instruction *Save, Instruction *ResumeOrDestroy)
Definition CoroSplit.cpp:1240
static LazyCallGraph::SCC & updateCallGraphAfterCoroutineSplit(LazyCallGraph::Node &N, const coro::Shape &Shape, const SmallVectorImpl< Function * > &Clones, LazyCallGraph::SCC &C, LazyCallGraph &CG, CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR, FunctionAnalysisManager &FAM)
Definition CoroSplit.cpp:2048
static void replaceFallthroughCoroEnd(AnyCoroEndInst *End, const coro::Shape &Shape, Value *FramePtr, bool InRamp, CallGraph *CG)
Replace a non-unwind call to llvm.coro.end.
Definition CoroSplit.cpp:214
static void replaceSwiftErrorOps(Function &F, coro::Shape &Shape, ValueToValueMapTy *VMap)
Definition CoroSplit.cpp:569
static void replaceCoroEnd(AnyCoroEndInst *End, const coro::Shape &Shape, Value *FramePtr, bool InRamp, CallGraph *CG)
Definition CoroSplit.cpp:384
static void addAsyncContextAttrs(AttributeList &Attrs, LLVMContext &Context, unsigned ParamIndex)
Definition CoroSplit.cpp:860
static void maybeFreeRetconStorage(IRBuilder<> &Builder, const coro::Shape &Shape, Value *FramePtr, CallGraph *CG)
Definition CoroSplit.cpp:158
static bool hasCallsInBlocksBetween(BasicBlock *SaveBB, BasicBlock *ResDesBB)
Definition CoroSplit.cpp:1211
static Function * createCloneDeclaration(Function &OrigF, coro::Shape &Shape, const Twine &Suffix, Module::iterator InsertBefore, AnyCoroSuspendInst *ActiveSuspend)
Definition CoroSplit.cpp:444
static FunctionType * getFunctionTypeFromAsyncSuspend(AnyCoroSuspendInst *Suspend)
Definition CoroSplit.cpp:436
static void updateScopeLine(Instruction *ActiveSuspend, DISubprogram &SPToUpdate)
Adjust the scope line of the funclet to the first line number after the suspend point.
Definition CoroSplit.cpp:802
static void removeCoroIsInRampFromRampFunction(const coro::Shape &Shape)
Definition CoroSplit.cpp:1973
static void addPrepareFunction(const Module &M, SmallVectorImpl< Function * > &Fns, StringRef Name)
Definition CoroSplit.cpp:2136
static SmallVector< DbgVariableRecord * > collectDbgVariableRecords(Function &F)
Returns all debug records in F.
Definition CoroSplit.cpp:627
static void simplifySuspendPoints(coro::Shape &Shape)
Definition CoroSplit.cpp:1327
static void addFramePointerAttrs(AttributeList &Attrs, LLVMContext &Context, unsigned ParamIndex, uint64_t Size, Align Alignment, bool NoAlias)
Definition CoroSplit.cpp:845
static bool hasSafeElideCaller(Function &F)
Definition CoroSplit.cpp:1981
static bool replaceAllPrepares(Function *PrepareFn, LazyCallGraph &CG, LazyCallGraph::SCC &C)
Definition CoroSplit.cpp:2123
static void replaceFrameSizeAndAlignment(coro::Shape &Shape)
Definition CoroSplit.cpp:1127
static std::unique_ptr< coro::BaseABI > CreateNewABI(Function &F, coro::Shape &S, std::function< bool(Instruction &)> IsMatCallback, const SmallVector< CoroSplitPass::BaseABITy > GenCustomABIs)
Definition CoroSplit.cpp:2145
static bool replaceCoroEndAsync(AnyCoroEndInst *End)
Replace an llvm.coro.end.async.
Definition CoroSplit.cpp:171
static void doSplitCoroutine(Function &F, SmallVectorImpl< Function * > &Clones, coro::BaseABI &ABI, TargetTransformInfo &TTI, bool OptimizeFrame)
Definition CoroSplit.cpp:1999
static bool hasCallsInBlockBetween(iterator_range< BasicBlock::iterator > R)
Definition CoroSplit.cpp:1199
static bool simplifySuspendPoint(CoroSuspendInst *Suspend, CoroBeginInst *CoroBegin)
Definition CoroSplit.cpp:1267
static void removeCoroEndsFromRampFunction(const coro::Shape &Shape)
Remove calls to llvm.coro.end in the original function.
Definition CoroSplit.cpp:1962
static void markCoroutineAsDone(IRBuilder<> &Builder, const coro::Shape &Shape, Value *FramePtr)
Definition CoroSplit.cpp:313
static void updateAsyncFuncPointerContextSize(coro::Shape &Shape)
Definition CoroSplit.cpp:1104
static void coerceArguments(IRBuilder<> &Builder, FunctionType *FnTy, ArrayRef< Value * > FnArgs, SmallVectorImpl< Value * > &CallArgs)
Coerce the arguments in FnArgs according to FnTy in CallArgs.
Definition CoroSplit.cpp:1683
static void replaceUnwindCoroEnd(AnyCoroEndInst *End, const coro::Shape &Shape, Value *FramePtr, bool InRamp, CallGraph *CG)
Replace an unwind call to llvm.coro.end.
Definition CoroSplit.cpp:347
static void lowerAwaitSuspend(IRBuilder<> &Builder, CoroAwaitSuspendInst *CB, coro::Shape &Shape)
Definition CoroSplit.cpp:86
static void lowerAwaitSuspends(Function &F, coro::Shape &Shape)
Definition CoroSplit.cpp:152
static void handleNoSuspendCoroutine(coro::Shape &Shape)
Definition CoroSplit.cpp:1165
static void postSplitCleanup(Function &F)
Definition CoroSplit.cpp:1151
static void replacePrepare(CallInst *Prepare, LazyCallGraph &CG, LazyCallGraph::SCC &C)
Replace a call to llvm.coro.prepare.retcon.
Definition CoroSplit.cpp:2087
static TypeSize getFrameSizeForShape(coro::Shape &Shape)
Definition CoroSplit.cpp:1119
static void replaceAsyncResumeFunction(CoroSuspendAsyncInst *Suspend, Value *Continuation)
Definition CoroSplit.cpp:1668
This file defines the DenseMap class.
This file contains constants used for implementing Dwarf debug support.
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
Module.h This file contains the declarations for the Module class.
Implements a lazy call graph analysis and related passes for the new pass manager.
Machine Check Debug Module
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
This file provides a priority worklist.
const SmallVectorImpl< MachineOperand > & Cond
Remove Loads Into Fake Uses
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
static SymbolRef::Type getType(const Symbol *Sym)
This pass exposes codegen information to IR-level passes.
static const unsigned FramePtr
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
CoroAllocInst * getCoroAlloc()
This class represents an incoming formal argument to a Function.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
LLVM Basic Block Representation.
const Function * getParent() const
Return the enclosing method, or null if none.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="", bool Before=false)
Split the basic block into two basic blocks at the specified instruction.
InstListType::iterator iterator
Instruction iterators...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
static BranchInst * Create(BasicBlock *IfTrue, InsertPosition InsertBefore=nullptr)
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
std::optional< OperandBundleUse > getOperandBundle(StringRef Name) const
Return an operand bundle by name, if present.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
Value * getCalledOperand() const
Value * getArgOperand(unsigned i) const
AttributeList getAttributes() const
Return the attributes for this call.
The basic data container for the call graph of a Module of IR.
This class represents a function call, abstracting a target machine's calling convention.
static LLVM_ABI Constant * get(ArrayType *T, ArrayRef< Constant * > V)
static LLVM_ABI Constant * getPointerCast(Constant *C, Type *Ty)
Create a BitCast, AddrSpaceCast, or a PtrToInt cast constant expression.
This is the shared class of boolean and integer constants.
static LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)
static LLVM_ABI ConstantInt * getFalse(LLVMContext &Context)
static LLVM_ABI ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
static LLVM_ABI Constant * get(StructType *T, ArrayRef< Constant * > V)
static LLVM_ABI ConstantTokenNone * get(LLVMContext &Context)
Return the ConstantTokenNone.
This represents the llvm.coro.align instruction.
This represents the llvm.coro.await.suspend.{void,bool,handle} instructions.
Value * getAwaiter() const
Function * getWrapperFunction() const
This class represents the llvm.coro.begin or llvm.coro.begin.custom.abi instructions.
bool hasCustomABI() const
void setInfo(Constant *C)
This represents the llvm.coro.size instruction.
This represents the llvm.coro.suspend.async instruction.
CoroAsyncResumeInst * getResumeFunction() const
This represents the llvm.coro.suspend instruction.
CoroSaveInst * getCoroSave() const
Subprogram description. Uses SubclassData1.
A parsed version of the target data layout string in and methods for querying it.
Record of a variable value-assignment, aka a non instruction representation of the dbg....
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
LLVM_ABI bool isReachableFromEntry(const Use &U) const
Provide an overload for a Use.
This class represents a freeze function that returns random concrete value if an operand is either a ...
A proxy from a FunctionAnalysisManager to an SCC.
Class to represent function types.
Type * getReturnType() const
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Intrinsic::ID getIntrinsicID() const LLVM_READONLY
getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
AttributeList getAttributes() const
Return the attribute list for this Function.
void setAttributes(AttributeList Attrs)
Set the attribute list for this Function.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Argument * getArg(unsigned i) const
void setLinkage(LinkageTypes LT)
Module * getParent()
Get the module that this global value is contained inside of...
PointerType * getType() const
Global values are always pointers.
@ InternalLinkage
Rename collisions when linking (static functions).
@ ExternalLinkage
Externally visible function.
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
LLVM_ABI void setInitializer(Constant *InitVal)
setInitializer - Sets the initializer for this global variable, removing any existing initializer if ...
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
This class captures the data input to the InlineFunction call, and records the auxiliary results prod...
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
This is an important class for using LLVM in a threaded context.
A node in the call graph.
An SCC of the call graph.
A lazily constructed view of the call graph of a module.
LLVM_ABI void addSplitFunction(Function &OriginalFunction, Function &NewFunction)
Add a new function split/outlined from an existing function.
LLVM_ABI void addSplitRefRecursiveFunctions(Function &OriginalFunction, ArrayRef< Function * > NewFunctions)
Add new ref-recursive functions split/outlined from an existing function.
Node & get(Function &F)
Get a graph node for a given function, scanning it to populate the graph data as necessary.
SCC * lookupSCC(Node &N) const
Lookup a function's SCC in the graph.
static std::enable_if_t< std::is_base_of< MDNode, T >::value, T * > replaceWithUniqued(std::unique_ptr< T, TempMDNodeDeleter > N)
Replace a temporary node with a uniqued one.
static LLVM_ABI MDString * get(LLVMContext &Context, StringRef Str)
A Module instance is used to store all the information related to an LLVM module.
FunctionListType::iterator iterator
The Function iterators.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the default address space (address sp...
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PrettyStackTraceEntry - This class is used to represent a frame of the "pretty" stack trace that is d...
Return a value (possibly void), from a function.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void reserve(size_type N)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
LLVM_ABI Type * getTypeAtIndex(const Value *V) const
Given an index value into the type, return the type of the element.
Analysis pass providing the TargetTransformInfo.
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
Value handle that tracks a Value across RAUW.
ValueTy * getValPtr() const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
A Use represents the edge between a Value definition and its users.
void setOperand(unsigned i, Value *Val)
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
iterator_range< user_iterator > users()
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
LLVM_ABI LLVMContext & getContext() const
All values hold a context through their type.
iterator_range< use_iterator > uses()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
void splitCoroutine(Function &F, coro::Shape &Shape, SmallVectorImpl< Function * > &Clones, TargetTransformInfo &TTI) override
Definition CoroSplit.cpp:1815
void splitCoroutine(Function &F, coro::Shape &Shape, SmallVectorImpl< Function * > &Clones, TargetTransformInfo &TTI) override
Definition CoroSplit.cpp:1718
void replaceSwiftErrorOps()
Definition CoroSplit.cpp:636
void salvageDebugInfo()
Definition CoroSplit.cpp:640
AnyCoroSuspendInst * ActiveSuspend
The active suspend instruction; meaningful only for continuation and async ABIs.
Value * deriveNewFramePointer()
Derive the value of the new frame pointer.
Definition CoroSplit.cpp:742
void replaceEntryBlock()
Definition CoroSplit.cpp:673
void replaceCoroSuspends()
Definition CoroSplit.cpp:514
void handleFinalSuspend()
Definition CoroSplit.cpp:402
TargetTransformInfo & TTI
static Function * createClone(Function &OrigF, const Twine &Suffix, coro::Shape &Shape, Function *NewF, AnyCoroSuspendInst *ActiveSuspend, TargetTransformInfo &TTI)
Create a clone for a continuation lowering.
void replaceCoroIsInRamp()
Definition CoroSplit.cpp:560
void replaceCoroEnds()
Definition CoroSplit.cpp:551
bool isSwitchDestroyFunction()
void replaceRetconOrAsyncSuspendUses()
Replace uses of the active llvm.coro.suspend.retcon/async call with the arguments to the continuation...
Definition CoroSplit.cpp:466
virtual void create()
Clone the body of the original function into a resume function of some sort.
Definition CoroSplit.cpp:876
void splitCoroutine(Function &F, coro::Shape &Shape, SmallVectorImpl< Function * > &Clones, TargetTransformInfo &TTI) override
Definition CoroSplit.cpp:1993
static Function * createClone(Function &OrigF, const Twine &Suffix, coro::Shape &Shape, CloneKind FKind, TargetTransformInfo &TTI)
Create a clone for a switch lowering.
void create() override
Clone the body of the original function into a resume function of some sort.
Definition CoroSplit.cpp:1090
const ParentTy * getParent() const
self_iterator getIterator()
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
A range adaptor for a pair of iterators.
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ C
The default llvm calling convention, compatible with C.
@ Async
The "async continuation" lowering, where each suspend point creates a single continuation function.
@ RetconOnce
The "unique returned-continuation" lowering, where each suspend point creates a single continuation f...
@ Retcon
The "returned-continuation" lowering, where each suspend point creates a single continuation function...
@ Switch
The "resume-switch" lowering, where there are separate resume and destroy functions that are shared b...
void suppressCoroAllocs(CoroIdInst *CoroId)
Replaces all @llvm.coro.alloc intrinsics calls associated with a given call @llvm....
void normalizeCoroutine(Function &F, coro::Shape &Shape, TargetTransformInfo &TTI)
CallInst * createMustTailCall(DebugLoc Loc, Function *MustTailCallFn, TargetTransformInfo &TTI, ArrayRef< Value * > Arguments, IRBuilder<> &)
Definition CoroSplit.cpp:1698
void replaceCoroFree(CoroIdInst *CoroId, bool Elide)
LLVM_ABI bool isTriviallyMaterializable(Instruction &I)
@ SwitchCleanup
The shared cleanup function for a switch lowering.
@ Continuation
An individual continuation function.
void salvageDebugInfo(SmallDenseMap< Argument *, AllocaInst *, 4 > &ArgToAllocaMap, DbgVariableRecord &DVR, bool UseEntryValue)
Attempts to rewrite the location operand of debug records in terms of the coroutine frame pointer,...
DiagnosticInfoOptimizationBase::Argument NV
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
auto cast_if_present(const Y &Val)
cast_if_present - Functionally identical to cast, except that a null value is accepted.
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI InlineResult InlineFunction(CallBase &CB, InlineFunctionInfo &IFI, bool MergeAttributes=false, AAResults *CalleeAAR=nullptr, bool InsertLifetime=true, Function *ForwardVarArgsTo=nullptr, OptimizationRemarkEmitter *ORE=nullptr)
This function inlines the called function into the basic block of the caller.
detail::zippy< detail::zip_first, T, U, Args... > zip_equal(T &&t, U &&u, Args &&...args)
zip iterator that assumes that all iteratees have the same length.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
LLVM_ABI bool verifyFunction(const Function &F, raw_ostream *OS=nullptr)
Check a function for errors, useful for use when debugging a pass.
LLVM_ABI LazyCallGraph::SCC & updateCGAndAnalysisManagerForFunctionPass(LazyCallGraph &G, LazyCallGraph::SCC &C, LazyCallGraph::Node &N, CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR, FunctionAnalysisManager &FAM)
Helper to update the call graph after running a function pass.
LLVM_ABI LazyCallGraph::SCC & updateCGAndAnalysisManagerForCGSCCPass(LazyCallGraph &G, LazyCallGraph::SCC &C, LazyCallGraph::Node &N, CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR, FunctionAnalysisManager &FAM)
Helper to update the call graph after running a CGSCC pass.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
bool isa_and_nonnull(const Y &Val)
AnalysisManager< LazyCallGraph::SCC, LazyCallGraph & > CGSCCAnalysisManager
The CGSCC analysis manager.
auto dyn_cast_or_null(const Y &Val)
LLVM_ABI BasicBlock::iterator skipDebugIntrinsics(BasicBlock::iterator It)
Advance It while it points to a debug instruction and return the result.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
iterator_range< SplittingIterator > split(StringRef Str, StringRef Separator)
Split the specified string over a separator and return a range-compatible iterable over its partition...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI unsigned changeToUnreachable(Instruction *I, bool PreserveLCSSA=false, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr)
Insert an unreachable instruction before the specified instruction, making it and the rest of the cod...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
ValueMap< const Value *, WeakTrackingVH > ValueToValueMapTy
LLVM_ABI void CloneFunctionInto(Function *NewFunc, const Function *OldFunc, ValueToValueMapTy &VMap, CloneFunctionChangeType Changes, SmallVectorImpl< ReturnInst * > &Returns, const char *NameSuffix="", ClonedCodeInfo *CodeInfo=nullptr, ValueMapTypeRemapper *TypeMapper=nullptr, ValueMaterializer *Materializer=nullptr)
Clone OldFunc into NewFunc, transforming the old arguments into references to VMap values.
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.
auto predecessors(const MachineBasicBlock *BB)
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
static auto filterDbgVars(iterator_range< simple_ilist< DbgRecord >::iterator > R)
Filter the DbgRecord range to DbgVariableRecord types only and downcast.
LLVM_ABI bool removeUnreachableBlocks(Function &F, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr)
Remove all blocks that can not be reached from the function's entry.
LLVM_ABI bool isPotentiallyReachable(const Instruction *From, const Instruction *To, const SmallPtrSetImpl< BasicBlock * > *ExclusionSet=nullptr, const DominatorTree *DT=nullptr, const LoopInfo *LI=nullptr)
Determine whether instruction 'To' is reachable from 'From', without passing through any blocks in Ex...
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Support structure for SCC passes to communicate updates the call graph back to the CGSCC pass manager...
SmallPriorityWorklist< LazyCallGraph::SCC *, 1 > & CWorklist
Worklist of the SCCs queued for processing.
LLVM_ABI PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, CGSCCUpdateResult &UR)
Definition CoroSplit.cpp:2212
LLVM_ABI CoroSplitPass(bool OptimizeFrame=false)
Definition CoroSplit.cpp:2168
BaseABITy CreateAndInitABI
CallInst * makeSubFnCall(Value *Arg, int Index, Instruction *InsertPt)
GlobalVariable * AsyncFuncPointer
bool IsFrameInlineInStorage
SwitchInst * ResumeSwitch
BasicBlock * ResumeEntryBlock
SmallVector< CallInst *, 2 > SymmetricTransfers
SmallVector< CoroAwaitSuspendInst *, 4 > CoroAwaitSuspends
AsyncLoweringStorage AsyncLowering
FunctionType * getResumeFunctionType() const
IntegerType * getIndexType() const
CoroIdInst * getSwitchCoroId() const
SmallVector< CoroSizeInst *, 2 > CoroSizes
SmallVector< AnyCoroSuspendInst *, 4 > CoroSuspends
ConstantInt * getIndex(uint64_t Value) const
SwitchLoweringStorage SwitchLowering
CoroBeginInst * CoroBegin
BasicBlock::iterator getInsertPtAfterFramePtr() const
SmallVector< CoroIsInRampInst *, 2 > CoroIsInRampInsts
LLVM_ABI void emitDealloc(IRBuilder<> &Builder, Value *Ptr, CallGraph *CG) const
Deallocate memory according to the rules of the active lowering.
RetconLoweringStorage RetconLowering
SmallVector< CoroAlignInst *, 2 > CoroAligns
SmallVector< AnyCoroEndInst *, 4 > CoroEnds
SmallVector< CallInst *, 2 > SwiftErrorOps
unsigned getSwitchIndexField() const