LLVM 20.0.0git
Classes | Namespaces | Macros | Typedefs | Enumerations | Functions | Variables
CoroFrame.cpp File Reference
#include "CoroInternal.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Analysis/CFG.h"
#include "llvm/Analysis/PtrUseVisitor.h"
#include "llvm/Analysis/StackLifetime.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/OptimizedStructLayout.h"
#include "llvm/Support/circular_raw_ostream.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Transforms/Utils/PromoteMemToReg.h"
#include <algorithm>
#include <deque>
#include <optional>

Go to the source code of this file.

Classes

struct  llvm::GraphTraits< RematGraph * >
 

Namespaces

namespace  llvm
 This is an optimization pass for GlobalISel generic memory operations.
 

Macros

#define DEBUG_TYPE   "coro-suspend-crossing"
 
#define DEBUG_TYPE   "coro-frame"
 

Typedefs

typedef SmallPtrSet< BasicBlock *, 8 > VisitedBlocksSet
 

Enumerations

enum  { SmallVectorThreshold = 32 }
 

Functions

static void dumpSpills (StringRef Title, const SpillInfo &Spills)
 
static void dumpRemats (StringRef Title, const SmallMapVector< Instruction *, std::unique_ptr< RematGraph >, 8 > &RM)
 
static void dumpAllocas (const SmallVectorImpl< AllocaInfo > &Allocas)
 
static void cacheDIVar (FrameDataInfo &FrameData, DenseMap< Value *, DILocalVariable * > &DIVarCache)
 
static StringRef solveTypeName (Type *Ty)
 Create name for Type.
 
static DITypesolveDIType (DIBuilder &Builder, Type *Ty, const DataLayout &Layout, DIScope *Scope, unsigned LineNum, DenseMap< Type *, DIType * > &DITypeCache)
 
static void buildFrameDebugInfo (Function &F, coro::Shape &Shape, FrameDataInfo &FrameData)
 Build artificial debug info for C++ coroutine frames to allow users to inspect the contents of the frame directly.
 
static StructTypebuildFrameType (Function &F, coro::Shape &Shape, FrameDataInfo &FrameData)
 
static InstructionsplitBeforeCatchSwitch (CatchSwitchInst *CatchSwitch)
 
static void insertSpills (const FrameDataInfo &FrameData, coro::Shape &Shape)
 
static void movePHIValuesToInsertedBlock (BasicBlock *SuccBB, BasicBlock *InsertedBB, BasicBlock *PredBB, PHINode *UntilPHI=nullptr)
 
static void rewritePHIsForCleanupPad (BasicBlock *CleanupPadBB, CleanupPadInst *CleanupPad)
 
static void cleanupSinglePredPHIs (Function &F)
 
static void rewritePHIs (BasicBlock &BB)
 
static void rewritePHIs (Function &F)
 
static bool isCoroutineStructureIntrinsic (Instruction &I)
 
static void rewriteMaterializableInstructions (const SmallMapVector< Instruction *, std::unique_ptr< RematGraph >, 8 > &AllRemats)
 
static BasicBlocksplitBlockIfNotFirst (Instruction *I, const Twine &Name)
 
static void splitAround (Instruction *I, const Twine &Name)
 
static bool isSuspendBlock (BasicBlock *BB)
 
static bool isSuspendReachableFrom (BasicBlock *From, VisitedBlocksSet &VisitedOrFreeBBs)
 Does control flow starting at the given block ever reach a suspend instruction before reaching a block in VisitedOrFreeBBs?
 
static bool isLocalAlloca (CoroAllocaAllocInst *AI)
 Is the given alloca "local", i.e.
 
static bool willLeaveFunctionImmediatelyAfter (BasicBlock *BB, unsigned depth=3)
 After we split the coroutine, will the given basic block be along an obvious exit path for the resumption function?
 
static bool localAllocaNeedsStackSave (CoroAllocaAllocInst *AI)
 
static void lowerLocalAllocas (ArrayRef< CoroAllocaAllocInst * > LocalAllocas, SmallVectorImpl< Instruction * > &DeadInsts)
 Turn each of the given local allocas into a normal (dynamic) alloca instruction.
 
static InstructionlowerNonLocalAlloca (CoroAllocaAllocInst *AI, coro::Shape &Shape, SmallVectorImpl< Instruction * > &DeadInsts)
 Turn the given coro.alloca.alloc call into a dynamic allocation.
 
static ValueemitGetSwiftErrorValue (IRBuilder<> &Builder, Type *ValueTy, coro::Shape &Shape)
 Get the current swifterror value.
 
static ValueemitSetSwiftErrorValue (IRBuilder<> &Builder, Value *V, coro::Shape &Shape)
 Set the given value as the current swifterror value.
 
static ValueemitSetAndGetSwiftErrorValueAround (Instruction *Call, AllocaInst *Alloca, coro::Shape &Shape)
 Set the swifterror value from the given alloca before a call, then put in back in the alloca afterwards.
 
static void eliminateSwiftErrorAlloca (Function &F, AllocaInst *Alloca, coro::Shape &Shape)
 Eliminate a formerly-swifterror alloca by inserting the get/set intrinsics and attempting to MemToReg the alloca away.
 
static void eliminateSwiftErrorArgument (Function &F, Argument &Arg, coro::Shape &Shape, SmallVectorImpl< AllocaInst * > &AllocasToPromote)
 "Eliminate" a swifterror argument by reducing it to the alloca case and then loading and storing in the prologue and epilog.
 
static void eliminateSwiftError (Function &F, coro::Shape &Shape)
 Eliminate all problematic uses of swifterror arguments and allocas from the function.
 
static void sinkSpillUsesAfterCoroBegin (Function &F, const FrameDataInfo &FrameData, CoroBeginInst *CoroBegin)
 retcon and retcon.once conventions assume that all spill uses can be sunk after the coro.begin intrinsic.
 
static void sinkLifetimeStartMarkers (Function &F, coro::Shape &Shape, SuspendCrossingInfo &Checker, const DominatorTree &DT)
 For each local variable that all of its user are only used inside one of suspended region, we sink their lifetime.start markers to the place where after the suspend block.
 
static void collectFrameAlloca (AllocaInst *AI, coro::Shape &Shape, const SuspendCrossingInfo &Checker, SmallVectorImpl< AllocaInfo > &Allocas, const DominatorTree &DT)
 
static std::optional< std::pair< Value &, DIExpression & > > salvageDebugInfoImpl (SmallDenseMap< Argument *, AllocaInst *, 4 > &ArgToAllocaMap, bool UseEntryValue, Function *F, Value *Storage, DIExpression *Expr, bool SkipOutermostLoad)
 
static void doRematerializations (Function &F, SuspendCrossingInfo &Checker, const std::function< bool(Instruction &)> &MaterializableCallback)
 

Variables

cl::opt< boolUseNewDbgInfoFormat
 

Macro Definition Documentation

◆ DEBUG_TYPE [1/2]

#define DEBUG_TYPE   "coro-suspend-crossing"

Definition at line 452 of file CoroFrame.cpp.

◆ DEBUG_TYPE [2/2]

#define DEBUG_TYPE   "coro-frame"

Definition at line 452 of file CoroFrame.cpp.

Typedef Documentation

◆ VisitedBlocksSet

Definition at line 2393 of file CoroFrame.cpp.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
SmallVectorThreshold 

Definition at line 53 of file CoroFrame.cpp.

Function Documentation

◆ buildFrameDebugInfo()

static void buildFrameDebugInfo ( Function F,
coro::Shape Shape,
FrameDataInfo &  FrameData 
)
static

Build artificial debug info for C++ coroutine frames to allow users to inspect the contents of the frame directly.

Create Debug information for coroutine frame with debug name "__coro_frame". The debug information for the fields of coroutine frame is constructed from the following way:

  1. For all the value in the Frame, we search the use of dbg.declare to find the corresponding debug variables for the value. If we can find the debug variable, we can get full and accurate debug information.
  2. If we can't get debug information in step 1 and 2, we could only try to build the DIType by Type. We did this in solveDIType. We only handle integer, float, double, integer type and struct type for now.

FIXME: If we fill the field SizeInBits with the actual size of __coro_index in bits, then __coro_index wouldn't show in the debugger.

Definition at line 1108 of file CoroFrame.cpp.

References llvm::coro::Shape::ABI, assert(), cacheDIVar(), llvm::DenseMapBase< DerivedT, KeyT, ValueT, KeyInfoT, BucketT >::contains(), llvm::DIBuilder::createAutoVariable(), llvm::DIBuilder::createBasicType(), llvm::DIBuilder::createExpression(), llvm::DIBuilder::createMemberType(), llvm::DIBuilder::createPointerType(), llvm::DIBuilder::createStructType(), llvm::coro::Shape::SwitchFieldIndex::Destroy, F, llvm::coro::Shape::FrameAlign, llvm::coro::Shape::FramePtr, llvm::coro::Shape::FrameSize, llvm::coro::Shape::FrameTy, llvm::MDTuple::get(), llvm::ValueAsMetadata::get(), llvm::MDNode::getContext(), llvm::StructType::getElementType(), llvm::DIScope::getFile(), llvm::details::FixedOrScalableQuantity< LeafTy, ValueTy >::getFixedValue(), llvm::coro::Shape::getInsertPtAfterFramePtr(), llvm::DIType::getName(), llvm::StructType::getNumElements(), llvm::DIBuilder::getOrCreateArray(), llvm::coro::Shape::getPromiseAlloca(), llvm::DataLayout::getTypeSizeInBits(), llvm::coro::Shape::SwitchLoweringStorage::IndexAlign, llvm::coro::Shape::SwitchLoweringStorage::IndexField, llvm::coro::Shape::SwitchLoweringStorage::IndexOffset, llvm::DenseMapBase< DerivedT, KeyT, ValueT, KeyInfoT, BucketT >::insert(), llvm::dwarf::isCPlusPlus(), llvm::Type::isSized(), Name, llvm::SmallVectorTemplateBase< T, bool >::push_back(), llvm::DIBuilder::replaceArrays(), llvm::MDNode::replaceOperandWith(), llvm::coro::Shape::SwitchFieldIndex::Resume, solveDIType(), llvm::StringRef::str(), llvm::Twine::str(), llvm::coro::Shape::SwitchLowering, UseNewDbgInfoFormat, llvm::Align::value(), and value.

Referenced by llvm::coro::buildCoroutineFrame().

◆ buildFrameType()

static StructType * buildFrameType ( Function F,
coro::Shape Shape,
FrameDataInfo &  FrameData 
)
static

◆ cacheDIVar()

static void cacheDIVar ( FrameDataInfo &  FrameData,
DenseMap< Value *, DILocalVariable * > &  DIVarCache 
)
static

◆ cleanupSinglePredPHIs()

static void cleanupSinglePredPHIs ( Function F)
static

◆ collectFrameAlloca()

static void collectFrameAlloca ( AllocaInst AI,
coro::Shape Shape,
const SuspendCrossingInfo &  Checker,
SmallVectorImpl< AllocaInfo > &  Allocas,
const DominatorTree DT 
)
static

◆ doRematerializations()

static void doRematerializations ( Function F,
SuspendCrossingInfo &  Checker,
const std::function< bool(Instruction &)> &  MaterializableCallback 
)
static

◆ dumpAllocas()

static void dumpAllocas ( const SmallVectorImpl< AllocaInfo > &  Allocas)
static

Definition at line 572 of file CoroFrame.cpp.

References A, and llvm::dbgs().

Referenced by llvm::coro::buildCoroutineFrame().

◆ dumpRemats()

static void dumpRemats ( StringRef  Title,
const SmallMapVector< Instruction *, std::unique_ptr< RematGraph >, 8 > &  RM 
)
static

Definition at line 562 of file CoroFrame.cpp.

References llvm::dbgs().

Referenced by doRematerializations().

◆ dumpSpills()

static void dumpSpills ( StringRef  Title,
const SpillInfo &  Spills 
)
static

Definition at line 553 of file CoroFrame.cpp.

References llvm::dbgs(), and I.

Referenced by llvm::coro::buildCoroutineFrame().

◆ eliminateSwiftError()

static void eliminateSwiftError ( Function F,
coro::Shape Shape 
)
static

Eliminate all problematic uses of swifterror arguments and allocas from the function.

We'll fix them up later when splitting the function.

Definition at line 2662 of file CoroFrame.cpp.

References eliminateSwiftErrorAlloca(), eliminateSwiftErrorArgument(), llvm::SmallVectorBase< Size_T >::empty(), F, llvm::AllocaInst::isSwiftError(), llvm::PromoteMemToReg(), llvm::SmallVectorTemplateBase< T, bool >::push_back(), and llvm::AllocaInst::setSwiftError().

Referenced by llvm::coro::buildCoroutineFrame().

◆ eliminateSwiftErrorAlloca()

static void eliminateSwiftErrorAlloca ( Function F,
AllocaInst Alloca,
coro::Shape Shape 
)
static

Eliminate a formerly-swifterror alloca by inserting the get/set intrinsics and attempting to MemToReg the alloca away.

Definition at line 2599 of file CoroFrame.cpp.

References Addr, assert(), emitSetAndGetSwiftErrorValueAround(), llvm::Use::getUser(), llvm::isAllocaPromotable(), llvm::make_early_inc_range(), llvm::Use::set(), and llvm::Value::uses().

Referenced by eliminateSwiftError(), and eliminateSwiftErrorArgument().

◆ eliminateSwiftErrorArgument()

static void eliminateSwiftErrorArgument ( Function F,
Argument Arg,
coro::Shape Shape,
SmallVectorImpl< AllocaInst * > &  AllocasToPromote 
)
static

◆ emitGetSwiftErrorValue()

static Value * emitGetSwiftErrorValue ( IRBuilder<> &  Builder,
Type ValueTy,
coro::Shape Shape 
)
static

◆ emitSetAndGetSwiftErrorValueAround()

static Value * emitSetAndGetSwiftErrorValueAround ( Instruction Call,
AllocaInst Alloca,
coro::Shape Shape 
)
static

Set the swifterror value from the given alloca before a call, then put in back in the alloca afterwards.

Returns an address that will stand in for the swifterror slot until splitting.

Definition at line 2569 of file CoroFrame.cpp.

References Addr, llvm::IRBuilderBase::CreateLoad(), llvm::IRBuilderBase::CreateStore(), emitGetSwiftErrorValue(), emitSetSwiftErrorValue(), llvm::AllocaInst::getAllocatedType(), and llvm::IRBuilderBase::SetInsertPoint().

Referenced by eliminateSwiftErrorAlloca(), and eliminateSwiftErrorArgument().

◆ emitSetSwiftErrorValue()

static Value * emitSetSwiftErrorValue ( IRBuilder<> &  Builder,
Value V,
coro::Shape Shape 
)
static

Set the given value as the current swifterror value.

Returns a slot that can be used as a swifterror slot.

Definition at line 2551 of file CoroFrame.cpp.

References llvm::IRBuilderBase::CreateCall(), llvm::ConstantPointerNull::get(), llvm::IRBuilderBase::getPtrTy(), and llvm::coro::Shape::SwiftErrorOps.

Referenced by eliminateSwiftErrorArgument(), and emitSetAndGetSwiftErrorValueAround().

◆ insertSpills()

static void insertSpills ( const FrameDataInfo &  FrameData,
coro::Shape Shape 
)
static

Definition at line 1737 of file CoroFrame.cpp.

References A, llvm::coro::Shape::ABI, llvm::coro::Shape::AllocaSpillBlock, llvm::any_of(), assert(), llvm::BasicBlock::begin(), llvm::CallingConv::C, llvm::SmallVectorImpl< T >::clear(), llvm::coro::Shape::CoroBegin, llvm::IRBuilderBase::CreateAdd(), llvm::IRBuilderBase::CreateAddrSpaceCast(), llvm::IRBuilderBase::CreateAlignedLoad(), llvm::IRBuilderBase::CreateAlignedStore(), llvm::IRBuilderBase::CreateAnd(), llvm::IRBuilderBase::CreateConstInBoundsGEP2_32(), llvm::IRBuilderBase::CreateInBoundsGEP(), llvm::IRBuilderBase::CreateIntToPtr(), llvm::IRBuilderBase::CreateLoad(), llvm::IRBuilderBase::CreateNot(), llvm::IRBuilderBase::CreatePtrAdd(), llvm::IRBuilderBase::CreatePtrToInt(), llvm::IRBuilderBase::CreateStore(), llvm::DominatorTree::dominates(), llvm::SmallVectorBase< Size_T >::empty(), llvm::TinyPtrVector< EltTy >::empty(), llvm::Instruction::eraseFromParent(), F, llvm::filterDbgVars(), llvm::findDbgDeclares(), llvm::findDbgUsers(), llvm::findDVRDeclares(), llvm::for_each(), FramePtr, llvm::coro::Shape::FramePtr, llvm::coro::Shape::FrameTy, G, GEP, llvm::IntegerType::get(), llvm::ValueAsMetadata::get(), llvm::AllocaInst::getAlign(), llvm::AllocaInst::getAllocatedType(), llvm::AllocaInst::getArraySize(), llvm::Value::getContext(), llvm::StructType::getElementType(), llvm::BasicBlock::getFirstInsertionPt(), llvm::Instruction::getFunction(), llvm::IRBuilderBase::GetInsertPoint(), llvm::coro::Shape::getInsertPtAfterFramePtr(), llvm::Type::getInt32Ty(), llvm::ilist_node_impl< OptionsT >::getIterator(), llvm::Instruction::getModule(), llvm::Value::getName(), llvm::GlobalValue::getParent(), llvm::BasicBlock::getParent(), llvm::BasicBlock::getTerminator(), llvm::AllocaInst::getType(), I, II, llvm::AllocaInst::isArrayAllocation(), P, llvm::coro::Shape::SwitchLoweringStorage::PromiseAlloca, llvm::SmallVectorTemplateBase< T, bool >::push_back(), llvm::Value::replaceAllUsesWith(), llvm::Value::replaceUsesWithIf(), llvm::report_fatal_error(), llvm::coro::salvageDebugInfo(), llvm::IRBuilderBase::SetInsertPoint(), llvm::BasicBlock::splitBasicBlock(), splitBeforeCatchSwitch(), llvm::SplitEdge(), llvm::coro::Shape::SwitchLowering, UseNewDbgInfoFormat, llvm::Value::users(), llvm::Value::uses(), and llvm::Align::value().

Referenced by llvm::coro::buildCoroutineFrame().

◆ isCoroutineStructureIntrinsic()

static bool isCoroutineStructureIntrinsic ( Instruction I)
static

Definition at line 2285 of file CoroFrame.cpp.

References I.

Referenced by llvm::coro::buildCoroutineFrame().

◆ isLocalAlloca()

static bool isLocalAlloca ( CoroAllocaAllocInst AI)
static

Is the given alloca "local", i.e.

bounded in lifetime to not cross a suspend point?

Definition at line 2420 of file CoroFrame.cpp.

References llvm::ilist_detail::node_parent_access< NodeTy, ParentTy >::getParent(), llvm::SmallPtrSetImpl< PtrType >::insert(), isSuspendReachableFrom(), and llvm::Value::users().

Referenced by llvm::coro::buildCoroutineFrame().

◆ isSuspendBlock()

static bool isSuspendBlock ( BasicBlock BB)
static

◆ isSuspendReachableFrom()

static bool isSuspendReachableFrom ( BasicBlock From,
VisitedBlocksSet VisitedOrFreeBBs 
)
static

Does control flow starting at the given block ever reach a suspend instruction before reaching a block in VisitedOrFreeBBs?

Definition at line 2397 of file CoroFrame.cpp.

References From, llvm::SmallPtrSetImpl< PtrType >::insert(), isSuspendBlock(), isSuspendReachableFrom(), and llvm::successors().

Referenced by isLocalAlloca(), and isSuspendReachableFrom().

◆ localAllocaNeedsStackSave()

static bool localAllocaNeedsStackSave ( CoroAllocaAllocInst AI)
static

Definition at line 2453 of file CoroFrame.cpp.

References llvm::Value::users(), and willLeaveFunctionImmediatelyAfter().

Referenced by lowerLocalAllocas().

◆ lowerLocalAllocas()

static void lowerLocalAllocas ( ArrayRef< CoroAllocaAllocInst * >  LocalAllocas,
SmallVectorImpl< Instruction * > &  DeadInsts 
)
static

◆ lowerNonLocalAlloca()

static Instruction * lowerNonLocalAlloca ( CoroAllocaAllocInst AI,
coro::Shape Shape,
SmallVectorImpl< Instruction * > &  DeadInsts 
)
static

Turn the given coro.alloca.alloc call into a dynamic allocation.

This happens during the all-instructions iteration, so it must not delete the call.

Definition at line 2511 of file CoroFrame.cpp.

References llvm::coro::Shape::emitAlloc(), llvm::coro::Shape::emitDealloc(), llvm::CoroAllocaAllocInst::getSize(), llvm::SmallVectorTemplateBase< T, bool >::push_back(), llvm::IRBuilderBase::SetInsertPoint(), and llvm::Value::users().

Referenced by llvm::coro::buildCoroutineFrame().

◆ movePHIValuesToInsertedBlock()

static void movePHIValuesToInsertedBlock ( BasicBlock SuccBB,
BasicBlock InsertedBB,
BasicBlock PredBB,
PHINode UntilPHI = nullptr 
)
static

◆ rewriteMaterializableInstructions()

static void rewriteMaterializableInstructions ( const SmallMapVector< Instruction *, std::unique_ptr< RematGraph >, 8 > &  AllRemats)
static

◆ rewritePHIs() [1/2]

static void rewritePHIs ( BasicBlock BB)
static

◆ rewritePHIs() [2/2]

static void rewritePHIs ( Function F)
static

◆ rewritePHIsForCleanupPad()

static void rewritePHIsForCleanupPad ( BasicBlock CleanupPadBB,
CleanupPadInst CleanupPad 
)
static

◆ salvageDebugInfoImpl()

static std::optional< std::pair< Value &, DIExpression & > > salvageDebugInfoImpl ( SmallDenseMap< Argument *, AllocaInst *, 4 > &  ArgToAllocaMap,
bool  UseEntryValue,
Function F,
Value Storage,
DIExpression Expr,
bool  SkipOutermostLoad 
)
static

◆ sinkLifetimeStartMarkers()

static void sinkLifetimeStartMarkers ( Function F,
coro::Shape Shape,
SuspendCrossingInfo &  Checker,
const DominatorTree DT 
)
static

For each local variable that all of its user are only used inside one of suspended region, we sink their lifetime.start markers to the place where after the suspend block.

Doing so minimizes the lifetime of each variable, hence minimizing the amount of data we end up putting on the frame.

Definition at line 2742 of file CoroFrame.cpp.

References assert(), llvm::coro::Shape::CoroSuspends, llvm::DominatorTree::dominates(), F, llvm::ilist_detail::node_parent_access< NodeTy, ParentTy >::getParent(), llvm::BasicBlock::getParent(), llvm::BasicBlock::getSingleSuccessor(), I, II, llvm::SmallPtrSetImpl< PtrType >::insert(), instructions, isLifetimeStart(), isSuspendBlock(), llvm::SmallVectorTemplateBase< T, bool >::push_back(), llvm::SmallVectorBase< Size_T >::size(), and llvm::Value::users().

Referenced by llvm::coro::buildCoroutineFrame().

◆ sinkSpillUsesAfterCoroBegin()

static void sinkSpillUsesAfterCoroBegin ( Function F,
const FrameDataInfo &  FrameData,
CoroBeginInst CoroBegin 
)
static

◆ solveDIType()

static DIType * solveDIType ( DIBuilder Builder,
Type Ty,
const DataLayout Layout,
DIScope Scope,
unsigned  LineNum,
DenseMap< Type *, DIType * > &  DITypeCache 
)
static

◆ solveTypeName()

static StringRef solveTypeName ( Type Ty)
static

◆ splitAround()

static void splitAround ( Instruction I,
const Twine Name 
)
static

Definition at line 2384 of file CoroFrame.cpp.

References I, Name, and splitBlockIfNotFirst().

Referenced by llvm::coro::buildCoroutineFrame().

◆ splitBeforeCatchSwitch()

static Instruction * splitBeforeCatchSwitch ( CatchSwitchInst CatchSwitch)
static

◆ splitBlockIfNotFirst()

static BasicBlock * splitBlockIfNotFirst ( Instruction I,
const Twine Name 
)
static

◆ willLeaveFunctionImmediatelyAfter()

static bool willLeaveFunctionImmediatelyAfter ( BasicBlock BB,
unsigned  depth = 3 
)
static

After we split the coroutine, will the given basic block be along an obvious exit path for the resumption function?

Definition at line 2434 of file CoroFrame.cpp.

References isSuspendBlock(), llvm::successors(), and willLeaveFunctionImmediatelyAfter().

Referenced by localAllocaNeedsStackSave(), and willLeaveFunctionImmediatelyAfter().

Variable Documentation

◆ UseNewDbgInfoFormat

cl::opt<bool> UseNewDbgInfoFormat
extern