#include "llvm/Transforms/Coroutines/CoroElide.h"
#include "CoroInternal.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include <optional>
usingnamespacellvm;
#define DEBUG_TYPE …
STATISTIC(NumOfCoroElided, "The # of coroutine get elided.");
#ifndef NDEBUG
static cl::opt<std::string> CoroElideInfoOutputFilename(
"coro-elide-info-output-file", cl::value_desc("filename"),
cl::desc("File to record the coroutines got elided"), cl::Hidden);
#endif
namespace {
class FunctionElideInfo { … };
class CoroIdElider { … };
}
static void replaceWithConstant(Constant *Value,
SmallVectorImpl<CoroSubFnInst *> &Users) { … }
static bool operandReferences(CallInst *CI, AllocaInst *Frame, AAResults &AA) { … }
static void removeTailCallAttribute(AllocaInst *Frame, AAResults &AA) { … }
static std::optional<std::pair<uint64_t, Align>>
getFrameLayout(Function *Resume) { … }
static Instruction *getFirstNonAllocaInTheEntryBlock(Function *F) { … }
#ifndef NDEBUG
static std::unique_ptr<raw_fd_ostream> getOrCreateLogFile() {
assert(!CoroElideInfoOutputFilename.empty() &&
"coro-elide-info-output-file shouldn't be empty");
std::error_code EC;
auto Result = std::make_unique<raw_fd_ostream>(CoroElideInfoOutputFilename,
EC, sys::fs::OF_Append);
if (!EC)
return Result;
llvm::errs() << "Error opening coro-elide-info-output-file '"
<< CoroElideInfoOutputFilename << " for appending!\n";
return std::make_unique<raw_fd_ostream>(2, false);
}
#endif
void FunctionElideInfo::collectPostSplitCoroIds() { … }
CoroIdElider::CoroIdElider(CoroIdInst *CoroId, FunctionElideInfo &FEI,
AAResults &AA, DominatorTree &DT,
OptimizationRemarkEmitter &ORE)
: … { … }
void CoroIdElider::elideHeapAllocations(uint64_t FrameSize, Align FrameAlign) { … }
bool CoroIdElider::canCoroBeginEscape(
const CoroBeginInst *CB, const SmallPtrSetImpl<BasicBlock *> &TIs) const { … }
bool CoroIdElider::lifetimeEligibleForElide() const { … }
bool CoroIdElider::attemptElide() { … }
PreservedAnalyses CoroElidePass::run(Function &F, FunctionAnalysisManager &AM) { … }