LLVM: lib/Transforms/Coroutines/CoroAnnotationElide.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

18

32

33#include

34

35using namespace llvm;

36

37#define DEBUG_TYPE "coro-annotation-elide"

38

41 cl::desc("Minimum BranchProbability to consider a elide a coroutine."));

43

50

51

52

54 Align FrameAlign) {

58 const DataLayout &DL = Caller->getDataLayout();

60 auto *Frame = new AllocaInst(FrameTy, DL.getAllocaAddrSpace(), "", InsertPt);

61 Frame->setAlignment(FrameAlign);

62 return Frame;

63}

64

65

66

67

68

69

72

73

74

81

84 NewArgs, "", NewCBInsertPt);

85 NewCI->setTailCallKind(CI->getTailCallKind());

86 NewCB = NewCI;

89 II->getNormalDest(), II->getUnwindDest(),

90 NewArgs, {}, "", NewCBInsertPt);

91 } else {

92 llvm_unreachable("CallBase should either be Call or Invoke!");

93 }

94

101

102 NewCB->removeFnAttr(llvm::Attribute::CoroElideSafe);

104

107 if (IR.isSuccess()) {

109 } else {

112 }

113}

114

122

123 auto &FAM =

125

127 Function *Callee = &N.getFunction();

128 Function *NewCallee = Callee->getParent()->getFunction(

129 (Callee->getName() + ".noalloc").str());

130 if (!NewCallee)

131 continue;

132

134 for (auto *U : Callee->users()) {

136 if (CB->getCalledFunction() == Callee)

137 Users.push_back(CB);

138 }

139 }

140 auto FramePtrArgPosition = NewCallee->arg_size() - 1;

141 auto FrameSize =

143 auto FrameAlign =

145

147

148 for (auto *CB : Users) {

149 auto *Caller = CB->getFunction();

150 if (!Caller)

151 continue;

152

153 bool IsCallerPresplitCoroutine = Caller->isPresplitCoroutine();

154 bool HasAttr = CB->hasFnAttr(llvm::Attribute::CoroElideSafe);

155 if (IsCallerPresplitCoroutine && HasAttr) {

157

158 auto BlockFreq = BFI.getBlockFreq(CB->getParent()).getFrequency();

159 auto EntryFreq = BFI.getEntryFreq().getFrequency();

162

163 if (BlockFreq < MinFreq) {

164 ORE.emit([&]() {

166 DEBUG_TYPE, "CoroAnnotationElideUnlikely", Caller)

167 << "'" << ore::NV("callee", Callee->getName())

168 << "' not elided in '"

169 << ore::NV("caller", Caller->getName())

170 << "' because of low frequency: "

171 << ore::NV("block_freq", BlockFreq)

172 << " (threshold: " << ore::NV("min_freq", MinFreq) << ")";

173 });

174 continue;

175 }

176

177 auto *CallerN = CG.lookup(*Caller);

178 auto *CallerC = CallerN ? CG.lookupSCC(*CallerN) : nullptr;

179

180

181 auto ShouldUpdateCallGraph = !!CallerC;

182 processCall(CB, Caller, NewCallee, FrameSize, FrameAlign);

183

184 ORE.emit([&]() {

186 << "'" << ore::NV("callee", Callee->getName())

187 << "' elided in '" << ore::NV("caller", Caller->getName())

188 << "' (block_freq: " << ore::NV("block_freq", BlockFreq)

189 << ")";

190 });

191

194 if (ShouldUpdateCallGraph)

197

198 } else {

199 ORE.emit([&]() {

201 Caller)

202 << "'" << ore::NV("callee", Callee->getName())

203 << "' not elided in '" << ore::NV("caller", Caller->getName())

204 << "' (caller_presplit="

205 << ore::NV("caller_presplit", IsCallerPresplitCoroutine)

206 << ", elide_safe_attr=" << ore::NV("elide_safe_attr", HasAttr)

207 << ")";

208 });

209 }

210 }

211 }

212

214}

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

This header provides classes for managing passes over SCCs of the call graph.

This file provides interfaces used to manipulate a call graph, regardless if it is a "old style" Call...

static void processCall(CallBase *CB, Function *Caller, Function *NewCallee, uint64_t FrameSize, Align FrameAlign)

Definition CoroAnnotationElide.cpp:70

static cl::opt< float > CoroElideBranchRatio("coro-elide-branch-ratio", cl::init(0.55), cl::Hidden, cl::desc("Minimum BranchProbability to consider a elide a coroutine."))

static Instruction * getFirstNonAllocaInTheEntryBlock(Function *F)

Definition CoroAnnotationElide.cpp:44

cl::opt< unsigned > MinBlockCounterExecution

static Value * allocateFrameInCaller(Function *Caller, uint64_t FrameSize, Align FrameAlign)

Definition CoroAnnotationElide.cpp:53

Module.h This file contains the declarations for the Module class.

This header defines various interfaces for pass management in LLVM.

iv Induction Variable Users

Implements a lazy call graph analysis and related passes for the new pass manager.

Legalize the Machine IR a function s Machine IR

uint64_t IntrinsicInst * II

FunctionAnalysisManager FAM

static const unsigned FramePtr

an instruction to allocate memory on the stack

PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)

Get the result of an analysis pass for a given IR unit.

static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)

This static method is the primary way to construct an ArrayType.

InstListType::iterator iterator

Instruction iterators...

Analysis pass which computes BlockFrequencyInfo.

Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...

void setCallingConv(CallingConv::ID CC)

bundle_op_iterator bundle_op_info_begin()

Return the start of the list of BundleOpInfo instances associated with this OperandBundleUser.

CallingConv::ID getCallingConv() const

bundle_op_iterator bundle_op_info_end()

Return the end of the list of BundleOpInfo instances associated with this OperandBundleUser.

User::op_iterator arg_begin()

Return the iterator pointing to the beginning of the argument list.

void setAttributes(AttributeList A)

Set the attributes for this call.

User::op_iterator arg_end()

Return the iterator pointing to the end of the argument list.

void removeFnAttr(Attribute::AttrKind Kind)

Removes the attribute from the function.

AttributeList getAttributes() const

Return the attributes for this call.

void setCalledFunction(Function *Fn)

Sets the function called, including updating the function type.

Wrapper to unify "old style" CallGraph and "new style" LazyCallGraph.

void initialize(LazyCallGraph &LCG, LazyCallGraph::SCC &SCC, CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR)

Initializers for usage outside of a CGSCC pass, inside a CGSCC pass in the old and new pass manager (...

static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)

A parsed version of the target data layout string in and methods for querying it.

A proxy from a FunctionAnalysisManager to an SCC.

FunctionType * getFunctionType() const

Returns the FunctionType for me.

uint64_t getParamDereferenceableBytes(unsigned ArgNo) const

Extract the number of dereferenceable bytes for a parameter.

MaybeAlign getParamAlign(unsigned ArgNo) const

This class captures the data input to the InlineFunction call, and records the auxiliary results prod...

InlineResult is basically true or false.

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.

void setDebugLoc(DebugLoc Loc)

Set the debug location information for this instruction.

static InvokeInst * Create(FunctionType *Ty, Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef< Value * > Args, const Twine &NameStr, InsertPosition InsertBefore=nullptr)

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.

SCC * lookupSCC(Node &N) const

Lookup a function's SCC in the graph.

Node * lookup(const Function &F) const

Lookup a function in the graph which has already been scanned and added.

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.

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.

static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)

LLVM Value Representation.

LLVM_ABI void replaceAllUsesWith(Value *V)

Change all uses of this to point to a new Value.

self_iterator getIterator()

Pass manager infrastructure for declaring and invalidating analyses.

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

@ C

The default llvm calling convention, compatible with C.

initializer< Ty > init(const Ty &Val)

DiagnosticInfoOptimizationBase::Argument NV

This is an optimization pass for GlobalISel generic memory operations.

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.

decltype(auto) dyn_cast(const From &Val)

dyn_cast - Return the argument parameter cast to the specified type.

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.

AnalysisManager< LazyCallGraph::SCC, LazyCallGraph & > CGSCCAnalysisManager

The CGSCC analysis manager.

bool isa(const From &Val)

isa - Return true if the parameter to the template is an instance of one of the template type argu...

This struct is a compact representation of a valid (non-zero power of two) alignment.

Support structure for SCC passes to communicate updates the call graph back to the CGSCC pass manager...

PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, CGSCCUpdateResult &UR)

Definition CoroAnnotationElide.cpp:115

Align valueOrOne() const

For convenience, returns a valid alignment or 1 if undefined.