aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CodeGenFunction.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-07-29 20:15:26 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-07-29 20:15:26 +0000
commit344a3780b2e33f6ca763666c380202b18aab72a3 (patch)
treef0b203ee6eb71d7fdd792373e3c81eb18d6934dd /clang/lib/CodeGen/CodeGenFunction.cpp
parentb60736ec1405bb0a8dd40989f67ef4c93da068ab (diff)
Diffstat (limited to 'clang/lib/CodeGen/CodeGenFunction.cpp')
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp258
1 files changed, 138 insertions, 120 deletions
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index b393c88f7751..a2384456ea94 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -75,6 +75,7 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext)
shouldEmitLifetimeMarkers(CGM.getCodeGenOpts(), CGM.getLangOpts())) {
if (!suppressNewContext)
CGM.getCXXABI().getMangleContext().startNewFunction();
+ EHStack.setCGF(this);
SetFastMathFlags(CurFPFeatures);
SetFPModel();
@@ -91,8 +92,8 @@ CodeGenFunction::~CodeGenFunction() {
// seems to be a reasonable spot. We do it here, as opposed to the deletion
// time of the CodeGenModule, because we have to ensure the IR has not yet
// been "emitted" to the outside, thus, modifications are still sensible.
- if (CGM.getLangOpts().OpenMPIRBuilder)
- CGM.getOpenMPRuntime().getOMPBuilder().finalize();
+ if (CGM.getLangOpts().OpenMPIRBuilder && CurFn)
+ CGM.getOpenMPRuntime().getOMPBuilder().finalize(CurFn);
}
// Map the LangOption for exception behavior into
@@ -174,7 +175,7 @@ void CodeGenFunction::CGFPOptionsRAII::ConstructorHelper(FPOptions FPFeatures) {
auto mergeFnAttrValue = [&](StringRef Name, bool Value) {
auto OldValue =
- CGF.CurFn->getFnAttribute(Name).getValueAsString() == "true";
+ CGF.CurFn->getFnAttribute(Name).getValueAsBool();
auto NewValue = OldValue & Value;
if (OldValue != NewValue)
CGF.CurFn->addFnAttr(Name, llvm::toStringRef(NewValue));
@@ -452,13 +453,13 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
if (CGM.getCodeGenOpts().EmitDeclMetadata)
EmitDeclMetadata();
- for (SmallVectorImpl<std::pair<llvm::Instruction *, llvm::Value *> >::iterator
- I = DeferredReplacements.begin(),
- E = DeferredReplacements.end();
- I != E; ++I) {
- I->first->replaceAllUsesWith(I->second);
- I->first->eraseFromParent();
+ for (const auto &R : DeferredReplacements) {
+ if (llvm::Value *Old = R.first) {
+ Old->replaceAllUsesWith(R.second);
+ cast<llvm::Instruction>(Old)->eraseFromParent();
+ }
}
+ DeferredReplacements.clear();
// Eliminate CleanupDestSlot alloca by replacing it with SSA values and
// PHIs if the current function is a coroutine. We don't do it for all
@@ -495,6 +496,13 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
// function.
CurFn->addFnAttr("min-legal-vector-width", llvm::utostr(LargestVectorWidth));
+ // Add vscale attribute if appropriate.
+ if (getLangOpts().ArmSveVectorBits) {
+ unsigned VScale = getLangOpts().ArmSveVectorBits / 128;
+ CurFn->addFnAttr(llvm::Attribute::getWithVScaleRangeArgs(getLLVMContext(),
+ VScale, VScale));
+ }
+
// If we generated an unreachable return block, delete it now.
if (ReturnBlock.isValid() && ReturnBlock.getBlock()->use_empty()) {
Builder.ClearInsertionPoint();
@@ -702,23 +710,23 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
DidCallStackSave = false;
CurCodeDecl = D;
- if (const auto *FD = dyn_cast_or_null<FunctionDecl>(D))
- if (FD->usesSEHTry())
- CurSEHParent = FD;
+ const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
+ if (FD && FD->usesSEHTry())
+ CurSEHParent = FD;
CurFuncDecl = (D ? D->getNonClosureContext() : nullptr);
FnRetTy = RetTy;
CurFn = Fn;
CurFnInfo = &FnInfo;
assert(CurFn->isDeclaration() && "Function already has body?");
- // If this function has been blacklisted for any of the enabled sanitizers,
+ // If this function is ignored for any of the enabled sanitizers,
// disable the sanitizer for the function.
do {
#define SANITIZER(NAME, ID) \
if (SanOpts.empty()) \
break; \
if (SanOpts.has(SanitizerKind::ID)) \
- if (CGM.isInSanitizerBlacklist(SanitizerKind::ID, Fn, Loc)) \
+ if (CGM.isInNoSanitizeList(SanitizerKind::ID, Fn, Loc)) \
SanOpts.set(SanitizerKind::ID, false);
#include "clang/Basic/Sanitizers.def"
@@ -726,8 +734,10 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
} while (0);
if (D) {
- // Apply the no_sanitize* attributes to SanOpts.
+ bool NoSanitizeCoverage = false;
+
for (auto Attr : D->specific_attrs<NoSanitizeAttr>()) {
+ // Apply the no_sanitize* attributes to SanOpts.
SanitizerMask mask = Attr->getMask();
SanOpts.Mask &= ~mask;
if (mask & SanitizerKind::Address)
@@ -738,7 +748,14 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
SanOpts.set(SanitizerKind::KernelHWAddress, false);
if (mask & SanitizerKind::KernelHWAddress)
SanOpts.set(SanitizerKind::HWAddress, false);
+
+ // SanitizeCoverage is not handled by SanOpts.
+ if (Attr->hasCoverage())
+ NoSanitizeCoverage = true;
}
+
+ if (NoSanitizeCoverage && CGM.getCodeGenOpts().hasSanitizeCoverage())
+ Fn->addFnAttr(llvm::Attribute::NoSanitizeCoverage);
}
// Apply sanitizer attributes to the function.
@@ -786,10 +803,9 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
// are not aware of how to move the extra UBSan instructions across the split
// coroutine boundaries.
if (D && SanOpts.has(SanitizerKind::Null))
- if (const auto *FD = dyn_cast<FunctionDecl>(D))
- if (FD->getBody() &&
- FD->getBody()->getStmtClass() == Stmt::CoroutineBodyStmtClass)
- SanOpts.Mask &= ~SanitizerKind::Null;
+ if (FD && FD->getBody() &&
+ FD->getBody()->getStmtClass() == Stmt::CoroutineBodyStmtClass)
+ SanOpts.Mask &= ~SanitizerKind::Null;
// Apply xray attributes to the function (as a string, for now)
bool AlwaysXRayAttr = false;
@@ -859,8 +875,8 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
}
// Add no-jump-tables value.
- Fn->addFnAttr("no-jump-tables",
- llvm::toStringRef(CGM.getCodeGenOpts().NoUseJumpTables));
+ if (CGM.getCodeGenOpts().NoUseJumpTables)
+ Fn->addFnAttr("no-jump-tables", "true");
// Add no-inline-line-tables value.
if (CGM.getCodeGenOpts().NoInlineLineTables)
@@ -876,32 +892,30 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
if (D && D->hasAttr<CFICanonicalJumpTableAttr>())
Fn->addFnAttr("cfi-canonical-jump-table");
- if (getLangOpts().OpenCL) {
+ if (D && D->hasAttr<NoProfileFunctionAttr>())
+ Fn->addFnAttr(llvm::Attribute::NoProfile);
+
+ if (FD && getLangOpts().OpenCL) {
// Add metadata for a kernel function.
- if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
- EmitOpenCLKernelMetadata(FD, Fn);
+ EmitOpenCLKernelMetadata(FD, Fn);
}
// If we are checking function types, emit a function type signature as
// prologue data.
- if (getLangOpts().CPlusPlus && SanOpts.has(SanitizerKind::Function)) {
- if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
- if (llvm::Constant *PrologueSig = getPrologueSignature(CGM, FD)) {
- // Remove any (C++17) exception specifications, to allow calling e.g. a
- // noexcept function through a non-noexcept pointer.
- auto ProtoTy =
- getContext().getFunctionTypeWithExceptionSpec(FD->getType(),
- EST_None);
- llvm::Constant *FTRTTIConst =
- CGM.GetAddrOfRTTIDescriptor(ProtoTy, /*ForEH=*/true);
- llvm::Constant *FTRTTIConstEncoded =
- EncodeAddrForUseInPrologue(Fn, FTRTTIConst);
- llvm::Constant *PrologueStructElems[] = {PrologueSig,
- FTRTTIConstEncoded};
- llvm::Constant *PrologueStructConst =
- llvm::ConstantStruct::getAnon(PrologueStructElems, /*Packed=*/true);
- Fn->setPrologueData(PrologueStructConst);
- }
+ if (FD && getLangOpts().CPlusPlus && SanOpts.has(SanitizerKind::Function)) {
+ if (llvm::Constant *PrologueSig = getPrologueSignature(CGM, FD)) {
+ // Remove any (C++17) exception specifications, to allow calling e.g. a
+ // noexcept function through a non-noexcept pointer.
+ auto ProtoTy = getContext().getFunctionTypeWithExceptionSpec(
+ FD->getType(), EST_None);
+ llvm::Constant *FTRTTIConst =
+ CGM.GetAddrOfRTTIDescriptor(ProtoTy, /*ForEH=*/true);
+ llvm::Constant *FTRTTIConstEncoded =
+ EncodeAddrForUseInPrologue(Fn, FTRTTIConst);
+ llvm::Constant *PrologueStructElems[] = {PrologueSig, FTRTTIConstEncoded};
+ llvm::Constant *PrologueStructConst =
+ llvm::ConstantStruct::getAnon(PrologueStructElems, /*Packed=*/true);
+ Fn->setPrologueData(PrologueStructConst);
}
}
@@ -928,14 +942,12 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
// kernels cannot include RTTI information, exception classes,
// recursive code, virtual functions or make use of C++ libraries that
// are not compiled for the device.
- if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
- if ((getLangOpts().CPlusPlus && FD->isMain()) || getLangOpts().OpenCL ||
- getLangOpts().SYCLIsDevice ||
- (getLangOpts().CUDA && FD->hasAttr<CUDAGlobalAttr>()))
- Fn->addFnAttr(llvm::Attribute::NoRecurse);
- }
+ if (FD && ((getLangOpts().CPlusPlus && FD->isMain()) ||
+ getLangOpts().OpenCL || getLangOpts().SYCLIsDevice ||
+ (getLangOpts().CUDA && FD->hasAttr<CUDAGlobalAttr>())))
+ Fn->addFnAttr(llvm::Attribute::NoRecurse);
- if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
+ if (FD) {
Builder.setIsFPConstrained(FD->hasAttr<StrictFPAttr>());
if (FD->hasAttr<StrictFPAttr>())
Fn->addFnAttr(llvm::Attribute::StrictFP);
@@ -943,10 +955,9 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
// If a custom alignment is used, force realigning to this alignment on
// any main function which certainly will need it.
- if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
- if ((FD->isMain() || FD->isMSVCRTEntryPoint()) &&
- CGM.getCodeGenOpts().StackAlignment)
- Fn->addFnAttr("stackrealign");
+ if (FD && ((FD->isMain() || FD->isMSVCRTEntryPoint()) &&
+ CGM.getCodeGenOpts().StackAlignment))
+ Fn->addFnAttr("stackrealign");
llvm::BasicBlock *EntryBB = createBasicBlock("entry", CurFn);
@@ -973,7 +984,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
// such as 'this' and 'vtt', show up in the debug info. Preserve the calling
// convention.
CallingConv CC = CallingConv::CC_C;
- if (auto *FD = dyn_cast_or_null<FunctionDecl>(D))
+ if (FD)
if (const auto *SrcFnTy = FD->getType()->getAs<FunctionType>())
CC = SrcFnTy->getCallConv();
SmallVector<QualType, 16> ArgTypes;
@@ -1033,6 +1044,10 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
Fn->addFnAttr("packed-stack");
}
+ if (CGM.getCodeGenOpts().WarnStackSize != UINT_MAX)
+ Fn->addFnAttr("warn-stack-size",
+ std::to_string(CGM.getCodeGenOpts().WarnStackSize));
+
if (RetTy->isVoidType()) {
// Void type; nothing to return.
ReturnValue = Address::invalid();
@@ -1060,9 +1075,12 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
unsigned Idx = CurFnInfo->getReturnInfo().getInAllocaFieldIndex();
llvm::Function::arg_iterator EI = CurFn->arg_end();
--EI;
- llvm::Value *Addr = Builder.CreateStructGEP(nullptr, &*EI, Idx);
+ llvm::Value *Addr = Builder.CreateStructGEP(
+ EI->getType()->getPointerElementType(), &*EI, Idx);
+ llvm::Type *Ty =
+ cast<llvm::GetElementPtrInst>(Addr)->getResultElementType();
ReturnValuePointer = Address(Addr, getPointerAlign());
- Addr = Builder.CreateAlignedLoad(Addr, getPointerAlign(), "agg.result");
+ Addr = Builder.CreateAlignedLoad(Ty, Addr, getPointerAlign(), "agg.result");
ReturnValue = Address(Addr, CGM.getNaturalTypeAlignment(RetTy));
} else {
ReturnValue = CreateIRTemp(RetTy, "retval");
@@ -1177,9 +1195,6 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
void CodeGenFunction::EmitFunctionBody(const Stmt *Body) {
incrementProfileCounter(Body);
- if (CPlusPlusWithProgress())
- FnIsMustProgress = true;
-
if (const CompoundStmt *S = dyn_cast<CompoundStmt>(Body))
EmitCompoundStmtWithoutScope(*S);
else
@@ -1187,7 +1202,7 @@ void CodeGenFunction::EmitFunctionBody(const Stmt *Body) {
// This is checked after emitting the function body so we know if there
// are any permitted infinite loops.
- if (FnIsMustProgress)
+ if (checkIfFunctionMustProgress())
CurFn->addFnAttr(llvm::Attribute::MustProgress);
}
@@ -1272,19 +1287,6 @@ QualType CodeGenFunction::BuildFunctionArgList(GlobalDecl GD,
return ResTy;
}
-static bool
-shouldUseUndefinedBehaviorReturnOptimization(const FunctionDecl *FD,
- const ASTContext &Context) {
- QualType T = FD->getReturnType();
- // Avoid the optimization for functions that return a record type with a
- // trivial destructor or another trivially copyable type.
- if (const RecordType *RT = T.getCanonicalType()->getAs<RecordType>()) {
- if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl()))
- return !ClassDecl->hasTrivialDestructor();
- }
- return !T.isTriviallyCopyableType(Context);
-}
-
void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
const CGFunctionInfo &FnInfo) {
const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
@@ -1294,8 +1296,14 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
QualType ResTy = BuildFunctionArgList(GD, Args);
// Check if we should generate debug info for this function.
- if (FD->hasAttr<NoDebugAttr>())
- DebugInfo = nullptr; // disable debug info indefinitely for this function
+ if (FD->hasAttr<NoDebugAttr>()) {
+ // Clear non-distinct debug info that was possibly attached to the function
+ // due to an earlier declaration without the nodebug attribute
+ if (Fn)
+ Fn->setSubprogram(nullptr);
+ // Disable debug info indefinitely for this function
+ DebugInfo = nullptr;
+ }
// The function might not have a body if we're generating thunks for a
// function declaration.
@@ -1321,14 +1329,25 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
Stmt *Body = FD->getBody();
- // Initialize helper which will detect jumps which can cause invalid lifetime
- // markers.
- if (Body && ShouldEmitLifetimeMarkers)
- Bypasses.Init(Body);
+ if (Body) {
+ // Coroutines always emit lifetime markers.
+ if (isa<CoroutineBodyStmt>(Body))
+ ShouldEmitLifetimeMarkers = true;
+
+ // Initialize helper which will detect jumps which can cause invalid
+ // lifetime markers.
+ if (ShouldEmitLifetimeMarkers)
+ Bypasses.Init(Body);
+ }
// Emit the standard function prologue.
StartFunction(GD, ResTy, Fn, FnInfo, Args, Loc, BodyRange.getBegin());
+ // Save parameters for coroutine function.
+ if (Body && isa_and_nonnull<CoroutineBodyStmt>(Body))
+ for (const auto *ParamDecl : FD->parameters())
+ FnArgs.push_back(ParamDecl);
+
// Generate the body of the function.
PGO.assignRegionCounters(GD, CurFn);
if (isa<CXXDestructorDecl>(FD))
@@ -1365,7 +1384,7 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
!FD->getReturnType()->isVoidType() && Builder.GetInsertBlock()) {
bool ShouldEmitUnreachable =
CGM.getCodeGenOpts().StrictReturn ||
- shouldUseUndefinedBehaviorReturnOptimization(FD, getContext());
+ !CGM.MayDropFunctionReturn(FD->getASTContext(), FD->getReturnType());
if (SanOpts.has(SanitizerKind::Return)) {
SanitizerScope SanScope(this);
llvm::Value *IsFalse = Builder.getFalse();
@@ -1774,10 +1793,19 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
return;
}
+ // Emit the code with the fully general case.
+ llvm::Value *CondV;
+ {
+ ApplyDebugLocation DL(*this, Cond);
+ CondV = EvaluateExprAsBool(Cond);
+ }
+
+ llvm::MDNode *Weights = nullptr;
+ llvm::MDNode *Unpredictable = nullptr;
+
// If the branch has a condition wrapped by __builtin_unpredictable,
// create metadata that specifies that the branch is unpredictable.
// Don't bother if not optimizing because that metadata would not be used.
- llvm::MDNode *Unpredictable = nullptr;
auto *Call = dyn_cast<CallExpr>(Cond->IgnoreImpCasts());
if (Call && CGM.getCodeGenOpts().OptimizationLevel != 0) {
auto *FD = dyn_cast_or_null<FunctionDecl>(Call->getCalleeDecl());
@@ -1787,18 +1815,17 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
}
}
- llvm::MDNode *Weights = createBranchWeights(LH);
- if (!Weights) {
+ // If there is a Likelihood knowledge for the cond, lower it.
+ // Note that if not optimizing this won't emit anything.
+ llvm::Value *NewCondV = emitCondLikelihoodViaExpectIntrinsic(CondV, LH);
+ if (CondV != NewCondV)
+ CondV = NewCondV;
+ else {
+ // Otherwise, lower profile counts. Note that we do this even at -O0.
uint64_t CurrentCount = std::max(getCurrentProfileCount(), TrueCount);
Weights = createProfileWeights(TrueCount, CurrentCount - TrueCount);
}
- // Emit the code with the fully general case.
- llvm::Value *CondV;
- {
- ApplyDebugLocation DL(*this, Cond);
- CondV = EvaluateExprAsBool(Cond);
- }
Builder.CreateCondBr(CondV, TrueBlock, FalseBlock, Weights, Unpredictable);
}
@@ -1826,8 +1853,8 @@ static void emitNonZeroVLAInit(CodeGenFunction &CGF, QualType baseType,
Address begin =
Builder.CreateElementBitCast(dest, CGF.Int8Ty, "vla.begin");
- llvm::Value *end =
- Builder.CreateInBoundsGEP(begin.getPointer(), sizeInChars, "vla.end");
+ llvm::Value *end = Builder.CreateInBoundsGEP(
+ begin.getElementType(), begin.getPointer(), sizeInChars, "vla.end");
llvm::BasicBlock *originBB = CGF.Builder.GetInsertBlock();
llvm::BasicBlock *loopBB = CGF.createBasicBlock("vla-init.loop");
@@ -2034,9 +2061,9 @@ llvm::Value *CodeGenFunction::emitArrayLength(const ArrayType *origArrayType,
addr = Builder.CreateElementBitCast(addr, baseType, "array.begin");
} else {
// Create the actual GEP.
- addr = Address(Builder.CreateInBoundsGEP(addr.getPointer(),
- gepIndices, "array.begin"),
- addr.getAlignment());
+ addr = Address(Builder.CreateInBoundsGEP(
+ addr.getElementType(), addr.getPointer(), gepIndices, "array.begin"),
+ addr.getAlignment());
}
baseType = eltType;
@@ -2642,35 +2669,26 @@ llvm::DebugLoc CodeGenFunction::SourceLocToDebugLoc(SourceLocation Location) {
return llvm::DebugLoc();
}
-static Optional<std::pair<uint32_t, uint32_t>>
-getLikelihoodWeights(Stmt::Likelihood LH) {
+llvm::Value *
+CodeGenFunction::emitCondLikelihoodViaExpectIntrinsic(llvm::Value *Cond,
+ Stmt::Likelihood LH) {
switch (LH) {
- case Stmt::LH_Unlikely:
- return std::pair<uint32_t, uint32_t>(llvm::UnlikelyBranchWeight,
- llvm::LikelyBranchWeight);
case Stmt::LH_None:
- return None;
+ return Cond;
case Stmt::LH_Likely:
- return std::pair<uint32_t, uint32_t>(llvm::LikelyBranchWeight,
- llvm::UnlikelyBranchWeight);
+ case Stmt::LH_Unlikely:
+ // Don't generate llvm.expect on -O0 as the backend won't use it for
+ // anything.
+ if (CGM.getCodeGenOpts().OptimizationLevel == 0)
+ return Cond;
+ llvm::Type *CondTy = Cond->getType();
+ assert(CondTy->isIntegerTy(1) && "expecting condition to be a boolean");
+ llvm::Function *FnExpect =
+ CGM.getIntrinsic(llvm::Intrinsic::expect, CondTy);
+ llvm::Value *ExpectedValueOfCond =
+ llvm::ConstantInt::getBool(CondTy, LH == Stmt::LH_Likely);
+ return Builder.CreateCall(FnExpect, {Cond, ExpectedValueOfCond},
+ Cond->getName() + ".expval");
}
llvm_unreachable("Unknown Likelihood");
}
-
-llvm::MDNode *CodeGenFunction::createBranchWeights(Stmt::Likelihood LH) const {
- Optional<std::pair<uint32_t, uint32_t>> LHW = getLikelihoodWeights(LH);
- if (!LHW)
- return nullptr;
-
- llvm::MDBuilder MDHelper(CGM.getLLVMContext());
- return MDHelper.createBranchWeights(LHW->first, LHW->second);
-}
-
-llvm::MDNode *CodeGenFunction::createProfileOrBranchWeightsForLoop(
- const Stmt *Cond, uint64_t LoopCount, const Stmt *Body) const {
- llvm::MDNode *Weights = createProfileWeightsForLoop(Cond, LoopCount);
- if (!Weights && CGM.getCodeGenOpts().OptimizationLevel)
- Weights = createBranchWeights(Stmt::getLikelihood(Body));
-
- return Weights;
-}