aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CodeGenFunction.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-02-16 20:13:02 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-02-16 20:13:02 +0000
commitb60736ec1405bb0a8dd40989f67ef4c93da068ab (patch)
tree5c43fbb7c9fc45f0f87e0e6795a86267dbd12f9d /clang/lib/CodeGen/CodeGenFunction.cpp
parentcfca06d7963fa0909f90483b42a6d7d194d01e08 (diff)
Diffstat (limited to 'clang/lib/CodeGen/CodeGenFunction.cpp')
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp315
1 files changed, 234 insertions, 81 deletions
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 4a7c84562dee..b393c88f7751 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -25,6 +25,7 @@
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Expr.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
#include "clang/Basic/Builtins.h"
@@ -32,6 +33,7 @@
#include "clang/Basic/TargetInfo.h"
#include "clang/CodeGen/CGFunctionInfo.h"
#include "clang/Frontend/FrontendDiagnostic.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Dominators.h"
@@ -40,6 +42,8 @@
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Operator.h"
+#include "llvm/Support/CRC.h"
+#include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h"
#include "llvm/Transforms/Utils/PromoteMemToReg.h"
using namespace clang;
using namespace CodeGen;
@@ -128,10 +132,24 @@ void CodeGenFunction::SetFastMathFlags(FPOptions FPFeatures) {
}
CodeGenFunction::CGFPOptionsRAII::CGFPOptionsRAII(CodeGenFunction &CGF,
+ const Expr *E)
+ : CGF(CGF) {
+ ConstructorHelper(E->getFPFeaturesInEffect(CGF.getLangOpts()));
+}
+
+CodeGenFunction::CGFPOptionsRAII::CGFPOptionsRAII(CodeGenFunction &CGF,
FPOptions FPFeatures)
- : CGF(CGF), OldFPFeatures(CGF.CurFPFeatures) {
+ : CGF(CGF) {
+ ConstructorHelper(FPFeatures);
+}
+
+void CodeGenFunction::CGFPOptionsRAII::ConstructorHelper(FPOptions FPFeatures) {
+ OldFPFeatures = CGF.CurFPFeatures;
CGF.CurFPFeatures = FPFeatures;
+ OldExcept = CGF.Builder.getDefaultConstrainedExcept();
+ OldRounding = CGF.Builder.getDefaultConstrainedRounding();
+
if (OldFPFeatures == FPFeatures)
return;
@@ -172,6 +190,8 @@ CodeGenFunction::CGFPOptionsRAII::CGFPOptionsRAII(CodeGenFunction &CGF,
CodeGenFunction::CGFPOptionsRAII::~CGFPOptionsRAII() {
CGF.CurFPFeatures = OldFPFeatures;
+ CGF.Builder.setDefaultConstrainedExcept(OldExcept);
+ CGF.Builder.setDefaultConstrainedRounding(OldRounding);
}
LValue CodeGenFunction::MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T) {
@@ -772,13 +792,16 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
SanOpts.Mask &= ~SanitizerKind::Null;
// Apply xray attributes to the function (as a string, for now)
+ bool AlwaysXRayAttr = false;
if (const auto *XRayAttr = D ? D->getAttr<XRayInstrumentAttr>() : nullptr) {
if (CGM.getCodeGenOpts().XRayInstrumentationBundle.has(
XRayInstrKind::FunctionEntry) ||
CGM.getCodeGenOpts().XRayInstrumentationBundle.has(
XRayInstrKind::FunctionExit)) {
- if (XRayAttr->alwaysXRayInstrument() && ShouldXRayInstrumentFunction())
+ if (XRayAttr->alwaysXRayInstrument() && ShouldXRayInstrumentFunction()) {
Fn->addFnAttr("function-instrument", "xray-always");
+ AlwaysXRayAttr = true;
+ }
if (XRayAttr->neverXRayInstrument())
Fn->addFnAttr("function-instrument", "xray-never");
if (const auto *LogArgs = D->getAttr<XRayLogArgsAttr>())
@@ -804,8 +827,22 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
if (!CGM.getCodeGenOpts().XRayInstrumentationBundle.has(
XRayInstrKind::FunctionEntry))
Fn->addFnAttr("xray-skip-entry");
+
+ auto FuncGroups = CGM.getCodeGenOpts().XRayTotalFunctionGroups;
+ if (FuncGroups > 1) {
+ auto FuncName = llvm::makeArrayRef<uint8_t>(
+ CurFn->getName().bytes_begin(), CurFn->getName().bytes_end());
+ auto Group = crc32(FuncName) % FuncGroups;
+ if (Group != CGM.getCodeGenOpts().XRaySelectedFunctionGroup &&
+ !AlwaysXRayAttr)
+ Fn->addFnAttr("function-instrument", "xray-never");
+ }
}
+ if (CGM.getCodeGenOpts().getProfileInstr() != CodeGenOptions::ProfileNone)
+ if (CGM.isProfileInstrExcluded(Fn, Loc))
+ Fn->addFnAttr(llvm::Attribute::NoProfile);
+
unsigned Count, Offset;
if (const auto *Attr =
D ? D->getAttr<PatchableFunctionEntryAttr>() : nullptr) {
@@ -899,8 +936,8 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
}
if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
- Builder.setIsFPConstrained(FD->usesFPIntrin());
- if (FD->usesFPIntrin())
+ Builder.setIsFPConstrained(FD->hasAttr<StrictFPAttr>());
+ if (FD->hasAttr<StrictFPAttr>())
Fn->addFnAttr(llvm::Attribute::StrictFP);
}
@@ -944,8 +981,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
ArgTypes.push_back(VD->getType());
QualType FnType = getContext().getFunctionType(
RetTy, ArgTypes, FunctionProtoType::ExtProtoInfo(CC));
- DI->EmitFunctionStart(GD, Loc, StartLoc, FnType, CurFn, CurFuncIsThunk,
- Builder);
+ DI->emitFunctionStart(GD, Loc, StartLoc, FnType, CurFn, CurFuncIsThunk);
}
if (ShouldInstrumentFunction()) {
@@ -1104,11 +1140,9 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
MD->getParent()->getLambdaCaptureDefault() == LCD_None)
SkippedChecks.set(SanitizerKind::Null, true);
- EmitTypeCheck(isa<CXXConstructorDecl>(MD) ? TCK_ConstructorCall
- : TCK_MemberCall,
- Loc, CXXABIThisValue, ThisTy,
- getContext().getTypeAlignInChars(ThisTy->getPointeeType()),
- SkippedChecks);
+ EmitTypeCheck(
+ isa<CXXConstructorDecl>(MD) ? TCK_ConstructorCall : TCK_MemberCall,
+ Loc, CXXABIThisValue, ThisTy, CXXABIThisAlignment, SkippedChecks);
}
}
@@ -1143,10 +1177,18 @@ 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
EmitStmt(Body);
+
+ // This is checked after emitting the function body so we know if there
+ // are any permitted infinite loops.
+ if (FnIsMustProgress)
+ CurFn->addFnAttr(llvm::Attribute::MustProgress);
}
/// When instrumenting to collect profile data, the counts for some blocks
@@ -1462,16 +1504,99 @@ bool CodeGenFunction::ConstantFoldsToSimpleInteger(const Expr *Cond,
return true;
}
+/// Determine whether the given condition is an instrumentable condition
+/// (i.e. no "&&" or "||").
+bool CodeGenFunction::isInstrumentedCondition(const Expr *C) {
+ // Bypass simplistic logical-NOT operator before determining whether the
+ // condition contains any other logical operator.
+ if (const UnaryOperator *UnOp = dyn_cast<UnaryOperator>(C->IgnoreParens()))
+ if (UnOp->getOpcode() == UO_LNot)
+ C = UnOp->getSubExpr();
+
+ const BinaryOperator *BOp = dyn_cast<BinaryOperator>(C->IgnoreParens());
+ return (!BOp || !BOp->isLogicalOp());
+}
+
+/// EmitBranchToCounterBlock - Emit a conditional branch to a new block that
+/// increments a profile counter based on the semantics of the given logical
+/// operator opcode. This is used to instrument branch condition coverage for
+/// logical operators.
+void CodeGenFunction::EmitBranchToCounterBlock(
+ const Expr *Cond, BinaryOperator::Opcode LOp, llvm::BasicBlock *TrueBlock,
+ llvm::BasicBlock *FalseBlock, uint64_t TrueCount /* = 0 */,
+ Stmt::Likelihood LH /* =None */, const Expr *CntrIdx /* = nullptr */) {
+ // If not instrumenting, just emit a branch.
+ bool InstrumentRegions = CGM.getCodeGenOpts().hasProfileClangInstr();
+ if (!InstrumentRegions || !isInstrumentedCondition(Cond))
+ return EmitBranchOnBoolExpr(Cond, TrueBlock, FalseBlock, TrueCount, LH);
+
+ llvm::BasicBlock *ThenBlock = NULL;
+ llvm::BasicBlock *ElseBlock = NULL;
+ llvm::BasicBlock *NextBlock = NULL;
+
+ // Create the block we'll use to increment the appropriate counter.
+ llvm::BasicBlock *CounterIncrBlock = createBasicBlock("lop.rhscnt");
+
+ // Set block pointers according to Logical-AND (BO_LAnd) semantics. This
+ // means we need to evaluate the condition and increment the counter on TRUE:
+ //
+ // if (Cond)
+ // goto CounterIncrBlock;
+ // else
+ // goto FalseBlock;
+ //
+ // CounterIncrBlock:
+ // Counter++;
+ // goto TrueBlock;
+ if (LOp == BO_LAnd) {
+ ThenBlock = CounterIncrBlock;
+ ElseBlock = FalseBlock;
+ NextBlock = TrueBlock;
+ }
+
+ // Set block pointers according to Logical-OR (BO_LOr) semantics. This means
+ // we need to evaluate the condition and increment the counter on FALSE:
+ //
+ // if (Cond)
+ // goto TrueBlock;
+ // else
+ // goto CounterIncrBlock;
+ //
+ // CounterIncrBlock:
+ // Counter++;
+ // goto FalseBlock;
+
+ else if (LOp == BO_LOr) {
+ ThenBlock = TrueBlock;
+ ElseBlock = CounterIncrBlock;
+ NextBlock = FalseBlock;
+ } else {
+ llvm_unreachable("Expected Opcode must be that of a Logical Operator");
+ }
+
+ // Emit Branch based on condition.
+ EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, TrueCount, LH);
+
+ // Emit the block containing the counter increment(s).
+ EmitBlock(CounterIncrBlock);
+
+ // Increment corresponding counter; if index not provided, use Cond as index.
+ incrementProfileCounter(CntrIdx ? CntrIdx : Cond);
+
+ // Go to the next block.
+ EmitBranch(NextBlock);
+}
/// EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g. for an if
/// statement) to the specified blocks. Based on the condition, this might try
/// to simplify the codegen of the conditional based on the branch.
-///
+/// \param LH The value of the likelihood attribute on the True branch.
void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
llvm::BasicBlock *TrueBlock,
llvm::BasicBlock *FalseBlock,
- uint64_t TrueCount) {
+ uint64_t TrueCount,
+ Stmt::Likelihood LH) {
Cond = Cond->IgnoreParens();
if (const BinaryOperator *CondBOp = dyn_cast<BinaryOperator>(Cond)) {
@@ -1485,8 +1610,8 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
ConstantBool) {
// br(1 && X) -> br(X).
incrementProfileCounter(CondBOp);
- return EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock,
- TrueCount);
+ return EmitBranchToCounterBlock(CondBOp->getRHS(), BO_LAnd, TrueBlock,
+ FalseBlock, TrueCount, LH);
}
// If we have "X && 1", simplify the code to use an uncond branch.
@@ -1494,8 +1619,8 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
if (ConstantFoldsToSimpleInteger(CondBOp->getRHS(), ConstantBool) &&
ConstantBool) {
// br(X && 1) -> br(X).
- return EmitBranchOnBoolExpr(CondBOp->getLHS(), TrueBlock, FalseBlock,
- TrueCount);
+ return EmitBranchToCounterBlock(CondBOp->getLHS(), BO_LAnd, TrueBlock,
+ FalseBlock, TrueCount, LH, CondBOp);
}
// Emit the LHS as a conditional. If the LHS conditional is false, we
@@ -1508,7 +1633,11 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
ConditionalEvaluation eval(*this);
{
ApplyDebugLocation DL(*this, Cond);
- EmitBranchOnBoolExpr(CondBOp->getLHS(), LHSTrue, FalseBlock, RHSCount);
+ // Propagate the likelihood attribute like __builtin_expect
+ // __builtin_expect(X && Y, 1) -> X and Y are likely
+ // __builtin_expect(X && Y, 0) -> only Y is unlikely
+ EmitBranchOnBoolExpr(CondBOp->getLHS(), LHSTrue, FalseBlock, RHSCount,
+ LH == Stmt::LH_Unlikely ? Stmt::LH_None : LH);
EmitBlock(LHSTrue);
}
@@ -1517,7 +1646,8 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
// Any temporaries created here are conditional.
eval.begin(*this);
- EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock, TrueCount);
+ EmitBranchToCounterBlock(CondBOp->getRHS(), BO_LAnd, TrueBlock,
+ FalseBlock, TrueCount, LH);
eval.end(*this);
return;
@@ -1531,8 +1661,8 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
!ConstantBool) {
// br(0 || X) -> br(X).
incrementProfileCounter(CondBOp);
- return EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock,
- TrueCount);
+ return EmitBranchToCounterBlock(CondBOp->getRHS(), BO_LOr, TrueBlock,
+ FalseBlock, TrueCount, LH);
}
// If we have "X || 0", simplify the code to use an uncond branch.
@@ -1540,8 +1670,8 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
if (ConstantFoldsToSimpleInteger(CondBOp->getRHS(), ConstantBool) &&
!ConstantBool) {
// br(X || 0) -> br(X).
- return EmitBranchOnBoolExpr(CondBOp->getLHS(), TrueBlock, FalseBlock,
- TrueCount);
+ return EmitBranchToCounterBlock(CondBOp->getLHS(), BO_LOr, TrueBlock,
+ FalseBlock, TrueCount, LH, CondBOp);
}
// Emit the LHS as a conditional. If the LHS conditional is true, we
@@ -1556,8 +1686,12 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
ConditionalEvaluation eval(*this);
{
+ // Propagate the likelihood attribute like __builtin_expect
+ // __builtin_expect(X || Y, 1) -> only Y is likely
+ // __builtin_expect(X || Y, 0) -> both X and Y are unlikely
ApplyDebugLocation DL(*this, Cond);
- EmitBranchOnBoolExpr(CondBOp->getLHS(), TrueBlock, LHSFalse, LHSCount);
+ EmitBranchOnBoolExpr(CondBOp->getLHS(), TrueBlock, LHSFalse, LHSCount,
+ LH == Stmt::LH_Likely ? Stmt::LH_None : LH);
EmitBlock(LHSFalse);
}
@@ -1566,7 +1700,8 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
// Any temporaries created here are conditional.
eval.begin(*this);
- EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock, RHSCount);
+ EmitBranchToCounterBlock(CondBOp->getRHS(), BO_LOr, TrueBlock, FalseBlock,
+ RHSCount, LH);
eval.end(*this);
@@ -1579,9 +1714,11 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
if (CondUOp->getOpcode() == UO_LNot) {
// Negate the count.
uint64_t FalseCount = getCurrentProfileCount() - TrueCount;
+ // The values of the enum are chosen to make this negation possible.
+ LH = static_cast<Stmt::Likelihood>(-LH);
// Negate the condition and swap the destination blocks.
return EmitBranchOnBoolExpr(CondUOp->getSubExpr(), FalseBlock, TrueBlock,
- FalseCount);
+ FalseCount, LH);
}
}
@@ -1590,9 +1727,11 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
llvm::BasicBlock *LHSBlock = createBasicBlock("cond.true");
llvm::BasicBlock *RHSBlock = createBasicBlock("cond.false");
+ // The ConditionalOperator itself has no likelihood information for its
+ // true and false branches. This matches the behavior of __builtin_expect.
ConditionalEvaluation cond(*this);
EmitBranchOnBoolExpr(CondOp->getCond(), LHSBlock, RHSBlock,
- getProfileCount(CondOp));
+ getProfileCount(CondOp), Stmt::LH_None);
// When computing PGO branch weights, we only know the overall count for
// the true block. This code is essentially doing tail duplication of the
@@ -1612,14 +1751,14 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
{
ApplyDebugLocation DL(*this, Cond);
EmitBranchOnBoolExpr(CondOp->getLHS(), TrueBlock, FalseBlock,
- LHSScaledTrueCount);
+ LHSScaledTrueCount, LH);
}
cond.end(*this);
cond.begin(*this);
EmitBlock(RHSBlock);
EmitBranchOnBoolExpr(CondOp->getRHS(), TrueBlock, FalseBlock,
- TrueCount - LHSScaledTrueCount);
+ TrueCount - LHSScaledTrueCount, LH);
cond.end(*this);
return;
@@ -1648,11 +1787,11 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
}
}
- // Create branch weights based on the number of times we get here and the
- // number of times the condition should be true.
- uint64_t CurrentCount = std::max(getCurrentProfileCount(), TrueCount);
- llvm::MDNode *Weights =
- createProfileWeights(TrueCount, CurrentCount - TrueCount);
+ llvm::MDNode *Weights = createBranchWeights(LH);
+ if (!Weights) {
+ uint64_t CurrentCount = std::max(getCurrentProfileCount(), TrueCount);
+ Weights = createProfileWeights(TrueCount, CurrentCount - TrueCount);
+ }
// Emit the code with the fully general case.
llvm::Value *CondV;
@@ -2075,7 +2214,6 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) {
case Type::UnaryTransform:
case Type::Attributed:
case Type::SubstTemplateTypeParm:
- case Type::PackExpansion:
case Type::MacroQualified:
// Keep walking after single level desugaring.
type = type.getSingleStepDesugaredType(getContext());
@@ -2206,13 +2344,16 @@ void CodeGenFunction::emitAlignmentAssumption(llvm::Value *PtrValue,
llvm::Value *CodeGenFunction::EmitAnnotationCall(llvm::Function *AnnotationFn,
llvm::Value *AnnotatedVal,
StringRef AnnotationStr,
- SourceLocation Location) {
- llvm::Value *Args[4] = {
- AnnotatedVal,
- Builder.CreateBitCast(CGM.EmitAnnotationString(AnnotationStr), Int8PtrTy),
- Builder.CreateBitCast(CGM.EmitAnnotationUnit(Location), Int8PtrTy),
- CGM.EmitAnnotationLineNo(Location)
+ SourceLocation Location,
+ const AnnotateAttr *Attr) {
+ SmallVector<llvm::Value *, 5> Args = {
+ AnnotatedVal,
+ Builder.CreateBitCast(CGM.EmitAnnotationString(AnnotationStr), Int8PtrTy),
+ Builder.CreateBitCast(CGM.EmitAnnotationUnit(Location), Int8PtrTy),
+ CGM.EmitAnnotationLineNo(Location),
};
+ if (Attr)
+ Args.push_back(CGM.EmitAnnotationArgs(Attr));
return Builder.CreateCall(AnnotationFn, Args);
}
@@ -2223,7 +2364,7 @@ void CodeGenFunction::EmitVarAnnotations(const VarDecl *D, llvm::Value *V) {
for (const auto *I : D->specific_attrs<AnnotateAttr>())
EmitAnnotationCall(CGM.getIntrinsic(llvm::Intrinsic::var_annotation),
Builder.CreateBitCast(V, CGM.Int8PtrTy, V->getName()),
- I->getAnnotation(), D->getLocation());
+ I->getAnnotation(), D->getLocation(), I);
}
Address CodeGenFunction::EmitFieldAnnotations(const FieldDecl *D,
@@ -2240,7 +2381,7 @@ Address CodeGenFunction::EmitFieldAnnotations(const FieldDecl *D,
// itself.
if (VTy != CGM.Int8PtrTy)
V = Builder.CreateBitCast(V, CGM.Int8PtrTy);
- V = EmitAnnotationCall(F, V, I->getAnnotation(), D->getLocation());
+ V = EmitAnnotationCall(F, V, I->getAnnotation(), D->getLocation(), I);
V = Builder.CreateBitCast(V, VTy);
}
@@ -2276,34 +2417,6 @@ void CGBuilderInserter::InsertHelper(
CGF->InsertHelper(I, Name, BB, InsertPt);
}
-static bool hasRequiredFeatures(const SmallVectorImpl<StringRef> &ReqFeatures,
- CodeGenModule &CGM, const FunctionDecl *FD,
- std::string &FirstMissing) {
- // If there aren't any required features listed then go ahead and return.
- if (ReqFeatures.empty())
- return false;
-
- // Now build up the set of caller features and verify that all the required
- // features are there.
- llvm::StringMap<bool> CallerFeatureMap;
- CGM.getContext().getFunctionFeatureMap(CallerFeatureMap, FD);
-
- // If we have at least one of the features in the feature list return
- // true, otherwise return false.
- return std::all_of(
- ReqFeatures.begin(), ReqFeatures.end(), [&](StringRef Feature) {
- SmallVector<StringRef, 1> OrFeatures;
- Feature.split(OrFeatures, '|');
- return llvm::any_of(OrFeatures, [&](StringRef Feature) {
- if (!CallerFeatureMap.lookup(Feature)) {
- FirstMissing = Feature.str();
- return false;
- }
- return true;
- });
- });
-}
-
// Emits an error if we don't have a valid set of target features for the
// called function.
void CodeGenFunction::checkTargetFeatures(const CallExpr *E,
@@ -2330,19 +2443,20 @@ void CodeGenFunction::checkTargetFeatures(SourceLocation Loc,
// listed cpu and any listed features.
unsigned BuiltinID = TargetDecl->getBuiltinID();
std::string MissingFeature;
+ llvm::StringMap<bool> CallerFeatureMap;
+ CGM.getContext().getFunctionFeatureMap(CallerFeatureMap, FD);
if (BuiltinID) {
- SmallVector<StringRef, 1> ReqFeatures;
- const char *FeatureList =
- CGM.getContext().BuiltinInfo.getRequiredFeatures(BuiltinID);
+ StringRef FeatureList(
+ CGM.getContext().BuiltinInfo.getRequiredFeatures(BuiltinID));
// Return if the builtin doesn't have any required features.
- if (!FeatureList || StringRef(FeatureList) == "")
+ if (FeatureList.empty())
return;
- StringRef(FeatureList).split(ReqFeatures, ',');
- if (!hasRequiredFeatures(ReqFeatures, CGM, FD, MissingFeature))
+ assert(FeatureList.find(' ') == StringRef::npos &&
+ "Space in feature list");
+ TargetFeatures TF(CallerFeatureMap);
+ if (!TF.hasRequiredFeatures(FeatureList))
CGM.getDiags().Report(Loc, diag::err_builtin_needs_feature)
- << TargetDecl->getDeclName()
- << CGM.getContext().BuiltinInfo.getRequiredFeatures(BuiltinID);
-
+ << TargetDecl->getDeclName() << FeatureList;
} else if (!TargetDecl->isMultiVersion() &&
TargetDecl->hasAttr<TargetAttr>()) {
// Get the required features for the callee.
@@ -2365,7 +2479,13 @@ void CodeGenFunction::checkTargetFeatures(SourceLocation Loc,
if (F.getValue())
ReqFeatures.push_back(F.getKey());
}
- if (!hasRequiredFeatures(ReqFeatures, CGM, FD, MissingFeature))
+ if (!llvm::all_of(ReqFeatures, [&](StringRef Feature) {
+ if (!CallerFeatureMap.lookup(Feature)) {
+ MissingFeature = Feature.str();
+ return false;
+ }
+ return true;
+ }))
CGM.getDiags().Report(Loc, diag::err_function_needs_feature)
<< FD->getDeclName() << TargetDecl->getDeclName() << MissingFeature;
}
@@ -2521,3 +2641,36 @@ llvm::DebugLoc CodeGenFunction::SourceLocToDebugLoc(SourceLocation Location) {
return llvm::DebugLoc();
}
+
+static Optional<std::pair<uint32_t, uint32_t>>
+getLikelihoodWeights(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;
+ case Stmt::LH_Likely:
+ return std::pair<uint32_t, uint32_t>(llvm::LikelyBranchWeight,
+ llvm::UnlikelyBranchWeight);
+ }
+ 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;
+}